| The Gaudi Framework v30r0 (c919700c)

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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