The Gaudi Framework  master (181af51f)
Loading...
Searching...
No Matches
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>
24#include <RootCnv/RootRefs.h>
25
30#include <GaudiKernel/NTuple.h>
31#include <GaudiKernel/SmartIF.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
46using namespace Gaudi;
47using namespace std;
48
49static inline istream& loadLong( istream& is ) {
50 long i;
51 is >> i;
52 return is;
53}
54static inline istream& operator>>( istream& is, IOpaqueAddress*& /*pObj*/ ) { return loadLong( is ); }
55
56#if 0
57static inline istream& operator>>(istream& is, SmartRef<DataObject>& /*pObj*/)
58{ return loadLong(is); }
59static inline istream& operator>>(istream& is, SmartRef<ContainedObject>& /*pObj*/)
60{ return loadLong(is); }
61static inline istream& operator>>(istream& is, string& /*pObj*/)
62{ return loadLong(is); }
63#endif
64
65template <class TYP>
66static 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
108template <class T>
109static 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
114static 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;
118 std::replace_if(
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 ) {
138 std::unique_ptr<RootNTupleDescriptor> dsc( ptr = new RootNTupleDescriptor() );
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 ) {
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;
175 status = createItem( tree, nt, is, title, true, 0u );
176 break;
178 status = createItem( tree, nt, is, title, true, 0ul );
179 break;
181 status = createItem( tree, nt, is, title, true, char( 0 ) );
182 break;
184 status = createItem( tree, nt, is, title, true, short( 0 ) );
185 break;
187 status = createItem( tree, nt, is, title, true, 0 );
188 break;
190 status = createItem( tree, nt, is, title, true, 0l );
191 break;
193 status = createItem( tree, nt, is, title, true, false );
194 break;
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;
322 pair<const RootRef*, const RootDataConnection::ContainerSection*> ls =
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() ) {
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;
402 desc = n + "/i";
403 b = tree->Branch( n.c_str(), const_cast<void*>( itm->buffer() ), desc.c_str() );
404 break;
406 desc = n + "/l";
407 b = tree->Branch( n.c_str(), const_cast<void*>( itm->buffer() ), desc.c_str() );
408 break;
410 desc = n + "/B";
411 b = tree->Branch( n.c_str(), const_cast<void*>( itm->buffer() ), desc.c_str() );
412 break;
414 desc = n + "/S";
415 b = tree->Branch( n.c_str(), const_cast<void*>( itm->buffer() ), desc.c_str() );
416 break;
418 desc = n + "/I";
419 b = tree->Branch( n.c_str(), const_cast<void*>( itm->buffer() ), desc.c_str() );
420 break;
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() ) {
440 putRange( os, dynamic_cast<NTuple::_Data<unsigned char>*>( itm ) );
441 break;
443 putRange( os, dynamic_cast<NTuple::_Data<unsigned short>*>( itm ) );
444 break;
446 putRange( os, dynamic_cast<NTuple::_Data<unsigned int>*>( itm ) );
447 break;
449 putRange( os, dynamic_cast<NTuple::_Data<unsigned long>*>( itm ) );
450 break;
452 putRange( os, dynamic_cast<NTuple::_Data<char>*>( itm ) );
453 break;
455 putRange( os, dynamic_cast<NTuple::_Data<short>*>( itm ) );
456 break;
458 putRange( os, dynamic_cast<NTuple::_Data<int>*>( itm ) );
459 break;
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;
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;
502 desc = "/i";
503 putRange( os, dynamic_cast<NTuple::_Data<unsigned int>*>( it ) );
504 break;
506 desc = "/l";
507 putRange( os, dynamic_cast<NTuple::_Data<unsigned long>*>( it ) );
508 break;
510 desc = "/B";
511 putRange( os, dynamic_cast<NTuple::_Data<char>*>( it ) );
512 break;
514 desc = "/S";
515 putRange( os, dynamic_cast<NTuple::_Data<short>*>( it ) );
516 break;
518 desc = "/I";
519 putRange( os, dynamic_cast<NTuple::_Data<int>*>( it ) );
520 break;
522 desc = "/L";
523 putRange( os, dynamic_cast<NTuple::_Data<long>*>( it ) );
524 break;
526 desc = "/b";
527 putRange( os, dynamic_cast<NTuple::_Data<bool>*>( it ) );
528 break;
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();
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
658namespace {
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
678template <class T>
679static 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
689template <>
690inline 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
699StatusCode 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;
766 }
767 pA->setClID( r.clid );
768 pA->setSvcType( r.svc );
769 break;
770 }
771 sc = 11;
772 break;
773 }
775 sc = load<unsigned char>( blob_items[k], blob, buf );
776 break;
778 sc = load<unsigned short>( blob_items[k], blob, buf );
779 break;
781 sc = load<unsigned int>( blob_items[k], blob, buf );
782 break;
784 sc = load<unsigned long>( blob_items[k], blob, buf );
785 break;
787 sc = load<char>( blob_items[k], blob, buf );
788 break;
790 sc = load<short>( blob_items[k], blob, buf );
791 break;
793 sc = load<int>( blob_items[k], blob, buf );
794 break;
796 sc = load<long>( blob_items[k], blob, buf );
797 break;
799 sc = load<bool>( blob_items[k], blob, buf );
800 break;
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
const long POOL_ROOTKEY_StorageType
Definition ClassID.h:77
unsigned int CLID
Class ID definition.
Definition ClassID.h:16
const long POOL_ROOT_StorageType
Definition ClassID.h:76
const long POOL_ROOTTREE_StorageType
Definition ClassID.h:78
const long ROOT_StorageType
Definition ClassID.h:60
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition MsgStream.h:198
#define S_OK
#define S_FAIL
StreamBuffer & operator>>(StreamBuffer &s, std::vector< T > &v)
SmartIF< IDataProviderSvc > & dataProvider() const override
Get Data provider service.
Definition Converter.cpp:77
A DataObject is the base class of any identifiable object on any data store.
Definition DataObject.h:37
IRegistry * registry() const
Get pointer to Registry.
Definition DataObject.h:79
virtual const CLID & clID() const
Retrieve reference to class definition structure.
virtual unsigned long release()
release reference to object
void resetAge()
Reset age.
Description:
Definition RootAddress.h:45
TTreeFormula * select
Pointer to ROOT select statement (filled for N-tuples only)
Definition RootAddress.h:48
TTree * section
Pointer to ROOT TTree (filled for N-tuples only)
Definition RootAddress.h:50
RootCnvSvc * m_dbMgr
Conversion service needed for proper operation to forward requests.
long repSvcType() const override
Retrieve the class type of the data store the converter uses.
virtual RootRef poolRef(size_t) const
Internal overload to facilitate the access to POOL files.
Concrete implementation of the IDataConnection interface to access ROOT files.
const std::string & getLink(int which) const
Access link name from saved index.
Tool * tool() const
Access tool.
TTree * getSection(std::string_view sect, bool create=false)
Access TTree section from section name. The section is created if required.
TBranch * getBranch(std::string_view section, std::string_view branch_name)
Access data branch by name: Get existing branch in read only mode.
void makeRef(const IRegistry &pA, RootRef &ref)
Create reference object from registry entry.
const std::string & getDb(int which) const
Access database/file name from saved index.
std::pair< const RootRef *, const ContainerSection * > getMergeSection(std::string_view container, int entry) const
Access link section for single container and entry.
const std::string & getCont(int which) const
Access container name from saved index.
StatusCode fillRepRefs(IOpaqueAddress *pAdd, DataObject *pObj) override
Resolve the references of the converted object.
StatusCode i__updateObjRoot(RootAddress *rpA, INTuple *tupl, TTree *tree, RootDataConnection *con)
Update the transient object: NTuples end here when reading records.
StatusCode createRep(DataObject *pObj, IOpaqueAddress *&refpAdd) override
Converter overrides: Convert the transient object to the requested representation.
StatusCode createObj(IOpaqueAddress *pAddress, DataObject *&refpObject) override
Converter overrides: Update the references of an updated transient object.
StatusCode updateObj(IOpaqueAddress *pAddress, DataObject *pObject) override
Update the transient object: NTuples end here when reading records.
StatusCode saveDescription(const std::string &path, const std::string &ident, const std::string &desc, const std::string &opt, const CLID &clid)
Save statistics object description.
virtual const std::string fileName(IRegistry *pReg) const
Retrieve the name of the file a given object is placed into.
StatusCode makeError(const std::string &msg, bool throw_exception=false) const
Helper method to issue error messages.
MsgStream & log() const
Helper to use mesage logger.
Definition RootStatCnv.h:47
virtual const std::string containerName(IRegistry *pDir) const
Retrieve the name of the container a given object is placed into.
Generic Transient Address.
void setClID(const CLID &clid)
Access : Set class ID of the link.
const std::string * par() const override
Retrieve string parameters.
const unsigned long * ipar() const override
Retrieve integer parameters.
void setSvcType(long typ)
Access : set the storage type of the class id.
NTuple interface class definition.
Definition INTuple.h:86
std::vector< INTupleItem * > ItemContainer
Definition INTuple.h:93
virtual ISelectStatement * selector()=0
Access selector.
virtual ItemContainer & items()=0
Access item container.
virtual const std::string & title() const =0
Object title.
NTuple interface class definition.
Definition INTuple.h:32
virtual long ndim() const =0
Dimension.
virtual const void * buffer() const =0
Access data buffer (CONST)
virtual long dim(long i) const =0
Access individual dimensions.
virtual const std::string & index() const =0
Access the index _Item.
virtual const std::type_info & typeID() const =0
Compiler type ID.
virtual long type() const =0
Type information of the item.
virtual long length() const =0
Access the buffer length.
virtual INTupleItem * indexItem()=0
Pointer to index column (if present, 0 else)
virtual const std::string & name() const =0
Access _Item name.
virtual bool hasIndex() const =0
Is the tuple have an index item?
Opaque address interface definition.
virtual unsigned long release()=0
release reference to object
virtual const unsigned long * ipar() const =0
Access to generic link parameters.
virtual const std::string * par() const =0
Retrieve String parameters.
virtual IRegistry * registry() const =0
Update branch name.
The IRegistry represents the entry door to the environment any data object residing in a transient da...
Definition IRegistry.h:29
virtual const name_type & name() const =0
Name of the directory (or key)
virtual IOpaqueAddress * address() const =0
Retrieve opaque storage address.
A select statement can either contain.
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.
Abstract class describing basic data in an Ntuple.
Definition NTuple.h:122
virtual const ItemRange & range() const =0
Access the range if specified.
static _Item * create(INTuple *tup, const std::string &name, const std::type_info &info, TYP min, TYP max, TYP def)
Create instance.
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.
Class defining a range.
Definition NTuple.h:58
TYP lower() const
Lower boundary of range.
Definition NTuple.h:78
TYP upper() const
Upper boundary of range.
Definition NTuple.h:80
Abstract base class which allows the user to interact with the actual N tuple implementation.
Definition NTuple.h:380
SmartIF< IFace > as() const
return a new SmartIF instance to another interface
Definition SmartIF.h:110
Kernel objects: SmartRef.
Definition SmartRef.h:64
This class is used for returning status codes from appropriate routines.
Definition StatusCode.h:64
bool isSuccess() const
Definition StatusCode.h:314
constexpr static const auto SUCCESS
Definition StatusCode.h:99
constexpr static const auto FAILURE
Definition StatusCode.h:100
The stream buffer is a small object collecting object data.
This file provides a Grammar for the type Gaudi::Accumulators::Axis It allows to use that type from p...
Definition __init__.py:1
@ FATAL
Definition IMessageSvc.h:22
@ DEBUG
Definition IMessageSvc.h:22
@ ERROR
Definition IMessageSvc.h:22
@ INFO
Definition IMessageSvc.h:22
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition System.cpp:260
STL namespace.
std::string description
Description string.
Definition RootRefs.h:88
std::string container
Identifier of description.
Definition RootRefs.h:92
Persistent reference object.
Definition extractEvt.C:44
int dbase
Data members to define object location in the persistent world.
Definition RootRefs.h:41
Shadow class to mimik POOL blobs.
Definition PoolClasses.h:56
unsigned char * m_buffer
Buffer with object content.
Definition PoolClasses.h:61
int m_size
Size of buffer.
Definition PoolClasses.h:59