ATLAS Offline Software
Loading...
Searching...
No Matches
PoolSvc.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 "PoolSvc.h"
11
12#include "GaudiKernel/IIoComponentMgr.h"
13#include "GaudiKernel/ConcurrencyFlags.h"
14
16
19
26
27#include "StorageSvc/DbType.h"
28#include "StorageSvc/DbPrint.h"
29
30#include <cstdlib>
31#include <cstring>
32#include <algorithm>
33#include <cstdio>
34#include <cctype>
35#include <exception> // for runtime_error
36
37bool isNumber(const std::string& s) {
38 return !s.empty() && (std::isdigit(s[0]) || s[0] == '+' || s[0] == '-');
39}
40
41//__________________________________________________________________________
42StatusCode PoolSvc::initialize() {
43 ATH_CHECK(::AthService::initialize());
44
45 // Register this service for 'I/O' events
46 ServiceHandle<IIoComponentMgr> iomgr("IoComponentMgr", name());
47 ATH_CHECK(iomgr.retrieve());
48 ATH_CHECK(iomgr->io_register(this));
49 // Register input file's names with the I/O manager, unless in SharedWrite mode, set by AthenaPoolCnvSvc
50 bool allGood = true;
51 for (const auto& catalog : m_readCatalog.value()) {
52 if (catalog.starts_with("xmlcatalog_file:")) {
53 const std::string fileName = catalog.substr(16);
54 if (!iomgr->io_register(this, IIoComponentMgr::IoMode::READ, fileName, fileName).isSuccess()) {
55 ATH_MSG_FATAL("could not register [" << catalog << "] for input !");
56 allGood = false;
57 } else {
58 ATH_MSG_INFO("io_register[" << this->name() << "](" << catalog << ") [ok]");
59 }
60 }
61 }
62 if (m_writeCatalog.value().starts_with("xmlcatalog_file:")) {
63 const std::string fileName = m_writeCatalog.value().substr(16);
64 if (!iomgr->io_register(this, IIoComponentMgr::IoMode::WRITE, fileName, fileName).isSuccess()) {
65 ATH_MSG_FATAL("could not register [" << m_writeCatalog.value() << "] for input !");
66 allGood = false;
67 } else {
68 ATH_MSG_INFO("io_register[" << this->name() << "](" << m_writeCatalog.value() << ") [ok]");
69 }
70 }
71 if (!allGood) {
72 return(StatusCode::FAILURE);
73 }
74
75 MSG::Level athLvl = msg().level();
76 ATH_MSG_DEBUG("OutputLevel is " << (int)athLvl);
78 return(setupPersistencySvc());
79}
80
81//__________________________________________________________________________
82StatusCode PoolSvc::io_reinit() {
83 ATH_MSG_INFO("I/O reinitialization...");
84 ServiceHandle<IIoComponentMgr> iomgr("IoComponentMgr", name());
85 if (!iomgr.retrieve().isSuccess()) {
86 ATH_MSG_FATAL("Could not retrieve IoComponentMgr !");
87 return(StatusCode::FAILURE);
88 }
89 if (!iomgr->io_hasitem(this)) {
90 ATH_MSG_FATAL("IoComponentMgr does not know about myself !");
91 return(StatusCode::FAILURE);
92 }
93 std::vector<std::string> readcat = m_readCatalog.value();
94 for (std::size_t icat = 0, imax = readcat.size(); icat < imax; icat++) {
95 if (readcat[icat].starts_with("xmlcatalog_file:")) {
96 std::string fileName = readcat[icat].substr(16);
97 if (iomgr->io_contains(this, fileName)) {
98 if (!iomgr->io_retrieve(this, fileName).isSuccess()) {
99 ATH_MSG_FATAL("Could not retrieve new value for [" << fileName << "] !");
100 return(StatusCode::FAILURE);
101 }
102 readcat[icat] = "xmlcatalog_file:" + fileName;
103 }
104 }
105 }
106 // all good... copy over.
107 m_readCatalog = readcat;
108 if (m_writeCatalog.value().starts_with("xmlcatalog_file:")) {
109 std::string fileName = m_writeCatalog.value().substr(16);
110 if (iomgr->io_contains(this, fileName)) {
111 if (!iomgr->io_retrieve(this, fileName).isSuccess()) {
112 ATH_MSG_FATAL("Could not retrieve new value for [" << fileName << "] !");
113 return(StatusCode::FAILURE);
114 }
115 if (!m_shareCat) {
116 m_writeCatalog.setValue("xmlcatalog_file:" + fileName);
117 }
118 }
119 }
120 return(setupPersistencySvc());
121}
122//__________________________________________________________________________
124 clearState();
125 ATH_MSG_INFO("Setting up FileCatalog and Streams");
127 if (m_catalog != nullptr) {
128 m_catalog->start();
129 } else {
130 ATH_MSG_FATAL("Failed to setup POOL File Catalog.");
131 return(StatusCode::FAILURE);
132 }
133 // Setup a persistency services
134 m_dbSessionVec.push_back(pool::createSession(*m_catalog).release()); // Read Service
135 m_pers_mut.push_back(new CallMutex);
136 if (!m_dbSessionVec[IPoolSvc::kInputStream]->technologySpecificAttributes(pool::ROOT_StorageType.type()).setAttribute<bool>("ENABLE_THREADSAFETY", true)) {
137 ATH_MSG_FATAL("Failed to enable thread safety in ROOT via PersistencySvc.");
138 return(StatusCode::FAILURE);
139 }
141 if (!connect(Io::READ, IPoolSvc::kInputStream).isSuccess()) {
142 ATH_MSG_FATAL("Failed to connect Input PersistencySvc.");
143 return(StatusCode::FAILURE);
144 }
145 m_dbSessionVec.push_back(pool::createSession(*m_catalog).release()); // Write Service
146 m_pers_mut.push_back(new CallMutex);
147
148 return(StatusCode::SUCCESS);
149}
150//__________________________________________________________________________
151StatusCode PoolSvc::start() {
152 // Switiching on ROOT implicit multi threading for AthenaMT
153 if (m_useROOTIMT && Gaudi::Concurrency::ConcurrencyFlags::numThreads() > 1) {
154 if (!m_dbSessionVec[IPoolSvc::kInputStream]->technologySpecificAttributes(pool::ROOT_StorageType.type()).setAttribute<int>("ENABLE_IMPLICITMT", Gaudi::Concurrency::ConcurrencyFlags::numThreads() - 1)) {
155 ATH_MSG_FATAL("Failed to enable implicit multithreading in ROOT via PersistencySvc.");
156 return(StatusCode::FAILURE);
157 }
158 ATH_MSG_INFO("Enabled implicit multithreading in ROOT via PersistencySvc to: " << Gaudi::Concurrency::ConcurrencyFlags::numThreads() - 1);
159 }
160 return(StatusCode::SUCCESS);
161}
162//__________________________________________________________________________
163StatusCode PoolSvc::stop() {
164 ATH_MSG_VERBOSE("stop()");
165 bool retError = false;
166 for (unsigned int contextId = 0, imax = m_dbSessionVec.size(); contextId < imax; contextId++) {
167 if (!disconnect(contextId).isSuccess()) {
168 ATH_MSG_FATAL("Cannot disconnect Stream: " << contextId);
169 retError = true;
170 }
171 }
172 return(retError ? StatusCode::FAILURE : StatusCode::SUCCESS);
173}
174
175//__________________________________________________________________________
177 std::lock_guard<CallMutex> lock(m_pool_mut);
178 // Cleanup persistency service
179 for (const auto& dbSession : m_dbSessionVec) {
180 delete dbSession;
181 }
182 m_dbSessionVec.clear();
183 for (const auto& persistencyMutex : m_pers_mut) {
184 delete persistencyMutex;
185 }
186 m_mainOutputLabel.clear();
187 m_inputContextLabel.clear();
188 m_outputContextLabel.clear();
189 m_pers_mut.clear();
190 if (m_catalog != nullptr) {
191 m_catalog->commit();
192 delete m_catalog; m_catalog = nullptr;
193 }
194}
195//__________________________________________________________________________
196StatusCode PoolSvc::finalize() {
197 clearState();
198 return(::AthService::finalize());
199}
200//__________________________________________________________________________
202 ATH_MSG_INFO("I/O finalization...");
203 for (size_t i = 0; i < m_dbSessionVec.size(); i++) {
204 if ((m_dbSessionVec[i]->transaction().type() == Io::WRITE || m_dbSessionVec[i]->transaction().type() == Io::APPEND) &&
205 !disconnect(i).isSuccess()) {
206 ATH_MSG_WARNING("Cannot disconnect output Stream " << i);
207 }
208 }
209 clearState();
210 return(StatusCode::SUCCESS);
211}
212//__________________________________________________________________________
214 const void* obj,
215 const RootType& classDesc) {
216 unsigned int contextId = IPoolSvc::kOutputStream;
217 const std::string& auxString = placement->auxString();
218 if (!auxString.empty()) {
219 if (auxString.starts_with("[CTXT=")) {
220 ::sscanf(auxString.c_str(), "[CTXT=%08X]", &contextId);
221 } else if (auxString.starts_with("[CLABEL=")) {
222 contextId = this->getOutputContext(auxString);
223 }
224 if (contextId >= m_dbSessionVec.size()) {
225 ATH_MSG_WARNING("registerForWrite: Using default output Stream instead of id = " << contextId);
226 contextId = IPoolSvc::kOutputStream;
227 }
228 }
229 std::lock_guard<CallMutex> lock(*m_pers_mut[contextId]);
230 Token* token = m_dbSessionVec[contextId]->registerForWrite(*placement, obj, classDesc);
231 if (token == nullptr) {
232 ATH_MSG_WARNING("Cannot write object: " << placement->containerName());
233 }
234 return(token);
235}
236//__________________________________________________________________________
237void PoolSvc::setObjPtr(void*& obj, const Token* token) {
238 unsigned int contextId = IPoolSvc::kInputStream;
239 const std::string& auxString = token->auxString();
240 if (!auxString.empty()) {
241 if (auxString.starts_with("[CTXT=")) {
242 ::sscanf(auxString.c_str(), "[CTXT=%08X]", &contextId);
243 } else if (auxString.starts_with("[CLABEL=")) {
244 contextId = this->getInputContext(auxString);
245 }
246 if (contextId >= m_dbSessionVec.size()) {
247 ATH_MSG_WARNING("setObjPtr: Using default input Stream instead of id = " << contextId);
248 contextId = IPoolSvc::kInputStream;
249 }
250 }
251 ATH_MSG_VERBOSE("setObjPtr: token=" << token->toString() << ", auxString=" << auxString << ", contextID=" << contextId);
252 // Get Context ID/label from Token
253 std::lock_guard<CallMutex> lock(*m_pers_mut[contextId]);
254 obj = m_dbSessionVec[contextId]->readObject(*token, obj);
255 std::map<unsigned int, unsigned int>::const_iterator maxFileIter = m_contextMaxFile.find(contextId);
256 if (maxFileIter != m_contextMaxFile.end() && maxFileIter->second > 0) {
257 m_guidLists[contextId].remove(token->dbID());
258 m_guidLists[contextId].push_back(token->dbID());
259 while (m_guidLists[contextId].size() > maxFileIter->second) {
260 this->disconnectDb("FID:" + m_guidLists[contextId].begin()->toString(), contextId).ignore();
261 }
262 }
263}
264//__________________________________________________________________________
265unsigned int PoolSvc::getOutputContext(const std::string& label) {
266 std::lock_guard<CallMutex> lock(m_pool_mut);
267 if (m_mainOutputLabel.empty()) {
270 }
271 if (label == m_mainOutputLabel || label.empty()) {
273 }
274 std::map<std::string, unsigned int>::const_iterator contextIter = m_outputContextLabel.find(label);
275 if (contextIter != m_outputContextLabel.end()) {
276 return(contextIter->second);
277 }
278 const unsigned int id = m_dbSessionVec.size();
279 m_dbSessionVec.push_back(pool::createSession(*m_catalog).release());
280 m_pers_mut.push_back(new CallMutex);
281 m_outputContextLabel.try_emplace(label, id);
282 return(id);
283}
284//__________________________________________________________________________
285unsigned int PoolSvc::getInputContext(const std::string& label, unsigned int maxFile) {
286 std::lock_guard<CallMutex> lock(m_pool_mut);
287 if (!label.empty()) {
288 std::map<std::string, unsigned int>::const_iterator contextIter = m_inputContextLabel.find(label);
289 if (contextIter != m_inputContextLabel.end()) {
290 if (maxFile > 0) {
291 m_contextMaxFile[contextIter->second] = maxFile;
292 }
293 return(contextIter->second);
294 }
295 }
296 const unsigned int id = m_dbSessionVec.size();
297 m_dbSessionVec.push_back( pool::createSession(*m_catalog, maxFile).release() );
298 m_pers_mut.push_back(new CallMutex);
299 if (!connect(Io::READ, id).isSuccess()) {
300 ATH_MSG_WARNING("Failed to connect Input PersistencySvc: " << id);
302 }
303 if (!label.empty()) {
304 m_inputContextLabel.try_emplace(label, id);
305 }
306 m_contextMaxFile.try_emplace(id, maxFile);
307 return(id);
308}
309//__________________________________________________________________________
310std::map<std::string, unsigned int> PoolSvc::getInputContextMap() const {
311 std::lock_guard<CallMutex> lock(m_pool_mut);
312 return(m_inputContextLabel);
313}
314//__________________________________________________________________________
316 std::lock_guard<CallMutex> lock(m_pool_mut);
317 return(m_inputContextLabel.size());
318}
319//__________________________________________________________________________
320pool::ISession* PoolSvc::getInputContextSession(unsigned int contextId) const {
321 if (contextId >= m_dbSessionVec.size()) {
322 ATH_MSG_WARNING("getInputContextSession: Using default input Stream instead of id = " << contextId);
323 contextId = IPoolSvc::kInputStream;
324 }
325 return(m_dbSessionVec[contextId]);
326}
327//__________________________________________________________________________
328void PoolSvc::setShareMode(bool shareCat) {
329 m_shareCat = shareCat;
330}
331//__________________________________________________________________________
333 if (m_catalog != nullptr) {
334 m_catalog->start();
335 }
336}
337//__________________________________________________________________________
339 if (m_catalog != nullptr) {
340 m_catalog->commit();
341 }
342}
343//__________________________________________________________________________
344void PoolSvc::lookupBestPfn(const std::string& token, std::string& pfn, std::string& type) const {
345 std::string dbID;
346 if (token.starts_with("PFN:")) {
347 m_catalog->lookupFileByPFN(token.substr(4), dbID, type); // PFN -> FID
348 } else if (token.starts_with("LFN:")) {
349 dbID = m_catalog->lookupLFN(token.substr(4)); // LFN -> FID
350 } else if (token.starts_with("FID:")) {
351 dbID = token.substr(4);
352 } else if (token.size() > Guid::stringSize()) { // full token
353 Token tok;
354 tok.fromString(token);
355 dbID = tok.dbID().toString();
356 } else { // guid only
357 dbID = token;
358 }
359 m_catalog->getFirstPFN(dbID, pfn, type); // FID -> best PFN
360}
361//__________________________________________________________________________
362void PoolSvc::renamePfn(const std::string& pf, const std::string& newpf) {
363 std::string dbID, type;
364 m_catalog->lookupFileByPFN(pf, dbID, type);
365 if (dbID.empty()) {
366 ATH_MSG_WARNING("Failed to lookup: " << pf << " in FileCatalog");
367 return;
368 }
369 m_catalog->lookupFileByPFN(newpf, dbID, type);
370 if (!dbID.empty()) {
371 ATH_MSG_INFO("Found: " << newpf << " in FileCatalog");
372 return;
373 }
374 m_catalog->renamePFN(pf, newpf);
375}
376//__________________________________________________________________________
377StatusCode PoolSvc::connectCollection(const std::string& connection,
378 const std::string& collectionName,
379 const pool::DbType& collectionType,
380 unsigned int contextId) const {
381 ATH_MSG_DEBUG("connectCollection() type=" << collectionType.storageName() << ", connection=" << connection
382 << ", name=" << collectionName << ", contextID=" << contextId);
383 if (contextId >= m_dbSessionVec.size()) {
384 ATH_MSG_WARNING("connectCollection: Using default input Stream instead of id = " << contextId);
385 contextId = IPoolSvc::kInputStream;
386 }
387
389 // Check POOL FileCatalog entry.
390 bool insertFile = false;
391 if (connection.starts_with("PFN:")) {
392 std::string fid, fileType;
393 m_catalog->lookupFileByPFN(connection.substr(4), fid, fileType);
394 if (fid.empty()) { // No entry in file catalog
395 insertFile = true;
396 ATH_MSG_INFO("File is not in Catalog! Attempt to open it anyway.");
397 }
398 }
399 if (collectionType.majorType() == pool::POOL_StorageType.type()) {
400 // Check whether Collection Container exists.
401 std::unique_ptr<pool::IDatabase> dbH = getDbHandle(contextId, connection);
402 if (dbH == nullptr) {
403 ATH_MSG_INFO("Failed to get Session/DatabaseHandle to create POOL collection.");
404 return(StatusCode::FAILURE);
405 }
406 try {
407 if (dbH->openMode() == Io::INVALID) {
408 dbH->connectForRead();
409 }
410 std::map<unsigned int, unsigned int>::const_iterator maxFileIter = m_contextMaxFile.find(contextId);
411 if (maxFileIter != m_contextMaxFile.end() && maxFileIter->second > 0 && !dbH->fid().empty()) {
412 const Guid guid(dbH->fid());
413 m_guidLists[contextId].remove(guid);
414 m_guidLists[contextId].push_back(guid);
415 while (m_guidLists[contextId].size() > maxFileIter->second + 1) {
416 this->disconnectDb("FID:" + m_guidLists[contextId].begin()->toString(), contextId).ignore();
417 }
418 }
419 } catch (std::exception& e) {
420 ATH_MSG_INFO("Failed to open container to check POOL collection - trying.");
421 }
422 }
423 // For multithreaded processing (with multiple events in flight),
424 // increase virtual tree size to accomodate back reads
425 if (m_useROOTMaxTree && contextId == IPoolSvc::kInputStream && Gaudi::Concurrency::ConcurrencyFlags::numConcurrentEvents() > 1) {
426 if (!this->setAttribute("TREE_MAX_VIRTUAL_SIZE", "-1", pool::ROOT_StorageType.type(), connection.substr(4), "CollectionTree", contextId).isSuccess()) {
427 ATH_MSG_DEBUG("Failed to increase maximum virtual TTree size.");
428 }
429 }
430 if (insertFile) return(StatusCode::RECOVERABLE);
431
432 return(StatusCode::SUCCESS);
433}
434//__________________________________________________________________________
435StatusCode PoolSvc::checkCollection(const std::string& connection,
436 unsigned int contextId,
437 bool noContainer) const {
439 std::unique_ptr<pool::IDatabase> dbH = getDbHandle(contextId, connection);
440 if (dbH != nullptr && !dbH->fid().empty()) {
441 if (noContainer) {
442 return(StatusCode::SUCCESS); // no events
443 }
444 if (m_attemptCatalogPatch.value()) {
445 patchCatalog(connection.substr(4), *dbH);
446 }
447 return(StatusCode::SUCCESS);
448 }
449 return(StatusCode::FAILURE);
450}
451//__________________________________________________________________________
452void PoolSvc::patchCatalog(const std::string& pfn, pool::IDatabase& dbH) const {
453 std::scoped_lock lock(m_pool_mut);
455 std::string fid = dbH.fid();
457 catalog_locked->registerPFN(pfn, "ROOT_All", fid);
458}
459//__________________________________________________________________________
460Token* PoolSvc::getToken(const std::string& connection,
461 const std::string& collection,
462 const unsigned long ientry) const {
463 std::lock_guard<CallMutex> lock(*m_pers_mut[IPoolSvc::kInputStream]);
464 std::unique_ptr<pool::IDatabase> dbH = getDbHandle(IPoolSvc::kInputStream, connection);
465 if (dbH == nullptr) {
466 return(nullptr);
467 }
468 if (dbH->openMode() == Io::INVALID) {
469 dbH->connectForRead();
470 }
471 std::unique_ptr<pool::IContainer> contH = getContainerHandle(dbH.get(), collection);
472 if (contH == nullptr) {
473 return(nullptr);
474 }
475 auto tokenIter = std::unique_ptr<pool::ITokenIterator>(contH->tokens());
476 // the Token returned by the iterator has the refCount already increased
477 return tokenIter->seek(ientry)? tokenIter->next() : nullptr;
478}
479//__________________________________________________________________________
480StatusCode PoolSvc::connect(Io::IoFlag type, unsigned int contextId) {
481 if (type != Io::READ) {
482 if (contextId >= m_dbSessionVec.size()) {
483 ATH_MSG_WARNING("connect: Using default output Stream instead of id = " << contextId);
484 contextId = IPoolSvc::kOutputStream;
485 }
486 } else {
487 if (contextId > m_dbSessionVec.size()) {
488 ATH_MSG_WARNING("connect: Using default input Stream instead of id = " << contextId);
489 contextId = IPoolSvc::kInputStream;
490 } else if (contextId == m_dbSessionVec.size()) {
491 ATH_MSG_INFO("Connecting to InputStream for: " << contextId);
492 contextId = this->getInputContext("");
493 }
494 }
495 if (contextId >= m_dbSessionVec.size()) {
496 return(StatusCode::FAILURE);
497 }
499 auto session = m_dbSessionVec[contextId];
500 // Connect to a logical database using the pre-defined technology and dbID
501 if (session->transaction().isActive()) {
502 return(StatusCode::SUCCESS);
503 }
504 if (!session->start(type)) {
505 ATH_MSG_ERROR("connect failed session = " << session << " type = " << type);
506 return(StatusCode::FAILURE);
507 }
508
509 return(StatusCode::SUCCESS);
510}
511//__________________________________________________________________________
512StatusCode PoolSvc::commit(unsigned int contextId) const {
513 if (contextId >= m_dbSessionVec.size()) {
514 return(StatusCode::FAILURE);
515 }
517 auto session = m_dbSessionVec[contextId];
518 if (session != nullptr && session->transaction().isActive()) {
519 if (!session->commit()) {
520 ATH_MSG_ERROR("POOL commit failed " << session);
521 return(StatusCode::FAILURE);
522 }
523 if (session->transaction().type() == Io::READ) {
524 session->disconnectAll();
525 }
526 }
527 return(StatusCode::SUCCESS);
528}
529//__________________________________________________________________________
530StatusCode PoolSvc::commitAndHold(unsigned int contextId) const {
531 if (contextId >= m_dbSessionVec.size()) {
532 return(StatusCode::FAILURE);
533 }
535 pool::ISession* session = m_dbSessionVec[contextId];
536 if (session != nullptr && session->transaction().isActive()) {
537 if (!session->commitAndHold()) {
538 ATH_MSG_ERROR("POOL commitAndHold failed " << session);
539 return(StatusCode::FAILURE);
540 }
541 }
542 return(StatusCode::SUCCESS);
543}
544//__________________________________________________________________________
545StatusCode PoolSvc::disconnect(unsigned int contextId) const {
546 ATH_MSG_DEBUG("Disconnect request for contextId=" << contextId);
547 if (contextId >= m_dbSessionVec.size()) {
548 return(StatusCode::SUCCESS);
549 }
551 pool::ISession* session = m_dbSessionVec[contextId];
552 if (session != nullptr && session->transaction().isActive()) {
553 if (!commit(contextId).isSuccess()) {
554 ATH_MSG_ERROR("disconnect failed to commit " << session);
555 return(StatusCode::FAILURE);
556 }
557 if (session->disconnectAll()) {
558 ATH_MSG_DEBUG("Disconnected PersistencySvc session");
559 } else {
560 ATH_MSG_ERROR("disconnect failed to diconnect PersistencySvc");
561 return(StatusCode::FAILURE);
562 }
563 }
564 return(StatusCode::SUCCESS);
565}
566//__________________________________________________________________________
567StatusCode PoolSvc::disconnectDb(const std::string& connection, unsigned int contextId) const {
568 if (contextId >= m_dbSessionVec.size()) {
569 return(StatusCode::SUCCESS);
570 }
572 std::unique_ptr<pool::IDatabase> dbH = getDbHandle(contextId, connection);
573 if (dbH == nullptr) {
574 ATH_MSG_ERROR("Failed to get Session/DatabaseHandle.");
575 return(StatusCode::FAILURE);
576 }
577 std::map<unsigned int, unsigned int>::const_iterator maxFileIter = m_contextMaxFile.find(contextId);
578 if (maxFileIter != m_contextMaxFile.end() && maxFileIter->second > 0) {
579 m_guidLists[contextId].remove(Guid(dbH->fid()));
580 }
581 dbH->disconnect();
582 return(StatusCode::SUCCESS);
583}
584//_______________________________________________________________________
585StatusCode PoolSvc::getAttribute(const std::string& optName,
586 std::string& data,
587 long tech,
588 unsigned int contextId) const {
589 if (contextId >= m_dbSessionVec.size()) {
590 ATH_MSG_WARNING("getAttribute: Using default input Stream instead of id = " << contextId);
591 contextId = IPoolSvc::kInputStream;
592 }
594 pool::ISession* sesH = m_dbSessionVec[contextId];
595 std::ostringstream oss;
596 if (data == "DbLonglong") {
597 oss << std::dec << sesH->technologySpecificAttributes(tech).attribute<long long int>(optName);
598 } else if (data == "double") {
599 oss << std::dec << sesH->technologySpecificAttributes(tech).attribute<double>(optName);
600 } else {
601 oss << std::dec << sesH->technologySpecificAttributes(tech).attribute<int>(optName);
602 }
603 data = oss.str();
604 ATH_MSG_INFO("Domain attribute [" << optName << "]" << ": " << data);
605 return(StatusCode::SUCCESS);
606}
607//_______________________________________________________________________
608StatusCode PoolSvc::getAttribute(const std::string& optName,
609 std::string& data,
610 long tech,
611 const std::string& dbName,
612 const std::string& contName,
613 unsigned int contextId) const {
615 std::unique_ptr<pool::IDatabase> dbH = getDbHandle(contextId, dbName);
616 if (dbH == nullptr) {
617 ATH_MSG_DEBUG("getAttribute: Failed to get Session/DatabaseHandle to get POOL property.");
618 return(StatusCode::FAILURE);
619 }
620 if (dbH->openMode() == Io::INVALID) {
621 if (m_dbSessionVec[contextId]->transaction().type() == Io::WRITE || m_dbSessionVec[contextId]->transaction().type() == Io::APPEND) {
622 dbH->setTechnology(tech);
623 dbH->connectForWrite();
624 } else {
625 dbH->connectForRead();
626 }
627 }
628 std::ostringstream oss;
629 if (contName.empty()) {
630 if (data == "DbLonglong") {
631 oss << std::dec << dbH->technologySpecificAttributes().attribute<long long int>(optName);
632 } else if (data == "double") {
633 oss << std::dec << dbH->technologySpecificAttributes().attribute<double>(optName);
634 } else if (data == "string") {
635 oss << dbH->technologySpecificAttributes().attribute<char*>(optName);
636 } else {
637 oss << std::dec << dbH->technologySpecificAttributes().attribute<int>(optName);
638 }
639 ATH_MSG_INFO("Database (" << dbH->pfn() << ") attribute [" << optName << "]" << ": " << oss.str());
640 } else {
641 std::unique_ptr<pool::IContainer> contH = getContainerHandle(dbH.get(), contName);
642 if (contH == nullptr) {
643 ATH_MSG_DEBUG("Failed to get ContainerHandle to get POOL property.");
644 return(StatusCode::FAILURE);
645 }
646 if (data == "DbLonglong") {
647 oss << std::dec << contH->technologySpecificAttributes().attribute<long long int>(optName);
648 } else if (data == "double") {
649 oss << std::dec << contH->technologySpecificAttributes().attribute<double>(optName);
650 } else {
651 oss << std::dec << contH->technologySpecificAttributes().attribute<int>(optName);
652 }
653 ATH_MSG_INFO("Container attribute [" << contName << "." << optName << "]: " << oss.str());
654 }
655 data = oss.str();
656 return(StatusCode::SUCCESS);
657}
658//_______________________________________________________________________
659StatusCode PoolSvc::setAttribute(const std::string& optName,
660 const std::string& data,
661 long tech,
662 unsigned int contextId) const {
663 if (contextId >= m_dbSessionVec.size()) {
664 ATH_MSG_WARNING("setAttribute: Using default output Stream instead of id = " << contextId);
665 contextId = IPoolSvc::kOutputStream;
666 }
668 pool::ISession* sesH = m_dbSessionVec[contextId];
669 if (data[data.size() - 1] == 'L') {
670 if (!sesH->technologySpecificAttributes(tech).setAttribute<long long int>(optName, atoll(data.c_str()))) {
671 ATH_MSG_DEBUG("Failed to set POOL property, " << optName << " to " << data);
672 return(StatusCode::FAILURE);
673 }
674 } else {
675 if (!sesH->technologySpecificAttributes(tech).setAttribute<int>(optName, atoi(data.c_str()))) {
676 ATH_MSG_DEBUG("Failed to set POOL property, " << optName << " to " << data);
677 return(StatusCode::FAILURE);
678 }
679 }
680 return(StatusCode::SUCCESS);
681}
682//_______________________________________________________________________
683StatusCode PoolSvc::setAttribute(const std::string& optName,
684 const std::string& data,
685 long tech,
686 const std::string& dbName,
687 const std::string& contName,
688 unsigned int contextId) const {
689 if (contextId >= m_dbSessionVec.size()) {
690 ATH_MSG_WARNING("setAttribute: Using default output Stream instead of id = " << contextId);
691 contextId = IPoolSvc::kOutputStream;
692 }
694 std::unique_ptr<pool::IDatabase> dbH = getDbHandle(contextId, dbName);
695 if (dbH == nullptr) {
696 ATH_MSG_DEBUG("Failed to get Session/DatabaseHandle to set POOL property.");
697 return(StatusCode::FAILURE);
698 }
699 if (dbH->openMode() == Io::INVALID) {
700 if (m_dbSessionVec[contextId]->transaction().type() == Io::WRITE || m_dbSessionVec[contextId]->transaction().type() == Io::APPEND) {
701 dbH->setTechnology(tech);
702 dbH->connectForWrite();
703 } else {
704 dbH->connectForRead();
705 }
706 }
707 bool retError = false;
708 std::string objName;
709 bool hasTTreeName = contName.starts_with("TTree=");
710 if (contName.empty() || hasTTreeName || m_dbSessionVec[contextId]->transaction().type() == Io::READ) {
711 objName = hasTTreeName ? contName.substr(6) : contName;
712 if( !isNumber(data) ) {
713 retError = dbH->technologySpecificAttributes().setAttribute(optName, data.c_str(), objName);
714 } else if( data[data.size() - 1] == 'L' ) {
715 retError = dbH->technologySpecificAttributes().setAttribute<long long int>(optName, atoll(data.c_str()), objName);
716 } else {
717 retError = dbH->technologySpecificAttributes().setAttribute<int>(optName, atoi(data.c_str()), objName);
718 }
719 if (!retError) {
720 ATH_MSG_DEBUG("Failed to set POOL property, " << optName << " to " << data);
721 return(StatusCode::FAILURE);
722 }
723 } else {
724 std::unique_ptr<pool::IContainer> contH = getContainerHandle(dbH.get(), contName);
725 if (contH == nullptr) {
726 ATH_MSG_DEBUG("Failed to get ContainerHandle to set POOL property.");
727 return(StatusCode::FAILURE);
728 }
729 if (auto p = contName.find('('); p != std::string::npos) {
730 objName = contName.substr(p + 1); // Get BranchName between parenthesis
731 objName.erase(objName.find(')'));
732 } else if (auto p = contName.find("::"); p != std::string::npos) {
733 objName = contName.substr(p + 2); // Split off Tree name
734 } else if (auto p = contName.find('_'); p != std::string::npos) {
735 objName = contName.substr(p + 1); // Split off "POOLContainer"
736 objName.erase(objName.find('/')); // Split off key
737 }
738 std::string::size_type off = 0;
739 while ((off = objName.find_first_of("<>/")) != std::string::npos) {
740 objName[off] = '_'; // Replace special chars (e.g. templates)
741 }
742 if (data[data.size() - 1] == 'L') {
743 retError = contH->technologySpecificAttributes().setAttribute<long long int>(optName, atoll(data.c_str()), objName);
744 } else {
745 retError = contH->technologySpecificAttributes().setAttribute<int>(optName, atoi(data.c_str()), objName);
746 }
747 if (!retError) {
748 ATH_MSG_DEBUG("Failed to set POOL container property, " << optName << " for " << contName << " : " << objName << " to " << data);
749 return(StatusCode::FAILURE);
750 }
751 }
752 return(StatusCode::SUCCESS);
753}
754
755//__________________________________________________________________________
758 ctlg->removeCatalog("*");
759 for (auto& catalog : m_readCatalog.value()) {
760 ATH_MSG_DEBUG("POOL ReadCatalog is " << catalog);
761 if (catalog.starts_with("apcfile:") || catalog.starts_with("prfile:")) {
762 std::string::size_type cpos = catalog.find(':');
763 // check for file accessed via ATLAS_POOLCOND_PATH
764 std::string file = poolCondPath(catalog.substr(cpos + 1));
765 if (!file.empty()) {
766 ATH_MSG_INFO("Resolved path (via ATLAS_POOLCOND_PATH) is " << file);
767 ctlg->addReadCatalog("file:" + file);
768 } else {
769 // As backup, check for file accessed via PathResolver
770 file = PathResolver::find_file(catalog.substr(cpos + 1), "DATAPATH");
771 if (!file.empty()) {
772 ATH_MSG_INFO("Resolved path (via DATAPATH) is " << file);
773 ctlg->addReadCatalog("file:" + file);
774 } else {
775 ATH_MSG_INFO("Unable find catalog "
776 << catalog
777 << " in $ATLAS_POOLCOND_PATH and $DATAPATH");
778 }
779 }
780 } else {
781 ctlg->addReadCatalog(catalog);
782 }
783 }
784 try {
785 ATH_MSG_INFO("POOL WriteCatalog is " << m_writeCatalog.value());
786 ctlg->setWriteCatalog(m_writeCatalog.value());
787 } catch(std::exception& e) {
788 ATH_MSG_ERROR("setWriteCatalog - caught exception: " << e.what());
789 return(nullptr); // This catalog is not setup properly!
790 }
791 return(ctlg);
792}
793
794//__________________________________________________________________________
797//__________________________________________________________________________
798std::unique_ptr<pool::IDatabase> PoolSvc::getDbHandle(unsigned int contextId, const std::string& dbName) const {
799 if (contextId >= m_dbSessionVec.size()) {
800 ATH_MSG_WARNING("getDbHandle: Using default input Stream instead of id = " << contextId);
801 contextId = IPoolSvc::kInputStream;
802 }
803 pool::ISession* sesH = m_dbSessionVec[contextId];
804 if (!sesH->transaction().isActive()) {
805 Io::IoFlag transMode = Io::READ;
806 ATH_MSG_DEBUG("Start transaction, type = " << transMode);
807 if (!sesH->transaction().start(transMode)) {
808 ATH_MSG_WARNING("Failed to start transaction, type = " << transMode);
809 return(nullptr);
810 }
811 }
812 if (dbName.starts_with("PFN:")) {
813 return sesH->databaseHandle(dbName.substr(4), pool::DatabaseSpecification::PFN);
814 } else if (dbName.starts_with("LFN:")) {
815 return sesH->databaseHandle(dbName.substr(4), pool::DatabaseSpecification::LFN);
816 } else if (dbName.starts_with("FID:")) {
817 return sesH->databaseHandle(dbName.substr(4), pool::DatabaseSpecification::FID);
818 }
820}
821//__________________________________________________________________________
822std::unique_ptr<pool::IContainer> PoolSvc::getContainerHandle(pool::IDatabase* dbH, const std::string& contName) const {
823 pool::IContainer* contH = nullptr;
824 if (dbH == nullptr) {
825 ATH_MSG_DEBUG("No DatabaseHandle to get Container.");
826 return(nullptr);
827 }
828 if (contName.find("DataHeader") != std::string::npos) {
829 contH = dbH->containerHandle(contName.substr(0, contName.find("_p")));
830 } else {
831 contH = dbH->containerHandle(contName);
832 }
833 return(std::unique_ptr<pool::IContainer>(contH));
834}
835//__________________________________________________________________________
836std::string PoolSvc::poolCondPath(const std::string& leaf) {
837 // look for files at $ATLAS_POOLCOND_PATH/<leaf>
838 // return full filename if exists, or empty string if not
839 const char* cpath = std::getenv("ATLAS_POOLCOND_PATH");
840 if (cpath && strcmp(cpath, "") != 0) {
841 const std::string testpath = std::string(cpath) + "/" + leaf;
842
843 // Try to open file for reading. Note that a simple stat call may return
844 // a wrong result if the file is residing on an auto-mounted FS (ATR-28801).
845 if (FILE* fp = std::fopen(testpath.c_str(), "r")) {
846 std::fclose(fp);
847 return testpath;
848 }
849 }
850 return {};
851}
#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_INFO(x,...)
#define ATH_MSG_FATAL(x,...)
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).
bool isNumber(const std::string &s)
Definition PoolSvc.cxx:37
This file contains the class definition for the PoolSvc class.
TTypeAdapter RootType
Definition RootType.h:211
size_t size() const
Number of registered mappings.
int imax(int i, int j)
This file contains the class definition for the Token class (migrated from POOL).
This class provides a encapsulation of a GUID/UUID/CLSID/IID data structure (128 bit number).
Definition Guid.h:25
constexpr void toString(std::span< char, StrLen > buf, bool uppercase=true) const noexcept
Automatic conversion to string representation.
static constexpr int stringSize()
Definition Guid.h:61
@ kOutputStream
Definition IPoolSvc.h:39
@ kInputStream
Definition IPoolSvc.h:39
static std::string find_file(const std::string &logical_file_name, const std::string &search_path)
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
virtual StatusCode io_reinit() override
Definition PoolSvc.cxx:82
pool::IFileCatalog * createCatalog()
Definition PoolSvc.cxx:756
virtual Token * registerForWrite(const Placement *placement, const void *obj, const RootType &classDesc) override
Definition PoolSvc.cxx:213
virtual ~PoolSvc()
Destructor.
Definition PoolSvc.cxx:795
virtual void startCatalog() override
Definition PoolSvc.cxx:332
virtual void renamePfn(const std::string &pf, const std::string &newpf) override
Definition PoolSvc.cxx:362
pool::IFileCatalog * m_catalog
Definition PoolSvc.h:227
virtual StatusCode connect(Io::IoFlag type, unsigned int contextId=IPoolSvc::kInputStream) override
Connect to a logical database unit; PersistencySvc is chosen according to transaction type (accessmod...
Definition PoolSvc.cxx:480
std::string poolCondPath(const std::string &leaf)
Resolve a file using ATLAS_POOLCOND_PATH.
Definition PoolSvc.cxx:836
virtual unsigned int getInputContextMapSize() const override
Definition PoolSvc.cxx:315
void patchCatalog(const std::string &pfn, pool::IDatabase &dbH) const
Definition PoolSvc.cxx:452
CallMutex m_pool_mut
Definition PoolSvc.h:224
virtual unsigned int getInputContext(const std::string &label, unsigned int maxFile=0) override
Definition PoolSvc.cxx:285
virtual void lookupBestPfn(const std::string &token, std::string &pfn, std::string &type) const override
Definition PoolSvc.cxx:344
virtual StatusCode setAttribute(const std::string &optName, const std::string &data, long tech, unsigned int contextId=IPoolSvc::kOutputStream) const override
Set POOL attributes - domain.
Definition PoolSvc.cxx:659
std::vector< pool::ISession * > m_dbSessionVec
Definition PoolSvc.h:228
Gaudi::Property< bool > m_useROOTIMT
Use ROOT Implicit MultiThreading, default = true.
Definition PoolSvc.h:247
virtual StatusCode commit(unsigned int contextId=IPoolSvc::kInputStream) const override
Commit data for a given contextId and flush buffer.
Definition PoolSvc.cxx:512
std::unique_ptr< pool::IContainer > getContainerHandle(pool::IDatabase *dbH, const std::string &contName) const
Get Container handle.
Definition PoolSvc.cxx:822
virtual Token * getToken(const std::string &connection, const std::string &collection, const unsigned long ientry) const override
Definition PoolSvc.cxx:460
virtual StatusCode start() override
Required of all Gaudi services:
Definition PoolSvc.cxx:151
StatusCode setupPersistencySvc()
Definition PoolSvc.cxx:123
virtual pool::ISession * getInputContextSession(unsigned int contextId) const override
Definition PoolSvc.cxx:320
virtual StatusCode io_finalize() override
Definition PoolSvc.cxx:201
virtual StatusCode checkCollection(const std::string &connection, unsigned int contextId, bool noContainer) const override
Definition PoolSvc.cxx:435
Gaudi::Property< int > m_dbAgeLimit
MaxFilesOpen, option to have PoolSvc limit the number of open Input Files: default = 0 (No files are ...
Definition PoolSvc.h:240
Gaudi::Property< bool > m_useROOTMaxTree
Increase virtual TTree size to avoid backreads in multithreading, default = false.
Definition PoolSvc.h:249
std::map< std::string, unsigned int > m_outputContextLabel
Definition PoolSvc.h:231
virtual StatusCode disconnectDb(const std::string &connection, unsigned int contextId=IPoolSvc::kInputStream) const override
Disconnect single Database.
Definition PoolSvc.cxx:567
std::recursive_mutex CallMutex
Definition PoolSvc.h:210
virtual void commitCatalog() override
Definition PoolSvc.cxx:338
std::vector< CallMutex * > m_pers_mut
Definition PoolSvc.h:229
std::map< std::string, unsigned int > m_inputContextLabel
Definition PoolSvc.h:230
virtual void setObjPtr(void *&obj, const Token *token) override
Definition PoolSvc.cxx:237
virtual StatusCode connectCollection(const std::string &connection, const std::string &collectionName, const pool::DbType &collectionType, unsigned int contextId=IPoolSvc::kInputStream) const override
Definition PoolSvc.cxx:377
Gaudi::Property< std::vector< std::string > > m_readCatalog
ReadCatalog, the list of additional POOL input file catalogs to consult: default = empty vector.
Definition PoolSvc.h:245
std::string m_mainOutputLabel
Definition PoolSvc.h:232
void clearState()
Definition PoolSvc.cxx:176
std::map< unsigned int, unsigned int > m_contextMaxFile
Definition PoolSvc.h:233
virtual void setShareMode(bool shareCat) override
Definition PoolSvc.cxx:328
std::unique_ptr< pool::IDatabase > getDbHandle(unsigned int contextId, const std::string &dbName) const
Get Database handle.
Definition PoolSvc.cxx:798
virtual StatusCode commitAndHold(unsigned int contextId=IPoolSvc::kInputStream) const override
Commit data for a given contextId and hold buffer.
Definition PoolSvc.cxx:530
virtual StatusCode disconnect(unsigned int contextId=IPoolSvc::kInputStream) const override
Disconnect PersistencySvc associated with a contextId.
Definition PoolSvc.cxx:545
virtual StatusCode finalize() override
Required of all Gaudi services:
Definition PoolSvc.cxx:196
virtual StatusCode initialize() override
Required of all Gaudi services:
Definition PoolSvc.cxx:42
virtual std::map< std::string, unsigned int > getInputContextMap() const override
Definition PoolSvc.cxx:310
virtual unsigned int getOutputContext(const std::string &label) override
Definition PoolSvc.cxx:265
Gaudi::Property< std::string > m_writeCatalog
WriteCatalog, the file catalog to be used to register output files (also default input catalog): defa...
Definition PoolSvc.h:243
virtual StatusCode stop() override
Definition PoolSvc.cxx:163
Gaudi::Property< bool > m_attemptCatalogPatch
AttemptCatalogPatch, option to create catalog: default = false.
Definition PoolSvc.h:252
std::map< unsigned int, std::list< Guid > > m_guidLists ATLAS_THREAD_SAFE
Definition PoolSvc.h:235
virtual StatusCode getAttribute(const std::string &optName, std::string &data, long tech, unsigned int contextId=IPoolSvc::kInputStream) const override
Get POOL attributes - domain.
Definition PoolSvc.cxx:585
bool m_shareCat
Definition PoolSvc.h:226
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
const std::string toString() const
Retrieve the string representation of the token.
Definition Token.cxx:135
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
const std::string storageName() const
Human readable storage type.
int majorType() const
Access to major type.
Definition DbType.h:67
IContainer is the base class for container objects.
Definition IContainer.h:23
IDatabase is the base class for database objects.
Definition IDatabase.h:37
virtual bool setTechnology(long technology)=0
Sets the technology identifier for this database.
virtual const std::string & fid()=0
Returns the file identifier of this database.
virtual IContainer * containerHandle(const std::string &name)=0
Returns a pointer to a container object. The user acquires ownership of that object.
void addReadCatalog(const std::string &connect)
Add new catalog, identified by name, to the existing ones.
void removeCatalog(const std::string &connect)
Remove catalog identified by name from the existing ones. * or '' removes all.
void setWriteCatalog(const std::string &connect)
Establish the writable catalog, identified by name.
ISession is the interface class for user (macroscopic) sessions Every transaction and connection to a...
Definition ISession.h:37
virtual std::unique_ptr< IDatabase > databaseHandle(const std::string &dbName, DatabaseSpecification::NameType dbNameType)=0
Returns a pointer to a database object. The user acquires ownership of that object.
virtual ITransaction & transaction()=0
Returns the transaction interface.
virtual const ITechnologySpecificAttributes & technologySpecificAttributes(long technology) const =0
Returns the object holding the technology specific attributes for a given technology domain.
virtual bool disconnectAll()=0
Explicitly disconnects all the databases.
T attribute(const std::string &attributeName, const std::string &option="")
Templated method to retrieve an attribute.
bool setAttribute(const std::string &attributeName, const T &atttibuteValue, const std::string &option="")
Templated method to set an attribute.
virtual bool commitAndHold()=0
Commits the holds transaction.
virtual bool start(Io::IoFlag type=Io::READ)=0
Starts a new transaction. Returns the success of the operation.
virtual bool isActive() const =0
Checks if the transaction is active.
static std::string release
Definition computils.h:50
std::string label(const std::string &format, int i)
Definition label.h:19
std::unique_ptr< ISession > createSession(IFileCatalog &catalog, int ageLimit=-1)
static const DbType ROOT_StorageType
Definition DbType.h:85
static const DbType POOL_StorageType
Definition DbType.h:84
@ FID
Physical File Name.
Definition IDatabase.h:26
@ LFN
File IDentifier.
Definition IDatabase.h:27
static void setLevel(MSG::Level l)
Definition DbPrint.h:20
MsgStream & msg
Definition testRead.cxx:32
TFile * file