| # Gaudi Framework, version v25r0 |

Home |  | Generated: Mon Feb 17 2014

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
DataOnDemandSvc.cpp
Go to the documentation of this file.
1 // ============================================================================
2 // Include files
3 // ============================================================================
4 // STD & STL
5 // ============================================================================
6 #include <string>
7 #include <set>
8 #include <map>
9 #include <math.h>
10 // ============================================================================
11 // GaudiKernel
12 // ============================================================================
13 #include "GaudiKernel/MsgStream.h"
14 #include "GaudiKernel/Tokenizer.h"
15 #include "GaudiKernel/DataObject.h"
16 #include "GaudiKernel/IAlgorithm.h"
17 #include "GaudiKernel/ISvcLocator.h"
18 #include "GaudiKernel/IAlgManager.h"
19 #include "GaudiKernel/IIncidentSvc.h"
20 #include "GaudiKernel/DataIncident.h"
21 #include "GaudiKernel/IDataProviderSvc.h"
22 #include "GaudiKernel/IToolSvc.h"
23 #include "GaudiKernel/TypeNameString.h"
24 #include "GaudiKernel/ToStream.h"
25 #include "GaudiKernel/Chrono.h"
26 #include "GaudiKernel/LockedChrono.h"
27 // ============================================================================
28 // Local
29 // ============================================================================
30 #include "DataOnDemandSvc.h"
31 // ============================================================================
32 // Boost
33 // ============================================================================
34 #ifdef __ICC
35 // disable icc remark #2259: non-pointer conversion from "X" to "Y" may lose significant bits
36 // TODO: To be removed, since it comes from Boost
37 #pragma warning(disable:2259)
38 #endif
39 #include "boost/format.hpp"
40 #include "boost/lexical_cast.hpp"
41 #include "GaudiKernel/Property.h"
42 // ============================================================================
43 // Constructors and Destructor
44 // ============================================================================
45 DataOnDemandSvc::DataOnDemandSvc
46 ( const std::string& name, ISvcLocator* svc )
47 : base_class(name, svc)
48 , m_incSvc ( 0 )
49 , m_algMgr ( 0 )
50 , m_dataSvc ( 0 )
51 //
52 , m_trapType ( "DataFault")
53 , m_dataSvcName ( "EventDataSvc" )
54 , m_partialPath ( true )
55 , m_dump ( false )
56 , m_init ( false )
57 , m_allowInitFailure(false)
58 //
59 , m_algMapping ()
60 , m_nodeMapping ()
61 //
62 , m_algMap ( )
63 , m_nodeMap ( )
64 //
65 , m_updateRequired ( true )
66 , m_prefix ( "/Event/" )
67 , m_log ( 0 )
68 , m_total ( )
69 , m_statAlg ( 0 )
70 , m_statNode ( 0 )
71 , m_stat ( 0 )
72 //
73 , m_timer_nodes ()
74 , m_timer_algs ()
75 , m_timer_all ()
76 , m_locked_nodes ( false )
77 , m_locked_algs ( false )
78 , m_locked_all ( false )
79 //
80 {
81 // ==========================================================================
82 declareProperty
83 ( "IncidentName" ,
84 m_trapType ,
85 "The type of handled Incident" ) ;
86 //
87 declareProperty ( "DataSvc" , m_dataSvcName ) ;
88 //
89 declareProperty ( "UsePreceedingPath" , m_partialPath ) ;
90 declareProperty
91 ( "Dump" ,
92 m_dump ,
93 "Dump the configuration and stastics" ) ->
94 declareUpdateHandler ( &DataOnDemandSvc::update_dump , this ) ;
95 //
96 declareProperty
97 ( "PreInitialize" ,
98 m_init ,
99 "Flag to (pre)initialize all algorithms" ) ;
100 declareProperty
101 ( "AllowPreInitializeFailure" ,
102 m_allowInitFailure ,
103 "Allow (pre)initialization of algorithms to fail without stopping the application" ) ;
104 //
105 declareProperty ( "Algorithms" , m_algMapping ) ->
106 declareUpdateHandler ( &DataOnDemandSvc::update_2 , this ) ;
107 declareProperty ( "Nodes" , m_nodeMapping ) ->
108 declareUpdateHandler ( &DataOnDemandSvc::update_3 , this ) ;
109 //
110 declareProperty ( "AlgMap" , m_algMap ) ->
111 declareUpdateHandler ( &DataOnDemandSvc::update_1 , this ) ;
112 declareProperty ( "NodeMap" , m_nodeMap ) ->
113 declareUpdateHandler ( &DataOnDemandSvc::update_1 , this ) ;
114
115 declareProperty ( "Prefix" , m_prefix ) ;
116
117 declareProperty("NodeMappingTools", m_nodeMapTools,
118 "List of tools of type IDODNodeMapper");
119 declareProperty("AlgMappingTools", m_algMapTools,
120 "List of tools of type IDODAlgMapper");
121 // ==========================================================================
122 }
123 // ============================================================================
124 // Update handler
125 // ============================================================================
126 void DataOnDemandSvc::update_1 ( Property& p )
127 {
128 stream() << MSG::VERBOSE << " I am update handler for property " << p << endmsg ;
129 // force update
130 m_updateRequired = true ;
131 }
132 // ============================================================================
133 // Update handler
134 // ============================================================================
135 void DataOnDemandSvc::update_3 ( Property& /* p */ )
136 {
137 stream() << MSG::WARNING
138 << "The property 'Nodes' is obsolete, switch to map-like 'NodeMap' "
139 << " = { 'data' : 'type' } "
140 << endmsg ;
141 // force update
142 m_updateRequired = true ;
143 }
144 // ============================================================================
145 // Update handler
146 // ============================================================================
147 void DataOnDemandSvc::update_2 ( Property& /* p */ )
148 {
149 stream() << MSG::WARNING
150 << "The property 'Algorithms' is obsolete, switch to map-like 'AlgMap' "
151 << " = { 'data' : 'algorithm' } "
152 << endmsg ;
153 // force update
154 m_updateRequired = true ;
155 }
156 // ============================================================================
157 // Update handler
158 // ============================================================================
159 void DataOnDemandSvc::update_dump ( Property& /* p */ )
160 {
161 // no action if not yet initialized
162 if ( FSMState() < Gaudi::StateMachine::INITIALIZED ) { return ; }
163 // dump the configuration:
164 if ( m_dump ) { dump ( MSG::ALWAYS ) ; }
165 }
166 // ============================================================================
167 // anonymous namespace to hide few local functions
168 // ============================================================================
169 namespace
170 {
171 // ==========================================================================
177 inline std::string no_prefix
178 ( const std::string& value ,
179 const std::string& prefix )
180 {
181 return
182 !prefix.empty() && 0 == value.find(prefix) ?
183 std::string( value , prefix.size() ) : value ;
184 }
185 // ==========================================================================
192 template <class MAP>
193 inline size_t add_prefix ( MAP& _map , const std::string& prefix )
194 {
195 // empty prefix
196 if ( prefix.empty() ) { return 0 ; } // RETURN
198 for ( typename MAP::iterator it = _map.begin() ; _map.end() != it ; ++it )
199 {
200 if ( 0 != it->first.find(prefix) ) // valid prefix?
201 {
202 std::string key = prefix + it->first ;
203 std::string value = it->second ;
204 _map.erase ( it ) ;
205 _map[ key ] = value ;
206 return 1 + add_prefix ( _map , prefix ) ; // RETURN, recursion
207 }
208 }
209 //
210 return 0 ;
211 }
212 // ==========================================================================
218 template <class SET>
219 inline size_t get_dir ( const std::string& object , SET& _set )
220 {
221 std::string::size_type ifind = object.rfind('/') ;
222 // stop recursion
223 if ( std::string::npos == ifind ) { return 0 ; } // RETURN
224 if ( 0 == ifind ) { return 0 ; }
225 //
226 const std::string top = std::string( object , 0 , ifind) ;
227 _set.insert( top ) ;
228 return 1 + get_dir ( top , _set ) ; // RETURN, recursion
229 }
230 // ==========================================================================
236 template <class MAP, class SET>
237 inline size_t get_dirs ( const MAP& _map, SET& _set )
238 {
239 size_t size = _set.size() ;
240 for ( typename MAP::const_iterator item = _map.begin() ;
241 _map.end() != item ; ++item ) { get_dir ( item->first , _set ) ; }
242 return _set.size() - size ;
243 }
244 // ==========================================================================
245 } // end of anonymous namespace
246
247 void DataOnDemandSvc::i_setNodeHandler(const std::string &name, const std::string &type){
248 ClassH cl = TClass::GetClass(type.c_str()) ;
249 if (!cl) {
250 warning()
251 << "Failed to access dictionary class for "
252 << name << " of type:" << type << endmsg;
253 }
254 m_nodes[name] = Node(cl, false, type);
255 }
256
257 StatusCode DataOnDemandSvc::i_setAlgHandler(const std::string &name, const Gaudi::Utils::TypeNameString &alg){
258 Leaf leaf(alg.type(), alg.name());
259 if (m_init)
260 {
261 StatusCode sc = configureHandler(leaf);
262 if (sc.isFailure()) {
263 if (m_allowInitFailure) {
264 // re-store the content of the leaf object to try again to initialize
265 // the algorithm later (on demand)
266 leaf = Leaf(alg.type(), alg.name());
267 }
268 else
269 return sc;
270 }
271 }
272 m_algs[name] = leaf;
273 return StatusCode::SUCCESS;
274 }
275
276 // ============================================================================
277 // update the content of Data-On-Demand actions
278 // ============================================================================
279 StatusCode DataOnDemandSvc::update ()
280 {
281 if ( !m_updateRequired ) { return StatusCode::SUCCESS ; }
282
284 StatusCode sc = setupNodeHandlers() ; // convert "Nodes" new "NodeMap"
285 if ( sc.isFailure() )
286 {
287 stream() << MSG::ERROR << "Failed to setup old \"Nodes\"" << endmsg ;
288 return sc ;
289 }
291 sc = setupAlgHandlers() ; // convert "Algorithms" into "AlgMap"
292 if ( sc.isFailure() )
293 {
294 stream() << MSG::ERROR << "Failed to setup old \"Algorithms\"" << endmsg ;
295 return sc ;
296 }
298 add_prefix ( m_algMap , m_prefix ) ;
300 add_prefix ( m_nodeMap , m_prefix ) ;
302 typedef std::set<std::string> Set ;
303 Set dirs ;
304 if ( m_partialPath ){ get_dirs ( m_algMap , dirs ) ; }
305 if ( m_partialPath ){ get_dirs ( m_nodeMap , dirs ) ; }
306 //
307 Set::iterator _e = dirs.find("/Event") ;
308 if ( dirs.end() != _e ) { dirs.erase( _e ) ; }
309 // add all directories as nodes
310 for ( Set::const_iterator dir = dirs.begin() ; dirs.end() != dir ; ++dir )
311 {
312 if ( m_algMap .end () != m_algMap .find ( *dir ) ) { continue ; }
313 if ( m_nodeMap .end () != m_nodeMap .find ( *dir ) ) { continue ; }
314 m_nodeMap [*dir] = "DataObject" ;
315 }
316 //
317 m_algs .clear () ;
318 m_nodes .clear () ;
319 //
321 for ( Map::const_iterator ialg = m_algMap.begin() ;
322 m_algMap.end() != ialg ; ++ialg )
323 {
324 if (i_setAlgHandler(ialg->first, ialg->second).isFailure())
325 return StatusCode::FAILURE;
326 }
328 for ( Map::const_iterator inode = m_nodeMap.begin() ;
329 m_nodeMap.end() != inode ; ++inode )
330 {
331 i_setNodeHandler(inode->first, inode->second);
332 }
334 m_updateRequired = false ;
335 //
336 return StatusCode::SUCCESS ;
337 }
338 // ============================================================================
339 // destructor
340 // ============================================================================
341 DataOnDemandSvc::~DataOnDemandSvc()
342 { if ( 0 != m_log ) { delete m_log ; m_log = 0 ; } }
343 //=============================================================================
344 // Inherited Service overrides:
345 //=============================================================================
346 StatusCode DataOnDemandSvc::initialize()
347 {
348 // initialize the Service Base class
349 StatusCode sc = Service::initialize();
350 if ( sc.isFailure() ) { return sc; }
351 sc = setup();
352 if ( sc.isFailure() ) { return sc; }
353 //
354 if ( m_dump ) { dump ( MSG::INFO ) ; }
355 else if ( MSG::DEBUG >= outputLevel() ) { dump ( MSG::DEBUG ) ; }
356 //
357 if ( m_init ) { return update () ; }
358 //
359 return StatusCode::SUCCESS ;
360 }
361 // ============================================================================
362 // finalization of the service
363 // ============================================================================
364 StatusCode DataOnDemandSvc::finalize()
365 {
366 //
367 stream ()
368 << MSG::INFO
369 << "Handled \"" << m_trapType << "\" incidents: "
370 << m_statAlg << "/" << m_statNode << "/" << m_stat << "(Alg/Node/Total)."
371 << endmsg ;
372 if ( m_dump || MSG::DEBUG >= outputLevel() )
373 {
374 stream ()
375 << MSG::INFO
376 << m_total.outputUserTime
377 ( "Algorithm timing: Mean(+-rms)/Min/Max:%3%(+-%4%)/%6%/%7%[ms] " , System::milliSec )
378 << m_total.outputUserTime ( "Total:%2%[s]" , System::Sec ) << endmsg ;
379 stream ()
380 << MSG::INFO
381 << m_timer_nodes.outputUserTime
382 ( "Nodes timing: Mean(+-rms)/Min/Max:%3%(+-%4%)/%6%/%7%[ms] " , System::milliSec )
383 << m_timer_nodes.outputUserTime ( "Total:%2%[s]" , System::Sec ) << endmsg ;
384 stream ()
385 << MSG::INFO
386 << m_timer_algs .outputUserTime
387 ( "Algs timing: Mean(+-rms)/Min/Max:%3%(+-%4%)/%6%/%7%[ms] " , System::milliSec )
388 << m_timer_algs .outputUserTime ( "Total:%2%[s]" , System::Sec ) << endmsg ;
389 stream ()
390 << MSG::INFO
391 << m_timer_all .outputUserTime
392 ( "All timing: Mean(+-rms)/Min/Max:%3%(+-%4%)/%6%/%7%[ms] " , System::milliSec )
393 << m_timer_all .outputUserTime ( "Total:%2%[s]" , System::Sec ) << endmsg ;
394 }
395 // dump it!
396 if ( m_dump ) { dump ( MSG::INFO , false ) ; }
397 else if ( MSG::DEBUG >= outputLevel() ) { dump ( MSG::DEBUG , false ) ; }
398 //
399 if ( m_incSvc )
400 {
401 m_incSvc->removeListener(this, m_trapType);
402 m_incSvc.reset();
403 }
404 m_algMgr.reset();
405 m_dataSvc.reset();
406 if (m_toolSvc) { // we may not have retrieved the ToolSvc
407 // Do not call releaseTool if the ToolSvc was already finalized.
408 if (SmartIF<IStateful>(m_toolSvc)->FSMState() > Gaudi::StateMachine::CONFIGURED) {
409 for(std::list<IDODNodeMapper*>::iterator i = m_nodeMappers.begin(); i != m_nodeMappers.end(); ++i)
410 m_toolSvc->releaseTool(*i).ignore();
411 for(std::list<IDODAlgMapper*>::iterator i = m_algMappers.begin(); i != m_algMappers.end(); ++i)
412 m_toolSvc->releaseTool(*i).ignore();
413 } else {
414 warning() << "ToolSvc already finalized: cannot release tools. Check options." << endmsg;
415 }
416 m_nodeMappers.clear();
417 m_algMappers.clear();
418 m_toolSvc.reset();
419 }
420 return Service::finalize();
421 }
422 // ============================================================================
424 // ============================================================================
425 StatusCode DataOnDemandSvc::reinitialize()
426 {
427 // reinitialize the Service Base class
428 if ( 0 != m_incSvc )
429 {
430 m_incSvc -> removeListener ( this , m_trapType );
431 m_incSvc.reset();
432 }
433 m_algMgr.reset();
434 m_dataSvc.reset();
435 for(std::list<IDODNodeMapper*>::iterator i = m_nodeMappers.begin(); i != m_nodeMappers.end(); ++i)
436 m_toolSvc->releaseTool(*i).ignore();
437 m_nodeMappers.clear();
438 for(std::list<IDODAlgMapper*>::iterator i = m_algMappers.begin(); i != m_algMappers.end(); ++i)
439 m_toolSvc->releaseTool(*i).ignore();
440 m_algMappers.clear();
441 m_toolSvc.reset();
442 if ( 0 != m_log ) { delete m_log ; m_log = 0 ; }
443 //
444 StatusCode sc = Service::reinitialize();
445 if ( sc.isFailure() ) { return sc; }
446 //
447 sc = setup() ;
448 if ( sc.isFailure() ) { return sc; }
449 //
450 if ( m_dump ) { dump ( MSG::INFO ) ; }
451 else if ( MSG::DEBUG >= outputLevel() ) { dump ( MSG::DEBUG ) ; }
452 //
453 return StatusCode::SUCCESS ;
454 }
455 // ============================================================================
456 // setup service
457 // ============================================================================
458 StatusCode DataOnDemandSvc::setup()
459 {
460 if ( !(m_algMgr = serviceLocator()) ) // assignment meant
461 {
462 error() << "Failed to retrieve the IAlgManager interface." << endmsg;
463 return StatusCode::FAILURE;
464 }
465
466 if ( !(m_incSvc = serviceLocator()->service("IncidentSvc")) ) // assignment meant
467 {
468 error() << "Failed to retrieve Incident service." << endmsg;
469 return StatusCode::FAILURE;
470 }
471 m_incSvc->addListener(this, m_trapType);
472
473 if ( !(m_dataSvc = serviceLocator()->service(m_dataSvcName)) ) // assignment meant
474 {
475 error()
476 << "Failed to retrieve the data provider interface of "
477 << m_dataSvcName << endmsg;
478 return StatusCode::FAILURE;
479 }
480
481 // No need to get the ToolSvc if we are not using tools
482 if (!(m_nodeMapTools.empty() && m_algMapTools.empty())) {
483 if ( !(m_toolSvc = serviceLocator()->service("ToolSvc")) ) // assignment meant
484 {
485 error() << "Failed to retrieve ToolSvc" << endmsg;
486 return StatusCode::FAILURE;
487 }
488
489 // load the node mapping tools
490 std::vector<std::string>::iterator i;
491 IDODNodeMapper *nodetool = 0;
492 for(i = m_nodeMapTools.begin(); i != m_nodeMapTools.end(); ++i) {
493 const StatusCode sc = m_toolSvc->retrieveTool(*i, nodetool);
494 if (sc.isFailure()) return sc;
495 m_nodeMappers.push_back(nodetool);
496 }
497 IDODAlgMapper *algtool = 0;
498 for(i = m_algMapTools.begin(); i != m_algMapTools.end(); ++i) {
499 const StatusCode sc = m_toolSvc->retrieveTool(*i, algtool);
500 if (sc.isFailure()) return sc;
501 m_algMappers.push_back(algtool);
502 }
503 }
504 return update();
505 }
506 // ============================================================================
507 // setup node handlers
508 // ============================================================================
509 StatusCode DataOnDemandSvc::setupNodeHandlers()
510 {
511 Setup::const_iterator j;
512 std::string nam, typ, tag;
513 StatusCode sc = StatusCode::SUCCESS;
514 // Setup for node leafs, where simply a constructor is called...
515 for ( j=m_nodeMapping.begin(); j != m_nodeMapping.end(); ++j)
516 {
517 Tokenizer tok(true);
518 tok.analyse(*j, " ", "", "", "=", "'", "'");
519 for ( Tokenizer::Items::iterator i = tok.items().begin();
520 i != tok.items().end(); i++ ) {
521 const std::string& t = (*i).tag();
522 const std::string& v = (*i).value();
523 switch( ::toupper(t[0]) ) {
524 case 'D':
525 tag = v;
526 break;
527 case 'T':
528 nam = v;
529 break;
530 }
531 }
532 if ( m_algMap .end () != m_algMap .find ( tag ) ||
533 m_nodeMap .end () != m_nodeMap .find ( tag ) )
534 {
535 stream()
536 << MSG::WARNING
537 << "The obsolete property 'Nodes' redefines the action for '"
538 + tag + "' to be '" +nam+"'"
539 << endmsg ;
540 }
541 m_nodeMap[tag] = nam ;
542 }
543 //
544 m_updateRequired = true ;
545 //
546 return sc;
547 }
548 // ============================================================================
549 // setup algorithm handlers
550 // ============================================================================
551 StatusCode DataOnDemandSvc::setupAlgHandlers()
552 {
553 Setup::const_iterator j;
554 std::string typ, tag;
555
556 for(j=m_algMapping.begin(); j != m_algMapping.end(); ++j)
557 {
558 Tokenizer tok(true);
559 tok.analyse(*j, " ", "", "", "=", "'", "'");
560 for(Tokenizer::Items::iterator i = tok.items().begin(); i != tok.items().end(); i++ ) {
561 const std::string& t = (*i).tag();
562 const std::string& v = (*i).value();
563 switch( ::toupper(t[0]) ) {
564 case 'D':
565 tag = v;
566 break;
567 case 'T':
568 typ = v;
569 break;
570 }
571 }
572 Gaudi::Utils::TypeNameString item(typ);
573 if ( m_algMap .end () != m_algMap .find ( tag ) ||
574 m_nodeMap .end () != m_nodeMap .find ( tag ) )
575 {
576 stream()
577 << MSG::WARNING
578 << "The obsolete property 'Algorithms' redefines the action for '"
579 + tag + "' to be '" +item.type() +"/"+item.name()+"'"
580 << endmsg ;
581 }
582 m_algMap[tag] = item.type() + "/" + item.name() ;
583 }
584 m_updateRequired = true ;
585 return StatusCode::SUCCESS;
586 }
587 // ============================================================================
589 // ============================================================================
590 StatusCode DataOnDemandSvc::configureHandler(Leaf& l)
591 {
592 if ( 0 != l.algorithm ) { return StatusCode::SUCCESS ; }
593 if ( 0 == m_algMgr ) { return StatusCode::FAILURE ; }
594 l.algorithm = m_algMgr->algorithm(l.name, false);
595 if ( 0 != l.algorithm ) { return StatusCode::SUCCESS ; }
596 // create it!
597 StatusCode sc = m_algMgr->createAlgorithm ( l.type , l.name , l.algorithm , true ) ;
598 if ( sc.isFailure() )
599 {
600 stream()
601 << MSG::ERROR
602 << "Failed to create algorithm "
603 << l.type << "('" << l.name<< "')" << endmsg;
604 l.algorithm = 0 ;
605 return sc ; // RETURN
606 }
607 if ( l.algorithm->isInitialized() ) { return StatusCode:: SUCCESS ;}
608 // initialize it!
609 sc = l.algorithm -> sysInitialize () ;
610 if ( sc.isFailure() )
611 {
612 stream()
613 << MSG::ERROR
614 << "Failed to initialize algorithm "
615 << l.type << "('" << l.name<< "')" << endmsg;
616 l.algorithm = 0 ;
617 return sc ; // RETURN
618 }
619 if ( Gaudi::StateMachine::RUNNING == l.algorithm->FSMState() )
620 { return StatusCode::SUCCESS ; }
621 // run it!
622 sc = l.algorithm->sysStart() ;
623 if ( sc.isFailure() )
624 {
625 stream()
626 << MSG::ERROR
627 << "Failed to 'run' algorithm "
628 << l.type << "('" << l.name<< "')" << endmsg;
629 l.algorithm = 0 ;
630 return sc ; // RETURN
631 }
632 return StatusCode::SUCCESS ;
633 }
634
635 // local algorithms
636 namespace {
639 struct ToolGetter {
641 std::string path;
643 ToolGetter(const std::string &_path): path(_path) {}
645 inline std::string operator() (IDODNodeMapper *t) const {
646 return t->nodeTypeForPath(path);
647 }
649 inline Gaudi::Utils::TypeNameString operator() (IDODAlgMapper *t) const {
650 return t->algorithmForPath(path);
651 }
652 };
653
656 inline bool isGood(const std::string& r) {return !r.empty();}
657 inline bool isGood(const Gaudi::Utils::TypeNameString& r) {return !r.name().empty();}
659
662 class Finder {
663 const ToolGetter getter;
664 const std::list<IDODNodeMapper*> &nodes;
665 const std::list<IDODAlgMapper*> &algs;
667 template <class R, class T>
668 R find(const std::list<T*> &l) const {
669 typename std::list<T*>::const_iterator i;
670 for(i = l.begin(); i != l.end(); ++i) {
671 R result = getter(*i);
672 if (isGood(result)) return result;
673 }
674 return R("");
675 }
676 public:
678 Finder(const std::string &_path,
679 const std::list<IDODNodeMapper*> &_nodes,
680 const std::list<IDODAlgMapper*> &_algs): getter(_path), nodes(_nodes), algs(_algs) {
681 }
683 inline std::string node() const {
684 return find<std::string>(nodes);
685 }
687 inline Gaudi::Utils::TypeNameString alg() const {
688 return find<Gaudi::Utils::TypeNameString>(algs);
689 }
690
691 };
692
693 }
694
695 // ===========================================================================
696 // IIncidentListener interfaces overrides: incident handling
697 // ===========================================================================
698 void DataOnDemandSvc::handle ( const Incident& incident )
699 {
700
701 Gaudi::Utils::LockedChrono timer ( m_timer_all , m_locked_all ) ;
702
703 ++m_stat ;
704 // proper incident type?
705 if ( incident.type() != m_trapType ) { return ; } // RETURN
706 const DataIncident* inc = dynamic_cast<const DataIncident*>(&incident);
707 if ( 0 == inc ) { return ; } // RETURN
708 // update if needed!
709 if ( m_updateRequired ) { update() ; }
710
711 if ( MSG::VERBOSE >= outputLevel() )
712 {
713 verbose()
714 << "Incident: [" << incident.type () << "] "
715 << " = " << incident.source ()
716 << " Location:" << inc->tag() << endmsg;
717 }
718 // ==========================================================================
719 // const std::string& tag = inc->tag();
720 Gaudi::StringKey tag ( inc->tag() ) ;
721 // ==========================================================================
722 NodeMap::iterator icl = m_nodes.find ( tag ) ;
723 if ( icl != m_nodes.end() )
724 {
725 StatusCode sc = execHandler ( tag , icl->second ) ;
726 if ( sc.isSuccess() ) { ++m_statNode ; }
727 return ; // RETURN
728 }
729 // ==========================================================================
730 AlgMap::iterator ialg = m_algs.find ( tag ) ;
731 if ( ialg != m_algs.end() )
732 {
733 StatusCode sc = execHandler ( tag , ialg->second ) ;
734 if ( sc.isSuccess() ) { ++m_statAlg ; }
735 return ; // RETURN
736 }
737 // ==========================================================================
738 // Fall back on the tools
739 if (m_toolSvc) {
740 if (MSG::VERBOSE >= outputLevel())
741 verbose() << "Try to find mapping with mapping tools" << endmsg;
742 Finder finder(no_prefix(inc->tag(), m_prefix), m_nodeMappers, m_algMappers);
743 // - try the node mappers
744 std::string node = finder.node();
745 if (isGood(node)) {
746 // if one is found update the internal node mapping and try again.
747 if (MSG::VERBOSE >= outputLevel())
748 verbose() << "Found Node handler: " << node << endmsg;
749 i_setNodeHandler(inc->tag(), node);
750 handle(incident);
751 --m_stat; // avoid double counting because of recursion
752 return;
753 }
754 // - try alg mappings
755 Gaudi::Utils::TypeNameString alg = finder.alg();
756 if (isGood(alg)) {
757 // we got an algorithm, update alg map and try to handle again
758 if (MSG::VERBOSE >= outputLevel())
759 verbose() << "Found Algorithm handler: " << alg << endmsg;
760 i_setAlgHandler(inc->tag(), alg).ignore();
761 handle(incident);
762 --m_stat; // avoid double counting because of recursion
763 return;
764 }
765 }
766 }
767 // ===========================================================================
768 // execute the handler
769 // ===========================================================================
770 StatusCode
771 DataOnDemandSvc::execHandler ( const std::string& tag, Node& n)
772 {
773
774 Gaudi::Utils::LockedChrono timer ( m_timer_nodes , m_locked_nodes ) ;
775
776 if ( n.executing ) { return StatusCode::FAILURE ; } // RETURN
777
778 Protection p(n.executing);
779
780 DataObject* object= 0 ;
781
782 if ( n.dataObject ) { object = new DataObject() ; }
783 else
784 {
785 // try to recover the handler
786 if ( !n.clazz ) { n.clazz = TClass::GetClass(n.name.c_str()) ; }
787 if ( !n.clazz )
788 {
789 stream()
790 << MSG::ERROR
791 << "Failed to get dictionary for class '"
792 << n.name
793 << "' for location:" << tag << endmsg;
794 return StatusCode::FAILURE ; // RETURN
795 }
796
797 object = reinterpret_cast<DataObject*>(n.clazz->New());
798
799 if ( !object )
800 {
801 stream()
802 << MSG::ERROR
803 << "Failed to create an object of type:"
804 << n.clazz->GetName() << " for location:" << tag
805 << endmsg;
806 return StatusCode::FAILURE ; // RETURN
807 }
808 }
809 //
810 StatusCode sc = m_dataSvc->registerObject(tag, object );
811 if ( sc.isFailure() )
812 {
813 stream()
814 << MSG::ERROR << "Failed to register an object of type:"
815 << n.name << " at location:" << tag
816 << endmsg;
817 return sc ; // RETURN
818 }
819 ++n.num ;
820 //
821 return StatusCode::SUCCESS ;
822 }
823 // ===========================================================================
824 // execute the handler
825 // ===========================================================================
826 StatusCode
827 DataOnDemandSvc::execHandler(const std::string& tag, Leaf& l)
828 {
829 Gaudi::Utils::LockedChrono timer ( m_timer_algs , m_locked_algs ) ;
830 //
831 if ( l.executing ) { return StatusCode::FAILURE ; } // RETURN
832 //
833 if ( 0 == l.algorithm )
834 {
835 StatusCode sc = configureHandler ( l ) ;
836 if ( sc.isFailure() )
837 {
838 stream()
839 << MSG::ERROR
840 << "Failed to configure handler for: "
841 << l.name << "[" << l.type << "] " << tag << endmsg;
842 return sc ; // RETURN
843 }
844 }
845 //
846 Chrono atimer ( m_total ) ;
847 //
848 Protection p(l.executing);
849 StatusCode sc = l.algorithm->sysExecute();
850 if ( sc.isFailure() )
851 {
852 stream() << MSG::ERROR
853 << "Failed to execute the algorithm:"
854 << l.algorithm->name() << " for location:" << tag << endmsg;
855 return sc ; // RETURN
856 }
857 ++l.num ;
858 //
859 return StatusCode::SUCCESS ;
860 }
861 // ============================================================================
862 /* dump the content of DataOnDemand service
863 * @param level the printout level
864 * @param mode the printout mode
865 */
866 // ============================================================================
867 void DataOnDemandSvc::dump
868 ( const MSG::Level level ,
869 const bool mode ) const
870 {
871 if ( m_algs.empty() && m_nodes.empty() ) { return ; }
872
873 typedef std::pair<std::string,std::string> Pair ;
874 typedef std::map<std::string,Pair> PMap ;
875
876 PMap _m ;
877 for ( AlgMap::const_iterator alg = m_algs.begin() ;
878 m_algs.end() != alg ; ++alg )
879 {
880 PMap::const_iterator check = _m.find(alg->first) ;
881 if ( _m.end() != check )
882 {
883 stream()
884 << MSG::WARNING
885 << " The data item is activated for '"
886 << check->first << "' as '" << check->second.first << "'" << endmsg ;
887 }
888 const Leaf& l = alg->second ;
889 std::string nam = ( l.name == l.type ? l.type : (l.type+"/"+l.name) ) ;
890 //
891 if ( !mode && 0 == l.num ) { continue ; }
892 //
893 std::string val ;
894 if ( mode ) { val = ( 0 == l.algorithm ) ? "F" : "T" ; }
895 else { val = boost::lexical_cast<std::string>( l.num ) ; }
896 //
897 _m[ no_prefix ( alg->first , m_prefix ) ] = std::make_pair ( nam , val ) ;
898 }
899 // nodes:
900 for ( NodeMap::const_iterator node = m_nodes.begin() ;
901 m_nodes.end() != node ; ++node )
902 {
903 PMap::const_iterator check = _m.find(node->first) ;
904 if ( _m.end() != check )
905 {
906 stream()
907 << MSG::WARNING
908 << " The data item is already activated for '"
909 << check->first << "' as '" << check->second.first << "'" << endmsg ;
910 }
911 const Node& n = node->second ;
912 std::string nam = "'" + n.name + "'" ;
913 //
914 std::string val ;
915
916 if ( !mode && 0 == n.num ) { continue ; }
917
918 if ( mode ) { val = ( 0 == n.clazz ) ? "F" : "T" ; }
919 else { val = boost::lexical_cast<std::string>( n.num ) ; }
920 //
921 _m[ no_prefix ( node->first , m_prefix ) ] = std::make_pair ( nam , val ) ;
922 }
923 //
924 if ( _m.empty() ) { return ; }
925
926 // find the correct formats
927 size_t n1 = 0 ;
928 size_t n2 = 0 ;
929 size_t n3 = 0 ;
930 for ( PMap::const_iterator it = _m.begin() ; _m.end() != it ; ++it )
931 {
932 n1 = std::max ( n1 , it->first.size() ) ;
933 n2 = std::max ( n2 , it->second.first.size() ) ;
934 n3 = std::max ( n3 , it->second.second.size() ) ;
935 }
936 if ( 10 > n1 ) { n1 = 10 ; }
937 if ( 10 > n2 ) { n2 = 10 ; }
938 if ( 60 < n1 ) { n1 = 60 ; }
939 if ( 60 < n2 ) { n2 = 60 ; }
940 //
941
942 const std::string _f = " | %%1$-%1%.%1%s | %%2$-%2%.%2%s | %%3$%3%.%3%s |" ;
943 boost::format _ff ( _f ) ;
944 _ff % n1 % n2 % n3 ;
945
946 const std::string _format = _ff.str() ;
947
948 MsgStream& msg = stream() << level ;
949
950 if ( mode ) { msg << "Data-On-Demand Actions enabled for:" ; }
951 else { msg << "Data-On-Demand Actions has been used for:" ; }
952
953 boost::format fmt1( _format) ;
954 fmt1 % "Address" % "Creator" % ( mode ? "S" : "#" ) ;
955 //
956 const std::string header = fmt1.str() ;
957 std::string line = std::string( header.size() , '-' ) ;
958 line[0] = ' ' ;
959
960 msg << std::endl << line
961 << std::endl << header
962 << std::endl << line ;
963
964 // make the actual printout:
965 for ( PMap::const_iterator item = _m.begin() ;
966 _m.end() != item ; ++item )
967 {
968 boost::format fmt( _format) ;
969 msg << std::endl <<
970 ( fmt % item->first % item->second.first % item->second.second ) ;
971 }
972
973 msg << std::endl << line << endmsg ;
974
975 }
976 // ============================================================================
980 DECLARE_COMPONENT(DataOnDemandSvc)
981 // ============================================================================
982
983 // ============================================================================
984 // The END
985 // ============================================================================