00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #define ALLOW_ALL_TYPES
00011
00012 #include "RootCnv/RootRefs.h"
00013 #include "RootCnv/RootAddress.h"
00014 #include "RootCnv/RootNTupleCnv.h"
00015 #include "RootCnv/RootDataConnection.h"
00016
00017 #include "GaudiKernel/NTuple.h"
00018 #include "GaudiKernel/SmartIF.h"
00019 #include "GaudiKernel/SmartRef.h"
00020 #include "GaudiKernel/INTupleSvc.h"
00021 #include "GaudiKernel/IRegistry.h"
00022 #include "GaudiKernel/ISelectStatement.h"
00023 #include "GaudiKernel/ContainedObject.h"
00024 #include "GaudiKernel/StreamBuffer.h"
00025
00026
00027 #include "TROOT.h"
00028 #include "TTree.h"
00029 #include "TBranch.h"
00030 #include "Reflex/Reflex.h"
00031
00032 #include <limits>
00033 #include <memory>
00034
00035 #define S_OK StatusCode::SUCCESS
00036 #define S_FAIL StatusCode::FAILURE
00037
00038 using namespace Gaudi;
00039 using namespace std;
00040
00041 static inline istream& loadLong(istream& is) {
00042 long i;
00043 is >> i;
00044 return is;
00045 }
00046 static inline istream& operator>>(istream& is, IOpaqueAddress*& )
00047 { return loadLong(is); }
00048
00049 #if 0
00050 static inline istream& operator>>(istream& is, SmartRef<DataObject>& )
00051 { return loadLong(is); }
00052 static inline istream& operator>>(istream& is, SmartRef<ContainedObject>& )
00053 { return loadLong(is); }
00054 static inline istream& operator>>(istream& is, string& )
00055 { return loadLong(is); }
00056 #endif
00057
00058 template<class TYP> static
00059 StatusCode createItem ( TTree* tree, INTuple* tuple, istream& is,const string& name,bool add,const TYP& null) {
00060 string idxName;
00061 long len, ndim, dim[4], hasIdx, idxLow, idxLen;
00062 long dim1 = 1, dim2 = 1;
00063 INTupleItem* it = 0;
00064 char c;
00065 is >> len >> c
00066 >> ndim >> c
00067 >> hasIdx >> c;
00068 if ( hasIdx ) {
00069 getline(is, idxName, ';') >> idxLow >> c >> idxLen >> c;
00070 }
00071 for ( int i = 0; i < ndim; i++ )
00072 is >> dim[i] >> c;
00073
00074 TYP low = null, high = null;
00075 is >> low >> c >> high >> c;
00076 is >> c;
00077 switch( ndim )
00078 {
00079 case 0:
00080 it = NTuple::_Item<TYP>::create (tuple, name, typeid(TYP), low, high, null);
00081 break;
00082 case 1:
00083 dim1 = (hasIdx) ? idxLen : dim[0];
00084 it = NTuple::_Array<TYP>::create (tuple,
00085 name,
00086 typeid(TYP),
00087 idxName,
00088 dim1,
00089 low,
00090 high,
00091 null);
00092 break;
00093 case 2:
00094 dim1 = (hasIdx) ? idxLen : dim[0];
00095 dim2 = (hasIdx) ? dim[0] : dim[1];
00096 it = NTuple::_Matrix<TYP>::create ( tuple,
00097 name,
00098 typeid(TYP),
00099 idxName,
00100 dim1,
00101 dim2,
00102 low,
00103 high,
00104 null);
00105 break;
00106 default:
00107 return S_FAIL;
00108 }
00109 if ( add ) {
00110 TBranch* b = tree->GetBranch(it->name().c_str());
00111 if ( b ) {
00112 b->SetAddress((void*)it->buffer());
00113 }
00114 else {
00115
00116 return tuple->add(it);
00117 }
00118 }
00119 return tuple->add(it);
00120 }
00121
00122 template <class T> static inline void putRange(ostream& os, NTuple::_Data<T>* it) {
00123 const NTuple::Range<T>& x = it->range();
00124 os << x.lower() << ';' << x.upper() << ';';
00125 }
00126
00127 static inline string _tr(const string& s) {
00128 string local = s;
00129 char* p = (char*)local.c_str();
00130 if ( strncmp(p,"<local>",7)==0 ) p += 7;
00131 for(;*p;++p)
00132 if ( !isalnum(*p) ) *p = '_';
00133 return local;
00134 }
00135
00136
00137 StatusCode
00138 RootNTupleCnv::createObj(IOpaqueAddress* pAddr, DataObject*& refpObject) {
00139 StatusCode status = S_FAIL;
00140 RootDataConnection* con = 0;
00141 IRegistry* pRegistry = pAddr->registry();
00142 RootAddress* rpA = dynamic_cast<RootAddress*>(pAddr);
00143 string path = fileName(pRegistry);
00144 string cntName = containerName(pRegistry);
00145 string* par = const_cast<string*>(pAddr->par());
00146 status = m_dbMgr->connectDatabase(path,IDataConnection::READ,&con);
00147 if ( status.isSuccess() ) {
00148 string par_val, par_guid;
00149 TBranch* b = con->getBranch("##Descriptors","GaudiStatisticsDescription");
00150 if ( b ) {
00151 RootNTupleDescriptor* ptr;
00152 auto_ptr<RootNTupleDescriptor> dsc(ptr=new RootNTupleDescriptor());
00153 b->SetAddress(&ptr);
00154 for(Long64_t i=0, nent = b->GetEntries(); i<nent; ++i) {
00155 int nb = b->GetEntry(i);
00156 if ( nb > 1 ) {
00157 if ( ptr->container == cntName ) {
00158 par_val = ptr->description;
00159 break;
00160 }
00161 }
00162 }
00163 }
00164 par[2] = _tr(cntName);
00165 TTree* tree = con->getSection(par[2]);
00166 if ( 0 == tree ) {
00167 return makeError("Failed to access N-Tuple tree:"+cntName);
00168 }
00169 if ( !par_val.empty() ) {
00170 SmartIF<INTupleSvc> ntupleSvc(dataProvider());
00171 if ( ntupleSvc.isValid() ) {
00172 char c;
00173 CLID clid;
00174 int siz, typ;
00175 string title;
00176 NTuple::Tuple* nt = 0;
00177 istringstream is(par_val);
00178 getline(is, title, ';') >> clid >> c >> siz >> c;
00179 status = ntupleSvc->create(clid, title, nt);
00180 for ( int j = 0; j < siz && status.isSuccess(); j++ ) {
00181 is >> c;
00182 getline(is, title, ';') >> typ >> c;
00183 switch ( typ )
00184 {
00185 case DataTypeInfo::UCHAR:
00186 status = createItem(tree, nt, is, title, true, (unsigned char)0);
00187 break;
00188 case DataTypeInfo::USHORT:
00189 status = createItem(tree, nt, is, title, true, (unsigned short)0);
00190 break;
00191 case DataTypeInfo::UINT:
00192 status = createItem(tree, nt, is, title, true, (unsigned int)0);
00193 break;
00194 case DataTypeInfo::ULONG:
00195 status = createItem(tree, nt, is, title, true, (unsigned long)0);
00196 break;
00197 case DataTypeInfo::CHAR:
00198 status = createItem(tree, nt, is, title, true, char(0));
00199 break;
00200 case DataTypeInfo::SHORT:
00201 status = createItem(tree, nt, is, title, true, short(0));
00202 break;
00203 case DataTypeInfo::INT:
00204 status = createItem(tree, nt, is, title, true, int(0));
00205 break;
00206 case DataTypeInfo::LONG:
00207 status = createItem(tree, nt, is, title, true, long(0));
00208 break;
00209 case DataTypeInfo::BOOL:
00210 status = createItem(tree, nt, is, title, true, false);
00211 break;
00212 case DataTypeInfo::FLOAT:
00213 status = createItem(tree, nt, is, title, true, float(0.0));
00214 break;
00215 case DataTypeInfo::DOUBLE:
00216 status = createItem(tree, nt, is, title, true, double(0.0));
00217 break;
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 case DataTypeInfo::OBJECT_ADDR:
00231 status = createItem(tree, nt, is, title, false, (IOpaqueAddress*)0);
00232 break;
00233 case DataTypeInfo::POINTER:
00234 status = createItem(tree, nt, is, title, true, (void*)0);
00235 break;
00236 case DataTypeInfo::UNKNOWN:
00237 default:
00238 status = S_FAIL;
00239 break;
00240 }
00241 if ( !status.isSuccess() ) {
00242 log() << MSG::FATAL
00243 << "Error connecting (Unknown) column:" << j << endmsg
00244 << par_val << endmsg;
00245 return makeError("createObj[NTuple]> Cannot determine column!");
00246 }
00247 }
00248 if ( status.isSuccess() ) {
00249 unsigned long* ipar = const_cast<unsigned long*>(rpA->ipar());
00250 log() << MSG::DEBUG << "Created N-tuple with description:"
00251 << par_val << endl;
00252 ipar[0] = (unsigned long)con;
00253 ipar[1] = ~0x0UL;
00254 rpA->section = tree;
00255 refpObject = nt;
00256 }
00257 else {
00258 refpObject = 0;
00259 if ( nt ) nt->release();
00260 }
00261 }
00262 }
00263 }
00264 return status;
00265 }
00266
00267
00268 StatusCode RootNTupleCnv::updateObj(IOpaqueAddress* pAddr, DataObject* pObj) {
00269 INTuple* tupl = dynamic_cast<INTuple*>(pObj);
00270 RootAddress* rpA = dynamic_cast<RootAddress*>(pAddr);
00271 if ( 0 != tupl && 0 != rpA ) {
00272 RootDataConnection* con = (RootDataConnection*)rpA->ipar()[0];
00273 if ( con ) {
00274 TTree* tree = rpA->section;
00275 if ( tree ) {
00276 con->resetAge();
00277 if ( con->tool()->refs() )
00278 return i__updateObjRoot(rpA,tupl,tree,con);
00279 #ifdef __POOL_COMPATIBILITY
00280
00281 return i__updateObjPool(rpA,tupl,tree,con);
00282 #else
00283 return makeError("Failed to access reference branch for data tree:"+rpA->par()[1]);
00284 #endif
00285 }
00286 return makeError("Failed to access data tree:"+pAddr->par()[1]);
00287 }
00288 return makeError("updateObj> Failed to access data source!");
00289 }
00290 return makeError("updateObj> Invalid Tuple reference.");
00291 }
00292
00293
00294 StatusCode RootNTupleCnv::i__updateObjRoot(RootAddress* rpA, INTuple* tupl, TTree* tree, RootDataConnection* con) {
00295 typedef INTuple::ItemContainer Cont;
00296 const string* par = rpA->par();
00297 unsigned long* ipar = const_cast<unsigned long*>(rpA->ipar());
00298 ++ipar[1];
00299 if ( Long64_t(ipar[1]) <= tree->GetEntries() ) {
00300 GenericAddress* pA = 0;
00301 Cont& it = tupl->items();
00302 size_t k, n = it.size();
00303 vector<RootRef*> paddr(n);
00304 vector<RootRef> addr(n);
00305 for(k = 0; k < n; ++k) {
00306 Cont::value_type j = it[k];
00307 switch( j->type() )
00308 {
00309 case DataTypeInfo::OBJECT_ADDR:
00310 paddr[k] = &addr[k];
00311 tree->SetBranchAddress(j->name().c_str(),&paddr[k]);
00312 break;
00313 default:
00314 break;
00315 }
00316 }
00317
00318 ULong64_t last = (ULong64_t)tree->GetEntries();
00319 ISelectStatement* sel = tupl->selector();
00320 if ( sel ) {
00321 string criteria = (sel && (sel->type() & ISelectStatement::STRING))
00322 ? sel->criteria() : string("");
00323 if ( !(criteria.length() == 0 || criteria == "*") ) {
00324 if ( rpA->select == 0 ) {
00325 log() << MSG::DEBUG << "Selection criteria: " << criteria << " " << ipar[1] << endmsg;
00326 rpA->select = new TTreeFormula(tree->GetName(),criteria.c_str(), tree);
00327 }
00328 rpA->select->SetTree(tree);
00329 for( ; ipar[1] < last; ++ipar[1]) {
00330 tree->LoadTree(ipar[1]);
00331 rpA->select->GetNdata();
00332 if ( fabs(rpA->select->EvalInstance(0)) > std::numeric_limits<float>::epsilon() ) {
00333 break;
00334 }
00335 log() << MSG::DEBUG << par[0] << "/" << par[1] << " SKIP Entry: " << ipar[1] << endmsg;
00336 }
00337 }
00338 }
00339 if ( ipar[1] < last ) {
00340 unsigned long entry = ipar[1];
00341 if ( tree->GetEntry(entry) > 1 ) {
00342 RootRef *r = 0;
00343 string *spar = 0;
00344 for(k = 0; k < n; ++k) {
00345 Cont::value_type j = it[k];
00346 switch( j->type() )
00347 {
00348 case DataTypeInfo::OBJECT_ADDR:
00349 r = paddr[k];
00350 pA = (*(GenericAddress**)j->buffer());
00351 if ( pA ) {
00352 spar = (string*)pA->par();
00353 ipar = (unsigned long*)pA->ipar();
00354 log() << MSG::DEBUG;
00355 pair<const RootRef*,const RootDataConnection::ContainerSection*> ls = con->getMergeSection(tree->GetName(),entry);
00356 if ( ls.first ) {
00357 if ( ls.first->dbase >= 0 ) {
00358
00359
00360
00361 r->dbase += ls.first->dbase;
00362 r->container += ls.first->container;
00363 r->link += ls.first->link;
00364
00365 if ( log().isActive() ) {
00366 log() << "Refs: LS [" << entry << "] -> "
00367 << ls.first->dbase << "," << ls.first->container
00368 << "," << ls.first->link
00369 << "," << ls.first->entry
00370 << " DB:" << con->getDb(r->dbase)
00371 << endmsg;
00372 }
00373 }
00374 }
00375 spar[0] = con->getDb(r->dbase);
00376 spar[1] = con->getCont(r->container);
00377 spar[2] = con->getLink(r->link);
00378 ipar[0] = 0;
00379 ipar[1] = r->entry;
00380 pA->setClID(r->clid);
00381 pA->setSvcType(r->svc);
00382 break;
00383 }
00384 break;
00385 default:
00386 break;
00387 }
00388 }
00389 return StatusCode::SUCCESS;
00390 }
00391 log() << MSG::ERROR << "Failed to read data from NTuple tree." << endmsg;
00392 return StatusCode::FAILURE;
00393 }
00394 log() << MSG::INFO << "End of input Ntuple." << endmsg;
00395 return StatusCode::FAILURE;
00396 }
00397 return StatusCode::FAILURE;
00398 }
00399
00401 StatusCode RootNTupleCnv::createRep(DataObject* pObj, IOpaqueAddress*& pAddr) {
00402 IRegistry* pRegistry = pObj->registry();
00403 if ( 0 != pRegistry ) {
00404 pAddr = pRegistry->address();
00405 if ( 0 != pAddr ) {
00406 return S_OK;
00407 }
00408
00409 RootDataConnection* con = 0;
00410 string path = fileName(pRegistry);
00411 string cntName = containerName(pRegistry);
00412 string secName = cntName.c_str();
00413 const INTuple* nt = dynamic_cast<const INTuple*>(pObj);
00414 StatusCode status = m_dbMgr->connectDatabase(path, IDataConnection::UPDATE, &con);
00415 if ( !status.isSuccess() ) {
00416 return makeError("Failed to access Tuple file:"+path);
00417 }
00418 TTree* tree = con->getSection(_tr(secName),true);
00419 if ( 0 != nt ) {
00420 const INTuple::ItemContainer& items = nt->items();
00421 ostringstream os;
00422 size_t item_no;
00423 string desc;
00424 os << nt->title()<<';'<<pObj->clID()<<';'<<items.size()<< ';';
00425 map<string,TBranch*> branches;
00426 TBranch* b = 0;
00427 for(item_no = 0; item_no < items.size(); ++item_no ) {
00428 INTupleItem* it = items[item_no];
00429 if ( it->hasIndex() ) {
00430 INTupleItem* itm = it->indexItem();
00431 const string& n = itm->name();
00432 switch( itm->type() )
00433 {
00434 case DataTypeInfo::UCHAR:
00435 desc = n+"/b";
00436 b = tree->Branch(n.c_str(),(void*)itm->buffer(),desc.c_str());
00437 break;
00438 case DataTypeInfo::USHORT:
00439 desc = n+"/s";
00440 b = tree->Branch(n.c_str(),(void*)itm->buffer(),desc.c_str());
00441 break;
00442 case DataTypeInfo::UINT:
00443 desc = n+"/i";
00444 b = tree->Branch(n.c_str(),(void*)itm->buffer(),desc.c_str());
00445 break;
00446 case DataTypeInfo::ULONG:
00447 desc = n+"/l";
00448 b = tree->Branch(n.c_str(),(void*)itm->buffer(),desc.c_str());
00449 break;
00450 case DataTypeInfo::CHAR:
00451 desc = n+"/B";
00452 b = tree->Branch(n.c_str(),(void*)itm->buffer(),desc.c_str());
00453 break;
00454 case DataTypeInfo::SHORT:
00455 desc = n+"/S";
00456 b = tree->Branch(n.c_str(),(void*)itm->buffer(),desc.c_str());
00457 break;
00458 case DataTypeInfo::INT:
00459 desc = n+"/I";
00460 b = tree->Branch(n.c_str(),(void*)itm->buffer(),desc.c_str());
00461 break;
00462 case DataTypeInfo::LONG:
00463 desc = n+"/L";
00464 b = tree->Branch(n.c_str(),(void*)itm->buffer(),desc.c_str());
00465 break;
00466 default:
00467 return makeError("Column "+it->index()+" is not a valid index column!");
00468 }
00469 branches[n] = b;
00470 }
00471 }
00472 for(item_no = 0; item_no < items.size(); ++item_no ) {
00473 INTupleItem* it = items[item_no];
00474 const string& n = it->name();
00475 os << '{'
00476 << n << ';'
00477 << it->type() << ';'
00478 << it->length() << ';'
00479 << it->ndim() << ';'
00480 << it->hasIndex() << ';';
00481 if ( it->hasIndex() ) {
00482 os << it->index() << ';';
00483 INTupleItem* itm = it->indexItem();
00484 switch( itm->type() )
00485 {
00486 case DataTypeInfo::UCHAR:
00487 putRange(os, dynamic_cast<NTuple::_Data<unsigned char>*>(itm));
00488 break;
00489 case DataTypeInfo::USHORT:
00490 putRange(os, dynamic_cast<NTuple::_Data<unsigned short>*>(itm));
00491 break;
00492 case DataTypeInfo::UINT:
00493 putRange(os, dynamic_cast<NTuple::_Data<unsigned int>*>(itm));
00494 break;
00495 case DataTypeInfo::ULONG:
00496 putRange(os, dynamic_cast<NTuple::_Data<unsigned long>*>(itm));
00497 break;
00498 case DataTypeInfo::CHAR:
00499 putRange(os, dynamic_cast<NTuple::_Data<char>*>(itm));
00500 break;
00501 case DataTypeInfo::SHORT:
00502 putRange(os, dynamic_cast<NTuple::_Data<short>*>(itm));
00503 break;
00504 case DataTypeInfo::INT:
00505 putRange(os, dynamic_cast<NTuple::_Data<int>*>(itm));
00506 break;
00507 case DataTypeInfo::LONG:
00508 putRange(os, dynamic_cast<NTuple::_Data<long>*>(itm));
00509 break;
00510 default:
00511 return makeError("NTuple:"+pRegistry->name()+" Column "+it->index()+
00512 " is not a valid index column!");
00513 }
00514 }
00515 for ( long k = 0; k < it->ndim(); k++ ) {
00516 os << it->dim(k) << ';';
00517 }
00518 desc = n;
00519 TClass* cl = 0;
00520 switch(it->type())
00521 {
00522 case DataTypeInfo::STRING:
00523 desc = "/C";
00524 os << 0 << ';' << 0 << ';';
00525 break;
00526 case DataTypeInfo::NTCHAR:
00527 desc = "/C";
00528 os << 0 << ';' << 0 << ';';
00529 break;
00530 case DataTypeInfo::OBJECT_ADDR:
00531 if ( it->length() == 1 ) {
00532 desc = System::typeinfoName(typeid(RootRef));
00533 os << 0 << ';' << 0 << ';';
00534 cl = gROOT->GetClass(desc.c_str(),kTRUE);
00535 }
00536 break;
00537 case DataTypeInfo::POINTER:
00538 if ( it->length() == 1 ) {
00539 ROOT::Reflex::Type typ = ROOT::Reflex::Type::ByName(it->typeName());
00540 desc = typ.Name(ROOT::Reflex::SCOPED);
00541 os << 0 << ';' << 0 << ';';
00542 cl = gROOT->GetClass(desc.c_str(),kTRUE);
00543 }
00544 break;
00545 case DataTypeInfo::UCHAR:
00546 desc = "/b";
00547 putRange(os, dynamic_cast<NTuple::_Data<unsigned char>*>(it));
00548 break;
00549 case DataTypeInfo::USHORT:
00550 desc = "/s";
00551 putRange(os, dynamic_cast<NTuple::_Data<unsigned short>*>(it));
00552 break;
00553 case DataTypeInfo::UINT:
00554 desc = "/i";
00555 putRange(os, dynamic_cast<NTuple::_Data<unsigned int>*>(it));
00556 break;
00557 case DataTypeInfo::ULONG:
00558 desc = "/l";
00559 putRange(os, dynamic_cast<NTuple::_Data<unsigned long>*>(it));
00560 break;
00561 case DataTypeInfo::CHAR:
00562 desc = "/B";
00563 putRange(os, dynamic_cast<NTuple::_Data<char>*>(it));
00564 break;
00565 case DataTypeInfo::SHORT:
00566 desc = "/S";
00567 putRange(os, dynamic_cast<NTuple::_Data<short>*>(it));
00568 break;
00569 case DataTypeInfo::INT:
00570 desc = "/I";
00571 putRange(os, dynamic_cast<NTuple::_Data<int>*>(it));
00572 break;
00573 case DataTypeInfo::LONG:
00574 desc = "/L";
00575 putRange(os, dynamic_cast<NTuple::_Data<long>*>(it));
00576 break;
00577 case DataTypeInfo::BOOL:
00578 desc = "/b";
00579 putRange(os, dynamic_cast<NTuple::_Data<bool>*>(it));
00580 break;
00581 case DataTypeInfo::FLOAT:
00582 desc = "/F";
00583 putRange(os, dynamic_cast<NTuple::_Data<float>*>(it));
00584 break;
00585 case DataTypeInfo::DOUBLE:
00586 desc = "/D";
00587 putRange(os, dynamic_cast<NTuple::_Data<double>*>(it));
00588 break;
00589 case DataTypeInfo::UNKNOWN:
00590 default:
00591 return makeError("Create item[FAIL]: "+it->name());
00592 }
00593 os << '}';
00594 if ( branches.find(n) == branches.end() ) {
00595 string tmp;
00596 char text[32];
00597 switch(it->ndim())
00598 {
00599 case 0:
00600 desc = n+desc;
00601 break;
00602 case 2:
00603 sprintf(text,"[%ld]",it->dim(0));
00604 tmp = text;
00605 case 1:
00606 if ( it->hasIndex() ) {
00607 INTupleItem* itm = it->indexItem();
00608 desc = n + tmp + "[" + itm->name() + "]" + desc;
00609 }
00610 else {
00611 sprintf(text,"[%ld]",it->dim(0));
00612 desc = n + tmp + text + desc;
00613 }
00614 }
00615 log() << MSG::DEBUG << "Create branch:" << n << " Desc:" << desc
00616 << " of type:" << it->type() << endmsg;
00617 switch(it->type())
00618 {
00619 case DataTypeInfo::OBJECT_ADDR:
00620 branches[n] = tree->Branch(n.c_str(),cl->GetName(),(void*)it->buffer());
00621 break;
00622 case DataTypeInfo::POINTER:
00623 branches[n] = tree->Branch(n.c_str(),cl->GetName(),(void*)it->buffer());
00624 break;
00625 default:
00626 branches[n] = tree->Branch(n.c_str(),(void*)it->buffer(),desc.c_str());
00627 break;
00628 }
00629 }
00630 }
00631
00632 log() << MSG::DEBUG << "Save description:" << path << " -> " << cntName << endmsg
00633 << os.str() << endmsg;
00634 status = saveDescription(path,cntName,os.str(),"",pObj->clID());
00635 if ( status.isSuccess() ) {
00636 status = m_dbMgr->commitOutput(path, true);
00637 if ( status.isSuccess() ) {
00638 string spar[] = { path, cntName};
00639 unsigned long ipar[] = { (unsigned long)con, ~0x0 };
00640 status = m_dbMgr->createAddress(repSvcType(),pObj->clID(),spar,ipar,pAddr);
00641 if ( status.isSuccess() ) {
00642 RootAddress* rpA = dynamic_cast<RootAddress*>(pAddr);
00643 ((unsigned long*)rpA->ipar())[0] = (unsigned long)con;
00644 rpA->section = tree;
00645 }
00646 else {
00647 pAddr->release();
00648 pAddr = 0;
00649 }
00650 }
00651 }
00652 return status;
00653 }
00654 }
00655 return S_FAIL;
00656 }
00657
00658
00659 StatusCode RootNTupleCnv::fillRepRefs(IOpaqueAddress* pAddr, DataObject* pObj) {
00660 typedef INTuple::ItemContainer Cont;
00661 INTuple* tupl = dynamic_cast<INTuple*>(pObj);
00662 IRegistry* pReg = pObj->registry();
00663 RootAddress* rpA = dynamic_cast<RootAddress*>(pAddr);
00664 if ( tupl && pReg && rpA ) {
00665 string cntName = containerName(pReg);
00666 unsigned long* ipar = const_cast<unsigned long*>(pAddr->ipar());
00667 RootDataConnection* con = (RootDataConnection*)rpA->ipar()[0];
00668 if ( con ) {
00669 TTree* tree = rpA->section;
00670 if ( tree ) {
00671 Cont& it = tupl->items();
00672 size_t k, n = it.size();
00673 vector<RootRef*> paddr(n);
00674 vector<RootRef> addr(n);
00675 for(k = 0; k < n; ++k) {
00676 IOpaqueAddress* pA = 0;
00677 Cont::value_type j = it[k];
00678 switch( j->type() )
00679 {
00680 case DataTypeInfo::OBJECT_ADDR:
00681 pA = (*(IOpaqueAddress**)j->buffer());
00682 paddr[k] = &addr[k];
00683 addr[k].reset();
00684 if ( pA ) {
00685 con->makeRef(pA->registry(),addr[k]);
00686 addr[k].entry = pA->ipar()[1];
00687 }
00688 tree->SetBranchAddress(j->name().c_str(),&paddr[k]);
00689 break;
00690 default:
00691 break;
00692 }
00693 }
00694 int nb = tree->Fill();
00695 if ( nb>1 ) ++ipar[1];
00696 for(k = 0; k < n; ++k) it[k]->reset();
00697 return nb>1 ? StatusCode::SUCCESS : StatusCode::FAILURE;
00698 }
00699 return makeError("fillRepRefs> Failed to access data tree:"+cntName);
00700 }
00701 return makeError("fillRepRefs> Failed to access data source!");
00702 }
00703 return makeError("fillRepRefs> Invalid Tuple reference.");
00704 }
00705
00706 #ifdef __POOL_COMPATIBILITY
00707 #include "PoolClasses.h"
00708
00709
00710
00711 namespace {
00712
00713 class IOBuffer : public StreamBuffer {
00714 public:
00715 UCharDbArray d;
00716 IOBuffer() : StreamBuffer() { }
00717 virtual ~IOBuffer() { m_pointer=0; m_length=0; m_buffer=0;}
00718 void start() {m_pointer=0; m_buffer=(char*)d.m_buffer; m_length=d.m_size;}
00719 };
00720 }
00721
00722
00723 template <class T> static inline int load(int blob, IOBuffer& s, void* buff) {
00724 if ( blob ) {
00725 int len;
00726 s >> len;
00727 s.swapFromBuffer(buff, len*sizeof(T));
00728 }
00729 return 0;
00730 }
00731
00732
00733 template <> inline int load<string>(int blob, IOBuffer& s, void* ptr) {
00734 if ( blob ) {
00735 string* str = (string*)ptr;
00736 s >> (*str);
00737 }
00738 return 0;
00739 }
00740
00741
00742 StatusCode RootNTupleCnv::i__updateObjPool(RootAddress* rpA, INTuple* tupl, TTree* tree, RootDataConnection* con) {
00743 typedef INTuple::ItemContainer Cont;
00744 const string* par = rpA->par();
00745 unsigned long* ipar = const_cast<unsigned long*>(rpA->ipar());
00746 ++ipar[1];
00747 if ( Long64_t(ipar[1]) <= tree->GetEntries() ) {
00748 Cont& it = tupl->items();
00749 size_t k, n = it.size();
00750 vector<PoolDbTokenWrap*> paddr(n);
00751 vector<PoolDbTokenWrap> addr(n);
00752 vector<int> blob_items(n,0);
00753 for(k = 0; k < n; ++k) {
00754 Cont::value_type j = it[k];
00755 switch( j->type() )
00756 {
00757 case DataTypeInfo::OBJECT_ADDR:
00758 paddr[k] = &addr[k];
00759 tree->SetBranchAddress(j->name().c_str(),&paddr[k]);
00760 break;
00761 default:
00762 if ( 0 == tree->GetBranch(j->name().c_str()) ) blob_items[k] = 1;
00763 break;
00764 }
00765 }
00766 ULong64_t last = (ULong64_t)tree->GetEntries();
00767 ISelectStatement* sel = tupl->selector();
00768 if ( sel ) {
00769 string criteria = (sel && (sel->type() & ISelectStatement::STRING))
00770 ? sel->criteria() : string("");
00771 if ( !(criteria.length() == 0 || criteria == "*") ) {
00772 if ( rpA->select == 0 ) {
00773 log() << MSG::DEBUG << "Selection criteria: " << criteria << " " << ipar[1] << endmsg;
00774 rpA->select = new TTreeFormula(tree->GetName(),criteria.c_str(), tree);
00775 }
00776 rpA->select->SetTree(tree);
00777
00778 for( ; ipar[1] < last; ++ipar[1]) {
00779 tree->LoadTree(ipar[1]);
00780 rpA->select->GetNdata();
00781 if ( fabs(rpA->select->EvalInstance(0)) > std::numeric_limits<float>::epsilon() ) {
00782 break;
00783 }
00784 log() << MSG::DEBUG << par[0] << "/" << par[1] << " SKIP Entry: " << ipar[1] << endmsg;
00785 }
00786 }
00787 }
00788 if ( ipar[1] < last ) {
00789 IOBuffer blob;
00790 UCharDbArray *pblob = &blob.d;
00791 tree->GetBranch("BlobData")->SetAddress(&pblob);
00792 if ( tree->GetEntry(ipar[1]) > 1 ) {
00793 int sc = 0;
00794 blob.start();
00795 for(k = 0; k < n; ++k) {
00796 Cont::value_type j = it[k];
00797 char* buf = (char*)j->buffer();
00798 switch( j->type() )
00799 {
00800 case DataTypeInfo::OBJECT_ADDR: {
00801 RootRef r = con->tool()->poolRef(addr[k].token.m_oid.first);
00802 GenericAddress* pA = (*(GenericAddress**)buf);
00803 if ( pA ) {
00804 string *spar = (string*)pA->par();
00805 ipar = (unsigned long*)pA->ipar();
00806 spar[0] = con->getDb(r.dbase);
00807 spar[1] = con->getCont(r.container);
00808 spar[2] = con->getLink(r.link);
00809 ipar[0] = 0;
00810 ipar[1] = addr[k].token.m_oid.second;
00811 if ( r.svc == POOL_ROOT_StorageType ||
00812 r.svc == POOL_ROOTKEY_StorageType ||
00813 r.svc == POOL_ROOTTREE_StorageType ) {
00814 r.svc = ROOT_StorageType;
00815 }
00816 pA->setClID(r.clid);
00817 pA->setSvcType(r.svc);
00818 break;
00819 }
00820 sc = 11;
00821 break;
00822 }
00823 case DataTypeInfo::UCHAR: sc=load<unsigned char> (blob_items[k],blob,buf); break;
00824 case DataTypeInfo::USHORT: sc=load<unsigned short>(blob_items[k],blob,buf); break;
00825 case DataTypeInfo::UINT: sc=load<unsigned int> (blob_items[k],blob,buf); break;
00826 case DataTypeInfo::ULONG: sc=load<unsigned long> (blob_items[k],blob,buf); break;
00827 case DataTypeInfo::CHAR: sc=load<char> (blob_items[k],blob,buf); break;
00828 case DataTypeInfo::SHORT: sc=load<short> (blob_items[k],blob,buf); break;
00829 case DataTypeInfo::INT: sc=load<int> (blob_items[k],blob,buf); break;
00830 case DataTypeInfo::LONG: sc=load<long> (blob_items[k],blob,buf); break;
00831 case DataTypeInfo::BOOL: sc=load<bool> (blob_items[k],blob,buf); break;
00832 case DataTypeInfo::FLOAT: sc=load<float> (blob_items[k],blob,buf); break;
00833 case DataTypeInfo::DOUBLE: sc=load<double> (blob_items[k],blob,buf); break;
00834 case DataTypeInfo::STRING: sc=load<string> (blob_items[k],blob,buf); break;
00835 case DataTypeInfo::NTCHAR: sc=load<char*> (blob_items[k],blob,buf); break;
00836 case DataTypeInfo::POINTER: sc = 0; break;
00837 case DataTypeInfo::UNKNOWN: break;
00838 default: break;
00839 }
00840 if ( 0 != sc ) {
00841 log() << MSG::DEBUG;
00842 switch (sc)
00843 {
00844 case 10:
00845 log() << "CANNOT Set Ntuple token: dynamic_cast<GenericAddress*> is NULL";
00846 break;
00847 case 11:
00848 log() << "CANNOT Set Ntuple token: invalid address buffer";
00849 break;
00850 }
00851 log() << endmsg;
00852 }
00853 }
00854 return StatusCode::SUCCESS;
00855 }
00856 log() << MSG::ERROR << "Failed to read data from NTuple tree." << endmsg;
00857 return StatusCode::FAILURE;
00858 }
00859 log() << MSG::INFO << "End of input Ntuple." << endmsg;
00860 return StatusCode::FAILURE;
00861 }
00862 return StatusCode::FAILURE;
00863 }
00864 #endif