Gaudi Framework, version v23r4

Home   Generated: Mon Sep 17 2012

DataOnDemandSvc.cpp

Go to the documentation of this file.
00001 // ============================================================================
00002 // Include files
00003 // ============================================================================
00004 // STD & STL
00005 // ============================================================================
00006 #include <string>
00007 #include <set>
00008 #include <map>
00009 #include <math.h>
00010 // ============================================================================
00011 // GaudiKernel
00012 // ============================================================================
00013 #include "GaudiKernel/MsgStream.h"
00014 #include "GaudiKernel/Tokenizer.h"
00015 #include "GaudiKernel/DataObject.h"
00016 #include "GaudiKernel/IAlgorithm.h"
00017 #include "GaudiKernel/ISvcLocator.h"
00018 #include "GaudiKernel/IAlgManager.h"
00019 #include "GaudiKernel/IIncidentSvc.h"
00020 #include "GaudiKernel/DataIncident.h"
00021 #include "GaudiKernel/IDataProviderSvc.h"
00022 #include "GaudiKernel/IToolSvc.h"
00023 #include "GaudiKernel/TypeNameString.h"
00024 #include "GaudiKernel/ToStream.h"
00025 #include "GaudiKernel/Chrono.h"
00026 #include "GaudiKernel/LockedChrono.h"
00027 // ============================================================================
00028 // Local
00029 // ============================================================================
00030 #include "DataOnDemandSvc.h"
00031 // ============================================================================
00032 // Boost
00033 // ============================================================================
00034 #ifdef __ICC
00035 // disable icc remark #2259: non-pointer conversion from "X" to "Y" may lose significant bits
00036 //   TODO: To be removed, since it comes from Boost
00037 #pragma warning(disable:2259)
00038 #endif
00039 #include "boost/format.hpp"
00040 #include "boost/lexical_cast.hpp"
00041 #include "GaudiKernel/Property.h"
00042 // ============================================================================
00043 // Constructors and Destructor
00044 // ============================================================================
00045 DataOnDemandSvc::DataOnDemandSvc
00046 ( const std::string& name, ISvcLocator* svc )
00047   : base_class(name, svc)
00048   , m_incSvc   ( 0 )
00049   , m_algMgr   ( 0 )
00050   , m_dataSvc  ( 0 )
00051   //
00052   , m_trapType    ( "DataFault")
00053   , m_dataSvcName ( "EventDataSvc" )
00054   , m_partialPath ( true  )
00055   , m_dump        ( false )
00056   , m_init        ( false )
00057   , m_allowInitFailure(false)
00058   //
00059   , m_algMapping  ()
00060   , m_nodeMapping ()
00061   //
00062   , m_algMap   (   )
00063   , m_nodeMap  (   )
00064   //
00065   , m_updateRequired ( true )
00066   , m_prefix         ( "/Event/" )
00067   , m_log      ( 0 )
00068   , m_total    (   )
00069   , m_statAlg  ( 0 )
00070   , m_statNode ( 0 )
00071   , m_stat     ( 0 )
00072   //
00073   , m_timer_nodes  ()
00074   , m_timer_algs   ()
00075   , m_timer_all    ()
00076   , m_locked_nodes ( false )
00077   , m_locked_algs  ( false )
00078   , m_locked_all   ( false )
00079   //
00080 {
00081   // ==========================================================================
00082   declareProperty
00083     ( "IncidentName"       ,
00084       m_trapType           ,
00085       "The type of handled Incident" ) ;
00086   //
00087   declareProperty ( "DataSvc"            , m_dataSvcName ) ;
00088   //
00089   declareProperty ( "UsePreceedingPath"  , m_partialPath ) ;
00090   declareProperty
00091     ( "Dump"        ,
00092       m_dump        ,
00093       "Dump the configuration and stastics" )  ->
00094     declareUpdateHandler ( &DataOnDemandSvc::update_dump , this ) ;
00095   //
00096   declareProperty
00097     ( "PreInitialize" ,
00098       m_init          ,
00099       "Flag to (pre)initialize all algorithms" ) ;
00100   declareProperty
00101     ( "AllowPreInitializeFailure" ,
00102       m_allowInitFailure          ,
00103       "Allow (pre)initialization of algorithms to fail without stopping the application" ) ;
00104   //
00105   declareProperty ( "Algorithms"         , m_algMapping  )  ->
00106     declareUpdateHandler ( &DataOnDemandSvc::update_2 , this ) ;
00107   declareProperty ( "Nodes"              , m_nodeMapping ) ->
00108     declareUpdateHandler ( &DataOnDemandSvc::update_3 , this ) ;
00109   //
00110   declareProperty ( "AlgMap"  , m_algMap  ) ->
00111     declareUpdateHandler ( &DataOnDemandSvc::update_1 , this ) ;
00112   declareProperty ( "NodeMap" , m_nodeMap ) ->
00113     declareUpdateHandler ( &DataOnDemandSvc::update_1 , this ) ;
00114 
00115   declareProperty ( "Prefix"             , m_prefix      ) ;
00116 
00117   declareProperty("NodeMappingTools", m_nodeMapTools,
00118                   "List of tools of type IDODNodeMapper");
00119   declareProperty("AlgMappingTools", m_algMapTools,
00120                   "List of tools of type IDODAlgMapper");
00121   // ==========================================================================
00122 }
00123 // ============================================================================
00124 // Update handler
00125 // ============================================================================
00126 void DataOnDemandSvc::update_1 ( Property& p )
00127 {
00128   stream() << MSG::VERBOSE << " I am update handler for property " << p << endmsg ;
00129   // force update
00130   m_updateRequired = true ;
00131 }
00132 // ============================================================================
00133 // Update handler
00134 // ============================================================================
00135 void DataOnDemandSvc::update_3 ( Property& /* p */ )
00136 {
00137   stream() << MSG::WARNING
00138            << "The property 'Nodes'      is obsolete, switch to map-like 'NodeMap' "
00139            << " = { 'data' : 'type'      } "
00140            << endmsg ;
00141   // force update
00142   m_updateRequired = true ;
00143 }
00144 // ============================================================================
00145 // Update handler
00146 // ============================================================================
00147 void DataOnDemandSvc::update_2 ( Property& /* p */ )
00148 {
00149   stream() << MSG::WARNING
00150            << "The property 'Algorithms' is obsolete, switch to map-like 'AlgMap'  "
00151            << " = { 'data' : 'algorithm' } "
00152            << endmsg ;
00153   // force update
00154   m_updateRequired = true ;
00155 }
00156 // ============================================================================
00157 // Update handler
00158 // ============================================================================
00159 void DataOnDemandSvc::update_dump ( Property& /* p */ )
00160 {
00161   // no action if not yet initialized
00162   if ( FSMState() < Gaudi::StateMachine::INITIALIZED ) { return ; }
00163   // dump the configuration:
00164   if ( m_dump ) { dump ( MSG::ALWAYS ) ; }
00165 }
00166 // ============================================================================
00167 // anonymous namespace to hide few local functions
00168 // ============================================================================
00169 namespace
00170 {
00171   // ==========================================================================
00177   inline std::string no_prefix
00178   ( const std::string& value  ,
00179     const std::string& prefix )
00180   {
00181     return
00182       !prefix.empty() && 0 == value.find(prefix) ?
00183       std::string( value , prefix.size() ) : value ;
00184   }
00185   // ==========================================================================
00192   template <class MAP>
00193   inline size_t add_prefix ( MAP& _map , const std::string& prefix )
00194   {
00195     // empty  prefix
00196     if ( prefix.empty() ) { return 0 ; }                    // RETURN
00198     for ( typename MAP::iterator it = _map.begin() ; _map.end() != it ; ++it )
00199     {
00200       if ( 0 != it->first.find(prefix) )  // valid prefix?
00201       {
00202         std::string key   = prefix + it->first ;
00203         std::string value = it->second ;
00204         _map.erase ( it ) ;
00205         _map[ key ] = value  ;
00206         return 1 + add_prefix ( _map , prefix ) ;    // RETURN, recursion
00207       }
00208     }
00209     //
00210     return 0 ;
00211   }
00212   // ==========================================================================
00218   template <class SET>
00219   inline size_t get_dir ( const std::string& object , SET& _set )
00220   {
00221     std::string::size_type ifind = object.rfind('/') ;
00222     // stop recursion
00223     if ( std::string::npos == ifind ) { return 0 ; } // RETURN
00224     if ( 0 == ifind                 ) { return 0 ; }
00225     //
00226     const std::string top = std::string( object , 0 , ifind) ;
00227     _set.insert( top ) ;
00228     return 1 + get_dir ( top , _set ) ;   // RETURN, recursion
00229   }
00230   // ==========================================================================
00236   template <class MAP, class SET>
00237   inline size_t get_dirs ( const MAP& _map, SET& _set )
00238   {
00239     size_t size = _set.size() ;
00240     for ( typename MAP::const_iterator item = _map.begin() ;
00241           _map.end() != item ; ++item ) {  get_dir ( item->first , _set ) ; }
00242     return _set.size() - size ;
00243   }
00244   // ==========================================================================
00245 } // end of anonymous namespace
00246 
00247 void DataOnDemandSvc::i_setNodeHandler(const std::string &name, const std::string &type){
00248   ClassH cl = ROOT::Reflex::Type::ByName(type) ;
00249   if (!cl) {
00250     warning()
00251         << "Failed to access dictionary class for "
00252         << name << " of type:" << type << endmsg;
00253   }
00254   m_nodes[name] = Node(cl, false, type);
00255 }
00256 
00257 StatusCode DataOnDemandSvc::i_setAlgHandler(const std::string &name, const Gaudi::Utils::TypeNameString &alg){
00258   Leaf leaf(alg.type(), alg.name());
00259   if (m_init)
00260   {
00261     StatusCode sc = configureHandler(leaf);
00262     if (sc.isFailure()) {
00263       if (m_allowInitFailure) {
00264         // re-store the content of the leaf object to try again to initialize
00265         // the algorithm later (on demand)
00266         leaf = Leaf(alg.type(), alg.name());
00267       }
00268       else
00269         return sc;
00270     }
00271   }
00272   m_algs[name] = leaf;
00273   return StatusCode::SUCCESS;
00274 }
00275 
00276 // ============================================================================
00277 // update the content of Data-On-Demand actions
00278 // ============================================================================
00279 StatusCode DataOnDemandSvc::update ()
00280 {
00281   if ( !m_updateRequired ) { return StatusCode::SUCCESS  ; }
00282 
00284   StatusCode sc = setupNodeHandlers() ; // convert "Nodes"      new "NodeMap"
00285   if ( sc.isFailure() )
00286   {
00287     stream() << MSG::ERROR << "Failed to setup old \"Nodes\""      << endmsg ;
00288     return sc ;
00289   }
00291   sc = setupAlgHandlers()   ; // convert "Algorithms" into "AlgMap"
00292   if ( sc.isFailure() )
00293   {
00294     stream() << MSG::ERROR << "Failed to setup old \"Algorithms\"" << endmsg ;
00295     return sc ;
00296   }
00298   add_prefix ( m_algMap  , m_prefix ) ;
00300   add_prefix ( m_nodeMap , m_prefix ) ;
00302   typedef std::set<std::string> Set ;
00303   Set dirs ;
00304   if ( m_partialPath ){ get_dirs ( m_algMap  , dirs ) ; }
00305   if ( m_partialPath ){ get_dirs ( m_nodeMap , dirs ) ; }
00306   //
00307   Set::iterator _e = dirs.find("/Event") ;
00308   if ( dirs.end() != _e ) { dirs.erase( _e ) ; }
00309   // add all directories as nodes
00310   for ( Set::const_iterator dir = dirs.begin() ; dirs.end() != dir ; ++dir )
00311   {
00312     if ( m_algMap  .end () != m_algMap  .find ( *dir ) ) { continue ; }
00313     if ( m_nodeMap .end () != m_nodeMap .find ( *dir ) ) { continue ; }
00314     m_nodeMap [*dir] = "DataObject" ;
00315   }
00316   //
00317   m_algs  .clear  () ;
00318   m_nodes .clear  () ;
00319   //
00321   for ( Map::const_iterator ialg = m_algMap.begin() ;
00322         m_algMap.end() != ialg ; ++ialg )
00323   {
00324     if (i_setAlgHandler(ialg->first, ialg->second).isFailure())
00325       return StatusCode::FAILURE;
00326   }
00328   for ( Map::const_iterator inode = m_nodeMap.begin() ;
00329         m_nodeMap.end() != inode ; ++inode )
00330   {
00331     i_setNodeHandler(inode->first, inode->second);
00332   }
00334   m_updateRequired = false ;
00335   //
00336   return StatusCode::SUCCESS ;
00337 }
00338 // ============================================================================
00339 // destructor
00340 // ============================================================================
00341 DataOnDemandSvc::~DataOnDemandSvc()
00342 { if ( 0 != m_log      ) { delete m_log      ; m_log      = 0 ; } }
00343 //=============================================================================
00344 // Inherited Service overrides:
00345 //=============================================================================
00346 StatusCode DataOnDemandSvc::initialize()
00347 {
00348   // initialize the Service Base class
00349   StatusCode sc = Service::initialize();
00350   if ( sc.isFailure() )  { return sc; }
00351   sc = setup();
00352   if ( sc.isFailure() )  { return sc; }
00353   //
00354   if      ( m_dump )                      { dump ( MSG::INFO  ) ; }
00355   else if ( MSG::DEBUG >= outputLevel() ) { dump ( MSG::DEBUG ) ; }
00356   //
00357   if ( m_init ) { return update () ; }
00358   //
00359   return StatusCode::SUCCESS ;
00360 }
00361 // ============================================================================
00362 // finalization of the service
00363 // ============================================================================
00364 StatusCode DataOnDemandSvc::finalize()
00365 {
00366   //
00367   stream ()
00368     << MSG::INFO
00369     << "Handled \"" << m_trapType << "\" incidents: "
00370     << m_statAlg  << "/" << m_statNode << "/" << m_stat << "(Alg/Node/Total)."
00371     << endmsg ;
00372   if ( m_dump || MSG::DEBUG >= outputLevel() )
00373   {
00374     stream ()
00375       << MSG::INFO
00376       << m_total.outputUserTime
00377       ( "Algorithm timing: Mean(+-rms)/Min/Max:%3%(+-%4%)/%6%/%7%[ms] " , System::milliSec )
00378       << m_total.outputUserTime ( "Total:%2%[s]" , System::Sec ) << endmsg ;
00379     stream ()
00380       << MSG::INFO
00381       << m_timer_nodes.outputUserTime
00382       ( "Nodes     timing: Mean(+-rms)/Min/Max:%3%(+-%4%)/%6%/%7%[ms] " , System::milliSec )
00383       << m_timer_nodes.outputUserTime ( "Total:%2%[s]" , System::Sec ) << endmsg ;
00384     stream ()
00385       << MSG::INFO
00386       << m_timer_algs .outputUserTime
00387       ( "Algs      timing: Mean(+-rms)/Min/Max:%3%(+-%4%)/%6%/%7%[ms] " , System::milliSec )
00388       << m_timer_algs .outputUserTime ( "Total:%2%[s]" , System::Sec ) << endmsg ;
00389     stream ()
00390       << MSG::INFO
00391       << m_timer_all  .outputUserTime
00392       ( "All       timing: Mean(+-rms)/Min/Max:%3%(+-%4%)/%6%/%7%[ms] " , System::milliSec )
00393       << m_timer_all  .outputUserTime ( "Total:%2%[s]" , System::Sec ) << endmsg ;
00394   }
00395   // dump it!
00396   if      ( m_dump )                      { dump ( MSG::INFO  , false ) ; }
00397   else if ( MSG::DEBUG >= outputLevel() ) { dump ( MSG::DEBUG , false ) ; }
00398   //
00399   if ( m_incSvc )
00400   {
00401     m_incSvc->removeListener(this, m_trapType);
00402     m_incSvc.reset();
00403   }
00404   m_algMgr.reset();
00405   m_dataSvc.reset();
00406   if (m_toolSvc) { // we may not have retrieved the ToolSvc
00407     // Do not call releaseTool if the ToolSvc was already finalized.
00408     if (SmartIF<IStateful>(m_toolSvc)->FSMState() > Gaudi::StateMachine::CONFIGURED) {
00409       for(std::list<IDODNodeMapper*>::iterator i = m_nodeMappers.begin(); i != m_nodeMappers.end(); ++i)
00410         m_toolSvc->releaseTool(*i).ignore();
00411       for(std::list<IDODAlgMapper*>::iterator i = m_algMappers.begin(); i != m_algMappers.end(); ++i)
00412         m_toolSvc->releaseTool(*i).ignore();
00413     } else {
00414       warning() << "ToolSvc already finalized: cannot release tools. Check options." << endmsg;
00415     }
00416     m_nodeMappers.clear();
00417     m_algMappers.clear();
00418     m_toolSvc.reset();
00419   }
00420   return Service::finalize();
00421 }
00422 // ============================================================================
00424 // ============================================================================
00425 StatusCode DataOnDemandSvc::reinitialize()
00426 {
00427   // reinitialize the Service Base class
00428   if ( 0 != m_incSvc )
00429   {
00430     m_incSvc -> removeListener ( this , m_trapType );
00431     m_incSvc.reset();
00432   }
00433   m_algMgr.reset();
00434   m_dataSvc.reset();
00435   for(std::list<IDODNodeMapper*>::iterator i = m_nodeMappers.begin(); i != m_nodeMappers.end(); ++i)
00436       m_toolSvc->releaseTool(*i).ignore();
00437   m_nodeMappers.clear();
00438   for(std::list<IDODAlgMapper*>::iterator i = m_algMappers.begin(); i != m_algMappers.end(); ++i)
00439     m_toolSvc->releaseTool(*i).ignore();
00440   m_algMappers.clear();
00441   m_toolSvc.reset();
00442   if ( 0 != m_log     ) { delete m_log ; m_log = 0 ; }
00443   //
00444   StatusCode sc = Service::reinitialize();
00445   if ( sc.isFailure() )  { return sc; }
00446   //
00447   sc = setup() ;
00448   if ( sc.isFailure() )  { return sc; }
00449   //
00450   if ( m_dump ) { dump ( MSG::INFO ) ; }
00451   else if ( MSG::DEBUG >= outputLevel() ) { dump ( MSG::DEBUG  ) ; }
00452   //
00453   return StatusCode::SUCCESS ;
00454 }
00455 // ============================================================================
00456 // setup service
00457 // ============================================================================
00458 StatusCode DataOnDemandSvc::setup()
00459 {
00460   if ( !(m_algMgr = serviceLocator()) ) // assignment meant
00461   {
00462     error() << "Failed to retrieve the IAlgManager interface." << endmsg;
00463     return StatusCode::FAILURE;
00464   }
00465 
00466   if ( !(m_incSvc = serviceLocator()->service("IncidentSvc")) ) // assignment meant
00467   {
00468     error() << "Failed to retrieve Incident service." << endmsg;
00469     return StatusCode::FAILURE;
00470   }
00471   m_incSvc->addListener(this, m_trapType);
00472 
00473   if ( !(m_dataSvc = serviceLocator()->service(m_dataSvcName)) ) // assignment meant
00474   {
00475     error()
00476       << "Failed to retrieve the data provider interface of "
00477       << m_dataSvcName << endmsg;
00478     return StatusCode::FAILURE;
00479   }
00480 
00481   // No need to get the ToolSvc if we are not using tools
00482   if (!(m_nodeMapTools.empty() && m_algMapTools.empty())) {
00483     if ( !(m_toolSvc = serviceLocator()->service("ToolSvc")) ) // assignment meant
00484     {
00485       error() << "Failed to retrieve ToolSvc" << endmsg;
00486       return StatusCode::FAILURE;
00487     }
00488 
00489     // load the node mapping tools
00490     std::vector<std::string>::iterator i;
00491     IDODNodeMapper *nodetool = 0;
00492     for(i = m_nodeMapTools.begin(); i != m_nodeMapTools.end(); ++i) {
00493       const StatusCode sc = m_toolSvc->retrieveTool(*i, nodetool);
00494       if (sc.isFailure()) return sc;
00495       m_nodeMappers.push_back(nodetool);
00496     }
00497     IDODAlgMapper *algtool = 0;
00498     for(i = m_algMapTools.begin(); i != m_algMapTools.end(); ++i) {
00499       const StatusCode sc = m_toolSvc->retrieveTool(*i, algtool);
00500       if (sc.isFailure()) return sc;
00501       m_algMappers.push_back(algtool);
00502     }
00503   }
00504   return update();
00505 }
00506 // ============================================================================
00507 // setup node handlers
00508 // ============================================================================
00509 StatusCode DataOnDemandSvc::setupNodeHandlers()
00510 {
00511   Setup::const_iterator j;
00512   std::string nam, typ, tag;
00513   StatusCode sc = StatusCode::SUCCESS;
00514   // Setup for node leafs, where simply a constructor is called...
00515   for ( j=m_nodeMapping.begin(); j != m_nodeMapping.end(); ++j)
00516   {
00517     Tokenizer tok(true);
00518     tok.analyse(*j, " ", "", "", "=", "'", "'");
00519     for ( Tokenizer::Items::iterator i = tok.items().begin();
00520           i != tok.items().end(); i++ )   {
00521       const std::string& t = (*i).tag();
00522       const std::string& v = (*i).value();
00523       switch( ::toupper(t[0]) )    {
00524       case 'D':
00525         tag = v;
00526         break;
00527       case 'T':
00528         nam = v;
00529         break;
00530       }
00531     }
00532     if ( m_algMap  .end () != m_algMap  .find ( tag ) ||
00533          m_nodeMap .end () != m_nodeMap .find ( tag ) )
00534     {
00535       stream()
00536         << MSG::WARNING
00537         << "The obsolete property 'Nodes' redefines the action for '"
00538         + tag + "' to be '" +nam+"'"
00539         << endmsg ;
00540     }
00541     m_nodeMap[tag] = nam ;
00542   }
00543   //
00544   m_updateRequired = true ;
00545   //
00546   return sc;
00547 }
00548 // ============================================================================
00549 // setup algorithm  handlers
00550 // ============================================================================
00551 StatusCode DataOnDemandSvc::setupAlgHandlers()
00552 {
00553   Setup::const_iterator j;
00554   std::string typ, tag;
00555 
00556   for(j=m_algMapping.begin(); j != m_algMapping.end(); ++j)
00557   {
00558     Tokenizer tok(true);
00559     tok.analyse(*j, " ", "", "", "=", "'", "'");
00560     for(Tokenizer::Items::iterator i = tok.items().begin(); i != tok.items().end(); i++ )   {
00561       const std::string& t = (*i).tag();
00562       const std::string& v = (*i).value();
00563       switch( ::toupper(t[0]) )    {
00564       case 'D':
00565         tag = v;
00566         break;
00567       case 'T':
00568         typ = v;
00569         break;
00570       }
00571     }
00572     Gaudi::Utils::TypeNameString item(typ);
00573     if ( m_algMap  .end () != m_algMap  .find ( tag ) ||
00574          m_nodeMap .end () != m_nodeMap .find ( tag ) )
00575     {
00576       stream()
00577         << MSG::WARNING
00578         << "The obsolete property 'Algorithms' redefines the action for '"
00579         + tag + "' to be '" +item.type() +"/"+item.name()+"'"
00580         << endmsg ;
00581     }
00582     m_algMap[tag] = item.type() + "/" + item.name() ;
00583   }
00584   m_updateRequired = true ;
00585   return StatusCode::SUCCESS;
00586 }
00587 // ============================================================================
00589 // ============================================================================
00590 StatusCode DataOnDemandSvc::configureHandler(Leaf& l)
00591 {
00592   if ( 0 != l.algorithm ) { return StatusCode::SUCCESS ; }
00593   if ( 0 == m_algMgr  ) { return StatusCode::FAILURE ; }
00594   l.algorithm = m_algMgr->algorithm(l.name, false);
00595   if ( 0 != l.algorithm ) { return StatusCode::SUCCESS ; }
00596   // create it!
00597   StatusCode sc = m_algMgr->createAlgorithm ( l.type , l.name , l.algorithm , true ) ;
00598   if ( sc.isFailure() )
00599   {
00600     stream()
00601       << MSG::ERROR
00602       << "Failed to create algorithm "
00603       << l.type << "('" << l.name<< "')" << endmsg;
00604     l.algorithm = 0 ;
00605     return sc ;                                                    // RETURN
00606   }
00607   if ( l.algorithm->isInitialized() ) { return StatusCode:: SUCCESS ;}
00608   // initialize it!
00609   sc = l.algorithm -> sysInitialize () ;
00610   if ( sc.isFailure() )
00611   {
00612     stream()
00613       << MSG::ERROR
00614       << "Failed to initialize algorithm "
00615       << l.type << "('" << l.name<< "')" << endmsg;
00616     l.algorithm = 0 ;
00617     return sc ;                                                    // RETURN
00618   }
00619   if ( Gaudi::StateMachine::RUNNING == l.algorithm->FSMState() )
00620   { return StatusCode::SUCCESS ; }
00621   // run it!
00622   sc = l.algorithm->sysStart() ;
00623   if ( sc.isFailure() )
00624   {
00625     stream()
00626       << MSG::ERROR
00627       << "Failed to 'run'      algorithm "
00628       << l.type << "('" << l.name<< "')" << endmsg;
00629     l.algorithm = 0 ;
00630     return sc ;                                                    // RETURN
00631   }
00632   return StatusCode::SUCCESS  ;
00633 }
00634 
00635 // local algorithms
00636 namespace {
00639   struct ToolGetter {
00641     std::string path;
00643     ToolGetter(const std::string &_path): path(_path) {}
00645     inline std::string operator() (IDODNodeMapper *t) const {
00646       return t->nodeTypeForPath(path);
00647     }
00649     inline Gaudi::Utils::TypeNameString operator() (IDODAlgMapper *t) const {
00650       return t->algorithmForPath(path);
00651     }
00652   };
00653 
00656   inline bool isGood(const std::string& r) {return !r.empty();}
00657   inline bool isGood(const Gaudi::Utils::TypeNameString& r) {return !r.name().empty();}
00659 
00662   class Finder {
00663     const ToolGetter getter;
00664     const std::list<IDODNodeMapper*> &nodes;
00665     const std::list<IDODAlgMapper*> &algs;
00667     template <class R, class T>
00668     R find(const std::list<T*> &l) const {
00669       typename std::list<T*>::const_iterator i;
00670       for(i = l.begin(); i != l.end(); ++i) {
00671         R result = getter(*i);
00672         if (isGood(result)) return result;
00673       }
00674       return R("");
00675     }
00676   public:
00678     Finder(const std::string &_path,
00679            const std::list<IDODNodeMapper*> &_nodes,
00680            const std::list<IDODAlgMapper*> &_algs): getter(_path), nodes(_nodes), algs(_algs) {
00681     }
00683     inline std::string node() const {
00684       return find<std::string>(nodes);
00685     }
00687     inline Gaudi::Utils::TypeNameString alg() const {
00688       return find<Gaudi::Utils::TypeNameString>(algs);
00689     }
00690 
00691   };
00692 
00693 }
00694 
00695 // ===========================================================================
00696 // IIncidentListener interfaces overrides: incident handling
00697 // ===========================================================================
00698 void DataOnDemandSvc::handle ( const Incident& incident )
00699 {
00700 
00701   Gaudi::Utils::LockedChrono timer ( m_timer_all , m_locked_all ) ;
00702 
00703   ++m_stat ;
00704   // proper incident type?
00705   if ( incident.type() != m_trapType ) { return ; }             // RETURN
00706   const DataIncident* inc = dynamic_cast<const DataIncident*>(&incident);
00707   if ( 0 == inc                      ) { return ; }             // RETURN
00708   // update if needed!
00709   if ( m_updateRequired ) { update() ; }
00710 
00711   if ( MSG::VERBOSE >= outputLevel() )
00712   {
00713     verbose()
00714       << "Incident: [" << incident.type   () << "] "
00715       << " = "         << incident.source ()
00716       << " Location:"  << inc->tag()         << endmsg;
00717   }
00718   // ==========================================================================
00719   // const std::string& tag = inc->tag();
00720   Gaudi::StringKey tag ( inc->tag() ) ;
00721   // ==========================================================================
00722   NodeMap::iterator icl = m_nodes.find ( tag ) ;
00723   if ( icl != m_nodes.end() )
00724   {
00725     StatusCode sc = execHandler ( tag , icl->second ) ;
00726     if ( sc.isSuccess() ) { ++m_statNode ; }
00727     return ;                                                        // RETURN
00728   }
00729   // ==========================================================================
00730   AlgMap::iterator ialg = m_algs.find ( tag ) ;
00731   if ( ialg != m_algs.end() )
00732   {
00733     StatusCode sc = execHandler ( tag , ialg->second ) ;
00734     if ( sc.isSuccess() ) { ++m_statAlg ; }
00735     return ;                                                        // RETURN
00736   }
00737   // ==========================================================================
00738   // Fall back on the tools
00739   if (m_toolSvc) {
00740     if (MSG::VERBOSE >= outputLevel())
00741       verbose() << "Try to find mapping with mapping tools" << endmsg;
00742     Finder finder(no_prefix(inc->tag(), m_prefix), m_nodeMappers, m_algMappers);
00743     //  - try the node mappers
00744     std::string node = finder.node();
00745     if (isGood(node)) {
00746       // if one is found update the internal node mapping and try again.
00747       if (MSG::VERBOSE >= outputLevel())
00748         verbose() << "Found Node handler: " << node << endmsg;
00749       i_setNodeHandler(inc->tag(), node);
00750       handle(incident);
00751       --m_stat; // avoid double counting because of recursion
00752       return;
00753     }
00754     //  - try alg mappings
00755     Gaudi::Utils::TypeNameString alg = finder.alg();
00756     if (isGood(alg)) {
00757       // we got an algorithm, update alg map and try to handle again
00758       if (MSG::VERBOSE >= outputLevel())
00759         verbose() << "Found Algorithm handler: " << alg << endmsg;
00760       i_setAlgHandler(inc->tag(), alg).ignore();
00761       handle(incident);
00762       --m_stat; // avoid double counting because of recursion
00763       return;
00764     }
00765   }
00766 }
00767 // ===========================================================================
00768 // execute the handler
00769 // ===========================================================================
00770 StatusCode
00771 DataOnDemandSvc::execHandler ( const std::string& tag, Node& n)
00772 {
00773 
00774   Gaudi::Utils::LockedChrono timer ( m_timer_nodes ,  m_locked_nodes ) ;
00775 
00776   if ( n.executing ) { return StatusCode::FAILURE ; }            // RETURN
00777 
00778   Protection p(n.executing);
00779 
00780   DataObject* object= 0 ;
00781 
00782   if ( n.dataObject )  { object = new DataObject() ; }
00783   else
00784   {
00785     // try to recover the handler
00786     if ( !n.clazz  ) { n.clazz = ROOT::Reflex::Type::ByName(n.name) ; }
00787     if ( !n.clazz  )
00788     {
00789       stream()
00790         << MSG::ERROR
00791         << "Failed to get dictionary for class '"
00792         << n.name
00793         << "' for location:" << tag << endmsg;
00794       return StatusCode::FAILURE ;                               // RETURN
00795     }
00796     //
00797     ROOT::Reflex::Object obj = n.clazz.Construct();
00798 
00799     object = (DataObject*) obj.Address();
00800 
00801     if ( !object )
00802     {
00803       stream()
00804         << MSG::ERROR
00805         << "Failed to create an object of type:"
00806         << n.clazz.Name(ROOT::Reflex::SCOPED) << " for location:" << tag
00807         << endmsg;
00808       return StatusCode::FAILURE  ;                               // RETURN
00809     }
00810   }
00811   //
00812   StatusCode sc = m_dataSvc->registerObject(tag, object );
00813   if ( sc.isFailure() )
00814   {
00815     stream()
00816       << MSG::ERROR << "Failed to register an object of type:"
00817       << n.name << " at location:" << tag
00818       << endmsg;
00819     return sc ;                                                  // RETURN
00820   }
00821   ++n.num ;
00822   //
00823   return StatusCode::SUCCESS ;
00824 }
00825 // ===========================================================================
00826 // execute the handler
00827 // ===========================================================================
00828 StatusCode
00829 DataOnDemandSvc::execHandler(const std::string& tag, Leaf& l)
00830 {
00831   Gaudi::Utils::LockedChrono timer ( m_timer_algs ,  m_locked_algs ) ;
00832   //
00833   if ( l.executing ) { return StatusCode::FAILURE ; }             // RETURN
00834   //
00835   if ( 0 == l.algorithm )
00836   {
00837     StatusCode sc = configureHandler ( l ) ;
00838     if ( sc.isFailure() )
00839     {
00840       stream()
00841         << MSG::ERROR
00842         << "Failed to configure handler for: "
00843         << l.name << "[" << l.type << "] " << tag << endmsg;
00844       return sc ;                                                 // RETURN
00845     }
00846   }
00847   //
00848   Chrono atimer ( m_total ) ;
00849   //
00850   Protection p(l.executing);
00851   StatusCode sc = l.algorithm->sysExecute();
00852   if ( sc.isFailure() )
00853   {
00854     stream() << MSG::ERROR
00855              << "Failed to execute the algorithm:"
00856              << l.algorithm->name() << " for location:" << tag << endmsg;
00857     return sc ;                                                       // RETURN
00858   }
00859   ++l.num ;
00860   //
00861   return StatusCode::SUCCESS ;
00862 }
00863 // ============================================================================
00864 /* dump the content of DataOnDemand service
00865  *  @param level the printout level
00866  *  @param mode  the printout mode
00867  */
00868 // ============================================================================
00869 void DataOnDemandSvc::dump
00870 ( const MSG::Level level ,
00871   const bool       mode  )  const
00872 {
00873   if ( m_algs.empty()  &&  m_nodes.empty() ) { return ; }
00874 
00875   typedef std::pair<std::string,std::string> Pair ;
00876   typedef std::map<std::string,Pair>         PMap ;
00877 
00878   PMap _m ;
00879   for ( AlgMap::const_iterator alg = m_algs.begin() ;
00880         m_algs.end() != alg ; ++alg )
00881   {
00882     PMap::const_iterator check = _m.find(alg->first) ;
00883     if ( _m.end() != check )
00884     {
00885       stream()
00886         << MSG::WARNING
00887         << " The data item is activated for '"
00888         << check->first << "' as '" << check->second.first << "'" << endmsg ;
00889     }
00890     const Leaf& l = alg->second ;
00891     std::string nam = ( l.name == l.type ? l.type  : (l.type+"/"+l.name) ) ;
00892     //
00893     if ( !mode && 0 == l.num ) { continue ; }
00894     //
00895     std::string val ;
00896     if ( mode ) { val = ( 0 == l.algorithm ) ? "F" : "T" ; }
00897     else { val = boost::lexical_cast<std::string>( l.num ) ; }
00898     //
00899     _m[ no_prefix ( alg->first , m_prefix ) ] = std::make_pair ( nam , val ) ;
00900   }
00901   // nodes:
00902   for ( NodeMap::const_iterator node = m_nodes.begin() ;
00903         m_nodes.end() != node ; ++node )
00904   {
00905     PMap::const_iterator check = _m.find(node->first) ;
00906     if ( _m.end() != check )
00907     {
00908       stream()
00909         << MSG::WARNING
00910         << " The data item is already activated for '"
00911         << check->first << "' as '" << check->second.first << "'" << endmsg ;
00912     }
00913     const Node& n = node->second ;
00914     std::string nam = "'" + n.name + "'"  ;
00915     //
00916     std::string val ;
00917 
00918     if ( !mode && 0 == n.num ) { continue ; }
00919 
00920     if ( mode ) { val = ( 0 == n.clazz ) ? "F" : "T" ; }
00921     else { val = boost::lexical_cast<std::string>( n.num ) ; }
00922     //
00923     _m[ no_prefix ( node->first , m_prefix ) ] = std::make_pair ( nam , val ) ;
00924   }
00925   //
00926   if ( _m.empty() ) { return ; }
00927 
00928   // find the correct formats
00929   size_t n1 = 0 ;
00930   size_t n2 = 0 ;
00931   size_t n3 = 0 ;
00932   for  ( PMap::const_iterator it = _m.begin() ; _m.end() != it ; ++it )
00933   {
00934     n1 = std::max ( n1 , it->first.size()         ) ;
00935     n2 = std::max ( n2 , it->second.first.size()  ) ;
00936     n3 = std::max ( n3 , it->second.second.size() ) ;
00937   }
00938   if ( 10 > n1 ) { n1 = 10 ; }
00939   if ( 10 > n2 ) { n2 = 10 ; }
00940   if ( 60 < n1 ) { n1 = 60 ; }
00941   if ( 60 < n2 ) { n2 = 60 ; }
00942   //
00943 
00944   const std::string _f = " | %%1$-%1%.%1%s | %%2$-%2%.%2%s | %%3$%3%.%3%s |" ;
00945   boost::format _ff ( _f ) ;
00946   _ff % n1 % n2 % n3 ;
00947 
00948   const std::string _format  = _ff.str() ;
00949 
00950   MsgStream& msg = stream() << level ;
00951 
00952   if ( mode ) { msg << "Data-On-Demand Actions enabled for:"       ; }
00953   else        { msg << "Data-On-Demand Actions has been used for:" ; }
00954 
00955   boost::format fmt1( _format)  ;
00956   fmt1 % "Address" % "Creator" % ( mode ? "S" : "#" ) ;
00957   //
00958   const std::string header = fmt1.str() ;
00959   std::string line = std::string( header.size() , '-' ) ;
00960   line[0] = ' ' ;
00961 
00962   msg << std::endl << line
00963       << std::endl << header
00964       << std::endl << line ;
00965 
00966   // make the actual printout:
00967   for ( PMap::const_iterator item = _m.begin() ;
00968         _m.end() != item ; ++item )
00969   {
00970     boost::format fmt( _format)  ;
00971     msg << std::endl <<
00972       ( fmt % item->first % item->second.first % item->second.second ) ;
00973   }
00974 
00975   msg << std::endl << line << endmsg ;
00976 
00977 }
00978 // ============================================================================
00982 DECLARE_SERVICE_FACTORY(DataOnDemandSvc)
00983 // ============================================================================
00984 
00985 // ============================================================================
00986 // The END
00987 // ============================================================================
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated at Mon Sep 17 2012 13:49:28 for Gaudi Framework, version v23r4 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004