ATLAS Offline Software
Loading...
Searching...
No Matches
DataHeaderCnv.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
9
10#include "DataHeaderCnv.h"
11
15
18
19#include "CoralBase/AttributeList.h"
20#include "CoralBase/Attribute.h"
21
22#include "GaudiKernel/IIncidentSvc.h"
23#include "GaudiKernel/FileIncident.h"
25
26#include <stdexcept>
27#include <format>
28
29
30static const pool::Guid DHForm_p6_Guid("7BE56CEF-C866-4BEE-9348-A5F34B5F1DAD");
31
32// cppcheck-suppress uninitMemberVar
33DataHeaderCnv::DataHeaderCnv(ISvcLocator* svcloc) :
34 DataHeaderCnvBase(svcloc, "DataHeaderCnv")
35{
36 m_classDesc = RootType( "DataHeader_p6" );
37}
38
39//______________________________________________________________________________
41{
42 // Remove itself from the IncidentSvc - if it is still around
43 ServiceHandle<IIncidentSvc> incSvc("IncidentSvc", "DataHeaderCnv");
44 if( incSvc.retrieve().isSuccess() ) {
45 try{
46 incSvc->removeListener(this, IncidentType::EndInputFile);
47 } catch ( GaudiException & e){
48 ATH_MSG_FATAL("Gaudi exception caught in DataHeaderCnv::~DataHeaderCnv");
49 }
50 }
51}
52//______________________________________________________________________________
54{
55 // Read properties from the ConversionSvc
56 m_inDHFMapMaxsize = 100; // default DHForm cache size
57 bool doFilterDHAliases = true;
58 const std::string svcName = (serviceLocator()->existsService("AthenaPoolSharedIOCnvSvc") ? "AthenaPoolSharedIOCnvSvc" : "AthenaPoolCnvSvc");
59 SmartIF<IProperty> cnvSvc{service(svcName, false)};
60 if( cnvSvc ) {
61 IntegerProperty sizeProp("maxDHFormCacheSize", m_inDHFMapMaxsize);
62 if( cnvSvc->getProperty(&sizeProp).isSuccess() ) {
63 m_inDHFMapMaxsize = sizeProp.value();
64 }
65 BooleanProperty aliasFilterProp("doFilterDHAliases", doFilterDHAliases);
66 if( cnvSvc->getProperty(&aliasFilterProp).isSuccess() ) {
67 doFilterDHAliases = aliasFilterProp.value();
68 }
69 BooleanProperty oneDHForm("OneDataHeaderForm", m_oneDHForm);
70 if( cnvSvc->getProperty(&oneDHForm).isSuccess() ) {
71 m_oneDHForm = oneDHForm.value();
72 }
73 }
74 ATH_MSG_VERBOSE("Using DHForm cache size: " << m_inDHFMapMaxsize);
75 if( doFilterDHAliases ) {
76 ATH_MSG_VERBOSE("Will filter SG Aux aliases in DataHeader");
77 } else {
78 ATH_MSG_VERBOSE("Will NOT filter SG Aux aliases in DataHeader");
79 }
80 m_tpOutConverter.setSGAliasFiltering( doFilterDHAliases );
81
82 // Get IncidentSvc
83 ServiceHandle<IIncidentSvc> incSvc("IncidentSvc", "DataHeaderCnv");
84 ATH_CHECK( incSvc.retrieve() );
85 // Listen to EndInputFile incidents to clear old DataHeaderForms from the cache
86 incSvc->addListener(this, IncidentType::EndInputFile, 0);
87 incSvc->addListener(this, "PreFork", 0);
88 // Listen to WriteDataHeaderForms incidents to flush DHForms after
89 incSvc->addListener(this, "WriteDataHeaderForms", 0);
91}
92
93
94void DataHeaderCnv::handle(const Incident& incident)
95{
96 if( incident.type() == "PreFork" ) {
97 m_persFormMap.clear();
98 }
99 if( incident.type() == IncidentType::EndInputFile ) {
100 // remove cached DHForms that came from the file that is now being closed
101 const std::string& guid = static_cast<const FileIncident&>(incident).fileGuid();
102 clearInputDHFormCache( guid );
103 }
104 if( incident.type() == "WriteDataHeaderForms" ) {
105 // Issued from OutputStream MetaData write() or directly called from AthenaPoolCnvSvc
106 const std::string& fileName = static_cast<const FileIncident*>(&incident)->fileName();
107 // Write out all the cached DHForms before closing a given output stream
108 std::vector<std::string> toWrite;
109 auto pos = fileName.find("[OutputCollection=MetaDataHdr]");
110 bool metaDataCommit = (pos != std::string::npos);
111 std::string justFileName = fileName.substr(0, pos);
112 ATH_MSG_DEBUG("Handling WriteDataHeaderForms incident for stream: " << fileName);
113 // collect DHForms related to the stream
114 for( const auto& elem : m_persFormMap ) {
115 const std::string& placementStr = elem.first;
116 Placement formPlacement;
117 formPlacement.fromString( placementStr );
118 ATH_MSG_VERBOSE("DatHeaderForm key in map=" << placementStr);
119 if( formPlacement.fileName() == justFileName or fileName == "*" ) {
120 // write only the Forms that correspond to the commit type (MetaData or others)
121 if( (placementStr.find("[CONT=MetaData") != std::string::npos) == metaDataCommit ) {
122 toWrite.push_back( placementStr );
123 }
124 }
125 }
126 // write the DHForms one by one (the only mode supported by RNTuple)
127 for( std::size_t n = 0; const std::string& placementStr : toWrite ) {
128 Placement formPlacement;
129 formPlacement.fromString( placementStr );
130 auto form_ptr = m_persFormMap[placementStr].get();
131 if( form_ptr->isModified() ) {
132 static const RootType dhFormType( typeid( *form_ptr ) );
133 ATH_MSG_DEBUG("Writing DatHeaderForm " << placementStr);
134 Token* form_token = m_athenaPoolCnvSvc->registerForWrite(&formPlacement, form_ptr, dhFormType);
135 if( !form_token ) {
136 std::string errmsg = std::format("Failed to write {} {}", dhFormType.Name(), placementStr);
138 throw GaudiException(std::move(errmsg), "DataHeaderCnv::WriteDataHeaderForms", StatusCode::FAILURE);
139 }
140 ATH_MSG_DEBUG("Wrote DatHeaderForm, placeemnt was " << placementStr << " token=" << form_token->toString());
141 form_token->release(); form_token = nullptr;
142 bool doCommit = (++n == toWrite.size());
143 const std::string connection = ( fileName!="*"? fileName : formPlacement.fileName() );
144 if( !m_athenaPoolCnvSvc->commitOutput(connection, doCommit).isSuccess() ) {
145 throw GaudiException("WriteDataHeaderForms failed", "DataHeaderCnv::WriteDataHeaderForms", StatusCode::FAILURE);
146 }
147 }
148 m_persFormMap.erase( placementStr );
149 }
150 }
151}
152
153
154void DataHeaderCnv::clearInputDHFormCache( const std::string& dbGuid )
155{
156 auto iter = m_inputDHForms.begin();
157 while( iter != m_inputDHForms.end() ) {
158 size_t dbpos = iter->first.find("[DB=");
159 if( dbpos != std::string::npos && iter->first.compare(dbpos+4, dbpos+36, dbGuid) == 0 ) {
160 iter = m_inputDHForms.erase( iter );
161 } else {
162 iter++;
163 }
164 }
165 m_inDHFormCount[ dbGuid ] = 0;
166}
167
168
169std::string getValForKey(const std::string& str, const std::string& key)
170{
171 auto start = str.find(key);
172 if( start == std::string::npos )
173 return "";
174 start += key.size();
175 auto end = str.find("]", start);
176 return str.substr(start, end-start);
177}
178
179inline
180std::string getSWNFromStr(const std::string& str) { return getValForKey(str, "[SWN="); }
181inline
182std::string getFILEFromStr(const std::string& str) { return getValForKey(str, "[FILE="); }
183
184std::string makeKeyValStr(const std::string &key, const std::string & val) {
185 return std::format("[{}={}]", key, val);
186}
187
188
189// Sort DHForms according to the SW client number so they can be written out in the correct order
190inline
191std::string storeSWNInStr(const std::string& str) { return std::format("[SWN={}]", str); }
192
193bool DataHeaderCnv::placementComp::operator() (const std::string& lhs, const std::string& rhs) const
194{
195 std::string lval = getValForKey(lhs,"[FILE=") + getValForKey(lhs,"[CONT=");
196 std::string rval = getValForKey(rhs,"[FILE=") + getValForKey(rhs,"[CONT=");
197 if( lval != rval ) return lval < rval;
198
199 lval = getSWNFromStr(lhs);
200 rval = getSWNFromStr(rhs);
201 if( lval.empty() or rval.empty() ) return false;
202 return std::stoul( lval ) < std::stoul( rval );
203}
204
205//______________________________________________________________________________
206/* For SharedWriter
207 Update the DataHeader reference to the DataHeaderForm with new fileName, DataHeader SG Key
208 and SharedWriter client number. The client number will be used by DH to find the right DHForm.
209 The forms are written out in the order of the client numbers, so the Form object OID
210 corresponds to the client number
211 pObject contains pointer to DataHeader_p6
212 pAddress: par[0] contains DH token, par[1] contains placement + DH processingTag as KEY
213*/
214StatusCode DataHeaderCnv::updateRep(IOpaqueAddress* pAddress, DataObject* pObject)
215{
216 auto dataHeader = reinterpret_cast<DataHeader_p6*>( pObject );
217 const std::string dhRef = pAddress->par()[0];
218 const std::string dhPlacementStr = pAddress->par()[1];
219 const std::string dhFile = getFILEFromStr( dhPlacementStr );
220 Placement dhFormPlacement;
221 dhFormPlacement.fromString( dataHeader->dhFormToken() );
222 dhFormPlacement.setFileName( dhFile );
223 const std::string clientN = getSWNFromStr( dhPlacementStr );
224 if( !clientN.empty() ) {
225 // Client num in the DHForm ref means it's OneDataHeaderForm mode
226 std::string dhFormNewRef = dhFormPlacement.toString() + storeSWNInStr( clientN );
227 ATH_MSG_DEBUG("Setting DH formRef to: " << dhFormNewRef);
228 dataHeader->setDhFormToken( dhFormNewRef );
229 } else {
230 /* DH is received by the SharedWriter first and needs the DHForm object both for
231 reference (Token) and to add DHElem with the ref to itself.
232 These updates will be handled by updateRepRefs() - cache the DH info so it can
233 by used later by updateRepRefs
234 */
236 ATH_MSG_ERROR( "updateRep called but the previous DataHeader was not yet processed."
237 << " cached DH Key=" << m_sharedWriterCachedDHKey
238 << " cached DH Ref=" << m_sharedWriterCachedDHToken );
239 return StatusCode::FAILURE;
240 }
241 // remember this DH and finish processing in updateRepRefs()
242 m_sharedWriterCachedDH = dataHeader;
243 m_sharedWriterCachedDHToken = std::move(dhRef);
244 std::size_t tagBeg = dhPlacementStr.find("[KEY=") + 5;
245 std::size_t tagSize = dhPlacementStr.find(']', tagBeg) - tagBeg;
246 m_sharedWriterCachedDHKey = dhPlacementStr.substr( tagBeg, tagSize );
247 }
248 return StatusCode::SUCCESS;
249}
250
251//______________________________________________________________________________
252StatusCode DataHeaderCnv::updateRepRefs(IOpaqueAddress* pAddress, DataObject* pObject)
253{
255 /* Attach a DHForm to the previous DataHeader (in SharedWriter server mode)
256 Finish writing of the DataHeader by attaching the DHForm to it and by adding
257 the self reference. DHForm is passed as pObject and is cached until a new one
258 arrives. This method is called for each event after the DH is received.
259 pObject is null if there is no new DHForm for this event - in this case the old
260 one is used
261 */
262 std::string dhid = pAddress->par()[1];
263 if( pObject ) {
264 this->setToken( pAddress->par()[0] );
266 ATH_MSG_ERROR( "updateRepRefs called without DataHeaderForm" );
267 return StatusCode::FAILURE;
268 }
269 // replace the old DHForm
270 // will keep this DHForm until a new one arrives
271 m_sharedWriterCachedDHForm[dhid].reset( reinterpret_cast<DataHeaderForm_p6*>( pObject ) );
272 m_sharedWriterCachedDHForm[dhid]->setToken( pAddress->par()[0] );
273 }
275 ATH_MSG_ERROR( "updateRepRefs: missing DataHeaderForm for DH ID=" << dhid );
276 return StatusCode::FAILURE;
277 }
278 // update the cached DataHeader (can be done until a commit is called)
279 m_sharedWriterCachedDH->setDhFormToken( m_sharedWriterCachedDHForm[dhid]->getToken() );
282 // this DataHeader object is now fully processed, so forget it
283 m_sharedWriterCachedDH = nullptr;
284 }
285 else {
286 // In OneDataHeaderForm mode - keep the DHForms from all clients and write them out at the end
287 m_persFormMap[ pAddress->par()[1] ].reset( reinterpret_cast<DataHeaderForm_p6*>( pObject ) );
288 }
289 return(StatusCode::SUCCESS);
290}
291
292//______________________________________________________________________________
293StatusCode DataHeaderCnv::DataObjectToPool(IOpaqueAddress* pAddr, DataObject* pObj)
294{
295 DataHeader* obj = nullptr;
296 if (!SG::fromStorable(pObj, obj) || obj == nullptr) {
297 ATH_MSG_ERROR( "Failed to cast DataHeader to transient type" );
298 return(StatusCode::FAILURE);
299 }
300 // DHForm placement:
301 Placement dhf_placement = setPlacementWithType("DataHeaderForm", pObj->name(), *pAddr->par());
302 std::string form_placement_str = dhf_placement.toString();
303 // Find or create Form
304 std::unique_ptr<DataHeaderForm_p6>& dhForm = m_persFormMap[form_placement_str];
305 if (dhForm == nullptr) {
306 // create new DHF for this file. Every new file/container should get its own DHForm
307 dhForm = std::make_unique<DataHeaderForm_p6>();
308 dhForm->setProcessTag( obj->getProcessTag() );
309 }
310
311 // DH placement first:
312 Placement dh_placement = setPlacementWithType("DataHeader", pObj->name(), *pAddr->par());
313 // remember the connection string, it may get changed in registerForWrite by SharedWriter
314 const std::string connection = dh_placement.fileName();
315 // Create persistent DH and update Form
316 DataHeader_p6* persObj = nullptr;
317 try {
318 persObj = createPersistent(obj, dhForm.get());
319 } catch (std::exception &e) {
320 ATH_MSG_FATAL("Failed to convert DataHeader to persistent type: " << e.what());
321 return(StatusCode::FAILURE);
322 }
323 // Queue the DH for write
324 std::unique_ptr<Token> dh_token (m_athenaPoolCnvSvc->registerForWrite(&dh_placement, persObj, m_classDesc));
325 if (dh_token == nullptr) {
326 ATH_MSG_FATAL("Failed to write DataHeader");
327 return(StatusCode::FAILURE);
328 }
329 keepPoolObj(persObj, connection);
330 // insert self reference - this updates DH and can modify the Form
331 m_tpOutConverter.insertDHRef(persObj, obj->getProcessTag(), dh_token->toString(), *dhForm);
332
333 if( !m_oneDHForm ) {
334 if( dhForm->isModified() ) {
335 // Write DHForm if in legacy mode in case it was modified (or new)
336 dhForm->setVersion( DataHeaderForm_p6::DHverFormRef );
337 static const RootType dhFormType(typeid(*dhForm));
338 Token* dhf_token = m_athenaPoolCnvSvc->registerForWrite(&dhf_placement, dhForm.get(), dhFormType);
339 if (dhf_token == nullptr) {
340 ATH_MSG_FATAL("Failed to write " << dhFormType.Name());
341 return(StatusCode::FAILURE);
342 }
343 if (dhf_token->technology() != 0) { // Only store DHF token if technology allows it to be appended to DH
344 dhForm->setToken(dhf_token->toString());
345 } else { // Otherwise keep string empty to cause DHF reading via DH token
346 ATH_MSG_DEBUG("Technology does not support setting DHF token for: " << dh_token->toString());
347 dhForm->setToken("");
348 }
349 ATH_MSG_DEBUG("wrote new DHForm with " << dhForm->sizeObj() << " SG object data");
350 dhf_token->release(); dhf_token = nullptr;
351 dhForm->clearModified();
352 }
353 // update the Ref to the DHForm
354 persObj->setDhFormToken( dhForm->getToken() );
355 }
356 else {
357 // use the DHForm placement as a Ref, as the DHForm will be written out at the end only
358 // but add DB ID to the placement str in case the filename is not unique between jobs
359 if( dhForm->getToken().empty() ) {
360 form_placement_str += std::format("[DB={}]", dh_token->dbID().toString());
361 dhForm->setToken( form_placement_str );
362 } else {
363 form_placement_str = dhForm->getToken();
364 }
365 // remove the [FILE= part as the DBID will be enough for reading back
366 auto b = form_placement_str.find("[FILE=");
367 auto e = form_placement_str.find("]", b);
368 form_placement_str.erase(b, e-b+1);
369 // store the modified DHForm placement in place of the Ref in the DH
370 persObj->setDhFormToken( form_placement_str );
371 }
372
373 const coral::AttributeList* list = obj->getAttributeList();
374 if (list != nullptr) {
375 obj->setEvtRefTokenStr(dh_token->toString());
376 Placement attr_placement = this->setPlacementWithType("AttributeList", "Token", *pAddr->par());
377 const Token* ref_token = m_athenaPoolCnvSvc->registerForWrite(&attr_placement,
378 obj->getEvtRefTokenStr().c_str(),
379 RootType("Token"));
380 delete ref_token; ref_token = nullptr;
381 for (coral::AttributeList::const_iterator iter = list->begin(), last = list->end(); iter != last; ++iter) {
382 attr_placement = this->setPlacementWithType("AttributeList", (*iter).specification().name(), *pAddr->par());
383 const Token* attr_token = m_athenaPoolCnvSvc->registerForWrite(&attr_placement,
384 (*iter).addressOfData(),
385 RootType((*iter).specification().type()) );
386 delete attr_token; attr_token = nullptr;
387 }
388 }
389 TokenAddress* tokAddr = dynamic_cast<TokenAddress*>(pAddr);
390 if (tokAddr != nullptr) {
391 tokAddr->setToken(std::move(dh_token));
392 } else {
393 return(StatusCode::FAILURE);
394 }
395 return(StatusCode::SUCCESS);
396}
397
398//______________________________________________________________________________
399std::unique_ptr<DataHeader_p5> DataHeaderCnv::poolReadObject_p5()
400{
401 void* voidPtr1 = nullptr;
402 m_athenaPoolCnvSvc->setObjPtr(voidPtr1, m_i_poolToken);
403 if (voidPtr1 == nullptr) {
404 throw std::runtime_error("Could not get object for token = " + m_i_poolToken->toString());
405 }
406 std::unique_ptr<DataHeader_p5> header( reinterpret_cast<DataHeader_p5*>(voidPtr1) );
407
408 void* voidPtr2 = nullptr;
409 Token mapToken;
410 mapToken.fromString( header->dhFormToken() );
411 mapToken.setAuxString( m_i_poolToken->auxString() ); // set PersSvc context
412 if (mapToken.classID() != Guid::null()) {
413 if( header->dhFormMdx() != m_dhFormMdx ) {
414 m_athenaPoolCnvSvc->setObjPtr(voidPtr2, &mapToken);
415 if (voidPtr2 == nullptr) {
416 throw std::runtime_error("Could not get object for token = " + mapToken.toString());
417 }
418 m_dhInForm5.reset( reinterpret_cast<DataHeaderForm_p5*>(voidPtr2) );
419 m_dhFormMdx = header->dhFormMdx();
420 }
421 }
422 return header;
423}
424
425//______________________________________________________________________________
426// Read the persistent rep of DataHeader
427// Also read DataHeaderForm if not yet cached
428std::unique_ptr<DataHeader_p6> DataHeaderCnv::poolReadObject_p6()
429{
430 void* voidPtr1 = nullptr;
431 std::string error_message;
432 try {
433 m_athenaPoolCnvSvc->setObjPtr(voidPtr1, m_i_poolToken);
434 } catch(const std::exception& err) {
435 voidPtr1 = nullptr;
436 error_message = err.what();
437 }
438 if (voidPtr1 == nullptr) {
439 throw std::runtime_error("Could not get object for token = " + m_i_poolToken->toString() + ", " + error_message);
440 }
441 std::unique_ptr<DataHeader_p6> header( reinterpret_cast<DataHeader_p6*>(voidPtr1) );
442
443 std::string dhFormToken = header->dhFormToken();
444 Token formToken;
445 if( !dhFormToken.empty() and dhFormToken.find("[OID=") == std::string::npos) {
446 // OneForm format of Form Ref (without OID)
447 // we need to reconstruct the real Ref before checking in the Ref cache
448 Placement dhf_placement;
449 dhf_placement.fromString( dhFormToken );
450 formToken.setDb( m_i_poolToken->dbID() );
451 formToken.setCont( dhf_placement.containerName() );
452 formToken.setTechnology( dhf_placement.technology() );
453 formToken.setAuxString( dhf_placement.auxString() );
454 formToken.setClassID( DHForm_p6_Guid );
455 std::int64_t oid2 = m_i_poolToken->oid().second;
456 oid2 >>= 32; oid2 <<= 32;
457 std::string swn = getSWNFromStr( dhFormToken );
458 // add the row number from the SHForm Ref
459 if( !swn.empty() ) oid2 += std::stoul( swn ) - 1;
460 formToken.setOid( {0,oid2} );
461 ATH_MSG_DEBUG("Constructed DHForm Ref=" << formToken.toString() << " from " << dhFormToken );
462 dhFormToken = formToken.toString();
463 header->setDhFormToken( dhFormToken );
464 }
465 // see if the DataHeaderForm is already cached
466 if( dhFormToken.empty() || m_inputDHForms.find(dhFormToken) == m_inputDHForms.end() ) {
467 // no cached DHForm
468 size_t dbpos = dhFormToken.find("[DB=");
469 if( dbpos != std::string::npos ) {
470 const std::string dbGuid = dhFormToken.substr(dbpos+4, dbpos+36);
471 if( ++m_inDHFormCount[dbGuid] > m_inDHFMapMaxsize ) {
472 // prevent the input DHFMap from growing too large
473 clearInputDHFormCache( dbGuid );
474 m_inDHFormCount[dbGuid] = 1;
475 }
476 }
477 // we need to read a new DHF
478 void* voidPtr2 = nullptr;
479 if( dhFormToken.empty() ) {
480 // Some technologies can't set DHF token, use DH token with new CLID.
481 m_i_poolToken->setData(&formToken);
482 formToken.setClassID( DHForm_p6_Guid );
483 } else {
484 formToken.fromString( dhFormToken );
485 formToken.setAuxString( m_i_poolToken->auxString() ); // set PersSvc context
486 }
487 if (formToken.classID() != Guid::null()) {
488 try {
489 m_athenaPoolCnvSvc->setObjPtr(voidPtr2, &formToken);
490 } catch(const std::exception& err) {
491 voidPtr2 = nullptr;
492 error_message = err.what();
493 }
494 if (voidPtr2 == nullptr) {
495 // if there is no good lastGoodDHFRef then try reading DataHeaderForm Token from the first DataHeader
496 if( m_lastGoodDHFRef.find(m_i_poolToken->contID()) == m_lastGoodDHFRef.end() ) {
497 Token firstToken;
498 m_i_poolToken->setData(&firstToken);
499 firstToken.setOid(Token::OID_t(firstToken.oid().first, 0));
500 void* firstPtr1 = nullptr;
501 try {
502 m_athenaPoolCnvSvc->setObjPtr(firstPtr1, &firstToken);
503 } catch(const std::exception& err) {
504 firstPtr1 = nullptr;
505 error_message = err.what();
506 }
507 if (firstPtr1 == nullptr) throw std::runtime_error("Could not get first DataHeader for token = " + firstToken.toString() + ", " + error_message);
508
509 // Get DataHeaderForm Token from the first DataHeader
510 std::unique_ptr<DataHeader_p6> firstHeader( reinterpret_cast<DataHeader_p6*>(firstPtr1) );
511 dhFormToken = firstHeader->dhFormToken();
512
513 // Read DataHeaderForm and insert it to the cache
514 formToken.fromString( dhFormToken );
515 formToken.setAuxString( m_i_poolToken->auxString() ); // set PersSvc context
516 try {
517 m_athenaPoolCnvSvc->setObjPtr(voidPtr2, &formToken);
518 } catch(const std::exception& err) {
519 voidPtr2 = nullptr;
520 error_message = err.what();
521 }
522 if (voidPtr2 == nullptr) throw std::runtime_error("Could not get DataHeaderForm for token = " + formToken.toString() + ", " + error_message);
523 m_lastGoodDHFRef[m_i_poolToken->contID()] = dhFormToken;
524 m_inputDHForms[dhFormToken].reset( reinterpret_cast<DataHeaderForm_p6*>(voidPtr2) );
525 ATH_MSG_WARNING("DataHeaderForm read exception: " << error_message << " - reusing the last good DHForm");
526 } else {
527 // try to reuse the last good DHForm Ref (object is already cached)
528 ATH_MSG_WARNING("DataHeaderForm read exception: " << error_message << " - reusing the last good DHForm");
529 }
530 header->setDhFormToken(m_lastGoodDHFRef[m_i_poolToken->contID()]);
531 return header;
532 }
533 if (voidPtr2 == nullptr) {
534 throw std::runtime_error("Could not get object for token = " + formToken.toString());
535 }
536 m_lastGoodDHFRef[m_i_poolToken->contID()] = dhFormToken;
537 }
538 m_inputDHForms[dhFormToken].reset( reinterpret_cast<DataHeaderForm_p6*>(voidPtr2) );
539 }
540 return header;
541}
542
543//______________________________________________________________________________
545{
546 return m_tpOutConverter.createPersistent( transObj, *dh_form );
547}
548
549//______________________________________________________________________________
551{
552 auto iter = dh->m_inputDataHeader.begin();
553 while( iter != dh->m_inputDataHeader.end() ) {
554 if( iter->getToken()->dbID() == Guid::null() ) {
555 ATH_MSG_WARNING("Removed incomplete Input Element");
556 iter = dh->m_inputDataHeader.erase(iter);
557 } else {
558 ++iter;
559 }
560 }
561}
562
563//______________________________________________________________________________
565 if (this->m_i_poolToken == nullptr) {
566 return(nullptr);
567 }
568 if (this->m_i_poolToken->technology() == 0x00001000) { // Artificial ByteStream DataHeader Token
569 DataHeader* dh = new DataHeader();
570 std::string bestPfn, fileType;
571 m_athenaPoolCnvSvc->getPoolSvc()->lookupBestPfn(this->m_i_poolToken->dbID().toString(), bestPfn, fileType);
573 dh->insert(dhe);
574 return(dh);
575 }
576 static const pool::Guid p6_guid("4DDBD295-EFCE-472A-9EC8-15CD35A9EB8D");
577 static const pool::Guid p5_guid("D82968A1-CF91-4320-B2DD-E0F739CBC7E6");
578 static const pool::Guid p4_guid("9630EB7B-CCD7-47D9-A39B-CBBF4133CDF2");
579 static const pool::Guid p3_guid("EC1318F0-8E28-45F8-9A2D-2597C1CC87A6");
580 try {
581 if( compareClassGuid( p6_guid ) ) {
582 std::unique_ptr<DataHeader_p6> header( poolReadObject_p6() );
583 auto dhForm = m_inputDHForms[ header->dhFormToken() ].get();
584 auto dh = m_tpInConverter.createTransient( header.get(), *dhForm, m_i_poolToken );
586 // To dump the DataHeader uncomment below
587 // std::ostringstream ss; dh->dump(ss); std::cout << ss.str() << std::endl;
588 return dh;
589 } else if (this->compareClassGuid( p5_guid )) {
590 std::unique_ptr<DataHeader_p5> obj_p5( poolReadObject_p5() );
591 return m_tpInConverter_p5.createTransient( *obj_p5, *m_dhInForm5 ).release();
592 } else if (this->compareClassGuid( p4_guid )) {
593 std::unique_ptr<DataHeader_p4> obj_p4(this->poolReadObject<DataHeader_p4>());
594 DataHeaderCnv_p4 tPconverter_p4;
595 return(tPconverter_p4.createTransient(obj_p4.get()));
596 } else if (this->compareClassGuid( p3_guid )) {
597 std::unique_ptr<DataHeader_p3> obj_p3(this->poolReadObject<DataHeader_p3>());
598 DataHeaderCnv_p3 tPconverter_p3;
599 return(tPconverter_p3.createTransient(obj_p3.get()));
600 }
601 } catch (std::exception &e) {
602 // upgrade all exceptions to runtime_error (who needs that? MN)
603 std::string error = e.what();
604 throw std::runtime_error(error);
605 }
606 return(nullptr);
607}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
static const pool::Guid DHForm_p6_Guid("7BE56CEF-C866-4BEE-9348-A5F34B5F1DAD")
std::string getValForKey(const std::string &str, const std::string &key)
std::string getSWNFromStr(const std::string &str)
std::string getFILEFromStr(const std::string &str)
std::string storeSWNInStr(const std::string &str)
std::string makeKeyValStr(const std::string &key, const std::string &val)
This file contains the class definition for the DataHeaderCnv class.
T_AthenaPoolCustomCnv< DataHeader, DataHeader_p6 > DataHeaderCnvBase
This file contains the class definition for the DataHeaderCnv_p3 and DataHeaderElementCnv_p3 classes.
This file contains the class definition for the DataHeaderCnv_p4 and DataHeaderElementCnv_p4 classes.
This file contains the class definition for the Placement class (migrated from POOL).
TTypeAdapter RootType
Definition RootType.h:211
This file contains the class definition for the TokenAddress class.
This file contains the class definition for the Token class (migrated from POOL).
static thread_local std::ostringstream errmsg
Definition WaferTree.h:25
ServiceHandle< IAthenaPoolCnvSvc > m_athenaPoolCnvSvc
virtual Placement setPlacementWithType(const std::string &tname, const std::string &key, const std::string &output)
This class provides the converter to customize the saving of DataHeader_p3.
DataHeader * createTransient(const DataHeader_p3 *persObj)
This class provides the converter to customize the saving of DataHeader_p4.
DataHeader * createTransient(const DataHeader_p4 *persObj)
unsigned m_inDHFMapMaxsize
Max DHForms to cache per input file.
virtual StatusCode initialize() override
Gaudi Service Interface method implementations:
DataHeaderCnv_p6 m_tpInConverter
virtual StatusCode updateRep(IOpaqueAddress *pAddress, DataObject *pObject) override
Extend base-class conversion methods.
std::map< std::string, unsigned > m_inDHFormCount
How many DHForms for an input file are in the cache.
void clearInputDHFormCache(const std::string &dbGuid)
Delete cached DHForms for a given input file GUID.
virtual StatusCode DataObjectToPool(IOpaqueAddress *pAddr, DataObject *pObj) override
Write an object into POOL.
DataHeaderCnv_p5 m_tpInConverter_p5
for use when reading DataHeader_p5
std::unique_ptr< DataHeaderForm_p5 > m_dhInForm5
std::string m_sharedWriterCachedDHKey
virtual StatusCode updateRepRefs(IOpaqueAddress *pAddress, DataObject *pObject) override
DataHeaderCnv(ISvcLocator *svcloc)
std::map< std::string, std::unique_ptr< DataHeaderForm_p6 > > m_sharedWriterCachedDHForm
map of cached DHForms for DataHeader ID
virtual DataHeader * createTransient() override
std::map< std::string, std::unique_ptr< DataHeaderForm_p6 > > m_inputDHForms
DHForm cache indexed by the DHForm reference (from DataHeader) that was used to read it.
DataHeader_p6 * m_sharedWriterCachedDH
cached values for use with SharedWriter server
std::string m_sharedWriterCachedDHToken
std::map< std::string, std::unique_ptr< DataHeaderForm_p6 >, placementComp > m_persFormMap
bool m_oneDHForm
if true write only one DataHeaderForm at the end (stop, finalize, or WriteDataHeaderForms incident) t...
std::unique_ptr< DataHeader_p6 > poolReadObject_p6()
virtual void handle(const Incident &incident) override
Incident service handle listening for EndInputFile.
std::unique_ptr< DataHeader_p5 > poolReadObject_p5()
DataHeaderCnv_p6 m_tpOutConverter
DataHeader_p6 * createPersistent(DataHeader *transObj, DataHeaderForm_p6 *)
std::map< std::string, std::string > m_lastGoodDHFRef
std::string m_dhFormMdx
void removeBadElements(DataHeader *dh)
Remove DataHeaderElements with incomplete (dbID="") refs.
This class provides a persistent form for the TransientAddress.
Definition DataHeader.h:37
This class provides storage for the constant fields of the persistent DataHeader class.
This class provides storage for the constant fields of the persistent DataHeader class.
This class provides a persistent representation for the DataHeader class.
This class provides a persistent representation for the DataHeader class.
void setDhFormToken(const std::string &formToken)
This class provides the layout for summary information stored for data written to POOL.
Definition DataHeader.h:123
static const Guid & null() noexcept
NULL-Guid: static class method.
Definition Guid.cxx:14
This class holds all the necessary information to guide the writing of an object in a physical place.
Definition Placement.h:19
const std::string & auxString() const
Access auxiliary string.
Definition Placement.h:40
const std::string & containerName() const
Access container name.
Definition Placement.h:32
Placement & setFileName(const std::string &fileName)
Set file name.
Definition Placement.h:30
const std::string toString() const
Retrieve the string representation of the placement.
Definition Placement.cxx:15
const std::string & fileName() const
Access file name.
Definition Placement.h:28
Placement & fromString(const std::string &from)
Build from the string representation of a placement.
Definition Placement.cxx:28
int technology() const
Access technology type.
Definition Placement.h:36
std::string Name(unsigned int mod=Reflex::SCOPED) const
Definition RootType.cxx:612
virtual bool compareClassGuid(const Guid &clid) const
virtual void setToken(const std::string &token)
void keepPoolObj(DataHeader_p6 *obj, const std::string &output)
This class provides a Generic Transient Address for POOL tokens.
void setToken(std::unique_ptr< Token > token)
This class provides a token that identifies in a unique way objects on the persistent storage.
Definition Token.h:21
Token & setCont(const std::string &cnt)
Set container name.
Definition Token.h:71
Token & setAuxString(const std::string &auxString)
Set auxiliary string.
Definition Token.h:93
Token & setDb(const Guid &db)
Set database name.
Definition Token.h:66
const Guid & classID() const
Access database identifier.
Definition Token.h:73
Token & setClassID(const Guid &cl_id)
Access database identifier.
Definition Token.h:75
virtual const std::string toString() const
Retrieve the string representation of the token.
Definition Token.cxx:134
int technology() const
Access technology type.
Definition Token.h:77
int release()
Release token: Decrease reference count and eventually delete.
Definition Token.cxx:80
Token & setOid(const OID_t &oid)
Set object identifier.
Definition Token.h:85
Token & setTechnology(int t)
Set technology type.
Definition Token.h:79
const OID_t & oid() const
Access object identifier.
Definition Token.h:81
Token & fromString(const std::string_view from)
Build from the string representation of a token.
Definition Token.cxx:147
bool fromStorable(DataObject *pDObj, T *&pTrans, bool quiet=false, IRegisterTransient *irt=0, bool isConst=true)
bool operator()(const std::string &lhs, const std::string &rhs) const