28 #include "TTreePerfStats.h"
29 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,33,0)
30 #include "Compression.h"
31 static int s_compressionLevel = ROOT::CompressionSettings(ROOT::kLZMA,6);
33 static int s_compressionLevel = 1;
39 using namespace Gaudi;
41 typedef const string&
CSTR;
43 static string s_empty;
44 static string s_local =
"<localDB>";
46 #ifdef __POOL_COMPATIBILITY
51 static bool match_wild(
const char *str,
const char *pat) {
55 static char table[256];
56 static bool first =
true;
60 for (
int i = 0;
i < 256; ++
i) table[
i] =
char(
i);
64 for (s = str, p = pat; *
s; ++
s, ++p) {
67 if (*s ==
'.')
goto starCheck;
72 do { ++pat; }
while (*pat ==
'*');
73 if (!*pat)
return true;
76 if ( *(table+*s) != *(table+*p) )
81 while (*p ==
'*') ++p;
85 if (!star)
return false;
104 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,33,0)
105 int res = 0,
level = ROOT::CompressionSettings(ROOT::kLZMA,6);
106 size_t idx = compression.find(
':');
107 if ( idx != string::npos ) {
108 string alg = compression.substr(0,idx);
109 ROOT::ECompressionAlgorithm alg_code = ROOT::kUseGlobalSetting;
110 if ( strcasecmp(alg.c_str(),
"ZLIB") == 0 )
111 alg_code = ROOT::kZLIB;
112 else if ( strcasecmp(alg.c_str(),
"LZMA") == 0 )
113 alg_code = ROOT::kLZMA;
115 throw runtime_error(
"ERROR: request to set unknown ROOT compression algorithm:"+alg);
116 res = ::sscanf(compression.c_str()+idx+1,
"%d",&
level);
118 s_compressionLevel = ROOT::CompressionSettings(alg_code,
level);
121 throw runtime_error(
"ERROR: request to set unknown ROOT compression level:"+compression.substr(idx+1));
123 else if ( 1==::sscanf(compression.c_str(),
"%d",&
level) ) {
124 s_compressionLevel =
level;
127 throw runtime_error(
"ERROR: request to set unknown ROOT compression mechanism:"+compression);
129 if ( !compression.empty() ) {}
136 return s_compressionLevel;
169 :
IDataConnection(owner,fname), m_setup(setup), m_statistics(0), m_tool(0)
172 if ( fname.length() == 36 && fname[8]==
'-'&&fname[13]==
'-'&&fname[18]==
'-'&&fname[23]==
'-' ) {
202 Clients::const_iterator
i=
m_clients.find(client);
215 if ( !statisticsFile.empty() )
226 m_statistics =
new TTreePerfStats((section+
"_ioperf").c_str(),t);
241 #ifdef __POOL_COMPATIBILITY
242 else if (
m_file->Get(
"##Links") != 0 )
260 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,33,0)
284 if ( !need_fid && fid !=
m_fid ) {
289 msgSvc() << MSG::DEBUG <<
"Using FID " <<
m_fid <<
" from params table...." <<
endmsg
307 m_file = TFile::Open(
m_pfn.c_str(),
"CREATE",
"Root event data",compress);
308 m_refs =
new TTree(
"Refs",
"Root reference data");
318 m_file = TFile::Open(
m_pfn.c_str(),
"RECREATE",
"Root event data",compress);
320 m_refs =
new TTree(
"Refs",
"Root reference data");
329 m_file = TFile::Open(
m_pfn.c_str(),
"UPDATE",
"Root event data",compress);
336 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,33,0)
345 TDirectory::TContext ctxt(
m_file);
346 m_refs =
new TTree(
"Refs",
"Root reference data");
362 if ( !
m_file->IsZombie() ) {
363 if (
m_file->IsWritable() ) {
365 TDirectory::TContext ctxt(
m_file);
372 if ( (*i).second->Write() < 0 )
badWriteError(
"Write section:"+(*i).first);
373 msgSvc() <<
"Disconnect section " << (*i).first <<
" " << (*i).second->GetName() <<
endmsg;
395 t = (TTree*)
m_file->Get(section.c_str());
396 if ( !t && create ) {
397 TDirectory::TContext ctxt(
m_file);
398 t =
new TTree(section.c_str(),
"Root data for Gaudi");
408 t->SetCacheSize(cacheSize);
409 t->SetCacheLearnEntries(learnEntries);
412 msg <<
"Tree:" << section <<
"Setting up tree cache:" << cacheSize <<
endmsg;
417 msg <<
"Tree:" << section <<
" Setting up tree cache:" << cacheSize <<
" Add all branches." <<
endmsg;
418 msg <<
"Tree:" << section <<
" Learn for " << learnEntries <<
" entries." <<
endmsg;
420 if ( cB.size()==0 && vB.size()== 0 ) {
421 msg <<
"Adding (default) all branches to tree cache." <<
endmsg;
422 t->AddBranchToCache(
"*",kTRUE);
424 if ( cB.size()==1 && cB[0]==
"*" ) {
425 msg <<
"Adding all branches to tree cache according to option \"CacheBranches\"." <<
endmsg;
426 t->AddBranchToCache(
"*",kTRUE);
429 StringVec::const_iterator
i;
430 for(TIter it(t->GetListOfBranches()); it.Next(); ) {
431 const char*
n = ((TNamed*)(*it))->GetName();
432 bool add =
false, veto =
false;
433 for(i=cB.begin(); i != cB.end();++
i) {
434 if ( !match_wild(n,(*i).c_str()) )
continue;
438 for(i=vB.begin(); !add && i!=vB.end();++
i) {
439 if ( !match_wild(n,(*i).c_str()) )
continue;
443 if ( add && !veto ) {
444 msg <<
"Add " << n <<
" to branch cache." <<
endmsg;
445 t->AddBranchToCache(n,kTRUE);
448 msg <<
"Do not cache branch " << n <<
endmsg;
462 string n = branch_name+
".";
463 for(
int i=0, m=n.length()-1;
i<m; ++
i)
if ( !isalnum(n[
i]) ) n[i]=
'_';
465 TBranch* b = t->GetBranch(n.c_str());
466 if ( !b && cl &&
m_file->IsWritable() ) {
467 b = t->Branch(n.c_str(),cl->GetName(),(
void*)(ptr ? &ptr : 0),buff_siz,split_lvl);
470 b = t->GetBranch(branch_name.c_str());
473 b->SetAutoDelete(kFALSE);
481 StringVec::iterator ip;
483 if( (*ip) == p )
return cnt;
491 if ( (which>=0) && (
size_t(which)<
m_dbs.size()) ) {
504 pair<int,unsigned long>
506 DataObjectPush push(pObj);
507 return save(section,cnt,cl,pObj,buff_siz,split_lvl,fill);
511 pair<int,unsigned long>
514 TBranch* b =
getBranch(section, cnt, cl, (
void*)(pObj ? &pObj : 0),buff_siz,split_lvl);
516 Long64_t
evt = b->GetEntries();
519 if ( fill_missing ) {
520 Long64_t num,
nevt = b->GetTree()->GetEntries();
524 while( num > 0 ) { b->Fill(); --num; }
526 <<
" / Tree: " << nevt <<
" / Branch: " << b->GetEntries()+1
527 <<
" NULL entries to:" << cnt <<
endmsg;
528 evt = b->GetEntries();
531 b->SetAddress(&pObj);
532 return make_pair(b->Fill(),(
unsigned long)evt);
534 else if ( 0 != pObj ) {
537 return make_pair(-1,~0);
544 TClass* cl = gROOT->GetClass(b->GetClassName(),kTRUE);
549 DataObjectPush push(pObj);
550 b->SetAddress(&pObj);
552 TTree* t = b->GetTree();
553 if ( Long64_t(entry) != t->GetReadEntry() ) {
554 t->LoadTree(Long64_t(entry));
557 nb = b->GetEntry(entry);
559 if (
msgSvc().isActive() ) {
560 msgSvc() <<
"Load [" << entry <<
"] --> " << section
561 <<
":" << cnt <<
" " << nb <<
" bytes."
565 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,33,0)
572 else if ( nb == 0 && pObj->
clID() == CLID_DataObject) {
573 TFile* f = b->GetFile();
574 int vsn = f->GetVersion();
580 else if ( vsn>1000000 && (vsn%1000000)<52400 ) {
602 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,33,0)
617 pair<const RootRef*,const RootDataConnection::ContainerSection*>
621 MergeSections::const_iterator i=
m_mergeSects.find(container);
625 for(ContainerSections::const_iterator j=s.begin(); j != s.end(); ++j,++cnt) {
631 <<
" [" << entry <<
"]" <<
endmsg
640 <<
" [" << entry <<
"]" <<
endmsg
654 int cdb=-1, ccnt=-1, clnk=-1;
655 StringVec::iterator idb, icnt, ilnk;
661 for(cdb=0,idb=
m_dbs.begin(); idb!=
m_dbs.end();++idb,++cdb)
662 if( (*idb) == db )
break;
663 if ( idb ==
m_dbs.end() ) {
668 if ( !cnt.empty() ) {
669 for(ccnt=0,icnt=
m_conts.begin(); icnt!=
m_conts.end();++icnt,++ccnt)
670 if( (*icnt) == cnt )
break;
676 if ( !name.empty() ) {
677 for(clnk=0,ilnk=
m_links.begin(); ilnk!=
m_links.end();++ilnk,++clnk)
678 if( (*ilnk) ==
name )
break;
void addClient(const IInterface *client)
Add new client to this data source.
void addRef()
Increase reference count.
bool lookupClient(const IInterface *client) const
Lookup client for this data source.
virtual const std::string * par() const =0
Retrieve String parameters.
MergeSections m_mergeSects
Database section map for merged files.
Definition of the MsgStream class used to transmit messages.
const std::string & fid() const
Access file id.
std::vector< ContainerSection > ContainerSections
Definition of container sections to handle merged files.
std::string m_name
Connection name/identifier.
IoType
I/O Connection types.
std::pair< int, unsigned long > saveObj(const std::string §ion, const std::string &cnt, TClass *cl, DataObject *pObj, int buff_siz, int split_lvl, bool fill_missing=false)
Save object of a given class to section and container.
unsigned long getCode() const
Get the status code by value.
void saveStatistics(const std::string &statisticsFile)
Save TTree access statistics if required.
const std::string & getDb(int which) const
Access database/file name from saved index.
std::string m_fid
File ID of the connection.
bool isSuccess() const
Test for a status code of SUCCESS.
int loadObj(const std::string §ion, const std::string &cnt, unsigned long entry, DataObject *&pObj)
Load object.
TFile * m_file
Reference to ROOT file.
int refCount
Object refrfence count.
static int compression()
Access to global compression level.
Clients m_clients
Client list.
int length
The length of the section.
TTree * getSection(const std::string §, bool create=false)
Access TTree section from section name. The section is created if required.
void release()
Decrease reference count.
int start
The start entry of the section.
IIncidentSvc * m_incidentSvc
Reference to incident service.
size_t removeClient(const IInterface *client)
Remove client from this data source.
bool isActive() const
Accessor: is MsgStream active.
GAUDI_API void fill(AIDA::IHistogram1D *histo, const double value, const double weight=1.0)
simple function to fill AIDA::IHistogram1D objects
virtual const name_type & name() const =0
Name of the directory (or key)
std::vector< std::string > StringVec
Type definition for string maps.
void setMessageSvc(MsgStream *m)
Set message service reference.
virtual long svcType() const =0
Retrieve service type.
int cacheSize
RootCnvSvc Property: Root data cache size.
const std::string & pfn() const
Access physical file name.
int loadRefs(const std::string §ion, const std::string &cnt, unsigned long entry, RootObjectRefs &refs)
Load references object.
Persistent reference object containing all leafs and links corresponding to a Gaudi DataObject...
StringVec m_links
Map containing internal links names.
ParamMap m_params
Parameter map for file parameters.
std::string loadSection
RootCnvSvc Property: Root data cache size.
const long POOL_ROOTKEY_StorageType
StringVec m_mergeFIDs
Map containing merge FIDs.
std::string m_pfn
Physical file name of the connection.
int dbase
Data members to define object location in the persistent world.
Persistent reference object.
virtual void fireIncident(const Incident &incident)=0
Fire an Incident.
virtual const CLID & clID() const
Retrieve reference to class definition structure.
virtual const CLID & clID() const =0
Retrieve class information from link.
const std::string & name() const
Connection name.
virtual ~RootDataConnection()
Standard destructor.
int learnEntries
RootCnvSvc Property: ROOT cache learn entries.
This class is used for returning status codes from appropriate routines.
Definition of the basic interface.
TBranch * getBranch(const std::string §ion, const std::string &branch_name)
Access data branch by name: Get existing branch in read only mode.
void makeRef(IRegistry *pA, RootRef &ref)
Create reference object from registry entry.
StringVec m_conts
Map containing external container names.
const std::string & empty() const
Empty string reference.
Sections m_sections
Tree sections in TFile.
std::pair< const RootRef *, const ContainerSection * > getMergeSection(const std::string &container, int entry) const
Access link section for single container and entry.
class Gaudi::RootDataConnection::Tool * m_tool
StringVec cacheBranches
Vector of strings with branches to be cached for input files.
The IRegistry represents the entry door to the environment any data object residing in a transient da...
const long ROOT_StorageType
def which
Locates an executable in the executables path ($PATH) and returns the full path to it...
const long POOL_ROOT_StorageType
TTreePerfStats * m_statistics
I/O read statistics from TTree.
RootConnectionSetup()
Standard constructor.
Tool * makeTool()
Create file access tool to encapsulate POOL compatibiliy.
virtual IOpaqueAddress * address() const =0
Retrieve opaque storage address.
StringVec vetoBranches
Vector of strings with branches to NOT be cached for input files.
std::pair< int, unsigned long > save(const std::string §ion, const std::string &cnt, TClass *cl, void *pObj, int buff_siz, int split_lvl, bool fill_missing=false)
Save object of a given class to section and container.
virtual unsigned long release()=0
Release Interface instance.
ABC describing basic data connection.
int makeLink(const std::string &p)
Convert path string to path index.
IIncidentSvc * incidentSvc() const
Retrieve incident service.
const long POOL_ROOTTREE_StorageType
virtual StatusCode disconnect()
Release data stream and release implementation dependent resources.
virtual StatusCode connectRead()
Open data stream in read mode.
LinkSections m_linkSects
Database link sections.
RootDataConnection(const IInterface *own, const std::string &nam, RootConnectionSetup *setup)
Standard constructor.
void resetAge()
Reset age.
Base class for all Incidents (computing events).
MsgStream & msgSvc() const
Allow access to printer service.
RootConnectionSetup * m_setup
Reference to the setup structure.
virtual StatusCode connectWrite(IoType typ)
Open data stream in write mode.
static long setCompression(const std::string &compression)
Set the global compression level.
virtual unsigned long addRef()=0
Increment the reference count of Interface instance.
Opaque address interface definition.
StringVec m_dbs
Map containing external database file names (fids)
This is a number of static methods for bootstrapping the Gaudi framework.
void setIncidentSvc(IIncidentSvc *m)
Set incident service reference.
void enableStatistics(const std::string §ion)
Enable TTreePerStats.
A DataObject is the base class of any identifiable object on any data store.
MsgStream * m_msgSvc
Reference to message service.
TTree * m_refs
Pointer to the reference tree.
virtual ~RootConnectionSetup()
Standard destructor.
Internal helper class, which described a TBranch section in a ROOT file.
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
const std::string CorruptedInputFile
the input file has shown a corruption
The interface implemented by the IncidentSvc service.
void badWriteError(const std::string &msg) const
Error handler when bad write statements occur.