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