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