ATLAS Offline Software
Loading...
Searching...
No Matches
DataHeaderCnv.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 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 Token poolToken;
265 poolToken.fromString( pAddress->par()[0] );
266 if( !compareClassGuid(&poolToken, DHForm_p6_Guid ) ) {
267 ATH_MSG_ERROR( "updateRepRefs called without DataHeaderForm" );
268 return StatusCode::FAILURE;
269 }
270 // replace the old DHForm
271 // will keep this DHForm until a new one arrives
272 m_sharedWriterCachedDHForm[dhid].reset( reinterpret_cast<DataHeaderForm_p6*>( pObject ) );
273 m_sharedWriterCachedDHForm[dhid]->setToken( pAddress->par()[0] );
274 }
276 ATH_MSG_ERROR( "updateRepRefs: missing DataHeaderForm for DH ID=" << dhid );
277 return StatusCode::FAILURE;
278 }
279 // update the cached DataHeader (can be done until a commit is called)
280 m_sharedWriterCachedDH->setDhFormToken( m_sharedWriterCachedDHForm[dhid]->getToken() );
283 // this DataHeader object is now fully processed, so forget it
284 m_sharedWriterCachedDH = nullptr;
285 }
286 else {
287 // In OneDataHeaderForm mode - keep the DHForms from all clients and write them out at the end
288 m_persFormMap[ pAddress->par()[1] ].reset( reinterpret_cast<DataHeaderForm_p6*>( pObject ) );
289 }
290 return(StatusCode::SUCCESS);
291}
292
293//______________________________________________________________________________
294StatusCode DataHeaderCnv::DataObjectToPool(IOpaqueAddress* pAddr, DataObject* pObj)
295{
296 std::lock_guard<AthenaPoolConverter::CallMutex> lock(this->m_conv_mut);
297 DataHeader* obj = nullptr;
298 if (!SG::fromStorable(pObj, obj) || obj == nullptr) {
299 ATH_MSG_ERROR( "Failed to cast DataHeader to transient type" );
300 return(StatusCode::FAILURE);
301 }
302 // DHForm placement:
303 Placement dhf_placement = setPlacementWithType("DataHeaderForm", pObj->name(), *pAddr->par());
304 std::string form_placement_str = dhf_placement.toString();
305 // Find or create Form
306 std::unique_ptr<DataHeaderForm_p6>& dhForm = m_persFormMap[form_placement_str];
307 if (dhForm == nullptr) {
308 // create new DHF for this file. Every new file/container should get its own DHForm
309 dhForm = std::make_unique<DataHeaderForm_p6>();
310 dhForm->setProcessTag( obj->getProcessTag() );
311 }
312
313 // DH placement first:
314 Placement dh_placement = setPlacementWithType("DataHeader", pObj->name(), *pAddr->par());
315 // remember the connection string, it may get changed in registerForWrite by SharedWriter
316 const std::string connection = dh_placement.fileName();
317 // Create persistent DH and update Form
318 DataHeader_p6* persObj = nullptr;
319 try {
320 persObj = createPersistent(obj, dhForm.get());
321 } catch (std::exception &e) {
322 ATH_MSG_FATAL("Failed to convert DataHeader to persistent type: " << e.what());
323 return(StatusCode::FAILURE);
324 }
325 // Queue the DH for write
326 std::unique_ptr<Token> dh_token(m_athenaPoolCnvSvc->registerForWrite(&dh_placement, persObj, m_classDesc));
327 if (dh_token == nullptr) {
328 ATH_MSG_FATAL("Failed to write DataHeader");
329 return(StatusCode::FAILURE);
330 }
331 keepPoolObj(persObj, connection);
332 // insert self reference - this updates DH and can modify the Form
333 m_tpOutConverter.insertDHRef(persObj, obj->getProcessTag(), dh_token->toString(), *dhForm);
334
335 if( !m_oneDHForm ) {
336 if( dhForm->isModified() ) {
337 // Write DHForm if in legacy mode in case it was modified (or new)
338 dhForm->setVersion( DataHeaderForm_p6::DHverFormRef );
339 static const RootType dhFormType(typeid(*dhForm));
340 Token* dhf_token = m_athenaPoolCnvSvc->registerForWrite(&dhf_placement, dhForm.get(), dhFormType);
341 if (dhf_token == nullptr) {
342 ATH_MSG_FATAL("Failed to write " << dhFormType.Name());
343 return(StatusCode::FAILURE);
344 }
345 if (dhf_token->technology() != 0) { // Only store DHF token if technology allows it to be appended to DH
346 dhForm->setToken(dhf_token->toString());
347 } else { // Otherwise keep string empty to cause DHF reading via DH token
348 ATH_MSG_DEBUG("Technology does not support setting DHF token for: " << dh_token->toString());
349 dhForm->setToken("");
350 }
351 ATH_MSG_DEBUG("wrote new DHForm with " << dhForm->sizeObj() << " SG object data");
352 dhf_token->release(); dhf_token = nullptr;
353 dhForm->clearModified();
354 }
355 // update the Ref to the DHForm
356 persObj->setDhFormToken( dhForm->getToken() );
357 }
358 else {
359 // use the DHForm placement as a Ref, as the DHForm will be written out at the end only
360 // but add DB ID to the placement str in case the filename is not unique between jobs
361 if( dhForm->getToken().empty() ) {
362 form_placement_str += std::format("[DB={}]", dh_token->dbID().toString());
363 dhForm->setToken( form_placement_str );
364 } else {
365 form_placement_str = dhForm->getToken();
366 }
367 // remove the [FILE= part as the DBID will be enough for reading back
368 auto b = form_placement_str.find("[FILE=");
369 auto e = form_placement_str.find("]", b);
370 form_placement_str.erase(b, e-b+1);
371 // store the modified DHForm placement in place of the Ref in the DH
372 persObj->setDhFormToken( form_placement_str );
373 }
374
375 const coral::AttributeList* list = obj->getAttributeList();
376 if (list != nullptr) {
377 static const std::string attributeListStr{"AttributeList"};
378 obj->setEvtRefTokenStr(dh_token->toString());
379 Placement attr_placement = this->setPlacementWithType(attributeListStr, "Token", *pAddr->par());
380 const Token* ref_token = m_athenaPoolCnvSvc->registerForWrite(&attr_placement,
381 obj->getEvtRefTokenStr().c_str(),
382 RootType("Token"));
383 delete ref_token; ref_token = nullptr;
384 for (coral::AttributeList::const_iterator iter = list->begin(), last = list->end(); iter != last; ++iter) {
385 attr_placement = this->setPlacementWithType(attributeListStr, (*iter).specification().name(), *pAddr->par());
386 const Token* attr_token = m_athenaPoolCnvSvc->registerForWrite(&attr_placement,
387 (*iter).addressOfData(),
388 RootType((*iter).specification().type()) );
389 delete attr_token; attr_token = nullptr;
390 }
391 }
392 TokenAddress* tokAddr = dynamic_cast<TokenAddress*>(pAddr);
393 if (tokAddr != nullptr) {
394 tokAddr->setToken(std::move(dh_token));
395 } else {
396 return(StatusCode::FAILURE);
397 }
398 return(StatusCode::SUCCESS);
399}
400
401//______________________________________________________________________________
402std::unique_ptr<DataHeader_p5> DataHeaderCnv::poolReadObject_p5(const Token* token)
403{
404 void* voidPtr1 = nullptr;
405 m_athenaPoolCnvSvc->setObjPtr(voidPtr1, token);
406 if (voidPtr1 == nullptr) {
407 throw std::runtime_error("Could not get object for token = " + token->toString());
408 }
409 std::unique_ptr<DataHeader_p5> header( reinterpret_cast<DataHeader_p5*>(voidPtr1) );
410
411 void* voidPtr2 = nullptr;
412 Token mapToken;
413 mapToken.fromString( header->dhFormToken() );
414 mapToken.setAuxString( token->auxString() ); // set PersSvc context
415 if (mapToken.classID() != Guid::null()) {
416 if( header->dhFormMdx() != m_dhFormMdx ) {
417 m_athenaPoolCnvSvc->setObjPtr(voidPtr2, &mapToken);
418 if (voidPtr2 == nullptr) {
419 throw std::runtime_error("Could not get object for token = " + mapToken.toString());
420 }
421 m_dhInForm5.reset( reinterpret_cast<DataHeaderForm_p5*>(voidPtr2) );
422 m_dhFormMdx = header->dhFormMdx();
423 }
424 }
425 return header;
426}
427
428//______________________________________________________________________________
429// Read the persistent rep of DataHeader
430// Also read DataHeaderForm if not yet cached
431std::unique_ptr<DataHeader_p6> DataHeaderCnv::poolReadObject_p6(const Token* token)
432{
433 void* voidPtr1 = nullptr;
434 std::string error_message;
435 try {
436 m_athenaPoolCnvSvc->setObjPtr(voidPtr1, token);
437 } catch(const std::exception& err) {
438 voidPtr1 = nullptr;
439 error_message = err.what();
440 }
441 if (voidPtr1 == nullptr) {
442 throw std::runtime_error("Could not get object for token = " + token->toString() + ", " + error_message);
443 }
444 std::unique_ptr<DataHeader_p6> header( reinterpret_cast<DataHeader_p6*>(voidPtr1) );
445
446 std::string dhFormToken = header->dhFormToken();
447 Token formToken;
448 if( !dhFormToken.empty() and dhFormToken.find("[OID=") == std::string::npos) {
449 // OneForm format of Form Ref (without OID)
450 // we need to reconstruct the real Ref before checking in the Ref cache
451 Placement dhf_placement;
452 dhf_placement.fromString( dhFormToken );
453 formToken.setDb( token->dbID() );
454 formToken.setCont( dhf_placement.containerName() );
455 formToken.setTechnology( dhf_placement.technology() );
456 formToken.setAuxString( dhf_placement.auxString() );
457 formToken.setClassID( DHForm_p6_Guid );
458 std::int64_t oid2 = token->oid().second;
459 oid2 >>= 32; oid2 <<= 32;
460 std::string swn = getSWNFromStr( dhFormToken );
461 // add the row number from the SHForm Ref
462 if( !swn.empty() ) oid2 += std::stoul( swn ) - 1;
463 formToken.setOid( {0,oid2} );
464 ATH_MSG_DEBUG("Constructed DHForm Ref=" << formToken.toString() << " from " << dhFormToken );
465 dhFormToken = formToken.toString();
466 header->setDhFormToken( dhFormToken );
467 }
468 // see if the DataHeaderForm is already cached
469 if( dhFormToken.empty() || m_inputDHForms.find(dhFormToken) == m_inputDHForms.end() ) {
470 // no cached DHForm
471 size_t dbpos = dhFormToken.find("[DB=");
472 if( dbpos != std::string::npos ) {
473 const std::string dbGuid = dhFormToken.substr(dbpos+4, dbpos+36);
474 if( ++m_inDHFormCount[dbGuid] > m_inDHFMapMaxsize ) {
475 // prevent the input DHFMap from growing too large
476 clearInputDHFormCache( dbGuid );
477 m_inDHFormCount[dbGuid] = 1;
478 }
479 }
480 // we need to read a new DHF
481 void* voidPtr2 = nullptr;
482 if( dhFormToken.empty() ) {
483 // Some technologies can't set DHF token, use DH token with new CLID.
484 token->setData(&formToken);
485 formToken.setClassID( DHForm_p6_Guid );
486 } else {
487 formToken.fromString( dhFormToken );
488 formToken.setAuxString( token->auxString() ); // set PersSvc context
489 }
490 if (formToken.classID() != Guid::null()) {
491 try {
492 m_athenaPoolCnvSvc->setObjPtr(voidPtr2, &formToken);
493 } catch(const std::exception& err) {
494 voidPtr2 = nullptr;
495 error_message = err.what();
496 }
497 if (voidPtr2 == nullptr) {
498 // if there is no good lastGoodDHFRef then try reading DataHeaderForm Token from the first DataHeader
499 if( m_lastGoodDHFRef.find(token->contID()) == m_lastGoodDHFRef.end() ) {
500 Token firstToken;
501 token->setData(&firstToken);
502 firstToken.setOid(Token::OID_t(firstToken.oid().first, 0));
503 void* firstPtr1 = nullptr;
504 try {
505 m_athenaPoolCnvSvc->setObjPtr(firstPtr1, &firstToken);
506 } catch(const std::exception& err) {
507 firstPtr1 = nullptr;
508 error_message = err.what();
509 }
510 if (firstPtr1 == nullptr) throw std::runtime_error("Could not get first DataHeader for token = " + firstToken.toString() + ", " + error_message);
511
512 // Get DataHeaderForm Token from the first DataHeader
513 std::unique_ptr<DataHeader_p6> firstHeader( reinterpret_cast<DataHeader_p6*>(firstPtr1) );
514 dhFormToken = firstHeader->dhFormToken();
515
516 // Read DataHeaderForm and insert it to the cache
517 formToken.fromString( dhFormToken );
518 formToken.setAuxString( token->auxString() ); // set PersSvc context
519 try {
520 m_athenaPoolCnvSvc->setObjPtr(voidPtr2, &formToken);
521 } catch(const std::exception& err) {
522 voidPtr2 = nullptr;
523 error_message = err.what();
524 }
525 if (voidPtr2 == nullptr) throw std::runtime_error("Could not get DataHeaderForm for token = " + formToken.toString() + ", " + error_message);
526 m_lastGoodDHFRef[token->contID()] = dhFormToken;
527 m_inputDHForms[dhFormToken].reset( reinterpret_cast<DataHeaderForm_p6*>(voidPtr2) );
528 ATH_MSG_WARNING("DataHeaderForm read exception: " << error_message << " - reusing the last good DHForm");
529 } else {
530 // try to reuse the last good DHForm Ref (object is already cached)
531 ATH_MSG_WARNING("DataHeaderForm read exception: " << error_message << " - reusing the last good DHForm");
532 }
533 header->setDhFormToken(m_lastGoodDHFRef[token->contID()]);
534 return header;
535 }
536 if (voidPtr2 == nullptr) {
537 throw std::runtime_error("Could not get object for token = " + formToken.toString());
538 }
539 m_lastGoodDHFRef[token->contID()] = dhFormToken;
540 }
541 m_inputDHForms[dhFormToken].reset( reinterpret_cast<DataHeaderForm_p6*>(voidPtr2) );
542 }
543 return header;
544}
545
546//______________________________________________________________________________
548{
549 return m_tpOutConverter.createPersistent( transObj, *dh_form );
550}
551
552//______________________________________________________________________________
554{
555 auto iter = dh->m_inputDataHeader.begin();
556 while( iter != dh->m_inputDataHeader.end() ) {
557 if( iter->getToken()->dbID() == Guid::null() ) {
558 ATH_MSG_WARNING("Removed incomplete Input Element");
559 iter = dh->m_inputDataHeader.erase(iter);
560 } else {
561 ++iter;
562 }
563 }
564}
565
566//______________________________________________________________________________
568 if (token == nullptr) {
569 return(nullptr);
570 }
571 if (token->technology() == 0x00001000) { // Artificial ByteStream DataHeader Token
572 DataHeader* dh = new DataHeader();
573 std::string bestPfn, fileType;
574 m_athenaPoolCnvSvc->getPoolSvc()->lookupBestPfn(token->dbID().toString(), bestPfn, fileType);
576 dh->insert(dhe);
577 return(dh);
578 }
579 static const pool::Guid p6_guid("4DDBD295-EFCE-472A-9EC8-15CD35A9EB8D");
580 static const pool::Guid p5_guid("D82968A1-CF91-4320-B2DD-E0F739CBC7E6");
581 static const pool::Guid p4_guid("9630EB7B-CCD7-47D9-A39B-CBBF4133CDF2");
582 static const pool::Guid p3_guid("EC1318F0-8E28-45F8-9A2D-2597C1CC87A6");
583 try {
584 if( compareClassGuid(token, p6_guid ) ) {
585 std::unique_ptr<DataHeader_p6> header( poolReadObject_p6(token) );
586 auto dhForm = m_inputDHForms[ header->dhFormToken() ].get();
587 auto dh = m_tpInConverter.createTransient( header.get(), *dhForm, token );
589 // To dump the DataHeader uncomment below
590 // std::ostringstream ss; dh->dump(ss); std::cout << ss.str() << std::endl;
591 return dh;
592 } else if (this->compareClassGuid(token, p5_guid )) {
593 std::unique_ptr<DataHeader_p5> obj_p5( poolReadObject_p5(token) );
594 return m_tpInConverter_p5.createTransient( *obj_p5, *m_dhInForm5 ).release();
595 } else if (this->compareClassGuid(token, p4_guid )) {
596 std::unique_ptr<DataHeader_p4> obj_p4(this->poolReadObject<DataHeader_p4>(token));
597 DataHeaderCnv_p4 tPconverter_p4;
598 return(tPconverter_p4.createTransient(obj_p4.get()));
599 } else if (this->compareClassGuid(token, p3_guid )) {
600 std::unique_ptr<DataHeader_p3> obj_p3(this->poolReadObject<DataHeader_p3>(token));
601 DataHeaderCnv_p3 tPconverter_p3;
602 return(tPconverter_p3.createTransient(obj_p3.get()));
603 }
604 } catch (std::exception &e) {
605 // upgrade all exceptions to runtime_error (who needs that? MN)
606 std::string error = e.what();
607 throw std::runtime_error(error);
608 }
609 return(nullptr);
610}
#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.
virtual void lock()=0
Interface to allow an object to lock itself when made const in SG.
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 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
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.
virtual DataHeader * createTransient(const Token *token) override
DataHeader_p6 * m_sharedWriterCachedDH
cached values for use with SharedWriter server
std::unique_ptr< DataHeader_p6 > poolReadObject_p6(const Token *token)
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...
virtual void handle(const Incident &incident) override
Incident service handle listening for EndInputFile.
std::unique_ptr< DataHeader_p5 > poolReadObject_p5(const Token *token)
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
std::vector< DataHeaderElement > m_inputDataHeader
vector with DataHeaderElement to upstream DataHeader ("Provenance").
Definition DataHeader.h:211
void insert(const SG::TransientAddress *sgAddress, IOpaqueAddress *tokAddress=0, const std::string &pTag="")
Insert a new element into the "DataObject" vector.
static const Guid & null() noexcept
NULL-Guid: static class method.
Definition Guid.cxx:14
constexpr void toString(std::span< char, StrLen > buf, bool uppercase=true) const noexcept
Automatic conversion to string representation.
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 Token *token, const Guid &clid) const
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
const std::string & auxString() const
Access auxiliary string.
Definition Token.h:91
Token & setCont(const std::string &cnt)
Set container name.
Definition Token.h:71
const Token & setData(Token *pToken) const
Set all the data part of the token.
Definition Token.cxx:225
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 std::string & contID() const
Access container identifier.
Definition Token.h:69
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
const Guid & dbID() const
Access database identifier.
Definition Token.h:64
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