The Gaudi Framework  master (e98cfcff)
Loading...
Searching...
No Matches
RootNTupleCnv.cpp
Go to the documentation of this file.
1/***********************************************************************************\
2* (c) Copyright 1998-2026 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
49// Helper to read values from stream - default uses operator>>
50template <class TYP>
51static inline istream& readValue( istream& is, TYP& val ) {
52 return is >> val;
53}
54// For pointer types, just read and discard a long (pointers have meaningless 0 values in the descriptor)
55template <class TYP>
56static inline istream& readValue( istream& is, TYP*& ) {
57 long dummy;
58 return is >> dummy;
59}
60// Specializations for float/double to work around libc++ vs libstdc++ difference.
61//
62// libc++ (macOS/clang) sets failbit when parsing floating point values near the
63// minimum representable value (e.g., FLT_MIN ~1.17549e-38), even though the value
64// is parsed correctly. libstdc++ (Linux/gcc) does not set failbit in this case.
65// This is due to ambiguity in the C++ standard about when failbit should be set
66// for underflow conditions (see LWG Issue 3689).
67//
68// Reproducer:
69// echo '#include <iostream>
70// #include <sstream>
71// int main() {
72// std::istringstream is("1.17549e-38");
73// float f;
74// is >> f;
75// std::cout << "good=" << is.good() << " fail=" << is.fail() << " val=" << f << std::endl;
76// }' | c++ -x c++ - -o /tmp/test && /tmp/test
77//
78// libstdc++ (Linux): good=0 fail=0 val=1.17549e-38
79// libc++ (macOS): good=0 fail=1 val=1.17549e-38
80//
81// The workaround clears failbit if a value was successfully read (i.e., not bad/eof).
82template <>
83inline istream& readValue<float>( istream& is, float& val ) {
84 is >> val;
85 if ( is.fail() && !is.bad() && !is.eof() ) is.clear( is.rdstate() & ~std::ios::failbit );
86 return is;
87}
88template <>
89inline istream& readValue<double>( istream& is, double& val ) {
90 is >> val;
91 if ( is.fail() && !is.bad() && !is.eof() ) is.clear( is.rdstate() & ~std::ios::failbit );
92 return is;
93}
94
95template <class TYP>
96static StatusCode createItem( TTree* tree, INTuple* tuple, istream& is, const string& name, bool add,
97 const TYP& null ) {
98 string idxName;
99 long len, ndim, dim[4], hasIdx, idxLow, idxLen;
100 long dim1 = 1, dim2 = 1;
101 INTupleItem* it = nullptr;
102 char c;
103 is >> len >> c >> ndim >> c >> hasIdx >> c;
104 if ( hasIdx ) { getline( is, idxName, ';' ) >> idxLow >> c >> idxLen >> c; }
105 for ( int i = 0; i < ndim; i++ ) is >> dim[i] >> c;
106
107 TYP low = null, high = null;
108 readValue( is, low ) >> c;
109 readValue( is, high ) >> c;
110 is >> c;
111 switch ( ndim ) {
112 case 0:
113 it = NTuple::_Item<TYP>::create( tuple, name, typeid( TYP ), low, high, null );
114 break;
115 case 1:
116 dim1 = ( hasIdx ) ? idxLen : dim[0];
117 it = NTuple::_Array<TYP>::create( tuple, name, typeid( TYP ), idxName, dim1, low, high, null );
118 break;
119 case 2:
120 dim1 = ( hasIdx ) ? idxLen : dim[0];
121 dim2 = ( hasIdx ) ? dim[0] : dim[1];
122 it = NTuple::_Matrix<TYP>::create( tuple, name, typeid( TYP ), idxName, dim1, dim2, low, high, null );
123 break;
124 default:
125 return S_FAIL;
126 }
127 if ( add ) {
128 TBranch* b = tree->GetBranch( it->name().c_str() );
129 if ( b ) {
130 b->SetAddress( const_cast<void*>( it->buffer() ) );
131 } else {
132 // return StatusCode::SUCCESS;
133 return tuple->add( it );
134 }
135 }
136 return tuple->add( it );
137}
138
139template <class T>
140static inline void putRange( ostream& os, NTuple::_Data<T>* it ) {
141 const NTuple::Range<T>& x = it->range();
142 os << x.lower() << ';' << x.upper() << ';';
143}
144
145static inline string _tr( string s ) {
146 string local = std::move( s );
147 auto p = std::begin( local );
148 if ( local.compare( 0, 7, "<local>" ) == 0 ) p += 7;
149 std::replace_if(
150 p, std::end( local ), []( const char& c ) { return !isalnum( c ); }, '_' );
151 return local;
152}
153
154// Converter overrides: Update the references of an updated transient object.
156 StatusCode status = S_FAIL;
157 RootDataConnection* con = nullptr;
158 IRegistry* pRegistry = pAddr->registry();
159 RootAddress* rpA = dynamic_cast<RootAddress*>( pAddr );
160 string path = fileName( pRegistry );
161 string cntName = containerName( pRegistry );
162 string* par = const_cast<string*>( pAddr->par() );
163 status = m_dbMgr->connectDatabase( path, IDataConnection::READ, &con );
164 if ( status.isSuccess() ) {
165 string par_val, par_guid;
166 TBranch* b = con->getBranch( "##Descriptors", "GaudiStatisticsDescription" );
167 if ( b ) {
169 std::unique_ptr<RootNTupleDescriptor> dsc( ptr = new RootNTupleDescriptor() );
170 b->SetAddress( &ptr );
171 for ( Long64_t i = 0, nent = b->GetEntries(); i < nent; ++i ) {
172 int nb = b->GetEntry( i );
173 if ( nb > 1 ) {
174 if ( ptr->container == cntName ) {
175 par_val = ptr->description;
176 break;
177 }
178 }
179 }
180 }
181 par[2] = _tr( cntName );
182 TTree* tree = con->getSection( par[2] );
183 if ( nullptr == tree ) { return makeError( "Failed to access N-Tuple tree:" + cntName ); }
184 if ( !par_val.empty() ) {
185 auto ntupleSvc = dataProvider().as<INTupleSvc>();
186 if ( ntupleSvc ) {
187 char c;
188 CLID clid;
189 int siz, typ;
190 string title;
191 NTuple::Tuple* nt = nullptr;
192 istringstream is( par_val );
193 getline( is, title, ';' ) >> clid >> c >> siz >> c;
194 status = ntupleSvc->create( clid, title, nt );
195 for ( int j = 0; j < siz && status.isSuccess(); j++ ) {
196 is >> c;
197 getline( is, title, ';' ) >> typ >> c;
198 switch ( typ ) {
200 status = createItem( tree, nt, is, title, true, (unsigned char)0 );
201 break;
203 status = createItem( tree, nt, is, title, true, (unsigned short)0 );
204 break;
206 status = createItem( tree, nt, is, title, true, 0u );
207 break;
209 status = createItem( tree, nt, is, title, true, 0ul );
210 break;
212 status = createItem( tree, nt, is, title, true, char( 0 ) );
213 break;
215 status = createItem( tree, nt, is, title, true, short( 0 ) );
216 break;
218 status = createItem( tree, nt, is, title, true, 0 );
219 break;
221 status = createItem( tree, nt, is, title, true, 0l );
222 break;
224 status = createItem( tree, nt, is, title, true, false );
225 break;
227 status = createItem( tree, nt, is, title, true, 0.f );
228 break;
230 status = createItem( tree, nt, is, title, true, 0. );
231 break;
232 /*
233 case DataTypeInfo::NTCHAR:
234 case DataTypeInfo::LONG_NTCHAR:
235 status =
236 createItem(tree, nt, is, title, true, (char*)0);
237 break;
238 case DataTypeInfo::STRING:
239 case DataTypeInfo::LONG_STRING:
240 status =
241 createItem(tree, nt, is, title, true, string(""));
242 break;
243 */
245 status = createItem( tree, nt, is, title, false, static_cast<IOpaqueAddress*>( nullptr ) );
246 break;
248 status = createItem( tree, nt, is, title, true, static_cast<void*>( nullptr ) );
249 break;
251 default:
252 status = S_FAIL;
253 break;
254 }
255 if ( !status.isSuccess() ) {
256 log() << MSG::FATAL << "Error connecting (Unknown) column:" << j << endmsg << par_val << endmsg;
257 return makeError( "createObj[NTuple]> Cannot determine column!" );
258 }
259 }
260 if ( status.isSuccess() && rpA ) {
261 unsigned long* ipar = const_cast<unsigned long*>( rpA->ipar() );
262 log() << MSG::DEBUG << "Created N-tuple with description:" << par_val << endl;
263 ipar[0] = reinterpret_cast<uintptr_t>( con );
264 ipar[1] = ~0x0UL;
265 rpA->section = tree;
266 refpObject = nt;
267 } else {
268 refpObject = nullptr;
269 if ( nt ) nt->release();
270 }
271 }
272 }
273 }
274 return status;
275}
276
277// Update the transient object: NTuples end here when reading records
279 INTuple* tupl = dynamic_cast<INTuple*>( pObj );
280 RootAddress* rpA = dynamic_cast<RootAddress*>( pAddr );
281 if ( !tupl || !rpA ) return makeError( "updateObj> Invalid Tuple reference." );
282 RootDataConnection* con = reinterpret_cast<RootDataConnection*>( rpA->ipar()[0] );
283 if ( !con ) return makeError( "updateObj> Failed to access data source!" );
284 TTree* tree = rpA->section;
285 if ( !tree ) return makeError( "Failed to access data tree:" + pAddr->par()[1] );
286 con->resetAge();
287 if ( con->tool()->refs() ) return i__updateObjRoot( rpA, tupl, tree, con );
288 return makeError( "Failed to access reference branch for data tree:" + rpA->par()[1] );
289}
290
291// Update the transient object: NTuples end here when reading records
293 typedef INTuple::ItemContainer Cont;
294 const string* par = rpA->par();
295 unsigned long* ipar = const_cast<unsigned long*>( rpA->ipar() );
296 ++ipar[1];
297 if ( Long64_t( ipar[1] ) <= tree->GetEntries() ) {
298 GenericAddress* pA = nullptr;
299 Cont& it = tupl->items();
300 size_t k, n = it.size();
301 vector<RootRef*> paddr( n );
302 vector<RootRef> addr( n );
303 for ( k = 0; k < n; ++k ) {
304 Cont::value_type j = it[k];
305 switch ( j->type() ) {
307 paddr[k] = &addr[k];
308 tree->SetBranchAddress( j->name().c_str(), &paddr[k] );
309 break;
310 default:
311 break;
312 }
313 }
314
315 ULong64_t last = tree->GetEntries();
316 ISelectStatement* sel = tupl->selector();
317 if ( sel ) {
318 string criteria = ( sel && ( sel->type() & ISelectStatement::STRING ) ) ? sel->criteria() : string( "" );
319 if ( !( criteria.length() == 0 || criteria == "*" ) ) {
320 if ( rpA->select == nullptr ) {
321 log() << MSG::DEBUG << "Selection criteria: " << criteria << " " << ipar[1] << endmsg;
322 rpA->select = new TTreeFormula( tree->GetName(), criteria.c_str(), tree );
323 }
324 rpA->select->SetTree( tree );
325 for ( ; ipar[1] < last; ++ipar[1] ) { // loop on all selected entries
326 tree->LoadTree( ipar[1] );
327 rpA->select->GetNdata();
328 if ( fabs( rpA->select->EvalInstance( 0 ) ) > std::numeric_limits<double>::epsilon() ) { break; }
329 log() << MSG::DEBUG << par[0] << "/" << par[1] << " SKIP Entry: " << ipar[1] << endmsg;
330 }
331 }
332 }
333 if ( ipar[1] < last ) {
334 unsigned long entry = ipar[1];
335 if ( tree->GetEntry( entry ) > 1 ) {
336 RootRef* r = nullptr;
337 string* spar = nullptr;
338 for ( k = 0; k < n; ++k ) {
339 Cont::value_type j = it[k];
340 switch ( j->type() ) {
342 r = paddr[k];
343 pA = ( *(GenericAddress**)j->buffer() );
344 if ( pA ) { // Fill only if item is connected!
345 spar = const_cast<string*>( pA->par() );
346 ipar = const_cast<unsigned long*>( pA->ipar() );
347 log() << MSG::DEBUG;
348 pair<const RootRef*, const RootDataConnection::ContainerSection*> ls =
349 con->getMergeSection( tree->GetName(), entry );
350 if ( ls.first ) {
351 if ( ls.first->dbase >= 0 ) {
352 // Now patch the references and links 'en block' to be efficient
353 // First the leafs from the TES
354
355 r->dbase += ls.first->dbase;
356 r->container += ls.first->container;
357 r->link += ls.first->link;
358
359 if ( log().isActive() ) {
360 log() << "Refs: LS [" << entry << "] -> " << ls.first->dbase << "," << ls.first->container << ","
361 << ls.first->link << "," << ls.first->entry << " DB:" << con->getDb( r->dbase ) << endmsg;
362 }
363 }
364 }
365 spar[0] = con->getDb( r->dbase );
366 spar[1] = con->getCont( r->container );
367 spar[2] = con->getLink( r->link );
368 ipar[0] = 0;
369 ipar[1] = r->entry;
370 pA->setClID( r->clid );
371 pA->setSvcType( r->svc );
372 break;
373 }
374 break;
375 default:
376 break;
377 }
378 }
379 return StatusCode::SUCCESS;
380 }
381 log() << MSG::ERROR << "Failed to read data from NTuple tree." << endmsg;
382 return StatusCode::FAILURE;
383 }
384 log() << MSG::INFO << "End of input Ntuple." << endmsg;
385 return StatusCode::FAILURE;
386 }
387 return StatusCode::FAILURE;
388}
389
392 IRegistry* pRegistry = pObj->registry();
393 if ( pRegistry ) {
394 pAddr = pRegistry->address();
395 if ( pAddr ) return S_OK;
396
397 RootDataConnection* con = nullptr;
398 string path = fileName( pRegistry );
399 string cntName = containerName( pRegistry );
400 string secName = cntName;
401 const INTuple* nt = dynamic_cast<const INTuple*>( pObj );
402 StatusCode status = m_dbMgr->connectDatabase( path, IDataConnection::UPDATE, &con );
403 if ( !status.isSuccess() ) { return makeError( "Failed to access Tuple file:" + path ); }
404 TTree* tree = con->getSection( _tr( secName ), true );
405 if ( nullptr != nt ) {
406 const INTuple::ItemContainer& items = nt->items();
407 ostringstream os;
408 size_t item_no;
409 string desc;
410 os << nt->title() << ';' << pObj->clID() << ';' << items.size() << ';';
411 map<string, TBranch*> branches;
412 TBranch* b = nullptr;
413 for ( item_no = 0; item_no < items.size(); ++item_no ) {
414 INTupleItem* it = items[item_no];
415 if ( it->hasIndex() ) {
416 INTupleItem* itm = it->indexItem();
417 const string& n = itm->name();
418 switch ( itm->type() ) {
420 desc = n + "/b";
421 b = tree->Branch( n.c_str(), const_cast<void*>( itm->buffer() ), desc.c_str() );
422 break;
424 desc = n + "/s";
425 b = tree->Branch( n.c_str(), const_cast<void*>( itm->buffer() ), desc.c_str() );
426 break;
428 desc = n + "/i";
429 b = tree->Branch( n.c_str(), const_cast<void*>( itm->buffer() ), desc.c_str() );
430 break;
432 desc = n + "/l";
433 b = tree->Branch( n.c_str(), const_cast<void*>( itm->buffer() ), desc.c_str() );
434 break;
436 desc = n + "/B";
437 b = tree->Branch( n.c_str(), const_cast<void*>( itm->buffer() ), desc.c_str() );
438 break;
440 desc = n + "/S";
441 b = tree->Branch( n.c_str(), const_cast<void*>( itm->buffer() ), desc.c_str() );
442 break;
444 desc = n + "/I";
445 b = tree->Branch( n.c_str(), const_cast<void*>( itm->buffer() ), desc.c_str() );
446 break;
448 desc = n + "/L";
449 b = tree->Branch( n.c_str(), const_cast<void*>( itm->buffer() ), desc.c_str() );
450 break;
451 default:
452 return makeError( "Column " + it->index() + " is not a valid index column!" );
453 }
454 branches[n] = b;
455 }
456 }
457 for ( item_no = 0; item_no < items.size(); ++item_no ) {
458 INTupleItem* it = items[item_no];
459 const string& n = it->name();
460 os << '{' << n << ';' << it->type() << ';' << it->length() << ';' << it->ndim() << ';' << it->hasIndex() << ';';
461 if ( it->hasIndex() ) {
462 os << it->index() << ';';
463 INTupleItem* itm = it->indexItem();
464 switch ( itm->type() ) {
466 putRange( os, dynamic_cast<NTuple::_Data<unsigned char>*>( itm ) );
467 break;
469 putRange( os, dynamic_cast<NTuple::_Data<unsigned short>*>( itm ) );
470 break;
472 putRange( os, dynamic_cast<NTuple::_Data<unsigned int>*>( itm ) );
473 break;
475 putRange( os, dynamic_cast<NTuple::_Data<unsigned long>*>( itm ) );
476 break;
478 putRange( os, dynamic_cast<NTuple::_Data<char>*>( itm ) );
479 break;
481 putRange( os, dynamic_cast<NTuple::_Data<short>*>( itm ) );
482 break;
484 putRange( os, dynamic_cast<NTuple::_Data<int>*>( itm ) );
485 break;
487 putRange( os, dynamic_cast<NTuple::_Data<long>*>( itm ) );
488 break;
489 default:
490 return makeError( "NTuple:" + pRegistry->name() + " Column " + it->index() +
491 " is not a valid index column!" );
492 }
493 }
494 for ( long k = 0; k < it->ndim(); k++ ) { os << it->dim( k ) << ';'; }
495 desc = n;
496 TClass* cl = nullptr;
497 switch ( it->type() ) {
499 desc = "/C";
500 os << 0 << ';' << 0 << ';';
501 break;
503 desc = "/C";
504 os << 0 << ';' << 0 << ';';
505 break;
507 if ( it->length() == 1 ) {
508 desc = System::typeinfoName( typeid( RootRef ) );
509 os << 0 << ';' << 0 << ';';
510 cl = TClass::GetClass( desc.c_str(), kTRUE );
511 }
512 break;
514 if ( it->length() == 1 ) {
515 os << 0 << ';' << 0 << ';';
516 cl = TClass::GetClass( it->typeID(), kTRUE );
517 }
518 break;
520 desc = "/b";
521 putRange( os, dynamic_cast<NTuple::_Data<unsigned char>*>( it ) );
522 break;
524 desc = "/s";
525 putRange( os, dynamic_cast<NTuple::_Data<unsigned short>*>( it ) );
526 break;
528 desc = "/i";
529 putRange( os, dynamic_cast<NTuple::_Data<unsigned int>*>( it ) );
530 break;
532 desc = "/l";
533 putRange( os, dynamic_cast<NTuple::_Data<unsigned long>*>( it ) );
534 break;
536 desc = "/B";
537 putRange( os, dynamic_cast<NTuple::_Data<char>*>( it ) );
538 break;
540 desc = "/S";
541 putRange( os, dynamic_cast<NTuple::_Data<short>*>( it ) );
542 break;
544 desc = "/I";
545 putRange( os, dynamic_cast<NTuple::_Data<int>*>( it ) );
546 break;
548 desc = "/L";
549 putRange( os, dynamic_cast<NTuple::_Data<long>*>( it ) );
550 break;
552 desc = "/b";
553 putRange( os, dynamic_cast<NTuple::_Data<bool>*>( it ) );
554 break;
556 desc = "/F";
557 putRange( os, dynamic_cast<NTuple::_Data<float>*>( it ) );
558 break;
560 desc = "/D";
561 putRange( os, dynamic_cast<NTuple::_Data<double>*>( it ) );
562 break;
564 default:
565 return makeError( "Create item[FAIL]: " + it->name() );
566 }
567 os << '}';
568 if ( branches.find( n ) == branches.end() ) {
569 string tmp;
570 char text[32];
571 switch ( it->ndim() ) {
572 case 0:
573 desc = n + desc;
574 break;
575 case 2:
576 snprintf( text, sizeof( text ), "[%ld]", it->dim( 0 ) );
577 tmp = text;
578 [[fallthrough]];
579 case 1:
580 if ( it->hasIndex() ) {
581 INTupleItem* itm = it->indexItem();
582 desc = n + tmp + "[" + itm->name() + "]" + desc;
583 } else {
584 snprintf( text, sizeof( text ), "[%ld]", it->dim( 0 ) );
585 desc = n + tmp + text + desc;
586 }
587 }
588 log() << MSG::DEBUG << "Create branch:" << n << " Desc:" << desc << " of type:" << it->type() << endmsg;
589 switch ( it->type() ) {
591 branches[n] = tree->Branch( n.c_str(), cl->GetName(), const_cast<void*>( it->buffer() ) );
592 break;
594 branches[n] = tree->Branch( n.c_str(), cl->GetName(), const_cast<void*>( it->buffer() ) );
595 break;
596 default:
597 branches[n] = tree->Branch( n.c_str(), const_cast<void*>( it->buffer() ), desc.c_str() );
598 break;
599 }
600 }
601 }
602
603 log() << MSG::DEBUG << "Save description:" << path << " -> " << cntName << endmsg << os.str() << endmsg;
604 status = saveDescription( path, cntName, os.str(), "", pObj->clID() );
605 if ( status.isSuccess() ) {
606 status = m_dbMgr->commitOutput( path, true );
607 if ( status.isSuccess() ) {
608 string spar[] = { path, cntName };
609 unsigned long ipar[] = { (unsigned long)con, ~0x0u };
610 status = m_dbMgr->createAddress( repSvcType(), pObj->clID(), spar, ipar, pAddr );
611 if ( status.isSuccess() ) {
612 RootAddress* rpA = dynamic_cast<RootAddress*>( pAddr );
613 if ( rpA ) {
614 ( (unsigned long*)rpA->ipar() )[0] = (unsigned long)con;
615 rpA->section = tree;
616 } else {
617 log() << MSG::ERROR << "cannot dynamic cast to RootAddress" << endmsg;
618 }
619
620 } else {
621 pAddr->release();
622 pAddr = nullptr;
623 }
624 }
625 }
626 return status;
627 }
628 }
629 return S_FAIL;
630}
631
632// Resolve the references of the converted object.
634 typedef INTuple::ItemContainer Cont;
635 INTuple* tupl = dynamic_cast<INTuple*>( pObj );
636 IRegistry* pReg = pObj->registry();
637 RootAddress* rpA = dynamic_cast<RootAddress*>( pAddr );
638 if ( tupl && pReg && rpA ) {
639 string cntName = containerName( pReg );
640 unsigned long* ipar = const_cast<unsigned long*>( pAddr->ipar() );
641 RootDataConnection* con = reinterpret_cast<RootDataConnection*>( rpA->ipar()[0] );
642 if ( con ) {
643 TTree* tree = rpA->section;
644 if ( tree ) {
645 Cont& it = tupl->items();
646 size_t k, n = it.size();
647 vector<RootRef*> paddr( n );
648 vector<RootRef> addr( n );
649 for ( k = 0; k < n; ++k ) {
650 IOpaqueAddress* pA = nullptr;
651 Cont::value_type j = it[k];
652 switch ( j->type() ) {
654 pA = ( *(IOpaqueAddress**)j->buffer() );
655 paddr[k] = &addr[k];
656 addr[k].reset();
657 if ( pA ) {
658 con->makeRef( *pA->registry(), addr[k] );
659 addr[k].entry = pA->ipar()[1];
660 }
661 tree->SetBranchAddress( j->name().c_str(), &paddr[k] );
662 break;
663 default:
664 break;
665 }
666 }
667 int nb = tree->Fill();
668 if ( nb > 1 ) ++ipar[1];
669 for ( k = 0; k < n; ++k ) it[k]->reset();
671 }
672 return makeError( "fillRepRefs> Failed to access data tree:" + cntName );
673 }
674 return makeError( "fillRepRefs> Failed to access data source!" );
675 }
676 return makeError( "fillRepRefs> Invalid Tuple reference." );
677}
unsigned int CLID
Class ID definition.
Definition ClassID.h:16
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition MsgStream.h:198
#define S_OK
#define S_FAIL
istream & readValue< double >(istream &is, double &val)
istream & readValue< float >(istream &is, float &val)
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:42
TTreeFormula * select
Pointer to ROOT select statement (filled for N-tuples only)
Definition RootAddress.h:45
TTree * section
Pointer to ROOT TTree (filled for N-tuples only)
Definition RootAddress.h:47
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.
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
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
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