All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules 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/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 #include "GaudiKernel/Property.h"
28 // ============================================================================
29 // Local
30 // ============================================================================
31 #include "DataOnDemandSvc.h"
32 // ============================================================================
33 // Boost
34 // ============================================================================
35 #include "boost/format.hpp"
36 #include "boost/algorithm/string/predicate.hpp"
37 // ============================================================================
38 // Constructors and Destructor
39 // ============================================================================
41 ( const std::string& name, ISvcLocator* svc )
42  : base_class( name, svc )
43 {
44  // ==========================================================================
45  declareProperty
46  ( "IncidentName" ,
47  m_trapType ,
48  "The type of handled Incident" ) ;
49  //
50  declareProperty ( "DataSvc" , m_dataSvcName ) ;
51  //
52  declareProperty ( "UsePreceedingPath" , m_partialPath ) ;
53  declareProperty
54  ( "Dump" ,
55  m_dump ,
56  "Dump the configuration and stastics" ) ->
57  declareUpdateHandler ( &DataOnDemandSvc::update_dump , this ) ;
58  //
59  declareProperty
60  ( "PreInitialize" ,
61  m_init ,
62  "Flag to (pre)initialize all algorithms" ) ;
63  declareProperty
64  ( "AllowPreInitializeFailure" ,
65  m_allowInitFailure ,
66  "Allow (pre)initialization of algorithms to fail without stopping the application" ) ;
67  //
68  declareProperty ( "Algorithms" , m_algMapping ) ->
69  declareUpdateHandler ( &DataOnDemandSvc::update_2 , this ) ;
70  declareProperty ( "Nodes" , m_nodeMapping ) ->
71  declareUpdateHandler ( &DataOnDemandSvc::update_3 , this ) ;
72  //
73  declareProperty ( "AlgMap" , m_algMap ) ->
74  declareUpdateHandler ( &DataOnDemandSvc::update_1 , this ) ;
75  declareProperty ( "NodeMap" , m_nodeMap ) ->
76  declareUpdateHandler ( &DataOnDemandSvc::update_1 , this ) ;
77 
78  declareProperty ( "Prefix" , m_prefix ) ;
79 
80  declareProperty("NodeMappingTools", m_nodeMapTools,
81  "List of tools of type IDODNodeMapper");
82  declareProperty("AlgMappingTools", m_algMapTools,
83  "List of tools of type IDODAlgMapper");
84  // ==========================================================================
85 }
86 // ============================================================================
87 // Update handler
88 // ============================================================================
90 {
91  stream() << MSG::VERBOSE << " I am update handler for property " << p << endmsg ;
92  // force update
93  m_updateRequired = true ;
94 }
95 // ============================================================================
96 // Update handler
97 // ============================================================================
99 {
100  stream() << MSG::WARNING
101  << "The property 'Nodes' is obsolete, switch to map-like 'NodeMap' "
102  << " = { 'data' : 'type' } "
103  << endmsg ;
104  // force update
105  m_updateRequired = true ;
106 }
107 // ============================================================================
108 // Update handler
109 // ============================================================================
111 {
112  stream() << MSG::WARNING
113  << "The property 'Algorithms' is obsolete, switch to map-like 'AlgMap' "
114  << " = { 'data' : 'algorithm' } "
115  << endmsg ;
116  // force update
117  m_updateRequired = true ;
118 }
119 // ============================================================================
120 // Update handler
121 // ============================================================================
123 {
124  // no action if not yet initialized
125  if ( FSMState() < Gaudi::StateMachine::INITIALIZED ) { return ; }
126  // dump the configuration:
127  if ( m_dump ) { dump ( MSG::ALWAYS ) ; }
128 }
129 // ============================================================================
130 // anonymous namespace to hide few local functions
131 // ============================================================================
132 namespace
133 {
134  // ==========================================================================
140  inline std::string no_prefix
141  ( const std::string& value ,
142  const std::string& prefix )
143  {
144  return boost::algorithm::starts_with(value,prefix) ?
145  value.substr( prefix.size() ) : value ;
146  }
147  // ==========================================================================
154  template <class MAP>
155  inline size_t add_prefix ( MAP& _map , const std::string& prefix )
156  {
157  // empty prefix
158  if ( prefix.empty() ) { return 0 ; } // RETURN
160  auto it = std::find_if_not( _map.begin(), _map.end(),
161  [&](typename MAP::const_reference i) {
162  return boost::algorithm::starts_with(i.first,prefix);
163  } );
164  if ( it == _map.end() ) return 0 ;
165  std::string key = prefix + it->first ;
166  std::string value = std::move(it->second); // steal the value we're about to erase..
167  _map.erase ( it ) ;
168  _map[ key ] = std::move(value); // and move it into its new location
169  return 1 + add_prefix ( _map , prefix ) ; // RETURN, recursion
170  //
171  }
172  // ==========================================================================
178  template <class SET>
179  inline size_t get_dir ( const std::string& object , SET& _set )
180  {
181  std::string::size_type ifind = object.rfind('/') ;
182  // stop recursion
183  if ( std::string::npos == ifind ) { return 0 ; } // RETURN
184  if ( 0 == ifind ) { return 0 ; }
185  //
186  const std::string top = std::string( object , 0 , ifind) ;
187  _set.insert( top ) ;
188  return 1 + get_dir ( top , _set ) ; // RETURN, recursion
189  }
190  // ==========================================================================
196  template <class MAP, class SET>
197  inline size_t get_dirs ( const MAP& _map, SET& _set )
198  {
199  size_t size = _set.size() ;
200  for ( const auto& item : _map )
201  { get_dir ( item.first , _set ) ; }
202  return _set.size() - size ;
203  }
204  // ==========================================================================
205 } // end of anonymous namespace
206 
207 void DataOnDemandSvc::i_setNodeHandler(const std::string &name, const std::string &type){
208  ClassH cl = TClass::GetClass(type.c_str()) ;
209  if (!cl) {
210  warning()
211  << "Failed to access dictionary class for "
212  << name << " of type:" << type << endmsg;
213  }
214  m_nodes[name] = Node(cl, false, type);
215 }
216 
218  Leaf leaf(alg.type(), alg.name());
219  if (m_init)
220  {
222  if (sc.isFailure()) {
223  if (m_allowInitFailure) {
224  // re-store the content of the leaf object to try again to initialize
225  // the algorithm later (on demand)
226  leaf = Leaf(alg.type(), alg.name());
227  }
228  else
229  return sc;
230  }
231  }
232  m_algs[name] = leaf;
233  return StatusCode::SUCCESS;
234 }
235 
236 // ============================================================================
237 // update the content of Data-On-Demand actions
238 // ============================================================================
240 {
241  if ( !m_updateRequired ) { return StatusCode::SUCCESS ; }
242 
244  StatusCode sc = setupNodeHandlers() ; // convert "Nodes" new "NodeMap"
245  if ( sc.isFailure() )
246  {
247  stream() << MSG::ERROR << "Failed to setup old \"Nodes\"" << endmsg ;
248  return sc ;
249  }
251  sc = setupAlgHandlers() ; // convert "Algorithms" into "AlgMap"
252  if ( sc.isFailure() )
253  {
254  stream() << MSG::ERROR << "Failed to setup old \"Algorithms\"" << endmsg ;
255  return sc ;
256  }
258  add_prefix ( m_algMap , m_prefix ) ;
260  add_prefix ( m_nodeMap , m_prefix ) ;
262  std::set<std::string> dirs ;
263  if ( m_partialPath ){ get_dirs ( m_algMap , dirs ) ; }
264  if ( m_partialPath ){ get_dirs ( m_nodeMap , dirs ) ; }
265  //
266  auto _e = dirs.find("/Event") ;
267  if ( dirs.end() != _e ) { dirs.erase( _e ) ; }
268  // add all directories as nodes
269  for ( const auto& dir : dirs )
270  {
271  if ( m_algMap .end () == m_algMap .find ( dir ) &&
272  m_nodeMap .end () == m_nodeMap .find ( dir ) )
273  m_nodeMap [dir] = "DataObject" ;
274  }
275  //
276  m_algs .clear () ;
277  m_nodes .clear () ;
278  //
280  for ( const auto& alg : m_algMap )
281  {
282  if (i_setAlgHandler(alg.first, alg.second).isFailure())
283  return StatusCode::FAILURE;
284  }
286  for ( const auto& node : m_nodeMap )
287  {
288  i_setNodeHandler(node.first, node.second);
289  }
291  m_updateRequired = false ;
292  //
293  return StatusCode::SUCCESS ;
294 }
295 //=============================================================================
296 // Inherited Service overrides:
297 //=============================================================================
299 {
300  // initialize the Service Base class
302  if ( sc.isFailure() ) { return sc; }
303  sc = setup();
304  if ( sc.isFailure() ) { return sc; }
305  //
306  if ( m_dump ) { dump ( MSG::INFO ) ; }
307  else if ( MSG::DEBUG >= outputLevel() ) { dump ( MSG::DEBUG ) ; }
308  //
309  if ( m_init ) { return update () ; }
310  //
311  return StatusCode::SUCCESS ;
312 }
313 // ============================================================================
314 // finalization of the service
315 // ============================================================================
317 {
318  //
319  stream ()
320  << MSG::INFO
321  << "Handled \"" << m_trapType << "\" incidents: "
322  << m_statAlg << "/" << m_statNode << "/" << m_stat << "(Alg/Node/Total)."
323  << endmsg ;
324  if ( m_dump || MSG::DEBUG >= outputLevel() )
325  {
326  stream ()
327  << MSG::INFO
329  ( "Algorithm timing: Mean(+-rms)/Min/Max:%3%(+-%4%)/%6%/%7%[ms] " , System::milliSec )
330  << m_total.outputUserTime ( "Total:%2%[s]" , System::Sec ) << endmsg ;
331  stream ()
332  << MSG::INFO
334  ( "Nodes timing: Mean(+-rms)/Min/Max:%3%(+-%4%)/%6%/%7%[ms] " , System::milliSec )
335  << m_timer_nodes.outputUserTime ( "Total:%2%[s]" , System::Sec ) << endmsg ;
336  stream ()
337  << MSG::INFO
339  ( "Algs timing: Mean(+-rms)/Min/Max:%3%(+-%4%)/%6%/%7%[ms] " , System::milliSec )
340  << m_timer_algs .outputUserTime ( "Total:%2%[s]" , System::Sec ) << endmsg ;
341  stream ()
342  << MSG::INFO
344  ( "All timing: Mean(+-rms)/Min/Max:%3%(+-%4%)/%6%/%7%[ms] " , System::milliSec )
345  << m_timer_all .outputUserTime ( "Total:%2%[s]" , System::Sec ) << endmsg ;
346  }
347  // dump it!
348  if ( m_dump ) { dump ( MSG::INFO , false ) ; }
349  else if ( MSG::DEBUG >= outputLevel() ) { dump ( MSG::DEBUG , false ) ; }
350  //
351  if ( m_incSvc )
352  {
354  m_incSvc.reset();
355  }
356  m_algMgr.reset();
357  m_dataSvc.reset();
358  if (m_toolSvc) { // we may not have retrieved the ToolSvc
359  // Do not call releaseTool if the ToolSvc was already finalized.
361  for(const auto& i : m_nodeMappers ) m_toolSvc->releaseTool(i).ignore();
362  for(const auto& i : m_algMappers ) m_toolSvc->releaseTool(i).ignore();
363  } else {
364  warning() << "ToolSvc already finalized: cannot release tools. Check options." << endmsg;
365  }
366  m_nodeMappers.clear();
367  m_algMappers.clear();
368  m_toolSvc.reset();
369  }
370  return Service::finalize();
371 }
372 // ============================================================================
374 // ============================================================================
376 {
377  // reinitialize the Service Base class
378  if ( m_incSvc )
379  {
380  m_incSvc -> removeListener ( this , m_trapType );
381  m_incSvc.reset();
382  }
383  m_algMgr.reset();
384  m_dataSvc.reset();
385  for(const auto& i : m_nodeMappers ) m_toolSvc->releaseTool(i).ignore();
386  m_nodeMappers.clear();
387  for(const auto& i : m_algMappers ) m_toolSvc->releaseTool(i).ignore();
388  m_algMappers.clear();
389  m_toolSvc.reset();
390  m_log.reset();
391  //
393  if ( sc.isFailure() ) { return sc; }
394  //
395  sc = setup() ;
396  if ( sc.isFailure() ) { return sc; }
397  //
398  if ( m_dump ) { dump ( MSG::INFO ) ; }
399  else if ( MSG::DEBUG >= outputLevel() ) { dump ( MSG::DEBUG ) ; }
400  //
401  return StatusCode::SUCCESS ;
402 }
403 // ============================================================================
404 // setup service
405 // ============================================================================
407 {
408  if ( !(m_algMgr = serviceLocator()) ) // assignment meant
409  {
410  error() << "Failed to retrieve the IAlgManager interface." << endmsg;
411  return StatusCode::FAILURE;
412  }
413 
414  if ( !(m_incSvc = serviceLocator()->service("IncidentSvc")) ) // assignment meant
415  {
416  error() << "Failed to retrieve Incident service." << endmsg;
417  return StatusCode::FAILURE;
418  }
420 
421  if ( !(m_dataSvc = serviceLocator()->service(m_dataSvcName)) ) // assignment meant
422  {
423  error()
424  << "Failed to retrieve the data provider interface of "
425  << m_dataSvcName << endmsg;
426  return StatusCode::FAILURE;
427  }
428 
429  // No need to get the ToolSvc if we are not using tools
430  if (!(m_nodeMapTools.empty() && m_algMapTools.empty())) {
431  if ( !(m_toolSvc = serviceLocator()->service("ToolSvc")) ) // assignment meant
432  {
433  error() << "Failed to retrieve ToolSvc" << endmsg;
434  return StatusCode::FAILURE;
435  }
436 
437  // load the node mapping tools
438  IDODNodeMapper *nodetool = nullptr;
439  for(const auto& i : m_nodeMapTools) {
440  const StatusCode sc = m_toolSvc->retrieveTool(i, nodetool);
441  if (sc.isFailure()) return sc;
442  m_nodeMappers.push_back(nodetool);
443  }
444  IDODAlgMapper *algtool = nullptr;
445  for(const auto& i : m_algMapTools) {
446  const StatusCode sc = m_toolSvc->retrieveTool(i, algtool);
447  if (sc.isFailure()) return sc;
448  m_algMappers.push_back(algtool);
449  }
450  }
451  return update();
452 }
453 // ============================================================================
454 // setup node handlers
455 // ============================================================================
457 {
458  std::string nam, typ, tag;
460  // Setup for node leafs, where simply a constructor is called...
461  for (auto node: m_nodeMapping)
462  {
463  using Parser = Gaudi::Utils::AttribStringParser;
464  for (auto attrib: Parser(node)) {
465  switch( ::toupper(attrib.tag[0]) ) {
466  case 'D':
467  tag = std::move(attrib.value);
468  break;
469  case 'T':
470  nam = std::move(attrib.value);
471  break;
472  }
473  }
474  if ( m_algMap .end () != m_algMap .find ( tag ) ||
475  m_nodeMap .end () != m_nodeMap .find ( tag ) )
476  {
477  stream()
478  << MSG::WARNING
479  << "The obsolete property 'Nodes' redefines the action for '"
480  + tag + "' to be '" +nam+"'"
481  << endmsg ;
482  }
483  m_nodeMap[tag] = nam ;
484  }
485  //
486  m_updateRequired = true ;
487  //
488  return sc;
489 }
490 // ============================================================================
491 // setup algorithm handlers
492 // ============================================================================
494 {
495  std::string typ, tag;
496 
497  for (auto alg: m_algMapping)
498  {
499  using Parser = Gaudi::Utils::AttribStringParser;
500  for (auto attrib: Parser(alg)) {
501  switch( ::toupper(attrib.tag[0]) ) {
502  case 'D':
503  tag = std::move(attrib.value);
504  break;
505  case 'T':
506  typ = std::move(attrib.value);
507  break;
508  }
509  }
511  if ( m_algMap .end () != m_algMap .find ( tag ) ||
512  m_nodeMap .end () != m_nodeMap .find ( tag ) )
513  {
514  stream()
515  << MSG::WARNING
516  << "The obsolete property 'Algorithms' redefines the action for '"
517  + tag + "' to be '" +item.type() +"/"+item.name()+"'"
518  << endmsg ;
519  }
520  m_algMap[tag] = item.type() + "/" + item.name() ;
521  }
522  m_updateRequired = true ;
523  return StatusCode::SUCCESS;
524 }
525 // ============================================================================
527 // ============================================================================
529 {
530  if ( l.algorithm ) { return StatusCode::SUCCESS ; }
531  if ( ! m_algMgr ) { return StatusCode::FAILURE ; }
532  l.algorithm = m_algMgr->algorithm(l.name, false);
533  if ( l.algorithm ) { return StatusCode::SUCCESS ; }
534  // create it!
535  StatusCode sc = m_algMgr->createAlgorithm ( l.type , l.name , l.algorithm , true ) ;
536  if ( sc.isFailure() )
537  {
538  stream()
539  << MSG::ERROR
540  << "Failed to create algorithm "
541  << l.type << "('" << l.name<< "')" << endmsg;
542  l.algorithm = nullptr ;
543  return sc ; // RETURN
544  }
545  if ( l.algorithm->isInitialized() ) { return StatusCode:: SUCCESS ;}
546  // initialize it!
547  sc = l.algorithm -> sysInitialize () ;
548  if ( sc.isFailure() )
549  {
550  stream()
551  << MSG::ERROR
552  << "Failed to initialize algorithm "
553  << l.type << "('" << l.name<< "')" << endmsg;
554  l.algorithm = nullptr ;
555  return sc ; // RETURN
556  }
557  if ( Gaudi::StateMachine::RUNNING == l.algorithm->FSMState() )
558  { return StatusCode::SUCCESS ; }
559  // run it!
560  sc = l.algorithm->sysStart() ;
561  if ( sc.isFailure() )
562  {
563  stream()
564  << MSG::ERROR
565  << "Failed to 'run' algorithm "
566  << l.type << "('" << l.name<< "')" << endmsg;
567  l.algorithm = nullptr ;
568  return sc ; // RETURN
569  }
570  return StatusCode::SUCCESS ;
571 }
572 
573 // local algorithms
574 namespace {
577  struct ToolGetter {
579  std::string path;
581  ToolGetter(std::string _path): path(std::move(_path)) {}
583  inline std::string operator() (IDODNodeMapper *t) const {
584  return t->nodeTypeForPath(path);
585  }
587  inline Gaudi::Utils::TypeNameString operator() (IDODAlgMapper *t) const {
588  return t->algorithmForPath(path);
589  }
590  };
591 
594  inline bool isGood(const std::string& r) {return !r.empty();}
595  inline bool isGood(const Gaudi::Utils::TypeNameString& r) {return !r.name().empty();}
597 
600  class Finder {
601  const ToolGetter getter;
602  const std::vector<IDODNodeMapper*> &nodes;
603  const std::vector<IDODAlgMapper*> &algs;
605  template <class R, class C>
606  R find(const C& l) const {
607  for(auto& i : l ){
608  auto result = getter(i);
609  if (isGood(result)) return result;
610  }
611  return R{""};
612  }
613  public:
615  Finder(std::string _path,
616  const std::vector<IDODNodeMapper*> &_nodes,
617  const std::vector<IDODAlgMapper*> &_algs)
618  : getter(std::move(_path)), nodes(_nodes), algs(_algs) {
619  }
621  inline std::string node() const {
622  return find<std::string>(nodes);
623  }
625  inline Gaudi::Utils::TypeNameString alg() const {
626  return find<Gaudi::Utils::TypeNameString>(algs);
627  }
628 
629  };
630 
631 }
632 
633 // ===========================================================================
634 // IIncidentListener interfaces overrides: incident handling
635 // ===========================================================================
636 void DataOnDemandSvc::handle ( const Incident& incident )
637 {
638 
640 
641  ++m_stat ;
642  // proper incident type?
643  if ( incident.type() != m_trapType ) { return ; } // RETURN
644  const DataIncident* inc = dynamic_cast<const DataIncident*>(&incident);
645  if ( ! inc ) { return ; } // RETURN
646  // update if needed!
647  if ( m_updateRequired ) { update() ; }
648 
649  if ( MSG::VERBOSE >= outputLevel() )
650  {
651  verbose()
652  << "Incident: [" << incident.type () << "] "
653  << " = " << incident.source ()
654  << " Location:" << inc->tag() << endmsg;
655  }
656  // ==========================================================================
657  Gaudi::StringKey tag ( inc->tag() ) ;
658  // ==========================================================================
659  auto icl = m_nodes.find ( tag ) ;
660  if ( icl != m_nodes.end() )
661  {
662  StatusCode sc = execHandler ( tag , icl->second ) ;
663  if ( sc.isSuccess() ) { ++m_statNode ; }
664  return ; // RETURN
665  }
666  // ==========================================================================
667  auto ialg = m_algs.find ( tag ) ;
668  if ( ialg != m_algs.end() )
669  {
670  StatusCode sc = execHandler ( tag , ialg->second ) ;
671  if ( sc.isSuccess() ) { ++m_statAlg ; }
672  return ; // RETURN
673  }
674  // ==========================================================================
675  // Fall back on the tools
676  if (m_toolSvc) {
677  if (MSG::VERBOSE >= outputLevel())
678  verbose() << "Try to find mapping with mapping tools" << endmsg;
679  Finder finder(no_prefix(inc->tag(), m_prefix), m_nodeMappers, m_algMappers);
680  // - try the node mappers
681  std::string node = finder.node();
682  if (isGood(node)) {
683  // if one is found update the internal node mapping and try again.
684  if (MSG::VERBOSE >= outputLevel())
685  verbose() << "Found Node handler: " << node << endmsg;
686  i_setNodeHandler(inc->tag(), node);
687  handle(incident);
688  --m_stat; // avoid double counting because of recursion
689  return;
690  }
691  // - try alg mappings
692  Gaudi::Utils::TypeNameString alg = finder.alg();
693  if (isGood(alg)) {
694  // we got an algorithm, update alg map and try to handle again
695  if (MSG::VERBOSE >= outputLevel())
696  verbose() << "Found Algorithm handler: " << alg << endmsg;
697  i_setAlgHandler(inc->tag(), alg).ignore();
698  handle(incident);
699  --m_stat; // avoid double counting because of recursion
700  return;
701  }
702  }
703 }
704 // ===========================================================================
705 // execute the handler
706 // ===========================================================================
708 DataOnDemandSvc::execHandler ( const std::string& tag, Node& n)
709 {
710 
712 
713  if ( n.executing ) { return StatusCode::FAILURE ; } // RETURN
714 
715  Protection p(n.executing);
716 
717  std::unique_ptr<DataObject> object;
718 
719  if ( n.dataObject ) { object.reset( new DataObject() ) ; }
720  else
721  {
722  // try to recover the handler
723  if ( !n.clazz ) { n.clazz = TClass::GetClass(n.name.c_str()) ; }
724  if ( !n.clazz )
725  {
726  stream()
727  << MSG::ERROR
728  << "Failed to get dictionary for class '"
729  << n.name
730  << "' for location:" << tag << endmsg;
731  return StatusCode::FAILURE ; // RETURN
732  }
733 
734  object.reset( reinterpret_cast<DataObject*>(n.clazz->New()) );
735 
736  if ( !object )
737  {
738  stream()
739  << MSG::ERROR
740  << "Failed to create an object of type:"
741  << n.clazz->GetName() << " for location:" << tag
742  << endmsg;
743  return StatusCode::FAILURE ; // RETURN
744  }
745  }
746  //
747  StatusCode sc = m_dataSvc->registerObject(tag, object.release() );
748  if ( sc.isFailure() )
749  {
750  stream()
751  << MSG::ERROR << "Failed to register an object of type:"
752  << n.name << " at location:" << tag
753  << endmsg;
754  return sc ; // RETURN
755  }
756  ++n.num ;
757  //
758  return StatusCode::SUCCESS ;
759 }
760 // ===========================================================================
761 // execute the handler
762 // ===========================================================================
764 DataOnDemandSvc::execHandler(const std::string& tag, Leaf& l)
765 {
767  //
768  if ( l.executing ) { return StatusCode::FAILURE ; } // RETURN
769  //
770  if ( ! l.algorithm )
771  {
772  StatusCode sc = configureHandler ( l ) ;
773  if ( sc.isFailure() )
774  {
775  stream()
776  << MSG::ERROR
777  << "Failed to configure handler for: "
778  << l.name << "[" << l.type << "] " << tag << endmsg;
779  return sc ; // RETURN
780  }
781  }
782  //
783  Chrono atimer ( m_total ) ;
784  //
785  Protection p(l.executing);
787  if ( sc.isFailure() )
788  {
789  stream() << MSG::ERROR
790  << "Failed to execute the algorithm:"
791  << l.algorithm->name() << " for location:" << tag << endmsg;
792  return sc ; // RETURN
793  }
794  ++l.num ;
795  //
796  return StatusCode::SUCCESS ;
797 }
798 // ============================================================================
799 /* dump the content of DataOnDemand service
800  * @param level the printout level
801  * @param mode the printout mode
802  */
803 // ============================================================================
805 ( const MSG::Level level ,
806  const bool mode ) const
807 {
808  if ( m_algs.empty() && m_nodes.empty() ) { return ; }
809 
810  typedef std::pair<std::string,std::string> Pair ;
811  std::map<std::string,Pair> _m ;
812  for ( auto& alg : m_algs )
813  {
814  auto check = _m.find(alg.first) ;
815  if ( _m.end() != check )
816  {
817  stream()
818  << MSG::WARNING
819  << " The data item is activated for '"
820  << check->first << "' as '" << check->second.first << "'" << endmsg ;
821  }
822  const Leaf& l = alg.second ;
823  std::string nam = ( l.name == l.type ? l.type : (l.type+"/"+l.name) ) ;
824  //
825  if ( !mode && 0 == l.num ) { continue ; }
826  //
827  std::string val ;
828  if ( mode ) { val = ( ! l.algorithm ) ? "F" : "T" ; }
829  else { val = std::to_string( l.num ) ; }
830  //
831  _m[ no_prefix ( alg.first , m_prefix ) ] = { nam , val } ;
832  }
833  // nodes:
834  for ( const auto& node : m_nodes )
835  {
836  auto check = _m.find(node.first) ;
837  if ( _m.end() != check )
838  {
839  stream()
840  << MSG::WARNING
841  << " The data item is already activated for '"
842  << check->first << "' as '" << check->second.first << "'" << endmsg ;
843  }
844  const Node& n = node.second ;
845  std::string nam = "'" + n.name + "'" ;
846  //
847  std::string val ;
848 
849  if ( !mode && 0 == n.num ) { continue ; }
850 
851  if ( mode ) { val = ( 0 == n.clazz ) ? "F" : "T" ; }
852  else { val = std::to_string( n.num ) ; }
853  //
854  _m[ no_prefix ( node.first , m_prefix ) ] = { nam , val } ;
855  }
856  //
857  if ( _m.empty() ) { return ; }
858 
859  // find the correct formats
860  size_t n1 = 0 ;
861  size_t n2 = 0 ;
862  size_t n3 = 0 ;
863  for ( const auto& i : _m )
864  {
865  n1 = std::max ( n1 , i.first.size() ) ;
866  n2 = std::max ( n2 , i.second.first.size() ) ;
867  n3 = std::max ( n3 , i.second.second.size() ) ;
868  }
869  if ( 10 > n1 ) { n1 = 10 ; }
870  if ( 10 > n2 ) { n2 = 10 ; }
871  if ( 60 < n1 ) { n1 = 60 ; }
872  if ( 60 < n2 ) { n2 = 60 ; }
873  //
874 
875  const std::string _f = " | %%1$-%1%.%1%s | %%2$-%2%.%2%s | %%3$%3%.%3%s |" ;
876  boost::format _ff ( _f ) ;
877  _ff % n1 % n2 % n3 ;
878 
879  const std::string _format = _ff.str() ;
880 
881  MsgStream& msg = stream() << level ;
882 
883  if ( mode ) { msg << "Data-On-Demand Actions enabled for:" ; }
884  else { msg << "Data-On-Demand Actions has been used for:" ; }
885 
886  boost::format fmt1( _format) ;
887  fmt1 % "Address" % "Creator" % ( mode ? "S" : "#" ) ;
888  //
889  const std::string header = fmt1.str() ;
890  std::string line = std::string( header.size() , '-' ) ;
891  line[0] = ' ' ;
892 
893  msg << '\n' << line
894  << '\n' << header
895  << '\n' << line ;
896 
897  // make the actual printout:
898  for ( const auto& item : _m )
899  {
900  boost::format fmt( _format) ;
901  msg << '\n' <<
902  ( fmt % item.first % item.second.first % item.second.second ) ;
903  }
904 
905  msg << '\n' << line << endmsg ;
906 
907 }
908 // ============================================================================
913 // ============================================================================
914 
915 // ============================================================================
916 // The END
917 // ============================================================================
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
StatusCode initialize() override
Definition: Service.cpp:63
string to_string(const T &value)
Definition: mergesort.cpp:40
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:25
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:244
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 ...
StatusCode finalize() override
Definition: Service.cpp:188
virtual StatusCode sysStart()=0
Startup method invoked by the framework.
ChronoEntity m_timer_algs
const std::string & source() const
Access to the source of the incident.
Definition: Incident.h:40
std::vector< IDODNodeMapper * > m_nodeMappers
bool isSuccess() const
Test for a status code of SUCCESS.
Definition: StatusCode.h:76
MsgStream & stream() const
get the message stream
SmartIF< IIncidentSvc > m_incSvc
Incident service.
void handle(const Incident &incident) override
IIncidentListener interfaces overrides: incident handling.
list path
Definition: __init__.py:15
std::unique_ptr< MsgStream > m_log
virtual StatusCode createAlgorithm(const std::string &algtype, const std::string &algname, IAlgorithm *&alg, bool managed=false, bool checkIfExists=true)=0
Create an instance of a algorithm type that has been declared beforehand and assigns to it a name...
std::vector< std::string > m_algMapTools
std::string m_trapType
Trap name.
STL namespace.
std::string m_dataSvcName
Data service name.
Setup m_nodeMapping
Mapping to nodes.
A small utility class for chronometry of user codes.
Definition: Chrono.h:25
Map m_algMap
the major configuration property { 'data' : 'algorithm' }
#define SET(x)
StatusCode initialize() override
Inherited Service overrides: Service initialization.
bool isFailure() const
Test for a status code of FAILURE.
Definition: StatusCode.h:86
StatusCode retrieveTool(const std::string &type, T *&tool, const IInterface *parent=nullptr, bool createIf=true)
Retrieve specified tool sub-type with tool dependent part of the name automatically assigned...
Definition: IToolSvc.h:145
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.
SmartIF< IDataProviderSvc > m_dataSvc
Data provider reference.
ulonglong m_statNode
ClassH clazz
the actual class
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:132
Helper class to parse a string of format "type/name".
Definition: TypeNameString.h:9
StatusCode setup()
Setup routine (called by (re-) initialize.
bool m_allowInitFailure
flag to allow DataOnDemand initialization to succeed even if the (pre)initialization of the algorithm...
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
Definition: MsgStream.cpp:119
StatusCode execHandler(const std::string &tag, Leaf &leaf)
Execute leaf handler (algorithm)
auto end(reverse_wrapper< T > &w)
Definition: reverse.h:47
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:26
#define DECLARE_COMPONENT(type)
Definition: PluginService.h:36
void update_dump(Property &)
update handler for 'Dump' property
StatusCode setupNodeHandlers()
Initialize node handlers.
iterator find(const key_type &key)
Definition: Map.h:149
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
StatusCode reinitialize() override
Definition: Service.cpp:283
void dump(const MSG::Level level, const bool mode=true) const
dump the content of DataOnDemand service
dictionary l
Definition: gaudirun.py:421
bool m_partialPath
Flag to allow for the creation of partial leaves.
std::string outputUserTime() const
print the chrono ;
std::vector< IDODAlgMapper * > m_algMappers
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:38
SmartIF< IAlgManager > m_algMgr
Algorithm manager.
SmartIF< IToolSvc > m_toolSvc
Data provider reference.
Helper object, useful for measurement of CPU-performance of highly-recursive structures, e.g.
Definition: LockedChrono.h:52
AlgMap m_algs
Map of algorithms to handle incidents.
Base class used to extend a class implementing other interfaces.
Definition: extends.h:10
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.
StatusCode finalize() override
Inherited Service overrides: Service finalization.
tuple item
print s1,s2
Definition: ana.py:146
void clear()
Definition: Map.h:178
virtual StatusCode releaseTool(IAlgTool *tool)=0
Release the tool.
ChronoEntity m_total
void reset(TYPE *ptr=nullptr)
Set the internal pointer to the passed one disposing of the old one.
Definition: SmartIF.h:88
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:108
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.
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.
void update_2(Property &p)
void toupper(std::string &s)
void update_3(Property &p)
void update_1(Property &p)
StatusCode reinitialize() override
Inherited Service overrides: Service reinitialization.
StatusCode update()
update the handlers
string type
Definition: gaudirun.py:151