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