28 #include "Compression.h"
29 #include "TTreePerfStats.h"
34 using namespace Gaudi;
36 typedef const string&
CSTR;
38 static string s_empty;
39 static string s_local =
"<localDB>";
41 #ifdef __POOL_COMPATIBILITY
46 static int s_compressionLevel = ROOT::CompressionSettings(ROOT::kLZMA,6);
48 static bool match_wild(
const char *str,
const char *pat) {
52 static char table[256];
53 static bool first =
true;
57 for (
int i = 0;
i < 256; ++
i) table[
i] =
char(
i);
61 for (s = str, p = pat; *
s; ++
s, ++p) {
64 if (*s ==
'.')
goto starCheck;
69 do { ++pat; }
while (*pat ==
'*');
70 if (!*pat)
return true;
73 if ( *(table+*s) != *(table+*p) )
78 while (*p ==
'*') ++p;
82 if (!star)
return false;
101 int res = 0,
level = ROOT::CompressionSettings(ROOT::kLZMA,6);
102 size_t idx = compression.find(
':');
103 if ( idx != string::npos ) {
104 string alg = compression.substr(0,idx);
105 ROOT::ECompressionAlgorithm alg_code = ROOT::kUseGlobalSetting;
106 if ( strcasecmp(alg.c_str(),
"ZLIB") == 0 )
107 alg_code = ROOT::kZLIB;
108 else if ( strcasecmp(alg.c_str(),
"LZMA") == 0 )
109 alg_code = ROOT::kLZMA;
111 throw runtime_error(
"ERROR: request to set unknown ROOT compression algorithm:"+alg);
112 res = ::sscanf(compression.c_str()+idx+1,
"%d",&
level);
114 s_compressionLevel = ROOT::CompressionSettings(alg_code,
level);
117 throw runtime_error(
"ERROR: request to set unknown ROOT compression level:"+compression.substr(idx+1));
119 else if ( 1==::sscanf(compression.c_str(),
"%d",&
level) ) {
120 s_compressionLevel =
level;
123 throw runtime_error(
"ERROR: request to set unknown ROOT compression mechanism:"+compression);
128 return s_compressionLevel;
161 :
IDataConnection(owner,fname), m_setup(setup), m_statistics(0), m_tool(0)
164 if ( fname.length() == 36 && fname[8]==
'-'&&fname[13]==
'-'&&fname[18]==
'-'&&fname[23]==
'-' ) {
194 Clients::const_iterator
i=
m_clients.find(client);
207 if ( !statisticsFile.empty() )
218 m_statistics =
new TTreePerfStats((section+
"_ioperf").c_str(),t);
233 #ifdef __POOL_COMPATIBILITY
234 else if (
m_file->Get(
"##Links") != 0 )
274 if ( !need_fid && fid !=
m_fid ) {
279 msgSvc() << MSG::DEBUG <<
"Using FID " <<
m_fid <<
" from params table...." <<
endmsg
297 m_file = TFile::Open(
m_pfn.c_str(),
"CREATE",
"Root event data",compress);
298 m_refs =
new TTree(
"Refs",
"Root reference data");
308 m_file = TFile::Open(
m_pfn.c_str(),
"RECREATE",
"Root event data",compress);
310 m_refs =
new TTree(
"Refs",
"Root reference data");
319 m_file = TFile::Open(
m_pfn.c_str(),
"UPDATE",
"Root event data",compress);
333 TDirectory::TContext ctxt(
m_file);
334 m_refs =
new TTree(
"Refs",
"Root reference data");
350 if ( !
m_file->IsZombie() ) {
351 if (
m_file->IsWritable() ) {
353 TDirectory::TContext ctxt(
m_file);
360 if ( (*i).second->Write() < 0 )
badWriteError(
"Write section:"+(*i).first);
361 msgSvc() <<
"Disconnect section " << (*i).first <<
" " << (*i).second->GetName() <<
endmsg;
383 t = (TTree*)
m_file->Get(section.c_str());
384 if ( !t && create ) {
385 TDirectory::TContext ctxt(
m_file);
386 t =
new TTree(section.c_str(),
"Root data for Gaudi");
396 t->SetCacheSize(cacheSize);
397 t->SetCacheLearnEntries(learnEntries);
400 msg <<
"Tree:" << section <<
"Setting up tree cache:" << cacheSize <<
endmsg;
405 msg <<
"Tree:" << section <<
" Setting up tree cache:" << cacheSize <<
" Add all branches." <<
endmsg;
406 msg <<
"Tree:" << section <<
" Learn for " << learnEntries <<
" entries." <<
endmsg;
408 if ( cB.size()==0 && vB.size()== 0 ) {
409 msg <<
"Adding (default) all branches to tree cache." <<
endmsg;
410 t->AddBranchToCache(
"*",kTRUE);
412 if ( cB.size()==1 && cB[0]==
"*" ) {
413 msg <<
"Adding all branches to tree cache according to option \"CacheBranches\"." <<
endmsg;
414 t->AddBranchToCache(
"*",kTRUE);
417 StringVec::const_iterator
i;
418 for(TIter it(t->GetListOfBranches()); it.Next(); ) {
419 const char*
n = ((TNamed*)(*it))->GetName();
420 bool add =
false, veto =
false;
421 for(i=cB.begin(); i != cB.end();++
i) {
422 if ( !match_wild(n,(*i).c_str()) )
continue;
426 for(i=vB.begin(); !add && i!=vB.end();++
i) {
427 if ( !match_wild(n,(*i).c_str()) )
continue;
431 if ( add && !veto ) {
432 msg <<
"Add " << n <<
" to branch cache." <<
endmsg;
433 t->AddBranchToCache(n,kTRUE);
436 msg <<
"Do not cache branch " << n <<
endmsg;
450 string n = branch_name+
".";
451 for(
int i=0, m=n.length()-1;
i<m; ++
i)
if ( !isalnum(n[
i]) ) n[i]=
'_';
453 TBranch* b = t->GetBranch(n.c_str());
454 if ( !b && cl &&
m_file->IsWritable() ) {
455 b = t->Branch(n.c_str(),cl->GetName(),(
void*)(ptr ? &ptr : 0),buff_siz,split_lvl);
458 b = t->GetBranch(branch_name.c_str());
461 b->SetAutoDelete(kFALSE);
469 StringVec::iterator ip;
471 if( (*ip) == p )
return cnt;
479 if ( (which>=0) && (
size_t(which)<
m_dbs.size()) ) {
492 pair<int,unsigned long>
494 DataObjectPush push(pObj);
495 return save(section,cnt,cl,pObj,buff_siz,split_lvl,fill);
499 pair<int,unsigned long>
502 TBranch* b =
getBranch(section, cnt, cl, (
void*)(pObj ? &pObj : 0),buff_siz,split_lvl);
504 Long64_t
evt = b->GetEntries();
507 if ( fill_missing ) {
508 Long64_t num,
nevt = b->GetTree()->GetEntries();
512 while( num > 0 ) { b->Fill(); --num; }
514 <<
" / Tree: " << nevt <<
" / Branch: " << b->GetEntries()+1
515 <<
" NULL entries to:" << cnt <<
endmsg;
516 evt = b->GetEntries();
519 b->SetAddress(&pObj);
520 return make_pair(b->Fill(),(
unsigned long)evt);
522 else if ( 0 != pObj ) {
525 return make_pair(-1,~0);
532 TClass* cl = gROOT->GetClass(b->GetClassName(),kTRUE);
537 DataObjectPush push(pObj);
538 b->SetAddress(&pObj);
540 TTree* t = b->GetTree();
541 if ( Long64_t(entry) != t->GetReadEntry() ) {
542 t->LoadTree(Long64_t(entry));
545 nb = b->GetEntry(entry);
547 if (
msgSvc().isActive() ) {
548 msgSvc() <<
"Load [" << entry <<
"] --> " << section
549 <<
":" << cnt <<
" " << nb <<
" bytes."
558 else if ( nb == 0 && pObj->
clID() == CLID_DataObject) {
559 TFile* f = b->GetFile();
560 int vsn = f->GetVersion();
566 else if ( vsn>1000000 && (vsn%1000000)<52400 ) {
601 pair<const RootRef*,const RootDataConnection::ContainerSection*>
605 MergeSections::const_iterator i=
m_mergeSects.find(container);
609 for(ContainerSections::const_iterator j=s.begin(); j != s.end(); ++j,++cnt) {
615 <<
" [" << entry <<
"]" <<
endmsg
624 <<
" [" << entry <<
"]" <<
endmsg
638 int cdb=-1, ccnt=-1, clnk=-1;
639 StringVec::iterator idb, icnt, ilnk;
645 for(cdb=0,idb=
m_dbs.begin(); idb!=
m_dbs.end();++idb,++cdb)
646 if( (*idb) == db )
break;
647 if ( idb ==
m_dbs.end() ) {
652 if ( !cnt.empty() ) {
653 for(ccnt=0,icnt=
m_conts.begin(); icnt!=
m_conts.end();++icnt,++ccnt)
654 if( (*icnt) == cnt )
break;
660 if ( !name.empty() ) {
661 for(clnk=0,ilnk=
m_links.begin(); ilnk!=
m_links.end();++ilnk,++clnk)
662 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).
std
AIDA -> ROTO converter.
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.