ATLAS Offline Software
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 
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 
30 static const pool::Guid DHForm_p6_Guid("7BE56CEF-C866-4BEE-9348-A5F34B5F1DAD");
31 
32 // cppcheck-suppress uninitMemberVar
33 DataHeaderCnv::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 
94 void 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();
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);
137  ATH_MSG_FATAL( errmsg );
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 
154 void 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 
169 std::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 
179 inline
180 std::string getSWNFromStr(const std::string& str) { return getValForKey(str, "[SWN="); }
181 inline
182 std::string getFILEFromStr(const std::string& str) { return getValForKey(str, "[FILE="); }
183 
184 std::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
190 inline
191 std::string storeSWNInStr(const std::string& str) { return std::format("[SWN={}]", str); }
192 
193 bool 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 */
214 StatusCode 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  */
235  if( m_sharedWriterCachedDH ) {
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 //______________________________________________________________________________
252 StatusCode DataHeaderCnv::updateRepRefs(IOpaqueAddress* pAddress, DataObject* pObject)
253 {
254  if( m_sharedWriterCachedDH ) {
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] );
265  if( !compareClassGuid( DHForm_p6_Guid ) ) {
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  }
274  if( m_sharedWriterCachedDHForm.find(dhid) == m_sharedWriterCachedDHForm.end() ) {
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)
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 //______________________________________________________________________________
293 StatusCode 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)
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 //______________________________________________________________________________
399 std::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
428 std::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 }
DataHeaderCnv::handle
virtual void handle(const Incident &incident) override
Incident service handle listening for EndInputFile.
Definition: DataHeaderCnv.cxx:94
getFILEFromStr
std::string getFILEFromStr(const std::string &str)
Definition: DataHeaderCnv.cxx:182
DataHeaderForm_p6
This class provides storage for the constant fields of the persistent DataHeader class.
Definition: DataHeader_p6.h:27
AthenaPoolConverter::setPlacementWithType
virtual Placement setPlacementWithType(const std::string &tname, const std::string &key, const std::string &output)
Set POOL placement hint for a given type.
Definition: AthenaPoolConverter.cxx:173
DataHeaderCnv::m_persFormMap
std::map< std::string, std::unique_ptr< DataHeaderForm_p6 >, placementComp > m_persFormMap
Definition: DataHeaderCnv.h:75
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
DataHeaderCnv_p6::setSGAliasFiltering
void setSGAliasFiltering(bool doFiltering)
Definition: DataHeaderCnv_p6.h:45
Guid::null
static const Guid & null()
NULL-Guid: static class method.
Definition: Guid.cxx:18
createLinkingScheme.iter
iter
Definition: createLinkingScheme.py:62
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
Placement
This class holds all the necessary information to guide the writing of an object in a physical place.
Definition: Placement.h:19
DataHeaderForm_p6::isModified
bool isModified() const
Definition: DataHeader_p6.cxx:134
storeSWNInStr
std::string storeSWNInStr(const std::string &str)
Definition: DataHeaderCnv.cxx:191
DataHeaderCnv::updateRep
virtual StatusCode updateRep(IOpaqueAddress *pAddress, DataObject *pObject) override
Extend base-class conversion methods.
Definition: DataHeaderCnv.cxx:214
DataHeaderCnv::createTransient
virtual DataHeader * createTransient() override
Definition: DataHeaderCnv.cxx:564
header
Definition: hcg.cxx:526
DataHeaderCnv::m_sharedWriterCachedDHToken
std::string m_sharedWriterCachedDHToken
Definition: DataHeaderCnv.h:96
Placement::containerName
const std::string & containerName() const
Access container name.
Definition: Placement.h:32
vtune_athena.format
format
Definition: vtune_athena.py:14
DataHeaderForm_p6::setVersion
void setVersion(const DHVersions ver)
change version if writing backward compatible format
Definition: DataHeader_p6.h:87
AthCheckMacros.h
Token::contID
const std::string & contID() const
Access container identifier.
Definition: Token.h:69
SG::fromStorable
bool fromStorable(DataObject *pDObj, T *&pTrans, bool quiet=false, IRegisterTransient *irt=0, bool isConst=true)
Definition: StorableConversions.h:169
AthenaPoolConverter::m_athenaPoolCnvSvc
ServiceHandle< IAthenaPoolCnvSvc > m_athenaPoolCnvSvc
Definition: AthenaPoolConverter.h:117
DataHeaderCnv::m_dhFormMdx
std::string m_dhFormMdx
Definition: DataHeaderCnv.h:89
DataHeaderCnv::m_sharedWriterCachedDHKey
std::string m_sharedWriterCachedDHKey
Definition: DataHeaderCnv.h:95
mergePhysValFiles.start
start
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:13
Token::auxString
const std::string & auxString() const
Access auxiliary string.
Definition: Token.h:91
DataHeaderCnv::m_tpOutConverter
DataHeaderCnv_p6 m_tpOutConverter
Definition: DataHeaderCnv.h:65
Token::dbID
const Guid & dbID() const
Access database identifier.
Definition: Token.h:64
T_AthenaPoolCustomCnvWithKey::keepPoolObj
void keepPoolObj(PERS *obj, const std::string &output)
Remember the POOL object to be written out (will be deleted after commit)
DataHeaderForm_p5
This class provides storage for the constant fields of the persistent DataHeader class.
Definition: DataHeader_p5.h:42
Placement::technology
int technology() const
Access technology type.
Definition: Placement.h:36
Guid::toString
const std::string toString() const
Automatic conversion to string representation.
Definition: Guid.cxx:58
DataHeaderCnv::m_tpInConverter_p5
DataHeaderCnv_p5 m_tpInConverter_p5
for use when reading DataHeader_p5
Definition: DataHeaderCnv.h:87
PyPoolBrowser.dh
dh
Definition: PyPoolBrowser.py:102
python.PyKernel.AttributeList
AttributeList
Definition: PyKernel.py:36
Token::classID
const Guid & classID() const
Access database identifier.
Definition: Token.h:73
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
DataHeaderForm_p6::setProcessTag
void setProcessTag(const std::string &tag)
Definition: DataHeader_p6.h:84
DataHeaderCnv::m_inputDHForms
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.
Definition: DataHeaderCnv.h:77
DataHeader_p6::setDhFormToken
void setDhFormToken(const std::string &formToken)
Definition: DataHeader_p6.cxx:166
DataHeaderCnv::m_sharedWriterCachedDHForm
std::map< std::string, std::unique_ptr< DataHeaderForm_p6 > > m_sharedWriterCachedDHForm
map of cached DHForms for DataHeader ID
Definition: DataHeaderCnv.h:94
makeKeyValStr
std::string makeKeyValStr(const std::string &key, const std::string &val)
Definition: DataHeaderCnv.cxx:184
getSWNFromStr
std::string getSWNFromStr(const std::string &str)
Definition: DataHeaderCnv.cxx:180
RootType
TTypeAdapter RootType
Definition: RootType.h:211
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:92
T_AthenaPoolCustCnv::setToken
virtual void setToken(const std::string &token)
Set the token (in std::string representation) and classID for the object that will be read next.
Token
This class provides a token that identifies in a unique way objects on the persistent storage.
Definition: Token.h:21
DataHeaderCnv::DataHeaderCnv
DataHeaderCnv(ISvcLocator *svcloc)
Definition: DataHeaderCnv.cxx:33
DataHeaderCnv::placementComp::operator()
bool operator()(const std::string &lhs, const std::string &rhs) const
Definition: DataHeaderCnv.cxx:193
TokenAddress
This class provides a Generic Transient Address for POOL tokens.
Definition: TokenAddress.h:23
DataHeaderCnv::m_inDHFMapMaxsize
unsigned m_inDHFMapMaxsize
Max DHForms to cache per input file.
Definition: DataHeaderCnv.h:82
DataHeaderForm_p6::DHverFormRef
@ DHverFormRef
Definition: DataHeader_p6.h:50
getValForKey
std::string getValForKey(const std::string &str, const std::string &key)
Definition: DataHeaderCnv.cxx:169
Token::OID_t
Definition: Token.h:24
pool::Guid
::Guid Guid
Definition: T_AthenaPoolCustCnv.h:19
Token::fromString
Token & fromString(const std::string &from)
Build from the string representation of a token.
Definition: Token.cxx:148
Token::setClassID
Token & setClassID(const Guid &cl_id)
Access database identifier.
Definition: Token.h:75
DataHeaderElement
This class provides a persistent form for the TransientAddress.
Definition: DataHeader.h:37
Token::technology
int technology() const
Access technology type.
Definition: Token.h:77
AthenaPoolConverter::m_i_poolToken
const Token * m_i_poolToken
Definition: AthenaPoolConverter.h:130
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
DataHeaderCnv_p6::insertDHRef
void insertDHRef(DataHeader_p6 *pers_dh, const std::string &key, const std::string &dh_tokstr, DataHeaderForm_p6 &dh_form) const
insert DH self reference as one of the DHElements. Contains the stream Key
Definition: DataHeaderCnv_p6.cxx:180
DataHeaderForm_p6::getToken
const std::string & getToken() const
Definition: DataHeader_p6.cxx:147
DataHeaderCnv::m_sharedWriterCachedDH
DataHeader_p6 * m_sharedWriterCachedDH
cached values for use with SharedWriter server
Definition: DataHeaderCnv.h:92
dqt_zlumi_pandas.err
err
Definition: dqt_zlumi_pandas.py:183
T_AthenaPoolCustomCnv
Compatibility for old converter classes that don't get passed the key.
Definition: T_AthenaPoolCustomCnv.h:132
DataHeader
This class provides the layout for summary information stored for data written to POOL.
Definition: DataHeader.h:126
DataHeader_p6::dhFormToken
const std::string & dhFormToken() const
Definition: DataHeader_p6.cxx:162
beamspotman.n
n
Definition: beamspotman.py:729
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
DataHeaderCnv::updateRepRefs
virtual StatusCode updateRepRefs(IOpaqueAddress *pAddress, DataObject *pObject) override
Definition: DataHeaderCnv.cxx:252
DataHeaderCnv_p6::createPersistent
DataHeader_p6 * createPersistent(const DataHeader *transObj, DataHeaderForm_p6 &form) const
Definition: DataHeaderCnv_p6.cxx:162
DataHeaderCnv::DataObjectToPool
virtual StatusCode DataObjectToPool(IOpaqueAddress *pAddr, DataObject *pObj) override
Write an object into POOL.
Definition: DataHeaderCnv.cxx:293
ClassID_traits
Default, invalid implementation of ClassID_traits.
Definition: Control/AthenaKernel/AthenaKernel/ClassID_traits.h:37
DataHeaderCnv::m_tpInConverter
DataHeaderCnv_p6 m_tpInConverter
Definition: DataHeaderCnv.h:66
calibdata.exception
exception
Definition: calibdata.py:495
DataHeaderCnv_p3.h
This file contains the class definition for the DataHeaderCnv_p3 and DataHeaderElementCnv_p3 classes.
DataHeaderCnv::clearInputDHFormCache
void clearInputDHFormCache(const std::string &dbGuid)
Delete cached DHForms for a given input file GUID.
Definition: DataHeaderCnv.cxx:154
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
Token::setDb
Token & setDb(const Guid &db)
Set database name.
Definition: Token.h:66
Placement::fileName
const std::string & fileName() const
Access file name.
Definition: Placement.h:28
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
Token::release
int release()
Release token: Decrease reference count and eventually delete.
Definition: Token.cxx:75
Placement::setFileName
Placement & setFileName(const std::string &fileName)
Set file name.
Definition: Placement.h:30
Token::setTechnology
Token & setTechnology(int t)
Set technology type.
Definition: Token.h:79
DataHeader_p6
This class provides a persistent representation for the DataHeader class.
Definition: DataHeader_p6.h:115
Placement::auxString
const std::string & auxString() const
Access auxiliary string.
Definition: Placement.h:40
DataHeaderCnv_p4::createTransient
DataHeader * createTransient(const DataHeader_p4 *persObj)
Definition: DataHeaderCnv_p4.h:51
TScopeAdapter::Name
std::string Name(unsigned int mod=Reflex::SCOPED) const
Definition: RootType.cxx:612
DataHeaderCnv::createPersistent
DataHeader_p6 * createPersistent(DataHeader *transObj, DataHeaderForm_p6 *)
Definition: DataHeaderCnv.cxx:544
DataHeaderCnv::m_dhInForm5
std::unique_ptr< DataHeaderForm_p5 > m_dhInForm5
Definition: DataHeaderCnv.h:88
DataHeaderCnv::poolReadObject_p5
std::unique_ptr< DataHeader_p5 > poolReadObject_p5()
Definition: DataHeaderCnv.cxx:399
DataHeader::insert
void insert(const SG::TransientAddress *sgAddress, IOpaqueAddress *tokAddress=0, const std::string &pTag="")
Insert a new element into the "DataObject" vector.
Definition: DataHeader.cxx:266
pool_uuid.guid
guid
Definition: pool_uuid.py:112
TokenAddress::setToken
void setToken(std::unique_ptr< Token > token)
Definition: TokenAddress.cxx:9
DataHeaderCnv::m_lastGoodDHFRef
std::map< std::string, std::string > m_lastGoodDHFRef
Definition: DataHeaderCnv.h:84
DataHeaderForm_p6::clearModified
void clearModified()
Definition: DataHeader_p6.cxx:138
DataHeaderCnv_p4.h
This file contains the class definition for the DataHeaderCnv_p4 and DataHeaderElementCnv_p4 classes.
DataHeaderCnv::m_oneDHForm
bool m_oneDHForm
if true write only one DataHeaderForm at the end (stop, finalize, or WriteDataHeaderForms incident) t...
Definition: DataHeaderCnv.h:72
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:76
DataHeaderForm_p6::setToken
void setToken(const std::string &tok)
Definition: DataHeader_p6.cxx:142
DataHeaderCnv_p4
This class provides the converter to customize the saving of DataHeader_p4.
Definition: DataHeaderCnv_p4.h:35
Token::toString
virtual const std::string toString() const
Retrieve the string representation of the token.
Definition: Token.cxx:129
DataHeaderForm_p6::sizeObj
std::size_t sizeObj() const
Definition: DataHeader_p6.cxx:100
DataHeaderCnv::m_inDHFormCount
std::map< std::string, unsigned > m_inDHFormCount
How many DHForms for an input file are in the cache.
Definition: DataHeaderCnv.h:80
Token::setOid
Token & setOid(const OID_t &oid)
Set object identifier.
Definition: Token.h:85
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:16
Placement::toString
const std::string toString() const
Retrieve the string representation of the placement.
Definition: Placement.cxx:15
DataHeaderCnv_p3::createTransient
DataHeader * createTransient(const DataHeader_p3 *persObj)
Definition: DataHeaderCnv_p3.h:51
DataHeaderCnv_p6::createTransient
DataHeader * createTransient(const DataHeader_p6 *persObj, const DataHeaderForm_p6 &form, const Token *dhToken) const
Definition: DataHeaderCnv_p6.cxx:72
TokenAddress.h
This file contains the class definition for the TokenAddress class.
DataHeaderCnv::removeBadElements
void removeBadElements(DataHeader *dh)
Remove DataHeaderElements with incomplete (dbID="") refs.
Definition: DataHeaderCnv.cxx:550
DataHeaderCnv_p5::createTransient
std::unique_ptr< DataHeader > createTransient(const DataHeader_p5 &persObj, const DataHeaderForm_p5 &dhForm) const
Definition: DataHeaderCnv_p5.h:70
ActsGeantFollowing_jobOptions_ITk.svcName
svcName
Definition: ActsGeantFollowing_jobOptions_ITk.py:196
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
Pythia8_RapidityOrderMPI.val
val
Definition: Pythia8_RapidityOrderMPI.py:14
DataHeader_p5
This class provides a persistent representation for the DataHeader class.
Definition: DataHeader_p5.h:67
Token::oid
const OID_t & oid() const
Access object identifier.
Definition: Token.h:81
Token::setAuxString
Token & setAuxString(const std::string &auxString)
Set auxiliary string.
Definition: Token.h:93
Token::setCont
Token & setCont(const std::string &cnt)
Set container name.
Definition: Token.h:71
str
Definition: BTagTrackIpAccessor.cxx:11
T_AthenaPoolCustCnv::compareClassGuid
virtual bool compareClassGuid(const Guid &clid) const
Compare POOL class GUID with the one of the object being read.
jobOptions.fileName
fileName
Definition: jobOptions.SuperChic_ALP2.py:39
Placement.h
This file contains the class definition for the Placement class (migrated from POOL).
DataHeaderCnv_p3
This class provides the converter to customize the saving of DataHeader_p3.
Definition: DataHeaderCnv_p3.h:35
AthenaPoolConverter::m_classDesc
RootType m_classDesc
Definition: AthenaPoolConverter.h:118
Token::setData
const Token & setData(Token *pToken) const
Set all the data part of the token.
Definition: Token.cxx:209
makeTOC.header
header
Definition: makeTOC.py:28
T_AthenaPoolCustCnv::initialize
virtual StatusCode initialize()
Gaudi Service Interface method implementations:
python.PyAthena.obj
obj
Definition: PyAthena.py:132
DataHeaderCnv::~DataHeaderCnv
~DataHeaderCnv()
Definition: DataHeaderCnv.cxx:40
Token.h
This file contains the class definition for the Token class (migrated from POOL).
error
Definition: IImpactPoint3dEstimator.h:70
Placement::fromString
Placement & fromString(const std::string &from)
Build from the string representation of a placement.
Definition: Placement.cxx:28
DataHeaderCnv::poolReadObject_p6
std::unique_ptr< DataHeader_p6 > poolReadObject_p6()
Definition: DataHeaderCnv.cxx:428
DataHeaderCnv::initialize
virtual StatusCode initialize() override
Gaudi Service Interface method implementations:
Definition: DataHeaderCnv.cxx:53
ServiceHandle< IIncidentSvc >
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37
DataHeaderCnv.h
This file contains the class definition for the DataHeaderCnv class.
TScopeAdapter
Definition: RootType.h:119