![]() |
|
|
Generated: 18 Jul 2008 |
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 // ============================================================================