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