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