RootCnvSvc.cpp
Go to the documentation of this file.
1 //====================================================================
2 // RootCnvSvc implementation
3 //--------------------------------------------------------------------
4 //
5 // Description: Implementation of the ROOT data storage
6 //
7 // Author : M.Frank
8 //
9 //====================================================================
10 
11 // Framework include files
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"
32 #include "RootUtils.h"
33 
34 using namespace std;
35 using namespace Gaudi;
36 typedef const string& CSTR;
37 
38 #define S_OK StatusCode::SUCCESS
39 #define S_FAIL StatusCode::FAILURE
40 namespace GaudiRoot { bool patchStreamers(MsgStream& log); }
41 
42 namespace {
43  static map<string, TClass*> s_classesNames;
44  static map<CLID, TClass*> s_classesClids;
45 }
46 #define MBYTE (1024*1024)
47 #define kBYTE 1024
48 // Standard constructor
49 RootCnvSvc::RootCnvSvc(CSTR nam, ISvcLocator* svc)
50 : ConversionSvc( nam, svc, ROOT_StorageType),
51  m_setup{ new RootConnectionSetup() }
52 {
53  m_classRefs = m_classDO = nullptr;
54  m_setup->cacheBranches.push_back("*");
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");
60 
61  // ROOT Write parameters
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); // empty: do nothing
67 
68  // ROOT Read parameters: must be shared for the entire file!
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);
73 }
74 
75 // Standard destructor
76 RootCnvSvc::~RootCnvSvc() {
77 }
78 
79 // Small routine to issue exceptions
81  if ( m_log ) {
82  log() << MSG::ERROR << "Error: " << msg << endmsg;
83  return S_FAIL;
84  }
85  MsgStream m(msgSvc(),name());
86  m << MSG::ERROR << "Error: " << msg << endmsg;
87  return S_FAIL;
88 }
89 
90 // Initialize the Db data persistency service
92  string cname;
94  if ( !status.isSuccess() ) {
95  return error("Failed to initialize ConversionSvc base class.");
96  }
97  m_log.reset( new MsgStream(msgSvc(),name()) );
98  if ( !m_compression.empty() ) {
99  log() << MSG::INFO << "Setting global ROOT compression to:" << m_compression << endmsg;
100  if ( !(status=RootConnectionSetup::setCompression(m_compression)).isSuccess() ) {
101  return error("Unable to interprete ROOT compression encoding:"+m_compression);
102  }
103  }
104  m_ioMgr = service("IODataManager");
105  if( !m_ioMgr)
106  return error("Unable to localize interface from service:IODataManager");
107  m_incidentSvc = service("IncidentSvc");
108  if( !m_incidentSvc )
109  return error("Unable to localize interface from service:IncidentSvc");
110  m_setup->setMessageSvc(new MsgStream(msgSvc(),name()));
111  m_setup->setIncidentSvc(m_incidentSvc.get());
113  cname = System::typeinfoName(typeid(DataObject));
114  m_classDO = TClass::GetClass(cname.c_str());
115  if ( !m_classDO )
116  return error("Unable to load class description for DataObject");
117  cname = System::typeinfoName(typeid(RootObjectRefs));
118  m_classRefs = TClass::GetClass(cname.c_str());
119  if ( !m_classRefs )
120  return error("Unable to load class description for ObjectRefs");
121  return S_OK;
122 }
123 
124 // Finalize the Db data persistency service
126  log() << MSG::INFO;
127  if ( m_ioMgr ) {
128  IIODataManager::Connections cons = m_ioMgr->connections(nullptr);
129  for(auto &i : cons ) {
130  auto pc = dynamic_cast<RootDataConnection*>(i);
131  if ( pc ) {
132  if ( pc->owner() == this && !m_ioPerfStats.empty() ) {
133  pc->saveStatistics(m_ioPerfStats);
134  }
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;
141  delete pc;
142  }
143  }
144  }
145  }
146  }
147  m_ioMgr.reset();
148  }
149  m_log.reset();
151  m_setup->setIncidentSvc(nullptr);
152  return ConversionSvc::finalize();
153 }
154 
155 // ConversionSvc overload: Create new Converter using factory
156 IConverter* RootCnvSvc::createConverter(long typ,const CLID& wanted,const ICnvFactory*) {
157  if ( wanted == CLID_StatisticsFile )
158  return new RootDatabaseCnv(typ,wanted,serviceLocator().get(),this);
159  else if ( wanted == CLID_StatisticsDirectory )
160  return new RootDirectoryCnv(typ,wanted,serviceLocator().get(),this);
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);
165  else
166  return new RootConverter(typ,wanted,serviceLocator().get(),this);
167 }
168 
169 // ConversionSvc overload: Load the class (dictionary) for the converter
171  if (pObject) {
172  string cname = System::typeinfoName(typeid(*pObject));
173  if( log().level() <= MSG::DEBUG )
174  log() << MSG::DEBUG << "Trying to 'Autoload' dictionary for class " << cname << endmsg;
175  TClass* cl = s_classesNames[cname];
176  if ( nullptr == cl ) {
177  cl = TClass::GetClass(cname.c_str());
178  if ( cl ) {
179  s_classesNames[cname] = cl;
180  s_classesClids[pObject->clID()] = cl;
181  }
182  }
183  }
184 }
185 
186 // Helper: Get TClass for a given DataObject pointer
187 TClass* RootCnvSvc::getClass(DataObject* pObject) {
188  auto i=s_classesClids.find(pObject->clID());
189  if ( i != s_classesClids.end() ) return i->second;
190  loadConverter(pObject);
191  i=s_classesClids.find(pObject->clID());
192  if ( i != s_classesClids.end() ) return i->second;
193 
194  string cname = System::typeinfoName(typeid(*pObject));
195  throw runtime_error("Unknown ROOT class for object:"+cname);
196  return nullptr;
197 }
198 
199 // Connect the output file to the service with open mode.
201  StatusCode sc = S_FAIL;
202  m_current = nullptr;
203  m_currSection.clear();
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 )
212  if ( sc.isSuccess() && m_current && m_current->isConnected() ) {
213  return S_OK;
214  }
215  m_incidentSvc->fireIncident(Incident(dsn,IncidentType::FailOutputFile));
216  log() << MSG::ERROR << "The dataset " << dsn << " cannot be opened in mode "
217  << openMode << ". [Invalid mode]" << endmsg;
218  return sc;
219 }
220 
221 // Connect the output file to the service with open mode.
223 RootCnvSvc::connectDatabase(CSTR dataset, int mode, RootDataConnection** con) {
224  try {
225  IDataConnection* c = m_ioMgr->connection(dataset);
226  bool fire_incident = false;
227  *con = nullptr;
228  if ( !c ) {
229  std::unique_ptr<RootDataConnection> connection(new RootDataConnection(this,dataset,m_setup));
230  StatusCode sc = (mode != IDataConnection::READ)
231  ? m_ioMgr->connectWrite(connection.get(),IDataConnection::IoType(mode),"ROOT")
232  : m_ioMgr->connectRead(false,connection.get());
233  c = sc.isSuccess() ? m_ioMgr->connection(dataset) : nullptr;
234  if ( c ) {
235  bool writable = 0 != (mode&(IDataConnection::UPDATE|IDataConnection::RECREATE));
236  fire_incident = m_incidentEnabled && (0 != (mode&(IDataConnection::UPDATE|IDataConnection::READ)));
237  if ( writable ) {
238  m_incidentSvc->fireIncident(ContextIncident<TFile*>(connection->pfn(),"CONNECTED_OUTPUT",connection->file()));
239  }
240  if ( 0 != (mode&IDataConnection::READ) ) {
241  if ( !m_ioPerfStats.empty() ) {
242  connection->enableStatistics(m_setup->loadSection);
243  }
244  }
245  connection.release();
246  }
247  else {
248  m_incidentSvc->fireIncident(Incident(dataset,mode == IDataConnection::READ
249  ? IncidentType::FailInputFile
250  : IncidentType::FailOutputFile));
251  // An error message was already printed by the IODataManager. no need to do it here!
252  return StatusCode::FAILURE;
253  }
254  }
255  RootDataConnection* pc = dynamic_cast<RootDataConnection*>(c);
256  if ( pc ) {
257  if ( !pc->isConnected() ) pc->connectRead();
258  *con = pc;
259  pc->resetAge();
260  pc->addClient(this);
261  }
262  if ( *con ) {
263  if ( fire_incident ) {
264  IOpaqueAddress* pAddr = nullptr;
265  string fid = pc->fid();
266  string section = m_recordName[0] == '/' ? m_recordName.substr(1) : m_recordName;
267  TBranch* b = pc->getBranch(section,m_recordName);
268  if ( b ) {
269  const string par[2] = { fid, m_recordName };
270  unsigned long ipar[2] = { (unsigned long)(*con), (unsigned long)b->GetEntries()-1 };
271  for(int i=0; i<b->GetEntries(); ++i) {
272  ipar[1] = i;
273  if ( !pc->mergeFIDs().empty() )
274  fid = pc->mergeFIDs()[i];
275  if ( !createAddress(repSvcType(),CLID_DataObject,par,ipar,pAddr).isSuccess() ) {
276  if( log().level() <= MSG::VERBOSE )
277  log() << MSG::VERBOSE << "Failed to create address for " << m_recordName << " in:" << fid
278  << " [" << pc->fid() << "][" << i << "]" << endmsg;
279  continue;
280  }
281  if( log().level() <= MSG::VERBOSE )
282  log() << MSG::VERBOSE << "Prepare " << m_recordName << " " << fid << " [" << par[0] << "][" << i << "]" << endmsg;
283  m_incidentSvc->fireIncident(ContextIncident<IOpaqueAddress*>(fid,"FILE_OPEN_READ",pAddr));
284  }
285  }
286  else {
287  if( log().level() <= MSG::VERBOSE )
288  log() << MSG::VERBOSE << "No valid Records " << m_recordName << " present in:" << pc->fid() << endmsg;
289  }
290  }
291 
292  // We can remove retired connections, which are no longer used....
293  for( auto &i : m_ioMgr->connections(this) ) {
294  if ( i != *con && !i->isConnected() ) {
295  RootDataConnection* pc = dynamic_cast<RootDataConnection*>(i);
296  if ( pc && pc->lookupClient(this) ) {
297  size_t num_client = pc->removeClient(this);
298  if ( num_client == 0 ) {
299  if ( m_ioMgr->disconnect(pc).isSuccess() ) {
300  log() << MSG::INFO << "Removed disconnected IO stream:" << pc->fid()
301  << " [" << pc->pfn() << "]" << endmsg;
302  delete pc;
303  }
304  }
305  }
306  }
307  }
308  return S_OK;
309  }
310  m_incidentSvc->fireIncident(Incident(dataset,IncidentType::FailOutputFile));
311  return S_FAIL;
312  }
313  catch (exception& e) {
314  m_incidentSvc->fireIncident(Incident(dataset,IncidentType::FailOutputFile));
315  return error(string("connectDatabase> Caught exception:")+e.what());
316  }
317  catch (...) {
318  m_incidentSvc->fireIncident(Incident(dataset,IncidentType::FailOutputFile));
319  return error("connectDatabase> Unknown Fatal Exception for "+dataset);
320  }
321 }
322 
323 // Conect output stream (valid until overwritten)
325  return connectOutput(db_name, "NEW");
326 }
327 
328 // Commit pending output on open container
329 StatusCode RootCnvSvc::commitOutput(CSTR dsn, bool /* doCommit */) {
330  if ( m_current ) {
331  size_t len = m_currSection.find('/',1);
332  string section = m_currSection.substr(1,len==string::npos ? string::npos : len-1);
333  TBranch* b = m_current->getBranch(section, m_currSection);
334  if ( b ) {
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);
346  while(num>0) {
347  br_ptr->Fill();
348  --num;
349  }
350  if( log().level() <= MSG::DEBUG ) log() << MSG::DEBUG
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;
355  }
356  }
357 
358  b->GetTree()->SetEntries(evt);
359  if ( evt == 1 ) {
360  b->GetTree()->OptimizeBaskets(m_basketSize,1.1,"");
361  }
362  if ( evt > 0 && (evt%m_autoFlush)==0 ) {
363  if ( evt == m_autoFlush ) {
364  b->GetTree()->SetAutoFlush(m_autoFlush);
365  b->GetTree()->OptimizeBaskets(m_basketSize,1.,"");
366  }
367  else {
368  b->GetTree()->FlushBaskets();
369  }
370  }
371  if( log().level() <= MSG::DEBUG )
372  log() << MSG::DEBUG << "Set section entries of " << m_currSection
373  << " to " << long(evt) << " entries." << endmsg;
374  }
375  else {
376  return error("commitOutput> Failed to update entry numbers on "+dsn);
377  }
378  }
379  return S_OK;
380 }
381 
382 // Disconnect from an existing data stream.
384  IDataConnection* c = m_ioMgr->connection(dataset);
385  return c ? m_ioMgr->disconnect(c) : S_FAIL;
386 }
387 
388 // IAddressCreator implementation: Address creation
390  const CLID& clid,
391  const string* par,
392  const unsigned long* ip,
393  IOpaqueAddress*& refpAddress)
394 {
395  refpAddress = new RootAddress(typ,clid,par[0],par[1],ip[0],ip[1]);
396  return S_OK;
397 }
398 
399 // Insert null marker for not existent transient object
401  size_t len = path.find('/',1);
402  string section = path.substr(1,len==string::npos ? string::npos : len-1);
403  m_current->saveObj(section,path,nullptr,nullptr,m_bufferSize,m_splitLevel);
404  return S_OK;
405 }
406 
407 // Insert null marker for not existent transient object
409  RootObjectRefs* refs = nullptr;
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 =
413  m_current->save(section,path+"#R",nullptr,refs,m_bufferSize,m_splitLevel);
414  if( log().level() <= MSG::VERBOSE )
415  log() << MSG::VERBOSE << "Writing object:" << path << " "
416  << ret.first << " " << hex << ret.second << dec << " [NULL]" << endmsg;
417  return S_OK;
418 }
419 
420 // Mark an object for write given an object reference
422  refpAddr = nullptr;
423  if ( !pObj ) return error("createRep> Current Database is invalid!");
424  CLID clid = pObj->clID();
425  IRegistry* pR = pObj->registry();
426  string p[2] = {m_current->fid(), pR->identifier()};
427  TClass* cl = (clid == CLID_DataObject) ? m_classDO : getClass(pObj);
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 =
431  m_current->saveObj(sect,p[1],cl,pObj,m_bufferSize,m_splitLevel,true);
432  if ( ret.first > 1 || (clid == CLID_DataObject && ret.first==1) ) {
433  unsigned long ip[2] = {0,ret.second};
434  if ( m_currSection.empty() ) m_currSection = p[1];
435  return createAddress(repSvcType(),clid,p,ip,refpAddr);
436  }
437  return error("Failed to write object data for:"+p[1]);
438 }
439 
440 // Save object references to data file
442  if ( pObj ) {
443  typedef vector<IRegistry*> Leaves;
444  Leaves leaves;
445  RootObjectRefs refs;
446  IRegistry* pR = pObj->registry();
447  auto dataMgr = SmartIF<IDataManagerSvc>{ pR->dataSvc() };
448  if ( dataMgr ) {
449  StatusCode status = dataMgr->objectLeaves(pObj, leaves);
450  if ( status.isSuccess() ) {
451  RootRef ref;
452  const string& id = pR->identifier();
453  size_t len = id.find('/',1);
454  string sect = id.substr(1,len==string::npos ? string::npos : len-1);
455  LinkManager* pLinks = pObj->linkMgr();
456  for(auto &i : leaves ) {
457  if ( i->address() ) {
458  m_current->makeRef(i,ref);
459  ref.entry = i->address()->ipar()[1];
460  refs.refs.push_back(ref);
461  }
462  }
463  for(int i = 0, n=pLinks->size(); i < n; ++i) {
464  LinkManager::Link* lnk = pLinks->link(i);
465  int link_id = m_current->makeLink(lnk->path());
466  refs.links.push_back(link_id);
467  }
468  pair<int,unsigned long> ret =
469  m_current->save(sect,id+"#R",m_classRefs,&refs,m_bufferSize,m_splitLevel,true);
470  if ( ret.first > 1 ) {
471  if( log().level() <= MSG::DEBUG )
472  log() << MSG::DEBUG << "Writing object:" << id << " "
473  << ret.first << " " << hex << ret.second << dec << endmsg;
474  return S_OK;
475  }
476  }
477  }
478  }
479  return S_FAIL;
480 }
481 
482 // Read existing object. Open transaction in read mode if not active
484  refpObj = nullptr;
485  if ( !pA ) return S_FAIL;
486  RootDataConnection* con = nullptr;
487  const string* par = pA->par();
488  unsigned long* ipar = const_cast<unsigned long*>(pA->ipar());
489  StatusCode sc = connectDatabase(par[0],IDataConnection::READ,&con);
490  if ( sc.isSuccess() ) {
491  ipar[0] = (unsigned long)con;
492  DataObject* pObj = nullptr;
493  size_t len = par[1].find('/',1);
494  string section = par[1].substr(1,len==string::npos ? string::npos : len-1);
495 
496  int nb = con->loadObj(section,par[1],ipar[1],pObj);
497  if ( nb > 1 || (nb == 1 && pObj->clID() == CLID_DataObject) ) {
498  refpObj = pObj;
499  return S_OK;
500  }
501  delete pObj;
502  }
503  string tag = par[0]+":"+par[1];
504  if ( m_badFiles.find(tag) == m_badFiles.end() ) {
505  m_badFiles.insert(tag);
506  return error("createObj> Cannot access the object:"+tag);
507  }
508  return S_FAIL;
509 
510 }
511 
512 // Resolve the references of the created transient object.
514  if ( !pA || !pObj )
515  return error("read> Cannot read object -- no valid object address present ");
516 
517  const unsigned long* ipar = pA->ipar();
518  RootDataConnection* con = (RootDataConnection*)ipar[0];
519  if ( con ) {
520  RootObjectRefs refs;
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);
525  if ( nb >= 1 ) {
526  string npar[3];
527  unsigned long nipar[2];
528  IRegistry* pR = pObj->registry();
529  auto dataMgr = SmartIF<IDataManagerSvc>{ pR->dataSvc() };
530  LinkManager* mgr = pObj->linkMgr();
531  for(const auto& i : refs.links ) mgr->addLink(con->getLink(i),nullptr);
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);
536  nipar[0] = 0;
537  nipar[1] = r.entry;
538  IOpaqueAddress* nPA = nullptr;
539  StatusCode sc = addressCreator()->createAddress(r.svc,r.clid,npar,nipar,nPA);
540  if ( sc.isSuccess() ) {
541  if( log().level() <= MSG::VERBOSE )
542  log() << MSG::VERBOSE << dataMgr.as<IService>()->name()
543  << " -> Register:" << pA->registry()->identifier()
544  << "#" << npar[2] << "[" << r.entry << "]" << endmsg;
545  sc = dataMgr->registerAddress(pA->registry(),npar[2],nPA);
546  if ( sc.isSuccess() ) continue;
547  }
548  log() << MSG::ERROR << con->fid() << ": Failed to create address!!!!" << endmsg;
549  return S_FAIL;
550  }
551  return pObj->update();
552  } else if ( nb < 0 ) {
553  string tag = par[0]+":"+par[1];
554  if ( m_badFiles.find(tag) == m_badFiles.end() ) {
555  m_badFiles.insert(tag);
556  return error("createObj> Cannot access the object:"+tag+" [Corrupted file]");
557  }
558  }
559  }
560  return S_FAIL;
561 }
void addClient(const IInterface *client)
Add new client to this data source.
bool lookupClient(const IInterface *client) const
Lookup client for this data source.
virtual const std::string * par() const =0
Retrieve String parameters.
tuple c
Definition: gaudirun.py:391
Definition of the MsgStream class used to transmit messages.
Definition: MsgStream.h:24
virtual StatusCode update()
Provide empty placeholder for internal object reconfiguration callback.
Definition: DataObject.cpp:83
MsgStream & log() const
Helper: Use message streamer.
Definition: RootCnvSvc.h:99
Description:
Definition: RootAddress.h:36
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:25
The data converters are responsible to translate data from one representation into another...
Definition: IConverter.h:57
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:244
std::pair< int, unsigned long > save(const std::string &section, 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.
Definition: RootCnvSvc.h:68
virtual IConverter * createConverter(long typ, const CLID &wanted, const ICnvFactory *fac)
ConversionSvc overload: Create new Converter using factory.
Definition: RootCnvSvc.cpp:156
virtual void loadConverter(DataObject *pObj)
ConversionSvc overload: Load the class (dictionary) for the converter.
Definition: RootCnvSvc.cpp:170
virtual StatusCode createNullRef(const std::string &path)
Insert null marker for not existent transient object.
Definition: RootCnvSvc.cpp:408
IoType
I/O Connection types.
MSG::Level level()
Retrieve output level.
Definition: MsgStream.h:112
virtual StatusCode createAddress(long svc_type, const CLID &clid, const std::string *par, const unsigned long *ip, IOpaqueAddress *&refpAddress)
IAddressCreator implementation: Address creation.
Definition: RootCnvSvc.cpp:389
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)
Definition: RootCnvSvc.h:84
Gaudi::RootDataConnection * m_current
On writing: reference to active output stream.
Definition: RootCnvSvc.h:60
std::unique_ptr< MsgStream > m_log
Message streamer.
Definition: RootCnvSvc.h:94
bool isSuccess() const
Test for a status code of SUCCESS.
Definition: StatusCode.h:76
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:297
int loadObj(const std::string &section, const std::string &cnt, unsigned long entry, DataObject *&pObj)
Load object.
std::set< std::string > m_badFiles
Set with bad files/tables.
Definition: RootCnvSvc.h:91
list path
Definition: __init__.py:15
std::vector< Connection * > Connections
size_t removeClient(const IInterface *client)
Remove client from this data source.
constexpr double pc
STL namespace.
bool patchStreamers(MsgStream &log)
const std::string & getLink(int which) const
Access link name from saved index.
SmartIF< Gaudi::IIODataManager > m_ioMgr
Reference to the I/O data manager.
Definition: RootCnvSvc.h:56
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.
Definition: RootRefs.h:60
IRegistry * registry() const
Get pointer to Registry.
Definition: DataObject.h:74
int loadRefs(const std::string &section, 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...
Definition: RootRefs.h:58
LinkManager * linkMgr() const
Retrieve Link manager.
Definition: DataObject.h:78
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.
Definition: SmartIF.h:76
Persistent reference object.
Definition: RootRefs.h:30
int m_splitLevel
Property: Split level optimization parameter for ROOT TTree.
Definition: RootCnvSvc.h:88
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.
Definition: DataObject.cpp:68
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.
Definition: IService.h:18
TClass * m_classDO
TClass pointer to DataObject class.
Definition: RootCnvSvc.h:64
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:26
constexpr double m
Definition: SystemOfUnits.h:93
#define S_OK
Definition: RootCnvSvc.cpp:38
TBranch * getBranch(const std::string &section, 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.
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.
Definition: RootCnvSvc.h:66
The IRegistry represents the entry door to the environment any data object residing in a transient da...
Definition: IRegistry.h:22
const std::string CSTR
virtual StatusCode i__createObj(IOpaqueAddress *pAddr, DataObject *&refpObj)
Create transient object from persistent data.
Definition: RootCnvSvc.cpp:483
const std::string & getCont(int which) const
Access container name from saved index.
virtual StatusCode finalize()
ConversionSvc overload: Finalize Db service.
Definition: RootCnvSvc.cpp:125
NTuple converter class definition for NTuples writted/read using ROOT.
Definition: RootNTupleCnv.h:34
std::pair< int, unsigned long > saveObj(const std::string &section, 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.
Definition: RootCnvSvc.h:71
const StringVec & mergeFIDs() const
Access merged FIDs.
#define MBYTE
Definition: RootCnvSvc.cpp:46
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.
Definition: RootCnvSvc.cpp:400
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.
Definition: RootCnvSvc.h:62
ABC describing basic data connection.
void resetAge()
Reset age.
Base class for all Incidents (computing events).
Definition: Incident.h:16
std::string m_compression
Property: Compression-algorithm:compression-level.
Definition: RootCnvSvc.h:79
virtual StatusCode i__fillRepRefs(IOpaqueAddress *pAddr, DataObject *pObj)
Resolve the references of the converted object.
Definition: RootCnvSvc.cpp:441
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.
Definition: RootCnvSvc.h:75
virtual StatusCode i__fillObjRefs(IOpaqueAddress *pAddr, DataObject *pObj)
Resolve the references of the created transient object.
Definition: RootCnvSvc.cpp:513
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.
Definition: SmartIF.h:88
virtual StatusCode initialize()
ConversionSvc overload: initialize Db service.
Definition: RootCnvSvc.cpp:91
SmartIF< IIncidentSvc > m_incidentSvc
Reference to incident service.
Definition: RootCnvSvc.h:58
int makeLink(const std::string &p)
Convert path string to path index.
Opaque address interface definition.
Base class for all conversion services.
Definition: ConversionSvc.h:46
unsigned int CLID
Class ID definition.
Definition: ClassID.h:8
std::string m_ioPerfStats
Property: Enable TTree IOperfStats if not empty; otherwise perf stat file name.
Definition: RootCnvSvc.h:77
#define S_FAIL
Definition: RootCnvSvc.cpp:39
A DataObject is the base class of any identifiable object on any data store.
Definition: DataObject.h:30
list i
Definition: ana.py:128
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.
Definition: RootRefs.h:62
virtual const unsigned long * ipar() const =0
Access to generic link parameters.
Helper functions to set/get the application return code.
Definition: __init__.py:1
virtual StatusCode i__createRep(DataObject *pObj, IOpaqueAddress *&refpAddr)
Convert the transient object to the requested persistent representation.
Definition: RootCnvSvc.cpp:421
#define kBYTE
Definition: RootCnvSvc.cpp:47
Description: Definition of the ROOT data converter.
Definition: RootConverter.h:32
int m_bufferSize
Property: Buffer size optimization parameter for ROOT TTree.
Definition: RootCnvSvc.h:86
const string & CSTR
Definition: RootCnvSvc.cpp:36
int m_autoFlush
Property: AutoFlush parameter for ROOT TTree (Number of events between auto flushes) ...
Definition: RootCnvSvc.h:82
const long ROOT_StorageType
Definition: ClassID.h:52
TClass * getClass(DataObject *pObject)
Helper: Get TClass for a given DataObject pointer.
Definition: RootCnvSvc.cpp:187