| # Gaudi Framework, version v23r1 |

Home |  | Generated: Wed Feb 29 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