12 #include "GaudiKernel/MsgStream.h"
13 #include "GaudiKernel/IRegistry.h"
14 #include "GaudiKernel/IUpdateable.h"
15 #include "GaudiKernel/IIncidentSvc.h"
16 #include "GaudiKernel/IDataManagerSvc.h"
17 #include "GaudiKernel/IDataProviderSvc.h"
18 #include "GaudiKernel/KeyedContainer.h"
19 #include "GaudiKernel/DataIncident.h"
20 #include "GaudiKernel/LinkManager.h"
21 #include "GaudiKernel/Incident.h"
22 #include "GaudiKernel/System.h"
23 #include "GaudiUtils/IIODataManager.h"
24 #include "RootCnv/RootRefs.h"
25 #include "RootCnv/RootCnvSvc.h"
26 #include "RootCnv/RootAddress.h"
27 #include "RootCnv/RootConverter.h"
28 #include "RootCnv/RootDatabaseCnv.h"
29 #include "RootCnv/RootDirectoryCnv.h"
30 #include "RootCnv/RootNTupleCnv.h"
31 #include "RootCnv/RootDataConnection.h"
35 using namespace Gaudi;
36 typedef const string&
CSTR;
38 #define S_OK StatusCode::SUCCESS
39 #define S_FAIL StatusCode::FAILURE
43 static map<string, TClass*> s_classesNames;
44 static map<CLID, TClass*> s_classesClids;
46 #define MBYTE (1024*1024)
53 m_classRefs = m_classDO =
nullptr;
55 declareProperty(
"IOPerfStats", m_ioPerfStats);
56 declareProperty(
"ShareFiles", m_shareFiles =
"NO");
57 declareProperty(
"EnableIncident", m_incidentEnabled =
true);
58 declareProperty(
"RecordsName", m_recordName =
"/FileRecords");
59 declareProperty(
"LoadSection", m_setup->loadSection =
"Event");
62 declareProperty(
"AutoFlush", m_autoFlush = 100);
63 declareProperty(
"BasketSize", m_basketSize = 2*
MBYTE);
64 declareProperty(
"BufferSize", m_bufferSize = 2*
kBYTE);
65 declareProperty(
"SplitLevel", m_splitLevel = 0);
66 declareProperty(
"GlobalCompression",m_compression);
69 declareProperty(
"CacheSize", m_setup->cacheSize = 10*
MBYTE);
70 declareProperty(
"LearnEntries", m_setup->learnEntries = 10);
71 declareProperty(
"CacheBranches", m_setup->cacheBranches);
72 declareProperty(
"VetoBranches", m_setup->vetoBranches);
76 RootCnvSvc::~RootCnvSvc() {
95 return error(
"Failed to initialize ConversionSvc base class.");
104 m_ioMgr = service(
"IODataManager");
106 return error(
"Unable to localize interface from service:IODataManager");
109 return error(
"Unable to localize interface from service:IncidentSvc");
114 m_classDO = TClass::GetClass(cname.c_str());
116 return error(
"Unable to load class description for DataObject");
120 return error(
"Unable to load class description for ObjectRefs");
129 for(
auto &
i : cons ) {
135 if (
pc->lookupClient(
this) ) {
136 size_t num_clients =
pc->removeClient(
this);
137 if ( num_clients == 0 ) {
138 if (
m_ioMgr->disconnect(
pc).isSuccess() ) {
139 log() <<
"Disconnected data IO:" <<
pc->fid()
140 <<
" [" <<
pc->pfn() <<
"]" <<
endmsg;
151 m_setup->setIncidentSvc(
nullptr);
157 if ( wanted == CLID_StatisticsFile )
159 else if ( wanted == CLID_StatisticsDirectory )
161 else if ( wanted == CLID_RowWiseTuple )
162 return new RootNTupleCnv(typ,wanted,serviceLocator().
get(),
this);
163 else if ( wanted == CLID_ColumnWiseTuple )
164 return new RootNTupleCnv(typ,wanted,serviceLocator().
get(),
this);
166 return new RootConverter(typ,wanted,serviceLocator().
get(),
this);
175 TClass* cl = s_classesNames[cname];
176 if (
nullptr == cl ) {
177 cl = TClass::GetClass(cname.c_str());
179 s_classesNames[cname] = cl;
180 s_classesClids[pObject->
clID()] = cl;
188 auto i=s_classesClids.find(pObject->
clID());
189 if (
i != s_classesClids.end() )
return i->second;
191 i=s_classesClids.find(pObject->
clID());
192 if (
i != s_classesClids.end() )
return i->second;
195 throw runtime_error(
"Unknown ROOT class for object:"+cname);
204 if ( ::strncasecmp(openMode.c_str(),
"RECREATE",3)==0 )
206 else if ( ::strncasecmp(openMode.c_str(),
"NEW",1)==0 )
208 else if ( ::strncasecmp(openMode.c_str(),
"CREATE",1)==0 )
210 else if ( ::strncasecmp(openMode.c_str(),
"UPDATE",1)==0 )
216 log() <<
MSG::ERROR <<
"The dataset " << dsn <<
" cannot be opened in mode "
217 << openMode <<
". [Invalid mode]" <<
endmsg;
226 bool fire_incident =
false;
232 :
m_ioMgr->connectRead(
false,connection.get());
242 connection->enableStatistics(
m_setup->loadSection);
245 connection.release();
249 ? IncidentType::FailInputFile
250 : IncidentType::FailOutputFile));
263 if ( fire_incident ) {
265 string fid = pc->
fid();
270 unsigned long ipar[2] = { (
unsigned long)(*con), (
unsigned long)b->GetEntries()-1 };
271 for(
int i=0;
i<b->GetEntries(); ++
i) {
278 <<
" [" << pc->
fid() <<
"][" <<
i <<
"]" <<
endmsg;
293 for(
auto &
i :
m_ioMgr->connections(
this) ) {
294 if (
i != *con && !
i->isConnected() ) {
298 if ( num_client == 0 ) {
299 if (
m_ioMgr->disconnect(pc).isSuccess() ) {
313 catch (exception& e) {
315 return error(
string(
"connectDatabase> Caught exception:")+e.what());
319 return error(
"connectDatabase> Unknown Fatal Exception for "+dataset);
332 string section =
m_currSection.substr(1,len==string::npos ? string::npos : len-1);
335 Long64_t
evt = b->GetEntries();
336 TTree* t = b->GetTree();
337 TObjArray* a = t->GetListOfBranches();
338 Int_t nb = a->GetEntriesFast();
340 for(Int_t
i=0;
i<nb; ++
i) {
341 TBranch* br_ptr = (TBranch*)a->UncheckedAt(
i);
342 Long64_t br_evt = br_ptr->GetEntries();
343 if ( br_evt < evt ) {
344 Long64_t num = evt-br_evt;
345 br_ptr->SetAddress(
nullptr);
351 <<
"commit: Added " << long(evt-br_evt)
352 <<
" Section: " << evt <<
" Branch: " << br_ptr->GetEntries()
353 <<
" RefNo: " << br_ptr->GetEntries()-1
354 <<
" NULL entries to:" << br_ptr->GetName() <<
endmsg;
358 b->GetTree()->SetEntries(evt);
363 if ( evt == m_autoFlush ) {
364 b->GetTree()->SetAutoFlush(m_autoFlush);
368 b->GetTree()->FlushBaskets();
373 <<
" to " << long(evt) <<
" entries." <<
endmsg;
376 return error(
"commitOutput> Failed to update entry numbers on "+dsn);
392 const unsigned long* ip,
395 refpAddress =
new RootAddress(typ,clid,par[0],par[1],ip[0],ip[1]);
401 size_t len = path.find(
'/',1);
402 string section = path.substr(1,len==string::npos ? string::npos : len-1);
410 size_t len = path.find(
'/',1);
411 string section = path.substr(1,len==string::npos ? string::npos : len-1);
412 pair<int,unsigned long> ret =
416 << ret.first <<
" " << hex << ret.second << dec <<
" [NULL]" <<
endmsg;
423 if ( !pObj )
return error(
"createRep> Current Database is invalid!");
428 size_t len = p[1].find(
'/',1);
429 string sect = p[1].substr(1,len==string::npos ? string::npos : len-1);
430 pair<int,unsigned long> ret =
432 if ( ret.first > 1 || (clid == CLID_DataObject && ret.first==1) ) {
433 unsigned long ip[2] = {0,ret.second};
437 return error(
"Failed to write object data for:"+p[1]);
443 typedef vector<IRegistry*> Leaves;
449 StatusCode status = dataMgr->objectLeaves(pObj, leaves);
453 size_t len =
id.find(
'/',1);
454 string sect =
id.substr(1,len==string::npos ? string::npos : len-1);
456 for(
auto &
i : leaves ) {
457 if (
i->address() ) {
459 ref.
entry =
i->address()->ipar()[1];
460 refs.
refs.push_back(ref);
463 for(
int i = 0,
n=pLinks->
size();
i <
n; ++
i) {
466 refs.
links.push_back(link_id);
468 pair<int,unsigned long> ret =
470 if ( ret.first > 1 ) {
473 << ret.first <<
" " << hex << ret.second << dec <<
endmsg;
487 const string* par = pA->
par();
488 unsigned long* ipar =
const_cast<unsigned long*
>(pA->
ipar());
491 ipar[0] = (
unsigned long)con;
493 size_t len = par[1].find(
'/',1);
494 string section = par[1].substr(1,len==string::npos ? string::npos : len-1);
496 int nb = con->
loadObj(section,par[1],ipar[1],pObj);
497 if ( nb > 1 || (nb == 1 && pObj->
clID() == CLID_DataObject) ) {
503 string tag = par[0]+
":"+par[1];
506 return error(
"createObj> Cannot access the object:"+tag);
515 return error(
"read> Cannot read object -- no valid object address present ");
517 const unsigned long* ipar = pA->
ipar();
521 const string* par = pA->
par();
522 size_t len = par[1].find(
'/',1);
523 string section = par[1].substr(1,len==string::npos ? string::npos : len-1);
524 int nb = con->
loadRefs(section,par[1],ipar[1],refs);
527 unsigned long nipar[2];
532 for(
auto & r : refs.
refs) {
533 npar[0] = con->
getDb(r.dbase);
534 npar[1] = con->
getCont(r.container);
535 npar[2] = con->
getLink(r.link);
544 <<
"#" << npar[2] <<
"[" << r.entry <<
"]" <<
endmsg;
545 sc = dataMgr->registerAddress(pA->
registry(),npar[2],nPA);
552 }
else if ( nb < 0 ) {
553 string tag = par[0]+
":"+par[1];
556 return error(
"createObj> Cannot access the object:"+tag+
" [Corrupted file]");
void addClient(const IInterface *client)
Add new client to this data source.
bool lookupClient(const IInterface *client) const
Lookup client for this data source.
const std::string & path() const
Access to path of object.
virtual const std::string * par() const =0
Retrieve String parameters.
Definition of the MsgStream class used to transmit messages.
virtual StatusCode update()
Provide empty placeholder for internal object reconfiguration callback.
MsgStream & log() const
Helper: Use message streamer.
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
The data converters are responsible to translate data from one representation into another...
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
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.
const std::string & fid() const
Access file id.
std::string m_currSection
Property: ROOT section name.
virtual IConverter * createConverter(long typ, const CLID &wanted, const ICnvFactory *fac)
ConversionSvc overload: Create new Converter using factory.
virtual void loadConverter(DataObject *pObj)
ConversionSvc overload: Load the class (dictionary) for the converter.
virtual StatusCode createNullRef(const std::string &path)
Insert null marker for not existent transient object.
IoType
I/O Connection types.
MSG::Level level()
Retrieve output level.
virtual StatusCode createAddress(long svc_type, const CLID &clid, const std::string *par, const unsigned long *ip, IOpaqueAddress *&refpAddress)
IAddressCreator implementation: Address creation.
const std::string & getDb(int which) const
Access database/file name from saved index.
virtual StatusCode createAddress(long svc_type, const CLID &clid, const std::string *par, const unsigned long *ipar, IOpaqueAddress *&refpAddress)=0
Create a Generic address using explicit arguments to identify a single object.
int m_basketSize
Property: Basket optimization parameter for ROOT TTree (total basket size)
Gaudi::RootDataConnection * m_current
On writing: reference to active output stream.
std::unique_ptr< MsgStream > m_log
Message streamer.
bool isSuccess() const
Test for a status code of SUCCESS.
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
int loadObj(const std::string §ion, const std::string &cnt, unsigned long entry, DataObject *&pObj)
Load object.
std::set< std::string > m_badFiles
Set with bad files/tables.
std::vector< Connection * > Connections
size_t removeClient(const IInterface *client)
Remove client from this data source.
bool patchStreamers(MsgStream &log)
const std::string & getLink(int which) const
Access link name from saved index.
long addLink(const std::string &path, const DataObject *pObject) const
Add link by object reference and path.
SmartIF< Gaudi::IIODataManager > m_ioMgr
Reference to the I/O data manager.
virtual StatusCode disconnect(const std::string &dbName)
Disconnect from an existing data stream.
const std::string & pfn() const
Access physical file name.
std::vector< int > links
The links of the link manager.
IRegistry * registry() const
Get pointer to Registry.
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...
LinkManager * linkMgr() const
Retrieve Link manager.
bool isConnected() const override
Check if connected to data source.
virtual StatusCode commitOutput(const std::string &outputFile, bool do_commit)
Commit pending output.
TYPE * get() const
Get interface pointer.
Persistent reference object.
int m_splitLevel
Property: Split level optimization parameter for ROOT TTree.
virtual void fireIncident(const Incident &incident)=0
Fire an Incident.
virtual long repSvcType() const
Retrieve the class type of the data store the converter uses.
virtual const CLID & clID() const
Retrieve reference to class definition structure.
virtual StatusCode finalize()
stop the service.
StatusCode error(const std::string &msg)
Standard way to print errors.
virtual IRegistry * registry() const =0
Update branch name.
General service interface definition.
TClass * m_classDO
TClass pointer to DataObject class.
This class is used for returning status codes from appropriate routines.
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.
Link * link(long id)
Retrieve symbolic link identified by ID.
Statistics file converter class definition.
StringVec cacheBranches
Vector of strings with branches to be cached for input files.
std::shared_ptr< RootConnectionSetup > m_setup
Setup structure (ref-counted) and passed to data connections.
The IRegistry represents the entry door to the environment any data object residing in a transient da...
virtual StatusCode i__createObj(IOpaqueAddress *pAddr, DataObject *&refpObj)
Create transient object from persistent data.
const std::string & getCont(int which) const
Access container name from saved index.
virtual StatusCode finalize()
ConversionSvc overload: Finalize Db service.
NTuple converter class definition for NTuples writted/read using ROOT.
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.
bool m_incidentEnabled
Property: Flag to enable incidents on FILE_OPEN.
const StringVec & mergeFIDs() const
Access merged FIDs.
StatusCode connectDatabase(const std::string &dataset, int mode, RootDataConnection **con)
Connect the output file to the service with open mode.
Description: NTuple directory converter class definition Definition of the converter to manage the di...
virtual StatusCode createNullRep(const std::string &path)
Insert null marker for not existent transient object.
StatusCode connectRead() override
Open data stream in read mode.
virtual StatusCode connectOutput(const std::string &outputFile, const std::string &openMode)
Connect the output file to the service with open mode.
TClass * m_classRefs
TClass pointer to reference class.
ABC describing basic data connection.
void resetAge()
Reset age.
Base class for all Incidents (computing events).
std::string m_compression
Property: Compression-algorithm:compression-level.
virtual StatusCode i__fillRepRefs(IOpaqueAddress *pAddr, DataObject *pObj)
Resolve the references of the converted object.
static long setCompression(const std::string &compression)
Set the global compression level.
std::string m_recordName
Property: Records name to fire incident for file records.
virtual StatusCode i__fillObjRefs(IOpaqueAddress *pAddr, DataObject *pObj)
Resolve the references of the created transient object.
virtual IDataProviderSvc * dataSvc() const =0
Retrieve pointer to Transient Store.
virtual SmartIF< IAddressCreator > & addressCreator() const
Retrieve address creator facility.
virtual StatusCode initialize()
Initialize the service.
virtual const id_type & identifier() const =0
Full identifier (or key)
void reset(TYPE *ptr=nullptr)
Set the internal pointer to the passed one disposing of the old one.
virtual StatusCode initialize()
ConversionSvc overload: initialize Db service.
SmartIF< IIncidentSvc > m_incidentSvc
Reference to incident service.
int makeLink(const std::string &p)
Convert path string to path index.
Embedded class defining a symbolic link Note: No copy constructor; bitwise copy (done by the compiler...
Opaque address interface definition.
Base class for all conversion services.
unsigned int CLID
Class ID definition.
std::string m_ioPerfStats
Property: Enable TTree IOperfStats if not empty; otherwise perf stat file name.
A DataObject is the base class of any identifiable object on any data store.
Concrete implementation of the IDataConnection interface to access ROOT files.
std::vector< RootRef > refs
The references corresponding to the next layer of items in the data store.
virtual const unsigned long * ipar() const =0
Access to generic link parameters.
A LinkManager is the object aggregated into a DataObject, which is responsible for the handling of no...
Helper functions to set/get the application return code.
virtual StatusCode i__createRep(DataObject *pObj, IOpaqueAddress *&refpAddr)
Convert the transient object to the requested persistent representation.
Description: Definition of the ROOT data converter.
int m_bufferSize
Property: Buffer size optimization parameter for ROOT TTree.
long size() const
Retrieve number of link present.
int m_autoFlush
Property: AutoFlush parameter for ROOT TTree (Number of events between auto flushes) ...
const long ROOT_StorageType
TClass * getClass(DataObject *pObject)
Helper: Get TClass for a given DataObject pointer.