13 #include "GaudiKernel/MsgStream.h"
14 #include "GaudiKernel/IRegistry.h"
15 #include "GaudiKernel/IUpdateable.h"
16 #include "GaudiKernel/IIncidentSvc.h"
17 #include "GaudiKernel/IDataManagerSvc.h"
18 #include "GaudiKernel/IDataProviderSvc.h"
19 #include "GaudiKernel/KeyedContainer.h"
20 #include "GaudiKernel/DataIncident.h"
21 #include "GaudiKernel/LinkManager.h"
22 #include "GaudiKernel/Incident.h"
23 #include "GaudiKernel/System.h"
24 #include "GaudiUtils/IIODataManager.h"
25 #include "RootCnv/RootRefs.h"
26 #include "RootCnv/RootCnvSvc.h"
27 #include "RootCnv/RootAddress.h"
28 #include "RootCnv/RootConverter.h"
29 #include "RootCnv/RootDatabaseCnv.h"
30 #include "RootCnv/RootDirectoryCnv.h"
31 #include "RootCnv/RootNTupleCnv.h"
32 #include "RootCnv/RootDataConnection.h"
36 using namespace Gaudi;
37 typedef const string&
CSTR;
39 #define S_OK StatusCode::SUCCESS
40 #define S_FAIL StatusCode::FAILURE
44 static map<string, TClass*> s_classesNames;
45 static map<CLID, TClass*> s_classesClids;
47 #define MBYTE 1024*1024
52 m_ioMgr(0), m_incidentSvc(0), m_current(0), m_setup(0)
54 m_classRefs = m_classDO = 0;
56 m_setup->cacheBranches.push_back(
"*");
57 declareProperty(
"IOPerfStats", m_ioPerfStats);
58 declareProperty(
"ShareFiles", m_shareFiles =
"NO");
59 declareProperty(
"EnableIncident", m_incidentEnabled =
true);
60 declareProperty(
"RecordsName", m_recordName =
"/FileRecords");
61 declareProperty(
"LoadSection", m_setup->loadSection =
"Event");
64 declareProperty(
"AutoFlush", m_autoFlush = 100);
65 declareProperty(
"BasketSize", m_basketSize = 2*
MBYTE);
66 declareProperty(
"BufferSize", m_bufferSize = 2*
kBYTE);
67 declareProperty(
"SplitLevel", m_splitLevel = 0);
68 declareProperty(
"GlobalCompression",m_compression);
71 declareProperty(
"CacheSize", m_setup->cacheSize = 10*
MBYTE);
72 declareProperty(
"LearnEntries", m_setup->learnEntries = 10);
73 declareProperty(
"CacheBranches", m_setup->cacheBranches);
74 declareProperty(
"VetoBranches", m_setup->vetoBranches);
78 RootCnvSvc::~RootCnvSvc() {
98 return error(
"Failed to initialize ConversionSvc base class.");
101 if ( !m_compression.empty() ) {
102 log() <<
MSG::INFO <<
"Setting global ROOT compression to:" << m_compression <<
endmsg;
103 if ( !(status=RootConnectionSetup::setCompression(m_compression)).isSuccess() ) {
104 return error(
"Unable to interprete ROOT compression encoding:"+m_compression);
107 if( !(status=service(
"IODataManager", m_ioMgr)).isSuccess() )
108 return error(
"Unable to localize interface from service:IODataManager");
109 if( !(status=service(
"IncidentSvc", m_incidentSvc)).isSuccess() )
110 return error(
"Unable to localize interface from service:IncidentSvc");
111 m_setup->setMessageSvc(
new MsgStream(msgSvc(),name()));
112 m_setup->setIncidentSvc(m_incidentSvc);
115 m_classDO = TClass::GetClass(cname.c_str());
116 if ( 0 == m_classDO )
117 return error(
"Unable to load class description for DataObject");
119 m_classRefs = TClass::GetClass(cname.c_str());
120 if ( 0 == m_classRefs )
121 return error(
"Unable to load class description for ObjectRefs");
130 for(IIODataManager::Connections::iterator
i=cons.begin();
i != cons.end(); ++
i) {
133 if ( pc->
owner() ==
this && !m_ioPerfStats.empty() ) {
138 if ( num_clients == 0 ) {
139 if ( m_ioMgr->disconnect(pc).isSuccess() ) {
140 log() <<
"Disconnected data IO:" << pc->
fid()
151 releasePtr(m_incidentSvc);
152 m_setup->setIncidentSvc(0);
157 IConverter* RootCnvSvc::createConverter(
long typ,
const CLID& wanted,
const ICnvFactory*) {
158 if ( wanted == CLID_StatisticsFile )
160 else if ( wanted == CLID_StatisticsDirectory )
162 else if ( wanted == CLID_RowWiseTuple )
163 return new RootNTupleCnv(typ,wanted,serviceLocator().
get(),
this);
164 else if ( wanted == CLID_ColumnWiseTuple )
165 return new RootNTupleCnv(typ,wanted,serviceLocator().
get(),
this);
167 return new RootConverter(typ,wanted,serviceLocator().
get(),
this);
176 TClass* cl = s_classesNames[cname];
178 cl = TClass::GetClass(cname.c_str());
180 s_classesNames[cname] = cl;
181 s_classesClids[pObject->
clID()] = cl;
189 map<CLID, TClass*>::iterator
i=s_classesClids.find(pObject->
clID());
190 if ( i != s_classesClids.end() )
return (*i).second;
191 loadConverter(pObject);
192 i=s_classesClids.find(pObject->
clID());
193 if ( i != s_classesClids.end() )
return (*i).second;
196 throw runtime_error(
"Unknown ROOT class for object:"+cname);
205 if ( ::strncasecmp(openMode.c_str(),
"RECREATE",3)==0 )
206 sc = connectDatabase(dsn, IDataConnection::RECREATE, &m_current);
207 else if ( ::strncasecmp(openMode.c_str(),
"NEW",1)==0 )
209 else if ( ::strncasecmp(openMode.c_str(),
"CREATE",1)==0 )
211 else if ( ::strncasecmp(openMode.c_str(),
"UPDATE",1)==0 )
212 sc = connectDatabase(dsn, IDataConnection::UPDATE, &m_current);
213 if ( sc.
isSuccess() && m_current && m_current->isConnected() ) {
217 log() <<
MSG::ERROR <<
"The dataset " << dsn <<
" cannot be opened in mode "
218 << openMode <<
". [Invalid mode]" <<
endmsg;
227 bool fire_incident =
false;
230 auto_ptr<RootDataConnection> connection(
new RootDataConnection(
this,dataset,m_setup));
233 : m_ioMgr->connectRead(
false,connection.get());
234 c = sc.
isSuccess() ? m_ioMgr->connection(dataset) : 0;
236 bool writable = 0 != (mode&(IDataConnection::UPDATE|IDataConnection::RECREATE));
242 if ( !m_ioPerfStats.empty() ) {
243 connection->enableStatistics(m_setup->loadSection);
246 connection.release();
249 m_incidentSvc->fireIncident(
Incident(dataset,mode == IDataConnection::READ
264 if ( fire_incident ) {
266 string fid = pc->
fid();
267 string section = m_recordName[0] ==
'/' ? m_recordName.substr(1) : m_recordName;
268 TBranch* b = pc->
getBranch(section,m_recordName);
270 const string par[2] = { fid, m_recordName };
271 unsigned long ipar[2] = { (
unsigned long)(*con), (
unsigned long)b->GetEntries()-1 };
272 for(
int i=0;
i<b->GetEntries(); ++
i) {
276 if ( !createAddress(repSvcType(),CLID_DataObject,par,ipar,pAddr).isSuccess() ) {
278 log() <<
MSG::VERBOSE <<
"Failed to create address for " << m_recordName <<
" in:" << fid
279 <<
" [" << pc->
fid() <<
"][" <<
i <<
"]" <<
endmsg;
283 log() <<
MSG::VERBOSE <<
"Prepare " << m_recordName <<
" " << fid <<
" [" << par[0] <<
"][" <<
i <<
"]" <<
endmsg;
295 for(IIODataManager::Connections::iterator
i=cons.begin();
i != cons.end(); ++
i) {
300 if ( num_client == 0 ) {
301 if ( m_ioMgr->disconnect(pc).isSuccess() ) {
315 catch (exception& e) {
317 return error(
string(
"connectDatabase> Caught exception:")+e.what());
321 return error(
"connectDatabase> Unknown Fatal Exception for "+dataset);
327 return connectOutput(db_name,
"NEW");
333 size_t len = m_currSection.find(
'/',1);
334 string section = m_currSection.substr(1,len==string::npos ? string::npos : len-1);
335 TBranch* b = m_current->getBranch(section, m_currSection);
337 Long64_t
evt = b->GetEntries();
338 TTree* t = b->GetTree();
339 TObjArray* a = t->GetListOfBranches();
340 Int_t nb = a->GetEntriesFast();
342 for(Int_t
i=0;
i<nb; ++
i) {
343 TBranch* br_ptr = (TBranch*)a->UncheckedAt(
i);
344 Long64_t br_evt = br_ptr->GetEntries();
345 if ( br_evt < evt ) {
346 Long64_t num = evt-br_evt;
347 br_ptr->SetAddress(0);
353 <<
"commit: Added " << long(evt-br_evt)
354 <<
" Section: " << evt <<
" Branch: " << br_ptr->GetEntries()
355 <<
" RefNo: " << br_ptr->GetEntries()-1
356 <<
" NULL entries to:" << br_ptr->GetName() <<
endmsg;
360 b->GetTree()->SetEntries(evt);
362 b->GetTree()->OptimizeBaskets(m_basketSize,1.1,
"");
364 if ( evt > 0 && (evt%m_autoFlush)==0 ) {
365 if ( evt == m_autoFlush ) {
366 b->GetTree()->SetAutoFlush(m_autoFlush);
367 b->GetTree()->OptimizeBaskets(m_basketSize,1.,
"");
370 b->GetTree()->FlushBaskets();
374 log() <<
MSG::DEBUG <<
"Set section entries of " << m_currSection
375 <<
" to " << long(evt) <<
" entries." <<
endmsg;
378 return error(
"commitOutput> Failed to update entry numbers on "+dsn);
394 const unsigned long* ip,
397 refpAddress =
new RootAddress(typ,clid,par[0],par[1],ip[0],ip[1]);
403 size_t len = path.find(
'/',1);
404 string section = path.substr(1,len==string::npos ? string::npos : len-1);
405 m_current->saveObj(section,path,0,0,m_bufferSize,m_splitLevel);
412 size_t len = path.find(
'/',1);
413 string section = path.substr(1,len==string::npos ? string::npos : len-1);
414 pair<int,unsigned long> ret =
415 m_current->save(section,path+
"#R",0,refs,m_bufferSize,m_splitLevel);
418 << ret.first <<
" " << hex << ret.second << dec <<
" [NULL]" <<
endmsg;
428 string p[2] = {m_current->fid(), pR->
identifier()};
429 TClass* cl = (clid == CLID_DataObject) ? m_classDO :
getClass(pObj);
430 size_t len = p[1].find(
'/',1);
431 string sect = p[1].substr(1,len==string::npos ? string::npos : len-1);
432 pair<int,unsigned long> ret =
433 m_current->saveObj(sect,p[1],cl,pObj,m_bufferSize,m_splitLevel,
true);
434 if ( ret.first > 1 || (clid == CLID_DataObject && ret.first==1) ) {
435 unsigned long ip[2] = {0,ret.second};
436 if ( m_currSection.empty() ) m_currSection = p[1];
437 return createAddress(repSvcType(),clid,p,ip,refpAddr);
439 return error(
"Failed to write object data for:"+p[1]);
441 return error(
"createRep> Current Database is invalid!");
447 typedef vector<IRegistry*> Leaves;
453 StatusCode status = dataMgr->objectLeaves(pObj, leaves);
457 size_t len =
id.find(
'/',1);
458 string sect =
id.substr(1,len==string::npos ? string::npos : len-1);
460 for(Leaves::iterator
i=leaves.begin(), iend=leaves.end();
i != iend; ++
i) {
461 if ( (*i)->address() ) {
462 m_current->makeRef(*
i,ref);
463 ref.
entry = (*i)->address()->ipar()[1];
464 refs.
refs.push_back(ref);
467 for(
int i = 0,
n=pLinks->
size();
i <
n; ++
i) {
469 int link_id = m_current->makeLink(lnk->
path());
470 refs.
links.push_back(link_id);
472 pair<int,unsigned long> ret =
473 m_current->save(sect,
id+
"#R",m_classRefs,&refs,m_bufferSize,m_splitLevel,
true);
474 if ( ret.first > 1 ) {
477 << ret.first <<
" " << hex << ret.second << dec <<
endmsg;
491 const string* par = pA->
par();
492 unsigned long* ipar =
const_cast<unsigned long*
>(pA->
ipar());
493 StatusCode sc = connectDatabase(par[0],IDataConnection::READ,&con);
495 ipar[0] = (
unsigned long)con;
497 size_t len = par[1].find(
'/',1);
498 string section = par[1].substr(1,len==string::npos ? string::npos : len-1);
500 int nb = con->
loadObj(section,par[1],ipar[1],pObj);
501 if ( nb > 1 || (nb == 1 && pObj->
clID() == CLID_DataObject) ) {
507 string tag = par[0]+
":"+par[1];
508 if ( m_badFiles.find(tag) == m_badFiles.end() ) {
509 m_badFiles.insert(tag);
510 return error(
"createObj> Cannot access the object:"+tag);
520 const unsigned long* ipar = pA->
ipar();
524 const string* par = pA->
par();
525 size_t len = par[1].find(
'/',1);
526 string section = par[1].substr(1,len==string::npos ? string::npos : len-1);
527 int nb = con->
loadRefs(section,par[1],ipar[1],refs);
530 unsigned long nipar[2];
536 for(vector<int>::const_iterator
i=refs.
links.begin();
i!=refs.
links.end();++
i) {
539 for(
size_t j=0,
n=refs.
refs.size(); j<
n; ++j) {
550 <<
"#" << npar[2] <<
"[" << r.
entry <<
"]" <<
endmsg;
551 sc = dataMgr->registerAddress(pA->
registry(),npar[2],nPA);
562 string tag = par[0]+
":"+par[1];
563 if ( m_badFiles.find(tag) == m_badFiles.end() ) {
564 m_badFiles.insert(tag);
565 return error(
"createObj> Cannot access the object:"+tag+
" [Corrupted file]");
571 return error(
"read> Cannot read object -- no valid object address present ");