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