| # Gaudi Framework, version v25r0 |

Home |  | Generated: Mon Feb 17 2014

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

- File List
- File Members

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