The Gaudi Framework  v36r13 (995e4364)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
ToolSvc.cpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 // Include Files
12 #include "ToolSvc.h"
13 #include "GaudiKernel/AlgTool.h"
15 #include "GaudiKernel/IAlgorithm.h"
18 #include "GaudiKernel/MsgStream.h"
19 #include "GaudiKernel/Service.h"
20 #include "boost/algorithm/string/erase.hpp"
21 #include "boost/algorithm/string/predicate.hpp"
22 #include "boost/circular_buffer.hpp"
23 #include <algorithm>
24 #include <cassert>
25 #include <functional>
26 #include <map>
27 #include <numeric>
28 #include <string>
29 namespace ba = boost::algorithm;
30 
31 #define ON_DEBUG if ( msgLevel( MSG::DEBUG ) )
32 #define ON_VERBOSE if ( msgLevel( MSG::VERBOSE ) )
33 
34 namespace {
35  //------------------------------------------------------------------------------
36  template <typename C>
37  unsigned long totalRefCount( const C& toolList )
38  //------------------------------------------------------------------------------
39  {
40  return std::accumulate( std::begin( toolList ), std::end( toolList ), 0ul,
41  [&]( unsigned long count, const IAlgTool* tool ) { return count + tool->refCount(); } );
42  }
43 
45  template <typename C>
46  void remove( C& c, typename C::const_reference i ) {
47  c.erase( std::remove( std::begin( c ), std::end( c ), i ), std::end( c ) );
48  }
49 } // namespace
50 
51 // Instantiation of a static factory class used by clients to create
52 // instances of this service
54 
55 //------------------------------------------------------------------------------
57  // tell the remaining observers that we're gone, and forget about unregistering..
58  std::for_each( std::begin( m_observers ), std::end( m_observers ),
59  [&]( IToolSvc::Observer* obs ) { obs->setUnregister( {} ); } );
60 }
61 
62 //------------------------------------------------------------------------------
64 //------------------------------------------------------------------------------
65 {
66  // Finalize and delete all left-over tools. Normally all tools created with
67  // ToolSvc are left over, since ToolSvc holds a refCount (via AlgTool ctor).
68  // Several cases need to be covered:
69  // 1) Simple dependencies: no circular dependencies between tools,
70  // and tools not using other tools
71  // 2) Tools-using-tools (but no circular dependencies)
72  // a) release() is called in the tool::finalize() (e.g. via GaudiAlgorithm)
73  // b) release() is called in the tool destructor (e.g. via ToolHandle)
74  // 3) Circular dependencies between tools
75  // a) release() is called in the tool::finalize() (e.g. via GaudiAlgorithm)
76  // b) release() is called in the tool destructor (e.g. via ToolHandle)
77  // 4) In addition to each of the above cases, refCounting of a particular tool
78  // might not have been done correctly in the code. Typically release()
79  // is not called, so we are left with a too high refCount.
80  // What to do with those, and how to avoid a crash while handling them...
81 
90  info() << "Removing all tools created by ToolSvc" << endmsg;
91 
92  // Print out list of tools
93  ON_DEBUG {
94  auto& log = debug();
95  log << " Tool List : ";
96  for ( const auto& iTool : m_instancesTools ) { log << iTool->name() << ":" << iTool->refCount() << " "; }
97  log << endmsg;
98  }
99 
100  //
101  // first pass: Finalize all tools (but don't delete them)
102  //
115  boost::circular_buffer<IAlgTool*> finalizedTools( m_instancesTools.size() ); // list of tools that have been finalized
116  bool fail( false );
117  size_t toolCount = m_instancesTools.size();
118  unsigned long startRefCount = 0;
119  unsigned long endRefCount = totalToolRefCount();
120  unsigned long startMinRefCount = 0;
121  unsigned long endMinRefCount = minimumToolRefCount();
122  while ( toolCount > 0 && endRefCount > 0 && ( endRefCount != startRefCount || endMinRefCount != startMinRefCount ) ) {
123  ON_DEBUG if ( endMinRefCount != startMinRefCount ) {
124  debug() << toolCount << " tools left to finalize. Summed refCounts: " << endRefCount << endmsg;
125  debug() << "Will finalize tools with refCount <= " << endMinRefCount << endmsg;
126  }
127  startMinRefCount = endMinRefCount;
128  startRefCount = endRefCount;
129  unsigned long maxLoop = toolCount + 1;
130  while ( --maxLoop > 0 && !m_instancesTools.empty() ) {
131  IAlgTool* pTool = m_instancesTools.back();
132  // removing tool from list makes ToolSvc::releaseTool( IAlgTool* ) a noop
134  unsigned long count = pTool->refCount();
135  // cache tool name
136  const std::string& toolName = pTool->name();
137  if ( count <= startMinRefCount ) {
138  ON_DEBUG debug() << " Performing finalization of " << toolName << " (refCount " << count << ")" << endmsg;
139  // finalize of one tool may trigger a release of another tool
140  // pTool->sysFinalize().ignore();
141  if ( !finalizeTool( pTool ).isSuccess() ) {
142  warning() << " FAILURE finalizing " << toolName << endmsg;
143  fail = true;
144  }
145  // postpone deletion
146  finalizedTools.push_back( pTool );
147  } else {
148  // Place back at the front of the list to try again later
149  // ToolSvc::releaseTool( IAlgTool* ) remains active for this tool
150  ON_DEBUG debug() << " Delaying finalization of " << toolName << " (refCount " << count << ")" << endmsg;
152  }
153  } // end of inner loop
154  toolCount = m_instancesTools.size();
155  endRefCount = totalToolRefCount();
156  endMinRefCount = minimumToolRefCount();
157  }; // end of outer loop
158 
159  //
160  // Second pass: Delete all finalized tools
161  //
162  // Delete in the order of increasing number of refCounts.
163  // Loop over tools in the same order as the order in which they were finalized.
164  // All tools in the list of finalized tools are no longer in the instancesTools list.
165  // If a tool destructor calls releaseTool() on another tool, this will have no
166  // effect on the 'other tool' if this 'other tool' is in the list of finalized tools.
167  // If this 'other tool' is still in the instancesTools list, it may trigger finalization
168  // (in releaseTool()), deletion and removal from the instancesTools list.
169  // Therefore, the check on non-finalised tools should happen *after* the deletion
170  // of the finalized tools.
171  ON_DEBUG debug() << "Deleting " << finalizedTools.size() << " finalized tools" << endmsg;
172  auto maxLoop = totalRefCount( finalizedTools ) + 1;
173  while ( --maxLoop > 0 && !finalizedTools.empty() ) {
174  IAlgTool* pTool = finalizedTools.front();
175  finalizedTools.pop_front();
176  auto count = pTool->refCount();
177  if ( count == 1 ) {
178  ON_DEBUG debug() << " Performing deletion of " << pTool->name() << endmsg;
179  } else {
180  ON_VERBOSE verbose() << " Delaying deletion of " << pTool->name() << " (refCount " << count << ")" << endmsg;
181  // Move to the end when refCount still not zero
182  finalizedTools.push_back( pTool );
183  }
184  // do a forced release
185  pTool->release();
186  }
187 
188  // Error if by now not all tools are properly finalised
189  if ( !m_instancesTools.empty() ) {
190  error() << "Unable to finalize and delete the following tools : ";
191  for ( const auto& iTool : m_instancesTools ) { error() << iTool->name() << ": " << iTool->refCount() << " "; }
192  error() << endmsg;
193  }
194 
195  // by now, all tools should be deleted and removed.
196  if ( !finalizedTools.empty() ) {
197  error() << "Failed to delete the following " << finalizedTools.size()
198  << " finalized tools. Bug in ToolSvc::finalize()?: ";
199  for ( const auto& iTool : finalizedTools ) { error() << iTool->name() << ": " << iTool->refCount() << " "; }
200  error() << endmsg;
201  }
202 
203  if ( m_pHistorySvc ) m_pHistorySvc->release();
204 
205  // Finalize this specific service
206  return ( Service::finalize().isSuccess() && !fail ) ? StatusCode::SUCCESS : StatusCode::FAILURE;
207 }
208 
209 // ===================================================================================
213 // ===================================================================================
214 namespace {
215  static const std::string s_PUBLIC = ":PUBLIC";
216 }
217 
218 //------------------------------------------------------------------------------
219 StatusCode ToolSvc::retrieve( std::string_view tooltype, const InterfaceID& iid, IAlgTool*& tool,
220  const IInterface* parent, bool createIf )
221 //------------------------------------------------------------------------------
222 {
223  // check for tools, which by name are required to be public:
224  if ( ba::ends_with( tooltype, s_PUBLIC ) ) {
225  // parent for PUBLIC tool is 'this', i.e. ToolSvc
226  tooltype.remove_suffix( s_PUBLIC.size() );
227  return retrieve( tooltype, iid, tool, this, createIf );
228  }
229 
230  // protect against empty type
231  if ( tooltype.empty() ) {
232  error() << "retrieve(): No Tool Type/Name given" << endmsg;
233  return StatusCode::FAILURE;
234  }
235  auto pos = tooltype.find( '/' );
236  if ( std::string_view::npos == pos ) { return retrieve( tooltype, tooltype, iid, tool, parent, createIf ); }
237  return retrieve( tooltype.substr( 0, pos ), tooltype.substr( pos + 1 ), iid, tool, parent, createIf );
238 }
239 
240 // ===================================================================================
241 
242 //------------------------------------------------------------------------------
243 StatusCode ToolSvc::retrieve( std::string_view tooltype, std::string_view toolname, const InterfaceID& iid,
244  IAlgTool*& tool, const IInterface* parent, bool createIf )
245 //------------------------------------------------------------------------------
246 {
247  // check the applicability of another method:
248  // ignore the provided name if it is empty or the type contains a name
249  if ( toolname.empty() || ( std::string_view::npos != tooltype.find( '/' ) ) ) {
250  return retrieve( tooltype, iid, tool, parent, createIf );
251  }
252 
253  // check for tools, which by name are required to be public:
254  if ( ba::ends_with( toolname, s_PUBLIC ) ) {
255  // parent for PUBLIC tool is this, i.e. ToolSvc
256  toolname.remove_suffix( s_PUBLIC.size() );
257  return retrieve( tooltype, toolname, iid, tool, this, createIf );
258  }
259 
260  auto lock = std::scoped_lock{ m_mut };
261 
262  IAlgTool* itool = nullptr;
264 
265  tool = nullptr;
266 
267  // If parent is not specified it means it is the ToolSvc itself
268  if ( !parent ) parent = this;
269  const std::string fullname = nameTool( toolname, parent );
270 
271  // Find tool in list of those already existing, and tell its
272  // interface that it has been used one more time
274  [&]( const IAlgTool* i ) { return i->name() == fullname && i->parent() == parent; } );
275  if ( it != std::end( m_instancesTools ) ) {
276  ON_DEBUG debug() << "Retrieved tool " << toolname << " with parent " << parent << endmsg;
277  itool = *it;
278  }
279 
280  if ( !itool ) {
281  // Instances of this tool do not exist, create an instance if desired
282  // otherwise return failure
283  if ( !createIf ) {
284  warning() << "Tool " << toolname << " not found and creation not requested" << endmsg;
285  return sc;
286  }
287  sc = create( std::string{ tooltype }, std::string{ toolname }, parent, itool );
288  if ( sc.isFailure() ) { return sc; }
289  }
290 
291  // Get the right interface of it
292  sc = itool->queryInterface( iid, pp_cast<void>( &tool ) );
293  if ( sc.isFailure() ) {
294  error() << "Tool " << toolname << " either does not implement the correct interface, or its version is incompatible"
295  << endmsg;
296  return sc;
297  }
298 
303  [&]( IToolSvc::Observer* obs ) { obs->onRetrieve( itool ); } );
304  return sc;
305 }
306 //------------------------------------------------------------------------------
308 //------------------------------------------------------------------------------
309 {
310 
311  auto lock = std::scoped_lock{ m_mut };
313  for ( const auto& tool : m_instancesTools ) {
314  if ( tool->type() == toolType ) tools.push_back( tool->name() );
315  }
316  return tools;
317 }
318 //------------------------------------------------------------------------------
320 //------------------------------------------------------------------------------
321 {
322  auto lock = std::scoped_lock{ m_mut };
325  []( const IAlgTool* t ) { return t->name(); } );
326  return tools;
327 }
328 //------------------------------------------------------------------------------
330 //------------------------------------------------------------------------------
331 {
332  auto lock = std::scoped_lock{ m_mut };
334 }
335 //------------------------------------------------------------------------------
337 //------------------------------------------------------------------------------
338 {
339  auto lock = std::scoped_lock{ m_mut };
341  // test if tool is in known list (protect trying to access a previously deleted tool)
343  unsigned long count = tool->refCount();
344  if ( count == 1 ) {
345  // finalize the tool
346 
348  // We are being called during ToolSvc::finalize()
349  // message format matches the one in ToolSvc::finalize()
350  debug() << " Performing finalization of " << tool->name() << " (refCount " << count << ")" << endmsg;
351  // message format matches the one in ToolSvc::finalize()
352  debug() << " Performing deletion of " << tool->name() << endmsg;
353  } else {
354  debug() << "Performing finalization and deletion of " << tool->name() << endmsg;
355  }
356  sc = finalizeTool( tool );
357  // remove from known tools...
358  remove( m_instancesTools, tool );
359  }
360  tool->release();
361  }
362  return sc;
363 }
364 
365 //------------------------------------------------------------------------------
366 StatusCode ToolSvc::create( const std::string& tooltype, const IInterface* parent, IAlgTool*& tool )
367 //------------------------------------------------------------------------------
368 {
369  const std::string& toolname = tooltype;
370  return create( tooltype, toolname, parent, tool );
371 }
372 
373 namespace {
376  template <typename T>
377  class ToolCreateGuard {
379  T& m_tools;
382 
383  public:
384  explicit ToolCreateGuard( T& tools ) : m_tools( tools ) {}
385  // we don't get a move constructor by default because we
386  // have a non-trivial destructor... However, the default
387  // one is just fine...
388  ToolCreateGuard( ToolCreateGuard&& ) noexcept = default;
390  void create( const std::string& tooltype, const std::string& fullname, const IInterface* parent ) {
391  // remove previous content
392  if ( m_tool ) remove( m_tools, m_tool.get() );
393  m_tool = AlgTool::Factory::create( tooltype, tooltype, fullname, parent );
394  // set new content
395  if ( m_tool ) m_tools.push_back( m_tool.get() );
396  }
398  IAlgTool* get() { return m_tool.get(); }
399  IAlgTool* operator->() const {
400  assert( m_tool );
401  return m_tool.get();
402  }
404  IAlgTool* release() { return m_tool.release(); }
406  ~ToolCreateGuard() {
407  if ( m_tool ) remove( m_tools, m_tool.get() );
408  }
409  };
410 
411  template <typename C>
412  ToolCreateGuard<C> make_toolCreateGuard( C& c ) {
413  return ToolCreateGuard<C>{ c };
414  }
415 } // namespace
416 
417 //------------------------------------------------------------------------------
425 StatusCode ToolSvc::create( const std::string& tooltype, const std::string& toolname, const IInterface* parent,
426  IAlgTool*& tool )
427 //------------------------------------------------------------------------------
428 {
429 
430  auto lock = std::scoped_lock{ m_mut };
431  // protect against empty type
432  if ( tooltype.empty() ) {
433  error() << "create(): No Tool Type given" << endmsg;
434  return StatusCode::FAILURE;
435  }
436 
437  // If parent has not been specified, assume it is the ToolSvc
438  if ( !parent ) parent = this;
439 
440  tool = nullptr;
441  // Automatically deletes the tool if not explicitly kept (i.e. on success).
442  // The tool is removed from the list of known tools too.
443  auto toolguard = make_toolCreateGuard( m_instancesTools );
444 
445  // Check if the tool already exist : this could happen with clones
446  std::string fullname = nameTool( toolname, parent );
447  if ( existsTool( fullname ) ) {
448  // Now check if the parent is the same. This allows for clones
449  for ( IAlgTool* iAlgTool : m_instancesTools ) {
450  if ( iAlgTool->name() == toolname && iAlgTool->parent() == parent ) {
451  // The tool exist with this name, type and parent: this is bad!
452  // This excludes the possibility of cloning public tools intrinsecally
453  error() << "Tool " << fullname << " already exists with the same parent" << endmsg;
454  if ( parent == this )
455  error() << "... In addition, the parent is the ToolSvc: public tools cannot be cloned!" << endmsg;
456 
457  return StatusCode::FAILURE;
458  }
459  }
460  ON_DEBUG debug() << "Creating clone of " << fullname << endmsg;
461  }
462  // instantiate the tool using the factory
463  try {
464  toolguard.create( tooltype, fullname, parent );
465  if ( !toolguard.get() ) {
466  error() << "Cannot create tool " << tooltype << " (No factory found)" << endmsg;
467  return StatusCode::FAILURE;
468  }
469  } catch ( const GaudiException& Exception ) {
470  // (1) perform the printout of message
471  fatal() << "Exception with tag=" << Exception.tag() << " is caught whilst instantiating tool '" << tooltype << "'"
472  << endmsg;
473  // (2) print the exception itself
474  // (NB! - GaudiException is a linked list of all "previous exceptions")
475  fatal() << Exception << endmsg;
476  return StatusCode::FAILURE;
477  } catch ( const std::exception& Exception ) {
478  // (1) perform the printout of message
479  fatal() << "Standard std::exception is caught whilst instantiating tool '" << tooltype << "'" << endmsg;
480  // (2) print the exception itself
481  // (NB! - GaudiException is a linked list of all "previous exceptions")
482  fatal() << Exception.what() << endmsg;
483  return StatusCode::FAILURE;
484  } catch ( ... ) {
485  // (1) perform the printout
486  fatal() << "UNKNOWN Exception is caught whilst instantiating tool '" << tooltype << "'" << endmsg;
487  return StatusCode::FAILURE;
488  }
489  ON_VERBOSE verbose() << "Created tool " << tooltype << "/" << fullname << endmsg;
490 
491  // Since only AlgTool has the setProperties() method it is necessary to cast
492  // to downcast IAlgTool to AlgTool in order to set the properties via the JobOptions
493  // service
494  AlgTool* mytool = dynamic_cast<AlgTool*>( toolguard.get() );
495  if ( mytool ) mytool->bindPropertiesTo( serviceLocator()->getOptsSvc() );
496 
497  // Initialize the Tool
499  try {
500  sc = toolguard->sysInitialize();
501  }
502  // Catch any exceptions
503  catch ( const GaudiException& Exception ) {
504  error() << "GaudiException with tag=" << Exception.tag() << " caught whilst initializing tool '" << fullname << "'"
505  << endmsg << Exception << endmsg;
506  return StatusCode::FAILURE;
507  } catch ( const std::exception& Exception ) {
508  error() << "Standard std::exception caught whilst initializing tool '" << fullname << "'" << endmsg
509  << Exception.what() << endmsg;
510  return StatusCode::FAILURE;
511  } catch ( ... ) {
512  error() << "UNKNOWN Exception caught whilst initializing tool '" << fullname << "'" << endmsg;
513  return StatusCode::FAILURE;
514  }
515 
516  // Status of tool initialization
517  if ( sc.isFailure() ) {
518  error() << "Error initializing tool '" << fullname << "'" << endmsg;
519  return sc;
520  }
521 
523  // Check to ensure that non-default named tools are configured.
524  if ( toolname != tooltype ) {
525  bool propsSet = false;
526  Gaudi::Interfaces::IOptionsSvc& joSvc = this->serviceLocator()->getOptsSvc();
527  // Check that at least one of the properties has been set:
528  for ( const auto prop : mytool->getProperties() ) {
529  bool isSet = joSvc.isSet( mytool->name() + "." + prop->name() );
530  if ( isSet ) propsSet = true;
531  }
532  if ( !propsSet ) {
533  warning() << tooltype << "/" << fullname
534  << " : Explicitly named tools should be configured! (assigned name=" << toolname << ", default is "
535  << tooltype << ")" << endmsg;
536  }
537  }
538  }
539 
540  // Start the tool if we are running.
542  sc = toolguard->sysStart();
543 
544  if ( sc.isFailure() ) {
545  error() << "Error starting tool '" << fullname << "'" << endmsg;
546  return sc;
547  }
548  }
549 
550  // The tool has been successfully created and initialized,
551  // so we inform the guard that it can release it
552  tool = toolguard.release();
553 
557  std::for_each( m_observers.begin(), m_observers.end(), [&]( IToolSvc::Observer* obs ) { obs->onCreate( tool ); } );
558  // TODO: replace by generic callback
559  // Register the tool with the HistorySvc
560  if ( m_pHistorySvc || service( "HistorySvc", m_pHistorySvc, false ).isSuccess() ) {
562  }
563  return StatusCode::SUCCESS;
564 }
565 
566 //------------------------------------------------------------------------------
567 std::string ToolSvc::nameTool( std::string_view toolname, const IInterface* parent )
568 //------------------------------------------------------------------------------
569 {
570 
571  if ( !parent ) { return std::string{ this->name() }.append( "." ).append( toolname ); } // RETURN
572 
573  // check that parent has a name!
574  auto named_parent = SmartIF<INamedInterface>( const_cast<IInterface*>( parent ) );
575  if ( named_parent ) {
576  auto fullname = std::string{ named_parent->name() }.append( "." ).append( toolname );
577  return fullname; // RETURN
578  }
579 
580  error() << "Private Tools only allowed for components implementing INamedInterface" << endmsg;
581  //
582  return std::string{ "." }.append( toolname );
583 }
584 
585 //------------------------------------------------------------------------------
586 bool ToolSvc::existsTool( std::string_view fullname ) const
587 //------------------------------------------------------------------------------
588 {
589  auto lock = std::scoped_lock{ m_mut };
590  auto i = std::find_if( std::begin( m_instancesTools ), std::end( m_instancesTools ),
591  [&]( const IAlgTool* tool ) { return tool->name() == fullname; } );
592  return i != std::end( m_instancesTools );
593 }
594 
595 //------------------------------------------------------------------------------
597 //------------------------------------------------------------------------------
598 {
599 
600  // Cache tool name in case of errors
601  const auto& toolName = itool->name();
602  StatusCode sc;
603 
604  // Finalise the tool inside a try block
605  try {
606  sc = itool->sysFinalize();
607  }
608  // Catch any exceptions
609  catch ( const GaudiException& Exception ) {
610  error() << "GaudiException with tag=" << Exception.tag() << " caught whilst finalizing tool '" << toolName << "'"
611  << endmsg << Exception << endmsg;
612  sc = StatusCode::FAILURE;
613  } catch ( const std::exception& Exception ) {
614  error() << "Standard std::exception caught whilst finalizing tool '" << toolName << "'" << endmsg
615  << Exception.what() << endmsg;
616  sc = StatusCode::FAILURE;
617  } catch ( ... ) {
618  error() << "UNKNOWN Exception caught whilst finalizing tool '" << toolName << "'" << endmsg;
619  sc = StatusCode::FAILURE;
620  }
621 
622  return sc;
623 }
624 
625 //------------------------------------------------------------------------------
626 unsigned long ToolSvc::totalToolRefCount() const
627 //------------------------------------------------------------------------------
628 {
629  return totalRefCount( m_instancesTools );
630 }
631 //------------------------------------------------------------------------------
632 unsigned long ToolSvc::minimumToolRefCount() const
633 //------------------------------------------------------------------------------
634 {
635  auto i =
637  []( const IAlgTool* lhs, const IAlgTool* rhs ) { return lhs->refCount() < rhs->refCount(); } );
638  return i != std::end( m_instancesTools ) ? ( *i )->refCount() : 0;
639 }
640 
641 //------------------------------------------------------------------------------
643  //------------------------------------------------------------------------------
644  if ( !obs ) throw GaudiException( "Received NULL pointer", this->name() + "::registerObserver", StatusCode::FAILURE );
645 
646  auto lock = std::scoped_lock{ m_mut };
647  obs->setUnregister( [this, obs]() {
648  auto lock = std::scoped_lock{ m_mut };
649  auto i = std::find( m_observers.begin(), m_observers.end(), obs );
650  if ( i != m_observers.end() ) m_observers.erase( i );
651  } );
652  m_observers.push_back( obs );
653 }
654 
655 //------------------------------------------------------------------------------
657 //------------------------------------------------------------------------------
658 {
659 
660  ON_DEBUG debug() << "START transition for AlgTools" << endmsg;
661 
662  if ( m_showToolDataDeps.value() ) {
663  info() << "Listing Data Dependencies of all Tools";
664  for ( auto& iTool : m_instancesTools ) {
665  IDataHandleHolder* idh = dynamic_cast<IDataHandleHolder*>( iTool );
666  if ( idh ) {
667  std::ostringstream ost;
668  for ( auto& dh : idh->inputHandles() ) { ost << "\n INPUT " << dh->fullKey(); }
669  for ( auto& id : idh->extraInputDeps() ) { ost << "\n EXTRA INPUT " << id; }
670  for ( auto& dh : idh->outputHandles() ) { ost << "\n OUTPUT " << dh->fullKey(); }
671  for ( auto& id : idh->extraOutputDeps() ) { ost << "\n EXTRA OUTPUT " << id; }
672  if ( ost.str().length() > 0 ) { info() << "\n" << iTool->name() << ost.str(); }
673  } else {
674  error() << "can't cast " << iTool->name() << " to IDataHandleHolder!" << endmsg;
675  }
676  }
677  info() << endmsg;
678  }
679 
680  bool fail( false );
681  for ( auto& iTool : m_instancesTools ) {
682  ON_VERBOSE verbose() << iTool->name() << "::start()" << endmsg;
683 
684  if ( !iTool->sysStart().isSuccess() ) {
685  fail = true;
686  error() << iTool->name() << " failed to start()" << endmsg;
687  }
688  }
689 
690  if ( fail ) {
691  error() << "One or more AlgTools failed to start()" << endmsg;
692  return StatusCode::FAILURE;
693  }
694  return StatusCode::SUCCESS;
695 }
696 
697 //------------------------------------------------------------------------------
699 //------------------------------------------------------------------------------
700 {
701 
702  ON_DEBUG debug() << "STOP transition for AlgTools" << endmsg;
703 
704  bool fail( false );
705  for ( auto& iTool : m_instancesTools ) {
706  ON_VERBOSE verbose() << iTool->name() << "::stop()" << endmsg;
707 
708  if ( !iTool->sysStop().isSuccess() ) {
709  fail = true;
710  error() << iTool->name() << " failed to stop()" << endmsg;
711  }
712  }
713 
714  if ( fail ) {
715  error() << "One or more AlgTools failed to stop()" << endmsg;
716  return StatusCode::FAILURE;
717  }
718  return StatusCode::SUCCESS;
719 }
IDataHandleHolder
Definition: IDataHandleHolder.h:24
ToolSvc::m_observers
std::vector< IToolSvc::Observer * > m_observers
Definition: ToolSvc.h:110
ToolSvc::finalize
StatusCode finalize() override
Finalize the service.
Definition: ToolSvc.cpp:63
ToolSvc::m_instancesTools
std::vector< IAlgTool * > m_instancesTools
Common Tools.
Definition: ToolSvc.h:105
IHistorySvc::registerAlgTool
virtual StatusCode registerAlgTool(const IAlgTool &)=0
std::for_each
T for_each(T... args)
ToolSvc::finalizeTool
StatusCode finalizeTool(IAlgTool *itool) const
Finalize the given tool, with exception handling.
Definition: ToolSvc.cpp:596
std::string
STL class.
IAlgTool
Definition: IAlgTool.h:33
ToolSvc::nameTool
std::string nameTool(std::string_view nameByUser, const IInterface *parent)
Get Tool full name by combining nameByUser and "parent" part.
Definition: ToolSvc.cpp:567
std::exception
STL class.
Gaudi.Configuration.log
log
Definition: Configuration.py:30
IToolSvc::Observer::setUnregister
void setUnregister(std::function< void()> unregister)
Definition: IToolSvc.h:235
IDataHandleHolder::extraInputDeps
virtual const DataObjIDColl & extraInputDeps() const =0
Service::m_state
Gaudi::StateMachine::State m_state
Service state
Definition: Service.h:200
ToolSvc::getInstances
std::vector< std::string > getInstances() const override
Get names of all tool instances.
Definition: ToolSvc.cpp:319
GaudiException.h
std::vector< std::string >
std::find_if
T find_if(T... args)
std::vector::size
T size(T... args)
GaudiException
Definition: GaudiException.h:31
std::unique_ptr::get
T get(T... args)
INamedInterface::name
virtual const std::string & name() const =0
Retrieve the name of the instance.
std::unique_ptr::release
T release(T... args)
conf.release
string release
Definition: conf.py:27
ToolSvc::existsTool
bool existsTool(std::string_view toolname) const
Check if the tool instance exists.
Definition: ToolSvc.cpp:586
IInterface::queryInterface
virtual StatusCode queryInterface(const InterfaceID &ti, void **pp)=0
Set the void** to the pointer to the requested interface of the instance.
gaudirun.c
c
Definition: gaudirun.py:527
std::vector::back
T back(T... args)
ToolSvc::getTools
std::vector< IAlgTool * > getTools() const override
Get pointers to all tool instances.
Definition: ToolSvc.cpp:329
ToolSvc
Definition: ToolSvc.h:34
ON_VERBOSE
#define ON_VERBOSE
Definition: ToolSvc.cpp:32
Service::finalize
StatusCode finalize() override
Definition: Service.cpp:222
AlgTool::name
const std::string & name() const override
Retrieve full identifying name of the concrete tool object.
Definition: AlgTool.cpp:67
PropertyHolder::bindPropertiesTo
void bindPropertiesTo(Gaudi::Interfaces::IOptionsSvc &optsSvc)
Definition: PropertyHolder.h:252
std::vector::push_back
T push_back(T... args)
ToolSvc::stop
StatusCode stop() override
Definition: ToolSvc.cpp:698
Service::tools
const std::vector< IAlgTool * > & tools() const
Definition: Service.cpp:409
PropertyHolder::getProperties
const std::vector< Gaudi::Details::PropertyBase * > & getProperties() const override
get all properties
Definition: PropertyHolder.h:222
ToolSvc::releaseTool
StatusCode releaseTool(IAlgTool *tool) override
Release tool.
Definition: ToolSvc.cpp:336
bug_34121.t
t
Definition: bug_34121.py:30
bug_34121.tool
tool
Definition: bug_34121.py:17
Gaudi::Functional::details::get
auto get(const Handle &handle, const Algo &, const EventContext &) -> decltype(details::deref(handle.get()))
Definition: FunctionalDetails.h:444
gaudirun.default
default
Definition: gaudirun.py:190
Service::name
const std::string & name() const override
Retrieve name of the service
Definition: Service.cpp:332
StatusCode
Definition: StatusCode.h:65
ToolSvc::m_pHistorySvc
IHistorySvc * m_pHistorySvc
Pointer to HistorySvc.
Definition: ToolSvc.h:108
IDataHandleHolder::extraOutputDeps
virtual const DataObjIDColl & extraOutputDeps() const =0
std::min_element
T min_element(T... args)
Gaudi::StateMachine::OFFLINE
@ OFFLINE
Definition: StateMachine.h:23
ToolSvc::m_checkNamedToolsConfigured
Gaudi::Property< bool > m_checkNamedToolsConfigured
Definition: ToolSvc.h:98
Gaudi::Property::value
const ValueType & value() const
Definition: Property.h:239
std::vector::erase
T erase(T... args)
GaudiPython.GaudiAlgs.iAlgTool
iAlgTool
Definition: GaudiAlgs.py:68
std::accumulate
T accumulate(T... args)
SmartIF< INamedInterface >
genconfuser.verbose
verbose
Definition: genconfuser.py:29
ToolSvc::registerObserver
void registerObserver(IToolSvc::Observer *obs) override
Definition: ToolSvc.cpp:642
IHistorySvc.h
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:203
std::remove
T remove(T... args)
std::vector::pop_back
T pop_back(T... args)
std::transform
T transform(T... args)
IDataHandleHolder::inputHandles
virtual std::vector< Gaudi::DataHandle * > inputHandles() const =0
Gaudi::StateMachine::RUNNING
@ RUNNING
Definition: StateMachine.h:26
IToolSvc::Observer
allow call-backs when a tool is a created or retrieved
Definition: IToolSvc.h:230
std::string::append
T append(T... args)
std::vector::rend
T rend(T... args)
StatusCode::ignore
const StatusCode & ignore() const
Allow discarding a StatusCode without warning.
Definition: StatusCode.h:139
Service.h
ToolSvc::create
StatusCode create(const std::string &type, const IInterface *parent, IAlgTool *&tool)
Create Tool standard way with automatically assigned name.
Definition: ToolSvc.cpp:366
std::ostringstream
STL class.
StatusCode::isFailure
bool isFailure() const
Definition: StatusCode.h:129
ToolSvc::retrieve
StatusCode retrieve(std::string_view type, const InterfaceID &iid, IAlgTool *&tool, const IInterface *parent, bool createIf) override
Retrieve tool, create it by default as common tool if it does not already exist.
Definition: ToolSvc.cpp:219
IAlgTool::parent
virtual const IInterface * parent() const =0
The parent of the concrete AlgTool.
IToolSvc::Observer::onRetrieve
virtual void onRetrieve(const IAlgTool *)
Definition: IToolSvc.h:238
StatusCode::SUCCESS
constexpr static const auto SUCCESS
Definition: StatusCode.h:100
gaudirun.toolname
toolname
Definition: gaudirun.py:456
AlgTool
Definition: AlgTool.h:62
std::begin
T begin(T... args)
std
STL namespace.
DECLARE_COMPONENT
#define DECLARE_COMPONENT(type)
Definition: PluginServiceV1.h:46
std::vector::insert
T insert(T... args)
IInterface
Definition: IInterface.h:237
IDataHandleHolder::outputHandles
virtual std::vector< Gaudi::DataHandle * > outputHandles() const =0
std::vector::empty
T empty(T... args)
Service::m_targetState
Gaudi::StateMachine::State m_targetState
Service state
Definition: Service.h:202
AlgTool.h
std::ostringstream::str
T str(T... args)
ToolSvc::minimumToolRefCount
unsigned long minimumToolRefCount() const
The minimum number of refCounts of all tools.
Definition: ToolSvc.cpp:632
ON_DEBUG
#define ON_DEBUG
Definition: ToolSvc.cpp:31
ToolSvc::start
StatusCode start() override
Definition: ToolSvc.cpp:656
std::end
T end(T... args)
InterfaceID
Definition: IInterface.h:39
IAlgorithm.h
StatusCode::FAILURE
constexpr static const auto FAILURE
Definition: StatusCode.h:101
ToolSvc.h
IInterface::refCount
virtual unsigned long refCount() const =0
Current reference count.
IInterface::release
virtual unsigned long release()=0
Release Interface instance.
ISvcLocator.h
std::unique_ptr
STL class.
Gaudi::Interfaces::IOptionsSvc
Interface for a component that manages application configuration options.
Definition: IOptionsSvc.h:46
ToolSvc::m_showToolDataDeps
Gaudi::Property< bool > m_showToolDataDeps
Definition: ToolSvc.h:102
ToolSvc::totalToolRefCount
unsigned long totalToolRefCount() const
The total number of refCounts on all tools in the instancesTools list.
Definition: ToolSvc.cpp:626
Service::service
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:88
std::vector::rbegin
T rbegin(T... args)
MsgStream.h
Service::serviceLocator
SmartIF< ISvcLocator > & serviceLocator() const override
Retrieve pointer to service locator
Definition: Service.cpp:335
Gaudi::Interfaces::IOptionsSvc::isSet
virtual bool isSet(const std::string &key) const =0
Test if an option key was explicitly set or not.
ToolSvc::m_mut
CallMutex m_mut
Definition: ToolSvc.h:113