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/AttribStringParser.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 // ============================================================================
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 // ============================================================================
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 // ============================================================================
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 // ============================================================================
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 // ============================================================================
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 
258  Leaf leaf(alg.type(), alg.name());
259  if (m_init)
260  {
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 // ============================================================================
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  }
335  //
336  return StatusCode::SUCCESS ;
337 }
338 // ============================================================================
339 // destructor
340 // ============================================================================
342 { if ( 0 != m_log ) { delete m_log ; m_log = 0 ; } }
343 //=============================================================================
344 // Inherited Service overrides:
345 //=============================================================================
347 {
348  // initialize the Service Base class
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 // ============================================================================
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
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
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
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
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  {
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.
409  for(std::list<IDODNodeMapper*>::iterator i = m_nodeMappers.begin(); i != m_nodeMappers.end(); ++i)
411  for(std::list<IDODAlgMapper*>::iterator i = m_algMappers.begin(); i != m_algMappers.end(); ++i)
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 // ============================================================================
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)
437  m_nodeMappers.clear();
438  for(std::list<IDODAlgMapper*>::iterator i = m_algMappers.begin(); i != m_algMappers.end(); ++i)
440  m_algMappers.clear();
441  m_toolSvc.reset();
442  if ( 0 != m_log ) { delete m_log ; m_log = 0 ; }
443  //
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 // ============================================================================
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  }
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 // ============================================================================
510 {
511  std::string nam, typ, tag;
513  // Setup for node leafs, where simply a constructor is called...
514  for (auto node: m_nodeMapping)
515  {
516  using Parser = Gaudi::Utils::AttribStringParser;
517  for (auto attrib: Parser(node)) {
518  switch( ::toupper(attrib.tag[0]) ) {
519  case 'D':
520  tag = std::move(attrib.value);
521  break;
522  case 'T':
523  nam = std::move(attrib.value);
524  break;
525  }
526  }
527  if ( m_algMap .end () != m_algMap .find ( tag ) ||
528  m_nodeMap .end () != m_nodeMap .find ( tag ) )
529  {
530  stream()
531  << MSG::WARNING
532  << "The obsolete property 'Nodes' redefines the action for '"
533  + tag + "' to be '" +nam+"'"
534  << endmsg ;
535  }
536  m_nodeMap[tag] = nam ;
537  }
538  //
539  m_updateRequired = true ;
540  //
541  return sc;
542 }
543 // ============================================================================
544 // setup algorithm handlers
545 // ============================================================================
547 {
548  std::string typ, tag;
549 
550  for (auto alg: m_algMapping)
551  {
552  using Parser = Gaudi::Utils::AttribStringParser;
553  for (auto attrib: Parser(alg)) {
554  switch( ::toupper(attrib.tag[0]) ) {
555  case 'D':
556  tag = std::move(attrib.value);
557  break;
558  case 'T':
559  typ = std::move(attrib.value);
560  break;
561  }
562  }
564  if ( m_algMap .end () != m_algMap .find ( tag ) ||
565  m_nodeMap .end () != m_nodeMap .find ( tag ) )
566  {
567  stream()
568  << MSG::WARNING
569  << "The obsolete property 'Algorithms' redefines the action for '"
570  + tag + "' to be '" +item.type() +"/"+item.name()+"'"
571  << endmsg ;
572  }
573  m_algMap[tag] = item.type() + "/" + item.name() ;
574  }
575  m_updateRequired = true ;
576  return StatusCode::SUCCESS;
577 }
578 // ============================================================================
580 // ============================================================================
582 {
583  if ( 0 != l.algorithm ) { return StatusCode::SUCCESS ; }
584  if ( 0 == m_algMgr ) { return StatusCode::FAILURE ; }
585  l.algorithm = m_algMgr->algorithm(l.name, false);
586  if ( 0 != l.algorithm ) { return StatusCode::SUCCESS ; }
587  // create it!
588  StatusCode sc = m_algMgr->createAlgorithm ( l.type , l.name , l.algorithm , true ) ;
589  if ( sc.isFailure() )
590  {
591  stream()
592  << MSG::ERROR
593  << "Failed to create algorithm "
594  << l.type << "('" << l.name<< "')" << endmsg;
595  l.algorithm = 0 ;
596  return sc ; // RETURN
597  }
598  if ( l.algorithm->isInitialized() ) { return StatusCode:: SUCCESS ;}
599  // initialize it!
600  sc = l.algorithm -> sysInitialize () ;
601  if ( sc.isFailure() )
602  {
603  stream()
604  << MSG::ERROR
605  << "Failed to initialize algorithm "
606  << l.type << "('" << l.name<< "')" << endmsg;
607  l.algorithm = 0 ;
608  return sc ; // RETURN
609  }
611  { return StatusCode::SUCCESS ; }
612  // run it!
613  sc = l.algorithm->sysStart() ;
614  if ( sc.isFailure() )
615  {
616  stream()
617  << MSG::ERROR
618  << "Failed to 'run' algorithm "
619  << l.type << "('" << l.name<< "')" << endmsg;
620  l.algorithm = 0 ;
621  return sc ; // RETURN
622  }
623  return StatusCode::SUCCESS ;
624 }
625 
626 // local algorithms
627 namespace {
630  struct ToolGetter {
632  std::string path;
634  ToolGetter(const std::string &_path): path(_path) {}
636  inline std::string operator() (IDODNodeMapper *t) const {
637  return t->nodeTypeForPath(path);
638  }
640  inline Gaudi::Utils::TypeNameString operator() (IDODAlgMapper *t) const {
641  return t->algorithmForPath(path);
642  }
643  };
644 
647  inline bool isGood(const std::string& r) {return !r.empty();}
648  inline bool isGood(const Gaudi::Utils::TypeNameString& r) {return !r.name().empty();}
650 
653  class Finder {
654  const ToolGetter getter;
655  const std::list<IDODNodeMapper*> &nodes;
656  const std::list<IDODAlgMapper*> &algs;
658  template <class R, class T>
659  R find(const std::list<T*> &l) const {
660  typename std::list<T*>::const_iterator i;
661  for(i = l.begin(); i != l.end(); ++i) {
662  R result = getter(*i);
663  if (isGood(result)) return result;
664  }
665  return R("");
666  }
667  public:
669  Finder(const std::string &_path,
670  const std::list<IDODNodeMapper*> &_nodes,
671  const std::list<IDODAlgMapper*> &_algs): getter(_path), nodes(_nodes), algs(_algs) {
672  }
674  inline std::string node() const {
675  return find<std::string>(nodes);
676  }
678  inline Gaudi::Utils::TypeNameString alg() const {
679  return find<Gaudi::Utils::TypeNameString>(algs);
680  }
681 
682  };
683 
684 }
685 
686 // ===========================================================================
687 // IIncidentListener interfaces overrides: incident handling
688 // ===========================================================================
689 void DataOnDemandSvc::handle ( const Incident& incident )
690 {
691 
693 
694  ++m_stat ;
695  // proper incident type?
696  if ( incident.type() != m_trapType ) { return ; } // RETURN
697  const DataIncident* inc = dynamic_cast<const DataIncident*>(&incident);
698  if ( 0 == inc ) { return ; } // RETURN
699  // update if needed!
700  if ( m_updateRequired ) { update() ; }
701 
702  if ( MSG::VERBOSE >= outputLevel() )
703  {
704  verbose()
705  << "Incident: [" << incident.type () << "] "
706  << " = " << incident.source ()
707  << " Location:" << inc->tag() << endmsg;
708  }
709  // ==========================================================================
710  // const std::string& tag = inc->tag();
711  Gaudi::StringKey tag ( inc->tag() ) ;
712  // ==========================================================================
713  NodeMap::iterator icl = m_nodes.find ( tag ) ;
714  if ( icl != m_nodes.end() )
715  {
716  StatusCode sc = execHandler ( tag , icl->second ) ;
717  if ( sc.isSuccess() ) { ++m_statNode ; }
718  return ; // RETURN
719  }
720  // ==========================================================================
721  AlgMap::iterator ialg = m_algs.find ( tag ) ;
722  if ( ialg != m_algs.end() )
723  {
724  StatusCode sc = execHandler ( tag , ialg->second ) ;
725  if ( sc.isSuccess() ) { ++m_statAlg ; }
726  return ; // RETURN
727  }
728  // ==========================================================================
729  // Fall back on the tools
730  if (m_toolSvc) {
731  if (MSG::VERBOSE >= outputLevel())
732  verbose() << "Try to find mapping with mapping tools" << endmsg;
733  Finder finder(no_prefix(inc->tag(), m_prefix), m_nodeMappers, m_algMappers);
734  // - try the node mappers
735  std::string node = finder.node();
736  if (isGood(node)) {
737  // if one is found update the internal node mapping and try again.
738  if (MSG::VERBOSE >= outputLevel())
739  verbose() << "Found Node handler: " << node << endmsg;
740  i_setNodeHandler(inc->tag(), node);
741  handle(incident);
742  --m_stat; // avoid double counting because of recursion
743  return;
744  }
745  // - try alg mappings
746  Gaudi::Utils::TypeNameString alg = finder.alg();
747  if (isGood(alg)) {
748  // we got an algorithm, update alg map and try to handle again
749  if (MSG::VERBOSE >= outputLevel())
750  verbose() << "Found Algorithm handler: " << alg << endmsg;
751  i_setAlgHandler(inc->tag(), alg).ignore();
752  handle(incident);
753  --m_stat; // avoid double counting because of recursion
754  return;
755  }
756  }
757 }
758 // ===========================================================================
759 // execute the handler
760 // ===========================================================================
762 DataOnDemandSvc::execHandler ( const std::string& tag, Node& n)
763 {
764 
766 
767  if ( n.executing ) { return StatusCode::FAILURE ; } // RETURN
768 
769  Protection p(n.executing);
770 
771  DataObject* object= 0 ;
772 
773  if ( n.dataObject ) { object = new DataObject() ; }
774  else
775  {
776  // try to recover the handler
777  if ( !n.clazz ) { n.clazz = TClass::GetClass(n.name.c_str()) ; }
778  if ( !n.clazz )
779  {
780  stream()
781  << MSG::ERROR
782  << "Failed to get dictionary for class '"
783  << n.name
784  << "' for location:" << tag << endmsg;
785  return StatusCode::FAILURE ; // RETURN
786  }
787 
788  object = reinterpret_cast<DataObject*>(n.clazz->New());
789 
790  if ( !object )
791  {
792  stream()
793  << MSG::ERROR
794  << "Failed to create an object of type:"
795  << n.clazz->GetName() << " for location:" << tag
796  << endmsg;
797  return StatusCode::FAILURE ; // RETURN
798  }
799  }
800  //
801  StatusCode sc = m_dataSvc->registerObject(tag, object );
802  if ( sc.isFailure() )
803  {
804  stream()
805  << MSG::ERROR << "Failed to register an object of type:"
806  << n.name << " at location:" << tag
807  << endmsg;
808  return sc ; // RETURN
809  }
810  ++n.num ;
811  //
812  return StatusCode::SUCCESS ;
813 }
814 // ===========================================================================
815 // execute the handler
816 // ===========================================================================
818 DataOnDemandSvc::execHandler(const std::string& tag, Leaf& l)
819 {
821  //
822  if ( l.executing ) { return StatusCode::FAILURE ; } // RETURN
823  //
824  if ( 0 == l.algorithm )
825  {
826  StatusCode sc = configureHandler ( l ) ;
827  if ( sc.isFailure() )
828  {
829  stream()
830  << MSG::ERROR
831  << "Failed to configure handler for: "
832  << l.name << "[" << l.type << "] " << tag << endmsg;
833  return sc ; // RETURN
834  }
835  }
836  //
837  Chrono atimer ( m_total ) ;
838  //
839  Protection p(l.executing);
841  if ( sc.isFailure() )
842  {
843  stream() << MSG::ERROR
844  << "Failed to execute the algorithm:"
845  << l.algorithm->name() << " for location:" << tag << endmsg;
846  return sc ; // RETURN
847  }
848  ++l.num ;
849  //
850  return StatusCode::SUCCESS ;
851 }
852 // ============================================================================
853 /* dump the content of DataOnDemand service
854  * @param level the printout level
855  * @param mode the printout mode
856  */
857 // ============================================================================
859 ( const MSG::Level level ,
860  const bool mode ) const
861 {
862  if ( m_algs.empty() && m_nodes.empty() ) { return ; }
863 
864  typedef std::pair<std::string,std::string> Pair ;
865  typedef std::map<std::string,Pair> PMap ;
866 
867  PMap _m ;
868  for ( AlgMap::const_iterator alg = m_algs.begin() ;
869  m_algs.end() != alg ; ++alg )
870  {
871  PMap::const_iterator check = _m.find(alg->first) ;
872  if ( _m.end() != check )
873  {
874  stream()
875  << MSG::WARNING
876  << " The data item is activated for '"
877  << check->first << "' as '" << check->second.first << "'" << endmsg ;
878  }
879  const Leaf& l = alg->second ;
880  std::string nam = ( l.name == l.type ? l.type : (l.type+"/"+l.name) ) ;
881  //
882  if ( !mode && 0 == l.num ) { continue ; }
883  //
884  std::string val ;
885  if ( mode ) { val = ( 0 == l.algorithm ) ? "F" : "T" ; }
886  else { val = boost::lexical_cast<std::string>( l.num ) ; }
887  //
888  _m[ no_prefix ( alg->first , m_prefix ) ] = std::make_pair ( nam , val ) ;
889  }
890  // nodes:
891  for ( NodeMap::const_iterator node = m_nodes.begin() ;
892  m_nodes.end() != node ; ++node )
893  {
894  PMap::const_iterator check = _m.find(node->first) ;
895  if ( _m.end() != check )
896  {
897  stream()
898  << MSG::WARNING
899  << " The data item is already activated for '"
900  << check->first << "' as '" << check->second.first << "'" << endmsg ;
901  }
902  const Node& n = node->second ;
903  std::string nam = "'" + n.name + "'" ;
904  //
905  std::string val ;
906 
907  if ( !mode && 0 == n.num ) { continue ; }
908 
909  if ( mode ) { val = ( 0 == n.clazz ) ? "F" : "T" ; }
910  else { val = boost::lexical_cast<std::string>( n.num ) ; }
911  //
912  _m[ no_prefix ( node->first , m_prefix ) ] = std::make_pair ( nam , val ) ;
913  }
914  //
915  if ( _m.empty() ) { return ; }
916 
917  // find the correct formats
918  size_t n1 = 0 ;
919  size_t n2 = 0 ;
920  size_t n3 = 0 ;
921  for ( PMap::const_iterator it = _m.begin() ; _m.end() != it ; ++it )
922  {
923  n1 = std::max ( n1 , it->first.size() ) ;
924  n2 = std::max ( n2 , it->second.first.size() ) ;
925  n3 = std::max ( n3 , it->second.second.size() ) ;
926  }
927  if ( 10 > n1 ) { n1 = 10 ; }
928  if ( 10 > n2 ) { n2 = 10 ; }
929  if ( 60 < n1 ) { n1 = 60 ; }
930  if ( 60 < n2 ) { n2 = 60 ; }
931  //
932 
933  const std::string _f = " | %%1$-%1%.%1%s | %%2$-%2%.%2%s | %%3$%3%.%3%s |" ;
934  boost::format _ff ( _f ) ;
935  _ff % n1 % n2 % n3 ;
936 
937  const std::string _format = _ff.str() ;
938 
939  MsgStream& msg = stream() << level ;
940 
941  if ( mode ) { msg << "Data-On-Demand Actions enabled for:" ; }
942  else { msg << "Data-On-Demand Actions has been used for:" ; }
943 
944  boost::format fmt1( _format) ;
945  fmt1 % "Address" % "Creator" % ( mode ? "S" : "#" ) ;
946  //
947  const std::string header = fmt1.str() ;
948  std::string line = std::string( header.size() , '-' ) ;
949  line[0] = ' ' ;
950 
951  msg << std::endl << line
952  << std::endl << header
953  << std::endl << line ;
954 
955  // make the actual printout:
956  for ( PMap::const_iterator item = _m.begin() ;
957  _m.end() != item ; ++item )
958  {
959  boost::format fmt( _format) ;
960  msg << std::endl <<
961  ( fmt % item->first % item->second.first % item->second.second ) ;
962  }
963 
964  msg << std::endl << line << endmsg ;
965 
966 }
967 // ============================================================================
972 // ============================================================================
973 
974 // ============================================================================
975 // The END
976 // ============================================================================
void i_setNodeHandler(const std::string &name, const std::string &type)
Internal method to initialize a node handler.
virtual SmartIF< IAlgorithm > & algorithm(const Gaudi::Utils::TypeNameString &typeName, const bool createIf=true)=0
Returns a smart pointer to a service.
ChronoEntity m_timer_all
Definition of the MsgStream class used to transmit messages.
Definition: MsgStream.h:24
MsgStream & verbose() const
shortcut for the method msgStream(MSG::VERBOSE)
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:26
const std::string & type() const
Access to the incident type.
Definition: Incident.h:34
The DataOnDemandSvc listens to incidents typically triggered by the data service of the configurable ...
virtual StatusCode sysStart()=0
Startup method invoked by the framework.
ChronoEntity m_timer_algs
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:244
std::list< IDODNodeMapper * > m_nodeMappers
const std::string & source() const
Access to the source of the incident.
Definition: Incident.h:40
MsgStream * m_log
bool isSuccess() const
Test for a status code of SUCCESS.
Definition: StatusCode.h:75
MsgStream & stream() const
get the message stream
SmartIF< IIncidentSvc > m_incSvc
Incident service.
virtual StatusCode reinitialize()
Inherited Service overrides: Service reinitialization.
list path
Definition: __init__.py:15
int outputLevel() const
get the Service's output level
Definition: Service.h:251
MsgStream & warning() const
shortcut for the method msgStream(MSG::WARNING)
std::vector< std::string > m_algMapTools
std::string m_trapType
Trap name.
std::string m_dataSvcName
Data service name.
Setup m_nodeMapping
Mapping to nodes.
return false
Definition: Bootstrap.cpp:338
A small utility class for chronometry of user codes.
Definition: Chrono.h:27
Map m_algMap
the major configuration property { 'data' : 'algorithm' }
#define SET(x)
bool isFailure() const
Test for a status code of FAILURE.
Definition: StatusCode.h:85
The helper class to represent the efficient "key" for access.
Definition: StringKey.h:35
virtual StatusCode sysExecute()=0
System execution. This method invokes the execute() method of a concrete algorithm.
virtual StatusCode initialize()
Inherited Service overrides: Service initialization.
virtual const std::string & name() const =0
Retrieve the name of the instance.
SmartIF< IDataProviderSvc > m_dataSvc
Data provider reference.
ulonglong m_statNode
virtual StatusCode createAlgorithm(const std::string &algtype, const std::string &algname, IAlgorithm *&alg, bool managed=false)=0
Create an instance of a algorithm type that has been declared beforehand and assigns to it a name...
StatusCode service(const Gaudi::Utils::TypeNameString &name, T *&svc, bool createIf=true)
Templated method to access a service by name.
Definition: ISvcLocator.h:82
ClassH clazz
the actual class
std::list< IDODAlgMapper * > m_algMappers
Interface of tools used by the DataOnDemandSvc to choose the type of node to be created at a path...
Setup m_algMapping
Mapping to algorithms.
iterator end()
Definition: Map.h:131
Helper class to parse a string of format "type/name".
Definition: TypeNameString.h:9
StatusCode setup()
Setup routine (called by (re-) initialize.
virtual void handle(const Incident &incident)
IIncidentListener interfaces overrides: incident handling.
bool m_allowInitFailure
flag to allow DataOnDemand initialization to succeed even if the (pre)initialization of the algorithm...
virtual Gaudi::StateMachine::State FSMState() const =0
Get the current state.
#define DECLARE_COMPONENT(type)
Definition: PluginService.h:36
StatusCode execHandler(const std::string &tag, Leaf &leaf)
Execute leaf handler (algorithm)
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:30
void update_dump(Property &)
update handler for 'Dump' property
StatusCode setupNodeHandlers()
Initialize node handlers.
iterator find(const key_type &key)
Definition: Map.h:148
Helper class of the DataOnDemandSvc.
virtual Gaudi::Utils::TypeNameString algorithmForPath(const std::string &path)=0
For the given path, returns a TypeNameString object identifying the algorithm to be run to produce th...
std::vector< std::string > m_nodeMapTools
NodeMap m_nodes
Map of "empty" objects to be placed as intermediate nodes.
std::string m_prefix
void dump(const MSG::Level level, const bool mode=true) const
dump the content of DataOnDemand service
map_type::const_iterator const_iterator
Definition: Map.h:99
virtual Gaudi::StateMachine::State FSMState() const
Get the current state.
Definition: Service.h:56
virtual const std::string & name() const
Retrieve name of the service.
Definition: Service.cpp:329
void reset(TYPE *ptr=0)
Set the internal pointer to the passed one disposing of the old one.
Definition: SmartIF.h:74
virtual StatusCode sysInitialize()
Initialize Service.
Definition: Service.cpp:35
tuple end
Definition: IOTest.py:101
dictionary l
Definition: gaudirun.py:420
bool m_partialPath
Flag to allow for the creation of partial leaves.
virtual StatusCode reinitialize()
Initialization (from INITIALIZED or RUNNING to INITIALIZED, via CONFIGURED).
Definition: Service.cpp:292
std::string outputUserTime() const
print the chrono ;
Interface of tools used by the DataOnDemandSvc to choose the algorithm to be run to produce the data ...
Definition: IDODAlgMapper.h:17
Property base class allowing Property* collections to be "homogeneous".
Definition: Property.h:43
map_type::iterator iterator
Definition: Map.h:98
SmartIF< IAlgManager > m_algMgr
Algorithm manager.
virtual StatusCode initialize()
Initialization (from CONFIGURED to INITIALIZED).
Definition: Service.cpp:72
SmartIF< IToolSvc > m_toolSvc
Data provider reference.
Helper object, useful for measurement of CPU-performance of highly-recursive structures, e.g.
Definition: LockedChrono.h:54
AlgMap m_algs
Map of algorithms to handle incidents.
bool m_dump
flag to force the printout
bool m_init
flag to warm up the configuration
const std::string & type() const
ChronoEntity m_timer_nodes
Base class for all Incidents (computing events).
Definition: Incident.h:16
virtual void addListener(IIncidentListener *lis, const std::string &type="", long priority=0, bool rethrow=false, bool singleShot=false)=0
Add listener.
bool dataObject
trivial object? DataObject?
DataOnDemandSvc(const std::string &name, ISvcLocator *svc)
Standard initializing service constructor.
tuple item
print s1,s2
Definition: ana.py:146
Templated class to add the standard messaging functionalities.
void clear()
Definition: Map.h:176
virtual StatusCode finalize()
Inherited Service overrides: Service finalization.
StatusCode service(const std::string &name, const T *&psvc, bool createIf=true) const
Access a service by name, creating it if it doesn't already exist.
Definition: Service.h:143
virtual StatusCode releaseTool(IAlgTool *tool)=0
Release the tool.
ChronoEntity m_total
virtual bool isInitialized() const =0
check if the algorithm is initialized properly
Map m_nodeMap
the major configuration property { 'data' : 'type' }
virtual void removeListener(IIncidentListener *lis, const std::string &type="")=0
Remove listener.
Data service incident class.
const std::string & name() const
void ignore() const
Definition: StatusCode.h:107
list header
Definition: Test.py:33
StatusCode setupAlgHandlers()
Initialize leaf handlers.
Helper class of the DataOnDemandSvc.
virtual std::string nodeTypeForPath(const std::string &path)=0
For the given path, returns a the type name of the object to be created at the path.
virtual StatusCode registerObject(const std::string &fullPath, DataObject *pObject)=0
Register object with the data store.
virtual ~DataOnDemandSvc()
Standard destructor.
A DataObject is the base class of any identifiable object on any data store.
Definition: DataObject.h:31
list i
Definition: ana.py:128
StatusCode i_setAlgHandler(const std::string &name, const Gaudi::Utils::TypeNameString &alg)
Internal method to initialize an algorithm handler.
StatusCode configureHandler(Leaf &leaf)
Configure handler for leaf.
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
void update_2(Property &p)
void toupper(std::string &s)
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
Definition: MsgStream.cpp:133
virtual StatusCode finalize()
Finalize (from INITIALIZED to CONFIGURED).
Definition: Service.cpp:197
StatusCode retrieveTool(const std::string &type, T *&tool, const IInterface *parent=0, bool createIf=true)
Retrieve specified tool sub-type with tool dependent part of the name automatically assigned...
Definition: IToolSvc.h:141
void update_3(Property &p)
void update_1(Property &p)
StatusCode update()
update the handlers
int line
Definition: ana.py:50
string type
Definition: gaudirun.py:151
SmartIF< ISvcLocator > & serviceLocator() const
Retrieve pointer to service locator.
Definition: Service.cpp:334