diff --git a/AtlasTest/DatabaseTest/IOVDbTestAlg/python/IOVDbTestAlgConfig.py b/AtlasTest/DatabaseTest/IOVDbTestAlg/python/IOVDbTestAlgConfig.py index 7c9b7f2fc310d22e2146bdcd7c777ada80808eb1..f0c2ad19bc1c8b628bf802632343aad50a9d0055 100644 --- a/AtlasTest/DatabaseTest/IOVDbTestAlg/python/IOVDbTestAlgConfig.py +++ b/AtlasTest/DatabaseTest/IOVDbTestAlg/python/IOVDbTestAlgConfig.py @@ -46,7 +46,8 @@ def IOVDbTestAlgWriteCfg(flags, registerIOV = False): from AthenaPoolCnvSvc.PoolCommonConfig import AthenaPoolCnvSvcCfg acc.merge( AthenaPoolCnvSvcCfg(flags, - PoolContainerPrefix = "ROOTTREE:CollectionTree", + PoolContainerPrefix = "CollectionTree", + StorageTechnology = "ROOTTREE", TopLevelContainerName = "<type>", SubLevelBranchName = "") ) diff --git a/Database/APR/CollectionBase/src/CollectionFactory.cpp b/Database/APR/CollectionBase/src/CollectionFactory.cpp index 951f4976baf9a96a4cbf1a1171e64104e8f05d3f..5acd3e8e6dc31e420c1521d525bd0c6377babe4c 100755 --- a/Database/APR/CollectionBase/src/CollectionFactory.cpp +++ b/Database/APR/CollectionBase/src/CollectionFactory.cpp @@ -53,7 +53,6 @@ pool::CollectionFactory::create_callPlugin( const pool::ICollectionDescription& pool::ISession* session ) const { std::string type( description.type() ); - // ICollection *coll = Gaudi::PluginService::Factory<ICollection*, const ICollectionDescription*, ICollection::OpenMode, ISession*>::create( type, &description, openMode, session ).release(); ICollection *coll = Gaudi::PluginService::Factory<ICollection*( const ICollectionDescription*, ICollection::OpenMode, ISession*)>::create( type, &description, openMode, session ).release(); if( !coll ) { std::string errorMsg = "APR::CollectionFactory::create(" + type + "," + description.name() + ") FAILED! Plugin for that collection technology could not be loaded."; diff --git a/Database/APR/POOLCore/POOLCore/APRDefaults.h b/Database/APR/POOLCore/POOLCore/APRDefaults.h index 422b40a426ce266a54cc01187254780551601c36..5d8b6779d5ec2d04b4940470281a6d699f99ce4c 100644 --- a/Database/APR/POOLCore/POOLCore/APRDefaults.h +++ b/Database/APR/POOLCore/POOLCore/APRDefaults.h @@ -4,12 +4,14 @@ namespace APRDefaults { // using a struct so PyROOT can autoload struct TTreeNames { - static constexpr const char* EventData {"CollectionTree"}; - static constexpr const char* EventTag {"POOLCollectionTree"}; + static constexpr const char* EventData {"CollectionTree"}; + static constexpr const char* EventTag {"POOLCollectionTree"}; + static constexpr const char* DataHeader {"POOLContainer"}; }; struct RNTupleNames { - static constexpr const char* EventData {"EventData"}; - static constexpr const char* EventTag {"EventTag"}; + static constexpr const char* EventData {"EventData"}; + static constexpr const char* EventTag {"EventTag"}; + static constexpr const char* DataHeader {"DataHeader"}; }; static constexpr const char* IndexColName {"index_ref"}; diff --git a/Database/APR/RootCollection/src/RNTCollection.cpp b/Database/APR/RootCollection/src/RNTCollection.cpp index 1920f0e46864ce81f97aa7a425b0220c0b4429bc..549f2ce3ee437e0dd7a64d33440ff3b609786ce5 100644 --- a/Database/APR/RootCollection/src/RNTCollection.cpp +++ b/Database/APR/RootCollection/src/RNTCollection.cpp @@ -92,8 +92,7 @@ void RNTCollection::delayedFileOpen( const std::string& method ) std::unique_ptr< RNTupleReader > RNTCollection::getCollectionRNTuple() { if( m_file ) { - std::string rntprefix { "RNT:" }; // MN: TODO: standarize RNTuple naming - auto reader = RNTupleReader::Open( rntprefix + APRDefaults::RNTupleNames::EventTag, m_fileName /* ,opts */ ); + auto reader = RNTupleReader::Open( APRDefaults::RNTupleNames::EventTag, m_fileName /* ,opts */ ); if( reader ) m_poolOut << coral::Debug << "Retrieved Collection RNTuple \"" #if ROOT_VERSION_CODE >= ROOT_VERSION( 6, 31, 0 ) diff --git a/Database/APR/RootStorageSvc/src/RootDatabase.cpp b/Database/APR/RootStorageSvc/src/RootDatabase.cpp index 5a3069f8b2e0c0ca8d790b91d0e677ac4594589d..425eeef697b3b710b29355d5907fbc367ebeea56 100644 --- a/Database/APR/RootStorageSvc/src/RootDatabase.cpp +++ b/Database/APR/RootStorageSvc/src/RootDatabase.cpp @@ -48,6 +48,7 @@ using ROOT::Experimental::Detail::RFieldBase; using namespace pool; using namespace std; + /// Standard Constuctor RootDatabase::RootDatabase() : m_file(nullptr), @@ -400,6 +401,20 @@ long long int RootDatabase::byteCount(int which) const { } } + +/// Safe way to check for a TTree with a given name +/// Any check (even dynamic_cast) of a pointer returned by file->Get(RNTuple) will SEGV +TTree* RootDatabase::getTree(const std::string &name) { + if( m_file ) { + TKey *key = m_file->GetKey(name.c_str()); + if( key and strcmp(key->GetClassName(), "TTree")==0 ) { + return static_cast<TTree*>( m_file->Get(name.c_str()) ); + } + } + return nullptr; +} + + /// Access options DbStatus RootDatabase::getOption(DbOption& opt) { const char* n = opt.name().c_str(); @@ -530,7 +545,7 @@ DbStatus RootDatabase::getOption(DbOption& opt) { if (!m_treeNameWithCache.size()) return opt._setValue((int)0); if ( !m_file ) return Error; - TTree* tr = (TTree*)m_file->Get(m_treeNameWithCache.c_str()); + TTree* tr = getTree( m_treeNameWithCache ); if (tr) return opt._setValue((int)tr->GetCacheSize()); return opt._setValue((int)0); } else if( !strcasecmp(n+5,"CACHE_LEARN_EVENTS") ) { @@ -691,7 +706,7 @@ DbStatus RootDatabase::setOption(const DbOption& opt) { log << DbPrintLvl::Error << "Must set option to tree name to start TREE_MAX_VIRTUAL_SIZE " << DbPrint::endmsg; return Error; } - TTree* tree = (TTree*)m_file->Get(opt.option().c_str()); + TTree* tree = getTree( opt.option() ); if (!tree) { log << DbPrintLvl::Debug << "Could not find tree " << opt.option() << ", no TREE_MAX_VIRTUAL_SIZE will be set" << DbPrint::endmsg; return Success; @@ -734,7 +749,7 @@ DbStatus RootDatabase::setOption(const DbOption& opt) { return Error; } m_treeNameWithCache = opt.option(); - TTree* tr = (TTree*)m_file->Get(m_treeNameWithCache.c_str()); + TTree* tr = getTree( m_treeNameWithCache ); if (!tr) { log << DbPrintLvl::Debug << "Could not find tree " << m_treeNameWithCache << ", no TREE_CACHE will be set" << DbPrint::endmsg; return Success; @@ -1086,14 +1101,14 @@ DbStatus RootDatabase::fillBranchContainerTrees() RPageSource* -RootDatabase::getNTupleReader(std::string ntuple_name) +RootDatabase::getNTupleReader(const std::string& ntuple_name) { auto reader_entry = m_ntupleReaderMap.find(ntuple_name); if( reader_entry != m_ntupleReaderMap.end() ) { return reader_entry->second.get(); } const std::string file_name = m_file->GetName(); - auto native_reader = RPageSource::Create(string("RNT:")+ntuple_name, file_name); + auto native_reader = RPageSource::Create(ntuple_name, file_name); RPageSource *ps = native_reader.get(); ps->Attach(); if( m_rntReaderMetricsEnabled ) { @@ -1113,7 +1128,7 @@ RootDatabase::getNTupleWriter(std::string ntuple_name, bool create) DbPrint log("RootDatabase.getNTupleWriter"); log << DbPrintLvl::Warning << "Buffered writing doesn't work reliably in MT jobs yet, use at your own risk!" << DbPrint::endmsg; } - writer = RootAuxDynIO::getNTupleAuxDynWriter(m_file, string("RNT:")+ntuple_name, m_rntBufferedWriteEnabled, m_rntWriterMetricsEnabled); + writer = RootAuxDynIO::getNTupleAuxDynWriter(m_file, ntuple_name, m_rntBufferedWriteEnabled, m_rntWriterMetricsEnabled); } if( writer and create ) { // treat the create flag as an indication of a new container client and count them diff --git a/Database/APR/RootStorageSvc/src/RootDatabase.h b/Database/APR/RootStorageSvc/src/RootDatabase.h index 78bc0daf821259860890394f47c1962306c85c99..98010fb8a2b1b745051a04c7963ef2dc91edb4cb 100644 --- a/Database/APR/RootStorageSvc/src/RootDatabase.h +++ b/Database/APR/RootStorageSvc/src/RootDatabase.h @@ -149,6 +149,9 @@ namespace pool { /// Access to the actual implemented file TFile* file() { return m_file; } + /// Get TTree by name from the TFile + TTree* getTree(const std::string& name); + /// Access to the version string const std::string& fmtVersion() const { return m_version; } @@ -244,7 +247,7 @@ namespace pool { /// Execute Database Transaction action virtual DbStatus transAct(Transaction::Action action); - RPageSource* getNTupleReader(std::string ntuple_name); + RPageSource* getNTupleReader(const std::string& ntuple_name); // translate index value to row# for a given RNTuple uint64_t indexLookup(RPageSource *ps, uint64_t idx_val); diff --git a/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaPoolCnvSvc.h b/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaPoolCnvSvc.h index 12fbba75a240cd2614481bc2fca743e8a335e8b0..ead18ed3d8a83d7a6acee9b0f7f2bd29c29d6b86 100644 --- a/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaPoolCnvSvc.h +++ b/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaPoolCnvSvc.h @@ -207,11 +207,11 @@ private: // properties /// Default Storage Tech for containers (ROOTTREE, ROOTTREEINDEX, ROOTRNTUPLE) StringProperty m_storageTechProp{this,"StorageTechnology", "ROOTTREEINDEX"}; - /// PoolContainerPrefix, prefix for top level POOL container: default = "POOLContainer" + /// PoolContainerPrefix, prefix for top level POOL container StringProperty m_containerPrefixProp{this,"PoolContainerPrefix","CollectionTree"}; /// TopLevelContainerName, naming hint policy for top level POOL container: default = "<type>" StringProperty m_containerNameHintProp{this,"TopLevelContainerName",""}; - /// SubLevelBranchName, naming hint policy for POOL branching: default = "" (no branching) + /// SubLevelBranchName, naming hint policy for POOL branching: ("" = no branching) StringProperty m_branchNameHintProp{this,"SubLevelBranchName", "<type>/<key>"}; /// Output PoolAttributes, vector with names and values of technology specific attributes for POOL diff --git a/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaPoolConverter.cxx b/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaPoolConverter.cxx index 3e55ed2804bea14d0dccf267c8d9b92f31b4da1b..28dbd29d0dd9be1cb53fcabeeec449b4f318b1a9 100644 --- a/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaPoolConverter.cxx +++ b/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaPoolConverter.cxx @@ -175,71 +175,85 @@ Placement AthenaPoolConverter::setPlacementWithType(const std::string& tname, co m_athenaPoolCnvSvc->decodeOutputSpec(outputConnectionSpec, tech).ignore(); // Set DB and Container names placement.setFileName(outputConnectionSpec); + + std::string containerPrefix = m_containerPrefix; + std::string dhContainerPrefix = pool::ROOTRNTUPLE_StorageType.exactMatch(tech)? + APRDefaults::RNTupleNames::DataHeader : APRDefaults::TTreeNames::DataHeader; std::string containerName; - // Override streaming parameters from StreamTool if requested. - std::string containerPrefix = m_containerPrefix; - std::string dhContainerPrefix = "POOLContainer"; - // Get Technology from containerPrefix - std::size_t colonPos = containerPrefix.find(':'); - if (colonPos != std::string::npos) { - dhContainerPrefix = containerPrefix.substr(0, colonPos + 1) + dhContainerPrefix; - } - std::string containerNameHint = m_containerNameHint; - std::string branchNameHint = m_branchNameHint; - std::string containerFriendPostfix; - while (pos1 != std::string::npos) { - const std::string::size_type pos2 = output.find('=', pos1); - const std::string key = output.substr(pos1 + 1, pos2 - pos1 - 1); - const std::string::size_type pos3 = output.find(']', pos2); - const std::string value = output.substr(pos2 + 1, pos3 - pos2 - 1); - if (key == "OutputCollection") { - dhContainerPrefix = value; - } else if (key == "PoolContainerPrefix") { - containerPrefix = value; - } else if (key == "TopLevelContainerName") { - containerNameHint = value; - } else if (key == "SubLevelBranchName") { - branchNameHint = value; - } else if (key == "PoolContainerFriendPostfix") { - containerFriendPostfix = value; - } - pos1 = output.find('[', pos3); + + // Get Technology from containerPrefix + std::size_t colonPos = containerPrefix.find(':'); + if (colonPos != std::string::npos) { + dhContainerPrefix = containerPrefix.substr(0, colonPos + 1) + dhContainerPrefix; + } + + // Override streaming parameters from StreamTool if requested. + std::string containerNameHint = m_containerNameHint; + std::string branchNameHint = m_branchNameHint; + std::string containerFriendPostfix; + while (pos1 != std::string::npos) { + const std::string::size_type pos2 = output.find('=', pos1); + const std::string key = output.substr(pos1 + 1, pos2 - pos1 - 1); + const std::string::size_type pos3 = output.find(']', pos2); + const std::string value = output.substr(pos2 + 1, pos3 - pos2 - 1); + if (key == "OutputCollection") { + dhContainerPrefix = value; + } else if (key == "PoolContainerPrefix") { + containerPrefix = value; + } else if (key == "TopLevelContainerName") { + containerNameHint = value; + } else if (key == "SubLevelBranchName") { + branchNameHint = value; + } else if (key == "PoolContainerFriendPostfix") { + containerFriendPostfix = value; } - if (tname.compare(0, 14, "DataHeaderForm") == 0) { + pos1 = output.find('[', pos3); + } + + // --- Special types: DataHeader & Form + if( tname.compare(0, 10, "DataHeader") == 0 ) { + if( tname.compare(10, 4, "Form") == 0 ) { containerName = dhContainerPrefix + "Form" + "(" + tname + ")"; - } else if (tname.compare(0, 10, "DataHeader") == 0) { + } else { if (key[key.size() - 1] == '/') { containerName = dhContainerPrefix + "(" + key + tname + ")"; } else { containerName = dhContainerPrefix + "(" + tname + ")"; } - } else if (tname.compare(0, 13, "AttributeList") == 0) { - // Find the right storage type and name for EventTag values - if( pool::ROOTRNTUPLE_StorageType.exactMatch(tech) ) { - containerName = "ROOTRNTUPLE:" + std::string(APRDefaults::RNTupleNames::EventTag) + "(" + key + ")"; - } else { - // no indexing for TTree storage (MN:not sure why) - containerName = "ROOTTREE:" + std::string(APRDefaults::TTreeNames::EventTag) + "(" + key + ")"; - } + } + } + // AttributeList - writing attributes separately to EventTag container group + else if (tname.compare(0, 13, "AttributeList") == 0) { + // Find the right storage type and name for EventTag values + if( pool::ROOTRNTUPLE_StorageType.exactMatch(tech) ) { + containerName = std::string(APRDefaults::RNTupleNames::EventTag) + "(" + key + ")"; } else { - const std::string typeTok = "<type>", keyTok = "<key>"; - containerName = containerPrefix + containerFriendPostfix + containerNameHint; - if (!branchNameHint.empty()) { - containerName += "(" + branchNameHint + ")"; - } - const std::size_t pos1 = containerName.find(typeTok); - if (pos1 != std::string::npos) { - containerName.replace(pos1, typeTok.size(), tname); - } - const std::size_t pos2 = containerName.find(keyTok); - if (pos2 != std::string::npos) { - if (key.empty()) { - containerName.replace(pos2, keyTok.size(), tname); - } else { - containerName.replace(pos2, keyTok.size(), key); - } + // no indexing needed (nothing points to Tags) + // safe to set tech here - it will not be overwritten by decodeOutput + tech = pool::ROOTTREE_StorageType.type(); + containerName = std::string(APRDefaults::TTreeNames::EventTag) + "(" + key + ")"; + } + } + // all other object types + else { + const std::string typeTok = "<type>", keyTok = "<key>"; + containerName = containerPrefix + containerFriendPostfix + containerNameHint; + if (!branchNameHint.empty()) { + containerName += "(" + branchNameHint + ")"; + } + const std::size_t pos1 = containerName.find(typeTok); + if (pos1 != std::string::npos) { + containerName.replace(pos1, typeTok.size(), tname); + } + const std::size_t pos2 = containerName.find(keyTok); + if (pos2 != std::string::npos) { + if (key.empty()) { + containerName.replace(pos2, keyTok.size(), tname); + } else { + containerName.replace(pos2, keyTok.size(), key); } } + } m_athenaPoolCnvSvc->decodeOutputSpec(containerName, tech).ignore(); placement.setContainerName(containerName); placement.setTechnology(tech); diff --git a/Database/AthenaPOOL/EventSelectorAthenaPool/src/EventSelectorAthenaPool.h b/Database/AthenaPOOL/EventSelectorAthenaPool/src/EventSelectorAthenaPool.h index 4c6882fea3ae2987b2952fafc49edda888247737..f77f3dd712d0d594ea750316d06f920d7710fe5c 100644 --- a/Database/AthenaPOOL/EventSelectorAthenaPool/src/EventSelectorAthenaPool.h +++ b/Database/AthenaPOOL/EventSelectorAthenaPool/src/EventSelectorAthenaPool.h @@ -16,6 +16,7 @@ #include "GaudiKernel/ServiceHandle.h" #include "GaudiKernel/ToolHandle.h" #include "PersistentDataModel/Guid.h" +#include "POOLCore/APRDefaults.h" #include "AthenaKernel/IAthenaIPCTool.h" #include "AthenaKernel/IAthenaSelectorTool.h" @@ -184,8 +185,8 @@ private: // properties Gaudi::Property<bool> m_processMetadata{this, "ProcessMetadata", true, ""}; /// CollectionType, type of the collection: default = "ImplicitROOT". Gaudi::Property<std::string> m_collectionType{this, "CollectionType", "ImplicitROOT", ""}; - /// CollectionTree, prefix of the collection TTree: default = "POOLContainer_". - Gaudi::Property<std::string> m_collectionTree{this, "CollectionTree", "POOLContainer", ""}; + /// CollectionTree, prefix of the collection TTree: default = "POOLContainer". + Gaudi::Property<std::string> m_collectionTree{this, "CollectionTree", APRDefaults::TTreeNames::DataHeader, ""}; /// Connection, connection string. // TODO: check if really not used anywhere Gaudi::Property<std::string> m_connection{this, "Connection", "", ""}; diff --git a/Database/AthenaPOOL/PoolSvc/src/PoolSvc.cxx b/Database/AthenaPOOL/PoolSvc/src/PoolSvc.cxx index da501a6d10ea5fe4fec3d7023bb86d322f68d635..09cc9106fde83472e84e9d0da5ffca70e9e901bb 100644 --- a/Database/AthenaPOOL/PoolSvc/src/PoolSvc.cxx +++ b/Database/AthenaPOOL/PoolSvc/src/PoolSvc.cxx @@ -516,8 +516,16 @@ pool::ICollection* PoolSvc::createCollection(const std::string& collectionType, std::scoped_lock lock(m_pool_mut); collPtr = collFac->create(collDes, pool::ICollection::READ); } else { + // Try to open APR EventTags Collection in the input file - first as RootCollection, then as RNTCollection + std::scoped_lock lock(m_pool_mut); + std::string tree_error, rntuple_error; try { - std::scoped_lock lock(m_pool_mut); + collPtr = collFac->create(collDes, pool::ICollection::READ, &m_persistencySvcVec[contextId]->session()); + } catch (std::exception &e) { + tree_error = e.what(); + } + if( !collPtr ) try { + collDes.setType("RNTCollection"); collPtr = collFac->create(collDes, pool::ICollection::READ, &m_persistencySvcVec[contextId]->session()); } catch (std::exception &e) { if (insertFile) { @@ -528,8 +536,11 @@ pool::ICollection* PoolSvc::createCollection(const std::string& collectionType, } } } - throw; // bad file, rethrow + rntuple_error = e.what(); } + if( !collPtr ) throw pool::Exception( "Failed to open APR Collection as RootCollection or RNTCollection: " + + tree_error + " | " + rntuple_error, + "PoolSvc::createCollection", "PoolSvc" ); } if (insertFile && m_attemptCatalogPatch.value()) { std::unique_ptr<pool::IDatabase> dbH = getDbHandle(contextId, connection);