| # Gaudi Framework, version v23r1 |

Home |  | Generated: Wed Feb 29 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