The Gaudi Framework  v33r2 (a6f0ec87)
GaudiCommon.icpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2020 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 // ============================================================================
12 /* @file GaudiCommon.cpp
13  *
14  * Implementation file for class : GaudiCommon
15  *
16  * @author Chris Jones Christopher.Rob.Jones@cern.ch
17  * @author Vanya BELYAEV Ivan.Belyaev@itep.ru
18  * @author Rob Lambert Rob.Lambert@cern.ch
19  * @date 2009-08-04
20  */
21 // ============================================================================
22 #include "GaudiAlg/GaudiCommon.h"
23 
25 #include "GaudiAlg/GaudiTool.h"
26 #include "GaudiAlg/Print.h"
27 #include "GaudiKernel/AlgTool.h"
28 #include "GaudiKernel/Algorithm.h"
32 #include "GaudiKernel/IProperty.h"
34 #include "GaudiKernel/IToolSvc.h"
35 #include "GaudiKernel/MsgStream.h"
37 #include "GaudiKernel/Property.h"
39 #include "GaudiKernel/SmartRef.h"
40 #include "GaudiKernel/Stat.h"
41 #include "GaudiKernel/StatEntity.h"
42 #include "GaudiKernel/System.h"
43 #include "GaudiKernel/reverse.h"
44 #include "GaudiUtils/RegEx.h"
45 #include <algorithm>
46 #include <cstdlib>
47 #include <fmt/format.h>
48 #include <numeric>
49 
50 // ============================================================================
51 // constructor initialisation
52 // ============================================================================
53 template <class PBASE>
55  // setup context from parent if available
56  if ( parent ) {
57  if ( const GaudiAlgorithm* gAlg = dynamic_cast<const GaudiAlgorithm*>( parent ) ) {
58  m_context = gAlg->context();
59  } else if ( const GaudiTool* gTool = dynamic_cast<const GaudiTool*>( parent ) ) {
60  m_context = gTool->context();
61  }
62  }
63 
64  // Get the job option service
65  auto jos = PBASE::template service<IJobOptionsSvc>( "JobOptionsSvc" );
66  if ( !jos ) Exception( "Cannot get JobOptionsSvc" );
67 
68  // Get the "Context" option if in the file...
69  const auto myList = jos->getProperties( this->name() );
70  if ( myList ) {
71  // Iterate over the list to set the options
72  for ( const auto& iter : *myList ) {
73  const Gaudi::Property<std::string>* sp = dynamic_cast<const Gaudi::Property<std::string>*>( iter );
74  if ( sp && iter->name().compare( "Context" ) == 0 ) { m_context = sp->value(); }
75  }
76  }
77 }
78 //=============================================================================
79 
80 //=============================================================================
81 // Initialise the common functionality
82 //=============================================================================
83 template <class PBASE>
85 
86  // initialize base class
87  const StatusCode sc = base_class::initialize();
88  if ( sc.isFailure() ) { return Error( "Failed to initialise base class PBASE", sc ); }
89 
90  // some debug printout
91  if ( this->msgLevel( MSG::DEBUG ) ) {
92  this->debug() << "Initialize base class GaudiCommon<" << System::typeinfoName( typeid( PBASE ) ) << ">" << endmsg;
93  if ( !context().empty() ) this->debug() << "Created with context = '" << context() << "'" << endmsg;
94  }
95 
96  // Set up the CounterSummarySvc May need to be changed
97  m_counterSummarySvc = this->svcLoc()->service( "CounterSummarySvc", false );
98  if ( this->msgLevel( MSG::DEBUG ) ) {
99  if ( !m_counterSummarySvc )
100  this->debug() << "could not locate CounterSummarySvc, no counter summary will be made" << endmsg;
101  else
102  this->debug() << "found CounterSummarySvc OK" << endmsg;
103  }
104 
105  // properties will be printed if asked for or in "MSG::DEBUG" mode
106  if ( propsPrint() ) {
107  printProps( MSG::ALWAYS );
108  } else if ( this->msgLevel( MSG::DEBUG ) ) {
109  printProps( MSG::DEBUG );
110  }
111 
112  return sc;
113 }
114 //=============================================================================
115 
116 //=============================================================================
117 // Finalize the common functionality
118 //=============================================================================
119 template <class PBASE>
122 
123  // print the general information about statistical counters
124  if ( this->msgLevel( MSG::DEBUG ) || ( statPrint() && this->nCounters() > 0 ) ) {
125  // print general statistical counters
126  printStat( statPrint() ? MSG::ALWAYS : MSG::DEBUG );
127  }
128  // add all counters to the CounterSummarySvc
129  if ( m_counterSummarySvc && this->svcLoc()->existsService( "CounterSummarySvc" ) ) {
130  if ( this->msgLevel( MSG::DEBUG ) ) this->debug() << "adding counters to CounterSummarySvc" << endmsg;
131 
132  Gaudi::Utils::RegEx::matchList statList{m_statEntityList.value()};
133  Gaudi::Utils::RegEx::matchList counterList{m_counterList.value()};
134 
135  for ( const auto& i : m_countersOwn ) {
136  if ( statList.Or( i.first ) )
137  m_counterSummarySvc->addCounter( this->name(), i.first, i.second, Gaudi::CounterSummary::SaveStatEntity );
138  else if ( counterList.Or( i.first ) )
139  m_counterSummarySvc->addCounter( this->name(), i.first, i.second );
140  }
141  }
142  // release all located tools and services
143  if ( this->msgLevel( MSG::DEBUG ) ) {
144  this->debug() << "Tools to release :";
145  for ( const auto& i : m_managedTools ) { this->debug() << " " << i->name(); }
146  this->debug() << endmsg;
147  }
148  while ( !m_managedTools.empty() ) {
149  sc = ( releaseTool( m_managedTools.back() ) && sc ) ? StatusCode::SUCCESS : StatusCode::FAILURE;
150  }
151 
152  // release all located services
153  if ( this->msgLevel( MSG::DEBUG ) ) {
154  this->debug() << "Services to release :";
155  for ( const auto& i : m_services ) this->debug() << " " << i->name();
156  this->debug() << endmsg;
157  }
158  while ( !m_services.empty() ) {
159  sc = ( releaseSvc( m_services.front() ) && sc ) ? StatusCode::SUCCESS : StatusCode::FAILURE;
160  }
161 
162  // release the CounterSummarySvc manually
163  m_counterSummarySvc.reset();
164 
165  // format printout
166  if ( !m_errors.empty() || !m_warnings.empty() || !m_exceptions.empty() ) {
167  this->always() << "Exceptions/Errors/Warnings/Infos Statistics : " << m_exceptions.size() << "/" << m_errors.size()
168  << "/" << m_warnings.size() << "/" << m_infos.size() << endmsg;
169  if ( errorsPrint() ) { printErrors(); }
170  }
171 
172  // clear *ALL* counters explicitly
173  this->clearCounters();
174  m_countersOwn.clear(); // then delete any owned counters
175  m_exceptions.clear();
176  m_infos.clear();
177  m_warnings.clear();
178  m_errors.clear();
179  m_counterList.clear();
180  m_statEntityList.clear();
181 
182  // finalize base class
183  return ( sc && base_class::finalize() ? StatusCode::SUCCESS : StatusCode::FAILURE );
184 }
185 //=============================================================================
186 
187 //=============================================================================
188 // Methods related to tools and services
189 //=============================================================================
190 
191 // ============================================================================
192 // manual forced (and 'safe') release of the active tool or service
193 // ============================================================================
194 template <class PBASE>
196  if ( !interface ) { return Error( "release(IInterface):: IInterface* points to NULL!" ); }
197  // dispatch between tools and services
198  const IAlgTool* algTool = dynamic_cast<const IAlgTool*>( interface );
199  // perform the actual release
200  return algTool ? releaseTool( algTool ) : releaseSvc( interface );
201 }
202 // ============================================================================
203 
204 // ============================================================================
205 // manual forced (and 'save') release of the tool
206 // ============================================================================
207 template <class PBASE>
209  if ( !algTool ) { return Error( "releaseTool(IAlgTool):: IAlgTool* points to NULL!" ); }
210  if ( !this->toolSvc() ) { return Error( "releaseTool(IAlgTool):: IToolSvc* points to NULL!" ); }
211  // find a tool in the list of active tools
212  auto it = std::find( m_managedTools.begin(), m_managedTools.end(), algTool );
213  if ( m_managedTools.end() == it ) { return Warning( "releaseTool(IAlgTool):: IAlgTool* is not active" ); }
214  // get the tool
215  IAlgTool* t = *it;
216  // cache name
217  const std::string name = t->name();
218  if ( this->msgLevel( MSG::DEBUG ) ) { this->debug() << "Releasing tool '" << name << "'" << endmsg; }
219  // remove the tool from the lists
220  base_class::deregisterTool( t );
221  m_managedTools.erase( it );
222  // release tool
223  if ( this->msgLevel( MSG::DEBUG ) ) {
224  this->debug() << "The tool '" << t->name() << "' of type '" << System::typeinfoName( typeid( *t ) )
225  << "' is released" << endmsg;
226  }
227  const StatusCode sc = this->toolSvc()->releaseTool( t );
228  return sc.isSuccess() ? sc : Warning( "releaseTool(IAlgTool):: error from IToolSvc releasing " + name, sc );
229 }
230 // ============================================================================
231 
232 // ============================================================================
233 // manual forced (and 'safe') release of the service
234 // ============================================================================
235 template <class PBASE>
237  if ( !Svc ) return Error( "releaseSvc(IInterface):: IInterface* points to NULL!" );
238  SmartIF<IService> svc{const_cast<IInterface*>( Svc )};
239  if ( !svc ) return Warning( "releaseSvc(IInterface):: IInterface* is not a service" );
240  auto it = std::lower_bound( std::begin( m_services ), std::end( m_services ), svc, GaudiCommon_details::svc_lt );
241  if ( it == m_services.end() || !GaudiCommon_details::svc_eq( *it, svc ) ) {
242  return Warning( "releaseSvc(IInterface):: IInterface* is not active" );
243  }
244  if ( this->msgLevel( MSG::DEBUG ) ) { this->debug() << "Releasing service '" << ( *it )->name() << "'" << endmsg; }
245  m_services.erase( it );
246  return StatusCode::SUCCESS;
247 }
248 // ============================================================================
249 // ============================================================================
250 
251 // ============================================================================
252 // Add the given service to the list of active services
253 // ============================================================================
254 template <class PBASE>
256  if ( svc ) {
257  auto i = std::lower_bound( std::begin( m_services ), std::end( m_services ), svc, GaudiCommon_details::svc_lt );
258  if ( i == std::end( m_services ) || !GaudiCommon_details::svc_eq( *i, svc ) ) {
259  m_services.insert( i, std::move( svc ) );
260  } else {
261  this->warning() << "Service " << svc->name() << " already present -- skipping" << endmsg;
262  }
263  }
264 }
265 // ============================================================================
266 
267 //=============================================================================
268 // Methods related to messaging
269 //=============================================================================
270 
271 // ============================================================================
272 // Print the error message and return status code
273 // ============================================================================
274 template <class PBASE>
275 StatusCode GaudiCommon<PBASE>::Error( std::string_view msg, const StatusCode st, const size_t mx ) const {
276  // increase local counter of errors
277  const size_t num = increment( m_errors, msg );
278  // If suppressed, just return
279  if ( num > mx ) {
280  return st;
281  } else if ( UNLIKELY( num == mx ) ) // issue one-time suppression message
282  {
283  return Print( std::string{"The ERROR message is suppressed : '"}.append( msg ).append( "'" ), st, MSG::ERROR );
284  }
285  // return message
286  return Print( msg, st, MSG::ERROR );
287 }
288 // ============================================================================
289 
290 // ============================================================================
291 // Print the warning message and return status code
292 // ============================================================================
293 template <class PBASE>
294 StatusCode GaudiCommon<PBASE>::Warning( std::string_view msg, const StatusCode st, const size_t mx ) const {
295  // increase local counter of warnings
296  const size_t num = increment( m_warnings, msg );
297  // If suppressed, just return
298  if ( num > mx ) {
299  return st;
300  } else if ( UNLIKELY( num == mx ) ) // issue one-time suppression message
301  {
302  return Print( std::string{"The WARNING message is suppressed : '"}.append( msg ).append( "'" ), st, MSG::WARNING );
303  }
304  // return message
305  return Print( msg, st, MSG::WARNING );
306 }
307 // ============================================================================
308 
309 // ============================================================================
310 // Print the info message and return status code
311 // ============================================================================
312 template <class PBASE>
313 StatusCode GaudiCommon<PBASE>::Info( std::string_view msg, const StatusCode st, const size_t mx ) const {
314  // increase local counter of warnings
315  const size_t num = increment( m_infos, msg );
316  // If suppressed, just return
317  if ( num > mx ) {
318  return st;
319  } else if ( UNLIKELY( num == mx ) ) // issue one-time suppression message
320  {
321  return Print( std::string{"The INFO message is suppressed : '"}.append( msg ).append( "'" ), st, MSG::INFO );
322  }
323  // return message
324  return Print( msg, st, MSG::INFO );
325 }
326 // ============================================================================
327 
328 // ============================================================================
329 // Print the message and return status code
330 // ============================================================================
331 template <class PBASE>
332 StatusCode GaudiCommon<PBASE>::Print( std::string_view msg, const StatusCode st, const MSG::Level lvl ) const {
333  // perform printout ?
334  if ( !this->msgLevel( lvl ) ) { return st; } // RETURN
335 
336  // use the predefined stream
337  MsgStream& str = this->msgStream( lvl );
338  if ( typePrint() ) { str << System::typeinfoName( typeid( *this ) ) << ":: "; }
339 
340  // print the message
341  str << msg;
342 
343  // test status code
344  if ( st.isSuccess() ) {
345  } else if ( StatusCode::FAILURE != st ) {
346  str << " StatusCode=" << st.getCode();
347  } else {
348  str << " StatusCode=FAILURE";
349  }
350 
351  // perform print operation
352  str << endmsg;
353 
354  // return
355  return st;
356 }
357 // ============================================================================
358 
359 // ============================================================================
360 // Create and (re)-throw the exception
361 // ============================================================================
362 template <class PBASE>
363 void GaudiCommon<PBASE>::Exception( std::string_view msg, const GaudiException& exc, const StatusCode sc ) const {
364  // increase local counter of exceptions
365  increment( m_exceptions, msg );
366  Print( std::string{"Exception (re)throw: "}.append( msg ), sc, MSG::FATAL ).ignore();
367  throw GaudiException( ( this->name() + ":: " ).append( msg ), this->name(), sc, exc );
368 }
369 // ============================================================================
370 
371 // ============================================================================
372 // Create and (re)-throw the exception
373 // ============================================================================
374 template <class PBASE>
375 void GaudiCommon<PBASE>::Exception( std::string_view msg, const std::exception& exc, const StatusCode sc ) const {
376  // increase local counter of exceptions
377  increment( m_exceptions, msg );
378  Print( std::string{"Exception (re)throw: "}.append( msg ), sc, MSG::FATAL ).ignore();
379  throw GaudiException( ( this->name() + ":: " ).append( msg ) + "(" + exc.what() + ")", "", sc );
380 }
381 // ============================================================================
382 
383 // ============================================================================
384 // Create and throw the exception
385 // ============================================================================
386 template <class PBASE>
387 void GaudiCommon<PBASE>::Exception( std::string_view msg, const StatusCode sc ) const {
388  // increase local counter of exceptions
389  increment( m_exceptions, msg );
390  Print( std::string{"Exception throw: "}.append( msg ), sc, MSG::FATAL ).ignore();
391  throw GaudiException( ( this->name() + ":: " ).append( msg ), "", sc );
392 }
393 // ============================================================================
394 
395 // ============================================================================
396 // perform the actual printout of counters
397 // ============================================================================
398 template <class PBASE>
400  // check how many counters think they should be printed or how many
401  // we anyway want to print
402  auto countToBePrinted = [&]() {
403  unsigned n = 0;
404  this->forEachCounter( [&n]( const auto&, const auto& counter ) { n += counter.toBePrinted(); } );
405  return n;
406  };
407  auto nbPrintedCounters =
408  ( ( !m_printEmptyCounters && !this->msgLevel( MSG::DEBUG ) ) ? countToBePrinted() : this->nCounters() );
409  // in case nothing should be printed, let's stop here
410  if ( nbPrintedCounters == 0 ) return 0;
411  MsgStream& msg = this->msgStream( level );
412  msg << "Number of counters : " << nbPrintedCounters << "\n" << m_header.value();
413  this->forEachCounter( [&]( const auto& label, const auto& counter ) {
414  if ( m_printEmptyCounters || this->msgLevel( MSG::DEBUG ) || counter.toBePrinted() ) {
415  std::ostringstream ost;
416  counter.print( ost, label );
417  msg << "\n" << ost.str();
418  }
419  } );
420  //
421  msg << endmsg;
422  //
423  return nbPrintedCounters;
424 }
425 // ============================================================================
426 
427 // ============================================================================
428 // perform the actual printout of error counters
429 // ============================================================================
430 template <class PBASE>
432  auto print = [&]( const Counter& c, const auto& label ) {
433  for ( const auto& i : c ) {
434  this->msgStream( level ) << fmt::format( " #{:<10s} = {:<8d} Message = '{}'", label, i.second, i.first )
435  << endmsg;
436  }
437  };
438 
439  print( m_exceptions, "EXCEPTIONS" );
440  print( m_errors, "ERRORS" );
441  print( m_warnings, "WARNINGS" );
442  print( m_infos, "INFOS" );
443 
444  // return total number of errors+warnings+exceptions
445  return m_exceptions.size() + m_errors.size() + m_warnings.size() + m_infos.size();
446 }
447 // ============================================================================
448 
449 // ============================================================================
453 // ============================================================================
454 template <class PBASE>
456 
457  // print ALL properties
458  MsgStream& msg = this->msgStream( level );
459  const auto& properties = this->getProperties();
460  msg << "List of ALL properties of " << System::typeinfoName( typeid( *this ) ) << "/" << this->name()
461  << " #properties = " << properties.size() << endmsg;
462  for ( const auto& property : reverse( properties ) ) { msg << "Property ['Name': Value] = " << *property << endmsg; }
463  return properties.size();
464 }
465 // ============================================================================
466 
467 // ============================================================================
468 // Methods for dealing with the TES and TDS
469 // ============================================================================
470 
471 // ============================================================================
472 // put results into Gaudi Event Transient Store
473 // ============================================================================
474 template <class PBASE>
476  std::string_view location, const bool useRootInTES ) const {
477  // check arguments
478  Assert( svc, "put():: Invalid 'service'!" );
479  Assert( static_cast<bool>( object ), "put():: Invalid 'Object'!" );
480  Assert( !location.empty(), "put():: Invalid 'address' = '' " );
481  // final data location
482  const auto& fullLocation = this->fullTESLocation( location, useRootInTES );
483  // register the object!
484  const StatusCode status = '/' == fullLocation[0] ? svc->registerObject( fullLocation, object.get() )
485  : svc->registerObject( "/Event/" + fullLocation, object.get() );
486  // check the result!
487  DataObject& obj = *object;
488  if ( status.isFailure() ) {
489  Exception( "put():: could not register '" + System::typeinfoName( typeid( obj ) ) + "' at address '" +
490  fullLocation + "'",
491  status );
492  }
493  if ( this->msgLevel( MSG::DEBUG ) ) {
494  Print( "The object of type '" + System::typeinfoName( typeid( obj ) ) + "' is registered in TS at address '" +
495  fullLocation + "'",
496  status, MSG::DEBUG )
497  .ignore();
498  }
499  // if we get here, ownership has been transferred to the IDataProviderSvc
500  return object.release();
501 }
502 // ============================================================================
503 
504 // ============================================================================
505 // The END
506 // ============================================================================
code_t getCode() const
Retrieve value ("checks" the StatusCode)
Definition: StatusCode.h:152
#define UNLIKELY(x)
Definition: Kernel.h:106
Definition of the MsgStream class used to transmit messages.
Definition: MsgStream.h:34
Header file for class GaudiAlgorithm.
Define general base for Gaudi exception.
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
Definition: MsgStream.cpp:119
long printStat(const MSG::Level level=MSG::ALWAYS) const
perform the actual printout of statistical counters
Implementation of property with value of concrete type.
Definition: Property.h:370
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:308
StatusCode Error(std::string_view msg, const StatusCode st=StatusCode::FAILURE, const size_t mx=10) const
Print the error message and return with the given StatusCode.
constexpr const struct GaudiCommon_details::svc_eq_t svc_eq
::details::reverse_wrapper< T > reverse(T &&iterable)
Definition: reverse.h:59
Header file for class GaudiAlgorithm.
void addToServiceList(SmartIF< IService > svc) const
Add the given service to the list of acquired services.
constexpr static const auto SUCCESS
Definition: StatusCode.h:100
StatusCode Print(std::string_view msg, const StatusCode st=StatusCode::SUCCESS, const MSG::Level lev=MSG::INFO) const
Print the message and return with the given StatusCode.
long printErrors(const MSG::Level level=MSG::ALWAYS) const
perform the actual printout of error counters
T end(T... args)
StatusCode finalize() override
standard finalization method
StatusCode Info(std::string_view msg, const StatusCode st=StatusCode::SUCCESS, const size_t mx=10) const
Print the info message and return with the given StatusCode.
auto get(const Handle &handle, const Algo &, const EventContext &) -> decltype(details::deref(handle.get()))
Data provider interface definition.
T lower_bound(T... args)
virtual const std::string & name() const =0
Retrieve the name of the instance.
STL class.
constexpr const struct GaudiCommon_details::svc_lt_t svc_lt
T what(T... args)
void Exception(std::string_view msg, const GaudiException &exc, const StatusCode sc=StatusCode(StatusCode::FAILURE, true)) const
Create and (re)-throw a given GaudiException.
StatusCode releaseTool(const IAlgTool *tool) const
manual forced (and 'safe') release of the tool
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:61
T append(T... args)
Definition of the basic interface.
Definition: IInterface.h:254
StatusCode Warning(std::string_view msg, const StatusCode st=StatusCode::FAILURE, const size_t mx=10) const
Print the warning message and return with the given StatusCode.
long printProps(const MSG::Level level=MSG::ALWAYS) const
perform the actual printout of properties
The useful base class for data processing algorithms.
StatusCode releaseSvc(const IInterface *svc) const
manual forced (and 'safe') release of the service
T str(T... args)
std::string fullTESLocation(std::string_view location, std::string_view rit)
Definition: FixTESPath.cpp:56
collection of useful utilities to print certain objects (currently used for implementation in class G...
bool isSuccess() const
Definition: StatusCode.h:366
STL class.
T move(T... args)
StatusCode initialize() override
standard initialization method
StatusCode release(const IInterface *interface) const
Manual forced (and 'safe') release of the active tool or service.
T find(T... args)
STL class.
StatusCode registerObject(std::string_view fullPath, DataObject *pObject)
Register object with the data store.
T begin(T... args)
The interface implemented by the AlgTool base class.
Definition: IAlgTool.h:33
constexpr static const auto FAILURE
Definition: StatusCode.h:101
const Gaudi::Algorithm & parent
The useful base class for tools.
Definition: GaudiTool.h:111
bool isFailure() const
Definition: StatusCode.h:145
DataObject * put(IDataProviderSvc *svc, std::unique_ptr< DataObject > object, std::string_view location, const bool useRootInTES=true) const
Register a data object or container into Gaudi Event Transient Store.
A DataObject is the base class of any identifiable object on any data store.
Definition: DataObject.h:40
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:202
void initGaudiCommonConstructor(const IInterface *parent=nullptr)
Constructor initializations.