All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
RootNTupleCnv.cpp
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
2 //
3 // Implementation of class : RootNTupleCnv
4 //
5 // Author : Markus Frank
6 //
7 //------------------------------------------------------------------------------
8 
9 #define ALLOW_ALL_TYPES
10 // Include files
11 #include "RootCnv/RootRefs.h"
12 #include "RootCnv/RootAddress.h"
13 #include "RootCnv/RootNTupleCnv.h"
15 
16 #include "GaudiKernel/NTuple.h"
17 #include "GaudiKernel/SmartIF.h"
18 #include "GaudiKernel/SmartRef.h"
19 #include "GaudiKernel/INTupleSvc.h"
20 #include "GaudiKernel/IRegistry.h"
24 
25 // ROOT include files
26 #include "TROOT.h"
27 #include "TTree.h"
28 #include "TBranch.h"
29 
30 #include <limits>
31 #include <memory>
32 
33 #define S_OK StatusCode::SUCCESS
34 #define S_FAIL StatusCode::FAILURE
35 
36 using namespace Gaudi;
37 using namespace std;
38 
39 static inline istream& loadLong(istream& is) {
40  long i;
41  is >> i;
42  return is;
43 }
44 static inline istream& operator>>(istream& is, IOpaqueAddress*& /*pObj*/)
45 { return loadLong(is); }
46 
47 #if 0
48 static inline istream& operator>>(istream& is, SmartRef<DataObject>& /*pObj*/)
49 { return loadLong(is); }
50 static inline istream& operator>>(istream& is, SmartRef<ContainedObject>& /*pObj*/)
51 { return loadLong(is); }
52 static inline istream& operator>>(istream& is, string& /*pObj*/)
53 { return loadLong(is); }
54 #endif
55 
56 template<class TYP> static
57 StatusCode createItem ( TTree* tree, INTuple* tuple, istream& is,const string& name,bool add,const TYP& null) {
58  string idxName;
59  long len, ndim, dim[4], hasIdx, idxLow, idxLen;
60  long dim1 = 1, dim2 = 1;
61  INTupleItem* it = nullptr;
62  char c;
63  is >> len >> c
64  >> ndim >> c
65  >> hasIdx >> c;
66  if ( hasIdx ) {
67  getline(is, idxName, ';') >> idxLow >> c >> idxLen >> c;
68  }
69  for ( int i = 0; i < ndim; i++ )
70  is >> dim[i] >> c;
71 
72  TYP low = null, high = null;
73  is >> low >> c >> high >> c;
74  is >> c;
75  switch( ndim )
76  {
77  case 0:
78  it = NTuple::_Item<TYP>::create (tuple, name, typeid(TYP), low, high, null);
79  break;
80  case 1:
81  dim1 = (hasIdx) ? idxLen : dim[0];
82  it = NTuple::_Array<TYP>::create (tuple,
83  name,
84  typeid(TYP),
85  idxName,
86  dim1,
87  low,
88  high,
89  null);
90  break;
91  case 2:
92  dim1 = (hasIdx) ? idxLen : dim[0];
93  dim2 = (hasIdx) ? dim[0] : dim[1];
94  it = NTuple::_Matrix<TYP>::create ( tuple,
95  name,
96  typeid(TYP),
97  idxName,
98  dim1,
99  dim2,
100  low,
101  high,
102  null);
103  break;
104  default:
105  return S_FAIL;
106  }
107  if ( add ) {
108  TBranch* b = tree->GetBranch(it->name().c_str());
109  if ( b ) {
110  b->SetAddress((void*)it->buffer());
111  }
112  else {
113  //return StatusCode::SUCCESS;
114  return tuple->add(it);
115  }
116  }
117  return tuple->add(it);
118 }
119 
120 template <class T> static inline void putRange(ostream& os, NTuple::_Data<T>* it) {
121  const NTuple::Range<T>& x = it->range();
122  os << x.lower() << ';' << x.upper() << ';';
123 }
124 
125 static inline string _tr(string s) {
126  string local = std::move(s);
127  auto p = std::begin(local);
128  if ( local.compare(0,7,"<local>")==0 ) p+=7;
129  std::replace_if(p,std::end(local),
130  [](const char& c) { return !isalnum(c); },
131  '_');
132  return local;
133 }
134 
135 // Converter overrides: Update the references of an updated transient object.
138  StatusCode status = S_FAIL;
139  RootDataConnection* con = nullptr;
140  IRegistry* pRegistry = pAddr->registry();
141  RootAddress* rpA = dynamic_cast<RootAddress*>(pAddr);
142  string path = fileName(pRegistry);
143  string cntName = containerName(pRegistry);
144  string* par = const_cast<string*>(pAddr->par());
145  status = m_dbMgr->connectDatabase(path,IDataConnection::READ,&con);
146  if ( status.isSuccess() ) {
147  string par_val, par_guid;
148  TBranch* b = con->getBranch("##Descriptors","GaudiStatisticsDescription");
149  if ( b ) {
152  b->SetAddress(&ptr);
153  for(Long64_t i=0, nent = b->GetEntries(); i<nent; ++i) {
154  int nb = b->GetEntry(i);
155  if ( nb > 1 ) {
156  if ( ptr->container == cntName ) {
157  par_val = ptr->description;
158  break;
159  }
160  }
161  }
162  }
163  par[2] = _tr(cntName);
164  TTree* tree = con->getSection(par[2]);
165  if ( nullptr == tree ) {
166  return makeError("Failed to access N-Tuple tree:"+cntName);
167  }
168  if ( !par_val.empty() ) {
169  auto ntupleSvc = dataProvider().as<INTupleSvc>();
170  if ( ntupleSvc ) {
171  char c;
172  CLID clid;
173  int siz, typ;
174  string title;
175  NTuple::Tuple* nt = nullptr;
176  istringstream is(par_val);
177  getline(is, title, ';') >> clid >> c >> siz >> c;
178  status = ntupleSvc->create(clid, title, nt);
179  for ( int j = 0; j < siz && status.isSuccess(); j++ ) {
180  is >> c;
181  getline(is, title, ';') >> typ >> c;
182  switch ( typ )
183  {
184  case DataTypeInfo::UCHAR:
185  status = createItem(tree, nt, is, title, true, (unsigned char)0);
186  break;
188  status = createItem(tree, nt, is, title, true, (unsigned short)0);
189  break;
190  case DataTypeInfo::UINT:
191  status = createItem(tree, nt, is, title, true, (unsigned int)0);
192  break;
193  case DataTypeInfo::ULONG:
194  status = createItem(tree, nt, is, title, true, (unsigned long)0);
195  break;
196  case DataTypeInfo::CHAR:
197  status = createItem(tree, nt, is, title, true, char(0));
198  break;
199  case DataTypeInfo::SHORT:
200  status = createItem(tree, nt, is, title, true, short(0));
201  break;
202  case DataTypeInfo::INT:
203  status = createItem(tree, nt, is, title, true, int(0));
204  break;
205  case DataTypeInfo::LONG:
206  status = createItem(tree, nt, is, title, true, long(0));
207  break;
208  case DataTypeInfo::BOOL:
209  status = createItem(tree, nt, is, title, true, false);
210  break;
211  case DataTypeInfo::FLOAT:
212  status = createItem(tree, nt, is, title, true, float(0.0));
213  break;
215  status = createItem(tree, nt, is, title, true, double(0.0));
216  break;
217  /*
218  case DataTypeInfo::NTCHAR:
219  case DataTypeInfo::LONG_NTCHAR:
220  status =
221  createItem(tree, nt, is, title, true, (char*)0);
222  break;
223  case DataTypeInfo::STRING:
224  case DataTypeInfo::LONG_STRING:
225  status =
226  createItem(tree, nt, is, title, true, string(""));
227  break;
228  */
230  status = createItem(tree, nt, is, title, false, (IOpaqueAddress*)nullptr);
231  break;
233  status = createItem(tree, nt, is, title, true, (void*)nullptr);
234  break;
236  default:
237  status = S_FAIL;
238  break;
239  }
240  if ( !status.isSuccess() ) {
241  log() << MSG::FATAL
242  << "Error connecting (Unknown) column:" << j << endmsg
243  << par_val << endmsg;
244  return makeError("createObj[NTuple]> Cannot determine column!");
245  }
246  }
247  if ( status.isSuccess() ) {
248  unsigned long* ipar = const_cast<unsigned long*>(rpA->ipar());
249  log() << MSG::DEBUG << "Created N-tuple with description:"
250  << par_val << endl;
251  ipar[0] = (unsigned long)con;
252  ipar[1] = ~0x0UL;
253  rpA->section = tree;
254  refpObject = nt;
255  }
256  else {
257  refpObject = nullptr;
258  if ( nt ) nt->release();
259  }
260  }
261  }
262  }
263  return status;
264 }
265 
266 // Update the transient object: NTuples end here when reading records
268  INTuple* tupl = dynamic_cast<INTuple*>(pObj);
269  RootAddress* rpA = dynamic_cast<RootAddress*>(pAddr);
270  if ( nullptr != tupl && nullptr != rpA ) {
271  RootDataConnection* con = (RootDataConnection*)rpA->ipar()[0];
272  if ( con ) {
273  TTree* tree = rpA->section;
274  if ( tree ) {
275  con->resetAge();
276  if ( con->tool()->refs() )
277  return i__updateObjRoot(rpA,tupl,tree,con);
278 #ifdef __POOL_COMPATIBILITY
279  // POOL compatibility mode:
280  return i__updateObjPool(rpA,tupl,tree,con);
281 #else
282  return makeError("Failed to access reference branch for data tree:"+rpA->par()[1]);
283 #endif
284  }
285  return makeError("Failed to access data tree:"+pAddr->par()[1]);
286  }
287  return makeError("updateObj> Failed to access data source!");
288  }
289  return makeError("updateObj> Invalid Tuple reference.");
290 }
291 
292 // Update the transient object: NTuples end here when reading records
294  typedef INTuple::ItemContainer Cont;
295  const string* par = rpA->par();
296  unsigned long* ipar = const_cast<unsigned long*>(rpA->ipar());
297  ++ipar[1];
298  if ( Long64_t(ipar[1]) <= tree->GetEntries() ) {
299  GenericAddress* pA = nullptr;
300  Cont& it = tupl->items();
301  size_t k, n = it.size();
302  vector<RootRef*> paddr(n);
303  vector<RootRef> addr(n);
304  for(k = 0; k < n; ++k) {
305  Cont::value_type j = it[k];
306  switch( j->type() )
307  {
309  paddr[k] = &addr[k];
310  tree->SetBranchAddress(j->name().c_str(),&paddr[k]);
311  break;
312  default:
313  break;
314  }
315  }
316 
317  ULong64_t last = (ULong64_t)tree->GetEntries();
318  ISelectStatement* sel = tupl->selector();
319  if ( sel ) {
320  string criteria = (sel && (sel->type() & ISelectStatement::STRING))
321  ? sel->criteria() : string("");
322  if ( !(criteria.length() == 0 || criteria == "*") ) {
323  if ( rpA->select == nullptr ) {
324  log() << MSG::DEBUG << "Selection criteria: " << criteria << " " << ipar[1] << endmsg;
325  rpA->select = new TTreeFormula(tree->GetName(),criteria.c_str(), tree);
326  }
327  rpA->select->SetTree(tree);
328  for( ; ipar[1] < last; ++ipar[1]) { // loop on all selected entries
329  tree->LoadTree(ipar[1]);
330  rpA->select->GetNdata();
331  if ( fabs(rpA->select->EvalInstance(0)) > std::numeric_limits<float>::epsilon() ) {
332  break;
333  }
334  log() << MSG::DEBUG << par[0] << "/" << par[1] << " SKIP Entry: " << ipar[1] << endmsg;
335  }
336  }
337  }
338  if ( ipar[1] < last ) {
339  unsigned long entry = ipar[1];
340  if ( tree->GetEntry(entry) > 1 ) {
341  RootRef *r = nullptr;
342  string *spar = nullptr;
343  for(k = 0; k < n; ++k) {
344  Cont::value_type j = it[k];
345  switch( j->type() )
346  {
348  r = paddr[k];
349  pA = (*(GenericAddress**)j->buffer());
350  if ( pA ) { // Fill only if item is connected!
351  spar = (string*)pA->par();
352  ipar = (unsigned long*)pA->ipar();
353  log() << MSG::DEBUG;
355  if ( ls.first ) {
356  if ( ls.first->dbase >= 0 ) {
357  // Now patch the references and links 'en block' to be efficient
358  // First the leafs from the TES
359 
360  r->dbase += ls.first->dbase;
361  r->container += ls.first->container;
362  r->link += ls.first->link;
363 
364  if ( log().isActive() ) {
365  log() << "Refs: LS [" << entry << "] -> "
366  << ls.first->dbase << "," << ls.first->container
367  << "," << ls.first->link
368  << "," << ls.first->entry
369  << " DB:" << con->getDb(r->dbase)
370  << endmsg;
371  }
372  }
373  }
374  spar[0] = con->getDb(r->dbase);
375  spar[1] = con->getCont(r->container);
376  spar[2] = con->getLink(r->link);
377  ipar[0] = 0;
378  ipar[1] = r->entry;
379  pA->setClID(r->clid);
380  pA->setSvcType(r->svc);
381  break;
382  }
383  break;
384  default:
385  break;
386  }
387  }
388  return StatusCode::SUCCESS;
389  }
390  log() << MSG::ERROR << "Failed to read data from NTuple tree." << endmsg;
391  return StatusCode::FAILURE;
392  }
393  log() << MSG::INFO << "End of input Ntuple." << endmsg;
394  return StatusCode::FAILURE;
395  }
396  return StatusCode::FAILURE;
397 }
398 
401  IRegistry* pRegistry = pObj->registry();
402  if ( nullptr != pRegistry ) {
403  pAddr = pRegistry->address();
404  if ( nullptr != pAddr ) {
405  return S_OK;
406  }
407 
408  RootDataConnection* con = nullptr;
409  string path = fileName(pRegistry);
410  string cntName = containerName(pRegistry);
411  string secName = cntName.c_str();
412  const INTuple* nt = dynamic_cast<const INTuple*>(pObj);
413  StatusCode status = m_dbMgr->connectDatabase(path, IDataConnection::UPDATE, &con);
414  if ( !status.isSuccess() ) {
415  return makeError("Failed to access Tuple file:"+path);
416  }
417  TTree* tree = con->getSection(_tr(secName),true);
418  if ( nullptr != nt ) {
419  const INTuple::ItemContainer& items = nt->items();
420  ostringstream os;
421  size_t item_no;
422  string desc;
423  os << nt->title()<<';'<<pObj->clID()<<';'<<items.size()<< ';';
424  map<string,TBranch*> branches;
425  TBranch* b = nullptr;
426  for(item_no = 0; item_no < items.size(); ++item_no ) {
427  INTupleItem* it = items[item_no];
428  if ( it->hasIndex() ) {
429  INTupleItem* itm = it->indexItem();
430  const string& n = itm->name();
431  switch( itm->type() )
432  {
433  case DataTypeInfo::UCHAR:
434  desc = n+"/b";
435  b = tree->Branch(n.c_str(),(void*)itm->buffer(),desc.c_str());
436  break;
438  desc = n+"/s";
439  b = tree->Branch(n.c_str(),(void*)itm->buffer(),desc.c_str());
440  break;
441  case DataTypeInfo::UINT:
442  desc = n+"/i";
443  b = tree->Branch(n.c_str(),(void*)itm->buffer(),desc.c_str());
444  break;
445  case DataTypeInfo::ULONG:
446  desc = n+"/l";
447  b = tree->Branch(n.c_str(),(void*)itm->buffer(),desc.c_str());
448  break;
449  case DataTypeInfo::CHAR:
450  desc = n+"/B";
451  b = tree->Branch(n.c_str(),(void*)itm->buffer(),desc.c_str());
452  break;
453  case DataTypeInfo::SHORT:
454  desc = n+"/S";
455  b = tree->Branch(n.c_str(),(void*)itm->buffer(),desc.c_str());
456  break;
457  case DataTypeInfo::INT:
458  desc = n+"/I";
459  b = tree->Branch(n.c_str(),(void*)itm->buffer(),desc.c_str());
460  break;
461  case DataTypeInfo::LONG:
462  desc = n+"/L";
463  b = tree->Branch(n.c_str(),(void*)itm->buffer(),desc.c_str());
464  break;
465  default:
466  return makeError("Column "+it->index()+" is not a valid index column!");
467  }
468  branches[n] = b;
469  }
470  }
471  for(item_no = 0; item_no < items.size(); ++item_no ) {
472  INTupleItem* it = items[item_no];
473  const string& n = it->name();
474  os << '{'
475  << n << ';'
476  << it->type() << ';'
477  << it->length() << ';'
478  << it->ndim() << ';'
479  << it->hasIndex() << ';';
480  if ( it->hasIndex() ) {
481  os << it->index() << ';';
482  INTupleItem* itm = it->indexItem();
483  switch( itm->type() )
484  {
485  case DataTypeInfo::UCHAR:
486  putRange(os, dynamic_cast<NTuple::_Data<unsigned char>*>(itm));
487  break;
489  putRange(os, dynamic_cast<NTuple::_Data<unsigned short>*>(itm));
490  break;
491  case DataTypeInfo::UINT:
492  putRange(os, dynamic_cast<NTuple::_Data<unsigned int>*>(itm));
493  break;
494  case DataTypeInfo::ULONG:
495  putRange(os, dynamic_cast<NTuple::_Data<unsigned long>*>(itm));
496  break;
497  case DataTypeInfo::CHAR:
498  putRange(os, dynamic_cast<NTuple::_Data<char>*>(itm));
499  break;
500  case DataTypeInfo::SHORT:
501  putRange(os, dynamic_cast<NTuple::_Data<short>*>(itm));
502  break;
503  case DataTypeInfo::INT:
504  putRange(os, dynamic_cast<NTuple::_Data<int>*>(itm));
505  break;
506  case DataTypeInfo::LONG:
507  putRange(os, dynamic_cast<NTuple::_Data<long>*>(itm));
508  break;
509  default:
510  return makeError("NTuple:"+pRegistry->name()+" Column "+it->index()+
511  " is not a valid index column!");
512  }
513  }
514  for ( long k = 0; k < it->ndim(); k++ ) {
515  os << it->dim(k) << ';';
516  }
517  desc = n;
518  TClass* cl = nullptr;
519  switch(it->type())
520  {
522  desc = "/C";
523  os << 0 << ';' << 0 << ';';
524  break;
526  desc = "/C";
527  os << 0 << ';' << 0 << ';';
528  break;
530  if ( it->length() == 1 ) {
531  desc = System::typeinfoName(typeid(RootRef));
532  os << 0 << ';' << 0 << ';';
533  cl = TClass::GetClass(desc.c_str(),kTRUE);
534  }
535  break;
537  if ( it->length() == 1 ) {
538  os << 0 << ';' << 0 << ';';
539  cl = TClass::GetClass(it->typeID(), kTRUE);
540  }
541  break;
542  case DataTypeInfo::UCHAR:
543  desc = "/b";
544  putRange(os, dynamic_cast<NTuple::_Data<unsigned char>*>(it));
545  break;
547  desc = "/s";
548  putRange(os, dynamic_cast<NTuple::_Data<unsigned short>*>(it));
549  break;
550  case DataTypeInfo::UINT:
551  desc = "/i";
552  putRange(os, dynamic_cast<NTuple::_Data<unsigned int>*>(it));
553  break;
554  case DataTypeInfo::ULONG:
555  desc = "/l";
556  putRange(os, dynamic_cast<NTuple::_Data<unsigned long>*>(it));
557  break;
558  case DataTypeInfo::CHAR:
559  desc = "/B";
560  putRange(os, dynamic_cast<NTuple::_Data<char>*>(it));
561  break;
562  case DataTypeInfo::SHORT:
563  desc = "/S";
564  putRange(os, dynamic_cast<NTuple::_Data<short>*>(it));
565  break;
566  case DataTypeInfo::INT:
567  desc = "/I";
568  putRange(os, dynamic_cast<NTuple::_Data<int>*>(it));
569  break;
570  case DataTypeInfo::LONG:
571  desc = "/L";
572  putRange(os, dynamic_cast<NTuple::_Data<long>*>(it));
573  break;
574  case DataTypeInfo::BOOL:
575  desc = "/b";
576  putRange(os, dynamic_cast<NTuple::_Data<bool>*>(it));
577  break;
578  case DataTypeInfo::FLOAT:
579  desc = "/F";
580  putRange(os, dynamic_cast<NTuple::_Data<float>*>(it));
581  break;
583  desc = "/D";
584  putRange(os, dynamic_cast<NTuple::_Data<double>*>(it));
585  break;
587  default:
588  return makeError("Create item[FAIL]: "+it->name());
589  }
590  os << '}';
591  if ( branches.find(n) == branches.end() ) {
592  string tmp;
593  char text[32];
594  switch(it->ndim())
595  {
596  case 0:
597  desc = n+desc;
598  break;
599  case 2:
600  sprintf(text,"[%ld]",it->dim(0));
601  tmp = text;
602  case 1:
603  if ( it->hasIndex() ) {
604  INTupleItem* itm = it->indexItem();
605  desc = n + tmp + "[" + itm->name() + "]" + desc;
606  }
607  else {
608  sprintf(text,"[%ld]",it->dim(0));
609  desc = n + tmp + text + desc;
610  }
611  }
612  log() << MSG::DEBUG << "Create branch:" << n << " Desc:" << desc
613  << " of type:" << it->type() << endmsg;
614  switch(it->type())
615  {
617  branches[n] = tree->Branch(n.c_str(),cl->GetName(),(void*)it->buffer());
618  break;
620  branches[n] = tree->Branch(n.c_str(),cl->GetName(),(void*)it->buffer());
621  break;
622  default:
623  branches[n] = tree->Branch(n.c_str(),(void*)it->buffer(),desc.c_str());
624  break;
625  }
626  }
627  }
628 
629  log() << MSG::DEBUG << "Save description:" << path << " -> " << cntName << endmsg
630  << os.str() << endmsg;
631  status = saveDescription(path,cntName,os.str(),"",pObj->clID());
632  if ( status.isSuccess() ) {
633  status = m_dbMgr->commitOutput(path, true);
634  if ( status.isSuccess() ) {
635  string spar[] = { path, cntName};
636  unsigned long ipar[] = { (unsigned long)con, ~0x0u };
637  status = m_dbMgr->createAddress(repSvcType(),pObj->clID(),spar,ipar,pAddr);
638  if ( status.isSuccess() ) {
639  RootAddress* rpA = dynamic_cast<RootAddress*>(pAddr);
640  ((unsigned long*)rpA->ipar())[0] = (unsigned long)con;
641  rpA->section = tree;
642  }
643  else {
644  pAddr->release();
645  pAddr = nullptr;
646  }
647  }
648  }
649  return status;
650  }
651  }
652  return S_FAIL;
653 }
654 
655 // Resolve the references of the converted object.
657  typedef INTuple::ItemContainer Cont;
658  INTuple* tupl = dynamic_cast<INTuple*>(pObj);
659  IRegistry* pReg = pObj->registry();
660  RootAddress* rpA = dynamic_cast<RootAddress*>(pAddr);
661  if ( tupl && pReg && rpA ) {
662  string cntName = containerName(pReg);
663  unsigned long* ipar = const_cast<unsigned long*>(pAddr->ipar());
664  RootDataConnection* con = (RootDataConnection*)rpA->ipar()[0];
665  if ( con ) {
666  TTree* tree = rpA->section;
667  if ( tree ) {
668  Cont& it = tupl->items();
669  size_t k, n = it.size();
670  vector<RootRef*> paddr(n);
671  vector<RootRef> addr(n);
672  for(k = 0; k < n; ++k) {
673  IOpaqueAddress* pA = nullptr;
674  Cont::value_type j = it[k];
675  switch( j->type() )
676  {
678  pA = (*(IOpaqueAddress**)j->buffer());
679  paddr[k] = &addr[k];
680  addr[k].reset();
681  if ( pA ) {
682  con->makeRef(pA->registry(),addr[k]);
683  addr[k].entry = pA->ipar()[1];
684  }
685  tree->SetBranchAddress(j->name().c_str(),&paddr[k]);
686  break;
687  default:
688  break;
689  }
690  }
691  int nb = tree->Fill();
692  if ( nb>1 ) ++ipar[1];
693  for(k = 0; k < n; ++k) it[k]->reset();
695  }
696  return makeError("fillRepRefs> Failed to access data tree:"+cntName);
697  }
698  return makeError("fillRepRefs> Failed to access data source!");
699  }
700  return makeError("fillRepRefs> Invalid Tuple reference.");
701 }
702 
703 #ifdef __POOL_COMPATIBILITY
704 #include "RootCnv/PoolClasses.h"
705 
706 // Compatibility code to access ETCs, which were written using POOL
707 
708 namespace {
709  // Blob I/O helper class
710  class IOBuffer : public StreamBuffer {
711  public:
712  UCharDbArray d;
713  IOBuffer() = default;
714  virtual ~IOBuffer() { m_pointer=0; m_length=0; m_buffer=nullptr;}
715  void start() {m_pointer=0; m_buffer=(char*)d.m_buffer; m_length=d.m_size;}
716  };
717 }
718 
719 // Helper to read
720 template <class T> static inline int load(int blob, IOBuffer& s, void* buff) {
721  if ( blob ) {
722  int len;
723  s >> len;
724  s.swapFromBuffer(buff, len*sizeof(T));
725  }
726  return 0;
727 }
728 
729 // Helper to read specialized for strings
730 template <> inline int load<string>(int blob, IOBuffer& s, void* ptr) {
731  if ( blob ) {
732  string* str = (string*)ptr;
733  s >> (*str);
734  }
735  return 0;
736 }
737 
738 // Update the transient object: NTuples end here when reading records
739 StatusCode RootNTupleCnv::i__updateObjPool(RootAddress* rpA, INTuple* tupl, TTree* tree, RootDataConnection* con) {
740  typedef INTuple::ItemContainer Cont;
741  const string* par = rpA->par();
742  unsigned long* ipar = const_cast<unsigned long*>(rpA->ipar());
743  ++ipar[1];
744  if ( Long64_t(ipar[1]) <= tree->GetEntries() ) {
745  Cont& it = tupl->items();
746  size_t k, n = it.size();
747  vector<PoolDbTokenWrap*> paddr(n);
748  vector<PoolDbTokenWrap> addr(n);
749  vector<int> blob_items(n,0);
750  for(k = 0; k < n; ++k) {
751  Cont::value_type j = it[k];
752  switch( j->type() )
753  {
755  paddr[k] = &addr[k];
756  tree->SetBranchAddress(j->name().c_str(),&paddr[k]);
757  break;
758  default:
759  if ( nullptr == tree->GetBranch(j->name().c_str()) ) blob_items[k] = 1;
760  break;
761  }
762  }
763  ULong64_t last = (ULong64_t)tree->GetEntries();
764  ISelectStatement* sel = tupl->selector();
765  if ( sel ) {
766  string criteria = (sel && (sel->type() & ISelectStatement::STRING))
767  ? sel->criteria() : string("");
768  if ( !(criteria.length() == 0 || criteria == "*") ) {
769  if ( rpA->select == nullptr ) {
770  log() << MSG::DEBUG << "Selection criteria: " << criteria << " " << ipar[1] << endmsg;
771  rpA->select = new TTreeFormula(tree->GetName(),criteria.c_str(), tree);
772  }
773  rpA->select->SetTree(tree);
774  // loop on all selected entries
775  for( ; ipar[1] < last; ++ipar[1]) {
776  tree->LoadTree(ipar[1]);
777  rpA->select->GetNdata();
778  if ( fabs(rpA->select->EvalInstance(0)) > std::numeric_limits<float>::epsilon() ) {
779  break;
780  }
781  log() << MSG::DEBUG << par[0] << "/" << par[1] << " SKIP Entry: " << ipar[1] << endmsg;
782  }
783  }
784  }
785  if ( ipar[1] < last ) {
786  IOBuffer blob;
787  UCharDbArray *pblob = &blob.d;
788  tree->GetBranch("BlobData")->SetAddress(&pblob);
789  if ( tree->GetEntry(ipar[1]) > 1 ) {
790  int sc = 0;
791  blob.start();
792  for(k = 0; k < n; ++k) {
793  Cont::value_type j = it[k];
794  char* buf = (char*)j->buffer();
795  switch( j->type() )
796  {
798  RootRef r = con->tool()->poolRef(addr[k].token.m_oid.first);
799  GenericAddress* pA = (*(GenericAddress**)buf);
800  if ( pA ) { // Fill only if item is connected!
801  string *spar = (string*)pA->par();
802  ipar = (unsigned long*)pA->ipar();
803  spar[0] = con->getDb(r.dbase);
804  spar[1] = con->getCont(r.container);
805  spar[2] = con->getLink(r.link);
806  ipar[0] = 0;
807  ipar[1] = addr[k].token.m_oid.second;
808  if ( r.svc == POOL_ROOT_StorageType ||
811  r.svc = ROOT_StorageType;
812  }
813  pA->setClID(r.clid);
814  pA->setSvcType(r.svc);
815  break;
816  }
817  sc = 11;
818  break;
819  }
820  case DataTypeInfo::UCHAR: sc=load<unsigned char> (blob_items[k],blob,buf); break;
821  case DataTypeInfo::USHORT: sc=load<unsigned short>(blob_items[k],blob,buf); break;
822  case DataTypeInfo::UINT: sc=load<unsigned int> (blob_items[k],blob,buf); break;
823  case DataTypeInfo::ULONG: sc=load<unsigned long> (blob_items[k],blob,buf); break;
824  case DataTypeInfo::CHAR: sc=load<char> (blob_items[k],blob,buf); break;
825  case DataTypeInfo::SHORT: sc=load<short> (blob_items[k],blob,buf); break;
826  case DataTypeInfo::INT: sc=load<int> (blob_items[k],blob,buf); break;
827  case DataTypeInfo::LONG: sc=load<long> (blob_items[k],blob,buf); break;
828  case DataTypeInfo::BOOL: sc=load<bool> (blob_items[k],blob,buf); break;
829  case DataTypeInfo::FLOAT: sc=load<float> (blob_items[k],blob,buf); break;
830  case DataTypeInfo::DOUBLE: sc=load<double> (blob_items[k],blob,buf); break;
831  case DataTypeInfo::STRING: sc=load<string> (blob_items[k],blob,buf); break;
832  case DataTypeInfo::NTCHAR: sc=load<char*> (blob_items[k],blob,buf); break;
833  case DataTypeInfo::POINTER: sc = 0; break;
834  case DataTypeInfo::UNKNOWN: break;
835  default: break;
836  }
837  if ( sc ) {
838  log() << MSG::DEBUG;
839  switch (sc)
840  {
841  case 10:
842  log() << "CANNOT Set Ntuple token: dynamic_cast<GenericAddress*> is NULL";
843  break;
844  case 11:
845  log() << "CANNOT Set Ntuple token: invalid address buffer";
846  break;
847  }
848  log() << endmsg;
849  }
850  }
851  return StatusCode::SUCCESS;
852  }
853  log() << MSG::ERROR << "Failed to read data from NTuple tree." << endmsg;
854  return StatusCode::FAILURE;
855  }
856  log() << MSG::INFO << "End of input Ntuple." << endmsg;
857  return StatusCode::FAILURE;
858  }
859  return StatusCode::FAILURE;
860 }
861 #endif
virtual const std::string & name() const =0
Access _Item name.
virtual const ItemRange & range() const =0
Access the range if specified.
T empty(T...args)
Description:
Definition: RootAddress.h:36
A select statement can either contain.
virtual RootRef poolRef(size_t) const
Internal overload to facilitate the access to POOL files.
TTree * section
Pointer to ROOT TTree (filled for N-tuples only)
Definition: RootAddress.h:41
const std::string & getDb(int which) const
Access database/file name from saved index.
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:299
void setSvcType(long typ)
Access : set the storage type of the class id.
The stream buffer is a small object collecting object data.
Definition: StreamBuffer.h:41
bool isSuccess() const
Test for a status code of SUCCESS.
Definition: StatusCode.h:74
int m_size
Size of buffer.
Definition: PoolClasses.h:44
T isalnum(T...args)
T getline(T...args)
TTree * getSection(const std::string &sect, bool create=false)
Access TTree section from section name. The section is created if required.
virtual StatusCode add(INTupleItem *item)=0
Add an item row to the N tuple.
T endl(T...args)
sel
Definition: IOTest.py:84
virtual IRegistry * registry() const =0
Update branch name.
STL namespace.
virtual const name_type & name() const =0
Name of the directory (or key)
#define S_FAIL
const std::string & getLink(int which) const
Access link name from saved index.
T end(T...args)
virtual unsigned long release()=0
release reference to object
Generic Transient Address.
virtual ISelectStatement * selector()=0
Access selector.
virtual const std::string * par() const =0
Retrieve String parameters.
STL class.
STL class.
IRegistry * registry() const
Get pointer to Registry.
Definition: DataObject.h:74
Shadow class to mimik POOL blobs.
Definition: PoolClasses.h:41
static _Array * create(INTuple *tup, const std::string &name, const std::type_info &info, const std::string &index, long len, TYP min, TYP max, TYP def)
Create instance.
Definition: NTupleItems.cpp:32
STL class.
const long POOL_ROOTKEY_StorageType
Definition: ClassID.h:69
NTuple interface class definition.
Definition: INTuple.h:79
virtual const std::string & criteria() const =0
Access the selection string.
int dbase
Data members to define object location in the persistent world.
Definition: RootRefs.h:32
Persistent reference object.
Definition: RootRefs.h:30
virtual long ndim() const =0
Dimension.
StreamBuffer & operator>>(StreamBuffer &s, std::vector< T > &v)
Definition: StreamBuffer.h:653
NTuple interface class definition.
Definition: INTuple.h:26
void setClID(const CLID &clid)
Access : Set class ID of the link.
virtual const CLID & clID() const
Retrieve reference to class definition structure.
Definition: DataObject.cpp:68
virtual const unsigned long * ipar() const =0
Access to generic link parameters.
virtual INTupleItem * indexItem()=0
Pointer to index column (if present, 0 else)
T replace_if(T...args)
virtual long length() const =0
Access the buffer length.
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:26
const unsigned long * ipar() const override
Retrieve integer parameters.
const std::string * par() const override
Retrieve string parameters.
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.
std::string description
Description string.
Definition: RootRefs.h:79
std::pair< const RootRef *, const ContainerSection * > getMergeSection(const std::string &container, int entry) const
Access link section for single container and entry.
start
Definition: IOTest.py:88
The IRegistry represents the entry door to the environment any data object residing in a transient da...
Definition: IRegistry.h:22
const long ROOT_StorageType
Definition: ClassID.h:52
const std::string & getCont(int which) const
Access container name from saved index.
TYP upper() const
Upper boundary of range.
Definition: NTuple.h:72
Abstract class describing basic data in an Ntuple.
Definition: NTuple.h:37
unsigned int CLID
Class ID definition.
Definition: ClassID.h:8
const long POOL_ROOT_StorageType
Definition: ClassID.h:68
virtual long type() const =0
Type information of the item.
T fabs(T...args)
T move(T...args)
Tool * tool() const
Access tool.
Abstract base class which allows the user to interact with the actual N tuple implementation.
Definition: NTuple.h:370
StatusCode createRep(DataObject *pObj, IOpaqueAddress *&refpAdd) override
Converter overrides: Convert the transient object to the requested representation.
virtual unsigned long release()
release reference to object
Definition: DataObject.cpp:56
virtual const void * buffer() const =0
Access data buffer (CONST)
StatusCode fillRepRefs(IOpaqueAddress *pAdd, DataObject *pObj) override
Resolve the references of the converted object.
T find(T...args)
T length(T...args)
STL class.
STL class.
const long POOL_ROOTTREE_StorageType
Definition: ClassID.h:70
unsigned char * m_buffer
Buffer with object content.
Definition: PoolClasses.h:46
T begin(T...args)
StatusCode updateObj(IOpaqueAddress *pAddress, DataObject *pObject) override
Update the transient object: NTuples end here when reading records.
void resetAge()
Reset age.
virtual const std::string & index() const =0
Access the index _Item.
std::string container
Identifier of description.
Definition: RootRefs.h:83
T c_str(T...args)
string s
Definition: gaudirun.py:245
Class defining a range.
Definition: NTuple.h:36
virtual long dim(long i) const =0
Access individual dimensions.
#define S_OK
virtual ItemContainer & items()=0
Access item container.
static _Item * create(INTuple *tup, const std::string &name, const std::type_info &info, TYP min, TYP max, TYP def)
Create instance.
Definition: NTupleItems.cpp:26
TTreeFormula * select
Pointer to ROOT select statement (filled for N-tuples only)
Definition: RootAddress.h:39
virtual bool hasIndex() const =0
Is the tuple have an index item?
Opaque address interface definition.
StatusCode i__updateObjRoot(RootAddress *rpA, INTuple *tupl, TTree *tree, RootDataConnection *con)
Update the transient object: NTuples end here when reading records.
StatusCode createObj(IOpaqueAddress *pAddress, DataObject *&refpObject) override
Converter overrides: Update the references of an updated transient object.
virtual IOpaqueAddress * address() const =0
Retrieve opaque storage address.
virtual const std::type_info & typeID() const =0
Compiler type ID.
virtual long type() const =0
Access the type of the object.
A DataObject is the base class of any identifiable object on any data store.
Definition: DataObject.h:30
Concrete implementation of the IDataConnection interface to access ROOT files.
T sprintf(T...args)
STL class.
virtual const std::string & title() const =0
Object title.
Helper functions to set/get the application return code.
Definition: __init__.py:1
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:244
TYP lower() const
Lower boundary of range.
Definition: NTuple.h:70
T compare(T...args)
static _Matrix * create(INTuple *tup, const std::string &name, const std::type_info &info, const std::string &index, long ncol, long nrow, TYP min, TYP max, TYP def)
Create instance.
Definition: NTupleItems.cpp:38