Go to the documentation of this file.
37 #if ROOT_VERSION_CODE >= ROOT_VERSION( 5, 33, 0 )
38 # include "Compression.h"
39 static int s_compressionLevel = ROOT::CompressionSettings( ROOT::kLZMA, 4 );
41 static int s_compressionLevel = 1;
49 using namespace Gaudi;
51 typedef const string&
CSTR;
53 static const string s_empty;
54 static const string s_local =
"<localDB>";
56 #ifdef __POOL_COMPATIBILITY
69 const char*
name()
const override {
return "RootDataConnection"; }
76 return "ROOT_READ_ERROR";
78 return "ROOT_OPEN_ERROR";
85 static bool match_wild(
const char* str,
const char* pat ) {
89 static const auto table = init_table();
93 for (
s = str, p = pat; *
s; ++
s, ++p ) {
96 if ( *
s ==
'.' )
goto starCheck;
101 do { ++pat; }
while ( *pat ==
'*' );
102 if ( !*pat )
return true;
105 if ( table[*
s] != table[*p] )
goto starCheck;
109 while ( *p ==
'*' ) ++p;
113 if ( !star )
return false;
123 #if ROOT_VERSION_CODE >= ROOT_VERSION( 5, 33, 0 )
124 int res = 0,
level = ROOT::CompressionSettings( ROOT::kLZMA, 6 );
125 auto idx = compression.find(
':' );
126 if ( idx != string::npos ) {
127 auto alg = compression.substr( 0, idx );
128 ROOT::ECompressionAlgorithm alg_code = ROOT::kUseGlobalSetting;
129 if (
alg.size() == 4 && strncasecmp(
alg.data(),
"ZLIB", 4 ) == 0 )
130 alg_code = ROOT::kZLIB;
131 else if (
alg.size() == 4 && strncasecmp(
alg.data(),
"LZMA", 4 ) == 0 )
132 alg_code = ROOT::kLZMA;
133 else if (
alg.size() == 3 && strncasecmp(
alg.data(),
"LZ4", 3 ) == 0 )
134 alg_code = ROOT::kLZ4;
135 # if ROOT_VERSION_CODE >= ROOT_VERSION( 6, 20, 0 )
136 else if (
alg.size() == 4 && strncasecmp(
alg.data(),
"ZSTD", 4 ) == 0 )
137 alg_code = ROOT::kZSTD;
144 s_compressionLevel = ROOT::CompressionSettings( alg_code,
level );
147 throw runtime_error(
"ERROR: request to set unknown ROOT compression level:" +
151 s_compressionLevel =
level;
156 if ( !compression.empty() ) {}
176 if ( fname.size() == 36 && fname[8] ==
'-' && fname[13] ==
'-' && fname[18] ==
'-' && fname[23] ==
'-' ) {
178 m_name.append( fname.data(), fname.size() );
233 #ifdef __POOL_COMPATIBILITY
257 #if ROOT_VERSION_CODE >= ROOT_VERSION( 5, 33, 0 )
269 if ( elem.first ==
"FID" ) {
271 if ( elem.second !=
m_fid ) {
294 if (
m_setup->produceReproducibleFiles ) spec +=
"?reproducible";
298 m_file.
reset( TFile::Open( spec.
c_str(),
"CREATE",
"Root event data", compress ) );
299 m_refs =
new TTree(
"Refs",
"Root reference data" );
307 m_file.
reset( TFile::Open( spec.
c_str(),
"RECREATE",
"Root event data", compress ) );
309 m_refs =
new TTree(
"Refs",
"Root reference data" );
316 m_file.
reset( TFile::Open( spec.
c_str(),
"UPDATE",
"Root event data", compress ) );
323 #if ROOT_VERSION_CODE >= ROOT_VERSION( 5, 33, 0 )
330 TDirectory::TContext ctxt(
m_file.
get() );
331 m_refs =
new TTree(
"Refs",
"Root reference data" );
347 if ( !
m_file->IsZombie() ) {
348 if (
m_file->IsWritable() ) {
350 TDirectory::TContext ctxt(
m_file.
get() );
357 if ( i.second->Write() < 0 )
badWriteError(
"Write section:" + i.first );
358 msgSvc() <<
"Disconnect section " << i.first <<
" " << i.second->GetName() <<
endmsg;
382 if ( !
t && create ) {
383 TDirectory::TContext ctxt(
m_file.
get() );
387 int cacheSize =
m_setup->cacheSize;
391 if ( section ==
m_setup->loadSection && cacheSize > -2 ) {
393 int learnEntries =
m_setup->learnEntries;
394 t->SetCacheSize( cacheSize );
395 t->SetCacheLearnEntries( learnEntries );
398 msg <<
"Tree:" << section <<
"Setting up tree cache:" << cacheSize <<
endmsg;
402 msg <<
"Tree:" << section <<
" Setting up tree cache:" << cacheSize <<
" Add all branches." <<
endmsg;
403 msg <<
"Tree:" << section <<
" Learn for " << learnEntries <<
" entries." <<
endmsg;
406 msg <<
"Adding (default) all branches to tree cache." <<
endmsg;
407 t->AddBranchToCache(
"*", kTRUE );
409 if ( cB.
size() == 1 && cB[0] ==
"*" ) {
410 msg <<
"Adding all branches to tree cache according to option \"CacheBranches\"." <<
endmsg;
411 t->AddBranchToCache(
"*", kTRUE );
413 for ( TIter it(
t->GetListOfBranches() ); it.Next(); ) {
414 const char*
n = ( (TNamed*)( *it ) )->GetName();
415 bool add =
false, veto =
false;
416 for (
const auto& i : cB ) {
417 if ( !match_wild(
n, ( i ).c_str() ) )
continue;
422 if ( !match_wild(
n, ( *i ).c_str() ) )
continue;
426 if (
add && !veto ) {
427 msg <<
"Add " <<
n <<
" to branch cache." <<
endmsg;
428 t->AddBranchToCache(
n, kTRUE );
443 TBranch* RootDataConnection::getBranch( std::string_view section, std::string_view branch_name, TClass* cl,
void* ptr,
444 int buff_siz,
int split_lvl ) {
450 TBranch* b =
t->GetBranch(
n.c_str() );
451 if ( !b && cl &&
m_file->IsWritable() ) {
452 b =
t->Branch(
n.c_str(), cl->GetName(), (
void*)( ptr ? &ptr :
nullptr ), buff_siz, split_lvl );
455 if ( b ) b->SetAutoDelete( kFALSE );
481 DataObject* pObj,
int minBufferSize,
int maxBufferSize,
482 int approxEventsPerBasket,
int split_lvl,
bool fill ) {
483 DataObjectPush push( pObj );
484 return save( section, cnt, cl, pObj, minBufferSize, maxBufferSize, approxEventsPerBasket, split_lvl,
fill );
489 void* pObj,
int minBufferSize,
int maxBufferSize,
490 int approxEventsPerBasket,
int split_lvl,
bool fill_missing ) {
492 TBranch* b =
getBranch( section, cnt, cl, pObj ? &pObj :
nullptr, minBufferSize, split_lvl );
494 Long64_t
evt = b->GetEntries();
497 bool set_buffer_size = (
evt == 0 );
498 if ( fill_missing ) {
499 Long64_t num, nevt = b->GetTree()->GetEntries();
501 set_buffer_size =
true;
502 b->SetAddress(
nullptr );
509 <<
" / Branch: " << b->GetEntries() + 1 <<
" NULL entries to:" << cnt <<
endmsg;
510 evt = b->GetEntries();
513 if ( set_buffer_size ) {
514 auto dummy_file = make_unique<TMemFile>(
"dummy.root",
"CREATE" );
515 auto dummy_tree = make_unique<TTree>(
"DummyTree",
"DummyTree", split_lvl, dummy_file->GetDirectory(
"/" ) );
516 TBranch* dummy_branch = dummy_tree->Branch(
"DummyBranch", cl->GetName(), &pObj, minBufferSize, split_lvl );
517 Int_t nWritten = dummy_branch->Fill();
518 if ( nWritten < 0 )
return { nWritten,
evt };
519 Int_t newBasketSize = nWritten * approxEventsPerBasket;
524 b->SetBasketSize(
std::min( maxBufferSize,
std::max( minBufferSize, newBasketSize ) ) );
527 b->SetAddress( &pObj );
528 return { b->Fill(),
evt };
539 TClass* cl = gROOT->GetClass( b->GetClassName(), kTRUE );
544 DataObjectPush push( pObj );
545 b->SetAddress( &pObj );
546 if ( section ==
m_setup->loadSection ) {
547 TTree*
t = b->GetTree();
548 if ( Long64_t( entry ) !=
t->GetReadEntry() ) {
t->LoadTree( Long64_t( entry ) ); }
550 nb = b->GetEntry( entry );
552 if (
msgSvc().isActive() ) {
553 msgSvc() <<
"Load [" << entry <<
"] --> " << section <<
":" << cnt <<
" " << nb <<
" bytes." <<
endmsg;
556 #if ROOT_VERSION_CODE >= ROOT_VERSION( 5, 33, 0 )
560 }
else if ( nb == 0 && pObj->
clID() == CLID_DataObject ) {
561 TFile* f = b->GetFile();
562 int vsn = f->GetVersion();
567 }
else if ( vsn > 1000000 && ( vsn % 1000000 ) < 52400 ) {
587 int nbytes =
m_tool->loadRefs( section, cnt, entry, refs );
588 #if ROOT_VERSION_CODE >= ROOT_VERSION( 5, 33, 0 )
611 if ( entry >=
c.start && entry < (
c.start +
c.length ) ) {
613 if (
msgSvc().isActive() ) {
622 msgSvc() <<
MSG::DEBUG <<
"Return INVALID MergeSection for:" << container <<
" [" << entry <<
"]" <<
endmsg
624 return {
nullptr,
nullptr };
635 std::string_view cnt,
int entry,
RootRef&
ref ) {
636 auto db = ( dbase ==
m_fid ? std::string_view{ s_local } : dbase );
647 if ( !cnt.empty() ) {
661 ref.container = ccnt;
const std::string & name() const
Connection name.
size_t removeClient(const IInterface *client)
Remove client from this data source.
Clients m_clients
Client list.
void enableStatistics(std::string_view section)
Enable TTreePerStats.
virtual const std::string * par() const =0
Retrieve String parameters.
void setMessageSvc(MsgStream *m)
Set message service reference.
static const Category & default_category() noexcept
Default Gaudi StatusCode category.
StatusCode disconnect() override
Release data stream and release implementation dependent resources.
void badWriteError(std::string_view msg) const
Error handler when bad write statements occur.
virtual long svcType() const =0
Retrieve service type.
void resetAge()
Reset age.
StatusCode connectRead() override
Open data stream in read mode.
std::unique_ptr< TFile > m_file
Reference to ROOT file.
std::pair< int, unsigned long > saveObj(std::string_view section, std::string_view cnt, TClass *cl, DataObject *pObj, int minBufferSize, int maxBufferSize, int approxEventsPerBasket, int split_lvl, bool fill_missing=false)
Save object of a given class to section and container.
ParamMap m_params
Parameter map for file parameters.
unsigned long code_t
type of StatusCode value
virtual void fireIncident(const Incident &incident)=0
Fire an Incident.
StringVec m_dbs
Map containing external database file names (fids)
LinkSections m_linkSects
Database link sections.
virtual const name_type & name() const =0
Name of the directory (or key)
const std::string & getDb(int which) const
Access database/file name from saved index.
StringVec m_mergeFIDs
Map containing merge FIDs.
std::shared_ptr< RootConnectionSetup > m_setup
Reference to the setup structure.
double * begin(CLHEP::HepVector &v)
const long POOL_ROOT_StorageType
MergeSections m_mergeSects
Database section map for merged files.
const long POOL_ROOTKEY_StorageType
void setIncidentSvc(IIncidentSvc *m)
Set incident service reference.
virtual const CLID & clID() const =0
Retrieve class information from link.
std::unique_ptr< TTreePerfStats > m_statistics
I/O read statistics from TTree.
std::string m_name
Connection name/identifier.
static StatusCode setCompression(std::string_view compression)
Set the global compression level.
IoType
I/O Connection types.
bool lookupClient(const IInterface *client) const
Lookup client for this data source.
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
void makeRef(const IRegistry &pA, RootRef &ref)
Create reference object from registry entry.
const long ROOT_StorageType
std::unique_ptr< Tool > m_tool
StringVec m_conts
Map containing external container names.
std::string m_fid
File ID of the connection.
Header file for std:chrono::duration-based Counters.
const StatusCode & ignore() const
Allow discarding a StatusCode without warning.
int makeLink(std::string_view p)
Convert path string to path index.
virtual IOpaqueAddress * address() const =0
Retrieve opaque storage address.
T emplace_back(T... args)
void saveStatistics(std::string_view statisticsFile)
Save TTree access statistics if required.
constexpr static const auto SUCCESS
int loadRefs(std::string_view section, std::string_view cnt, unsigned long entry, RootObjectRefs &refs)
Load references object.
const long POOL_ROOTTREE_StorageType
std::pair< int, unsigned long > save(std::string_view section, std::string_view cnt, TClass *cl, void *pObj, int minBufferSize, int maxBufferSize, int approxEventsPerBasket, int split_lvl, bool fill_missing=false)
Save object of a given class to section and container.
#define STATUSCODE_ENUM_IMPL(...)
Assign a category to the StatusCode enum declared with STATUSCODE_ENUM_DECL( ENUM )
TTree * getSection(std::string_view sect, bool create=false)
Access TTree section from section name. The section is created if required.
RootDataConnection(const IInterface *own, std::string_view nam, std::shared_ptr< RootConnectionSetup > setup)
Standard constructor.
std::pair< const RootRef *, const ContainerSection * > getMergeSection(std::string_view container, int entry) const
Access link section for single container and entry.
const std::string & fid() const
Access file id.
StringVec m_links
Map containing internal links names.
GAUDI_API void fill(AIDA::IHistogram1D *histo, const double value, const double weight=1.0)
simple function to fill AIDA::IHistogram1D objects
int loadObj(std::string_view section, std::string_view cnt, unsigned long entry, DataObject *&pObj)
Load object.
std::string m_pfn
Physical file name of the connection.
const std::string & pfn() const
Access physical file name.
void addClient(const IInterface *client)
Add new client to this data source.
Tool * makeTool()
Create file access tool to encapsulate POOL compatibiliy.
constexpr static const auto FAILURE
const std::string & empty() const
Empty string reference.
Sections m_sections
Tree sections in TFile.
TBranch * getBranch(std::string_view section, std::string_view branch_name)
Access data branch by name: Get existing branch in read only mode.
virtual const CLID & clID() const
Retrieve reference to class definition structure.
static int compression()
Access to global compression level.
MsgStream & msgSvc() const
Allow access to printer service.
StatusCode connectWrite(IoType typ) override
Open data stream in write mode.
TTree * m_refs
Pointer to the reference tree.
virtual std::string message(code_t code) const
Description for code within this category.