ATLAS Offline Software
Loading...
Searching...
No Matches
AthenaPoolCnvSvc.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
9
10#include "AthenaPoolCnvSvc.h"
11
12#include "GaudiKernel/AttribStringParser.h"
13#include "GaudiKernel/ClassID.h"
14#include "GaudiKernel/FileIncident.h"
15#include "GaudiKernel/IIncidentSvc.h"
16#include "GaudiKernel/IIoComponentMgr.h"
17#include "GaudiKernel/IOpaqueAddress.h"
18
23
24#include "StorageSvc/DbReflex.h"
26
27#include <algorithm>
28#include <charconv>
29#include <format>
30#include <iomanip>
31#include <sstream>
32
33//______________________________________________________________________________
34// Initialize the service.
36 // Initialize DataModelCompatSvc
37 ServiceHandle<IService> dmcsvc("DataModelCompatSvc", this->name());
38 ATH_CHECK(dmcsvc.retrieve());
39 // Retrieve PoolSvc
40 ATH_CHECK(m_poolSvc.retrieve());
41 StringProperty defContainerType("DefaultContainerType", "ROOTTREEINDEX");
42 if(IProperty* propertyServer = dynamic_cast<IProperty*>(m_poolSvc.get())) {
43 propertyServer->getProperty(&defContainerType).ignore();
44 }
45 m_defContainerType = defContainerType.value();
46 // Retrieve ClassIDSvc
47 ATH_CHECK(m_clidSvc.retrieve());
48 // Register this service for 'I/O' events
49 ServiceHandle<IIoComponentMgr> iomgr("IoComponentMgr", name());
50 ATH_CHECK(iomgr.retrieve());
51 if (!iomgr->io_register(this).isSuccess()) {
52 ATH_MSG_FATAL("Could not register myself with the IoComponentMgr !");
53 return(StatusCode::FAILURE);
54 }
55 // Validate provided event data technologies and fill the internal cache
56 for (const auto& [key, value] : m_storageTechProp.value()) {
57 try {
58 const auto dbType = pool::DbType::getType(value);
59 if (dbType == pool::TEST_StorageType) {
60 ATH_MSG_FATAL(std::format("Unknown storage type requested for file {}: {}", key, value));
61 return StatusCode::FAILURE;
62 }
63 m_storageTechMap.emplace(key, dbType.type());
64 } catch (const std::exception& e) {
65 ATH_MSG_FATAL(std::format("Exception while getting storage type for file {}: {}", key, e.what()));
66 return StatusCode::FAILURE;
67 } catch (...) {
68 ATH_MSG_FATAL(std::format("Unknown exception while getting storage type for file {}", key));
69 return StatusCode::FAILURE;
70 }
71 }
72 // Extracting INPUT POOL ItechnologySpecificAttributes for Domain, Database and Container.
74 // Extracting the INPUT POOL ItechnologySpecificAttributes which are to be printed for each event
76 // Setup incident for EndEvent to print out attributes each event
77 ServiceHandle<IIncidentSvc> incSvc("IncidentSvc", name());
78 long int pri = 1000;
79 if (!m_inputPoolAttrPerEvent.value().empty()) {
80 // Set to be listener for EndEvent
81 incSvc->addListener(this, "EndEvent", pri);
82 ATH_MSG_DEBUG("Subscribed to EndEvent for printing out input file attributes.");
83 }
84 if (!processPoolAttributes(m_inputAttr, "", IPoolSvc::kInputStream, false, true, true).isSuccess()) {
85 ATH_MSG_DEBUG("setInputAttribute failed setting POOL domain attributes.");
86 }
87
88 // Load these dictionaries now, so we don't need to try to do so
89 // while multiple threads are running.
90 TClass::GetClass ("TLeafI");
91 TClass::GetClass ("TLeafL");
92 TClass::GetClass ("TLeafD");
93 TClass::GetClass ("TLeafF");
94
95 return(StatusCode::SUCCESS);
96}
97//______________________________________________________________________________
99 ATH_MSG_DEBUG("I/O reinitialization...");
100 m_processedContextIds.clear();
101 return(StatusCode::SUCCESS);
102}
103//______________________________________________________________________________
104void AthenaPoolCnvSvc::flushDataHeaderForms(const std::string& streamName) {
105 // Write remaining DataHeaderForms for a given streamName, "*"" means all
106 auto DHCnvListener = dynamic_cast<IIncidentListener*>( converter( ClassID_traits<DataHeader>::ID() ) );
107 FileIncident incident(name(), "WriteDataHeaderForms", streamName);
108 if( DHCnvListener ) DHCnvListener->handle(incident);
109}
110//______________________________________________________________________________
112 ATH_MSG_VERBOSE("stop()");
113 // In case of direct writing without an OutputStream, this should be a good time to flush DHForms
115 return StatusCode::SUCCESS;
116}
117//______________________________________________________________________________
119 ATH_MSG_VERBOSE("Finalizing...");
120 // Some algorithms write in finalize(), flush DHForms if any are left
122 // Release ClassIDSvc
123 if (!m_clidSvc.release().isSuccess()) {
124 ATH_MSG_WARNING("Cannot release ClassIDSvc.");
125 }
126 // Release PoolSvc
127 if (!m_poolSvc.release().isSuccess()) {
128 ATH_MSG_WARNING("Cannot release PoolSvc.");
129 }
130 // Print Performance Statistics
131 // The pattern AthenaPoolCnvSvc.*PerfStats is ignored in AtlasTest/TestTools/share/post.sh
132 const std::string msgPrefix{"PerfStats "};
133 ATH_MSG_INFO(msgPrefix << std::string(40, '-'));
134 ATH_MSG_INFO(msgPrefix << "Timing Measurements for AthenaPoolCnvSvc");
135 ATH_MSG_INFO(msgPrefix << std::string(40, '-'));
136 for(const auto& [key, value] : m_chronoMap) {
137 ATH_MSG_INFO(msgPrefix << "| " << std::left << std::setw(15) << key << " | "
138 << std::right << std::setw(15) << std::fixed << std::setprecision(0) << value << " ms |");
139 }
140 ATH_MSG_INFO(msgPrefix << std::string(40, '-'));
141
142 m_cnvs.clear();
143 m_cnvs.shrink_to_fit();
144 return(StatusCode::SUCCESS);
145}
146//______________________________________________________________________________
148 ATH_MSG_DEBUG("I/O finalization...");
149 return(StatusCode::SUCCESS);
150}
151//______________________________________________________________________________
152StatusCode AthenaPoolCnvSvc::createObj(IOpaqueAddress* pAddress, DataObject*& refpObject) {
153 assert(pAddress);
154 std::string objName = "ALL";
155 if (m_useDetailChronoStat.value()) {
156 if (m_clidSvc->getTypeNameOfID(pAddress->clID(), objName).isFailure()) {
157 objName = std::to_string(pAddress->clID());
158 }
159 objName += '#';
160 objName += *(pAddress->par() + 1);
161 }
162 // StopWatch listens from here until the end of this current scope
163 PMonUtils::BasicStopWatch stopWatch("cObj_" + objName, m_chronoMap);
164 if (!m_persSvcPerInputType.empty()) { // Use separate PersistencySvc for each input data type
165 TokenAddress* tokAddr = dynamic_cast<TokenAddress*>(pAddress);
166 if (tokAddr != nullptr && tokAddr->getToken() != nullptr && (tokAddr->getToken()->contID().starts_with(m_persSvcPerInputType.value() + "(") || tokAddr->getToken()->contID().starts_with(m_persSvcPerInputType.value() + "_"))) {
167 const unsigned int maxContext = m_poolSvc->getInputContextMapSize();
168 const unsigned int auxContext = m_poolSvc->getInputContext(tokAddr->getToken()->classID().toString() + tokAddr->getToken()->dbID().toString(), 1);
169 char text[32];
170 const std::string contextStr = std::format("[CTXT={:08X}]", auxContext);
171 std::strncpy(text, contextStr.c_str(), sizeof(text) - 1);
172 text[sizeof(text) - 1] = '\0';
173 if (m_poolSvc->getInputContextMapSize() > maxContext) {
174 if (!m_poolSvc->setAttribute("TREE_CACHE", "0", pool::DbType(pool::ROOTTREE_StorageType).type(), "FID:" + tokAddr->getToken()->dbID().toString(), m_persSvcPerInputType.value(), auxContext).isSuccess()) {
175 ATH_MSG_DEBUG("setInputAttribute failed to switch off TTreeCache for id = " << auxContext << ".");
176 }
177 }
178 tokAddr->getToken()->setAuxString(text);
179 }
180 }
181 // Forward to base class createObj
182 StatusCode status = ::AthCnvSvc::createObj(pAddress, refpObject);
183 return(status);
184}
185//______________________________________________________________________________
186StatusCode AthenaPoolCnvSvc::createRep(DataObject* pObject, IOpaqueAddress*& refpAddress) {
187 assert(pObject);
188 std::string objName = "ALL";
189 if (m_useDetailChronoStat.value()) {
190 if (m_clidSvc->getTypeNameOfID(pObject->clID(), objName).isFailure()) {
191 objName = std::to_string(pObject->clID());
192 }
193 objName += '#';
194 objName += pObject->registry()->name();
195 }
196 // StopWatch listens from here until the end of this current scope
197 PMonUtils::BasicStopWatch stopWatch("cRep_" + objName, m_chronoMap);
198 StatusCode status = StatusCode::FAILURE;
199 if (pObject->clID() == 1) {
200 // No transient object was found use cnv to write default persistent object
201 SG::DataProxy* proxy = dynamic_cast<SG::DataProxy*>(pObject->registry());
202 if (proxy != nullptr) {
203 IConverter* cnv = converter(proxy->clID());
204 status = cnv->createRep(pObject, refpAddress);
205 }
206 } else {
207 // Forward to base class createRep
208 try {
209 status = ::AthCnvSvc::createRep(pObject, refpAddress);
210 } catch(std::runtime_error& e) {
211 ATH_MSG_FATAL(e.what());
212 }
213 }
214 return(status);
215}
216//______________________________________________________________________________
217StatusCode AthenaPoolCnvSvc::fillRepRefs(IOpaqueAddress* pAddress, DataObject* pObject) {
218 assert(pObject);
219 std::string objName = "ALL";
220 if (m_useDetailChronoStat.value()) {
221 if (m_clidSvc->getTypeNameOfID(pObject->clID(), objName).isFailure()) {
222 objName = std::to_string(pObject->clID());
223 }
224 objName += '#';
225 objName += pObject->registry()->name();
226 }
227 // StopWatch listens from here until the end of this current scope
228 PMonUtils::BasicStopWatch stopWatch("fRep_" + objName, m_chronoMap);
229 StatusCode status = StatusCode::FAILURE;
230 if (pObject->clID() == 1) {
231 // No transient object was found use cnv to write default persistent object
232 SG::DataProxy* proxy = dynamic_cast<SG::DataProxy*>(pObject->registry());
233 if (proxy != nullptr) {
234 IConverter* cnv = converter(proxy->clID());
235 status = cnv->fillRepRefs(pAddress, pObject);
236 }
237 } else {
238 // Forward to base class fillRepRefs
239 try {
240 status = ::AthCnvSvc::fillRepRefs(pAddress, pObject);
241 } catch(std::runtime_error& e) {
242 ATH_MSG_FATAL(e.what());
243 }
244 }
245 return(status);
246}
247//______________________________________________________________________________
248StatusCode AthenaPoolCnvSvc::connectOutput(const std::string& outputConnectionSpec,
249 const std::string& /*openMode*/) {
250 return(connectOutput(outputConnectionSpec));
251}
252//______________________________________________________________________________
253StatusCode AthenaPoolCnvSvc::connectOutput(const std::string& outputConnectionSpec) {
254// This is called before DataObjects are being converted.
255 std::string outputConnection = outputConnectionSpec.substr(0, outputConnectionSpec.find('['));
256 // Extract the technology
257 int tech{0};
258 if (!decodeOutputSpec(outputConnection, tech).isSuccess()) {
259 ATH_MSG_ERROR("connectOutput FAILED extract file name and technology.");
260 return(StatusCode::FAILURE);
261 }
262 unsigned int contextId = outputContextId(outputConnection);
263 try {
264 if (!m_poolSvc->connect(pool::ITransaction::UPDATE, contextId).isSuccess()) {
265 ATH_MSG_ERROR("connectOutput FAILED to open an UPDATE transaction.");
266 return(StatusCode::FAILURE);
267 }
268 } catch (std::exception& e) {
269 ATH_MSG_ERROR("connectOutput - caught exception: " << e.what());
270 return(StatusCode::FAILURE);
271 }
272 std::unique_lock<std::mutex> lock(m_mutex);
273 if (m_processedContextIds.insert(contextId).second) {
274 // Extracting OUTPUT POOL ItechnologySpecificAttributes for Domain, Database and Container.
276 }
277 if (!processPoolAttributes(m_domainAttr, outputConnection, contextId).isSuccess()) {
278 ATH_MSG_DEBUG("connectOutput failed process POOL domain attributes.");
279 }
280 if (!processPoolAttributes(m_databaseAttr, outputConnection, contextId).isSuccess()) {
281 ATH_MSG_DEBUG("connectOutput failed process POOL database attributes.");
282 }
283 return(StatusCode::SUCCESS);
284}
285
286//______________________________________________________________________________
287StatusCode AthenaPoolCnvSvc::commitOutput(const std::string& outputConnectionSpec, bool doCommit) {
288 // This is called after all DataObjects are converted.
289 std::string outputConnection = outputConnectionSpec.substr(0, outputConnectionSpec.find('['));
290 // StopWatch listens from here until the end of this current scope
291 PMonUtils::BasicStopWatch stopWatch("commitOutput", m_chronoMap);
292 std::unique_lock<std::mutex> lock(m_mutex);
293 // Extract the technology
294 int tech{0};
295 if (!decodeOutputSpec(outputConnection, tech).isSuccess()) {
296 ATH_MSG_ERROR("connectOutput FAILED extract file name and technology.");
297 return(StatusCode::FAILURE);
298 }
299 unsigned int contextId = outputContextId(outputConnection);
300 if (!processPoolAttributes(m_domainAttr, outputConnection, contextId).isSuccess()) {
301 ATH_MSG_DEBUG("commitOutput failed process POOL domain attributes.");
302 }
303 if (!processPoolAttributes(m_databaseAttr, outputConnection, contextId).isSuccess()) {
304 ATH_MSG_DEBUG("commitOutput failed process POOL database attributes.");
305 }
306 if (!processPoolAttributes(m_containerAttr, outputConnection, contextId).isSuccess()) {
307 ATH_MSG_DEBUG("commitOutput failed process POOL container attributes.");
308 }
309
310 // lock.unlock(); //MN: first need to make commitCache slot-specific
311 try {
312 if (doCommit) {
313 if (!m_poolSvc->commit(contextId).isSuccess()) {
314 ATH_MSG_ERROR("commitOutput FAILED to commit OutputStream.");
315 return(StatusCode::FAILURE);
316 }
317 } else {
318 if (!m_poolSvc->commitAndHold(contextId).isSuccess()) {
319 ATH_MSG_ERROR("commitOutput FAILED to commitAndHold OutputStream.");
320 return(StatusCode::FAILURE);
321 }
322 }
323 } catch (std::exception& e) {
324 ATH_MSG_ERROR("commitOutput - caught exception: " << e.what());
325 return(StatusCode::FAILURE);
326 }
327 if (!this->cleanUp(outputConnection).isSuccess()) {
328 ATH_MSG_ERROR("commitOutput FAILED to cleanup converters.");
329 return(StatusCode::FAILURE);
330 }
331 return(StatusCode::SUCCESS);
332}
333
334//______________________________________________________________________________
335StatusCode AthenaPoolCnvSvc::disconnectOutput(const std::string& outputConnectionSpec) {
336 std::string outputConnection = outputConnectionSpec.substr(0, outputConnectionSpec.find('['));
337 unsigned int contextId = outputContextId(outputConnection);
338 StatusCode sc = m_poolSvc->disconnect(contextId);
339 return sc;
340}
341
342//______________________________________________________________________________
343unsigned int AthenaPoolCnvSvc::outputContextId(const std::string& outputConnection) {
344 return m_persSvcPerOutput?
345 m_poolSvc->getOutputContext(outputConnection) : (unsigned int)IPoolSvc::kOutputStream;
346}
347
348//______________________________________________________________________________
352//______________________________________________________________________________
353Token* AthenaPoolCnvSvc::registerForWrite(Placement* placement, const void* obj, const RootType& classDesc) {
354 // StopWatch listens from here until the end of this current scope
355 PMonUtils::BasicStopWatch stopWatch("cRepR_ALL", m_chronoMap);
356 Token* token = nullptr;
357 if (m_persSvcPerOutput) { // Use separate PersistencySvc for each output stream/file
358 char text[32];
359 const std::string contextStr = std::format("[CTXT={:08X}]", m_poolSvc->getOutputContext(placement->fileName()));
360 std::strncpy(text, contextStr.c_str(), sizeof(text) - 1);
361 text[sizeof(text) - 1] = '\0';
362 placement->setAuxString(text);
363 }
364 token = m_poolSvc->registerForWrite(placement, obj, classDesc);
365 return(token);
366}
367//______________________________________________________________________________
368void AthenaPoolCnvSvc::setObjPtr(void*& obj, const Token* token) {
369 ATH_MSG_VERBOSE("Requesting object for: " << token->toString());
370 // StopWatch listens from here until the end of this current scope
371 PMonUtils::BasicStopWatch stopWatch("cObjR_ALL", m_chronoMap);
372 if (token->dbID() != Guid::null()) {
373 ATH_MSG_VERBOSE("Requesting object for: " << token->toString());
374 m_poolSvc->setObjPtr(obj, token);
375 }
376}
377//______________________________________________________________________________
379 return(m_useDetailChronoStat.value());
380}
381//______________________________________________________________________________
382StatusCode AthenaPoolCnvSvc::createAddress(long svcType,
383 const CLID& clid,
384 const std::string* par,
385 const unsigned long* ip,
386 IOpaqueAddress*& refpAddress) {
387 if( svcType != repSvcType() ) {
388 ATH_MSG_ERROR("createAddress: svcType != POOL_StorageType " << svcType << " " << repSvcType());
389 return(StatusCode::FAILURE);
390 }
391 std::unique_ptr<Token> token;
392 if (par[0].compare(0, 3, "SHM") == 0) {
393 token = std::make_unique<Token>();
394 token->setOid(Token::OID_t(ip[0], ip[1]));
395 token->setAuxString("[PNAME=" + par[2] + "]");
396 RootType classDesc = RootType::ByNameNoQuiet(par[2]);
397 token->setClassID(pool::DbReflex::guid(classDesc));
398 } else {
399 token.reset(m_poolSvc->getToken(par[0], par[1], ip[0]));
400 }
401 if (token == nullptr) {
402 return(StatusCode::RECOVERABLE);
403 }
404 refpAddress = new TokenAddress(repSvcType(), clid, "", par[1], IPoolSvc::kInputStream, std::move(token));
405 return(StatusCode::SUCCESS);
406}
407//______________________________________________________________________________
408StatusCode AthenaPoolCnvSvc::createAddress(long svcType,
409 const CLID& clid,
410 const std::string& refAddress,
411 IOpaqueAddress*& refpAddress) {
412 if (svcType != repSvcType()) {
413 ATH_MSG_ERROR("createAddress: svcType != POOL_StorageType " << svcType << " " << repSvcType());
414 return(StatusCode::FAILURE);
415 }
416 refpAddress = new GenericAddress(repSvcType(), clid, refAddress);
417 return(StatusCode::SUCCESS);
418}
419//______________________________________________________________________________
420StatusCode AthenaPoolCnvSvc::convertAddress(const IOpaqueAddress* pAddress,
421 std::string& refAddress) {
422 assert(pAddress);
423 const TokenAddress* tokAddr = dynamic_cast<const TokenAddress*>(pAddress);
424 if (tokAddr != nullptr && tokAddr->getToken() != nullptr) {
425 refAddress = tokAddr->getToken()->toString();
426 } else {
427 refAddress = *pAddress->par();
428 }
429 return(StatusCode::SUCCESS);
430}
431//__________________________________________________________________________
432StatusCode AthenaPoolCnvSvc::decodeOutputSpec(std::string& fileSpec, int& outputTech) const {
433 if (fileSpec.starts_with ( "ROOTKEY:")) {
434 outputTech = pool::ROOTKEY_StorageType.type();
435 fileSpec.erase(0, 8);
436 } else if (fileSpec.starts_with ( "ROOTTREE:")) {
437 outputTech = pool::ROOTTREE_StorageType.type();
438 fileSpec.erase(0, 9);
439 } else if (fileSpec.starts_with ( "ROOTTREEINDEX:")) {
440 outputTech = pool::ROOTTREEINDEX_StorageType.type();
441 fileSpec.erase(0, 14);
442 } else if (fileSpec.starts_with ( "ROOTRNTUPLE:")) {
443 outputTech = pool::ROOTRNTUPLE_StorageType.type();
444 fileSpec.erase(0, 12);
445 } else if (outputTech == 0) {
446 // Find the appropriate event data technology for this file
447 // This will be used for event data and its data header
448 // First we look for an exact file name match
449 // If that fails, we look for a wildcard ("*") match
450 // If that also fails, we use the default value from PoolSvc
451 if (auto it = m_storageTechMap.find(fileSpec); it != m_storageTechMap.end()) {
452 outputTech = it->second;
453 } else if (it = m_storageTechMap.find("*"); it != m_storageTechMap.end()) {
454 outputTech = it->second;
455 } else {
457 }
458 }
459 return StatusCode::SUCCESS;
460}
461//______________________________________________________________________________
463 m_cnvs.push_back(cnv);
464 return(StatusCode::SUCCESS);
465}
466//______________________________________________________________________________
467StatusCode AthenaPoolCnvSvc::cleanUp(const std::string& connection) {
468 bool retError = false;
469 std::size_t cpos = connection.find(':');
470 std::size_t bpos = connection.find('[');
471 if (cpos == std::string::npos) {
472 cpos = 0;
473 } else {
474 cpos++;
475 }
476 if (bpos != std::string::npos) bpos = bpos - cpos;
477 const std::string conn = connection.substr(cpos, bpos);
478 ATH_MSG_VERBOSE("Cleanup for Connection='"<< conn <<"'");
479 for (auto converter : m_cnvs) {
480 if (!converter->cleanUp(conn).isSuccess()) {
481 ATH_MSG_WARNING("AthenaPoolConverter cleanUp failed.");
482 retError = true;
483 }
484 }
485 return(retError ? StatusCode::FAILURE : StatusCode::SUCCESS);
486}
487//______________________________________________________________________________
488StatusCode AthenaPoolCnvSvc::setInputAttributes(const std::string& fileName) {
489 // Set attributes for input file
490 m_lastInputFileName = fileName; // Save file name for printing attributes per event
491 if (!processPoolAttributes(m_inputAttr, m_lastInputFileName, IPoolSvc::kInputStream, false, true, false).isSuccess()) {
492 ATH_MSG_DEBUG("setInputAttribute failed setting POOL database/container attributes.");
493 }
495 ATH_MSG_DEBUG("setInputAttribute failed getting POOL database/container attributes.");
496 }
497 if (!m_persSvcPerInputType.empty()) {
498 // Loop over all extra event input contexts and switch off TTreeCache
499 const auto& extraInputContextMap = m_poolSvc->getInputContextMap();
500 for (const auto& [label, id]: extraInputContextMap) {
501 if (!m_poolSvc->setAttribute("TREE_CACHE", "0", pool::DbType(pool::ROOTTREE_StorageType).type(), m_lastInputFileName, m_persSvcPerInputType.value(), id).isSuccess()) {
502 ATH_MSG_DEBUG("setInputAttribute failed to switch off TTreeCache for = " << label << ".");
503 }
504 }
505 }
506 return(StatusCode::SUCCESS);
507}
508
509//______________________________________________________________________________
510void AthenaPoolCnvSvc::handle(const Incident& incident) {
511 if (incident.type() == "EndEvent") {
513 ATH_MSG_DEBUG("handle EndEvent failed process POOL database attributes.");
514 }
515 }
516}
517//______________________________________________________________________________
518AthenaPoolCnvSvc::AthenaPoolCnvSvc(const std::string& name, ISvcLocator* pSvcLocator) :
519 base_class(name, pSvcLocator, pool::POOL_StorageType.type()) {
520}
521//__________________________________________________________________________
522void AthenaPoolCnvSvc::extractPoolAttributes(const StringArrayProperty& property,
523 std::vector<std::vector<std::string> >* contAttr,
524 std::vector<std::vector<std::string> >* dbAttr,
525 std::vector<std::vector<std::string> >* domAttr) const {
526 std::vector<std::string> opt;
527 std::string attributeName, containerName, databaseName, valueString;
528 for (const auto& propertyValue : property.value()) {
529 opt.clear();
530 attributeName.clear();
531 containerName.clear();
532 databaseName.clear();
533 valueString.clear();
534 using Gaudi::Utils::AttribStringParser;
535 for (const AttribStringParser::Attrib& attrib : AttribStringParser (propertyValue)) {
536 if (attrib.tag == "DatabaseName") {
537 databaseName = attrib.value;
538 } else if (attrib.tag == "ContainerName") {
539 if (databaseName.empty()) {
540 databaseName = "*";
541 }
542 containerName = attrib.value;
543 } else {
544 attributeName = attrib.tag;
545 valueString = attrib.value;
546 }
547 }
548 if (!attributeName.empty() && !valueString.empty()) {
549 opt.push_back(attributeName);
550 opt.push_back(valueString);
551 if (!databaseName.empty()) {
552 opt.push_back(databaseName);
553 if (!containerName.empty()) {
554 opt.push_back(containerName);
555 if (containerName.compare(0, 6, "TTree=") == 0) {
556 dbAttr->push_back(opt);
557 } else {
558 contAttr->push_back(opt);
559 }
560 } else {
561 opt.push_back("");
562 dbAttr->push_back(opt);
563 }
564 } else if (domAttr != 0) {
565 domAttr->push_back(opt);
566 } else {
567 opt.push_back("*");
568 opt.push_back("");
569 dbAttr->push_back(opt);
570 }
571 }
572 }
573}
574//__________________________________________________________________________
575StatusCode AthenaPoolCnvSvc::processPoolAttributes(std::vector<std::vector<std::string> >& attr,
576 const std::string& fileName,
577 unsigned long contextId,
578 bool doGet,
579 bool doSet,
580 bool doClear) const {
581 bool retError = false;
582 for (auto& attrEntry : attr) {
583 if (attrEntry.size() == 2) {
584 const std::string& opt = attrEntry[0];
585 std::string data = attrEntry[1];
586 if (data == "int" || data == "DbLonglong" || data == "double" || data == "string") {
587 if (doGet) {
588 if (!m_poolSvc->getAttribute(opt, data, pool::DbType(pool::ROOTTREE_StorageType).type(), contextId).isSuccess()) {
589 ATH_MSG_DEBUG("getAttribute failed for domain attr " << opt);
590 retError = true;
591 }
592 }
593 } else if (doSet) {
594 if (m_poolSvc->setAttribute(opt, data, pool::DbType(pool::ROOTTREE_StorageType).type(), contextId).isSuccess()) {
595 ATH_MSG_DEBUG("setAttribute " << opt << " to " << data);
596 if (doClear) {
597 attrEntry.clear();
598 }
599 } else {
600 ATH_MSG_DEBUG("setAttribute failed for domain attr " << opt << " to " << data);
601 retError = true;
602 }
603 }
604 }
605 if (attrEntry.size() == 4) {
606 const std::string& opt = attrEntry[0];
607 std::string data = attrEntry[1];
608 const std::string& file = attrEntry[2];
609 const std::string& cont = attrEntry[3];
610 if (!fileName.empty() && (0 == fileName.compare(0, fileName.find('?'), file)
611 || (file[0] == '*' && file.find("," + fileName + ",") == std::string::npos))) {
612 if (data == "int" || data == "DbLonglong" || data == "double" || data == "string") {
613 if (doGet) {
614 if (!m_poolSvc->getAttribute(opt, data, pool::DbType(pool::ROOTTREE_StorageType).type(), fileName, cont, contextId).isSuccess()) {
615 ATH_MSG_DEBUG("getAttribute failed for database/container attr " << opt);
616 retError = true;
617 }
618 }
619 } else if (doSet) {
620 if (m_poolSvc->setAttribute(opt, data, pool::DbType(pool::ROOTTREE_StorageType).type(), fileName, cont, contextId).isSuccess()) {
621 ATH_MSG_DEBUG("setAttribute " << opt << " to " << data << " for db: " << fileName << " and cont: " << cont);
622 if (doClear) {
623 if (file[0] == '*' && !m_persSvcPerOutput) {
624 attrEntry[2] += "," + fileName + ",";
625 } else {
626 attrEntry.clear();
627 }
628 }
629 } else {
630 ATH_MSG_DEBUG("setAttribute failed for " << opt << " to " << data << " for db: " << fileName << " and cont: " << cont);
631 retError = true;
632 }
633 }
634 }
635 }
636 }
637 std::erase_if(attr, [](const auto& entry) { return entry.empty(); });
638 return(retError ? StatusCode::FAILURE : StatusCode::SUCCESS);
639}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
This file contains the class definition for the AthenaPoolCnvSvc class.
This file contains the class definition for the DataHeader and DataHeaderElement classes.
uint32_t CLID
The Class ID type.
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
static Double_t sc
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).
virtual StatusCode createRep(DataObject *pObject, IOpaqueAddress *&refpAddress) override
Implementation of IConverter: Convert the transient object to the requested representation.
virtual StatusCode createObj(IOpaqueAddress *pAddress, DataObject *&refpObject) override
Implementation of IConverter: Create the transient representation of an object.
virtual StatusCode fillRepRefs(IOpaqueAddress *pAddress, DataObject *pObject) override
Implementation of IConverter: Resolve the references of the converted object.
ServiceHandle< IClassIDSvc > m_clidSvc
virtual IPoolSvc * getPoolSvc() override
StatusCode createAddress(long svcType, const CLID &clid, const std::string *par, const unsigned long *ip, IOpaqueAddress *&refpAddress) override
Create a Generic address using explicit arguments to identify a single object.
virtual void handle(const Incident &incident) override
Implementation of IIncidentListener: Handle for EndEvent incidence.
Gaudi::Property< bool > m_useDetailChronoStat
UseDetailChronoStat, enable detailed output for time and size statistics for AthenaPOOL: default = fa...
StatusCode processPoolAttributes(std::vector< std::vector< std::string > > &attr, const std::string &fileName, unsigned long contextId, bool doGet=true, bool doSet=true, bool doClear=true) const
Set/get technology dependent POOL attributes.
std::map< std::string, int > m_storageTechMap
std::vector< std::vector< std::string > > m_inputAttrPerEvent
virtual StatusCode io_finalize() override
virtual StatusCode initialize() override
Required of all Gaudi Services.
virtual StatusCode stop() override
virtual StatusCode io_reinit() override
virtual StatusCode registerCleanUp(IAthenaPoolCleanUp *cnv) override
Implement registerCleanUp to register a IAthenaPoolCleanUp to be called during cleanUp.
virtual StatusCode fillRepRefs(IOpaqueAddress *pAddress, DataObject *pObject) override
Implementation of IConversionSvc: Resolve the references of the converted object.
virtual StatusCode decodeOutputSpec(std::string &connectionSpec, int &outputTech) const override
Extract/deduce the DB technology from the connection string/file specification.
std::vector< std::vector< std::string > > m_databaseAttr
virtual StatusCode createObj(IOpaqueAddress *pAddress, DataObject *&refpObject) override
Implementation of IConversionSvc: Create the transient representation of an object from persistent st...
void extractPoolAttributes(const Gaudi::Property< std::vector< std::string > > &property, std::vector< std::vector< std::string > > *contAttr, std::vector< std::vector< std::string > > *dbAttr, std::vector< std::vector< std::string > > *domAttr=0) const
Extract POOL ItechnologySpecificAttributes for Domain, Database and Container from property.
virtual bool useDetailChronoStat() const override
std::vector< std::vector< std::string > > m_containerAttr
virtual Token * registerForWrite(Placement *placement, const void *obj, const RootType &classDesc) override
virtual StatusCode disconnectOutput(const std::string &outputConnectionSpec) override
Disconnect to the output connection.
Gaudi::Property< std::string > m_persSvcPerInputType
PersSvcPerInputType, string property, tree name to use multiple persistency services,...
Gaudi::Property< std::vector< std::string > > m_inputPoolAttr
Input PoolAttributes, vector with names and values of technology specific attributes for POOL.
virtual StatusCode createRep(DataObject *pObject, IOpaqueAddress *&refpAddress) override
Implementation of IConversionSvc: Convert the transient object to the requested representation.
PMonUtils::BasicStopWatchResultMap_t m_chronoMap
Map that holds chrono information.
std::string m_defContainerType
Default container type (from PoolSvc)
virtual StatusCode connectOutput(const std::string &outputConnectionSpec, const std::string &openMode) override
Implementation of IConversionSvc: Connect to the output connection specification with open mode.
AthenaPoolCnvSvc(const std::string &name, ISvcLocator *pSvcLocator)
Standard Service Constructor.
Gaudi::Property< bool > m_persSvcPerOutput
PersSvcPerOutput, boolean property to use multiple persistency services, one per output stream.
std::string m_lastInputFileName
decoded storage tech requested in "StorageTechnology" property
virtual StatusCode finalize() override
Required of all Gaudi Services.
virtual StatusCode commitOutput(const std::string &outputConnectionSpec, bool doCommit) override
Implementation of IConversionSvc: Commit pending output.
void flushDataHeaderForms(const std::string &streamName="*")
Tell DataHeaderCnv to write out all DataHeaderForms for a given streamName (default is all)
unsigned outputContextId(const std::string &outputConnection)
ServiceHandle< IPoolSvc > m_poolSvc
std::set< unsigned int > m_processedContextIds
Track context IDs for which extractPoolAttributes has been called.
virtual StatusCode cleanUp(const std::string &connection) override
Implement cleanUp to call all registered IAthenaPoolCleanUp cleanUp() function.
std::vector< std::vector< std::string > > m_inputAttr
virtual StatusCode convertAddress(const IOpaqueAddress *pAddress, std::string &refAddress) override
Convert address to string form.
Gaudi::Property< std::map< std::string, std::string > > m_storageTechProp
Default Storage Tech for containers (ROOTTREE, ROOTTREEINDEX, ROOTRNTUPLE)
virtual void setObjPtr(void *&obj, const Token *token) override
std::vector< std::vector< std::string > > m_domainAttr
Gaudi::Property< std::vector< std::string > > m_poolAttr
Output PoolAttributes, vector with names and values of technology specific attributes for POOL.
virtual StatusCode setInputAttributes(const std::string &fileName) override
Set the input file attributes, if any are requested from jobOpts.
Gaudi::Property< std::vector< std::string > > m_inputPoolAttrPerEvent
Print input PoolAttributes per event, vector with names of technology specific attributes for POOL to...
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 provides the interface for the AthenaPoolCleanUp which is used to clean up AthenaPoolConve...
This class provides the interface to the LCG POOL persistency software.
Definition IPoolSvc.h:36
@ kOutputStream
Definition IPoolSvc.h:40
@ kInputStream
Definition IPoolSvc.h:40
This class holds all the necessary information to guide the writing of an object in a physical place.
Definition Placement.h:19
Placement & setAuxString(const std::string &auxString)
Set auxiliary string.
Definition Placement.h:42
const std::string & fileName() const
Access file name.
Definition Placement.h:28
static TScopeAdapter ByNameNoQuiet(const std::string &name, Bool_t load=kTRUE)
Definition RootType.cxx:586
This class provides a Generic Transient Address for POOL tokens.
Token * getToken()
This class provides a token that identifies in a unique way objects on the persistent storage.
Definition Token.h:21
Token & setAuxString(const std::string &auxString)
Set auxiliary string.
Definition Token.h:93
const std::string & contID() const
Access container identifier.
Definition Token.h:69
const Guid & classID() const
Access database identifier.
Definition Token.h:73
virtual const std::string toString() const
Retrieve the string representation of the token.
Definition Token.cxx:134
const Guid & dbID() const
Access database identifier.
Definition Token.h:64
static Guid guid(const TypeH &id)
Determine Guid (normalized string form) from reflection type.
int type() const
Access to full type.
Definition DbType.h:65
static DbType getType(const std::string &name)
Access known storage type object by name.
std::string label(const std::string &format, int i)
Definition label.h:19
pool namespace
Definition libname.h:15
static const DbType TEST_StorageType
Definition DbType.h:97
static const DbType ROOTTREE_StorageType
Definition DbType.h:101
static const DbType ROOTRNTUPLE_StorageType
Definition DbType.h:103
static const DbType ROOTTREEINDEX_StorageType
Definition DbType.h:102
static const DbType ROOTKEY_StorageType
Definition DbType.h:100
std::size_t erase_if(T_container &container, T_Func pred)
TFile * file