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