00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <string>
00010 #include <set>
00011 #include <map>
00012 #include <math.h>
00013
00014
00015
00016 #include "GaudiKernel/MsgStream.h"
00017 #include "GaudiKernel/Tokenizer.h"
00018 #include "GaudiKernel/DataObject.h"
00019 #include "GaudiKernel/IAlgorithm.h"
00020 #include "GaudiKernel/ISvcLocator.h"
00021 #include "GaudiKernel/IAlgManager.h"
00022 #include "GaudiKernel/IIncidentSvc.h"
00023 #include "GaudiKernel/DataIncident.h"
00024 #include "GaudiKernel/IDataProviderSvc.h"
00025 #include "GaudiKernel/TypeNameString.h"
00026 #include "GaudiKernel/ToStream.h"
00027 #include "DataOnDemandSvc.h"
00028
00029
00030
00031 #include "boost/format.hpp"
00032 #include "boost/lexical_cast.hpp"
00033
00034
00035
00036
00037 DataOnDemandSvc::DataOnDemandSvc
00038 ( const std::string& name, ISvcLocator* svc )
00039 : base_class(name, svc)
00040 , m_incSvc ( 0 )
00041 , m_algMgr ( 0 )
00042 , m_dataSvc ( 0 )
00043
00044 , m_trapType ( "DataFault")
00045 , m_dataSvcName ( "EventDataSvc" )
00046 , m_partialPath ( true )
00047 , m_dump ( false )
00048
00049 , m_algMapping ()
00050 , m_nodeMapping ()
00051
00052 , m_algMap ( )
00053 , m_nodeMap ( )
00054
00055 , m_updateRequired ( true )
00056 , m_prefix ( "/Event/" )
00057 , m_log ( 0 )
00058 , m_total ( )
00059 , m_statAlg ( 0 )
00060 , m_statNode ( 0 )
00061 , m_stat ( 0 )
00062 {
00063
00064 declareProperty ( "IncidentName" , m_trapType ) ;
00065 declareProperty ( "DataSvc" , m_dataSvcName ) ;
00066 declareProperty ( "UsePreceedingPath" , m_partialPath ) ;
00067 declareProperty ( "Dump" , m_dump ) ;
00068
00069 declareProperty ( "Algorithms" , m_algMapping ) ->
00070 declareUpdateHandler ( &DataOnDemandSvc::update_2 , this ) ;
00071 declareProperty ( "Nodes" , m_nodeMapping ) ->
00072 declareUpdateHandler ( &DataOnDemandSvc::update_3 , this ) ;
00073
00074 declareProperty ( "AlgMap" , m_algMap ) ->
00075 declareUpdateHandler ( &DataOnDemandSvc::update_1 , this ) ;
00076 declareProperty ( "NodeMap" , m_nodeMap ) ->
00077 declareUpdateHandler ( &DataOnDemandSvc::update_1 , this ) ;
00078
00079 declareProperty ( "Prefix" , m_prefix ) ;
00080
00081 }
00082
00083
00084
00085 void DataOnDemandSvc::update_1 ( Property& p )
00086 {
00087 stream() << MSG::VERBOSE << " I am update handler for property " << p << endmsg ;
00088
00089 m_updateRequired = true ;
00090 }
00091
00092
00093
00094 void DataOnDemandSvc::update_3 ( Property& )
00095 {
00096 stream() << MSG::WARNING
00097 << "The property 'Nodes' is obsolete, switch to map-like 'NodeMap' "
00098 << " = { 'data' : 'type' } "
00099 << endmsg ;
00100
00101 m_updateRequired = true ;
00102 }
00103
00104
00105
00106 void DataOnDemandSvc::update_2 ( Property& )
00107 {
00108 stream() << MSG::WARNING
00109 << "The property 'Algorithms' is obsolete, switch to map-like 'AlgMap' "
00110 << " = { 'data' : 'algorithm' } "
00111 << endmsg ;
00112
00113 m_updateRequired = true ;
00114 }
00115
00116
00117
00118 namespace
00119 {
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 }
00134
00141 template <class MAP>
00142 inline size_t add_prefix ( MAP& _map , const std::string& prefix )
00143 {
00144
00145 if ( prefix.empty() ) { return 0 ; }
00147 for ( typename MAP::iterator it = _map.begin() ; _map.end() != it ; ++it )
00148 {
00149 if ( 0 != it->first.find(prefix) )
00150 {
00151 std::string key = prefix + it->first ;
00152 std::string value = it->second ;
00153 _map.erase ( it ) ;
00154 _map[ key ] = value ;
00155 return 1 + add_prefix ( _map , prefix ) ;
00156 }
00157 }
00158
00159 return 0 ;
00160 }
00161
00167 template <class SET>
00168 inline size_t get_dir ( const std::string& object , SET& _set )
00169 {
00170 std::string::size_type ifind = object.rfind('/') ;
00171
00172 if ( std::string::npos == ifind ) { return 0 ; }
00173 if ( 0 == ifind ) { return 0 ; }
00174
00175 const std::string top = std::string( object , 0 , ifind) ;
00176 _set.insert( top ) ;
00177 return 1 + get_dir ( top , _set ) ;
00178 }
00179
00185 template <class MAP, class SET>
00186 inline size_t get_dirs ( const MAP& _map, SET& _set )
00187 {
00188 size_t size = _set.size() ;
00189 for ( typename MAP::const_iterator item = _map.begin() ;
00190 _map.end() != item ; ++item ) { get_dir ( item->first , _set ) ; }
00191 return _set.size() - size ;
00192 }
00193
00194 }
00195
00196
00197
00198 StatusCode DataOnDemandSvc::update ()
00199 {
00200 StatusCode sc = StatusCode::SUCCESS ;
00202 sc = setupNodeHandlers() ;
00203 if ( sc.isFailure() )
00204 {
00205 stream() << MSG::ERROR << "Failed to setup old \"Nodes\"" << endmsg ;
00206 return sc ;
00207 }
00209 sc = setupAlgHandlers() ;
00210 if ( sc.isFailure() )
00211 {
00212 stream() << MSG::ERROR << "Failed to setup old \"Algorithms\"" << endmsg ;
00213 return sc ;
00214 }
00216 add_prefix ( m_algMap , m_prefix ) ;
00218 add_prefix ( m_nodeMap , m_prefix ) ;
00220 typedef std::set<std::string> Set ;
00221 Set dirs ;
00222 if ( m_partialPath ){ get_dirs ( m_algMap , dirs ) ; }
00223 if ( m_partialPath ){ get_dirs ( m_nodeMap , dirs ) ; }
00224
00225 Set::iterator _e = dirs.find("/Event") ;
00226 if ( dirs.end() != _e ) { dirs.erase( _e ) ; }
00227
00228 for ( Set::const_iterator dir = dirs.begin() ; dirs.end() != dir ; ++dir )
00229 {
00230 if ( m_algMap .end () != m_algMap .find ( *dir ) ) { continue ; }
00231 if ( m_nodeMap .end () != m_nodeMap .find ( *dir ) ) { continue ; }
00232 m_nodeMap [*dir] = "DataObject" ;
00233 }
00234
00235 m_algs .clear () ;
00236 m_nodes .clear () ;
00237
00239 for ( Map::const_iterator ialg = m_algMap.begin() ;
00240 m_algMap.end() != ialg ; ++ialg )
00241 {
00242 Gaudi::Utils::TypeNameString alg ( ialg->second ) ;
00243 m_algs[ialg->first] = Leaf( alg.type() , alg.name() ) ;
00244 }
00246 for ( Map::const_iterator inode = m_nodeMap.begin() ;
00247 m_nodeMap.end() != inode ; ++inode )
00248 {
00249 ClassH cl = ROOT::Reflex::Type::ByName( inode->second ) ;
00250 if ( !cl )
00251 {
00252 stream() << MSG::WARNING
00253 << "Failed to access dictionary class for "
00254 << inode->first << " of type:" << inode->second << endmsg;
00255 }
00256 m_nodes[inode->first] = Node ( cl , false , inode->second ) ;
00257 }
00259 m_updateRequired = false ;
00260
00261 return StatusCode::SUCCESS ;
00262 }
00263
00264
00265
00266 DataOnDemandSvc::~DataOnDemandSvc()
00267 { if ( 0 != m_log ) { delete m_log ; m_log = 0 ; } }
00268
00269
00270
00271 StatusCode DataOnDemandSvc::initialize()
00272 {
00273
00274 StatusCode sc = Service::initialize();
00275 if ( sc.isFailure() ) { return sc; }
00276 sc = setup();
00277 if ( sc.isFailure() ) { return sc; }
00278
00279 if ( m_dump ) { dump ( MSG::INFO ) ; }
00280 else if ( MSG::DEBUG >= outputLevel() ) { dump ( MSG::DEBUG ) ; }
00281
00282 return StatusCode::SUCCESS ;
00283 }
00284
00285
00286
00287
00288
00289
00290 void DataOnDemandSvc::dump
00291 ( const MSG::Level level ,
00292 const bool mode ) const
00293 {
00294 if ( m_algs.empty() && m_nodes.empty() ) { return ; }
00295
00296 typedef std::pair<std::string,std::string> Pair ;
00297 typedef std::map<std::string,Pair> PMap ;
00298
00299 PMap _m ;
00300 for ( AlgMap::const_iterator alg = m_algs.begin() ;
00301 m_algs.end() != alg ; ++alg )
00302 {
00303 PMap::const_iterator check = _m.find(alg->first) ;
00304 if ( _m.end() != check )
00305 {
00306 stream()
00307 << MSG::WARNING
00308 << " The data item is activated for '"
00309 << check->first << "' as '" << check->second.first << "'" << endmsg ;
00310 }
00311 const Leaf& l = alg->second ;
00312 std::string nam = ( l.name == l.type ? l.type : (l.type+"/"+l.name) ) ;
00313
00314 if ( !mode && 0 == l.num ) { continue ; }
00315
00316 std::string val ;
00317 if ( mode ) { val = ( 0 == l.algorithm ) ? "F" : "T" ; }
00318 else { val = boost::lexical_cast<std::string>( l.num ) ; }
00319
00320 _m[ no_prefix ( alg->first , m_prefix ) ] = std::make_pair ( nam , val ) ;
00321 }
00322
00323 for ( NodeMap::const_iterator node = m_nodes.begin() ;
00324 m_nodes.end() != node ; ++node )
00325 {
00326 PMap::const_iterator check = _m.find(node->first) ;
00327 if ( _m.end() != check )
00328 {
00329 stream()
00330 << MSG::WARNING
00331 << " The data item is already activated for '"
00332 << check->first << "' as '" << check->second.first << "'" << endmsg ;
00333 }
00334 const Node& n = node->second ;
00335 std::string nam = "'" + n.name + "'" ;
00336
00337 std::string val ;
00338
00339 if ( !mode && 0 == n.num ) { continue ; }
00340
00341 if ( mode ) { val = ( 0 == n.clazz ) ? "F" : "T" ; }
00342 else { val = boost::lexical_cast<std::string>( n.num ) ; }
00343
00344 _m[ no_prefix ( node->first , m_prefix ) ] = std::make_pair ( nam , val ) ;
00345 }
00346
00347 if ( _m.empty() ) { return ; }
00348
00349
00350 size_t n1 = 0 ;
00351 size_t n2 = 0 ;
00352 size_t n3 = 0 ;
00353 for ( PMap::const_iterator it = _m.begin() ; _m.end() != it ; ++it )
00354 {
00355 n1 = std::max ( n1 , it->first.size() ) ;
00356 n2 = std::max ( n2 , it->second.first.size() ) ;
00357 n3 = std::max ( n3 , it->second.second.size() ) ;
00358 }
00359 if ( 10 > n1 ) { n1 = 10 ; }
00360 if ( 10 > n2 ) { n2 = 10 ; }
00361 if ( 60 < n1 ) { n1 = 60 ; }
00362 if ( 60 < n2 ) { n2 = 60 ; }
00363
00364
00365 const std::string _f = " | %%1$-%1%.%1%s | %%2$-%2%.%2%s | %%3$%3%.%3%s |" ;
00366 boost::format _ff ( _f ) ;
00367 _ff % n1 % n2 % n3 ;
00368
00369 const std::string _format = _ff.str() ;
00370
00371 MsgStream& msg = stream() << level ;
00372
00373 if ( mode ) { msg << "Data-On-Demand Actions enabled for:" ; }
00374 else { msg << "Data-On-Demand Actions has been used for:" ; }
00375
00376 boost::format fmt1( _format) ;
00377 fmt1 % "Address" % "Creator" % ( mode ? "S" : "#" ) ;
00378
00379 const std::string header = fmt1.str() ;
00380 std::string line = std::string( header.size() , '-' ) ;
00381 line[0] = ' ' ;
00382
00383 msg << std::endl << line
00384 << std::endl << header
00385 << std::endl << line ;
00386
00387
00388 for ( PMap::const_iterator item = _m.begin() ;
00389 _m.end() != item ; ++item )
00390 {
00391 boost::format fmt( _format) ;
00392 msg << std::endl <<
00393 ( fmt % item->first % item->second.first % item->second.second ) ;
00394 }
00395
00396 msg << std::endl << line << endmsg ;
00397
00398 }
00399
00400
00401
00402 StatusCode DataOnDemandSvc::finalize()
00403 {
00404
00405 stream ()
00406 << MSG::INFO
00407 << "Handled \"" << m_trapType << "\" incidents: "
00408 << m_statAlg << "/" << m_statNode << "/" << m_stat << "(Alg/Node/Total)."
00409 << endmsg ;
00410 if ( m_dump || MSG::DEBUG >= outputLevel() )
00411 {
00412 stream ()
00413 << MSG::INFO
00414 << m_total.outputUserTime
00415 ( "Algorithm timing: Mean(+-rms)/Min/Max:%3%(+-%4%)/%6%/%7%[ms] " , System::milliSec )
00416 << m_total.outputUserTime ( "Total:%2%[s]" , System::Sec ) << endmsg ;
00417 }
00418
00419 if ( m_dump ) { dump ( MSG::INFO , false ) ; }
00420 else if ( MSG::DEBUG >= outputLevel() ) { dump ( MSG::DEBUG , false ) ; }
00421
00422 if ( m_incSvc )
00423 {
00424 m_incSvc->removeListener(this, m_trapType);
00425 m_incSvc->release();
00426 m_incSvc = 0;
00427 }
00428 if ( 0 != m_algMgr ) { m_algMgr -> release () ; m_algMgr = 0 ; }
00429 if ( 0 != m_dataSvc ) { m_dataSvc -> release () ; m_dataSvc = 0 ; }
00430
00431 return Service::finalize();
00432 }
00433
00435
00436 StatusCode DataOnDemandSvc::reinitialize()
00437 {
00438
00439 if ( 0 != m_incSvc )
00440 {
00441 m_incSvc -> removeListener ( this , m_trapType );
00442 m_incSvc -> release ();
00443 m_incSvc = 0;
00444 }
00445 if ( 0 != m_algMgr ) { m_algMgr -> release() ; m_algMgr = 0 ; }
00446 if ( 0 != m_dataSvc ) { m_dataSvc -> release() ; m_dataSvc = 0 ; }
00447 if ( 0 != m_log ) { delete m_log ; m_log = 0 ; }
00448
00449 StatusCode sc = Service::reinitialize();
00450 if ( sc.isFailure() ) { return sc; }
00451
00452 sc = setup() ;
00453 if ( sc.isFailure() ) { return sc; }
00454
00455 if ( m_dump ) { dump ( MSG::INFO ) ; }
00456 else if ( MSG::DEBUG >= outputLevel() ) { dump ( MSG::DEBUG ) ; }
00457
00458 return StatusCode::SUCCESS ;
00459 }
00460
00461
00462
00463 StatusCode DataOnDemandSvc::setup()
00464 {
00465 m_algMgr = 0;
00466 StatusCode sc =
00467 serviceLocator()->queryInterface(IAlgManager::interfaceID(), pp_cast<void>(&m_algMgr));
00468 if ( sc.isFailure () )
00469 {
00470 stream()
00471 << MSG::ERROR
00472 << "Failed to retrieve the IAlgManager interface." << endmsg;
00473 return sc;
00474 }
00475 sc = service("IncidentSvc", m_incSvc, true);
00476 if ( sc.isFailure () )
00477 {
00478 stream()
00479 << MSG::ERROR << "Failed to retrieve Incident service." << endmsg;
00480 return sc;
00481 }
00482 m_incSvc->addListener(this, m_trapType);
00483 sc = service(m_dataSvcName, m_dataSvc, true);
00484 if ( sc.isFailure () )
00485 {
00486 stream()
00487 << MSG::ERROR
00488 << "Failed to retrieve the data provider interface of "
00489 << m_dataSvcName << endmsg;
00490 return sc;
00491 }
00492 return update() ;
00493 }
00494
00495
00496
00497 StatusCode DataOnDemandSvc::setupNodeHandlers()
00498 {
00499 Setup::const_iterator j;
00500 std::string nam, typ, tag;
00501 StatusCode sc = StatusCode::SUCCESS;
00502
00503 for ( j=m_nodeMapping.begin(); j != m_nodeMapping.end(); ++j)
00504 {
00505 Tokenizer tok(true);
00506 tok.analyse(*j, " ", "", "", "=", "'", "'");
00507 for ( Tokenizer::Items::iterator i = tok.items().begin();
00508 i != tok.items().end(); i++ ) {
00509 const std::string& t = (*i).tag();
00510 const std::string& v = (*i).value();
00511 switch( ::toupper(t[0]) ) {
00512 case 'D':
00513 tag = v;
00514 break;
00515 case 'T':
00516 nam = v;
00517 break;
00518 }
00519 }
00520 if ( m_algMap .end () != m_algMap .find ( tag ) ||
00521 m_nodeMap .end () != m_nodeMap .find ( tag ) )
00522 {
00523 stream()
00524 << MSG::WARNING
00525 << "The obsolete property 'Nodes' redefines the action for '"
00526 + tag + "' to be '" +nam+"'"
00527 << endmsg ;
00528 }
00529 m_nodeMap[tag] = nam ;
00530 }
00531
00532 m_updateRequired = true ;
00533
00534 return sc;
00535 }
00536
00537
00538
00539 StatusCode DataOnDemandSvc::setupAlgHandlers()
00540 {
00541 Setup::const_iterator j;
00542 std::string typ, tag;
00543
00544 for(j=m_algMapping.begin(); j != m_algMapping.end(); ++j)
00545 {
00546 Tokenizer tok(true);
00547 tok.analyse(*j, " ", "", "", "=", "'", "'");
00548 for(Tokenizer::Items::iterator i = tok.items().begin(); i != tok.items().end(); i++ ) {
00549 const std::string& t = (*i).tag();
00550 const std::string& v = (*i).value();
00551 switch( ::toupper(t[0]) ) {
00552 case 'D':
00553 tag = v;
00554 break;
00555 case 'T':
00556 typ = v;
00557 break;
00558 }
00559 }
00560 Gaudi::Utils::TypeNameString item(typ);
00561 if ( m_algMap .end () != m_algMap .find ( tag ) ||
00562 m_nodeMap .end () != m_nodeMap .find ( tag ) )
00563 {
00564 stream()
00565 << MSG::WARNING
00566 << "The obsolete property 'Algorithms' redefines the action for '"
00567 + tag + "' to be '" +item.type() +"/"+item.name()+"'"
00568 << endmsg ;
00569 }
00570 m_algMap[tag] = item.type() + "/" + item.name() ;
00571 }
00572 m_updateRequired = true ;
00573 return StatusCode::SUCCESS;
00574 }
00575
00577
00578 StatusCode DataOnDemandSvc::configureHandler(Leaf& l)
00579 {
00580 StatusCode sc = StatusCode::FAILURE;
00581 if ( 0 == m_algMgr ) { return sc; }
00582 l.algorithm = m_algMgr->algorithm(l.name, false);
00583 if ( 0 == l.algorithm )
00584 {
00585 sc = m_algMgr->createAlgorithm(l.type, l.name, l.algorithm, true );
00586 if ( sc.isFailure() )
00587 {
00588 stream()
00589 << MSG::ERROR
00590 << "Failed to create algorithm "
00591 << l.type << "('" << l.name<< "')" << endmsg;
00592 }
00593 }
00594 return sc;
00595 }
00596
00598
00599 void DataOnDemandSvc::handle ( const Incident& incident )
00600 {
00601 ++m_stat ;
00602
00603 if ( incident.type() != m_trapType ) { return ; }
00604 const DataIncident* inc = dynamic_cast<const DataIncident*>(&incident);
00605 if ( 0 == inc ) { return ; }
00606
00607 if ( m_updateRequired ) { update() ; }
00608 const std::string& tag = inc->tag();
00609 if ( MSG::VERBOSE >= outputLevel() )
00610 {
00611 stream()
00612 << MSG::VERBOSE
00613 << "Incident: [" << incident.type () << "] "
00614 << " = " << incident.source ()
00615 << " Location:" << tag << endmsg;
00616 }
00617
00618 NodeMap::iterator icl = m_nodes.find ( tag ) ;
00619 if ( icl != m_nodes.end() )
00620 {
00621 StatusCode sc = execHandler ( tag , icl->second ) ;
00622 if ( sc.isSuccess() ) { ++m_statNode ; }
00623 return ;
00624 }
00625
00626 AlgMap::iterator ialg = m_algs.find ( tag ) ;
00627 if ( ialg != m_algs.end() )
00628 {
00629 StatusCode sc = execHandler ( tag , ialg->second ) ;
00630 if ( sc.isSuccess() ) { ++m_statAlg ; }
00631 return ;
00632 }
00633 }
00634
00635
00636
00637 StatusCode
00638 DataOnDemandSvc::execHandler(const std::string& tag, Node& n)
00639 {
00640 if ( n.executing ) { return StatusCode::FAILURE ; }
00641
00642
00643 if ( !n.clazz ) { n.clazz = ROOT::Reflex::Type::ByName(n.name) ; }
00644 if ( !n.clazz )
00645 {
00646 stream()
00647 << MSG::ERROR
00648 << "Failed to get dictionary for class '"
00649 << n.name
00650 << "' for location:" << tag << endmsg;
00651 return StatusCode::FAILURE ;
00652 }
00653
00654 ROOT::Reflex::Object obj = n.clazz.Construct();
00655 DataObject* pO = (DataObject*)obj.Address();
00656 if ( !pO )
00657 {
00658 stream()
00659 << MSG::ERROR
00660 << "Failed to create an object of type:"
00661 << n.clazz.Name(ROOT::Reflex::SCOPED) << " for location:" << tag
00662 << endmsg;
00663 return StatusCode::FAILURE ;
00664 }
00665
00666 Protection p(n.executing);
00667 StatusCode sc = m_dataSvc->registerObject(tag, pO);
00668 if ( sc.isFailure() )
00669 {
00670 stream()
00671 << MSG::ERROR << "Failed to register an object of type:"
00672 << n.clazz.Name(ROOT::Reflex::SCOPED) << " at location:" << tag
00673 << endmsg;
00674 return sc ;
00675 }
00676 ++n.num ;
00677
00678 return StatusCode::SUCCESS ;
00679 }
00680
00681
00682
00683 StatusCode
00684 DataOnDemandSvc::execHandler(const std::string& tag, Leaf& l)
00685 {
00686
00687 if ( l.executing ) { return StatusCode::FAILURE ; }
00688
00689 if ( 0 == l.algorithm )
00690 {
00691 StatusCode sc = configureHandler ( l ) ;
00692 if ( sc.isFailure() )
00693 {
00694 stream()
00695 << MSG::ERROR
00696 << "Failed to configure handler for: "
00697 << l.name << "[" << l.type << "] " << tag << endmsg;
00698 return sc ;
00699 }
00700 }
00701
00702 Timer timer ( m_total ) ;
00703
00704 Protection p(l.executing);
00705 StatusCode sc = l.algorithm->sysExecute();
00706 if ( sc.isFailure() )
00707 {
00708 stream() << MSG::ERROR
00709 << "Failed to execute the algorithm:"
00710 << l.algorithm->name() << " for location:" << tag << endmsg;
00711 return sc ;
00712 }
00713 ++l.num ;
00714
00715 return StatusCode::SUCCESS ;
00716 }
00717
00721 DECLARE_SERVICE_FACTORY(DataOnDemandSvc)
00722
00723
00724
00725
00726