Gaudi Framework, version v24r2

Home   Generated: Wed Dec 4 2013
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
NTupleSvc.cpp
Go to the documentation of this file.
1 //====================================================================
2 // NTupleSvc.cpp
3 //--------------------------------------------------------------------
4 //
5 // Package : GaudiSvc/NTupleSvc ( The LHCb Offline System)
6 //
7 // Description: implementation of the NTuple service
8 //
9 // Author : M.Frank
10 // History :
11 // +---------+----------------------------------------------+---------
12 // | Date | Comment | Who
13 // +---------+----------------------------------------------+---------
14 // | 29/10/98| Initial version | MF
15 // | 29/09/99| Added access to ICnvManager for missing |
16 // | | converters | MF
17 // | 20/09/00| Connect dynamically to conversion service |
18 // | | for N-tuple persistency | MF
19 // +---------+----------------------------------------------+---------
20 //
21 //====================================================================
22 #define GAUDISVC_NTUPLESVC_CPP
23 
24 // Framework include files
25 #include "GaudiKernel/xtoa.h"
26 #include "GaudiKernel/SmartIF.h"
27 #include "GaudiKernel/Tokenizer.h"
28 #include "GaudiKernel/SvcFactory.h"
29 #include "GaudiKernel/DataObject.h"
32 
33 #include "GaudiKernel/IProperty.h"
36 
37 #include "GaudiKernel/Property.h"
38 #include "GaudiKernel/Selector.h"
39 #include "GaudiKernel/MsgStream.h"
43 
44 #include "NTupleSvc.h"
45 
46 // Instantiation of a static factory class used by clients to create
47 // instances of this service
49 
50 
51 DECLARE_NAMESPACE_OBJECT_FACTORY(NTuple,Selector)
52 
53 #include <sstream>
54 
55 namespace {
56  inline std::string toStr(long id) {
57  std::ostringstream s; s << id;
58  return s.str();
59  }
60 }
61 
64  : base_class(name, svc)
65 {
66  declareProperty("Input", m_input);
67  declareProperty("Output", m_output);
68  m_rootName = "/NTUPLES";
70 }
71 
74 }
75 
79  if ( status.isSuccess() ) {
80  status = setProperties();
81  if ( status.isSuccess() ) {
84  status = setRoot(m_rootName, root);
85  for ( DBaseEntries::iterator i = m_output.begin(); i != m_output.end(); ++i ) {
86  iret = connect(*i);
87  if ( !iret.isSuccess() ) {
88  status = iret;
89  }
90  }
91  for ( DBaseEntries::iterator j = m_input.begin(); j != m_input.end(); ++j ) {
92  iret = connect(*j);
93  if ( !iret.isSuccess() ) {
94  status = iret;
95  }
96  }
97  }
98  }
99  return status;
100 }
101 
104  return StatusCode::SUCCESS;
105 }
106 
107 // Check if a datasource is connected
108 bool NTupleSvc::isConnected(const std::string& identifier) const {
110  return !(i==m_connections.end());
111 }
112 
115  if ( 0 != pRegistry ) {
116  std::string full = pRegistry->identifier();
117  size_t len = m_rootName.length();
118  size_t idx = full.find(SEPARATOR,len+1);
119  std::string path = (idx==std::string::npos) ? full : full.substr(0, idx);
121  if ( i != m_connections.end() ) {
122  return (*i).second.service;
123  }
124  }
125  return 0;
126 }
127 
129  typedef std::vector<IRegistry*> Leaves;
130  long need_update = 0;
131  DataObject* pO = 0;
132  StatusCode iret = findObject(m_rootName, pO);
133  MsgStream log ( msgSvc(), name() );
134  // log << MSG::DEBUG << "in finalize()" << endmsg;
135  if ( iret.isSuccess() ) {
136  Leaves leaves;
137  iret = objectLeaves(pO, leaves);
138  if ( iret.isSuccess() ) {
139  // Only traverse the tree below the files
140  for ( Leaves::iterator d = leaves.begin(); d != leaves.end(); d++ ) {
141  if ( (*d)->object() ) {
142  IOpaqueAddress* pA = (*d)->address();
143  if ( pA ) {
144  unsigned long typ = pA->ipar()[1];
145  if ( typ == 'R' || typ == 'N' || typ == 'U' ) {
146  // ...starting from the file entries: first save the directories/ntuples
147  IConversionSvc* svc = getDataLoader(*d);
148  if ( 0 != svc ) {
149  StatusCode status;
150  DataSelectionAgent agent;
151  IDataSelector* sel = agent.selectedObjects();
152  traverseSubTree ( (*d)->object(), &agent ).ignore();
153  for(int i = sel->size()-1; i >= 0; i-- ) {
154  DataObject* o = (*sel)[i];
155  IRegistry* r = o->registry();
156  status = svc->updateRep(r->address(), o);
157  if ( !status.isSuccess() ) {
158  iret = status;
159  }
160  }
161  for(int j = sel->size()-1; j >= 0; j-- ) {
162  DataObject* o = (*sel)[j];
163  IRegistry* r = o->registry();
164  status = svc->updateRepRefs(r->address(), o);
165  if ( !status.isSuccess() ) {
166  iret = status;
167  }
168  }
169  if ( iret.isSuccess() ) need_update += sel->size();
170  }
171  }
172  }
173  }
174  }
175  }
176  }
177  if ( !iret.isSuccess() ) {
178  log << MSG::ERROR << "ERROR while saving NTuples" << endmsg;
179  return iret;
180  }
181  else if ( need_update > 0 ) {
182  log << MSG::INFO << "NTuples saved successfully" << endmsg;
183  }
184  return iret;
185 }
186 
187 // Finalize single service
189  SmartIF<IService> isvc( c.service );
190  if ( isvc.isValid( ) ) {
191  isvc->finalize().ignore();
192  }
193  c.service->release();
194  c.service = 0;
195 }
196 
197 // Close all open connections
200  if ( i != m_connections.end() ) {
201  releaseConnection((*i).second);
202  m_connections.erase(i);
203  return StatusCode::SUCCESS;
204  }
205  return StatusCode::FAILURE;
206 }
207 
208 // Close all open connections
211  releaseConnection((*i).second);
212  }
214  return StatusCode::SUCCESS;
215 }
216 
219  StatusCode status = updateDirectories();
220  status = clearStore();
221  status = DataSvc::finalize();
222  status = disconnectAll();
223  return status;
224 }
225 
227  std::string logName;
228  return connect(ident, logName);
229 }
230 
232  MsgStream log ( msgSvc(), name() );
233  DataObject* pO = 0;
234  StatusCode status = findObject(m_rootName, pO);
235  if ( status.isSuccess() ) {
236  char typ=0;
237  Tokenizer tok(true);
238  std::vector<Prop> props;
239  long loc = ident.find(" ");
240  std::string filename, auth, svc = "", db_typ = "";
241  logname = ident.substr(0,loc);
242  tok.analyse(ident.substr(loc+1,ident.length()), " ", "", "", "=", "'", "'");
243  for ( Tokenizer::Items::iterator i = tok.items().begin(); i != tok.items().end(); ++i) {
244  const std::string& tag = (*i).tag();
245  switch( ::toupper(tag[0]) ) {
246  case 'A':
247  break;
248  case 'F': // FILE='<file name>'
249  case 'D': // DATAFILE='<file name>'
250  filename = (*i).value();
251  break;
252  case 'O': // OPT='<NEW<CREATE,WRITE>, UPDATE, READ>'
253  switch( ::toupper((*i).value()[0]) ) {
254  case 'C':
255  case 'N':
256  case 'W':
257  typ = 'N';
258  break;
259  case 'U':
260  typ = 'U';
261  break;
262  case 'O':
263  case 'R':
264  typ = 'O';
265  break;
266  default:
267  typ = 0;
268  break;
269  }
270  break;
271  case 'T': // TYP='<HBOOK,ROOT,OBJY,...>'
272  db_typ = (*i).value();
273  break;
274  default:
275  props.push_back( Prop((*i).tag(), (*i).value()));
276  break;
277  }
278  }
279  if ( 0 != typ ) {
280  IConversionSvc* pSvc = 0;
281  status = createService(name()+'.'+logname, db_typ, props, pSvc);
282  if ( status.isSuccess() ) {
283  status = attachTuple(filename, logname, typ, pSvc->repSvcType());
284  if ( status.isSuccess() ) {
286  return StatusCode::SUCCESS;
287  }
288  }
289  }
290  }
291  log << MSG::ERROR << "Cannot add " << ident << " invalid filename!" << endmsg;
292  return StatusCode::FAILURE;
293 }
294 
296  const std::string& typ,
297  const std::vector<Prop>& /* props */,
298  IConversionSvc*& pSvc)
299 {
300  MsgStream log ( msgSvc(), name() );
302  // Get the value of the Stat persistancy mechanism from the AppMgr
303  IProperty* appPropMgr = 0;
304  StatusCode sts = serviceLocator()->queryInterface(IProperty::interfaceID(), pp_cast<void>(&appPropMgr) );
305  if( !sts.isSuccess() ) {
306  // Report an error and return the FAILURE status code
307  log << MSG::ERROR << "Could not get PropMgr" << endmsg;
308  return sts;
309  }
310 
311  StringProperty sp("HistogramPersistency","");
312  sts = appPropMgr->getProperty( &sp );
313  if ( !sts.isSuccess() ) {
314  log << MSG::ERROR << "Could not get NTuple Persistency format"
315  << " from ApplicationMgr properties" << endmsg;
316  return sts;
317  }
318 
319  long storage_typ = TEST_StorageType;
320  if ( sp.value() == "HBOOK" ) {
321  storage_typ = HBOOK_StorageType;
322  }
323  else if ( sp.value() == "ROOT" ) {
324  storage_typ = ROOT_StorageType;
325  }
326  else {
327  appPropMgr->release();
328  log << MSG::ERROR << "Unknown NTuple Persistency format: " << sp.value() << endmsg;
329  return StatusCode::FAILURE;
330  }
331  // Clean up
332  appPropMgr->release();
333 
334  if ( typ.length() > 0 && typ != sp.value() ) {
335  log << MSG::WARNING << "NTuple persistency type is "
336  << sp.value() << "." << endmsg
337  << "Type given by job option "
338  << "NTupleSvc.Input/Output ignored!" << endmsg;
339  }
340 
341  // log << MSG::DEBUG << "storage type: " << m_storageType << endmsg;
342 
343  // FIXME: (MCl) why NTupleSvc has to directly create a ConversionSvc?
344  IService* pService = 0;
345  IInterface* iface = new ConversionSvc(name()+"Conversions", serviceLocator(), storage_typ);
346  StatusCode status = iface->queryInterface(IService::interfaceID(), pp_cast<void>(&pService));
347  if ( status.isSuccess() ) {
348  status = iface->queryInterface(IConversionSvc::interfaceID(), pp_cast<void>(&pSvc));
349  if ( !status.isSuccess() ) {
350  pService->release();
351  return status;
352  }
353  }
354  status = pService->sysInitialize();
355  if ( !status.isSuccess() ) {
356  return status;
357  }
358  pService->release();
359  status = pSvc->setDataProvider(this);
360  if ( !status.isSuccess() ) {
361  return status;
362  }
363  return status;
364 }
365 
367 StatusCode NTupleSvc::create(const CLID& typ, const std::string& title, NTuple::Tuple*& refpTuple) {
368  NTuple::TupleImp* pTuple = 0;
370  if ( typ == CLID_ColumnWiseTuple ) {
371  pTuple = new NTuple::ColumnWiseTuple( title );
372  }
373  else if ( typ == CLID_RowWiseTuple ) {
374  pTuple = new NTuple::RowWiseTuple( title );
375  }
376  else {
378  }
379  if ( 0 != pTuple ) {
380  pTuple->setTupleService(this);
381  status = StatusCode::SUCCESS;
382  }
383  refpTuple = pTuple;
384  return status;
385 }
386 
388 NTuple::Tuple* NTupleSvc::book (const std::string& fullPath, const CLID& type, const std::string& title) {
389  DataObject* pObj = 0;
390  std::string path = fullPath;
391  MsgStream log(msgSvc(), name());
392  if ( path[0] != SEPARATOR ) {
393  path = m_rootName;
394  path += SEPARATOR;
395  path += fullPath;
396  }
397  StatusCode status = retrieveObject(path, pObj);
398  if ( !status.isSuccess() ) {
399  int sep = path.rfind(SEPARATOR);
400  if ( sep > 0 ) {
401  std::string p_path (path, 0, sep);
402  std::string o_path (path, sep, path.length());
403  DataObject* dir = createDirectory(p_path);
404  if ( 0 != dir ) {
405  NTuple::Tuple* tup = book( dir, o_path, type, title);
406  if ( 0 == tup ) {
407  log << MSG::ERROR << "Cannot book N-tuple " << path << " (Unknown reason)" << endmsg;
408  }
409  return tup;
410  }
411  log << MSG::ERROR << "Cannot book N-tuple " << path << " (Invalid parent directory)" << endmsg;
412  return 0;
413  }
414  log << MSG::ERROR << "Cannot book N-tuple " << path << " (Invalid path)" << endmsg;
415  return 0;
416  }
417  log << MSG::ERROR << "Cannot book N-tuple " << path << " (Exists already)" << endmsg;
418  return 0;
419 }
420 
422 NTuple::Tuple* NTupleSvc::book (const std::string& dirPath, const std::string& relPath, const CLID& type, const std::string& title) {
423  std::string full = dirPath;
424  if (relPath[0] != SEPARATOR) full += SEPARATOR;
425  full += relPath;
426  return book(full, type, title);
427 }
428 
430 NTuple::Tuple* NTupleSvc::book (const std::string& dirPath, long id, const CLID& type, const std::string& title) {
431  return book( dirPath, toStr(id), type, title);
432 }
433 
435 NTuple::Tuple* NTupleSvc::book (DataObject* pParent, const std::string& relPath, const CLID& type, const std::string& title) {
436  NTuple::Tuple* pObj = 0;
437  // Check if object is already present
438  StatusCode status = findObject(pParent, relPath, *pp_cast<DataObject>(&pObj));
439  // No ? Then create it!
440  if ( !status.isSuccess() ) {
441  status = create( type, title, pObj);
442  if ( status.isSuccess() ) {
443  // Finally register the created N tuple with the store
444  status = registerObject(pParent, relPath, pObj);
445  if ( status.isSuccess() ) {
446  return pObj;
447  }
448  pObj->release();
449  }
450  }
451  return 0;
452 }
453 
456  long id,
457  const CLID& type,
458  const std::string& title) {
459  return book( pParent, toStr(id), type, title);
460 }
461 
464  const std::string& relPath) {
465  if ( 0 != pParent ) {
466  IRegistry* pDir = pParent->registry();
467  if ( 0 != pDir ) {
468  std::string full = pDir->identifier();
469  full += (relPath[0]=='/') ? "" : "/";
470  full += relPath;
471  return createDirectory(full);
472  }
473  }
474  return 0;
475 }
476 
479  return createDirectory( pParent, toStr(id) );
480 }
481 
484  return createDirectory( dirPath, toStr(id) );
485 }
486 
489  std::string full = dirPath;
490  full += (relPath[0]=='/') ? "" : "/";
491  full += relPath;
492  return createDirectory(full);
493 }
494 
495 StatusCode NTupleSvc::attachTuple(const std::string& filename, const std::string& logname, const char typ, const long t) {
496  MsgStream log(msgSvc(), name());
497  DataObject* p;
498  // First get the root object
499  StatusCode status = retrieveObject(m_rootName, p);
500  if ( status.isSuccess() ) {
501  // Now add the registry entry to the store
502  std::string entryname = m_rootName;
503  entryname += '/';
504  entryname += logname;
505  GenericAddress* pA =
506  new GenericAddress(t, CLID_NTupleFile, filename, entryname, 0, typ);
507  status = registerAddress(p, logname, pA);
508  if ( status.isSuccess() ) {
509  log << MSG::INFO << "Added stream file:" << filename << " as " << logname << endmsg;
510  return status;
511  }
512  pA->release();
513  }
514  log << MSG::ERROR << "Cannot add file:" << filename << " as " << logname << endmsg;
515  return status;
516 }
517 
520  NTuple::Directory* p = 0;
521  StatusCode status = findObject(fullPath, *pp_cast<DataObject>(&p));
522  if ( !status.isSuccess() ) {
523  int sep2 = fullPath.rfind(SEPARATOR);
524  if ( sep2 > 0 ) {
525  std::string relPath = fullPath.substr(0, sep2);
526  p = createDirectory(relPath);
527  if ( 0 != p ) {
528  p = new NTuple::Directory();
529  // Finally register the created N tuple with the store
530  status = registerObject(fullPath, p);
531  if ( status.isSuccess() ) {
532  // ...starting from the file entries
534  if ( 0 != svc ) {
535  IOpaqueAddress* pAddr = 0;
536  status = svc->createRep (p, pAddr);
537  if ( status.isSuccess() ) {
538  p->registry()->setAddress(pAddr);
539  status = svc->fillRepRefs (pAddr, p);
540  if ( status.isSuccess() ) {
541  return p;
542  }
543  }
544  }
545  unregisterObject(p);
546  }
547  p->release();
548  p = 0;
549  }
550  }
551  }
552  try {
553  p = dynamic_cast<NTuple::Directory*>(p);
554  return p;
555  }
556  catch (...) {
557  }
558  return 0;
559 }
560 
563  MsgStream log ( msgSvc(), name() );
564  return 0;
565 }
566 
569  MsgStream log ( msgSvc(), name() );
570  NTuple::Tuple* pObj = 0;
571  StatusCode status = findObject(fullPath, *pp_cast<DataObject>(&pObj)); // Check if object is present
572  if ( status.isSuccess() ) {
573  return save ( pObj );
574  }
575  return INVALID_OBJ_PATH;
576 }
577 
580  NTuple::TupleImp* tuple = (NTuple::TupleImp*)n_tuple;
581  if ( 0 != tuple ) {
582  try {
583  IConversionSvc* pSvc = tuple->conversionService();
584  IRegistry* pReg = tuple->registry();
585  if ( 0 != pSvc && 0 != pReg ) {
586  IOpaqueAddress* pAddr = pReg->address();
587  StatusCode status = pSvc->updateRep(pAddr, n_tuple);
588  if ( status.isSuccess() ) {
589  status = pSvc->updateRepRefs(pAddr, n_tuple);
590  }
591  return status;
592  }
594  }
595  catch(...) {
596  }
597  }
598  return INVALID_OBJECT;
599 }
600 
603  NTuple::Tuple* pObj = 0;
604  StatusCode status = findObject(pParent, relPath, *pp_cast<DataObject>(&pObj)); // Check if object is present
605  if ( status.isSuccess() ) {
606  return save ( pObj );
607  }
608  return INVALID_OBJ_PATH;
609 }
610 
613  NTuple::TupleImp* tuple = (NTuple::TupleImp*)n_tuple;
614  if ( 0 != tuple ) {
615  try {
616  IConversionSvc* pSvc = tuple->conversionService();
617  if ( 0 == pSvc ) {
618  pSvc = getDataLoader(n_tuple->registry());
619  tuple->setConversionService(pSvc);
620  }
621  if ( 0 != pSvc ) {
622  IRegistry* pReg = n_tuple->registry();
623  IOpaqueAddress* pAddr = pReg->address();
624  StatusCode status = pSvc->createRep(n_tuple, pAddr);
625  if ( status.isSuccess() ) {
626  pReg->setAddress(pAddr);
627  status = pSvc->fillRepRefs(pAddr, n_tuple);
628  }
629  return status;
630  }
632  }
633  catch(...) {
634  }
635  }
636  return INVALID_OBJECT;
637 }
638 
641  NTuple::Tuple* pObj = 0;
642  StatusCode status = findObject(fullPath, *pp_cast<DataObject>(&pObj)); // Check if object is present
643  if ( status.isSuccess() ) {
644  return writeRecord ( pObj );
645  }
646  return INVALID_OBJ_PATH;
647 }
648 
651  NTuple::Tuple* pObj = 0;
652  StatusCode status = findObject(pParent, relPath, *pp_cast<DataObject>(&pObj)); // Check if object is present
653  if ( status.isSuccess() ) {
654  return writeRecord ( pObj );
655  }
656  return INVALID_OBJ_PATH;
657 }
658 
661  StatusCode status = INVALID_OBJECT;
662  NTuple::TupleImp* tuple = (NTuple::TupleImp*)n_tuple;
663  if ( 0 != tuple ) {
664  try {
665  IConversionSvc* pSvc = tuple->conversionService();
666  if ( 0 == pSvc ) {
667  pSvc = getDataLoader(n_tuple->registry());
668  tuple->setConversionService(pSvc);
669  }
670  if ( 0 != pSvc ) {
671  IRegistry* pReg = n_tuple->registry();
672  IOpaqueAddress* pAddr = pReg->address();
673  status = pSvc->updateObj(pAddr, n_tuple);
674  if ( status.isSuccess() ) {
675  status = pSvc->updateObjRefs(pAddr, n_tuple);
676  }
677  return status;
678  }
680  }
681  catch(...) {
682  status = INVALID_OBJECT;
683  }
684  }
685  return status;
686 }
687 
690  NTuple::Tuple* pObj = 0;
691  StatusCode status = findObject(fullPath, *pp_cast<DataObject>(&pObj)); // Check if object is present
692  if ( status.isSuccess() ) {
693  return readRecord ( pObj );
694  }
695  return INVALID_OBJ_PATH;
696 }
697 
700  NTuple::Tuple* pObj = 0;
701  StatusCode status = findObject(pParent, relPath, *pp_cast<DataObject>(&pObj)); // Check if object is present
702  if ( status.isSuccess() ) {
703  return readRecord ( pObj );
704  }
705  return INVALID_OBJ_PATH;
706 }

Generated at Wed Dec 4 2013 14:33:11 for Gaudi Framework, version v24r2 by Doxygen version 1.8.2 written by Dimitri van Heesch, © 1997-2004