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 // Global POOL container naming scheme
75 } else {
76 ATH_MSG_ERROR(std::format("Invalid PoolContainerNamingScheme: {}, see APRDefaults.h for the full list.", m_containerNamingSchemeProp.value()));
77 return StatusCode::FAILURE;
78 }
79 // Extracting INPUT POOL ItechnologySpecificAttributes for Domain, Database and Container.
81 // Extracting the INPUT POOL ItechnologySpecificAttributes which are to be printed for each event
83 // Setup incident for EndEvent to print out attributes each event
84 ServiceHandle<IIncidentSvc> incSvc("IncidentSvc", name());
85 long int pri = 1000;
86 if (!m_inputPoolAttrPerEvent.value().empty()) {
87 // Set to be listener for EndEvent
88 incSvc->addListener(this, "EndEvent", pri);
89 ATH_MSG_DEBUG("Subscribed to EndEvent for printing out input file attributes.");
90 }
91 if (!processPoolAttributes(m_inputAttr, "", IPoolSvc::kInputStream, false, true, true).isSuccess()) {
92 ATH_MSG_DEBUG("setInputAttribute failed setting POOL domain attributes.");
93 }
94
95 // Load these dictionaries now, so we don't need to try to do so
96 // while multiple threads are running.
97 TClass::GetClass ("TLeafI");
98 TClass::GetClass ("TLeafL");
99 TClass::GetClass ("TLeafD");
100 TClass::GetClass ("TLeafF");
101
102 return(StatusCode::SUCCESS);
103}
104//______________________________________________________________________________
106 ATH_MSG_DEBUG("I/O reinitialization...");
107 m_processedContextIds.clear();
108 return(StatusCode::SUCCESS);
109}
110//______________________________________________________________________________
111void AthenaPoolCnvSvc::flushDataHeaderForms(const std::string& streamName) {
112 // Write remaining DataHeaderForms for a given streamName, "*"" means all
113 auto DHCnvListener = dynamic_cast<IIncidentListener*>( converter( ClassID_traits<DataHeader>::ID() ) );
114 FileIncident incident(name(), "WriteDataHeaderForms", streamName);
115 if( DHCnvListener ) DHCnvListener->handle(incident);
116}
117//______________________________________________________________________________
119 ATH_MSG_VERBOSE("stop()");
120 // In case of direct writing without an OutputStream, this should be a good time to flush DHForms
122 return StatusCode::SUCCESS;
123}
124//______________________________________________________________________________
126 ATH_MSG_VERBOSE("Finalizing...");
127 // Some algorithms write in finalize(), flush DHForms if any are left
129 // Release ClassIDSvc
130 if (!m_clidSvc.release().isSuccess()) {
131 ATH_MSG_WARNING("Cannot release ClassIDSvc.");
132 }
133 // Release PoolSvc
134 if (!m_poolSvc.release().isSuccess()) {
135 ATH_MSG_WARNING("Cannot release PoolSvc.");
136 }
137 // Print Performance Statistics
138 // The pattern AthenaPoolCnvSvc.*PerfStats is ignored in AtlasTest/TestTools/share/post.sh
139 const std::string msgPrefix{"PerfStats "};
140 ATH_MSG_INFO(msgPrefix << std::string(40, '-'));
141 ATH_MSG_INFO(msgPrefix << "Timing Measurements for AthenaPoolCnvSvc");
142 ATH_MSG_INFO(msgPrefix << std::string(40, '-'));
143 for(const auto& [key, value] : m_chronoMap) {
144 ATH_MSG_INFO(msgPrefix << "| " << std::left << std::setw(15) << key << " | "
145 << std::right << std::setw(15) << std::fixed << std::setprecision(0) << value << " ms |");
146 }
147 ATH_MSG_INFO(msgPrefix << std::string(40, '-'));
148
149 m_cnvs.clear();
150 m_cnvs.shrink_to_fit();
151 return(StatusCode::SUCCESS);
152}
153//______________________________________________________________________________
155 ATH_MSG_DEBUG("I/O finalization...");
156 return(StatusCode::SUCCESS);
157}
158//______________________________________________________________________________
159StatusCode AthenaPoolCnvSvc::createObj(IOpaqueAddress* pAddress, DataObject*& refpObject) {
160 assert(pAddress);
161 std::string objName = "ALL";
162 if (m_useDetailChronoStat.value()) {
163 if (m_clidSvc->getTypeNameOfID(pAddress->clID(), objName).isFailure()) {
164 objName = std::to_string(pAddress->clID());
165 }
166 objName += '#';
167 objName += *(pAddress->par() + 1);
168 }
169 // StopWatch listens from here until the end of this current scope
170 PMonUtils::BasicStopWatch stopWatch("cObj_" + objName, m_chronoMap);
171 if (!m_persSvcPerInputType.empty()) { // Use separate PersistencySvc for each input data type
172 TokenAddress* tokAddr = dynamic_cast<TokenAddress*>(pAddress);
173 if (tokAddr != nullptr && tokAddr->getToken() != nullptr && (tokAddr->getToken()->contID().starts_with(m_persSvcPerInputType.value() + "(") || tokAddr->getToken()->contID().starts_with(m_persSvcPerInputType.value() + "_"))) {
174 const unsigned int maxContext = m_poolSvc->getInputContextMapSize();
175 const unsigned int auxContext = m_poolSvc->getInputContext(tokAddr->getToken()->classID().toString() + tokAddr->getToken()->dbID().toString(), 1);
176 char text[32];
177 const std::string contextStr = std::format("[CTXT={:08X}]", auxContext);
178 std::strncpy(text, contextStr.c_str(), sizeof(text) - 1);
179 text[sizeof(text) - 1] = '\0';
180 if (m_poolSvc->getInputContextMapSize() > maxContext) {
181 if (!m_poolSvc->setAttribute("TREE_CACHE", "0", pool::DbType(pool::ROOTTREE_StorageType).type(), "FID:" + tokAddr->getToken()->dbID().toString(), m_persSvcPerInputType.value(), auxContext).isSuccess()) {
182 ATH_MSG_DEBUG("setInputAttribute failed to switch off TTreeCache for id = " << auxContext << ".");
183 }
184 }
185 tokAddr->getToken()->setAuxString(text);
186 }
187 }
188 // Forward to base class createObj
189 StatusCode status = ::AthCnvSvc::createObj(pAddress, refpObject);
190 return(status);
191}
192//______________________________________________________________________________
193StatusCode AthenaPoolCnvSvc::createRep(DataObject* pObject, IOpaqueAddress*& refpAddress) {
194 assert(pObject);
195 std::string objName = "ALL";
196 if (m_useDetailChronoStat.value()) {
197 if (m_clidSvc->getTypeNameOfID(pObject->clID(), objName).isFailure()) {
198 objName = std::to_string(pObject->clID());
199 }
200 objName += '#';
201 objName += pObject->registry()->name();
202 }
203 // StopWatch listens from here until the end of this current scope
204 PMonUtils::BasicStopWatch stopWatch("cRep_" + objName, m_chronoMap);
205 StatusCode status = StatusCode::FAILURE;
206 if (pObject->clID() == 1) {
207 // No transient object was found use cnv to write default persistent object
208 SG::DataProxy* proxy = dynamic_cast<SG::DataProxy*>(pObject->registry());
209 if (proxy != nullptr) {
210 IConverter* cnv = converter(proxy->clID());
211 status = cnv->createRep(pObject, refpAddress);
212 }
213 } else {
214 // Forward to base class createRep
215 try {
216 status = ::AthCnvSvc::createRep(pObject, refpAddress);
217 } catch(std::runtime_error& e) {
218 ATH_MSG_FATAL(e.what());
219 }
220 }
221 return(status);
222}
223//______________________________________________________________________________
224StatusCode AthenaPoolCnvSvc::fillRepRefs(IOpaqueAddress* pAddress, DataObject* pObject) {
225 assert(pObject);
226 std::string objName = "ALL";
227 if (m_useDetailChronoStat.value()) {
228 if (m_clidSvc->getTypeNameOfID(pObject->clID(), objName).isFailure()) {
229 objName = std::to_string(pObject->clID());
230 }
231 objName += '#';
232 objName += pObject->registry()->name();
233 }
234 // StopWatch listens from here until the end of this current scope
235 PMonUtils::BasicStopWatch stopWatch("fRep_" + objName, m_chronoMap);
236 StatusCode status = StatusCode::FAILURE;
237 if (pObject->clID() == 1) {
238 // No transient object was found use cnv to write default persistent object
239 SG::DataProxy* proxy = dynamic_cast<SG::DataProxy*>(pObject->registry());
240 if (proxy != nullptr) {
241 IConverter* cnv = converter(proxy->clID());
242 status = cnv->fillRepRefs(pAddress, pObject);
243 }
244 } else {
245 // Forward to base class fillRepRefs
246 try {
247 status = ::AthCnvSvc::fillRepRefs(pAddress, pObject);
248 } catch(std::runtime_error& e) {
249 ATH_MSG_FATAL(e.what());
250 }
251 }
252 return(status);
253}
254//______________________________________________________________________________
255StatusCode AthenaPoolCnvSvc::connectOutput(const std::string& outputConnectionSpec,
256 const std::string& /*openMode*/) {
257 return(connectOutput(outputConnectionSpec));
258}
259//______________________________________________________________________________
260StatusCode AthenaPoolCnvSvc::connectOutput(const std::string& outputConnectionSpec) {
261// This is called before DataObjects are being converted.
262 std::string outputConnection = outputConnectionSpec.substr(0, outputConnectionSpec.find('['));
263 // Extract the technology
264 int tech{0};
265 if (!decodeOutputSpec(outputConnection, tech).isSuccess()) {
266 ATH_MSG_ERROR("connectOutput FAILED extract file name and technology.");
267 return(StatusCode::FAILURE);
268 }
269 unsigned int contextId = outputContextId(outputConnection);
270 try {
271 if (!m_poolSvc->connect(pool::ITransaction::UPDATE, contextId).isSuccess()) {
272 ATH_MSG_ERROR("connectOutput FAILED to open an UPDATE transaction.");
273 return(StatusCode::FAILURE);
274 }
275 } catch (std::exception& e) {
276 ATH_MSG_ERROR("connectOutput - caught exception: " << e.what());
277 return(StatusCode::FAILURE);
278 }
279 std::unique_lock<std::mutex> lock(m_mutex);
280 if (m_processedContextIds.insert(contextId).second) {
281 // Extracting OUTPUT POOL ItechnologySpecificAttributes for Domain, Database and Container.
283 }
284 if (!processPoolAttributes(m_domainAttr, outputConnection, contextId).isSuccess()) {
285 ATH_MSG_DEBUG("connectOutput failed process POOL domain attributes.");
286 }
287 if (!processPoolAttributes(m_databaseAttr, outputConnection, contextId).isSuccess()) {
288 ATH_MSG_DEBUG("connectOutput failed process POOL database attributes.");
289 }
290 return(StatusCode::SUCCESS);
291}
292
293//______________________________________________________________________________
294StatusCode AthenaPoolCnvSvc::commitOutput(const std::string& outputConnectionSpec, bool doCommit) {
295 // This is called after all DataObjects are converted.
296 std::string outputConnection = outputConnectionSpec.substr(0, outputConnectionSpec.find('['));
297 // StopWatch listens from here until the end of this current scope
298 PMonUtils::BasicStopWatch stopWatch("commitOutput", m_chronoMap);
299 std::unique_lock<std::mutex> lock(m_mutex);
300 // Extract the technology
301 int tech{0};
302 if (!decodeOutputSpec(outputConnection, tech).isSuccess()) {
303 ATH_MSG_ERROR("connectOutput FAILED extract file name and technology.");
304 return(StatusCode::FAILURE);
305 }
306 unsigned int contextId = outputContextId(outputConnection);
307 if (!processPoolAttributes(m_domainAttr, outputConnection, contextId).isSuccess()) {
308 ATH_MSG_DEBUG("commitOutput failed process POOL domain attributes.");
309 }
310 if (!processPoolAttributes(m_databaseAttr, outputConnection, contextId).isSuccess()) {
311 ATH_MSG_DEBUG("commitOutput failed process POOL database attributes.");
312 }
313 if (!processPoolAttributes(m_containerAttr, outputConnection, contextId).isSuccess()) {
314 ATH_MSG_DEBUG("commitOutput failed process POOL container attributes.");
315 }
316
317 // lock.unlock(); //MN: first need to make commitCache slot-specific
318 try {
319 if (doCommit) {
320 if (!m_poolSvc->commit(contextId).isSuccess()) {
321 ATH_MSG_ERROR("commitOutput FAILED to commit OutputStream.");
322 return(StatusCode::FAILURE);
323 }
324 } else {
325 if (!m_poolSvc->commitAndHold(contextId).isSuccess()) {
326 ATH_MSG_ERROR("commitOutput FAILED to commitAndHold OutputStream.");
327 return(StatusCode::FAILURE);
328 }
329 }
330 } catch (std::exception& e) {
331 ATH_MSG_ERROR("commitOutput - caught exception: " << e.what());
332 return(StatusCode::FAILURE);
333 }
334 if (!this->cleanUp(outputConnection).isSuccess()) {
335 ATH_MSG_ERROR("commitOutput FAILED to cleanup converters.");
336 return(StatusCode::FAILURE);
337 }
338 return(StatusCode::SUCCESS);
339}
340
341//______________________________________________________________________________
342StatusCode AthenaPoolCnvSvc::disconnectOutput(const std::string& outputConnectionSpec) {
343 std::string outputConnection = outputConnectionSpec.substr(0, outputConnectionSpec.find('['));
344 unsigned int contextId = outputContextId(outputConnection);
345 StatusCode sc = m_poolSvc->disconnect(contextId);
346 return sc;
347}
348
349//______________________________________________________________________________
350unsigned int AthenaPoolCnvSvc::outputContextId(const std::string& outputConnection) {
351 return m_persSvcPerOutput?
352 m_poolSvc->getOutputContext(outputConnection) : (unsigned int)IPoolSvc::kOutputStream;
353}
354
355//______________________________________________________________________________
359//______________________________________________________________________________
360Token* AthenaPoolCnvSvc::registerForWrite(Placement* placement, const void* obj, const RootType& classDesc) {
361 // StopWatch listens from here until the end of this current scope
362 PMonUtils::BasicStopWatch stopWatch("cRepR_ALL", m_chronoMap);
363 Token* token = nullptr;
364 if (m_persSvcPerOutput) { // Use separate PersistencySvc for each output stream/file
365 char text[32];
366 const std::string contextStr = std::format("[CTXT={:08X}]", m_poolSvc->getOutputContext(placement->fileName()));
367 std::strncpy(text, contextStr.c_str(), sizeof(text) - 1);
368 text[sizeof(text) - 1] = '\0';
369 placement->setAuxString(text);
370 }
371 token = m_poolSvc->registerForWrite(placement, obj, classDesc);
372 return(token);
373}
374//______________________________________________________________________________
375void AthenaPoolCnvSvc::setObjPtr(void*& obj, const Token* token) {
376 ATH_MSG_VERBOSE("Requesting object for: " << token->toString());
377 // StopWatch listens from here until the end of this current scope
378 PMonUtils::BasicStopWatch stopWatch("cObjR_ALL", m_chronoMap);
379 if (token->dbID() != Guid::null()) {
380 ATH_MSG_VERBOSE("Requesting object for: " << token->toString());
381 m_poolSvc->setObjPtr(obj, token);
382 }
383}
384//______________________________________________________________________________
386 return(m_useDetailChronoStat.value());
387}
388//______________________________________________________________________________
389StatusCode AthenaPoolCnvSvc::createAddress(long svcType,
390 const CLID& clid,
391 const std::string* par,
392 const unsigned long* ip,
393 IOpaqueAddress*& refpAddress) {
394 if( svcType != repSvcType() ) {
395 ATH_MSG_ERROR("createAddress: svcType != POOL_StorageType " << svcType << " " << repSvcType());
396 return(StatusCode::FAILURE);
397 }
398 std::unique_ptr<Token> token;
399 if (par[0].compare(0, 3, "SHM") == 0) {
400 token = std::make_unique<Token>();
401 token->setOid(Token::OID_t(ip[0], ip[1]));
402 token->setAuxString("[PNAME=" + par[2] + "]");
403 RootType classDesc = RootType::ByNameNoQuiet(par[2]);
404 token->setClassID(pool::DbReflex::guid(classDesc));
405 } else {
406 token.reset(m_poolSvc->getToken(par[0], par[1], ip[0]));
407 }
408 if (token == nullptr) {
409 return(StatusCode::RECOVERABLE);
410 }
411 refpAddress = new TokenAddress(repSvcType(), clid, "", par[1], IPoolSvc::kInputStream, std::move(token));
412 return(StatusCode::SUCCESS);
413}
414//______________________________________________________________________________
415StatusCode AthenaPoolCnvSvc::createAddress(long svcType,
416 const CLID& clid,
417 const std::string& refAddress,
418 IOpaqueAddress*& refpAddress) {
419 if (svcType != repSvcType()) {
420 ATH_MSG_ERROR("createAddress: svcType != POOL_StorageType " << svcType << " " << repSvcType());
421 return(StatusCode::FAILURE);
422 }
423 refpAddress = new GenericAddress(repSvcType(), clid, refAddress);
424 return(StatusCode::SUCCESS);
425}
426//______________________________________________________________________________
427StatusCode AthenaPoolCnvSvc::convertAddress(const IOpaqueAddress* pAddress,
428 std::string& refAddress) {
429 assert(pAddress);
430 const TokenAddress* tokAddr = dynamic_cast<const TokenAddress*>(pAddress);
431 if (tokAddr != nullptr && tokAddr->getToken() != nullptr) {
432 refAddress = tokAddr->getToken()->toString();
433 } else {
434 refAddress = *pAddress->par();
435 }
436 return(StatusCode::SUCCESS);
437}
438//__________________________________________________________________________
439StatusCode AthenaPoolCnvSvc::decodeOutputSpec(std::string& fileSpec, int& outputTech) const {
440 if (fileSpec.starts_with ( "ROOTKEY:")) {
441 outputTech = pool::ROOTKEY_StorageType.type();
442 fileSpec.erase(0, 8);
443 } else if (fileSpec.starts_with ( "ROOTTREE:")) {
444 outputTech = pool::ROOTTREE_StorageType.type();
445 fileSpec.erase(0, 9);
446 } else if (fileSpec.starts_with ( "ROOTTREEINDEX:")) {
447 outputTech = pool::ROOTTREEINDEX_StorageType.type();
448 fileSpec.erase(0, 14);
449 } else if (fileSpec.starts_with ( "ROOTRNTUPLE:")) {
450 outputTech = pool::ROOTRNTUPLE_StorageType.type();
451 fileSpec.erase(0, 12);
452 } else if (outputTech == 0) {
453 // Find the appropriate event data technology for this file
454 // This will be used for event data and its data header
455 // First we look for an exact file name match
456 // If that fails, we look for a wildcard ("*") match
457 // If that also fails, we use the default value from PoolSvc
458 if (auto it = m_storageTechMap.find(fileSpec); it != m_storageTechMap.end()) {
459 outputTech = it->second;
460 } else if (it = m_storageTechMap.find("*"); it != m_storageTechMap.end()) {
461 outputTech = it->second;
462 } else {
464 }
465 }
466 return StatusCode::SUCCESS;
467}
468//______________________________________________________________________________
470 m_cnvs.push_back(cnv);
471 return(StatusCode::SUCCESS);
472}
473//______________________________________________________________________________
474StatusCode AthenaPoolCnvSvc::cleanUp(const std::string& connection) {
475 bool retError = false;
476 std::size_t cpos = connection.find(':');
477 std::size_t bpos = connection.find('[');
478 if (cpos == std::string::npos) {
479 cpos = 0;
480 } else {
481 cpos++;
482 }
483 if (bpos != std::string::npos) bpos = bpos - cpos;
484 const std::string conn = connection.substr(cpos, bpos);
485 ATH_MSG_VERBOSE("Cleanup for Connection='"<< conn <<"'");
486 for (auto converter : m_cnvs) {
487 if (!converter->cleanUp(conn).isSuccess()) {
488 ATH_MSG_WARNING("AthenaPoolConverter cleanUp failed.");
489 retError = true;
490 }
491 }
492 return(retError ? StatusCode::FAILURE : StatusCode::SUCCESS);
493}
494//______________________________________________________________________________
495StatusCode AthenaPoolCnvSvc::setInputAttributes(const std::string& fileName) {
496 // Set attributes for input file
497 m_lastInputFileName = fileName; // Save file name for printing attributes per event
498 if (!processPoolAttributes(m_inputAttr, m_lastInputFileName, IPoolSvc::kInputStream, false, true, false).isSuccess()) {
499 ATH_MSG_DEBUG("setInputAttribute failed setting POOL database/container attributes.");
500 }
502 ATH_MSG_DEBUG("setInputAttribute failed getting POOL database/container attributes.");
503 }
504 if (!m_persSvcPerInputType.empty()) {
505 // Loop over all extra event input contexts and switch off TTreeCache
506 const auto& extraInputContextMap = m_poolSvc->getInputContextMap();
507 for (const auto& [label, id]: extraInputContextMap) {
508 if (!m_poolSvc->setAttribute("TREE_CACHE", "0", pool::DbType(pool::ROOTTREE_StorageType).type(), m_lastInputFileName, m_persSvcPerInputType.value(), id).isSuccess()) {
509 ATH_MSG_DEBUG("setInputAttribute failed to switch off TTreeCache for = " << label << ".");
510 }
511 }
512 }
513 return(StatusCode::SUCCESS);
514}
515
516//______________________________________________________________________________
517void AthenaPoolCnvSvc::handle(const Incident& incident) {
518 if (incident.type() == "EndEvent") {
520 ATH_MSG_DEBUG("handle EndEvent failed process POOL database attributes.");
521 }
522 }
523}
524//______________________________________________________________________________
525AthenaPoolCnvSvc::AthenaPoolCnvSvc(const std::string& name, ISvcLocator* pSvcLocator) :
526 base_class(name, pSvcLocator, pool::POOL_StorageType.type()) {
527}
528//__________________________________________________________________________
529void AthenaPoolCnvSvc::extractPoolAttributes(const StringArrayProperty& property,
530 std::vector<std::vector<std::string> >* contAttr,
531 std::vector<std::vector<std::string> >* dbAttr,
532 std::vector<std::vector<std::string> >* domAttr) const {
533 std::vector<std::string> opt;
534 std::string attributeName, containerName, databaseName, valueString;
535 for (const auto& propertyValue : property.value()) {
536 opt.clear();
537 attributeName.clear();
538 containerName.clear();
539 databaseName.clear();
540 valueString.clear();
541 using Gaudi::Utils::AttribStringParser;
542 for (const AttribStringParser::Attrib& attrib : AttribStringParser (propertyValue)) {
543 if (attrib.tag == "DatabaseName") {
544 databaseName = attrib.value;
545 } else if (attrib.tag == "ContainerName") {
546 if (databaseName.empty()) {
547 databaseName = "*";
548 }
549 containerName = attrib.value;
550 } else {
551 attributeName = attrib.tag;
552 valueString = attrib.value;
553 }
554 }
555 if (!attributeName.empty() && !valueString.empty()) {
556 opt.push_back(attributeName);
557 opt.push_back(valueString);
558 if (!databaseName.empty()) {
559 opt.push_back(databaseName);
560 if (!containerName.empty()) {
561 opt.push_back(containerName);
562 if (containerName.compare(0, 6, "TTree=") == 0) {
563 dbAttr->push_back(opt);
564 } else {
565 contAttr->push_back(opt);
566 }
567 } else {
568 opt.push_back("");
569 dbAttr->push_back(opt);
570 }
571 } else if (domAttr != 0) {
572 domAttr->push_back(opt);
573 } else {
574 opt.push_back("*");
575 opt.push_back("");
576 dbAttr->push_back(opt);
577 }
578 }
579 }
580}
581//__________________________________________________________________________
582StatusCode AthenaPoolCnvSvc::processPoolAttributes(std::vector<std::vector<std::string> >& attr,
583 const std::string& fileName,
584 unsigned long contextId,
585 bool doGet,
586 bool doSet,
587 bool doClear) const {
588 bool retError = false;
589 for (auto& attrEntry : attr) {
590 if (attrEntry.size() == 2) {
591 const std::string& opt = attrEntry[0];
592 std::string data = attrEntry[1];
593 if (data == "int" || data == "DbLonglong" || data == "double" || data == "string") {
594 if (doGet) {
595 if (!m_poolSvc->getAttribute(opt, data, pool::DbType(pool::ROOTTREE_StorageType).type(), contextId).isSuccess()) {
596 ATH_MSG_DEBUG("getAttribute failed for domain attr " << opt);
597 retError = true;
598 }
599 }
600 } else if (doSet) {
601 if (m_poolSvc->setAttribute(opt, data, pool::DbType(pool::ROOTTREE_StorageType).type(), contextId).isSuccess()) {
602 ATH_MSG_DEBUG("setAttribute " << opt << " to " << data);
603 if (doClear) {
604 attrEntry.clear();
605 }
606 } else {
607 ATH_MSG_DEBUG("setAttribute failed for domain attr " << opt << " to " << data);
608 retError = true;
609 }
610 }
611 }
612 if (attrEntry.size() == 4) {
613 const std::string& opt = attrEntry[0];
614 std::string data = attrEntry[1];
615 const std::string& file = attrEntry[2];
616 const std::string& cont = attrEntry[3];
617 if (!fileName.empty() && (0 == fileName.compare(0, fileName.find('?'), file)
618 || (file[0] == '*' && file.find("," + fileName + ",") == std::string::npos))) {
619 if (data == "int" || data == "DbLonglong" || data == "double" || data == "string") {
620 if (doGet) {
621 if (!m_poolSvc->getAttribute(opt, data, pool::DbType(pool::ROOTTREE_StorageType).type(), fileName, cont, contextId).isSuccess()) {
622 ATH_MSG_DEBUG("getAttribute failed for database/container attr " << opt);
623 retError = true;
624 }
625 }
626 } else if (doSet) {
627 if (m_poolSvc->setAttribute(opt, data, pool::DbType(pool::ROOTTREE_StorageType).type(), fileName, cont, contextId).isSuccess()) {
628 ATH_MSG_DEBUG("setAttribute " << opt << " to " << data << " for db: " << fileName << " and cont: " << cont);
629 if (doClear) {
630 if (file[0] == '*' && !m_persSvcPerOutput) {
631 attrEntry[2] += "," + fileName + ",";
632 } else {
633 attrEntry.clear();
634 }
635 }
636 } else {
637 ATH_MSG_DEBUG("setAttribute failed for " << opt << " to " << data << " for db: " << fileName << " and cont: " << cont);
638 retError = true;
639 }
640 }
641 }
642 }
643 }
644 std::erase_if(attr, [](const auto& entry) { return entry.empty(); });
645 return(retError ? StatusCode::FAILURE : StatusCode::SUCCESS);
646}
#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
Gaudi::Property< std::string > m_containerNamingSchemeProp
POOL container naming scheme selection.
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
void setNamingScheme(NamingScheme scheme)
Definition APRDefaults.h:72
std::optional< NamingScheme > parseNamingScheme(std::string_view name)
Definition APRDefaults.h:87
pool namespace
Definition libname.h:15
static const DbType TEST_StorageType
Definition DbType.h:83
static const DbType ROOTTREE_StorageType
Definition DbType.h:87
static const DbType ROOTRNTUPLE_StorageType
Definition DbType.h:89
static const DbType ROOTTREEINDEX_StorageType
Definition DbType.h:88
static const DbType ROOTKEY_StorageType
Definition DbType.h:86
std::size_t erase_if(T_container &container, T_Func pred)
TFile * file