diff --git a/HLT/Trigger/TrigControl/TrigServices/CMakeLists.txt b/HLT/Trigger/TrigControl/TrigServices/CMakeLists.txt index e778a7736a982b223e085bca97a4c56b21a02154..dbc97d83ec1c01f9eb34d166fbd23ca6d0636466 100644 --- a/HLT/Trigger/TrigControl/TrigServices/CMakeLists.txt +++ b/HLT/Trigger/TrigControl/TrigServices/CMakeLists.txt @@ -22,6 +22,7 @@ atlas_depends_on_subdirs( PUBLIC Trigger/TrigDataAccess/TrigROBDataProviderSvc Trigger/TrigEvent/TrigSteeringEvent PRIVATE + Control/CxxUtils Database/AthenaPOOL/AthenaPoolUtilities Trigger/TrigConfiguration/TrigConfInterfaces Trigger/TrigSteer/TrigOutputHandling ) diff --git a/HLT/Trigger/TrigControl/TrigServices/python/TrigServicesConfig.py b/HLT/Trigger/TrigControl/TrigServices/python/TrigServicesConfig.py index 4f7f02252d2c028da54c2a435c08c49f4d327aae..a50c90630b3443136752af038bb12934fc2c8eb1 100644 --- a/HLT/Trigger/TrigControl/TrigServices/python/TrigServicesConfig.py +++ b/HLT/Trigger/TrigControl/TrigServices/python/TrigServicesConfig.py @@ -35,13 +35,15 @@ class TrigCOOLUpdateHelper(_TrigCOOLUpdateHelper): def setupMessageSvc(): from AthenaCommon.AppMgr import theApp from AthenaCommon.AppMgr import ServiceMgr as svcMgr - from AthenaCommon.Constants import VERBOSE, DEBUG, INFO, WARNING + from AthenaCommon.Constants import VERBOSE, DEBUG, INFO, WARNING, ERROR svcMgr.MessageSvc = theApp.service( "MessageSvc" ) # already instantiated MessageSvc = svcMgr.MessageSvc MessageSvc.OutputLevel = theApp.OutputLevel MessageSvc.Format = "% F%40W%S%4W%e%s%7W%R%T %0W%M" + MessageSvc.ErsFormat = "%S: %M" + MessageSvc.printEventIDLevel = WARNING # Message suppression MessageSvc.enableSuppression = False @@ -63,20 +65,12 @@ def setupMessageSvc(): MessageSvc.defaultLimit = 0 MessageSvc.enableSuppression = False - # publish message counts during RUNNING in histogram - MessageSvc.publishStats = True - MessageSvc.publishLevel = INFO - # show summary statistics of messages in finalize MessageSvc.showStats = True MessageSvc.statLevel = WARNING MessageSvc.statLevelRun = VERBOSE - # publish message counts during RUNNING in histogram - MessageSvc.publishStats = True - MessageSvc.publishLevel = INFO - -# online ROB data provider service +# online ROB data provider service from TrigServicesConf import HltROBDataProviderSvc as _HltROBDataProviderSvc class HltROBDataProviderSvc(_HltROBDataProviderSvc): __slots__ = () diff --git a/HLT/Trigger/TrigControl/TrigServices/src/THistSvcHLT.cxx b/HLT/Trigger/TrigControl/TrigServices/src/THistSvcHLT.cxx index e253e0663f7307316a0ec35c01411735fcb765ef..7e8cc47879fe78b2454045516eaa4949ffc9ceef 100644 --- a/HLT/Trigger/TrigControl/TrigServices/src/THistSvcHLT.cxx +++ b/HLT/Trigger/TrigControl/TrigServices/src/THistSvcHLT.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration */ /* * This is a copy of GaudiSvc/src/THistSvc with THistSvc renamed to THistSvcHLT @@ -36,6 +36,8 @@ // local headers #include "THistSvcHLT.h" +ATLAS_NO_CHECK_FILE_THREAD_SAFETY; // copied from Gaudi, no checking + namespace { template <typename InputIterator, typename OutputIterator, typename UnaryOperation, typename UnaryPredicate> diff --git a/HLT/Trigger/TrigControl/TrigServices/src/THistSvcHLT.h b/HLT/Trigger/TrigControl/TrigServices/src/THistSvcHLT.h index 5832fc6f574fa0319a9cfa7222498117423f5a67..4623886d31fd89c4d752110aaec9d05bca5f7453 100644 --- a/HLT/Trigger/TrigControl/TrigServices/src/THistSvcHLT.h +++ b/HLT/Trigger/TrigControl/TrigServices/src/THistSvcHLT.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration */ /* * This is a copy of GaudiSvc/src/THistSvc with THistSvc renamed to THistSvcHLT @@ -33,6 +33,9 @@ #include "AthenaBaseComps/AthService.h" +#include "CxxUtils/checker_macros.h" +ATLAS_NO_CHECK_FILE_THREAD_SAFETY; // copied from Gaudi, no checking + class IIncidentSvc; class THistSvcHLT : public extends<AthService, ITHistSvc, IIncidentListener, IIoComponent> diff --git a/HLT/Trigger/TrigControl/TrigServices/src/TrigHLTIssues.h b/HLT/Trigger/TrigControl/TrigServices/src/TrigHLTIssues.h deleted file mode 100644 index 3e282bed7f22c33b796532ebbe471a159217b16f..0000000000000000000000000000000000000000 --- a/HLT/Trigger/TrigControl/TrigServices/src/TrigHLTIssues.h +++ /dev/null @@ -1,37 +0,0 @@ -// Dear emacs, this is -*- c++ -*- - -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -/** - * @file TrigHLTIssues.h - * @author <a href="mailto:Werner.Wiedenmann@cern.ch">Werner Wiedenmann</a> - * - * @brief ERS issue classes for HLT - */ - -#ifndef TRIG_HLT_ISSUES_H -#define TRIG_HLT_ISSUES_H - -#include "ers/ers.h" - -ERS_DECLARE_ISSUE( ers, HLTMessage, , ) -ERS_DECLARE_ISSUE( ers, HLTAbort, "Fatal error during event processing", ) - -#define ERS_HLT_WARNING( message ) \ -{ \ - ERS_REPORT_IMPL( ers::warning, ers::HLTMessage, message, ); \ -} - -#define ERS_HLT_ERROR( message ) \ -{ \ - ERS_REPORT_IMPL( ers::error, ers::HLTMessage, message, ); \ -} - -#define ERS_HLT_FATAL( message ) \ -{ \ - ERS_REPORT_IMPL( ers::fatal, ers::HLTMessage, message, ); \ -} - -#endif /* TRIG_HLT_ISSUES_H */ diff --git a/HLT/Trigger/TrigControl/TrigServices/src/TrigMessageSvc.cxx b/HLT/Trigger/TrigControl/TrigServices/src/TrigMessageSvc.cxx index 6406101bbf0e6e680cbe6025378ef1feecf1871f..d13cc16ef6d871cbf2ea5fcf4583a98d0bc0d2e5 100644 --- a/HLT/Trigger/TrigControl/TrigServices/src/TrigMessageSvc.cxx +++ b/HLT/Trigger/TrigControl/TrigServices/src/TrigMessageSvc.cxx @@ -1,1181 +1,380 @@ /* Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration */ - +#include "TrigMessageSvc.h" +#include "GaudiKernel/IAppMgrUI.h" #include "GaudiKernel/Kernel.h" -#include "GaudiKernel/IIncidentSvc.h" -#include "GaudiKernel/ITHistSvc.h" -#include "GaudiKernel/StatusCode.h" #include "GaudiKernel/Message.h" -#include "GaudiKernel/IJobOptionsSvc.h" -#include "EventInfo/EventInfo.h" -#include "EventInfo/EventID.h" -#include "TrigMessageSvc.h" -#include "TrigHLTIssues.h" -#include "TrigMonitorBase/TrigLockedHist.h" +#include "GaudiKernel/StatusCode.h" +#include "GaudiKernel/System.h" -#include <TH1I.h> -#include <TH2I.h> +#include "ers/ers.h" -#include <sstream> +#include <fstream> #include <iostream> +#include <sstream> -#include <pthread.h> -#include <boost/thread/recursive_mutex.hpp> - - -static pthread_mutex_t msgsvcmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; - -using namespace std; +// Declare ERS issue type +ERS_DECLARE_ISSUE(ers, HLTMessage, , ) -static std::string levelNames[MSG::NUM_LEVELS]; +static const std::string levelNames[MSG::NUM_LEVELS] = {"NIL", "VERBOSE", "DEBUG", "INFO", + "WARNING", "ERROR", "FATAL", "ALWAYS"}; -// ERS debug level for which to enforce DEBUG OutputLevel -static int ersGaudiDebugOffset = 8; +namespace { + /// Calculate message hash ignoring any digits + size_t msgHash(const Message& msg) + { + std::string s = msg.getSource() + msg.getMessage(); + s.erase(std::remove_if(s.begin(), s.end(), [](char c) { return std::isdigit(c); }), s.end()); + return std::hash<std::string>()(s); + } +} // namespace -// Constructor -TrigMessageSvc::TrigMessageSvc( const std::string& name, ISvcLocator* svcloc ) - : base_class(name, svcloc) - , m_doSuppress{false} - , m_running{false} - , m_canEnter{false} - , m_evtStore{"StoreGateSvc/StoreGateSvc", name} - , m_msgCountHist{nullptr} - , m_msgCountSrcHist{nullptr} +TrigMessageSvc::TrigMessageSvc(const std::string& name, ISvcLocator* svcloc) : + base_class(name, svcloc) { - m_defaultStream = &std::cout; - m_outputLevel = MSG::NIL; - declareProperty( "Format", m_defaultFormat = "% F%18W%S%7W%R%T %0W%M" ); - declareProperty( "timeFormat", m_defaultTimeFormat = "%Y-%m-%d %H:%M:%S,%f" ); - - declareProperty( "showStats", m_stats = false ); - declareProperty( "statLevel", m_statLevel = 0, "Show statistics for messages >= level" ); - declareProperty( "statLevelRun", m_statLevelRun = 0, "Show per-run statistics for messages >= level" ); - - declareProperty( "publishStats", m_publishStats = false, - "Publish message statistics as histogram"); - - declareProperty( "publishLevel", m_publishLevel = MSG::INFO, - "Publish message statistics for this and higher message levels"); - - declareProperty( "resetStatsAtBeginRun", m_resetStats = false ); - - declareProperty( "printEventIDLevel", m_eventIDLevel = MSG::WARNING, - "Print event ID for this and higher message levels"); - - // Special properties to control output level of individual sources - declareProperty( "setVerbose", m_thresholdProp[MSG::VERBOSE] ); - declareProperty( "setDebug", m_thresholdProp[MSG::DEBUG] ); - declareProperty( "setInfo", m_thresholdProp[MSG::INFO] ); - declareProperty( "setWarning", m_thresholdProp[MSG::WARNING] ); - declareProperty( "setError", m_thresholdProp[MSG::ERROR] ); - declareProperty( "setFatal", m_thresholdProp[MSG::FATAL] ); - declareProperty( "setAlways", m_thresholdProp[MSG::ALWAYS] ); - - declareProperty( "useColors", m_color=false); - m_color.declareUpdateHandler(&TrigMessageSvc::initColors, this); - - declareProperty( "fatalColorCode", m_logColors[MSG::FATAL] ); - declareProperty( "errorColorCode", m_logColors[MSG::ERROR] ); - declareProperty( "warningColorCode", m_logColors[MSG::WARNING] ); - declareProperty( "infoColorCode", m_logColors[MSG::INFO] ); - declareProperty( "debugColorCode", m_logColors[MSG::DEBUG] ); - declareProperty( "verboseColorCode", m_logColors[MSG::VERBOSE] ); - declareProperty( "alwaysColorCode", m_logColors[MSG::ALWAYS] ); - - m_defaultLimit = 500; - declareProperty( "fatalLimit", m_msgLimit[MSG::FATAL] = m_defaultLimit ); - declareProperty( "errorLimit", m_msgLimit[MSG::ERROR] = m_defaultLimit ); - declareProperty( "warningLimit", m_msgLimit[MSG::WARNING] = m_defaultLimit ); - declareProperty( "infoLimit", m_msgLimit[MSG::INFO] = m_defaultLimit ); - declareProperty( "debugLimit", m_msgLimit[MSG::DEBUG] = m_defaultLimit ); - declareProperty( "verboseLimit", m_msgLimit[MSG::VERBOSE] = m_defaultLimit ); - declareProperty( "alwaysLimit", m_msgLimit[MSG::ALWAYS] = 0 ); + m_outputLevel.declareUpdateHandler([svcloc](Gaudi::Details::PropertyBase&) { + SmartIF<IAppMgrUI> app = svcloc; + if (app) app->outputLevelUpdate(); + }); - declareProperty( "defaultLimit", m_msgLimit[MSG::NIL] = m_defaultLimit ); - - declareProperty( "enableSuppression", m_suppress = false, - "Enable message suppression"); - - declareProperty( "suppressRunningOnly", m_suppressRunningOnly = true, - "Use message suppression only during RUNNING state"); - - m_suppress.declareUpdateHandler(&TrigMessageSvc::setupSuppression, this); - m_suppressRunningOnly.declareUpdateHandler(&TrigMessageSvc::setupSuppression, this); - - /* Special properties to control output to ERS of individual sources. - The syntax is as follows (these are NOT regular expressions): - - useErsFatal = [] # forward none (default) - useErsFatal = ['*'] # forward all - useErsFatal = ['CoreDumpSvc','MyAlg'] # forward these sources - useErsFatal = ['*','!MyAlg'] # forward all except MyAlg - */ - - const vector<string> defaultErsUse; - declareProperty( "useErsVerbose", m_useERS[MSG::VERBOSE] = defaultErsUse ); - declareProperty( "useErsDebug", m_useERS[MSG::DEBUG] = defaultErsUse ); - declareProperty( "useErsInfo", m_useERS[MSG::INFO] = defaultErsUse ); - declareProperty( "useErsWarning", m_useERS[MSG::WARNING] = defaultErsUse ); - declareProperty( "useErsError", m_useERS[MSG::ERROR] = defaultErsUse ); - declareProperty( "useErsFatal", m_useERS[MSG::FATAL] = defaultErsUse ); - declareProperty( "useErsAlways", m_useERS[MSG::ALWAYS] = defaultErsUse ); - - declareProperty( "alwaysUseMsgStream", m_alwaysUseMsgStream = true, - "Print all messages to MsgStream, even if forwarded to ERS"); - - declareProperty( "useErsRunningOnly", m_useErsRunningOnly = false, - "Forward messages to ERS only during RUNNING state"); - - declareProperty( "forceOutputLevel", m_forceOutputLevel = false, - "Enforce the global OutputLevel for all sources"); - - for (int ic=0; ic<MSG::NUM_LEVELS; ++ic) { - m_logColors[ic].declareUpdateHandler(&TrigMessageSvc::setupColors, this); + for (int ic = 0; ic < MSG::NUM_LEVELS; ++ic) { m_msgLimit[ic].declareUpdateHandler(&TrigMessageSvc::setupLimits, this); m_thresholdProp[ic].declareUpdateHandler(&TrigMessageSvc::setupThreshold, this); } - levelNames[0] = "NIL"; - levelNames[1] = "VERBOSE"; - levelNames[2] = "DEBUG"; - levelNames[3] = "INFO"; - levelNames[4] = "WARNING"; - levelNames[5] = "ERROR"; - levelNames[6] = "FATAL"; - levelNames[7] = "ALWAYS"; - -} -//############################################################################# -// Destructor -TrigMessageSvc::~TrigMessageSvc() -{ - pthread_mutex_destroy(&msgsvcmutex); + std::fill(std::begin(m_msgCount), std::end(m_msgCount), 0); } -/// Initialize Service -StatusCode TrigMessageSvc::initialize() { - - StatusCode sc; - sc = Service::initialize(); - if( sc.isFailure() ) return sc; - - m_running = false; - m_canEnter = true; - -#ifdef _WIN32 - m_color = false; -#endif - - // Reset message counters - resetMsgStats(); - m_sourceMapTotal.clear(); - - // Initialize message suppression - setupSuppression(m_suppress); +StatusCode TrigMessageSvc::initialize() +{ + StatusCode sc = Service::initialize(); + if (sc.isFailure()) return sc; - m_colMap["black"] = MSG::BLACK; - m_colMap["red"] = MSG::RED; - m_colMap["green"] = MSG::GREEN; - m_colMap["yellow"] = MSG::YELLOW; - m_colMap["blue"] = MSG::BLUE; - m_colMap["purple"] = MSG::PURPLE; - m_colMap["cyan"] = MSG::CYAN; - m_colMap["white"] = MSG::WHITE; + m_doSuppress = m_suppress; - /* - * m_state is set in the base class sysInitialize after initialize succeeded. - * However, we need to set it already here otherwise the following - * use of IncidentSvc/JobOptionsSvc creates a service initialization loop. - */ - m_state = Gaudi::StateMachine::INITIALIZED; - - /* - * This will force the OutputLevel of all components to be the global - * OutputLevel (m_outputLevel of this service). It should cover the use-cases: - * 1) 'MsgStream(msgSvc(),name())' - * 2) 'MsgStream::setLevel(m_outputLevel)' - * For 2) we rely on the fact that the MessageSvc is created/initialized after - * the JobOptionsSvc in ApplicationMgr::i_startup(). - */ - int ers_debug = ers::Configuration::instance().debug_level(); - if ( ers_debug >= ersGaudiDebugOffset+1 ) { - setOutputLevel(MSG::VERBOSE); - m_forceOutputLevel.setValue(true); + if (m_color) { + std::cout << "TrigMessageSvc WARNING: Colors are not supported by TrigMessageSvc" << std::endl; } - else if ( ers_debug >= ersGaudiDebugOffset ) { - setOutputLevel(MSG::DEBUG); - m_forceOutputLevel.setValue(true); - } - - if ( m_forceOutputLevel.value() ) { - resetOutputLevels(); // Clear all individual OutputLevels (to cover use-case 1) - setOutputLevelViaJobOptSvc(); // Set 'OutputLevel' in JobOptionsSvc (to cover use-case 2) - reportMessage(name(), MSG::INFO, "Enforcing global OutputLevel = "+levelNames[m_outputLevel.value()]); - } - - // Register incident handlers - ServiceHandle<IIncidentSvc> incSvc("IncidentSvc",name()); - sc = incSvc.retrieve(); - if (sc.isFailure()) { - reportMessage(name(), MSG::WARNING, "Cannot find IncidentSvc"); - } - else { - incSvc->addListener(this, "BeginRun", LONG_MAX); - incSvc->addListener(this, "EndOfBeginRun", LONG_MAX); - incSvc->addListener(this, "EndRun", LONG_MAX); - } - - return StatusCode::SUCCESS; + return StatusCode::SUCCESS; } -//############################################################################# - -/// Reinitialize Service -StatusCode TrigMessageSvc::reinitialize() { +StatusCode TrigMessageSvc::reinitialize() +{ m_state = Gaudi::StateMachine::OFFLINE; return initialize(); } - -//############################################################################# -void TrigMessageSvc::handle(const Incident& inc) { - - // We cannot use start/stop for the MessageSvc due to bug #46216 - if (inc.type()=="BeginRun") { - if (m_suppressRunningOnly.value()) { - m_doSuppress = m_suppress.value(); - } - if (m_publishStats) bookHistograms(); - } - else if (inc.type()=="EndOfBeginRun") { - if (m_resetStats) { - reportMessage(name(), MSG::INFO, "Resetting message counts"); - resetMsgStats(); - } - m_running = true; - } - else if (inc.type()=="EndRun") { - m_running = false; - if (m_resetStats) reportMsgStats(MSG::INFO); - if (m_suppressRunningOnly.value()) m_doSuppress = false; - } -} - - -//############################################################################# -void TrigMessageSvc::resetMsgStats() +void TrigMessageSvc::setupLimits(Gaudi::Details::PropertyBase& prop) { - // Copy current counts to total counts map - std::map<std::string,msgAry>::const_iterator itr; - std::map<std::string,msgAry>::iterator tot; - for (itr=m_sourceMap.begin(); itr!=m_sourceMap.end(); ++itr) { - tot = m_sourceMapTotal.find(itr->first); - if (tot==m_sourceMapTotal.end()) { // new entry - for (int i=0; i<MSG::NUM_LEVELS; i++) m_sourceMapTotal[itr->first].msg[i] = itr->second.msg[i]; - } - else { // existing entry - for (int i=0; i<MSG::NUM_LEVELS; i++) tot->second.msg[i] += itr->second.msg[i]; - } - } - - m_sourceMap.clear(); - m_msgCountMap.clear(); - for (int i=0; i<MSG::NUM_LEVELS; i++) m_msgCount[i] = 0; -} - - -// --------------------------------------------------------------------------- -// Book the message stats histograms -// --------------------------------------------------------------------------- -void TrigMessageSvc::bookHistograms() -{ - ServiceHandle<ITHistSvc> histSvc("THistSvc",name()); - if ( histSvc.retrieve().isFailure() ) { - reportMessage(name(), MSG::WARNING, - "Cannot find THistSvc. Message stats will not be published."); - return; - } - - // monitoring information root directory - const string path = "/EXPERT/" + name() + "/"; - const int nLevelBins = MSG::NUM_LEVELS - m_publishLevel; - m_msgCountHist = new TH1I("MessageCount", "Messages while RUNNING;Severity;Count", - nLevelBins, 0, nLevelBins); - - const int nSrcBins = 1; - m_msgCountSrcHist = new TH2I("MessageCountBySource", "Messages while RUNNING;Severity;Source", - nLevelBins, 0, nLevelBins, nSrcBins, 0, nSrcBins); - - - for (int i=m_publishLevel; i<MSG::NUM_LEVELS; i++) { - m_msgCountHist->GetXaxis()->SetBinLabel(i-m_publishLevel+1, levelNames[i].c_str()); - m_msgCountSrcHist->GetXaxis()->SetBinLabel(i-m_publishLevel+1, levelNames[i].c_str()); - } - - if ( histSvc->regHist(path + m_msgCountHist->GetName(), m_msgCountHist).isFailure() ) { - reportMessage(name(), MSG::WARNING, "Cannot register monitoring histogram 'MessageCount'"); - } - if ( histSvc->regHist(path + m_msgCountSrcHist->GetName(), m_msgCountSrcHist).isFailure() ) { - reportMessage(name(), MSG::WARNING, "Cannot register monitoring histogram 'MessageCountBySource'"); - } -} - -void TrigMessageSvc::initColors(Property& /*prop*/) { - - if (m_color == true) { - - if (m_logColors[MSG::FATAL].value().size() == 0) { - vector<string> fatDef; - fatDef.push_back( "[94;101;1m" ); - m_logColors[MSG::FATAL].set( fatDef ); - } else { - TrigMessageSvc::setupColors( m_logColors[MSG::FATAL] ); - } - - if (m_logColors[MSG::ERROR].value().size() == 0) { - vector<string> errDef; - errDef.push_back( "[97;101;1m" ); - m_logColors[MSG::ERROR].set( errDef ); - } else { - TrigMessageSvc::setupColors( m_logColors[MSG::ERROR] ); - } - - if (m_logColors[MSG::WARNING].value().size() == 0) { - vector<string> warDef; - warDef.push_back( "[93;1m" ); - m_logColors[MSG::WARNING].set( warDef ); - } else { - TrigMessageSvc::setupColors( m_logColors[MSG::WARNING] ); - } - - } else { - - // reset all color codes; - for (int ic=0; ic<MSG::NUM_LEVELS; ++ic) { - vector<string> def; - m_logColors[ic].set( def ); - } - - } - -} - -//############################################################################# - -void TrigMessageSvc::setupColors(Property& prop) { - - if (! m_color) return; - - int ic; - if (prop.name() == "fatalColorCode") { - ic = MSG::FATAL; - } else if (prop.name() == "errorColorCode") { - ic = MSG::ERROR; - } else if (prop.name() == "warningColorCode") { - ic = MSG::WARNING; - } else if (prop.name() == "infoColorCode") { - ic = MSG::INFO; - } else if (prop.name() == "debugColorCode") { - ic = MSG::DEBUG; - } else if (prop.name() == "verboseColorCode") { - ic = MSG::VERBOSE; - } else if (prop.name() == "alwaysColorCode") { - ic = MSG::ALWAYS; - } else { - std::ostringstream internal_msg ; - internal_msg << "ERROR: Unknown message color parameter: " << prop.name(); - if (passErsFilter(name(), m_useERS[MSG::ERROR])) { - ers::error( ers::HLTMessage(ERS_HERE,internal_msg.str()) ); - } else { - std::cerr << internal_msg.str() << std::endl; - } - return; - } - - string code; - vector<string>::const_iterator itr; - itr = m_logColors[ic].value().begin(); - - if ( m_logColors[ic].value().size() == 1 ) { - - if (*itr == "") { - code = ""; - } else if (itr->substr(0,1) == "[") { - code = "\033" + *itr; - } else { - code = "\033[" + colTrans(*itr, 90) + ";1m"; - } - - } else if (m_logColors[ic].value().size() == 2) { - vector<string>::const_iterator itr2 = itr + 1; - - code = "\033[" + colTrans(*itr, 90) + ";" - + colTrans(*itr2, 100) + ";1m"; - - } - - m_logColorCodes[ic] = code; - -} -//############################################################################# - -void TrigMessageSvc::setupLimits(Property& prop) { - const auto& pname = prop.name(); - if (pname == "alwaysLimit") { - IntegerProperty *p = dynamic_cast<IntegerProperty*>(&prop); + // Just report problems in the settings of the limits and unknown limit + // parameters + if (prop.name() == "alwaysLimit") { + Gaudi::Property<int>* p = dynamic_cast<Gaudi::Property<int>*>(&prop); if (p && p->value() != 0) { - std::ostringstream internal_msg ; - internal_msg << "TrigMessageSvc ERROR: cannot suppress ALWAYS messages" ; - if (passErsFilter(name(), m_useERS[MSG::ERROR])) { - ers::error( ers::HLTMessage(ERS_HERE,internal_msg.str()) ); - } else { - std::cerr << internal_msg.str() << std::endl; - } + std::cout << "TrigMessageSvc ERROR: cannot suppress ALWAYS messages" << std::endl; p->setValue(0); } - } else if (pname == "defaultLimit") { - // Only change the limits that are still on the default value - for (int i = MSG::VERBOSE; i< MSG::NUM_LEVELS; ++i) { - if ( (i != MSG::ALWAYS) && (m_msgLimit[i].value() == m_defaultLimit) ) { + } + else if (prop.name() == "defaultLimit") { + for (int i = MSG::VERBOSE; i < MSG::NUM_LEVELS; ++i) { + if (i != MSG::ALWAYS) { m_msgLimit[i] = m_msgLimit[MSG::NIL].value(); } } - } else if (pname != "fatalLimit" && - pname != "errorLimit" && - pname != "warningLimit" && - pname != "infoLimit" && - pname != "debugLimit" && - pname != "verboseLimit") { - std::ostringstream internal_msg ; - internal_msg << "TrigMessageSvc ERROR: Unknown message limit parameter: " << prop.name() ; - if (passErsFilter(name(), m_useERS[MSG::ERROR])) { - ers::error( ers::HLTMessage(ERS_HERE,internal_msg.str()) ); - } else { - std::cerr << internal_msg.str() << std::endl; - } - return; } -} -//############################################################################# - -void TrigMessageSvc::setupThreshold(Property& prop) { - - int ic = 0; - if (prop.name() == "setFatal") { - ic = MSG::FATAL; - } else if (prop.name() == "setError") { - ic = MSG::ERROR; - } else if (prop.name() == "setWarning") { - ic = MSG::WARNING; - } else if (prop.name() == "setInfo") { - ic = MSG::INFO; - } else if (prop.name() == "setDebug") { - ic = MSG::DEBUG; - } else if (prop.name() == "setVerbose") { - ic = MSG::VERBOSE; - } else if (prop.name() == "setAlways") { - ic = MSG::ALWAYS; - } else { - std::ostringstream internal_msg ; - internal_msg << "TrigMessageSvc ERROR: Unknown message theshold parameter: " << prop.name(); - if (passErsFilter(name(), m_useERS[MSG::ERROR])) { - ers::error( ers::HLTMessage(ERS_HERE,internal_msg.str()) ); - } else { - std::cerr << internal_msg.str() << std::endl; - } - return; - } - - StringArrayProperty *sap = dynamic_cast<StringArrayProperty*>( &prop); - if (sap == 0) { - std::ostringstream internal_msg ; - internal_msg << "could not dcast " << prop.name() - << " to a StringArrayProperty (which it should be!)"; - if (passErsFilter(name(),m_useERS[MSG::ERROR])) { - ers::error( ers::HLTMessage(ERS_HERE,internal_msg.str()) ); - } else { - std::cerr << internal_msg.str() << std::endl; - } + else if (prop.name() != "fatalLimit" && prop.name() != "errorLimit" && + prop.name() != "warningLimit" && prop.name() == "infoLimit" && + prop.name() == "debugLimit" && prop.name() == "verboseLimit") { + std::cout << "TrigMessageSvc ERROR: Unknown message limit parameter: " << prop.name() + << std::endl; return; - } else { - std::vector<std::string>::const_iterator itr; - for ( itr = sap->value().begin(); - itr != sap->value().end(); - ++itr) { - setOutputLevel( *itr, ic ); - } } - } -//############################################################################# - -bool TrigMessageSvc::passErsFilter(const std::string& source, - const std::vector<std::string>& filter) +void TrigMessageSvc::setupThreshold(Gaudi::Details::PropertyBase& prop) { - if (m_useErsRunningOnly.value() and not m_running) return false; - if (filter.empty()) return false; // forward none - vector<string>::const_iterator it = filter.begin(); - if (filter.size()==1 && (*it)=="*") return true; // forward all - - bool pass(false); - for (; it!=filter.end(); ++it) { - if ((*it)=="*") pass=true; // forward except if there is a veto later - if (source==(*it)) return true; // forward specific source - if ("!"+source==(*it)) return false; // veto specific source + static const std::array<std::pair<const char*, MSG::Level>, 7> tbl{{{"setFatal", MSG::FATAL}, + {"setError", MSG::ERROR}, + {"setWarning", MSG::WARNING}, + {"setInfo", MSG::INFO}, + {"setDebug", MSG::DEBUG}, + {"setVerbose", MSG::VERBOSE}, + {"setAlways", MSG::ALWAYS}}}; + + auto i = std::find_if( + std::begin(tbl), std::end(tbl), + [&](const std::pair<const char*, MSG::Level>& t) { return prop.name() == t.first; }); + if (i == std::end(tbl)) { + std::cerr << "TrigMessageSvc ERROR: Unknown message threshold parameter: " << prop.name() + << std::endl; + return; } - return pass; -} - - -//############################################################################# + int ic = i->second; -void TrigMessageSvc::setupSuppression(Property& /*prop*/) { - // (De)activate suppression - if ( m_suppressRunningOnly.value() ) { - m_doSuppress = (m_running && m_suppress.value()); + Gaudi::Property<std::vector<std::string>>* sap = + dynamic_cast<Gaudi::Property<std::vector<std::string>>*>(&prop); + if (!sap) { + std::cerr << "could not dcast " << prop.name() + << " to a Gaudi::Property<std::vector<std::string>> (which it " + "should be!)" + << std::endl; } else { - m_doSuppress = m_suppress.value(); + for (auto& i : sap->value()) setOutputLevel(i, ic); } } -//############################################################################# -/// Finalize Service -StatusCode TrigMessageSvc::finalize() { - - m_running = false; - m_doSuppress = false; - resetMsgStats(); // to get the final total sum - reportMsgStats(m_statLevel.value(),true); - m_state = Gaudi::StateMachine::OFFLINE; - return StatusCode::SUCCESS; -} - - -//############################################################################# -/// Report message counts -void TrigMessageSvc::reportMsgStats(uint statLevel, bool total) { - +StatusCode TrigMessageSvc::finalize() +{ + m_suppress = false; std::ostringstream os; if (m_stats) { - os << "Summarizing all message counts"; - if (!total){ - const EventInfo* pEvent(0); - if ( m_evtStore->retrieve(pEvent).isSuccess() ) { - os << " for run " << pEvent->event_ID()->run_number(); - } - } - os << " (severity >= " << levelNames[statLevel] << ")" << endl; - } else { - os << "Listing sources of suppressed message: " << endl; + os << "Summarizing all message counts" + << " (severity >= " << levelNames[m_statLevel] << ")" << std::endl; + } + else { + os << "Listing sources of suppressed message: " << std::endl; } - os << "==========================================================" << endl; - os << " Message Source | Level | Count" << endl; - os << "----------------------------------+---------+-------------" << endl; + os << "=====================================================" << std::endl; + os << " Message Source | Level | Count" << std::endl; + os << "-----------------------------+---------+-------------" << std::endl; bool found(false); - std::map<std::string,msgAry>::const_iterator itr = m_sourceMap.begin(); - std::map<std::string,msgAry>::const_iterator enditr = m_sourceMap.end(); - - if (total) { - itr = m_sourceMapTotal.begin(); - enditr = m_sourceMapTotal.end(); - } - - for (; itr!=enditr; ++itr) { + for (auto itr = m_sourceMap.begin(); itr != m_sourceMap.end(); ++itr) { for (unsigned int ic = 0; ic < MSG::NUM_LEVELS; ++ic) { - if ( (m_suppress.value() && itr->second.msg[ic] >= abs(m_msgLimit[ic]) && m_msgLimit[ic] != 0 ) || - (m_stats && itr->second.msg[ic] > 0 && ic >= statLevel) ) { - os << " "; - os.width(33); - os.setf(ios_base::left,ios_base::adjustfield); - os << itr->first; - - os << "|"; - - os.width(8); - os.setf(ios_base::right,ios_base::adjustfield); - os << levelNames[ic]; - - os << " |"; - - os.width(9); - os << itr->second.msg[ic]; - - os << endl; - - found = true; + if ((m_suppress && itr->second.msg[ic] >= abs(m_msgLimit[ic]) && m_msgLimit[ic] != 0) || + (m_stats && itr->second.msg[ic] > 0 && ic >= m_statLevel.value())) { + os << " "; + os.width(28); + os.setf(std::ios_base::left, std::ios_base::adjustfield); + os << itr->first; + os << "|"; + + os.width(8); + os.setf(std::ios_base::right, std::ios_base::adjustfield); + os << levelNames[ic]; + os << " |"; + + os.width(9); + os << itr->second.msg[ic]; + os << std::endl; + + found = true; } } } - os << "==========================================================" << endl; - + os << "=====================================================" << std::endl; if (found || m_stats) { reportMessage(name(), MSG::INFO, os.str()); } -} - -//############################################################################# -std::string TrigMessageSvc::colTrans(std::string col, int offset) { - ColorMap::const_iterator itr = m_colMap.find(col); - int icol; - if (itr != m_colMap.end()) { - icol = offset + itr->second; - } else { - icol = offset + 8; - } - std::ostringstream os1; - - os1 << icol; - - return os1.str(); + return StatusCode::SUCCESS; } -//############################################################################# -// --------------------------------------------------------------------------- -// Routine: reportMessage -// Purpose: dispatches a message to the relevant streams. -// --------------------------------------------------------------------------- -// - -void TrigMessageSvc::reportMessage( const Message& msg, int outputLevel ) { +void TrigMessageSvc::reportMessage(const Message& msg, int outputLevel) +{ + std::unique_lock<std::recursive_mutex> lock(m_reportMutex); + i_reportMessage(msg, outputLevel); +} - pthread_mutex_lock(&msgsvcmutex); - int key = msg.getType(); +/** + * Internal implementation of reportMessage(const Message&,int) without lock. + */ +void TrigMessageSvc::i_reportMessage(const Message& msg, int outputLevel) +{ + const int key = msg.getType(); ++m_msgCount[key]; - // Publish message statistics if enabled and only while RUNNING - if ( m_publishStats && m_running && key>=static_cast<int>(m_publishLevel) ) { - m_msgCountHist->Fill(key-m_publishLevel, 1); - { // Adding bins on the fly needs to be protected by mutex - scoped_lock_histogram lock; - m_msgCountSrcHist->Fill(key-m_publishLevel, msg.getSource().c_str(), 1); - m_msgCountSrcHist->LabelsDeflate("Y"); - } - } + const Message* cmsg = &msg; - const Message *cmsg = &msg; + if (m_doSuppress || m_stats.value()) { - if ( m_doSuppress || m_stats.value() ) { - int nmsg; - std::map<std::string,msgAry>::iterator itr = m_sourceMap.find(msg.getSource()); - if ( itr != m_sourceMap.end() ) { - nmsg = ++(itr->second.msg[key]); - } - else { - msgAry A; - for (int i=0; i<MSG::NUM_LEVELS; ++i) A.msg[i] = 0; - A.msg[key] = 1; - m_sourceMap[msg.getSource()] = A; - nmsg = 1; - } - + // Increase the counter of 'key' type of messages for the source and + // get the new value. + int nmsg = ++(m_sourceMap[msg.getSource()].msg[key]); + + const int msgLimit = m_msgLimit[key].value(); if (m_doSuppress) { - const int msgLimit = m_msgLimit[key].value(); - - if ( msgLimit > 0 ) { // regular suppression - if (nmsg == msgLimit) { - std::ostringstream os; - os << levelNames[key] << " message limit (" << msgLimit << ") reached for " - << msg.getSource() + ". Suppressing further output."; - cmsg = new Message(msg.getSource(), MSG::WARNING, os.str()); - cmsg->setFormat(msg.getFormat()); - cmsg->setTimeFormat(msg.getTimeFormat()); - } - else if (nmsg > msgLimit) { - pthread_mutex_unlock(&msgsvcmutex); - return; + if (msgLimit > 0) { // regular suppression + if (nmsg > msgLimit) return; + if (nmsg == msgLimit) { + std::string txt = levelNames[key] + " message limit (" + std::to_string(msgLimit) + + ") reached for " + msg.getSource() + ". Suppressing further output."; + cmsg = new Message(msg.getSource(), MSG::WARNING, std::move(txt)); } } - else if ( msgLimit < 0 ) { // logarithmic suppression - - // Use source/level/message as identifier and calculate hash - const unsigned int msgKey = msgHash(*cmsg); - MsgCountMap::iterator itr = m_msgCountMap.find(msgKey); - - // Check if we saw this message already and increase counter - if (itr != m_msgCountMap.end()) - nmsg = ++itr->second; - else - nmsg = m_msgCountMap[msgKey] = 1; - - if ( nmsg == abs(msgLimit) ) { + } + else if (msgLimit < 0) { // logarithmic suppression + // Calculate message hash + const unsigned int mh = msgHash(*cmsg); + // Check if we saw this message already and increase counter + auto m = m_msgHashCount.find(mh); + if (m != m_msgHashCount.end()) { + nmsg = ++m->second; + } + else { + nmsg = m_msgHashCount[mh] = 1; + } + if (nmsg == abs(msgLimit)) { + std::ostringstream os; + os << msg.getMessage() << " [Message limit (" << abs(msgLimit) + << ") reached. Log-suppression of further output.]"; + cmsg = new Message(msg.getSource(), msg.getType(), os.str()); + } + else if (nmsg > abs(msgLimit)) { + const int everyNth = (int)exp10((int)log10(nmsg)); + if ((nmsg % everyNth) == 0) { std::ostringstream os; - os << msg.getMessage() << " [Message limit (" << abs(msgLimit) - << ") reached. Log-suppression of further output.]"; + os << msg.getMessage() << " [suppressed " << everyNth << " similar messages]"; cmsg = new Message(msg.getSource(), msg.getType(), os.str()); - cmsg->setFormat(msg.getFormat()); - cmsg->setTimeFormat(msg.getTimeFormat()); - } - else if ( nmsg > abs(msgLimit) ) { - const int everyNth = (int)exp10((int)log10(nmsg)); - if ((nmsg % everyNth)==0) { - std::ostringstream os; - os << msg.getMessage() << " [suppressed " << everyNth << " similar messages]"; - cmsg = new Message(msg.getSource(), msg.getType(), os.str()); - cmsg->setFormat(msg.getFormat()); - cmsg->setTimeFormat(msg.getTimeFormat()); - } - else { - pthread_mutex_unlock(&msgsvcmutex); - return; - } } } } - } // suppression - - // Optional message trailer (ignored in hash) - std::ostringstream msgTrailer; - - // Avoid recursion in case StoreGateSvc::retrieve prints a message - if ( m_canEnter ) { - m_canEnter = false; - if ( m_running && - key >= static_cast<int>(m_eventIDLevel.value()) && - m_evtStore.retrieve().isSuccess() ) { - const EventInfo* pEvent(0); - if ( m_evtStore->retrieve(pEvent).isSuccess() ) { - // Add EventID - msgTrailer << " " << *pEvent->event_ID(); - } - } - m_canEnter = true; } - StreamMap::const_iterator first = m_streamMap.lower_bound( key ); - if ( first != m_streamMap.end() ) { - StreamMap::const_iterator last = m_streamMap.upper_bound( key ); - while( first != last ) { - std::ostream& stream = *( (*first).second.second ); - stream << *cmsg << msgTrailer.str() << std::endl; - ++first; + // Print the message + if (key >= outputLevel) { + if (m_eventIDLevel != MSG::NIL && key >= static_cast<int>(m_eventIDLevel)) { + cmsg->setFormat(m_defaultFormat + " %E"); } - } - else if ( key >= outputLevel ) { - cmsg->setFormat(m_defaultFormat); - cmsg->setTimeFormat(m_defaultTimeFormat); - std::ostringstream out_string_stream ; - if (!m_color) { - (out_string_stream) << *cmsg << msgTrailer.str(); - } else { - (out_string_stream) << m_logColorCodes[key] << *cmsg << msgTrailer.str() << "\033[m" ; + else { + cmsg->setFormat(m_defaultFormat); } + cmsg->setTimeFormat(m_defaultTimeFormat); + (*m_defaultStream) << *cmsg << std::endl << std::flush; - bool useERS = passErsFilter(cmsg->getSource(), m_useERS[key]); - - if ( m_alwaysUseMsgStream.value() || !useERS ) { - // output to the default stream - (*m_defaultStream) << out_string_stream.str() << std::endl << std::flush; + // ERS forwarding + if (passErsFilter(cmsg->getSource(), m_useERS[key])) { + i_reportERS(*cmsg); } + } - // output to ERS - if (useERS) { - - /* - * Create ERS context object - * - * The (cross-node) MRS throttling is based on filename+line_number, i.e. ignoring - * the message text itself. We therefor use the message source as filename and the - * message hash as line_number. That way the same message from different nodes - * gets properly throttled by MRS. - */ - const char* filename = cmsg->getSource().c_str(); - unsigned int line_number = msgHash(*cmsg); - const char* function_name = filename; - const char* package_name = "HLT"; - ers::LocalContext hlt_context_info(package_name, filename, line_number, function_name); - - /* - * Create ERS issue object - * - * Add the source to the ERS message text. Otherwise the source is not visible - * in the MRS monitor, for example. - * The "HLT" qualifier can be used to filter ERS messages from the log file. - */ - ers::HLTMessage ersMsg(hlt_context_info, cmsg->getSource() + ": " + cmsg->getMessage() + msgTrailer.str()); - ersMsg.add_qualifier("HLT"); // used for filtering - - // forward Gaudi message to ERS - switch (key) { - case MSG::NIL: ers::debug( ersMsg, 3 ); break; - case MSG::VERBOSE: ers::debug( ersMsg, 2 ); break; - case MSG::DEBUG: ers::debug( ersMsg, 1 ); break; - case MSG::INFO: ers::info( ersMsg ); break; - case MSG::WARNING: ers::warning( ersMsg ); break; - case MSG::ERROR: ers::error( ersMsg ); break; - case MSG::FATAL: ers::fatal( ersMsg ); break; - default: - std::ostringstream internal_msg ; - internal_msg << "ERROR: Unknown message severity level: " << key ; - ers::error( ers::HLTMessage(ERS_HERE,internal_msg.str()) ); - } - } + if (cmsg != &msg) { + delete cmsg; } - - if (cmsg != &msg) { delete cmsg; } - pthread_mutex_unlock(&msgsvcmutex); } - -void TrigMessageSvc::reportMessage( const Message& msg ) +/** + * Report message to online messaging system (ERS) + */ +void TrigMessageSvc::i_reportERS(const Message& msg) const { - reportMessage(msg, outputLevel(msg.getSource())); -} - -void TrigMessageSvc::reportMessage (const char* source, - int type, - const char* message) { - Message msg( source, type, message); - reportMessage( msg ); -} - - -void TrigMessageSvc::reportMessage (const std::string& source, - int type, - const std::string& message) { - Message msg( source, type, message); - reportMessage( msg ); -} - -//############################################################################# -// --------------------------------------------------------------------------- -// Routine: sendMessage -// Purpose: finds a message for a given status code and dispatches it. -// --------------------------------------------------------------------------- -// + /* + * Create ERS context object + * + * The (cross-node) MRS throttling is based on filename+line_number, i.e. + * ignoring the message text itself. We therefor use the message source as + * filename and the message hash as line_number. That way the same message + * from different nodes gets properly throttled by MRS. + */ + const char* filename = msg.getSource().c_str(); + const char* function_name = ""; + const int line_number = msgHash(msg); + const char* package_name = "HLT"; + ers::LocalContext hlt_context_info(package_name, filename, line_number, function_name); -void TrigMessageSvc::reportMessage (const StatusCode& key, - const std::string& source) -{ - pthread_mutex_lock(&msgsvcmutex); - MessageMap::const_iterator first = m_messageMap.lower_bound( key ); - if ( first != m_messageMap.end() ) { - MessageMap::const_iterator last = m_messageMap.upper_bound( key ); - while( first != last ) { - Message msg = (*first).second; - msg.setSource( source ); - std::ostringstream os1; - os1 << "Status Code " << key.getCode() << std::ends; - Message stat_code1( source, msg.getType(), os1.str() ); - reportMessage( stat_code1 ); - reportMessage( msg ); - ++first; - } + // Create ERS issue object + Message m(msg); + if (m_eventIDLevel != MSG::NIL && msg.getType() >= static_cast<int>(m_eventIDLevel)) { + m.setFormat(m_ersFormat + " %E"); } else { - Message mesg = m_defaultMessage; - mesg.setSource( source ); - std::ostringstream os2; - os2 << "Status Code " << key.getCode() << std::ends; - Message stat_code2( source, mesg.getType(), os2.str() ); - reportMessage( stat_code2 ); - reportMessage( mesg ); - } - pthread_mutex_unlock(&msgsvcmutex); -} - -//############################################################################# -// --------------------------------------------------------------------------- -// Routine: insertStream -// Purpose: inserts a stream for a message type. -// --------------------------------------------------------------------------- -// - -void TrigMessageSvc::insertStream (int key, - const std::string& name, - std::ostream *stream) + m.setFormat(m_ersFormat); + } + std::ostringstream oss; + oss << m; + ers::HLTMessage ersMsg(hlt_context_info, oss.str()); + ersMsg.add_qualifier("HLT"); // useful for filtering + + // Forward Message to ERS + switch (msg.getType()) { + case MSG::NIL: break; + case MSG::VERBOSE: ers::debug(ersMsg, 2); break; + case MSG::DEBUG: ers::debug(ersMsg, 1); break; + case MSG::INFO: ers::info(ersMsg); break; + case MSG::WARNING: ers::warning(ersMsg); break; + case MSG::ERROR: ers::error(ersMsg); break; + case MSG::FATAL: ers::fatal(ersMsg); break; + default: + std::ostringstream oss; + oss << "Unknown message severity level: " << msg.getType() << " Original message was: " << m; + ers::error(ers::HLTMessage(ERS_HERE, oss.str())); + } +} + +void TrigMessageSvc::reportMessage(const Message& msg) { - typedef StreamMap::value_type value_type; - pthread_mutex_lock(&msgsvcmutex); - m_streamMap.insert( value_type( key, NamedStream(name,stream) ) ); - pthread_mutex_unlock(&msgsvcmutex); + reportMessage(msg, outputLevel(msg.getSource())); } -//############################################################################# -// --------------------------------------------------------------------------- -// Routine: eraseStream -// Purpose: erases all the streams for all the message types. -// --------------------------------------------------------------------------- -// - -void TrigMessageSvc::eraseStream() +void TrigMessageSvc::reportMessage(const char* source, int type, const char* message) { - pthread_mutex_lock(&msgsvcmutex); - m_streamMap.erase( m_streamMap.begin(), m_streamMap.end() ); - pthread_mutex_unlock(&msgsvcmutex); + reportMessage(Message{source, type, message}); } -//############################################################################# -// --------------------------------------------------------------------------- -// Routine: eraseStream -// Purpose: erases all the streams for a message type. -// --------------------------------------------------------------------------- -// - -void TrigMessageSvc::eraseStream( int message_type ) +void TrigMessageSvc::reportMessage(const std::string& source, int type, const std::string& message) { - pthread_mutex_lock(&msgsvcmutex); - m_streamMap.erase( message_type ); - pthread_mutex_unlock(&msgsvcmutex); + reportMessage(Message{source, type, message}); } -//############################################################################# -// --------------------------------------------------------------------------- -// Routine: eraseStream -// Purpose: erases one stream for a message type. -// --------------------------------------------------------------------------- -// - -void TrigMessageSvc::eraseStream( int key, std::ostream* stream ) { - pthread_mutex_lock(&msgsvcmutex); - if ( 0 != stream ) { - bool changed = true; - while( changed ) { - changed = false; - StreamMap::iterator first = m_streamMap.lower_bound( key ); - StreamMap::iterator last = m_streamMap.upper_bound( key ); - while( first != last ) { - if ( (*first).second.second == stream ) { - m_streamMap.erase( first ); - changed = true; - break; - } - } - } - } - pthread_mutex_unlock(&msgsvcmutex); -} - -//############################################################################# -// --------------------------------------------------------------------------- -// Routine: eraseStream -// Purpose: erases one stream for all message types. -// --------------------------------------------------------------------------- -// - -void TrigMessageSvc::eraseStream( std::ostream* stream ) { - pthread_mutex_lock(&msgsvcmutex); - if ( 0 != stream ) { - bool changed = true; - while( changed ) { - changed = false; - StreamMap::iterator first = m_streamMap.begin(); - while( first != m_streamMap.end() ) { - if ( (*first).second.second == stream ) { - m_streamMap.erase( first ); - changed = true; - break; - } - } - } - } - pthread_mutex_unlock(&msgsvcmutex); -} - - -//############################################################################# -// --------------------------------------------------------------------------- -// Routine: insertMessage -// Purpose: inserts a message for a status code. -// --------------------------------------------------------------------------- -// - -void TrigMessageSvc::insertMessage( const StatusCode& key, const Message& msg ) +int TrigMessageSvc::outputLevel() const { - typedef MessageMap::value_type value_type; - pthread_mutex_lock(&msgsvcmutex); - m_messageMap.insert( value_type( key, msg ) ); - pthread_mutex_unlock(&msgsvcmutex); -} - -//############################################################################# -// --------------------------------------------------------------------------- -// Routine: eraseMessage -// Purpose: erases all the messages for all the status codes. -// --------------------------------------------------------------------------- -// - -void TrigMessageSvc::eraseMessage() -{ - pthread_mutex_lock(&msgsvcmutex); - m_messageMap.erase( m_messageMap.begin(), m_messageMap.end() ); - pthread_mutex_unlock(&msgsvcmutex); + return m_outputLevel; } -//############################################################################# -// --------------------------------------------------------------------------- -// Routine: eraseMessage -// Purpose: erases all the messages for a status code. -// --------------------------------------------------------------------------- -// - -void TrigMessageSvc::eraseMessage( const StatusCode& key ) +int TrigMessageSvc::outputLevel(const std::string& source) const { - pthread_mutex_lock(&msgsvcmutex); - m_messageMap.erase( key ); - pthread_mutex_unlock(&msgsvcmutex); + std::unique_lock<std::recursive_mutex> lock(m_thresholdMapMutex); + auto it = m_thresholdMap.find(source); + return it != m_thresholdMap.end() ? it->second : m_outputLevel.value(); } -//############################################################################# -// --------------------------------------------------------------------------- -// Routine: eraseMessage -// Purpose: erases one message for a status code. -// --------------------------------------------------------------------------- -// - -void TrigMessageSvc::eraseMessage( const StatusCode& key, const Message& msg ) +void TrigMessageSvc::setOutputLevel(int new_level) { - pthread_mutex_lock(&msgsvcmutex); - bool changed = true; - while( changed ) { - changed = false; - MessageMap::iterator first = m_messageMap.lower_bound( key ); - MessageMap::iterator last = m_messageMap.upper_bound( key ); - while( first != last ) { - const Message& message = (*first).second; - if ( message == msg ) { - m_messageMap.erase( first ); - changed = true; - break; - } - } - } - pthread_mutex_unlock(&msgsvcmutex); -} - -// --------------------------------------------------------------------------- -int TrigMessageSvc::outputLevel() const { -// --------------------------------------------------------------------------- - return m_outputLevel; -} -// --------------------------------------------------------------------------- -int TrigMessageSvc::outputLevel( const std::string& source ) const { -// --------------------------------------------------------------------------- - ThresholdMap::const_iterator it; - - pthread_mutex_lock(&msgsvcmutex); - it = m_thresholdMap.find( source ); - int level; - - if( it != m_thresholdMap.end() ) { - level = (*it).second; - } - else { - level = m_outputLevel; - } - pthread_mutex_unlock(&msgsvcmutex); - return level; -} - -// --------------------------------------------------------------------------- -void TrigMessageSvc::setOutputLevel(int new_level) { -// --------------------------------------------------------------------------- - pthread_mutex_lock(&msgsvcmutex); m_outputLevel = new_level; - pthread_mutex_unlock(&msgsvcmutex); -} - -// --------------------------------------------------------------------------- -void TrigMessageSvc::setOutputLevel(const std::string& source, int level) { -// --------------------------------------------------------------------------- - // Ignore in case we enforce the global OutputLevel - if (m_forceOutputLevel.value()) return; - - pthread_mutex_lock(&msgsvcmutex); - std::pair<ThresholdMap::iterator, bool> p; - p = m_thresholdMap.insert(ThresholdMap::value_type( source, level) ); - if( p.second == false ) { - // Already existing an output level for that source. Erase and enter it again - m_thresholdMap.erase ( p.first ); - m_thresholdMap.insert(ThresholdMap::value_type( source, level) ); - } - pthread_mutex_unlock(&msgsvcmutex); } +void TrigMessageSvc::setOutputLevel(const std::string& source, int level) +{ + std::unique_lock<std::recursive_mutex> lock(m_thresholdMapMutex); -// --------------------------------------------------------------------------- -void TrigMessageSvc::setOutputLevelViaJobOptSvc() { -// --------------------------------------------------------------------------- - ServiceHandle<IJobOptionsSvc> jobOptSvc("JobOptionsSvc", name()); - if ( jobOptSvc.retrieve()==StatusCode::FAILURE ) { - reportMessage(name(), MSG::ERROR, "Cannot retrieve JobOptionsSvc"); - return; + // only write if we really have to... + auto i = m_thresholdMap.find(source); + if (i == m_thresholdMap.end()) { + m_thresholdMap[source] = level; } - - std::vector<std::string> clients = jobOptSvc->getClients(); - std::vector<std::string>::iterator cl; - std::vector<const Property*>::const_iterator pr; - - // Loop over all clients/properties and set OutputLevel accordingly - for (cl=clients.begin(); cl!=clients.end(); ++cl) { - const std::vector<const Property*> *props = jobOptSvc->getProperties(*cl); - for (pr=props->begin(); pr!=props->end(); ++pr) { - if ( (*pr)->name()=="OutputLevel" ) { - if ( jobOptSvc->addPropertyToCatalogue(*cl, m_outputLevel).isSuccess() ){ - std::ostringstream msg; - msg << "Setting " << (*pr)->name() << ".OutputLevel = " << m_outputLevel.value(); - reportMessage(name(), MSG::DEBUG, msg.str()); - } - else { - std::ostringstream msg; - msg << "Cannot set " << (*pr)->name() << ".OutputLevel"; - reportMessage(name(), MSG::WARNING, msg.str()); - } - } - } + else if (i->second != level) { + i->second = level; } } - -// --------------------------------------------------------------------------- -void TrigMessageSvc::resetOutputLevels() { -// --------------------------------------------------------------------------- - m_thresholdMap.clear(); -} -// --------------------------------------------------------------------------- -std::string TrigMessageSvc::getLogColor(int logLevel) const { -// --------------------------------------------------------------------------- - if (logLevel < MSG::NUM_LEVELS) { - return m_logColorCodes[logLevel]; - } else { - return ""; - } +void TrigMessageSvc::resetOutputLevels() +{ + std::unique_lock<std::recursive_mutex> lock(m_thresholdMapMutex); + m_thresholdMap.clear(); } -// --------------------------------------------------------------------------- -int TrigMessageSvc::messageCount( MSG::Level level) const { +int TrigMessageSvc::messageCount(MSG::Level level) const +{ return m_msgCount[level]; } -// --------------------------------------------------------------------------- - -// --------------------------------------------------------------------------- -// Calculate message hash (ignoring any numbers) -// --------------------------------------------------------------------------- -unsigned int TrigMessageSvc::msgHash(const Message& msg) +bool TrigMessageSvc::passErsFilter(const std::string& source, + const std::vector<std::string>& filter) const { - // Message type is lowest decimal - unsigned int hash = msg.getType(); - - // Add all characters of source - const std::string& src = msg.getSource(); - for (size_t i=0; i<src.length(); ++i) { - hash += 10*(int)src[i]; - } + if (filter.empty()) return false; // forward none + auto it = filter.begin(); + if (filter.size() == 1 && (*it) == "*") return true; // forward all - // Add all letters of message - const std::string& str = msg.getMessage(); - for (size_t i=0; i<str.length(); ++i) { - const char& ch = str[i]; - if (ch<',' || ch>'9') hash += 10*(int)ch; + bool pass(false); + for (; it != filter.end(); ++it) { + if ((*it) == "*") pass = true; // forward except if there is a veto later + if (source == (*it)) return true; // forward specific source + if ("!" + source == (*it)) return false; // veto specific source } - - return hash; + return pass; } diff --git a/HLT/Trigger/TrigControl/TrigServices/src/TrigMessageSvc.h b/HLT/Trigger/TrigControl/TrigServices/src/TrigMessageSvc.h index b64914f57314f51db58b7454d77cfdc45f0f375a..3791d6b1aeeec3283ccc9cf8d7afa88d28d931cb 100644 --- a/HLT/Trigger/TrigControl/TrigServices/src/TrigMessageSvc.h +++ b/HLT/Trigger/TrigControl/TrigServices/src/TrigMessageSvc.h @@ -1,31 +1,33 @@ /* Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration */ - #ifndef TRIGSERVICES_TRIGMESSAGESVC_H #define TRIGSERVICES_TRIGMESSAGESVC_H // Include files +#include <iosfwd> +#include <map> +#include <memory> +#include <mutex> +#include <set> #include <string> #include <vector> -#include <map> -#include "GaudiKernel/StatusCode.h" -#include "GaudiKernel/Service.h" -#include "GaudiKernel/ServiceHandle.h" +#include "CxxUtils/checker_macros.h" #include "GaudiKernel/IMessageSvc.h" -#include "GaudiKernel/IIncidentListener.h" #include "GaudiKernel/Message.h" #include "GaudiKernel/Property.h" - -#include "StoreGate/StoreGateSvc.h" +#include "GaudiKernel/Service.h" +#include "GaudiKernel/StatusCode.h" #include "TrigKernel/ITrigMessageSvc.h" +// Helper to mark some virtual methods as not supported +#define NOTSUPPORTED \ + throw std::logic_error(std::string(__func__) + " is not supported by TrigMessageSvc") + // Forward declarations class ISvcLocator; -class TH1I; -class TH2I; /**@class TrigMessageSvc * @brief MessageSvc used by the HLT applications @@ -44,172 +46,147 @@ class TH2I; * * @author Iain Last, Werner Wiedenmann, Frank Winklmeier */ +class TrigMessageSvc : public extends<Service, IMessageSvc, ITrigMessageSvc> { +public: + typedef std::map<std::string, int> ThresholdMap; + + TrigMessageSvc(const std::string& name, ISvcLocator* svcloc); -class TrigMessageSvc : public extends<Service,IMessageSvc,ITrigMessageSvc,IIncidentListener> { -public: - typedef std::pair< std::string, std::ostream* > NamedStream; - typedef std::multimap< int, NamedStream > StreamMap; - typedef std::multimap< StatusCode, Message > MessageMap; - typedef std::map< std::string, int > ThresholdMap; - - // Default constructor. - TrigMessageSvc( const std::string& name, ISvcLocator* svcloc ); - // Destructor. - virtual ~TrigMessageSvc(); - - // Implementation of IService::reinitialize() virtual StatusCode reinitialize() override; - // Implementation of IService::initialize() virtual StatusCode initialize() override; - // Implementation of IService::finalize() virtual StatusCode finalize() override; - // Implementation of IMessageSvc::reportMessage() - virtual void reportMessage( const Message& message ) override; - - // Implementation of IMessageSvc::reportMessage() - virtual void reportMessage( const Message& message, int outputLevel ) override; - - // Implementation of IMessageSvc::reportMessage() - virtual void reportMessage( const StatusCode& code, const std::string& source = "") override; - - // Implementation of IMessageSvc::reportMessage() - virtual void reportMessage( const char* source, int type, const char* message) override; - - // Implementation of IMessageSvc::reportMessage() - virtual void reportMessage( const std::string& source, int type, const std::string& message) override; - - // Implementation of IMessageSvc::insertMessage() - virtual void insertMessage( const StatusCode& code, const Message& message ) override; - - // Implementation of IMessageSvc::eraseMessage() - virtual void eraseMessage() override; - - // Implementation of IMessageSvc::eraseMessage() - virtual void eraseMessage( const StatusCode& code ) override; - - // Implementation of IMessageSvc::eraseMessage() - virtual void eraseMessage( const StatusCode& code, const Message& message ) override; - - // Implementation of IMessageSvc::insertStream() - virtual void insertStream( int message_type, const std::string& name, std::ostream* stream ) override; - - // Implementation of IMessageSvc::eraseStream() - virtual void eraseStream() override; - - // Implementation of IMessageSvc::eraseStream() - virtual void eraseStream( int message_type ) override; - - // Implementation of IMessageSvc::eraseStream() - virtual void eraseStream( int message_type, std::ostream* stream ) override; - - // Implementation of IMessageSvc::eraseStream() - virtual void eraseStream( std::ostream* stream ) override; - - // Implementation of IMessageSvc::desaultStream() - virtual std::ostream* defaultStream() const override { - return m_defaultStream; + virtual void reportMessage(const Message& message) override; + virtual void reportMessage(const Message& msg, int outputLevel) override; + virtual void reportMessage(const char* source, int type, const char* message) override; + virtual void reportMessage(const std::string& source, int type, + const std::string& message) override; + virtual std::ostream* defaultStream ATLAS_NOT_THREAD_SAFE() const override + { + return m_defaultStream; } - // Implementation of IMessageSvc::setDefaultStream() - virtual void setDefaultStream( std::ostream* stream ) override { + virtual void setDefaultStream(std::ostream* stream) override + { + std::unique_lock<std::recursive_mutex> lock(m_reportMutex); m_defaultStream = stream; } - // Implementation of IMessageSvc::ouputLevel() - virtual int outputLevel() const override; - - // Implementation of IMessageSvc::ouputLevel() - virtual int outputLevel(const std::string& source) const override; - - // Implementation of IMessageSvc::setOuputLevel() + virtual int outputLevel() const override; + virtual int outputLevel(const std::string& source) const override; virtual void setOutputLevel(int new_level) override; - - // Implementation of IMessageSvc::setOuputLevel() virtual void setOutputLevel(const std::string& source, int new_level) override; - - // Implementation of IMessageSvc::useColor() - virtual bool useColor() const override { return m_color; } - - // Implementation of IMessageSvc::getLogColor() - virtual std::string getLogColor(int logLevel) const override; - - // Implementation of IMessageSvc::messageCount() - virtual int messageCount( MSG::Level logLevel ) const override; - - /// \name ITrigMessageSvc implementation - //@{ - /// Reset all individual output levels + virtual int messageCount(MSG::Level logLevel) const override; virtual void resetOutputLevels() override; - //@} - // Implemenation of IIncidentListener::handle() - virtual void handle(const Incident& inc) override; + virtual bool useColor() const override { return m_color; } + virtual std::string getLogColor(int) const override { return ""; } + + ///@{ Not supported by this implementation + virtual void reportMessage(const StatusCode&, const std::string&) override { NOTSUPPORTED; } + virtual void insertMessage(const StatusCode&, const Message&) override { NOTSUPPORTED; } + virtual void eraseMessage() override { NOTSUPPORTED; } + virtual void eraseMessage(const StatusCode&) override { NOTSUPPORTED; } + virtual void eraseMessage(const StatusCode&, const Message&) override { NOTSUPPORTED; } + virtual void insertStream(int, const std::string&, std::ostream*) override { NOTSUPPORTED; } + virtual void eraseStream() override { NOTSUPPORTED; } + virtual void eraseStream(int) override { NOTSUPPORTED; } + virtual void eraseStream(int, std::ostream*) override { NOTSUPPORTED; } + virtual void eraseStream(std::ostream*) override { NOTSUPPORTED; } + ///@} private: - typedef std::map<std::string, MSG::Color> ColorMap; - typedef std::map< unsigned int, unsigned int > MsgCountMap; - - std::ostream* m_defaultStream; ///< Pointer to the output stream. - Message m_defaultMessage; ///< Default Message - StreamMap m_streamMap; ///< Stream map - MessageMap m_messageMap; ///< Message map - ThresholdMap m_thresholdMap; ///< Output level threshold map - std::string m_defaultFormat; ///< Default format for the messages - std::string m_defaultTimeFormat; ///< Default time format for the messages - int m_defaultLimit; ///< Original default message limit - bool m_doSuppress; ///< Message suppression currently active? - bool m_running; ///< In RUNNING state - bool m_canEnter; ///< used to avoid infinite recursions - - ServiceHandle<StoreGateSvc> m_evtStore; ///< Event store - - /* Properties */ - StringArrayProperty m_thresholdProp[MSG::NUM_LEVELS]; - StringArrayProperty m_logColors[MSG::NUM_LEVELS]; - UnsignedIntegerProperty m_statLevel; - UnsignedIntegerProperty m_statLevelRun; - UnsignedIntegerProperty m_publishLevel; - UnsignedIntegerProperty m_eventIDLevel; - IntegerProperty m_msgLimit[MSG::NUM_LEVELS]; - BooleanProperty m_color; - BooleanProperty m_stats; - BooleanProperty m_publishStats; - BooleanProperty m_resetStats; - StringArrayProperty m_useERS[MSG::NUM_LEVELS]; - BooleanProperty m_alwaysUseMsgStream; - BooleanProperty m_useErsRunningOnly; - BooleanProperty m_suppress; - BooleanProperty m_suppressRunningOnly; - BooleanProperty m_forceOutputLevel; - - /* Message colors */ - std::string m_logColorCodes[MSG::NUM_LEVELS]; - std::string colTrans(std::string, int); - ColorMap m_colMap; - - /* Message counting */ - struct msgAry { int msg[MSG::NUM_LEVELS]; }; - std::map<std::string, msgAry> m_sourceMap; ///< Current message counting per source - std::map<std::string, msgAry> m_sourceMapTotal; ///< Total message counting per source - int m_msgCount[MSG::NUM_LEVELS]; ///< Message counting per level - MsgCountMap m_msgCountMap; ///< Message counting per message - TH1I* m_msgCountHist; ///< Message counting per level histogram - TH2I* m_msgCountSrcHist; ///< Message counting per message source - - /* Update handlers */ - void initColors(Property& prop); - void setupColors(Property& prop); - void setupLimits(Property& prop); - void setupThreshold(Property& prop); - void setupSuppression(Property& prop); - - unsigned int msgHash(const Message& msg); ///< Hash of message (for log. suppression) - void resetMsgStats(); ///< Reset message statistics - void reportMsgStats(uint statLevel, bool total=false); ///< Report message statistics - void setOutputLevelViaJobOptSvc(); ///< Change OutputLevel properties in JobOptionsSvc - void bookHistograms(); ///< Book histograms for message statistics - bool passErsFilter(const std::string& source, const std::vector<std::string>& filter); ///< Source passes ERS filter? + ////////////////////////////////////////////////////////////////////// + // Properties + ////////////////////////////////////////////////////////////////////// + Gaudi::Property<std::string> m_defaultFormat{this, "Format", Message::getDefaultFormat(), + "Default message format"}; + Gaudi::Property<std::string> m_ersFormat{this, "ErsFormat", Message::getDefaultFormat(), + "ERS message format"}; + Gaudi::Property<std::string> m_defaultTimeFormat{ + this, "timeFormat", Message::getDefaultTimeFormat(), "Message time format"}; + Gaudi::Property<bool> m_stats{this, "showStats", false, "Show message statistics"}; + Gaudi::Property<unsigned int> m_statLevel{this, "statLevel", 0, + "Show total message statistics for >= level"}; + Gaudi::Property<unsigned int> m_statLevelRun{this, "statLevelRun", 0, + "Show per-run statistics for messages >= level"}; + Gaudi::Property<bool> m_resetStats{this, "resetStatsAtBeginRun", false, + "Reset message statistics at BeginRun"}; + Gaudi::Property<unsigned int> m_eventIDLevel{this, "printEventIDLevel", MSG::NIL, + "Print event ID for this and higher message levels"}; + Gaudi::Property<bool> m_color{this, "useColors", false, + "Colors are not supported by TrigMessageSvc"}; + Gaudi::Property<bool> m_suppress{this, "enableSuppression", false, "Enable message suppression"}; + Gaudi::Property<bool> m_suppressRunningOnly{this, "suppressRunningOnly", true, + "Use message suppression only during RUNNING state"}; + + std::array<Gaudi::Property<std::vector<std::string>>, MSG::NUM_LEVELS> m_thresholdProp{ + {{/*ignored*/}, + {this, "setVerbose"}, + {this, "setDebug"}, + {this, "setInfo"}, + {this, "setWarning"}, + {this, "setError"}, + {this, "setFatal"}, + {this, "setAlways"}}}; + + std::array<Gaudi::Property<int>, MSG::NUM_LEVELS> m_msgLimit{{{this, "defaultLimit", 500}, + {this, "verboseLimit", 500}, + {this, "debugLimit", 500}, + {this, "infoLimit", 500}, + {this, "warningLimit", 500}, + {this, "errorLimit", 500}, + {this, "fatalLimit", 500}, + {this, "alwaysLimit", 0}}}; + + /** + * Special properties to control output to ERS of individual sources. + * The syntax is as follows (these are NOT regular expressions): + * + * useErsFatal = [] # forward none (default) + * useErsFatal = ['*'] # forward all + * useErsFatal = ['CoreDumpSvc','MyAlg'] # forward these sources + * useErsFatal = ['*','!MyAlg'] # forward all except MyAlg + */ + std::array<Gaudi::Property<std::vector<std::string>>, MSG::NUM_LEVELS> m_useERS{ + {{/*ignored*/}, + {this, "useErsVerbose", {}}, + {this, "useErsDebug", {}}, + {this, "useErsInfo", {}}, + {this, "useErsWarning", {}}, + {this, "useErsError", {}}, + {this, "useErsFatal", {}}, + {this, "useErsAlways", {}}}}; + + ////////////////////////////////////////////////////////////////////// + // Private members + ////////////////////////////////////////////////////////////////////// + std::ostream* m_defaultStream = &std::cout; ///< Pointer to the output stream. + ThresholdMap m_thresholdMap; ///< Output level threshold map + + /// Private helper class to keep the count of messages of a type (MSG::LEVEL). + struct MsgAry final { + /// Internal array of counters. + std::array<int, MSG::NUM_LEVELS> msg = {{0}}; + /// Default constructor. + MsgAry() = default; + }; + + std::map<std::string, MsgAry> m_sourceMap; ///< counts per source + std::array<int, MSG::NUM_LEVELS> m_msgCount; ///< counts per level + std::map<size_t, unsigned int> m_msgHashCount; ///< counts per message hash + + bool m_running{false}; ///< are we in running state? + bool m_doSuppress{false}; ///< is suppression currently enabled? + + mutable std::recursive_mutex m_reportMutex; ///< mutex for printing + mutable std::recursive_mutex m_thresholdMapMutex; /// (@see MsgStream::doOutput). + + void setupLimits(Gaudi::Details::PropertyBase& prop); + void setupThreshold(Gaudi::Details::PropertyBase& prop); + bool passErsFilter(const std::string& source, const std::vector<std::string>& filter) const; + void i_reportMessage(const Message& msg, int outputLevel); + void i_reportERS(const Message& msg) const; }; #endif diff --git a/HLT/Trigger/TrigControl/TrigServices/src/TrigMonTHistSvc.cxx b/HLT/Trigger/TrigControl/TrigServices/src/TrigMonTHistSvc.cxx index 85a1766f21a13aea199ffccd7a64a2cb56eb65de..cf57b1ea47040566ae525ecdfc66b1c34d1027b5 100644 --- a/HLT/Trigger/TrigControl/TrigServices/src/TrigMonTHistSvc.cxx +++ b/HLT/Trigger/TrigControl/TrigServices/src/TrigMonTHistSvc.cxx @@ -1,11 +1,12 @@ /* - Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration */ #include "GaudiKernel/ISvcLocator.h" #include "AthenaKernel/errorcheck.h" +#include "CxxUtils/checker_macros.h" #include "TrigMonTHistSvc.h" #include "TrigMonitorBase/TrigLockedHist.h" @@ -52,7 +53,7 @@ StatusCode TrigMonTHistSvc::queryInterface(const InterfaceID & riid, } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -StatusCode TrigMonTHistSvc::initialize() { +StatusCode TrigMonTHistSvc::initialize ATLAS_NOT_THREAD_SAFE() { CHECK(THistSvcHLT::initialize()); CHECK(setProperties());