00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #define GAUDISVC_NTUPLESVC_CPP
00023
00024
00025 #include "GaudiKernel/xtoa.h"
00026 #include "GaudiKernel/SmartIF.h"
00027 #include "GaudiKernel/Tokenizer.h"
00028 #include "GaudiKernel/SvcFactory.h"
00029 #include "GaudiKernel/DataObject.h"
00030 #include "GaudiKernel/ObjectFactory.h"
00031 #include "GaudiKernel/GenericAddress.h"
00032
00033 #include "GaudiKernel/IProperty.h"
00034 #include "GaudiKernel/ISvcManager.h"
00035 #include "GaudiKernel/ISvcLocator.h"
00036 #include "GaudiKernel/IDataSelector.h"
00037 #include "GaudiKernel/IConversionSvc.h"
00038
00039 #include "GaudiKernel/MsgStream.h"
00040 #include "GaudiKernel/RegistryEntry.h"
00041 #include "GaudiKernel/DataSelectionAgent.h"
00042 #include "GaudiKernel/Property.h"
00043 #include "GaudiKernel/NTupleImplementation.h"
00044 #include "GaudiKernel/Selector.h"
00045 #include "GaudiKernel/ConversionSvc.h"
00046
00047 #include "NTupleSvc.h"
00048
00049
00050
00051 static SvcFactory<NTupleSvc> s_factory;
00052 const ISvcFactory& NTupleSvcFactory = s_factory;
00053
00055 ObjectFactory<NTuple::Selector> s_NTupleSelectorFactory;
00056 const IFactory& NTupleSelectorFactory = s_NTupleSelectorFactory;
00057
00059 NTupleSvc::NTupleSvc(const std::string& name, ISvcLocator* svc)
00060 : DataSvc(name, svc)
00061 {
00062 declareProperty("Input", m_input);
00063 declareProperty("Output", m_output);
00064 declareProperty("StoreName", m_storeName = "/NTUPLES");
00065 }
00066
00068 NTupleSvc::~NTupleSvc() {
00069 }
00070
00072 StatusCode NTupleSvc::initialize() {
00073 StatusCode status = DataSvc::initialize();
00074 MsgStream log ( msgSvc(), name() );
00075
00076 if ( status.isSuccess() ) {
00077 status = setProperties();
00078 if ( status.isSuccess() ) {
00079 DataObject* root = new DataObject();
00080 status = setRoot(m_storeName, root);
00081 for ( DBaseEntries::iterator i = m_output.begin(); i != m_output.end(); i++ ) {
00082 StatusCode iret = connect(*i);
00083 if ( !iret.isSuccess() ) {
00084 status = iret;
00085 }
00086 }
00087 for ( DBaseEntries::iterator j = m_input.begin(); j != m_input.end(); j++ ) {
00088 StatusCode iret = connect(*j);
00089 if ( !iret.isSuccess() ) {
00090 status = iret;
00091 }
00092 }
00093 }
00094 }
00095 return status;
00096 }
00097
00098
00099 bool NTupleSvc::isConnected(const std::string& identifier) const {
00100 Connections::const_iterator i = m_connections.find(identifier);
00101 return i==m_connections.end();
00102 }
00103
00104 StatusCode NTupleSvc::loadObject(IDataDirectory* pDirectory) {
00105 StatusCode status = INVALID_OBJ_ADDR;
00106 DataObject* obj = 0;
00107 if ( 0 == pDirectory->address() ) {
00108 return INVALID_OBJ_ADDR;
00109 }
00110 try {
00111 long len = m_storeName.length();
00112 std::string full = pDirectory->fullpath();
00113 std::string path = full.substr(0, full.find(IDataDirectory::SEPARATOR,len+1));
00114 Connections::iterator i = m_connections.find(path);
00115 if ( i != m_connections.end() ) {
00116 status = (*i).second->createObj(pDirectory->address(), obj);
00117 if ( status.isSuccess() ) {
00118 NTuple::TupleImp* imp = dynamic_cast<NTuple::TupleImp*>(obj);
00119 if ( 0 != imp ) {
00120 imp->setConversionSvc((*i).second);
00121 return status;
00122 }
00123 }
00124 }
00125 else {
00126 status = NO_DATA_LOADER;
00127 }
00128 }
00129 catch(...) {
00130 status = StatusCode::FAILURE;
00131 }
00132 return status;
00133 }
00134
00135 StatusCode NTupleSvc::updateDirectories() {
00136 long need_update = 0;
00137 DataObject* pO = 0;
00138 StatusCode iret = findObject(m_storeName, pO);
00139 MsgStream log ( msgSvc(), name() );
00140
00141 if ( iret.isSuccess() ) {
00142 DataSelectionAgent agent;
00143 DataObject::DirIterator d;
00144 IDataSelector* selection = agent.selectedObjects();
00145 IDataSelector sel, files;
00146
00147 for ( d = pO->dirBegin(); d != pO->dirEnd(); d++ ) {
00148 sel.erase(sel.begin(), sel.end());
00149 if ( (*d)->object() ) {
00150 IOpaqueAddress* pA = (*d)->address();
00151 if ( pA ) {
00152 char typ = pA->genericLink()->genericInfo()->m_info[1];
00153 if ( typ == 'N' || typ == 'U' ) {
00154 traverseSubTree ( (*d)->object(), &agent );
00155 while ( selection->size() > 0 ) {
00156 DataObject* o = selection->back();
00157
00158 log << MSG::DEBUG << "Update " << o->fullpath() << endreq;
00159 sel.push_back( o );
00160
00161 selection->pop_back();
00162 }
00163
00164 Connections::iterator i = m_connections.find((*d)->fullpath());
00165 if ( i != m_connections.end() ) {
00166 need_update += sel.size();
00167 iret = (*i).second->updateReps ( &sel );
00168 }
00169 }
00170 }
00171 }
00172 }
00173 }
00174 if ( !iret.isSuccess() ) {
00175 log << MSG::ERROR << "ERROR while saving NTuples" << endreq;
00176 return iret;
00177 }
00178 else if ( need_update > 0 ) {
00179 log << MSG::INFO << "ALL NTuples saved successfully" << endreq;
00180 }
00181 return iret;
00182 }
00183
00184
00185 StatusCode NTupleSvc::disconnect(const std::string& nam) {
00186 Connections::iterator i = m_connections.find(nam);
00187 if ( i != m_connections.end() ) {
00188 SmartIF<IService> isvc(IID_IService, (*i).second);
00189 if ( isvc.isValid( ) ) {
00190 isvc->finalize();
00191 }
00192 (*i).second->release();
00193 (*i).second = 0;
00194 m_connections.erase(i);
00195 return StatusCode::SUCCESS;
00196 }
00197 return StatusCode::FAILURE;
00198 }
00199
00200
00201 StatusCode NTupleSvc::disconnectAll() {
00202 for ( Connections::iterator i = m_connections.begin(); i != m_connections.end(); i++ ) {
00203 SmartIF<IService> isvc(IID_IService, (*i).second);
00204 if ( isvc.isValid( ) ) {
00205 isvc->finalize();
00206 }
00207 (*i).second->release();
00208 (*i).second = 0;
00209 }
00210 m_connections.erase(m_connections.begin(), m_connections.end());
00211 return StatusCode::SUCCESS;
00212 }
00213
00215 StatusCode NTupleSvc::finalize() {
00216 StatusCode status = updateDirectories();
00217 status = clearStore();
00218 status = DataSvc::finalize();
00219 status = disconnectAll();
00220 return status;
00221 }
00222
00224 StatusCode NTupleSvc::queryInterface(const IID& riid, void** ppvInterface) {
00225 if ( IID_INTupleSvc == riid ) {
00226 *ppvInterface = (INTupleSvc*)this;
00227 }
00228 else if ( IID_IDataSourceMgr == riid ) {
00229 *ppvInterface = (IDataSourceMgr*)this;
00230 }
00231 else {
00232
00233 return DataSvc::queryInterface(riid, ppvInterface);
00234 }
00235 addRef();
00236 return StatusCode::SUCCESS;
00237 }
00238
00239 StatusCode NTupleSvc::connect(const std::string& ident) {
00240 std::string logName;
00241 return connect(ident, logName);
00242 }
00243
00244 StatusCode NTupleSvc::connect(const std::string& ident, std::string& logname) {
00245 MsgStream log ( msgSvc(), name() );
00246 DataObject* pO = 0;
00247 StatusCode status = findObject(m_storeName, pO);
00248 if ( status.isSuccess() ) {
00249 IDataDirectory* dir = pO->directory();
00250 status = INVALID_ROOT;
00251 if ( 0 != dir ) {
00252 char typ;
00253 bool known_type = false;
00254 Tokenizer tok;
00255 std::vector<Prop> props;
00256 long loc = ident.find(" ");
00257 std::string filename, auth, svc = "DbCnvSvc";
00258 logname = ident.substr(0,loc);
00259 tok.analyse(ident.substr(loc+1,ident.length()), " ", "", "", "=", "'", "'");
00260 for ( Tokenizer::Items::iterator i = tok.items().begin(); i != tok.items().end(); i++) {
00261 const std::string& tag = (*i).tag();
00262 switch( ::toupper(tag[0]) ) {
00263 case 'A':
00264 props.push_back( Prop("Server", (*i).value()));
00265 break;
00266 case 'F':
00267 case 'D':
00268 filename = (*i).value();
00269 break;
00270 case 'O':
00271 switch( ::toupper((*i).value()[0]) ) {
00272 case 'C':
00273 case 'N':
00274 case 'W':
00275 typ = 'N';
00276 break;
00277 case 'U':
00278 typ = 'U';
00279 break;
00280 case 'O':
00281 case 'R':
00282 typ = 'O';
00283 break;
00284 default:
00285 typ = 0;
00286 break;
00287 }
00288 break;
00289 case 'S':
00290 known_type = true;
00291 svc = (*i).value();
00292 break;
00293 case 'T':
00294 known_type = true;
00295 switch(::toupper((*i).value()[0])) {
00296 case 'H':
00297 svc = "HbookCnv::ConvSvc";
00298 break;
00299 default:
00300 props.push_back( Prop("DbType", (*i).value()));
00301 svc = "DbCnvSvc";
00302 break;
00303 }
00304 break;
00305 default:
00306 props.push_back( Prop((*i).tag(), (*i).value()));
00307 break;
00308 }
00309 }
00310 if ( 0 != typ ) {
00311 IConversionSvc* pSvc = 0;
00312 if ( known_type ) {
00313 status = createService(name()+'.'+logname, svc, props, pSvc);
00314 }
00315 else {
00316 status = connectToHistogramPersistency(name()+'.'+logname, svc, props, pSvc);
00317 }
00318 if ( status.isSuccess() ) {
00319 status = attachTuple(filename, logname, typ, pSvc->repSvcType());
00320 if ( status.isSuccess() ) {
00321 m_connections.insert(Connections::value_type(m_storeName+'/'+logname, pSvc));
00322 return StatusCode::SUCCESS;
00323 }
00324 }
00325 }
00326 }
00327 }
00328 log << MSG::ERROR << "Cannot add " << ident << " invalid filename!" << endreq;
00329 return StatusCode::FAILURE;
00330 }
00331
00332 StatusCode NTupleSvc::createService(const std::string& nam, const std::string& typ, const std::vector<Prop>& props, IConversionSvc*& pSvc) {
00333 SmartIF<ISvcManager> mgr(IID_ISvcManager, serviceLocator());
00334 StatusCode status = NO_INTERFACE;
00335 if ( mgr.isValid( ) ) {
00336 IService* isvc = 0;
00337 status = mgr->createService(typ, nam, isvc);
00338 if ( status.isSuccess() ) {
00339 status = isvc->queryInterface(IID_IConversionSvc, (void**)&pSvc);
00340 if ( status.isSuccess() ) {
00341 SmartIF<IProperty> iprop(IID_IProperty,isvc);
00342 status = NO_INTERFACE;
00343 if ( iprop.isValid( ) ) {
00344 for ( std::vector<Prop>::const_iterator j = props.begin(); j != props.end(); j++) {
00345 iprop->setProperty(StringProperty((*j).first, (*j).second));
00346 }
00347 status = isvc->initialize();
00348 if ( status.isSuccess() ) {
00349 status = pSvc->setStore(this);
00350 if ( status.isSuccess() ) {
00351 return status;
00352 }
00353 }
00354 }
00355 pSvc->release();
00356 }
00357 isvc->release();
00358 }
00359 }
00360 pSvc = 0;
00361 return status;
00362 }
00363
00364 StatusCode NTupleSvc::connectToHistogramPersistency(const std::string& , const std::string& , const std::vector<Prop>& , IConversionSvc*& pSvc) {
00365 MsgStream log ( msgSvc(), name() );
00367
00368 IProperty* appPropMgr = 0;
00369 StatusCode sts;
00370
00371 sts = serviceLocator()->queryInterface(IID_IProperty,(void **)&appPropMgr );
00372 if( sts.isFailure() ) {
00373
00374 log << MSG::ERROR << "Could not get PropMgr" << endreq;
00375 return sts;
00376 }
00377
00378 StringProperty sp("HistogramPersistency","");
00379 sts = appPropMgr->getProperty( &sp );
00380 if (sts.isFailure()) {
00381 log << MSG::ERROR << "Could not get NTuple Persistency format"
00382 << " from ApplicationMgr properties" << endreq;
00383 return sts;
00384 }
00385
00386 unsigned char storage_typ = (unsigned char)TEST_StorageType;
00387 if ( sp.value() == "HBOOK" ) {
00388 storage_typ = HBOOK_StorageType;
00389 }
00390 else if ( sp.value() == "ROOT" ) {
00391 storage_typ = ROOT_StorageType;
00392 }
00393 else {
00394 appPropMgr->release();
00395 log << MSG::ERROR << "Unknown NTuple Persistency format: " << sp.value() << endreq;
00396 return StatusCode::FAILURE;
00397 }
00398
00399 appPropMgr->release();
00400
00401
00402 IService* pService = 0;
00403 IInterface* iface = new ConversionSvc(name()+"Conversions", serviceLocator(), storage_typ);
00404 StatusCode status = iface->queryInterface(IID_IService, (void**)&pService);
00405 if ( status.isSuccess() ) {
00406 status = iface->queryInterface(IID_IConversionSvc, (void**)&pSvc);
00407 if ( !status.isSuccess() ) {
00408 pService->release();
00409 return status;
00410 }
00411 }
00412 status = pService->initialize();
00413 if ( !status.isSuccess() ) {
00414 return status;
00415 }
00416 pService->release();
00417 status = pSvc->setStore(this);
00418 if ( !status.isSuccess() ) {
00419 return status;
00420 }
00421 return status;
00422 }
00423
00425 StatusCode NTupleSvc::create(const CLID& typ, const std::string& title, NTuple::Tuple*& refpTuple) {
00426
00427
00428
00429
00430 if ( typ == CLID_ColumnWiseTuple ) {
00431 refpTuple = new NTuple::ColumnWiseTuple( title );
00432 return StatusCode::SUCCESS;
00433 }
00434 else if ( typ == CLID_RowWiseTuple ) {
00435 refpTuple = new NTuple::RowWiseTuple( title );
00436 return StatusCode::SUCCESS;
00437 }
00438 refpTuple = 0;
00439 return StatusCode::FAILURE;
00440 }
00441
00443 NTuple::Tuple* NTupleSvc::book (const std::string& fullPath, const CLID& type, const std::string& title) {
00444 int sep = fullPath.rfind(IDataDirectory::SEPARATOR);
00445 if ( sep > 0 ) {
00446 std::string p_path (fullPath, 0, sep);
00447 std::string o_path (fullPath, sep, fullPath.length());
00448 DataObject* dir = createDirectory(p_path);
00449 if ( 0 != dir ) {
00450 return book( dir, o_path, type, title);
00451 }
00452 }
00453 return 0;
00454 }
00455
00457 NTuple::Tuple* NTupleSvc::book (const std::string& dirPath, const std::string& relPath, const CLID& type, const std::string& title) {
00458 std::string full = dirPath;
00459 full += (relPath[0]=='/') ? "" : "/";
00460 full += relPath;
00461 return book(full, type, title);
00462 }
00463
00465 NTuple::Tuple* NTupleSvc::book (const std::string& dirPath, long id, const CLID& type, const std::string& title) {
00466 char txt[32];
00467 return book( dirPath, _itoa(id, txt, 10), type, title);
00468 }
00469
00471 NTuple::Tuple* NTupleSvc::book (DataObject* pParent, const std::string& relPath, const CLID& type, const std::string& title) {
00472 NTuple::Tuple* pObj = 0;
00473
00474 StatusCode status = findObject(pParent, relPath, (DataObject*&)pObj);
00475
00476 if ( !status.isSuccess() ) {
00477 status = create( type, title, pObj);
00478 if ( status.isSuccess() ) {
00479
00480 status = registerObject(pParent, relPath, pObj);
00481 if ( status.isSuccess() ) {
00482 long len = m_storeName.length();
00483 std::string full = pObj->fullpath();
00484 std::string path = full.substr(0, full.find(IDataDirectory::SEPARATOR,len+1));
00485 Connections::iterator i = m_connections.find(path);
00486 if ( i != m_connections.end() ) {
00487 NTuple::TupleImp* imp = (NTuple::TupleImp*)pObj;
00488 imp->setConversionSvc((*i).second);
00489 return pObj;
00490 }
00491 }
00492 pObj->release();
00493 }
00494 }
00495 return 0;
00496 }
00497
00499 NTuple::Tuple* NTupleSvc::book (DataObject* pParent, long id, const CLID& type, const std::string& title) {
00500 char txt[32];
00501 return book( pParent, ::_itoa(id, txt,10), type, title);
00502 }
00503
00505 NTuple::Directory* NTupleSvc::createDirectory (DataObject* pParent, const std::string& relPath) {
00506 if ( 0 != pParent ) {
00507 std::string full = pParent->fullpath();
00508 full += (relPath[0]=='/') ? "" : "/";
00509 full += relPath;
00510 return createDirectory(full);
00511 }
00512 return 0;
00513 }
00514
00516 NTuple::Directory* NTupleSvc::createDirectory (DataObject* pParent, long id) {
00517 char txt[32];
00518 return createDirectory( pParent, ::_itoa(id, txt,10) );
00519 }
00520
00522 NTuple::Directory* NTupleSvc::createDirectory (const std::string& dirPath, long id) {
00523 char txt[32];
00524 return createDirectory( dirPath, ::_itoa(id, txt,10) );
00525 }
00526
00528 NTuple::Directory* NTupleSvc::createDirectory (const std::string& dirPath, const std::string& relPath ) {
00529 std::string full = dirPath;
00530 full += (relPath[0]=='/') ? "" : "/";
00531 full += relPath;
00532 return createDirectory(full);
00533 }
00534
00535 StatusCode NTupleSvc::attachTuple(const std::string& filename, const std::string& logname, const char typ, unsigned char t) {
00536 MsgStream log(msgSvc(), name());
00537 DataObject* p;
00538
00539 StatusCode status = retrieveObject(m_storeName, p);
00540 if ( status.isSuccess() ) {
00541
00542 std::string entryname = m_storeName;
00543 entryname += '/';
00544 entryname += logname;
00545 RegistryEntry* ent = dynamic_cast<RegistryEntry*>(p->directory());
00546 GenericAddress* pA = 0;
00547 pA = new GenericAddress(t, CLID_NTupleFile, 0);
00548 pA->setDbName(filename);
00549 pA->setContainerName(entryname);
00550 pA->setObjectName(logname);
00551 pA->genericInfo()->m_info[1] = typ;
00552 status = ent->add( logname, pA );
00553 if ( status.isSuccess() ) {
00554 log << MSG::INFO << "Added stream file:" << filename << " as " << logname << endreq;
00555 return status;
00556 }
00557 pA->release();
00558 }
00559 log << MSG::ERROR << "Cannot add file:" << filename << " as " << logname << endreq;
00560 return status;
00561 }
00562
00564 NTuple::Directory* NTupleSvc::createDirectory (const std::string& fullPath) {
00565 NTuple::Directory* p = 0;
00566 StatusCode status = findObject(fullPath, (DataObject*&)p);
00567 if ( !status.isSuccess() ) {
00568 int sep2 = fullPath.rfind(IDataDirectory::SEPARATOR);
00569 if ( sep2 > 0 ) {
00570 std::string relPath = fullPath.substr(0, sep2);
00571 p = createDirectory(relPath);
00572 if ( 0 != p ) {
00573 p = new NTuple::Directory( );
00574
00575 status = registerObject(fullPath, p);
00576 if ( status.isSuccess() ) {
00577 IDataSelector sel;
00578 sel.push_back( p );
00579
00580 long len = m_storeName.length();
00581 std::string path = fullPath.substr(0, fullPath.find(IDataDirectory::SEPARATOR,len+1));
00582 Connections::iterator i = m_connections.find(path);
00583 if ( i != m_connections.end() ) {
00584 status = (*i).second->createReps ( &sel );
00585 if ( status.isSuccess() ) {
00586 return p;
00587 }
00588 }
00589 unregisterObject(p);
00590 }
00591 p->release();
00592 p = 0;
00593 }
00594 }
00595 }
00596 try {
00597 p = dynamic_cast<NTuple::Directory*>(p);
00598 return p;
00599 }
00600 catch (...) {
00601 }
00602 return 0;
00603 }
00604
00606 NTuple::Tuple* NTupleSvc::access(const std::string&, const std::string&) {
00607 MsgStream log ( msgSvc(), name() );
00608 return 0;
00609 }
00610
00612 StatusCode NTupleSvc::save(const std::string& fullPath) {
00613 MsgStream log ( msgSvc(), name() );
00614 NTuple::Tuple* pObj = 0;
00615 StatusCode status = findObject(fullPath, (DataObject*&)pObj);
00616 if ( status.isSuccess() ) {
00617 return save ( pObj );
00618 }
00619 return INVALID_OBJ_PATH;
00620 }
00621
00623 StatusCode NTupleSvc::save(NTuple::Tuple* t) {
00624 try {
00625 NTuple::TupleImp* tuple = dynamic_cast<NTuple::TupleImp*>(t);
00626 if ( 0 != tuple ) {
00627 IConversionSvc* svc = tuple->conversionSvc();
00628 if ( 0 != svc ) {
00629 IDataSelector selector;
00630 selector.push_back( tuple );
00631 return svc->updateReps ( &selector );
00632 }
00633 }
00634 }
00635 catch (...) {
00636 }
00637 return StatusCode::FAILURE;
00638 }
00639
00641 StatusCode NTupleSvc::save(DataObject* pParent, const std::string& relPath) {
00642 NTuple::Tuple* pObj = 0;
00643 StatusCode status = findObject(pParent, relPath, (DataObject*&)pObj);
00644 if ( status.isSuccess() ) {
00645 return save ( pObj );
00646 }
00647 return INVALID_OBJ_PATH;
00648 }
00649
00651 StatusCode NTupleSvc::writeRecord( NTuple::Tuple* t ) {
00652 try {
00653 NTuple::TupleImp* tuple = dynamic_cast<NTuple::TupleImp*>(t);
00654 if ( 0 != tuple ) {
00655 IConversionSvc* svc = tuple->conversionSvc();
00656 if ( 0 != svc ) {
00657 IDataSelector selector;
00658 selector.push_back( tuple );
00659 return svc->createReps ( &selector );
00660 }
00661 }
00662 }
00663 catch (...) {
00664 }
00665 return StatusCode::FAILURE;
00666 }
00667
00669 StatusCode NTupleSvc::writeRecord(const std::string& fullPath ) {
00670 NTuple::Tuple* pObj = 0;
00671 StatusCode status = findObject(fullPath, (DataObject*&)pObj);
00672 if ( status.isSuccess() ) {
00673 return writeRecord ( pObj );
00674 }
00675 return INVALID_OBJ_PATH;
00676 }
00677
00679 StatusCode NTupleSvc::writeRecord( DataObject* pParent, const std::string& relPath) {
00680 NTuple::Tuple* pObj = 0;
00681 StatusCode status = findObject(pParent, relPath, (DataObject*&)pObj);
00682 if ( status.isSuccess() ) {
00683 return writeRecord ( pObj );
00684 }
00685 return INVALID_OBJ_PATH;
00686 }
00687
00689 StatusCode NTupleSvc::readRecord( NTuple::Tuple* tuple ) {
00690 IDataDirectory* pDirectory = tuple->directory();
00691 if ( 0 == pDirectory ) {
00692 return INVALID_OBJ_ADDR;
00693 }
00694 NTuple::TupleImp* imp = (NTuple::TupleImp*)tuple;
00695 IConversionSvc* svc = imp->conversionSvc();
00696 if ( 0 != svc ) {
00697 return svc->updateObj(pDirectory->address(), tuple);
00698 }
00699 return NO_DATA_LOADER;
00700 }
00701
00703 StatusCode NTupleSvc::readRecord(const std::string& fullPath) {
00704 NTuple::Tuple* pObj = 0;
00705 StatusCode status = findObject(fullPath, (DataObject*&)pObj);
00706 if ( status.isSuccess() ) {
00707 return readRecord ( pObj );
00708 }
00709 return INVALID_OBJ_PATH;
00710 }
00711
00713 StatusCode NTupleSvc::readRecord(DataObject* pParent, const std::string& relPath) {
00714 NTuple::Tuple* pObj = 0;
00715 StatusCode status = findObject(pParent, relPath, (DataObject*&)pObj);
00716 if ( status.isSuccess() ) {
00717 return readRecord ( pObj );
00718 }
00719 return INVALID_OBJ_PATH;
00720 }
00721