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#include "MicroSessionManager.h"
12
13#include "GaudiKernel/IIoComponentMgr.h"
14#include "GaudiKernel/ConcurrencyFlags.h"
15
17
20
21#include "PoolSvc/ISession.h"
22#include "PoolSvc/IDatabase.h"
23#include "PoolSvc/IContainer.h"
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 const bool& atttibuteValue = true;
137 if (!m_dbSessionVec[IPoolSvc::kInputStream]->microSessionManager(pool::ROOT_StorageType.type()).setAttributeOfType("ENABLE_THREADSAFETY", static_cast<const void*>(&atttibuteValue), typeid(bool), "")) {
138 ATH_MSG_FATAL("Failed to enable thread safety in ROOT via PersistencySvc.");
139 return(StatusCode::FAILURE);
140 }
142 if (!connect(Io::READ, IPoolSvc::kInputStream).isSuccess()) {
143 ATH_MSG_FATAL("Failed to connect Input PersistencySvc.");
144 return(StatusCode::FAILURE);
145 }
146 m_dbSessionVec.push_back(pool::createSession(*m_catalog).release()); // Write Service
147 m_pers_mut.push_back(new CallMutex);
148
149 return(StatusCode::SUCCESS);
150}
151//__________________________________________________________________________
152StatusCode PoolSvc::start() {
153 // Switiching on ROOT implicit multi threading for AthenaMT
154 if (m_useROOTIMT && Gaudi::Concurrency::ConcurrencyFlags::numThreads() > 1) {
155 const int& atttibuteValue = Gaudi::Concurrency::ConcurrencyFlags::numThreads() - 1;
156 if (!m_dbSessionVec[IPoolSvc::kInputStream]->microSessionManager(pool::ROOT_StorageType.type()).setAttributeOfType("ENABLE_IMPLICITMT", static_cast<const void*>(&atttibuteValue), typeid(int), "")) {
157 ATH_MSG_FATAL("Failed to enable implicit multithreading in ROOT via PersistencySvc.");
158 return(StatusCode::FAILURE);
159 }
160 ATH_MSG_INFO("Enabled implicit multithreading in ROOT via PersistencySvc to: " << Gaudi::Concurrency::ConcurrencyFlags::numThreads() - 1);
161 }
162 return(StatusCode::SUCCESS);
163}
164//__________________________________________________________________________
165StatusCode PoolSvc::stop() {
166 ATH_MSG_VERBOSE("stop()");
167 bool retError = false;
168 for (unsigned int contextId = 0, imax = m_dbSessionVec.size(); contextId < imax; contextId++) {
169 if (!disconnect(contextId).isSuccess()) {
170 ATH_MSG_FATAL("Cannot disconnect Stream: " << contextId);
171 retError = true;
172 }
173 }
174 return(retError ? StatusCode::FAILURE : StatusCode::SUCCESS);
175}
176
177//__________________________________________________________________________
179 std::lock_guard<CallMutex> lock(m_pool_mut);
180 // Cleanup persistency service
181 for (const auto& dbSession : m_dbSessionVec) {
182 delete dbSession;
183 }
184 m_dbSessionVec.clear();
185 for (const auto& persistencyMutex : m_pers_mut) {
186 delete persistencyMutex;
187 }
188 m_mainOutputLabel.clear();
189 m_inputContextLabel.clear();
190 m_outputContextLabel.clear();
191 m_pers_mut.clear();
192 if (m_catalog != nullptr) {
193 m_catalog->commit();
194 delete m_catalog; m_catalog = nullptr;
195 }
196}
197//__________________________________________________________________________
198StatusCode PoolSvc::finalize() {
199 clearState();
200 return(::AthService::finalize());
201}
202//__________________________________________________________________________
204 ATH_MSG_INFO("I/O finalization...");
205 for (size_t i = 0; i < m_dbSessionVec.size(); i++) {
206 if ((m_dbSessionVec[i]->type() == Io::WRITE || m_dbSessionVec[i]->type() == Io::APPEND) &&
207 !disconnect(i).isSuccess()) {
208 ATH_MSG_WARNING("Cannot disconnect output Stream " << i);
209 }
210 }
211 clearState();
212 return(StatusCode::SUCCESS);
213}
214//__________________________________________________________________________
216 const void* obj,
217 const RootType& classDesc) {
218 unsigned int contextId = IPoolSvc::kOutputStream;
219 const std::string& auxString = placement->auxString();
220 if (!auxString.empty()) {
221 if (auxString.starts_with("[CTXT=")) {
222 ::sscanf(auxString.c_str(), "[CTXT=%08X]", &contextId);
223 } else if (auxString.starts_with("[CLABEL=")) {
224 contextId = this->getOutputContext(auxString);
225 }
226 if (contextId >= m_dbSessionVec.size()) {
227 ATH_MSG_WARNING("registerForWrite: Using default output Stream instead of id = " << contextId);
228 contextId = IPoolSvc::kOutputStream;
229 }
230 }
231 std::lock_guard<CallMutex> lock(*m_pers_mut[contextId]);
232 Token* token = m_dbSessionVec[contextId]->registerForWrite(*placement, obj, classDesc);
233 if (token == nullptr) {
234 ATH_MSG_WARNING("Cannot write object: " << placement->containerName());
235 }
236 return(token);
237}
238//__________________________________________________________________________
239void PoolSvc::setObjPtr(void*& obj, const Token* token) {
240 unsigned int contextId = IPoolSvc::kInputStream;
241 const std::string& auxString = token->auxString();
242 if (!auxString.empty()) {
243 if (auxString.starts_with("[CTXT=")) {
244 ::sscanf(auxString.c_str(), "[CTXT=%08X]", &contextId);
245 } else if (auxString.starts_with("[CLABEL=")) {
246 contextId = this->getInputContext(auxString);
247 }
248 if (contextId >= m_dbSessionVec.size()) {
249 ATH_MSG_WARNING("setObjPtr: Using default input Stream instead of id = " << contextId);
250 contextId = IPoolSvc::kInputStream;
251 }
252 }
253 ATH_MSG_VERBOSE("setObjPtr: token=" << token->toString() << ", auxString=" << auxString << ", contextID=" << contextId);
254 // Get Context ID/label from Token
255 std::lock_guard<CallMutex> lock(*m_pers_mut[contextId]);
256 obj = m_dbSessionVec[contextId]->readObject(*token, obj);
257 std::map<unsigned int, unsigned int>::const_iterator maxFileIter = m_contextMaxFile.find(contextId);
258 if (maxFileIter != m_contextMaxFile.end() && maxFileIter->second > 0) {
259 m_guidLists[contextId].remove(token->dbID());
260 m_guidLists[contextId].push_back(token->dbID());
261 while (m_guidLists[contextId].size() > maxFileIter->second) {
262 this->disconnectDb("FID:" + m_guidLists[contextId].begin()->toString(), contextId).ignore();
263 }
264 }
265}
266//__________________________________________________________________________
267unsigned int PoolSvc::getOutputContext(const std::string& label) {
268 std::lock_guard<CallMutex> lock(m_pool_mut);
269 if (m_mainOutputLabel.empty()) {
272 }
273 if (label == m_mainOutputLabel || label.empty()) {
275 }
276 std::map<std::string, unsigned int>::const_iterator contextIter = m_outputContextLabel.find(label);
277 if (contextIter != m_outputContextLabel.end()) {
278 return(contextIter->second);
279 }
280 const unsigned int id = m_dbSessionVec.size();
281 m_dbSessionVec.push_back(pool::createSession(*m_catalog).release());
282 m_pers_mut.push_back(new CallMutex);
283 m_outputContextLabel.try_emplace(label, id);
284 return(id);
285}
286//__________________________________________________________________________
287unsigned int PoolSvc::getInputContext(const std::string& label, unsigned int maxFile) {
288 std::lock_guard<CallMutex> lock(m_pool_mut);
289 if (!label.empty()) {
290 std::map<std::string, unsigned int>::const_iterator contextIter = m_inputContextLabel.find(label);
291 if (contextIter != m_inputContextLabel.end()) {
292 if (maxFile > 0) {
293 m_contextMaxFile[contextIter->second] = maxFile;
294 }
295 return(contextIter->second);
296 }
297 }
298 const unsigned int id = m_dbSessionVec.size();
299 m_dbSessionVec.push_back( pool::createSession(*m_catalog, maxFile).release() );
300 m_pers_mut.push_back(new CallMutex);
301 if (!connect(Io::READ, id).isSuccess()) {
302 ATH_MSG_WARNING("Failed to connect Input PersistencySvc: " << id);
304 }
305 if (!label.empty()) {
306 m_inputContextLabel.try_emplace(label, id);
307 }
308 m_contextMaxFile.try_emplace(id, maxFile);
309 return(id);
310}
311//__________________________________________________________________________
312std::map<std::string, unsigned int> PoolSvc::getInputContextMap() const {
313 std::lock_guard<CallMutex> lock(m_pool_mut);
314 return(m_inputContextLabel);
315}
316//__________________________________________________________________________
318 std::lock_guard<CallMutex> lock(m_pool_mut);
319 return(m_inputContextLabel.size());
320}
321//__________________________________________________________________________
322pool::ISession* PoolSvc::getInputContextSession(unsigned int contextId) const {
323 if (contextId >= m_dbSessionVec.size()) {
324 ATH_MSG_WARNING("getInputContextSession: Using default input Stream instead of id = " << contextId);
325 contextId = IPoolSvc::kInputStream;
326 }
327 return(m_dbSessionVec[contextId]);
328}
329//__________________________________________________________________________
330void PoolSvc::setShareMode(bool shareCat) {
331 m_shareCat = shareCat;
332}
333//__________________________________________________________________________
335 if (m_catalog != nullptr) {
336 m_catalog->start();
337 }
338}
339//__________________________________________________________________________
341 if (m_catalog != nullptr) {
342 m_catalog->commit();
343 }
344}
345//__________________________________________________________________________
346void PoolSvc::lookupBestPfn(const std::string& token, std::string& pfn, std::string& type) const {
347 std::string dbID;
348 if (token.starts_with("PFN:")) {
349 m_catalog->lookupFileByPFN(token.substr(4), dbID, type); // PFN -> FID
350 } else if (token.starts_with("LFN:")) {
351 dbID = m_catalog->lookupLFN(token.substr(4)); // LFN -> FID
352 } else if (token.starts_with("FID:")) {
353 dbID = token.substr(4);
354 } else if (token.size() > Guid::stringSize()) { // full token
355 Token tok;
356 tok.fromString(token);
357 dbID = tok.dbID().toString();
358 } else { // guid only
359 dbID = token;
360 }
361 m_catalog->getFirstPFN(dbID, pfn, type); // FID -> best PFN
362}
363//__________________________________________________________________________
364void PoolSvc::renamePfn(const std::string& pf, const std::string& newpf) {
365 std::string dbID, type;
366 m_catalog->lookupFileByPFN(pf, dbID, type);
367 if (dbID.empty()) {
368 ATH_MSG_WARNING("Failed to lookup: " << pf << " in FileCatalog");
369 return;
370 }
371 m_catalog->lookupFileByPFN(newpf, dbID, type);
372 if (!dbID.empty()) {
373 ATH_MSG_INFO("Found: " << newpf << " in FileCatalog");
374 return;
375 }
376 m_catalog->renamePFN(pf, newpf);
377}
378//__________________________________________________________________________
379StatusCode PoolSvc::connectCollection(const std::string& connection,
380 const std::string& collectionName,
381 unsigned int contextId) const
382{
383 ATH_MSG_DEBUG("connectCollection() connection=" << connection
384 << ", name=" << collectionName << ", contextID=" << contextId);
385 if (contextId >= m_dbSessionVec.size()) {
386 ATH_MSG_WARNING("connectCollection: Using default input Stream instead of id = " << contextId);
387 contextId = IPoolSvc::kInputStream;
388 }
389
391 // Check POOL FileCatalog entry.
392 bool insertFile = false;
393 if (connection.starts_with("PFN:")) {
394 std::string fid, fileType;
395 m_catalog->lookupFileByPFN(connection.substr(4), fid, fileType);
396 if (fid.empty()) { // No entry in file catalog
397 insertFile = true;
398 ATH_MSG_INFO("File is not in Catalog! Attempt to open it anyway.");
399 }
400 }
401
402 // Check whether Collection Container exists.
403 std::unique_ptr<pool::IDatabase> dbH = getDbHandle(contextId, connection);
404 if( !dbH ) {
405 ATH_MSG_INFO("connectCollection(): Failed to get Database Handle for: " << connection);
406 return StatusCode::FAILURE;
407 }
408 try {
409 if (dbH->openMode() == Io::INVALID) {
410 dbH->connectForRead();
411 }
412 std::map<unsigned int, unsigned int>::const_iterator maxFileIter = m_contextMaxFile.find(contextId);
413 if (maxFileIter != m_contextMaxFile.end() && maxFileIter->second > 0 && !dbH->fid().empty()) {
414 const Guid guid(dbH->fid());
415 m_guidLists[contextId].remove(guid);
416 m_guidLists[contextId].push_back(guid);
417 while (m_guidLists[contextId].size() > maxFileIter->second + 1) {
418 this->disconnectDb("FID:" + m_guidLists[contextId].begin()->toString(), contextId).ignore();
419 }
420 }
421 } catch (std::exception& e) {
422 ATH_MSG_INFO("connectCollection() failed to open '" << connection << "' - trying.");
423 }
424 // For multithreaded processing (with multiple events in flight),
425 // increase virtual tree size to accomodate back reads
426 if (m_useROOTMaxTree && contextId == IPoolSvc::kInputStream && Gaudi::Concurrency::ConcurrencyFlags::numConcurrentEvents() > 1) {
427 ATH_MSG_DEBUG("connectCollection(): Increasing virtual TTree size for: " << connection);
428 if (!this->setAttribute("TREE_MAX_VIRTUAL_SIZE", "-1", pool::ROOT_StorageType.type(), connection.substr(4), "CollectionTree", contextId).isSuccess()) {
429 ATH_MSG_DEBUG("Failed to increase maximum virtual TTree size.");
430 }
431 }
432 if (insertFile) return(StatusCode::RECOVERABLE);
433
434 return(StatusCode::SUCCESS);
435}
436//__________________________________________________________________________
437StatusCode PoolSvc::checkCollection(const std::string& connection,
438 unsigned int contextId,
439 bool noContainer) const {
441 std::unique_ptr<pool::IDatabase> dbH = getDbHandle(contextId, connection);
442 if (dbH != nullptr && !dbH->fid().empty()) {
443 if (noContainer) {
444 return(StatusCode::SUCCESS); // no events
445 }
446 if (m_attemptCatalogPatch.value()) {
447 patchCatalog(connection.substr(4), *dbH);
448 }
449 return(StatusCode::SUCCESS);
450 }
451 return(StatusCode::FAILURE);
452}
453//__________________________________________________________________________
454void PoolSvc::patchCatalog(const std::string& pfn, pool::IDatabase& dbH) const {
455 std::scoped_lock lock(m_pool_mut);
457 std::string fid = dbH.fid();
459 catalog_locked->registerPFN(pfn, "ROOT_All", fid);
460}
461//__________________________________________________________________________
462Token* PoolSvc::getToken(const std::string& connection,
463 const std::string& collection,
464 const unsigned long ientry) const {
465 std::lock_guard<CallMutex> lock(*m_pers_mut[IPoolSvc::kInputStream]);
466 std::unique_ptr<pool::IDatabase> dbH = getDbHandle(IPoolSvc::kInputStream, connection);
467 if (dbH == nullptr) {
468 return(nullptr);
469 }
470 if (dbH->openMode() == Io::INVALID) {
471 dbH->connectForRead();
472 }
473 std::unique_ptr<pool::IContainer> contH = getContainerHandle(dbH.get(), collection);
474 if (contH == nullptr) {
475 return(nullptr);
476 }
477 auto tokenIter = std::unique_ptr<pool::ITokenIterator>(contH->tokens());
478 // the Token returned by the iterator has the refCount already increased
479 return tokenIter->seek(ientry)? tokenIter->next() : nullptr;
480}
481//__________________________________________________________________________
482StatusCode PoolSvc::connect(Io::IoFlag type, unsigned int contextId) {
483 if (type != Io::READ) {
484 if (contextId >= m_dbSessionVec.size()) {
485 ATH_MSG_WARNING("connect: Using default output Stream instead of id = " << contextId);
486 contextId = IPoolSvc::kOutputStream;
487 }
488 } else {
489 if (contextId > m_dbSessionVec.size()) {
490 ATH_MSG_WARNING("connect: Using default input Stream instead of id = " << contextId);
491 contextId = IPoolSvc::kInputStream;
492 } else if (contextId == m_dbSessionVec.size()) {
493 ATH_MSG_INFO("Connecting to InputStream for: " << contextId);
494 contextId = this->getInputContext("");
495 }
496 }
497 if (contextId >= m_dbSessionVec.size()) {
498 return(StatusCode::FAILURE);
499 }
501 auto session = m_dbSessionVec[contextId];
502 // Connect to a logical database using the pre-defined technology and dbID
503 if (session != nullptr && session->type() != Io::INVALID) {
504 return(StatusCode::SUCCESS);
505 }
506 if (session == nullptr || !session->start(type)) {
507 ATH_MSG_ERROR("connect failed session = " << session << " type = " << type);
508 return(StatusCode::FAILURE);
509 }
510
511 return(StatusCode::SUCCESS);
512}
513//__________________________________________________________________________
514StatusCode PoolSvc::commit(unsigned int contextId) const {
515 if (contextId >= m_dbSessionVec.size()) {
516 return(StatusCode::FAILURE);
517 }
519 auto session = m_dbSessionVec[contextId];
520 if (session != nullptr && session->type() != Io::INVALID) {
521 if (!session->commit()) {
522 ATH_MSG_ERROR("POOL commit failed " << session);
523 return(StatusCode::FAILURE);
524 }
525 if (session->type() == Io::READ) {
526 session->disconnectAll();
527 }
528 }
529 return(StatusCode::SUCCESS);
530}
531//__________________________________________________________________________
532StatusCode PoolSvc::commitAndHold(unsigned int contextId) const {
533 if (contextId >= m_dbSessionVec.size()) {
534 return(StatusCode::FAILURE);
535 }
537 pool::ISession* session = m_dbSessionVec[contextId];
538 if (session != nullptr && session->type() != Io::INVALID) {
539 if (!session->commitAndHold()) {
540 ATH_MSG_ERROR("POOL commitAndHold failed " << session);
541 return(StatusCode::FAILURE);
542 }
543 }
544 return(StatusCode::SUCCESS);
545}
546//__________________________________________________________________________
547StatusCode PoolSvc::disconnect(unsigned int contextId) const {
548 ATH_MSG_DEBUG("Disconnect request for contextId=" << contextId);
549 if (contextId >= m_dbSessionVec.size()) {
550 return(StatusCode::SUCCESS);
551 }
553 pool::ISession* session = m_dbSessionVec[contextId];
554 if (session != nullptr && session->type() != Io::INVALID) {
555 if (!commit(contextId).isSuccess()) {
556 ATH_MSG_ERROR("disconnect failed to commit " << session);
557 return(StatusCode::FAILURE);
558 }
559 if (session->disconnectAll()) {
560 ATH_MSG_DEBUG("Disconnected PersistencySvc session");
561 } else {
562 ATH_MSG_ERROR("disconnect failed to diconnect PersistencySvc");
563 return(StatusCode::FAILURE);
564 }
565 }
566 return(StatusCode::SUCCESS);
567}
568//__________________________________________________________________________
569StatusCode PoolSvc::disconnectDb(const std::string& connection, unsigned int contextId) const {
570 if (contextId >= m_dbSessionVec.size()) {
571 return(StatusCode::SUCCESS);
572 }
574 std::unique_ptr<pool::IDatabase> dbH = getDbHandle(contextId, connection);
575 if (dbH == nullptr) {
576 ATH_MSG_ERROR("Failed to get Session/DatabaseHandle.");
577 return(StatusCode::FAILURE);
578 }
579 std::map<unsigned int, unsigned int>::const_iterator maxFileIter = m_contextMaxFile.find(contextId);
580 if (maxFileIter != m_contextMaxFile.end() && maxFileIter->second > 0) {
581 m_guidLists[contextId].remove(Guid(dbH->fid()));
582 }
583 dbH->disconnect();
584 return(StatusCode::SUCCESS);
585}
586//_______________________________________________________________________
587StatusCode PoolSvc::getAttribute(const std::string& optName,
588 std::string& data,
589 long tech,
590 unsigned int contextId) const {
591 if (contextId >= m_dbSessionVec.size()) {
592 ATH_MSG_WARNING("getAttribute: Using default input Stream instead of id = " << contextId);
593 contextId = IPoolSvc::kInputStream;
594 }
596 pool::ISession* sesH = m_dbSessionVec[contextId];
597 std::ostringstream oss;
598 if (data == "DbLonglong") {
599 long long int attr_data;
600 oss << std::dec << sesH->microSessionManager(tech).attributeOfType(optName, static_cast<void*>(&attr_data), typeid(long long int), "");
601 } else if (data == "double") {
602 double attr_data;
603 oss << std::dec << sesH->microSessionManager(tech).attributeOfType(optName, static_cast<void*>(&attr_data), typeid(double), "");
604 } else {
605 int attr_data;
606 oss << std::dec << sesH->microSessionManager(tech).attributeOfType(optName, static_cast<void*>(&attr_data), typeid(int), "");
607 }
608 data = oss.str();
609 ATH_MSG_INFO("Domain attribute [" << optName << "]" << ": " << data);
610 return(StatusCode::SUCCESS);
611}
612//_______________________________________________________________________
613StatusCode PoolSvc::getAttribute(const std::string& optName,
614 std::string& data,
615 long tech,
616 const std::string& dbName,
617 const std::string& contName,
618 unsigned int contextId) const {
620 std::unique_ptr<pool::IDatabase> dbH = getDbHandle(contextId, dbName);
621 if (dbH == nullptr) {
622 ATH_MSG_DEBUG("getAttribute: Failed to get Session/DatabaseHandle to get POOL property.");
623 return(StatusCode::FAILURE);
624 }
625 if (dbH->openMode() == Io::INVALID) {
626 if (m_dbSessionVec[contextId]->type() == Io::WRITE || m_dbSessionVec[contextId]->type() == Io::APPEND) {
627 dbH->setTechnology(tech);
628 dbH->connectForWrite();
629 } else {
630 dbH->connectForRead();
631 }
632 }
633 std::ostringstream oss;
634 if (contName.empty()) {
635 if (data == "DbLonglong") {
636 long long int attr_data;
637 oss << std::dec << dbH->attributeOfType(optName, static_cast<void*>(&attr_data), typeid(long long int), "");
638 } else if (data == "double") {
639 double attr_data;
640 oss << std::dec << dbH->attributeOfType(optName, static_cast<void*>(&attr_data), typeid(double), "");
641 } else if (data == "string") {
642 char* attr_data;
643 oss << std::dec << dbH->attributeOfType(optName, static_cast<void*>(&attr_data), typeid(char*), "");
644 } else {
645 int attr_data;
646 oss << std::dec << dbH->attributeOfType(optName, static_cast<void*>(&attr_data), typeid(int), "");
647 }
648 ATH_MSG_INFO("Database (" << dbH->pfn() << ") attribute [" << optName << "]" << ": " << oss.str());
649 } else {
650 std::unique_ptr<pool::IContainer> contH = getContainerHandle(dbH.get(), contName);
651 if (contH == nullptr) {
652 ATH_MSG_DEBUG("Failed to get ContainerHandle to get POOL property.");
653 return(StatusCode::FAILURE);
654 }
655 if (data == "DbLonglong") {
656 long long int attr_data;
657 oss << std::dec << contH->attributeOfType(optName, static_cast<void*>(&attr_data), typeid(long long int), "");
658 } else if (data == "double") {
659 double attr_data;
660 oss << std::dec << contH->attributeOfType(optName, static_cast<void*>(&attr_data), typeid(double), "");
661 } else {
662 int attr_data;
663 oss << std::dec << contH->attributeOfType(optName, static_cast<void*>(&attr_data), typeid(int), "");
664 }
665 ATH_MSG_INFO("Container attribute [" << contName << "." << optName << "]: " << oss.str());
666 }
667 data = oss.str();
668 return(StatusCode::SUCCESS);
669}
670//_______________________________________________________________________
671StatusCode PoolSvc::setAttribute(const std::string& optName,
672 const std::string& data,
673 long tech,
674 unsigned int contextId) const {
675 if (contextId >= m_dbSessionVec.size()) {
676 ATH_MSG_WARNING("setAttribute: Using default output Stream instead of id = " << contextId);
677 contextId = IPoolSvc::kOutputStream;
678 }
680 pool::ISession* sesH = m_dbSessionVec[contextId];
681 if (data[data.size() - 1] == 'L') {
682 const long long int& atttibuteValue = atoll(data.c_str());
683 if (!sesH->microSessionManager(tech).setAttributeOfType(optName, static_cast<const void*>(&atttibuteValue), typeid(long long int), "")) {
684 ATH_MSG_DEBUG("Failed to set POOL property, " << optName << " to " << data);
685 return(StatusCode::FAILURE);
686 }
687 } else {
688 const int& atttibuteValue = atoi(data.c_str());
689 if (!sesH->microSessionManager(tech).setAttributeOfType(optName, static_cast<const void*>(&atttibuteValue), typeid(int), "")) {
690 ATH_MSG_DEBUG("Failed to set POOL property, " << optName << " to " << data);
691 return(StatusCode::FAILURE);
692 }
693 }
694 return(StatusCode::SUCCESS);
695}
696//_______________________________________________________________________
697StatusCode PoolSvc::setAttribute(const std::string& optName,
698 const std::string& data,
699 long tech,
700 const std::string& dbName,
701 const std::string& contName,
702 unsigned int contextId) const {
703 if (contextId >= m_dbSessionVec.size()) {
704 ATH_MSG_WARNING("setAttribute: Using default output Stream instead of id = " << contextId);
705 contextId = IPoolSvc::kOutputStream;
706 }
708 std::unique_ptr<pool::IDatabase> dbH = getDbHandle(contextId, dbName);
709 if (dbH == nullptr) {
710 ATH_MSG_DEBUG("Failed to get Session/DatabaseHandle to set POOL property.");
711 return(StatusCode::FAILURE);
712 }
713 if (dbH->openMode() == Io::INVALID) {
714 if (m_dbSessionVec[contextId]->type() == Io::WRITE || m_dbSessionVec[contextId]->type() == Io::APPEND) {
715 dbH->setTechnology(tech);
716 dbH->connectForWrite();
717 } else {
718 dbH->connectForRead();
719 }
720 }
721 bool retError = false;
722 std::string objName;
723 bool hasTTreeName = contName.starts_with("TTree=");
724 if (contName.empty() || hasTTreeName || m_dbSessionVec[contextId]->type() == Io::READ) {
725 objName = hasTTreeName ? contName.substr(6) : contName;
726 if( !isNumber(data) ) {
727 const char* atttibuteValue = data.c_str();
728 retError = dbH->setAttributeOfType(optName, static_cast<const void*>(&atttibuteValue), typeid(char*), objName);
729 } else if( data[data.size() - 1] == 'L' ) {
730 const long long int& atttibuteValue = atoll(data.c_str());
731 retError = dbH->setAttributeOfType(optName, static_cast<const void*>(&atttibuteValue), typeid(long long int), objName);
732 } else {
733 const int& atttibuteValue = atoi(data.c_str());
734 retError = dbH->setAttributeOfType(optName, static_cast<const void*>(&atttibuteValue), typeid(int), objName);
735 }
736 if (!retError) {
737 ATH_MSG_DEBUG("Failed to set POOL property, " << optName << " to " << data);
738 return(StatusCode::FAILURE);
739 }
740 } else {
741 std::unique_ptr<pool::IContainer> contH = getContainerHandle(dbH.get(), contName);
742 if (contH == nullptr) {
743 ATH_MSG_DEBUG("Failed to get ContainerHandle to set POOL property.");
744 return(StatusCode::FAILURE);
745 }
746 if (auto p = contName.find('('); p != std::string::npos) {
747 objName = contName.substr(p + 1); // Get BranchName between parenthesis
748 objName.erase(objName.find(')'));
749 } else if (auto p = contName.find("::"); p != std::string::npos) {
750 objName = contName.substr(p + 2); // Split off Tree name
751 } else if (auto p = contName.find('_'); p != std::string::npos) {
752 objName = contName.substr(p + 1); // Split off "POOLContainer"
753 objName.erase(objName.find('/')); // Split off key
754 }
755 std::string::size_type off = 0;
756 while ((off = objName.find_first_of("<>/")) != std::string::npos) {
757 objName[off] = '_'; // Replace special chars (e.g. templates)
758 }
759 if (data[data.size() - 1] == 'L') {
760 const long long int& atttibuteValue = atoll(data.c_str());
761 retError = contH->setAttributeOfType(optName, static_cast<const void*>(&atttibuteValue), typeid(long long int), objName);
762 } else {
763 const int& atttibuteValue = atoi(data.c_str());
764 retError = contH->setAttributeOfType(optName, static_cast<const void*>(&atttibuteValue), typeid(int), objName);
765 }
766 if (!retError) {
767 ATH_MSG_DEBUG("Failed to set POOL container property, " << optName << " for " << contName << " : " << objName << " to " << data);
768 return(StatusCode::FAILURE);
769 }
770 }
771 return(StatusCode::SUCCESS);
772}
773
774//__________________________________________________________________________
777 ctlg->removeCatalog("*");
778 for (auto& catalog : m_readCatalog.value()) {
779 ATH_MSG_DEBUG("POOL ReadCatalog is " << catalog);
780 if (catalog.starts_with("apcfile:") || catalog.starts_with("prfile:")) {
781 std::string::size_type cpos = catalog.find(':');
782 // check for file accessed via ATLAS_POOLCOND_PATH
783 std::string file = poolCondPath(catalog.substr(cpos + 1));
784 if (!file.empty()) {
785 ATH_MSG_INFO("Resolved path (via ATLAS_POOLCOND_PATH) is " << file);
786 ctlg->addReadCatalog("file:" + file);
787 } else {
788 // As backup, check for file accessed via PathResolver
789 file = PathResolver::find_file(catalog.substr(cpos + 1), "DATAPATH");
790 if (!file.empty()) {
791 ATH_MSG_INFO("Resolved path (via DATAPATH) is " << file);
792 ctlg->addReadCatalog("file:" + file);
793 } else {
794 ATH_MSG_INFO("Unable find catalog "
795 << catalog
796 << " in $ATLAS_POOLCOND_PATH and $DATAPATH");
797 }
798 }
799 } else {
800 ctlg->addReadCatalog(catalog);
801 }
802 }
803 try {
804 ATH_MSG_INFO("POOL WriteCatalog is " << m_writeCatalog.value());
805 ctlg->setWriteCatalog(m_writeCatalog.value());
806 } catch(std::exception& e) {
807 ATH_MSG_ERROR("setWriteCatalog - caught exception: " << e.what());
808 return(nullptr); // This catalog is not setup properly!
809 }
810 return(ctlg);
811}
812
813//__________________________________________________________________________
816//__________________________________________________________________________
817std::unique_ptr<pool::IDatabase> PoolSvc::getDbHandle(unsigned int contextId, const std::string& dbName) const {
818 if (contextId >= m_dbSessionVec.size()) {
819 ATH_MSG_WARNING("getDbHandle: Using default input Stream instead of id = " << contextId);
820 contextId = IPoolSvc::kInputStream;
821 }
822 pool::ISession* sesH = m_dbSessionVec[contextId];
823 if (!sesH){
824 ATH_MSG_ERROR("Session pointer is null.");
825 return nullptr;
826 }
827 if (sesH->type() == Io::INVALID) {
828 Io::IoFlag transMode = Io::READ;
829 ATH_MSG_DEBUG("Start transaction, type = " << transMode);
830 if (!sesH->start(transMode)) {
831 ATH_MSG_WARNING("Failed to start transaction, type = " << transMode);
832 return nullptr;
833 }
834 }
835 if (dbName.starts_with("PFN:")) {
836 return sesH->databaseHandle(dbName.substr(4), pool::DatabaseSpecification::PFN);
837 } else if (dbName.starts_with("LFN:")) {
838 return sesH->databaseHandle(dbName.substr(4), pool::DatabaseSpecification::LFN);
839 } else if (dbName.starts_with("FID:")) {
840 return sesH->databaseHandle(dbName.substr(4), pool::DatabaseSpecification::FID);
841 }
843}
844//__________________________________________________________________________
845std::unique_ptr<pool::IContainer> PoolSvc::getContainerHandle(pool::IDatabase* dbH, const std::string& contName) const {
846 pool::IContainer* contH = nullptr;
847 if (dbH == nullptr) {
848 ATH_MSG_DEBUG("No DatabaseHandle to get Container.");
849 return(nullptr);
850 }
851 if (contName.find("DataHeader") != std::string::npos) {
852 contH = dbH->containerHandle(contName.substr(0, contName.find("_p")));
853 } else {
854 contH = dbH->containerHandle(contName);
855 }
856 return(std::unique_ptr<pool::IContainer>(contH));
857}
858//__________________________________________________________________________
859std::string PoolSvc::poolCondPath(const std::string& leaf) {
860 // look for files at $ATLAS_POOLCOND_PATH/<leaf>
861 // return full filename if exists, or empty string if not
862 const char* cpath = std::getenv("ATLAS_POOLCOND_PATH");
863 if (cpath && strcmp(cpath, "") != 0) {
864 const std::string testpath = std::string(cpath) + "/" + leaf;
865
866 // Try to open file for reading. Note that a simple stat call may return
867 // a wrong result if the file is residing on an auto-mounted FS (ATR-28801).
868 if (FILE* fp = std::fopen(testpath.c_str(), "r")) {
869 std::fclose(fp);
870 return testpath;
871 }
872 }
873 return {};
874}
#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:775
virtual Token * registerForWrite(const Placement *placement, const void *obj, const RootType &classDesc) override
Definition PoolSvc.cxx:215
virtual ~PoolSvc()
Destructor.
Definition PoolSvc.cxx:814
virtual void startCatalog() override
Definition PoolSvc.cxx:334
virtual void renamePfn(const std::string &pf, const std::string &newpf) override
Definition PoolSvc.cxx:364
pool::IFileCatalog * m_catalog
Definition PoolSvc.h:225
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:482
std::string poolCondPath(const std::string &leaf)
Resolve a file using ATLAS_POOLCOND_PATH.
Definition PoolSvc.cxx:859
virtual unsigned int getInputContextMapSize() const override
Definition PoolSvc.cxx:317
void patchCatalog(const std::string &pfn, pool::IDatabase &dbH) const
Definition PoolSvc.cxx:454
CallMutex m_pool_mut
Definition PoolSvc.h:222
virtual unsigned int getInputContext(const std::string &label, unsigned int maxFile=0) override
Definition PoolSvc.cxx:287
virtual void lookupBestPfn(const std::string &token, std::string &pfn, std::string &type) const override
Definition PoolSvc.cxx:346
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:671
std::vector< pool::ISession * > m_dbSessionVec
Definition PoolSvc.h:226
Gaudi::Property< bool > m_useROOTIMT
Use ROOT Implicit MultiThreading, default = true.
Definition PoolSvc.h:245
virtual StatusCode commit(unsigned int contextId=IPoolSvc::kInputStream) const override
Commit data for a given contextId and flush buffer.
Definition PoolSvc.cxx:514
std::unique_ptr< pool::IContainer > getContainerHandle(pool::IDatabase *dbH, const std::string &contName) const
Get Container handle.
Definition PoolSvc.cxx:845
virtual Token * getToken(const std::string &connection, const std::string &collection, const unsigned long ientry) const override
Definition PoolSvc.cxx:462
virtual StatusCode start() override
Required of all Gaudi services:
Definition PoolSvc.cxx:152
virtual StatusCode connectCollection(const std::string &connection, const std::string &collectionName, unsigned int contextId=IPoolSvc::kInputStream) const override
Definition PoolSvc.cxx:379
StatusCode setupPersistencySvc()
Definition PoolSvc.cxx:123
virtual pool::ISession * getInputContextSession(unsigned int contextId) const override
Definition PoolSvc.cxx:322
virtual StatusCode io_finalize() override
Definition PoolSvc.cxx:203
virtual StatusCode checkCollection(const std::string &connection, unsigned int contextId, bool noContainer) const override
Definition PoolSvc.cxx:437
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:238
Gaudi::Property< bool > m_useROOTMaxTree
Increase virtual TTree size to avoid backreads in multithreading, default = false.
Definition PoolSvc.h:247
std::map< std::string, unsigned int > m_outputContextLabel
Definition PoolSvc.h:229
virtual StatusCode disconnectDb(const std::string &connection, unsigned int contextId=IPoolSvc::kInputStream) const override
Disconnect single Database.
Definition PoolSvc.cxx:569
std::recursive_mutex CallMutex
Definition PoolSvc.h:208
virtual void commitCatalog() override
Definition PoolSvc.cxx:340
std::vector< CallMutex * > m_pers_mut
Definition PoolSvc.h:227
std::map< std::string, unsigned int > m_inputContextLabel
Definition PoolSvc.h:228
virtual void setObjPtr(void *&obj, const Token *token) override
Definition PoolSvc.cxx:239
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:243
std::string m_mainOutputLabel
Definition PoolSvc.h:230
void clearState()
Definition PoolSvc.cxx:178
std::map< unsigned int, unsigned int > m_contextMaxFile
Definition PoolSvc.h:231
virtual void setShareMode(bool shareCat) override
Definition PoolSvc.cxx:330
std::unique_ptr< pool::IDatabase > getDbHandle(unsigned int contextId, const std::string &dbName) const
Get Database handle.
Definition PoolSvc.cxx:817
virtual StatusCode commitAndHold(unsigned int contextId=IPoolSvc::kInputStream) const override
Commit data for a given contextId and hold buffer.
Definition PoolSvc.cxx:532
virtual StatusCode disconnect(unsigned int contextId=IPoolSvc::kInputStream) const override
Disconnect PersistencySvc associated with a contextId.
Definition PoolSvc.cxx:547
virtual StatusCode finalize() override
Required of all Gaudi services:
Definition PoolSvc.cxx:198
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:312
virtual unsigned int getOutputContext(const std::string &label) override
Definition PoolSvc.cxx:267
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:241
virtual StatusCode stop() override
Definition PoolSvc.cxx:165
Gaudi::Property< bool > m_attemptCatalogPatch
AttemptCatalogPatch, option to create catalog: default = false.
Definition PoolSvc.h:250
std::map< unsigned int, std::list< Guid > > m_guidLists ATLAS_THREAD_SAFE
Definition PoolSvc.h:233
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:587
bool m_shareCat
Definition PoolSvc.h:224
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
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 connection to a database and ob...
Definition ISession.h:36
virtual Io::IoFlag type() const =0
Returns the transaction type.
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 MicroSessionManager & microSessionManager(long technology)=0
Returns the technology given a technology type.
virtual bool start(Io::IoFlag type=Io::READ)=0
Starts a new transaction. Returns the success of the operation.
virtual bool commitAndHold()=0
Commits the holds transaction.
virtual bool disconnectAll()=0
Explicitly disconnects all the databases.
virtual bool attributeOfType(const std::string &attributeName, void *data, const std::type_info &typeInfo, const std::string &option)
virtual bool setAttributeOfType(const std::string &attributeName, const void *data, const std::type_info &typeInfo, const std::string &option)
static std::string release
Definition computils.h:54
std::string label(const std::string &format, int i)
Definition label.h:19
static const DbType ROOT_StorageType
Definition DbType.h:85
std::unique_ptr< ISession > createSession(IFileCatalog &catalog, int ageLimit=-1)
@ 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