Gaudi Framework, version v23r2

Home   Generated: Thu Jun 28 2012

RootNTupleCnv.cpp

Go to the documentation of this file.
00001 // $Id: RootNTupleCnv.cpp,v 1.13 2010-09-27 15:43:53 frankb Exp $
00002 //------------------------------------------------------------------------------
00003 //
00004 // Implementation of class :  RootNTupleCnv
00005 //
00006 // Author :                   Markus Frank
00007 //
00008 //------------------------------------------------------------------------------
00009 
00010 #define ALLOW_ALL_TYPES
00011 // Include files
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 // ROOT include files
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*& /*pObj*/)
00047 {  return loadLong(is);          }
00048 
00049 #if 0
00050 static inline istream& operator>>(istream& is, SmartRef<DataObject>& /*pObj*/)   
00051 {  return loadLong(is);          }
00052 static inline istream& operator>>(istream& is, SmartRef<ContainedObject>& /*pObj*/)   
00053 {  return loadLong(is);          }
00054 static inline istream& operator>>(istream& is, string& /*pObj*/)   
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       //return StatusCode::SUCCESS;
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 // Converter overrides: Update the references of an updated transient object.
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             case DataTypeInfo::NTCHAR:
00220             case DataTypeInfo::LONG_NTCHAR:
00221             status =
00222             createItem(tree, nt, is, title, true, (char*)0);
00223             break;
00224             case DataTypeInfo::STRING:
00225             case DataTypeInfo::LONG_STRING:
00226             status =
00227             createItem(tree, nt, is, title, true, string(""));
00228             break;
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 // Update the transient object: NTuples end here when reading records
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         // POOL compatibility mode:
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 // Update the transient object: NTuples end here when reading records
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]) {     // loop on all selected entries
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 ) { // Fill only if item is connected!
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                   // Now patch the references and links 'en block' to be efficient
00359                   // First the leafs from the TES
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 // Resolve the references of the converted object.
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 // Compatibility code to access ETCs, which were written using POOL
00710 
00711 namespace {
00712   // Blob I/O helper class
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 // Helper to read
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 // Helper to read specialized for strings
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 // Update the transient object: NTuples end here when reading records
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         // loop on all selected entries
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 ) { // Fill only if item is connected!
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated at Thu Jun 28 2012 23:27:30 for Gaudi Framework, version v23r2 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004