Gaudi Framework, version v20r2

Generated: 18 Jul 2008

DataOnDemandSvc.cpp

Go to the documentation of this file.
00001 // $Id: DataOnDemandSvc.cpp,v 1.15 2008/01/14 19:42:15 marcocle Exp $
00002 // ============================================================================
00003 // CVS tag $Name: v17r1 $ 
00004 // ============================================================================
00005 // Incldue files 
00006 // ============================================================================
00007 // STD & STL 
00008 // ============================================================================
00009 #include <string>
00010 #include <set>
00011 #include <map>
00012 // ============================================================================
00013 // GaudiKernel
00014 // ============================================================================
00015 #include "GaudiKernel/MsgStream.h"
00016 #include "GaudiKernel/Tokenizer.h"
00017 #include "GaudiKernel/DataObject.h"
00018 #include "GaudiKernel/IAlgorithm.h"
00019 #include "GaudiKernel/ISvcLocator.h"
00020 #include "GaudiKernel/IAlgManager.h"
00021 #include "GaudiKernel/IIncidentSvc.h"
00022 #include "GaudiKernel/DataIncident.h"
00023 #include "GaudiKernel/IDataProviderSvc.h"
00024 #include "GaudiKernel/ListItem.h"
00025 #include "DataOnDemandSvc.h"
00026 // ============================================================================
00027 // Boost 
00028 // ============================================================================
00029 #include "boost/format.hpp"
00030 // ============================================================================
00031 
00032 // Instantiation of a static factory class used by clients to create
00033 //  instances of this service
00034 DECLARE_SERVICE_FACTORY(DataOnDemandSvc)
00035 
00036 //============================================================================================
00037 // Constructors and Desctructors
00038 //============================================================================================
00039 DataOnDemandSvc::DataOnDemandSvc 
00040 ( const std::string& name, ISvcLocator* svc )
00041   : Service(name, svc)
00042   , m_incSvc   ( 0 )
00043   , m_algMgr   ( 0 )
00044   , m_dataSvc  ( 0 )
00045   //
00046   , m_algMap   (   ) 
00047   , m_nodeMap  (   )  
00048   , m_algMap_  ( 0 ) 
00049   , m_nodeMap_ ( 0 )  
00050   //
00051   , m_updateRequired ( true )
00052   , m_prefix         ( "/Event/" )
00053   , m_log      ( 0 )
00054   , m_total    (   ) 
00055   , m_statAlg  ( 0 ) 
00056   , m_statNode ( 0 ) 
00057   , m_stat     ( 0 )
00058 {
00059   declareProperty ( "Algorithms"         , m_algMapping                   ) ;
00060   declareProperty ( "Nodes"              , m_nodeMapping                  ) ;
00061   declareProperty ( "UsePreceedingPath"  , m_partialPath = true           ) ;
00062   declareProperty ( "IncidentName"       , m_trapType    = "DataFault"    ) ;
00063   declareProperty ( "DataSvc"            , m_dataSvcName = "EventDataSvc" ) ;
00064   declareProperty ( "Prefix"             , m_prefix                       ) ;
00065   // 
00066   m_algMap_  = new MapRef ( "AlgMap"  , m_algMap  ) ;
00067   m_nodeMap_ = new MapRef ( "NodeMap" , m_nodeMap ) ;
00068   declareProperty ( m_algMap_  -> name () , *m_algMap_  ) ;
00069   declareProperty ( m_nodeMap_ -> name () , *m_nodeMap_ ) ;
00070   m_algMap_  ->  declareUpdateHandler ( &DataOnDemandSvc::update_1 , this ) ;
00071   m_nodeMap_ ->  declareUpdateHandler ( &DataOnDemandSvc::update_1 , this ) ;
00072   //
00073   m_algMapping  .declareUpdateHandler ( &DataOnDemandSvc::update_2 , this ) ;
00074   m_nodeMapping .declareUpdateHandler ( &DataOnDemandSvc::update_3 , this ) ;
00075 } 
00076 // ============================================================================
00078 // ============================================================================
00079 void DataOnDemandSvc::update_1 ( Property& p ) 
00080 {
00081   stream() 
00082     << MSG::VERBOSE << " I am update handler for property " << p << endreq ;
00083   // force update 
00084   m_updateRequired = true ;
00085 } 
00086 // ============================================================================
00088 // ============================================================================
00089 void DataOnDemandSvc::update_3 ( Property& p ) 
00090 {
00091   stream() 
00092     << MSG::VERBOSE << " I am update handler for property " << p << endreq ;
00093   if ( setupNodeHandlers().isFailure() ) 
00094   {
00095     stream() 
00096       << MSG::ERROR << " Error from setupNodeHandlers " << endreq ;
00097   }
00098   // force update 
00099   m_updateRequired = true ;
00100 } 
00101 // ============================================================================
00103 // ============================================================================
00104 void DataOnDemandSvc::update_2 ( Property& p ) 
00105 {
00106   stream() 
00107     << MSG::VERBOSE << " I am update handler for property " << p << endreq ;
00108   if ( setupAlgHandlers().isFailure() ) 
00109   {
00110     stream() 
00111       << MSG::ERROR << " Error from setupAlgHandlers " << endreq ;
00112   }
00113   // force update 
00114   m_updateRequired = true ;
00115 }
00116 // ============================================================================
00118 // ============================================================================
00119 namespace 
00120 {
00126   inline std::string no_prefix 
00127   ( const std::string& value  , 
00128     const std::string& prefix )
00129   {
00130     return 
00131       !prefix.empty() && 0 == value.find(prefix) ? 
00132       std::string( value , prefix.size() ) : value ;
00133   }
00140   template <class MAP>
00141   inline size_t add_prefix ( MAP& _map , const std::string& prefix ) 
00142   {
00143     // empty  prefix 
00144     if ( prefix.empty() ) { return 0 ; }                    // RETURN 
00146     for ( typename MAP::iterator it = _map.begin() ; _map.end() != it ; ++it ) 
00147     {
00148       if ( 0 != it->first.find(prefix) )  // valid prefix? 
00149       { 
00150         std::string key   = prefix + it->first ;
00151         std::string value = it->second ;
00152         _map.erase ( it ) ;
00153         _map[ key ] = value  ;
00154         return 1 + add_prefix ( _map , prefix ) ;    // RETURN, recursion
00155       }
00156     }
00157     //
00158     return 0 ;
00159   }
00165   template <class SET>
00166   inline size_t get_dir ( const std::string& object , SET& _set ) 
00167   {
00168     std::string::size_type ifind = object.rfind('/') ;
00169     // stop recursion 
00170     if ( std::string::npos == ifind ) { return 0 ; } // RETURN 
00171     if ( 0 == ifind                 ) { return 0 ; }
00172     //
00173     const std::string top = std::string( object , 0 , ifind) ;
00174     _set.insert( top ) ;
00175     return 1 + get_dir ( top , _set ) ;   // RETURN, recursion 
00176   } 
00182   template <class MAP, class SET>
00183   inline size_t get_dirs ( const MAP& _map, SET& _set ) 
00184   {
00185     size_t size = _set.size() ;
00186     for ( typename MAP::const_iterator item = _map.begin() ; 
00187           _map.end() != item ; ++item ) {  get_dir ( item->first , _set ) ; }
00188     return _set.size() - size ;
00189   } 
00190 } // end of anonymous namespace
00191 // ============================================================================
00192 // update the content of Data-On-Demand actions 
00193 // ============================================================================
00194 StatusCode DataOnDemandSvc::update () 
00195 {
00197   add_prefix ( m_algMap  , m_prefix ) ;
00199   add_prefix ( m_nodeMap , m_prefix ) ;
00201   typedef std::set<std::string> Set ; 
00202   Set dirs ;
00203   if ( m_partialPath ){ get_dirs ( m_algMap  , dirs ) ; }
00204   if ( m_partialPath ){ get_dirs ( m_nodeMap , dirs ) ; }
00205   //
00206   Set::iterator _e = dirs.find("/Event") ;
00207   if ( dirs.end() != _e ) { dirs.erase( _e ) ; }
00208   // add all directories as nodes 
00209   for ( Set::const_iterator dir = dirs.begin() ; dirs.end() != dir ; ++dir ) 
00210   {
00211     if ( m_algMap  .end () != m_algMap  .find ( *dir ) ) { continue ; }
00212     if ( m_nodeMap .end () != m_nodeMap .find ( *dir ) ) { continue ; }    
00213     m_nodeMap [*dir] = "DataObject" ;  
00214   }
00215   //
00216   m_algs  .clear  () ;
00217   m_nodes .clear () ;
00218   //
00220   for ( Map::const_iterator ialg = m_algMap.begin() ; 
00221         m_algMap.end() != ialg ; ++ialg )
00222   {
00223     ListItem alg ( ialg->second ) ;
00224     m_algs[ialg->first] =  Leaf( alg.type() , alg.name() ) ;
00225   }
00227   for ( Map::const_iterator inode = m_nodeMap.begin() ; 
00228         m_nodeMap.end() != inode ; ++inode ) 
00229   {
00230     ClassH cl = ROOT::Reflex::Type::ByName( inode->second ) ;
00231     if ( !cl ) 
00232     {
00233       stream() << MSG::WARNING 
00234                << "Failed to access dictionary class for "
00235                << inode->first << " of type:" << inode->second << endmsg;
00236     }
00237     m_nodes[inode->first] = Node ( cl , false , inode->second ) ;
00238   }
00240   m_updateRequired = false ;
00241   //
00242   return StatusCode::SUCCESS ;
00243 }
00244 // ============================================================================
00246 // ============================================================================
00247 DataOnDemandSvc::~DataOnDemandSvc() 
00248 { 
00249   if ( 0 != m_algMap_  ) { delete m_algMap_  ; m_algMap_  = 0 ; }
00250   if ( 0 != m_nodeMap_ ) { delete m_nodeMap_ ; m_nodeMap_ = 0 ; }
00251   if ( 0 != m_log      ) { delete m_log      ; m_log      = 0 ; }
00252 }
00253 //=============================================================================
00254 // Inherited Service overrides:
00255 //=============================================================================
00256 StatusCode DataOnDemandSvc::initialize() 
00257 {
00258   // initialize the Service Base class
00259   StatusCode sc = Service::initialize();
00260   if ( sc.isFailure() )  { return sc; }
00261   sc = setup();
00262   if ( sc.isFailure() )  { return sc; }
00263   return dump( ) ;
00264 }
00265 // ============================================================================
00267 // ============================================================================
00268 StatusCode DataOnDemandSvc::dump ( MSG::Level level )  const 
00269 {
00270   if ( !m_algs.empty()  || m_nodes.empty() ) 
00271   {
00272     stream() << level << "DataOnDemand Actions enabled for:" << endmsg;
00273     Map _m ;
00274     for ( AlgMap::const_iterator alg = m_algs.begin() ; 
00275           m_algs.end() != alg ; ++alg )
00276     {
00277       Map::const_iterator check = _m.find(alg->first) ;
00278       if ( _m.end() != check ) 
00279       {
00280         stream() << MSG::WARNING 
00281                  << " The data item is activated for '"
00282                  << check->first << "' as '" << check->second << "'" << endreq ;
00283       }
00284       boost::format fmt ("%1% %|40t|%2%") ;
00285       const Leaf& l = alg->second ;
00286       fmt 
00287         % ( l.name == l.type ? l.type  : (l.type+"/"+l.name) ) 
00288         % ( 0 == l.algorithm ? "F"     : "T"                 ) ;
00289       _m[alg->first] = boost::str( fmt ) ;
00290     }
00291     for ( NodeMap::const_iterator node = m_nodes.begin() ; 
00292           m_nodes.end() != node ; ++node )
00293     {
00294       Map::const_iterator check = _m.find(node->first) ;
00295       if ( _m.end() != check ) 
00296       {
00297         stream() << MSG::WARNING 
00298                  << " The data item is already activated for '"
00299                  << check->first << "' as '" << check->second << "'" << endreq ;
00300       }
00301       boost::format fmt ("%1% %|40t|%2%") ;
00302       const Node& n = node->second ;
00303       fmt % ( "'" + n.name + "'" ) % ( n.clazz ? "T" : "F" ) ;
00304       _m[node->first] = boost::str( fmt ) ;
00305     }
00306     for ( Map::const_iterator item = _m.begin() ; _m.end() != item ; ++item ) 
00307     {
00308       boost::format fmt( "  %1% %|45t|%2% " ) ;
00309       fmt % no_prefix( item->first , m_prefix )  % item->second ;
00310       stream() << level  << boost::str( fmt ) << endreq ;
00311     }
00312   }
00313   return StatusCode::SUCCESS ;
00314 }
00315 // ============================================================================
00317 // ============================================================================
00318 StatusCode DataOnDemandSvc::finalize() 
00319 {
00320   stream() << MSG::INFO 
00321            <<  " #Incidents: Alg/Node/All:"
00322            << " " << m_statAlg << "/" << m_statNode << "/" << m_stat 
00323            << " Algorithms: " << m_total.outputUserTime () << endreq ;
00324   
00325   // dump it! 
00326   dump ( MSG::DEBUG ).ignore() ;
00327   //
00328   if ( m_incSvc )  
00329   {
00330     m_incSvc->removeListener(this, m_trapType);
00331     m_incSvc->release();
00332     m_incSvc = 0;
00333   }
00334   if ( 0 != m_algMgr  ) { m_algMgr   -> release () ; m_algMgr  = 0 ; }
00335   if ( 0 != m_dataSvc ) { m_dataSvc  -> release () ; m_dataSvc = 0 ; }
00336   if ( 0 != m_log     ) { delete m_log ; m_log = 0 ; }
00337   //
00338   return Service::finalize();
00339 }
00340 // ============================================================================
00342 // ============================================================================
00343 StatusCode DataOnDemandSvc::reinitialize() 
00344 {
00345   // reinitialize the Service Base class
00346   if ( 0 != m_incSvc )  
00347   {
00348     m_incSvc->removeListener(this, m_trapType);
00349     m_incSvc->release();
00350     m_incSvc = 0;
00351   }
00352   if ( 0 != m_algMgr  ) { m_algMgr   -> release() ; m_algMgr  = 0 ; }
00353   if ( 0 != m_dataSvc ) { m_dataSvc  -> release() ; m_dataSvc = 0 ; }
00354   //
00355   StatusCode sc = Service::reinitialize();
00356   if ( sc.isFailure() )  { return sc; }
00357   //
00358   sc = setup() ;
00359   if ( sc.isFailure() )  { return sc; }
00360   //
00361   return dump() ;
00362 }
00363 // ============================================================================
00365 // ============================================================================
00366 StatusCode DataOnDemandSvc::queryInterface
00367 ( const InterfaceID& riid, 
00368   void** ppvInterface ) 
00369 {
00370   if ( IID_IIncidentListener == riid )    
00371   {
00372     *ppvInterface = static_cast<IIncidentListener*>(this);
00373     addRef();
00374     return StatusCode::SUCCESS;
00375   }
00376   // Interface is not directly available: try out a base class
00377   return Service::queryInterface(riid, ppvInterface);
00378 }
00379 // ============================================================================
00381 // ============================================================================
00382 StatusCode DataOnDemandSvc::setup() 
00383 {
00384   m_algMgr = 0;
00385   StatusCode sc = 
00386     serviceLocator()->queryInterface(IID_IAlgManager, pp_cast<void>(&m_algMgr));
00387   if ( sc.isFailure () )  
00388   {
00389     stream() 
00390       << MSG::ERROR
00391       << "Failed to retrieve the IAlgManager interface." << endmsg;
00392     return sc;
00393   }
00394   sc = service("IncidentSvc", m_incSvc, true);
00395   if ( sc.isFailure () )  
00396   {
00397     stream() 
00398       << MSG::ERROR << "Failed to retrieve Incident service." << endmsg;
00399     return sc;
00400   }
00401   m_incSvc->addListener(this, m_trapType);
00402   sc = service(m_dataSvcName, m_dataSvc, true);
00403   if ( sc.isFailure () )  
00404   {
00405     stream() 
00406       << MSG::ERROR
00407       << "Failed to retrieve the data provider interface of "
00408       << m_dataSvcName << endmsg;
00409     return sc;
00410   }
00411   sc = setupNodeHandlers() ;
00412   if ( sc.isFailure() ) 
00413   {
00414     stream() << MSG::ERROR << "Failed to setup nodes " << endreq ;
00415     return sc ;
00416   }
00417   sc = setupAlgHandlers();
00418   if ( sc.isFailure() ) 
00419   {
00420     stream() << MSG::ERROR << "Failed to setup algorithms " << endreq ;
00421     return sc ;
00422   }
00423   //
00424   return update() ;
00425 }
00426 // ============================================================================
00428 // ============================================================================
00429 StatusCode DataOnDemandSvc::setupNodeHandlers()  
00430 {
00431   Setup::const_iterator j;
00432   std::string nam, typ, tag;
00433   StatusCode sc = StatusCode::SUCCESS;
00434   // Setup for node leafs, where simply a constructor is called...
00435   for ( j=m_nodeMapping.value().begin(); j != m_nodeMapping.value().end(); ++j) 
00436   {
00437     Tokenizer tok(true);
00438     tok.analyse(*j, " ", "", "", "=", "'", "'");
00439     for ( Tokenizer::Items::iterator i = tok.items().begin(); 
00440           i != tok.items().end(); i++ )   {
00441       const std::string& t = (*i).tag();
00442       const std::string& v = (*i).value();
00443       switch( ::toupper(t[0]) )    {
00444       case 'D':
00445         tag = v;
00446         break;
00447       case 'T':
00448         nam = v;
00449         break;
00450       }
00451     } 
00452     m_nodeMap[tag] = nam ; 
00453   }
00454   //
00455   m_updateRequired = true ;
00456   //
00457   return sc;
00458 }
00459 // ============================================================================
00461 // ============================================================================
00462 StatusCode DataOnDemandSvc::setupAlgHandlers()  
00463 {
00464   Setup::const_iterator j;
00465   std::string typ, tag;
00466   m_algs.clear();
00467   for(j=m_algMapping.value().begin(); j != m_algMapping.value().end(); ++j)  
00468   {
00469     Tokenizer tok(true);
00470     tok.analyse(*j, " ", "", "", "=", "'", "'");
00471     for(Tokenizer::Items::iterator i = tok.items().begin(); i != tok.items().end(); i++ )   {
00472       const std::string& t = (*i).tag();
00473       const std::string& v = (*i).value();
00474       switch( ::toupper(t[0]) )    {
00475       case 'D':
00476         tag = v;
00477         break;
00478       case 'T':
00479         typ = v;
00480         break;
00481       }
00482     }
00483     ListItem item(typ);
00484     m_algMap[tag] = item.type() + "/" + item.name() ;
00485   }
00486   m_updateRequired = true ;
00487   return StatusCode::SUCCESS;
00488 }
00489 // ============================================================================
00491 // ============================================================================
00492 StatusCode DataOnDemandSvc::configureHandler(Leaf& l)  
00493 {
00494   if ( 0 == m_algMgr  ) { return StatusCode::FAILURE ; }
00495   StatusCode sc = m_algMgr->getAlgorithm(l.name, l.algorithm);
00496   if ( sc.isFailure() ) 
00497   {
00498     sc = m_algMgr->createAlgorithm(l.type, l.name, l.algorithm, true );
00499     if ( sc.isFailure() ) 
00500     {
00501       stream()  
00502         << MSG::ERROR 
00503         << "Failed to create algorithm of type:"
00504         << l.name << "[" << l.type << "] " << endmsg; 
00505     }
00506   }
00507   return sc;
00508 }
00509 // ===========================================================================
00511 // ===========================================================================
00512 void DataOnDemandSvc::handle ( const Incident& incident )
00513 { 
00514   ++m_stat ;
00515   // proper incident type? 
00516   if ( incident.type() != m_trapType ) { return ; }             // RETURN
00517   const DataIncident* inc = dynamic_cast<const DataIncident*>(&incident);
00518   if ( 0 == inc                      ) { return ; }             // RETURN
00519   // update if needed! 
00520   if ( m_updateRequired ) { update() ; }
00521   const std::string& tag = inc->tag();
00522   stream()
00523     << MSG::DEBUG 
00524     << "Incident: [" << incident.type   () << "] " 
00525     << " = "         << incident.source ()
00526     << " Location:"  << tag  << endmsg;
00527   NodeMap::iterator icl = m_nodes.find ( tag ) ;
00528   if ( icl != m_nodes.end() )  
00529   {
00530     StatusCode sc = execHandler ( tag , icl->second ) ;
00531     if ( sc.isSuccess() ) { ++m_statNode ; } 
00532     return ;                                                        // RETURN 
00533   }
00534   AlgMap::iterator ialg = m_algs.find ( tag ) ;
00535   if ( ialg != m_algs.end() )  
00536   {
00537     StatusCode sc = execHandler ( tag , ialg->second ) ;
00538     if ( sc.isSuccess() ) { ++m_statAlg ; }
00539     return ;                                                        // RETURN 
00540   }
00541 }
00542 // ===========================================================================
00544 // ===========================================================================
00545 StatusCode 
00546 DataOnDemandSvc::execHandler(const std::string& tag, Node& n)  
00547 {
00548   if ( n.executing ) { return StatusCode::FAILURE ; }            // RETURN 
00549  
00550   // try to recover the handler 
00551   if ( !n.clazz  ) { n.clazz = ROOT::Reflex::Type::ByName(n.name) ; }
00552   if ( !n.clazz  ) 
00553   {
00554     stream() 
00555       << MSG::ERROR 
00556       << "Failed to get dictionary for class '"
00557       << n.name  
00558       << "' for location:" << tag << endmsg;
00559     return StatusCode::FAILURE ;                               // RETURN 
00560   }
00561   
00562   ROOT::Reflex::Object obj = n.clazz.Construct();
00563   DataObject* pO = (DataObject*)obj.Address();
00564   if ( !pO )
00565   {
00566     stream() 
00567       << MSG::ERROR 
00568       << "Failed to create an object of type:"
00569       << n.clazz.Name(ROOT::Reflex::SCOPED) << " for location:" << tag 
00570       << endmsg;  
00571     return StatusCode::FAILURE  ;                               // RETURN 
00572   }
00573   //
00574   Protection p(n.executing);
00575   StatusCode sc = m_dataSvc->registerObject(tag, pO);
00576   if ( sc.isFailure() ) 
00577   {
00578     stream() 
00579       << MSG::ERROR << "Failed to register an object of type:"
00580       << n.clazz.Name(ROOT::Reflex::SCOPED) << " at location:" << tag 
00581       << endmsg;
00582     return sc ;                                                  // RETURN 
00583   }
00584   //
00585   return StatusCode::SUCCESS ;
00586 }
00587 // ===========================================================================
00589 // ===========================================================================
00590 StatusCode 
00591 DataOnDemandSvc::execHandler(const std::string& tag, Leaf& l)  
00592 {
00593   //
00594   if ( l.executing ) { return StatusCode::FAILURE ; }             // RETURN  
00595   //
00596   if ( 0 == l.algorithm ) 
00597   {
00598     StatusCode sc = configureHandler ( l ) ;
00599     if ( sc.isFailure() ) 
00600     {
00601       stream()  
00602         << MSG::ERROR 
00603         << "Failed to configure handler for: "
00604         << l.name << "[" << l.type << "] " << tag << endmsg; 
00605       return sc ;                                                 // RETURN 
00606     }
00607   }
00608   //
00609   Timer timer ( m_total ) ;
00610   //
00611   Protection p(l.executing);
00612   StatusCode sc = l.algorithm->sysExecute();
00613   if ( sc.isFailure() )  
00614   {
00615     stream() << MSG::ERROR 
00616              << "Failed to execute the algorithm:"
00617              << l.algorithm->name() << " for location:" << tag << endmsg;
00618     return sc ;                                                       // RETURN 
00619   }
00620   //
00621   return StatusCode::SUCCESS ;
00622 }
00623 // ============================================================================
00624 // The END 
00625 // ============================================================================

Generated at Fri Jul 18 11:59:24 2008 for Gaudi Framework, version v20r2 by Doxygen version 1.5.1 written by Dimitri van Heesch, © 1997-2004