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