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