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