Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

OutputStream.cpp

Go to the documentation of this file.
00001 //      ====================================================================
00002 //  OutputStream.cpp
00003 //      --------------------------------------------------------------------
00004 //
00005 //      Package   : GaudiSvc/PersistencySvc
00006 //
00007 //      Author    : Markus Frank
00008 //
00009 //      ====================================================================
00010 #define GAUDISVC_PERSISTENCYSVC_OUTPUTSTREAM_CPP
00011 
00012 // STL include files
00013 #include <iostream>
00014 // Framework include files
00015 #include "GaudiKernel/Tokenizer.h"
00016 #include "GaudiKernel/AlgFactory.h"
00017 #include "GaudiKernel/IAlgManager.h"
00018 #include "GaudiKernel/ISvcLocator.h"
00019 #include "GaudiKernel/IConversionSvc.h"
00020 #include "GaudiKernel/IDataDirectory.h"
00021 #include "GaudiKernel/IDataManagerSvc.h"
00022 #include "GaudiKernel/IDataProviderSvc.h"
00023 #include "GaudiKernel/IPersistencySvc.h"
00024 
00025 #include "GaudiKernel/MsgStream.h"
00026 #include "GaudiKernel/DataStoreItem.h"
00027 #include "OutputStream.h"
00028 #include "OutputStreamAgent.h"
00029 
00030 // Define the algorithm factory for the standard output data writer
00031 static const AlgFactory<OutputStream> s_factory;
00032 const IAlgFactory& OutputStreamFactory = s_factory;
00033 
00034 // Standard Constructor
00035 OutputStream::OutputStream(const std::string& name, ISvcLocator* pSvcLocator)
00036  : Algorithm(name, pSvcLocator)
00037 {
00038   m_doPreLoad      = true;
00039   m_output         = "";
00040   m_outputName     = "";
00041   m_storeName      = "EventDataSvc";
00042   m_persName       = "EventPersistencySvc";
00043   m_agent          = new OutputStreamAgent(this);
00044   m_pDataManager   = 0;
00045   m_pDataProvider  = 0;
00046   m_pConversionSvc = 0;
00047   m_acceptAlgs     = new std::vector<Algorithm*>( );
00048   m_requireAlgs    = new std::vector<Algorithm*>( );
00049   m_vetoAlgs       = new std::vector<Algorithm*>( );
00050         declareProperty("ItemList",         m_itemNames);
00051         declareProperty("Output",           m_output);
00052         declareProperty("OutputFile",       m_outputName);
00053         declareProperty("EvtDataSvc",       m_storeName);
00054         declareProperty("EvtConversionSvc", m_persName);
00055         declareProperty("AcceptAlgs",       m_acceptNames);
00056         declareProperty("RequireAlgs",      m_requireNames);
00057         declareProperty("VetoAlgs",         m_vetoNames);
00058 
00059     // Associate action handlers with the AcceptAlgs, RequireAlgs & VetoAlgs properties
00060   m_acceptNames.declareUpdateHandler ( &OutputStream::acceptAlgsHandler , this );
00061     m_requireNames.declareUpdateHandler( &OutputStream::requireAlgsHandler, this );
00062     m_vetoNames.declareUpdateHandler   ( &OutputStream::vetoAlgsHandler   , this );
00063 }
00064 
00065 // Standard Destructor
00066 OutputStream::~OutputStream()   {
00067   delete m_agent;
00068   delete m_acceptAlgs;
00069   delete m_requireAlgs;
00070   delete m_vetoAlgs;
00071 }
00072 
00073 // initialize data writer
00074 StatusCode OutputStream::initialize() {
00075   StatusCode status = StatusCode::SUCCESS;
00076         MsgStream log(msgSvc(), name());
00077         
00078         // Reset the number of events written
00079         m_events = 0;
00080         
00081         // Use the Job options service to set the Algorithm's parameters
00082         setProperties();
00083   // Get access to the DataManagerSvc
00084   status = serviceLocator()->getService(m_storeName, IID_IDataManagerSvc, (IInterface*&)m_pDataManager );
00085   if( !status.isSuccess() )   {
00086     log << MSG::FATAL << "Unable to locate IDataManagerSvc interface" << endreq;
00087     return status;
00088   }
00089   m_pDataManager->addRef();
00090   // Get access to the assigned data service
00091   status = serviceLocator()->getService(m_storeName, IID_IDataProviderSvc, (IInterface*&)m_pDataProvider );
00092   if( !status.isSuccess() )   {
00093     log << MSG::FATAL << "Unable to locate IDataProviderSvc interface of " << m_storeName << endreq;
00094     return status;
00095   }
00096   m_pDataProvider->addRef();
00097   status = connectConversionSvc();
00098   if( !status.isSuccess() )   {
00099     log << MSG::FATAL << "Unable to connect to conversion service." << endreq;
00100     return status;
00101   }
00102   m_pConversionSvc->addRef();
00103 
00104   // Clear the item list
00105   clearItems();
00106   // Take the new item list from the properties.
00107   for(ItemNames::iterator i = m_itemNames.begin(); i != m_itemNames.end(); i++)   {
00108     addItem( *i );
00109   }
00110   // Take the item list to the data service preload list.
00111   if ( m_doPreLoad )    {
00112     for(Items::iterator j = m_itemList.begin(); j != m_itemList.end(); j++)   {
00113       m_pDataProvider->addPreLoadItem( *(*j) );
00114     }
00115     // Not working: bad reference counting! pdataSvc->release();
00116   }
00117   log << MSG::INFO << "Data source: " << m_storeName  << endreq;
00118   log << MSG::INFO << "Data output: " << m_output << endreq;
00119 
00120   // Decode the accept, required and veto Algorithms. The logic is the following:
00121   //  a. The event is accepted if all lists are empty.
00122   //  b. The event is provisionally accepted if any Algorithm in the accept list
00123   //     has been executed and has indicated that its filter is passed. This
00124   //     provisional acceptance can be overridden by the other lists.
00125   //  c. The event is rejected unless all Algorithms in the required list have
00126   //     been executed and have indicated that their filter passed.
00127   //  d. The event is rejected if any Algorithm in the veto list has been
00128   //     executed and has indicated that its filter has passed.
00129   decodeAcceptAlgs ( );
00130   decodeRequireAlgs( );
00131   decodeVetoAlgs   ( );
00132   return status;
00133 }
00134 
00135 // terminate data writer
00136 StatusCode OutputStream::finalize() {
00137   MsgStream log(msgSvc(), name());
00138   log << MSG::INFO << "Events output: " << m_events << endreq;
00139   if ( m_pDataProvider ) m_pDataProvider->release();
00140   m_pDataProvider = 0;
00141   if ( m_pDataManager ) m_pDataManager->release();
00142   m_pDataManager = 0;
00143   if ( m_pConversionSvc ) m_pConversionSvc->release();
00144   m_pConversionSvc = 0;
00145   clearItems();
00146         return StatusCode::SUCCESS;
00147 }
00148 
00149 // Work entry point
00150 StatusCode OutputStream::execute() {
00151   StatusCode status = StatusCode::SUCCESS;
00152   // Clear any previously existing item list
00153   clearSelection();
00154 
00155   // Test whether this event should be output
00156   if ( isEventAccepted( ) ) {
00157     // Connect the output file to the service
00158     status = m_pConversionSvc->connectOutput(m_outputName);
00159     if ( status.isSuccess() )   {
00160       // Traverse the tree and collect the requested objects
00161       for ( Items::iterator i = m_itemList.begin(); i != m_itemList.end(); i++ )    {
00162         m_currentItem = (*i);
00163         status = m_pDataManager->traverseSubTree(m_currentItem->path(), m_agent);
00164       }
00165       if ( status.isSuccess() )   {
00166         // Now pass the collection to the persistency service
00167         status = m_pConversionSvc->createReps( selectedObjects() );
00168       }
00169       clearSelection();
00170       m_events++;
00171     }
00172   }
00173   return status;
00174 }
00175 
00176 // Place holder to create configurable data store agent
00177 bool OutputStream::collect(IDataDirectory* dir, int level)    {
00178   if ( level < m_currentItem->depth() )   {
00179     if ( dir->object() != 0 )   {
00180       /*
00181       std::cout << "Analysing (" 
00182                 << dir->name() 
00183                 << ") Object:" 
00184                 << ((dir->object()==0) ? "UNLOADED" : "LOADED") 
00185                 << std::endl;
00186       */
00187       m_objects.push_back(dir->object());
00188       return true;
00189     }
00190   }
00191   return false;
00192 }
00193 
00194 // Clear collected object list
00195 void OutputStream::clearSelection()     {
00196   m_objects.erase(m_objects.begin(), m_objects.end());
00197 }
00198 
00199 // Remove all items from the output streamer list;
00200 void OutputStream::clearItems()     {
00201   for ( Items::iterator i = m_itemList.begin(); i != m_itemList.end(); i++ )    {  
00202     delete (*i);
00203   }
00204   m_itemList.erase(m_itemList.begin(), m_itemList.end());
00205 }
00206 
00207 // Add item to output streamer list
00208 void OutputStream::addItem(const std::string& descriptor)   {
00209         MsgStream log(msgSvc(), name());
00210   int sep = descriptor.rfind("#");
00211   int level = 0;
00212   std::string obj_path (descriptor,0,sep);
00213   std::string slevel   (descriptor,sep+1,descriptor.length());
00214   if ( slevel == "*" )  {
00215     level = 9999999;
00216   }
00217   else   {
00218     level = atoi(slevel.c_str());
00219   }
00220   DataStoreItem* item = new DataStoreItem(obj_path, level);
00221   log << MSG::INFO << "Adding OutputStream item " << item->path()
00222       << " with " << item->depth() 
00223       << " level(s)." << endreq;
00224   m_itemList.push_back( item );
00225 }
00226 
00227 // Connect to proper conversion service
00228 StatusCode OutputStream::connectConversionSvc()   {
00229   StatusCode status = StatusCode::FAILURE;
00230         MsgStream log(msgSvc(), name());
00231   // Get output file from input
00232   std::string dbType, svc;
00233   Tokenizer tok;
00234   tok.analyse(m_output, " ", "", "", "=", "'", "'");
00235   for ( Tokenizer::Items::iterator i = tok.items().begin(); i != tok.items().end(); i++ )   {
00236     const std::string& tag = (*i).tag();
00237     const std::string& val = (*i).value();
00238     switch( ::toupper(tag[0]) )    {
00239     case 'D':
00240       m_outputName = val;
00241       break;
00242     case 'T':
00243       dbType = val;
00244       break;
00245     case 'S':
00246       svc = val;
00247       break;
00248     default:
00249       break;
00250     }
00251   }
00252   // Get access to the default Persistency service
00253   // The default service is the same for input as for output.
00254   // If this is not desired, then a specialized OutputStream must overwrite 
00255   // this value.
00256   if ( dbType.length() > 0 && svc.length()==0 )   {
00257     IPersistencySvc* ipers = 0;
00258     status = serviceLocator()->getService(m_persName, IID_IPersistencySvc, (IInterface*&)ipers );
00259     if( !status.isSuccess() )   {
00260       log << MSG::FATAL << "Unable to locate IPersistencySvc interface of " << m_persName << endreq;
00261       return status;
00262     }
00263     status = ipers->getService(dbType, m_pConversionSvc);
00264     if( !status.isSuccess() )   {
00265       log << MSG::FATAL << "Unable to locate IConversionSvc interface of database type " << dbType << endreq;
00266       return status;
00267     }
00268   }
00269   else if ( svc.length() > 0 )    {
00270     status = serviceLocator()->getService(svc, IID_IConversionSvc, (IInterface*&)m_pConversionSvc );
00271     if( !status.isSuccess() )   {
00272       log << MSG::FATAL << "Unable to locate IConversionSvc interface of " << svc << endreq;
00273       return status;
00274     }
00275   }
00276   else    {
00277     if ( m_output.length() == 0 )  m_output = m_outputName + " SVC='"+m_persName+"'";
00278     if ( m_outputName.length() == 0 )  m_outputName = m_output;
00279     status = serviceLocator()->getService(m_persName, IID_IConversionSvc, (IInterface*&)m_pConversionSvc );
00280     if( !status.isSuccess() )   {
00281       log << MSG::FATAL << "Unable to locate IConversionSvc interface of " << m_persName << endreq;
00282       return status;
00283     }
00284   }
00285   return status;
00286 }
00287 
00288 StatusCode
00289 OutputStream::decodeAcceptAlgs( )
00290 {
00291   StatusCode result = decodeAlgorithms( m_acceptNames, m_acceptAlgs );
00292   return result;
00293 }
00294 
00295 void
00296 OutputStream::acceptAlgsHandler( Property& /* theProp */ )
00297 {
00298   decodeAlgorithms( m_acceptNames, m_acceptAlgs );
00299 }
00300 
00301 StatusCode
00302 OutputStream::decodeRequireAlgs( )
00303 {
00304   StatusCode result = decodeAlgorithms( m_requireNames, m_requireAlgs );
00305   return result;
00306 }
00307 
00308 void
00309 OutputStream::requireAlgsHandler( Property& /* theProp */ )
00310 {
00311   decodeAlgorithms( m_requireNames, m_requireAlgs );
00312 }
00313 
00314 StatusCode
00315 OutputStream::decodeVetoAlgs( )
00316 {
00317   StatusCode result = decodeAlgorithms( m_vetoNames, m_vetoAlgs );
00318   return result;
00319 }
00320 
00321 void
00322 OutputStream::vetoAlgsHandler( Property& /* theProp */ )
00323 {
00324   decodeAlgorithms( m_vetoNames, m_vetoAlgs );
00325 }
00326 
00327 StatusCode
00328 OutputStream::decodeAlgorithms( StringArrayProperty& theNames,
00329                                 std::vector<Algorithm*>* theAlgs )
00330 {
00331 
00332   // Reset the list of Algorithms
00333   theAlgs->clear( );
00334 
00335   MsgStream log( msgSvc( ), name( ) );
00336 
00337   IAlgManager* theAlgMgr;
00338   StatusCode result = serviceLocator( )->getService( "ApplicationMgr",
00339                                            IID_IAlgManager,
00340                                            (IInterface*&)theAlgMgr );
00341   if ( result.isSuccess( ) ) {
00342 
00343     // Build the list of Algorithms from the names list
00344     const std::vector<std::string> nameList = theNames.value( );
00345     std::vector<std::string>::const_iterator it;
00346     std::vector<std::string>::const_iterator itend = nameList.end( );
00347     for (it = nameList.begin(); it != itend; it++) {
00348 
00349       // Check whether the suppied name corresponds to an existing
00350       // Algorithm object.
00351       std::string theName = (*it);
00352       IAlgorithm* theIAlg;
00353       Algorithm*  theAlgorithm;
00354       result = theAlgMgr->getAlgorithm( theName, theIAlg );
00355       if ( result.isSuccess( ) ) {
00356             try{
00357                   theAlgorithm = dynamic_cast<Algorithm*>(theIAlg);
00358             } catch(...){
00359                   result = StatusCode::FAILURE;
00360             }
00361           }
00362       if ( result.isSuccess( ) ) {
00363 
00364         // Check that the specified algorithm doesn't already exist in the list
00365         std::vector<Algorithm*>::iterator ita;
00366         std::vector<Algorithm*>::iterator itaend = theAlgs->end( );
00367         for (ita = theAlgs->begin(); ita != itaend; ita++) {
00368           Algorithm* existAlgorithm = (*ita);
00369           if ( theAlgorithm == existAlgorithm ) {
00370             result = StatusCode::FAILURE;
00371             break;
00372           }
00373         }
00374         if ( result.isSuccess( ) ) {
00375           theAlgs->push_back( theAlgorithm );
00376         }
00377       } else {
00378         log << MSG::INFO << theName << " doesn't exist - ignored" << endreq;
00379       }
00380     }
00381     result = StatusCode::SUCCESS;
00382   } else {
00383     log << MSG::FATAL << "Can't locate ApplicationMgr!!!" << endreq;
00384   }
00385   return result;
00386 }
00387 
00388 bool
00389 OutputStream::isEventAccepted( ) const
00390 {
00391   bool result = true;
00392 
00393   // Loop over all Algorithms in the accept list to see
00394   // whether any have been executed and have their filter
00395   // passed flag set. Any match causes the event to be
00396   // provisionally accepted.
00397   if ( ! m_acceptAlgs->empty( ) ) {
00398     result = false;
00399     std::vector<Algorithm*>::iterator it;
00400     std::vector<Algorithm*>::iterator itend = m_acceptAlgs->end( );
00401     for (it = m_acceptAlgs->begin(); it != itend; it++) {
00402       Algorithm* theAlgorithm = (*it);
00403       if ( theAlgorithm->isExecuted( ) && theAlgorithm->filterPassed( ) ) {
00404         result = true;
00405         break;
00406       }
00407     }
00408   }
00409 
00410   // Loop over all Algorithms in the required list to see
00411   // whether all have been executed and have their filter
00412   // passed flag set. Any mismatch causes the event to be
00413   // rejected.
00414   if ( result && ! m_requireAlgs->empty( ) ) {
00415     std::vector<Algorithm*>::iterator it;
00416     std::vector<Algorithm*>::iterator itend = m_requireAlgs->end( );
00417     for (it = m_requireAlgs->begin(); it != itend; it++) {
00418       Algorithm* theAlgorithm = (*it);
00419       if ( ! theAlgorithm->isExecuted( ) || ! theAlgorithm->filterPassed( ) ) {
00420         result = false;
00421         break;
00422       }
00423     }
00424   }
00425 
00426   // Loop over all Algorithms in the veto list to see
00427   // whether any have been executed and have their filter
00428   // passed flag set. Any match causes the event to be
00429   // rejected.
00430   if ( result && ! m_vetoAlgs->empty( ) ) {
00431     std::vector<Algorithm*>::iterator it;
00432     std::vector<Algorithm*>::iterator itend = m_vetoAlgs->end( );
00433     for (it = m_vetoAlgs->begin(); it != itend; it++) {
00434       Algorithm* theAlgorithm = (*it);
00435       if ( theAlgorithm->isExecuted( ) && theAlgorithm->filterPassed( ) ) {
00436         result = false;
00437         break;
00438       }
00439     }
00440   }
00441   return result;
00442 }

Generated at Wed Nov 21 12:22:30 2001 by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000