diff --git a/HLT/Trigger/TrigControl/TrigServices/TrigServices/HltEventLoopMgr.h b/HLT/Trigger/TrigControl/TrigServices/TrigServices/HltEventLoopMgr.h index 1d047b8bf919583aa2f2b38ffcdf910ea72a5a7a..2a35beeb4ac4e6e5eabb56ee77d709c52ea301f6 100644 --- a/HLT/Trigger/TrigControl/TrigServices/TrigServices/HltEventLoopMgr.h +++ b/HLT/Trigger/TrigControl/TrigServices/TrigServices/HltEventLoopMgr.h @@ -36,6 +36,7 @@ // Forward declarations class IIncidentSvc; class IAlgContextSvc; +class IAlgExecStateSvc; class StoreGateSvc; class IROBDataProviderSvc; class ITHistSvc; @@ -291,6 +292,9 @@ private: // check whether a subdetector is in the run, according to the current detmask bool isSubDetectorIn(eformat::SubDetector sd) const; + // Helper to create EventContext + StatusCode installEventContext (const EventInfo* pEvent, EventID::number_type run); + /** Handles to required services/tools **/ typedef ServiceHandle<IIncidentSvc> IIncidentSvc_t; IIncidentSvc_t m_incidentSvc; @@ -306,6 +310,8 @@ private: typedef ServiceHandle<ITHistSvc> ITHistSvc_t; ITHistSvc_t m_THistSvc; + ServiceHandle<IAlgExecStateSvc> m_aess; + ToolHandle<TrigISHelper> m_isHelper; ToolHandle<TrigCOOLUpdateHelper> m_coolHelper; @@ -443,7 +449,7 @@ private: /// we need this maintain the data uint32_t m_status_words[3] = {0}; - EventContext* m_eventContext; + EventContext m_eventContext; }; //========================================================================= diff --git a/HLT/Trigger/TrigControl/TrigServices/python/TriggerUnixStandardSetup.py b/HLT/Trigger/TrigControl/TrigServices/python/TriggerUnixStandardSetup.py index 06ca2b2d7eb66bbc158849212b74a19890ef784e..a23e44b44b7d34c0ee87a0518d9a406aa16663d0 100644 --- a/HLT/Trigger/TrigControl/TrigServices/python/TriggerUnixStandardSetup.py +++ b/HLT/Trigger/TrigControl/TrigServices/python/TriggerUnixStandardSetup.py @@ -1,4 +1,4 @@ -# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +# Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration ## @file TriggerUnixStandardSetup.py ## @brief py-module to configure the Athena AppMgr for trigger @@ -81,12 +81,6 @@ def _setupCommonServices(): from TrigServices.TrigServicesConf import TrigISHelper ToolSvc += TrigISHelper("TrigISHelper") - # Configure TrigPreFlightCheck - from TrigServices.TrigServicesConf import TrigPreFlightCheck - ToolSvc += TrigPreFlightCheck("TrigPreFlightCheck", - ReleaseDirs = ["AtlasP1HLT","AtlasHLT"] - ) - # Configure CoreDumpSvc if not hasattr(svcMgr,"CoreDumpSvc"): from AthenaServices.Configurables import CoreDumpSvc diff --git a/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.cxx b/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.cxx index 1e70db0df9297816f589380416922867fc826c34..8fb7371777cf078249488c6b5ccdad919204c9bc 100644 --- a/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.cxx +++ b/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.cxx @@ -11,12 +11,15 @@ #include "GaudiKernel/ITHistSvc.h" #include "GaudiKernel/Timing.h" #include "GaudiKernel/IAlgContextSvc.h" +#include "GaudiKernel/IAlgExecStateSvc.h" #include "GaudiKernel/IAlgManager.h" #include "GaudiKernel/ServiceLocatorHelper.h" #include "GaudiKernel/SmartIF.h" #include "GaudiKernel/EventContext.h" // Athena includes +#include "AthenaKernel/ExtendedEventContext.h" +#include "AthenaKernel/EventContextClid.h" #include "StoreGate/StoreGateSvc.h" #include "EventInfo/EventIncident.h" #include "EventInfo/EventInfo.h" @@ -36,7 +39,6 @@ static std::string CMT_PACKAGE_VERSION = PACKAGE_VERSION; #include "TrigServices/HltEventLoopMgr.h" #include "TrigServices/TrigISHelper.h" #include "TrigServices/TrigHLTIssues.h" -#include "TrigPreFlightCheck.h" #include "TrigCOOLUpdateHelper.h" #include "TrigSORFromPtreeHelper.h" #include "TrigConfInterfaces/IHLTConfigSvc.h" @@ -272,6 +274,7 @@ HltEventLoopMgr::HltEventLoopMgr(const std::string& nam, m_inputMetaDataStore( "StoreGateSvc/InputMetaDataStore", nam ), m_robDataProviderSvc( "ROBDataProviderSvc",nam ), m_THistSvc( "THistSvc", nam ), + m_aess( "AlgExecStateSvc", nam), m_isHelper( "TrigISHelper", this), m_coolHelper( "TrigCOOLUpdateHelper", this), m_sorTime_stamp(2,0), @@ -284,8 +287,7 @@ HltEventLoopMgr::HltEventLoopMgr(const std::string& nam, m_histProp_numStreamTags(Gaudi::Histo1DDef("NumberOfStreamTags",-.5,19.5,20)), m_histProp_streamTagNames(Gaudi::Histo1DDef("StreamTagNames",-.5,.5,1)), m_histProp_num_partial_eb_robs(Gaudi::Histo1DDef("NumberROBsPartialEB",-.5,199.5,200)), - m_histProp_Hlt_Edm_Sizes(Gaudi::Histo1DDef("HltEDMSizes",0.,10000.,100)), - m_eventContext(nullptr) + m_histProp_Hlt_Edm_Sizes(Gaudi::Histo1DDef("HltEDMSizes",0.,10000.,100)) { m_mandatoryL1ROBs.value() = {begin(L1R_MANDATORY_ROBS), end(L1R_MANDATORY_ROBS)}; @@ -504,8 +506,6 @@ StatusCode HltEventLoopMgr::initialize() msgStream() << MSG::INFO << " ---> Debug stream name for events with truncated HLT result = " << m_HltTruncationDebugStreamName << endmsg; msgStream() << MSG::INFO << " ---> Stream names of events with a truncated HLT result which will not be send to the debug stream = " << m_excludeFromHltTruncationDebugStream << endmsg; - m_eventContext = new EventContext(); - //------------------------------------------------------------------------- // Setup the StoreGateSvc //------------------------------------------------------------------------- @@ -566,6 +566,8 @@ StatusCode HltEventLoopMgr::initialize() return sc; } + ATH_CHECK(m_aess.retrieve()); + //-------------------------------------------------------------------------- // Setup the TrigISHelper //-------------------------------------------------------------------------- @@ -599,28 +601,6 @@ StatusCode HltEventLoopMgr::initialize() msgStream() << MSG::DEBUG << "No AlgContextSvc available" << endmsg; } - //-------------------------------------------------------------------------- - // Pre flight check - //-------------------------------------------------------------------------- - ToolHandle<TrigPreFlightCheck> preFlightCheck; - if (preFlightCheck.retrieve().isFailure()) { - msgStream() << MSG::FATAL << "Error retrieving TrigPreFlightCheck "+preFlightCheck << endmsg; - return StatusCode::FAILURE; - } - - // A failed pre-flight check is fatal in a partition - if ( validPartition() ) { - if ( preFlightCheck->check(MSG::ERROR).isFailure() ) { - msgStream() << MSG::FATAL << "Pre-flight check for HLT failed." << endmsg; - return StatusCode::FAILURE; - } - } - else { - if ( preFlightCheck->check(MSG::WARNING).isFailure() ) - msgStream() << MSG::WARNING << "Pre-flight check for HLT failed." << endmsg; - } - preFlightCheck->release(); - // The remainder of this method used to be in the L2/EF specialization // fill CTP ROB id vector @@ -712,7 +692,6 @@ StatusCode HltEventLoopMgr::finalize() msgStream() << MSG::ERROR << "Error in MinimalEventLoopMgr Finalize" << endmsg; } - delete m_eventContext; m_eventContext = nullptr; // Release all interfaces m_incidentSvc.release().ignore(); @@ -767,25 +746,13 @@ StatusCode HltEventLoopMgr::reinitialize() StatusCode HltEventLoopMgr::executeAlgorithms() { - // Call the resetExecuted() method of ALL "known" algorithms - // (before we were reseting only the topalgs) - SmartIF<IAlgManager> algMan(serviceLocator()); - if ( algMan.isValid() ) { - const auto& allAlgs = algMan->getAlgorithms() ; - for( auto ialg = allAlgs.begin() ; allAlgs.end() != ialg ; ++ialg ) { - if ( 0 != *ialg ) (*ialg)->resetExecuted(); - } - } + // Reset all algorithms + m_aess->reset(m_eventContext); // Call the execute() method of all top algorithms - StatusCode sc; for(auto alg : m_topAlgList) { -#ifdef GAUDI_SYSEXECUTE_WITHCONTEXT - sc = alg->sysExecute(*m_eventContext); -#else - sc = alg->sysExecute(); -#endif + sc = alg->sysExecute(m_eventContext); if(sc.isFailure()) { msgStream() << MSG::ERROR << "Execution of algorithm " << alg->name() << " failed" << endmsg; @@ -826,8 +793,11 @@ StatusCode HltEventLoopMgr::executeEvent(void* par) << *(m_currentEvent->event_ID()) << endmsg; } - m_eventContext->setEventID( *((EventIDBase*) m_currentEvent->event_ID()) ); - + //----------------------------------------------------------------------- + // Create EventContext + //----------------------------------------------------------------------- + ATH_CHECK(installEventContext(m_currentEvent, m_currentRun)); + //----------------------------------------------------------------------- // obtain the HLT conditions update counters from the CTP fragment //----------------------------------------------------------------------- @@ -977,8 +947,7 @@ StatusCode HltEventLoopMgr::executeEvent(void* par) if (sc.isSuccess()) { // Call the execute() method of all output streams for (auto o : m_outStreamList ) { - o->resetExecuted(); - sc = o->sysExecute(*m_eventContext); + sc = o->sysExecute(m_eventContext); if(sc.isFailure()) { msgStream() << MSG::WARNING << "Execution of output stream " << o->name() << " failed" << endmsg; eventFailed = true; @@ -995,6 +964,7 @@ StatusCode HltEventLoopMgr::executeEvent(void* par) return eventFailed ? StatusCode::FAILURE : StatusCode::SUCCESS; } + //========================================================================= // prepare for run step //========================================================================= @@ -1050,6 +1020,21 @@ StatusCode HltEventLoopMgr::prepareForRun(const ptree & pt) return StatusCode::FAILURE; } +StatusCode HltEventLoopMgr::installEventContext(const EventInfo* pEvent, EventID::number_type run) +{ + if (pEvent) m_eventContext.setEventID( *((EventIDBase*) pEvent->event_ID()) ); + m_eventContext.set(m_total_evt ,0); + + m_eventContext.setExtension( Atlas::ExtendedEventContext( m_evtStore->hiveProxyDict(), run) ); + Gaudi::Hive::setCurrentContext( m_eventContext ); + + m_aess->reset(m_eventContext); + ATH_CHECK(m_evtStore->record(std::make_unique<EventContext> (m_eventContext), "EventContext")); + + return StatusCode::SUCCESS; +} + + //========================================================================= // allow for updates after forking the workers and issue an incident // to inform the clients @@ -1937,7 +1922,7 @@ void HltEventLoopMgr::bookHistograms() regHistsTProfile.reserve(4); // monitoring information root directory - const std::string histPath = std::string("/EXPERT/"); + const std::string histPath = std::string("/EXPERT/") + name() + "/"; // +--------------------+ // *-- | Event accept flags | @@ -2230,7 +2215,7 @@ void HltEventLoopMgr::HltBookHistograms() if ( !m_doMonitoring.value() ) { return; } // monitoring information root directory - std::string path = std::string("/EXPERT/"); + std::string path = std::string("/EXPERT/") + name() + "/"; // *-- SubDetectors from l1 ROBs auto nbins = L1R_BINS.size() + 2; @@ -2469,9 +2454,11 @@ const SOR * HltEventLoopMgr::processRunParams(const ptree & pt) // update the run number m_currentRun = pt.get<uint32_t>("RunParams.run_number"); + ATH_CHECK(installEventContext(nullptr, m_currentRun), nullptr); + // Fill SOR parameters from the ptree TrigSORFromPtreeHelper sorhelp{msgStream()}; - auto sor = sorhelp.fillSOR(pt.get_child("RunParams"), *m_eventContext); + auto sor = sorhelp.fillSOR(pt.get_child("RunParams"), m_eventContext); if(!sor) msgStream() << MSG::ERROR << ST_WHERE << "setup of SOR from ptree failed" << endmsg; diff --git a/HLT/Trigger/TrigControl/TrigServices/src/HltROBDataProviderSvc.cxx b/HLT/Trigger/TrigControl/TrigServices/src/HltROBDataProviderSvc.cxx index d063fafc783dc39d32fa3463783187945d6143eb..d68ed1b638553f97a5f8ed8c44ba853472f88981 100644 --- a/HLT/Trigger/TrigControl/TrigServices/src/HltROBDataProviderSvc.cxx +++ b/HLT/Trigger/TrigControl/TrigServices/src/HltROBDataProviderSvc.cxx @@ -935,7 +935,7 @@ void HltROBDataProviderSvc::handle(const Incident& incident) { } // *-- booking path - std::string path = std::string("/EXPERT/"); + std::string path = std::string("/EXPERT/") + name() + "/"; // *-- number of bins for sub detector plots (55 SubDet max.) uint32_t n_bins_partEBSubDet = eformat::helper::SubDetectorDictionary.size(); diff --git a/HLT/Trigger/TrigControl/TrigServices/src/THistSvcHLT.cxx b/HLT/Trigger/TrigControl/TrigServices/src/THistSvcHLT.cxx new file mode 100644 index 0000000000000000000000000000000000000000..12da877f9d143dcd246f86ac2902333c08abb14b --- /dev/null +++ b/HLT/Trigger/TrigControl/TrigServices/src/THistSvcHLT.cxx @@ -0,0 +1,2023 @@ +/* + * This is a copy of GaudiSvc/src/THistSvc with THistSvc renamed to THistSvcHLT + * to allow inheritance of this class by TrigMonTHistSvc. + */ +// system headers +#include <cstdio> +#include <sstream> +#include <streambuf> + +// boost headers +#include "boost/algorithm/string/case_conv.hpp" + +// ROOT headers +#include "TDirectory.h" +#include "TError.h" +#include "TFile.h" +#include "TGraph.h" +#include "TKey.h" +#include "TROOT.h" + +// Gaudi headers +#include "GaudiKernel/AttribStringParser.h" +#include "GaudiKernel/FileIncident.h" +#include "GaudiKernel/GaudiException.h" +#include "GaudiKernel/IEventProcessor.h" +#include "GaudiKernel/IFileMgr.h" +#include "GaudiKernel/IIncidentSvc.h" +#include "GaudiKernel/IIoComponentMgr.h" +#include "GaudiKernel/IJobOptionsSvc.h" +#include "GaudiKernel/ISvcLocator.h" +#include "GaudiKernel/Property.h" + +// local headers +#include "THistSvcHLT.h" + +DECLARE_COMPONENT( THistSvcHLT ) + +namespace +{ + template <typename InputIterator, typename OutputIterator, typename UnaryOperation, typename UnaryPredicate> + OutputIterator transform_if( InputIterator first, InputIterator last, OutputIterator result, UnaryOperation op, + UnaryPredicate pred ) + { + while ( first != last ) { + if ( pred( *first ) ) *result++ = op( *first ); + ++first; + } + return result; + } + + constexpr struct select1st_t { + template <typename T, typename S> + const T& operator()( const std::pair<T, S>& p ) const + { + return p.first; + } + } select1st{}; +} + +//*************************************************************************// + +THistSvcHLT::THistSvcHLT( const std::string& name, ISvcLocator* svc ) : base_class( name, svc ) +{ + m_compressionLevel.declareUpdateHandler( &THistSvcHLT::setupCompressionLevel, this ); + m_outputfile.declareUpdateHandler( &THistSvcHLT::setupOutputFile, this ); + m_inputfile.declareUpdateHandler( &THistSvcHLT::setupInputFile, this ); +} + +StatusCode THistSvcHLT::initialize() +{ + GlobalDirectoryRestore restore( m_svcMut ); + + StatusCode status = Service::initialize(); + + if ( status.isFailure() ) { + error() << "initializing service" << endmsg; + return status; + } + + StatusCode st( StatusCode::SUCCESS ); + + try { + setupOutputFile( m_outputfile ); + } catch ( GaudiException& err ) { + error() << "Caught: " << err << endmsg; + st = StatusCode::FAILURE; + } + + try { + setupInputFile( m_inputfile ); + } catch ( GaudiException& err ) { + error() << "Caught: " << err << endmsg; + st = StatusCode::FAILURE; + } + + // Protect against multiple instances of TROOT + if ( !gROOT ) { + static TROOT root( "root", "ROOT I/O" ); + // gDebug = 99; + } else { + if ( msgLevel( MSG::VERBOSE ) ) { + verbose() << "ROOT already initialized, debug = " << gDebug << endmsg; + } + } + + if ( service( "IncidentSvc", p_incSvc, true ).isFailure() ) { + error() << "unable to get the IncidentSvc" << endmsg; + st = StatusCode::FAILURE; + } else { + p_incSvc->addListener( this, "EndEvent", 100, true ); + } + + if ( service( "FileMgr", p_fileMgr, true ).isFailure() ) { + error() << "unable to get the FileMgr" << endmsg; + st = StatusCode::FAILURE; + } else { + debug() << "got the FileMgr" << endmsg; + } + + // Register open/close callback actions + using namespace std::placeholders; + auto boa = [this]( const Io::FileAttr* fa, const std::string& caller ) { return this->rootOpenAction( fa, caller ); }; + if ( p_fileMgr->regAction( boa, Io::OPEN, Io::ROOT ).isFailure() ) { + error() << "unable to register ROOT file open action with FileMgr" << endmsg; + } + auto bea = [this]( const Io::FileAttr* fa, const std::string& caller ) { + return this->rootOpenErrAction( fa, caller ); + }; + if ( p_fileMgr->regAction( bea, Io::OPEN_ERR, Io::ROOT ).isFailure() ) { + error() << "unable to register ROOT file open Error action with FileMgr" << endmsg; + } + + m_okToConnect = true; + if ( m_delayConnect ) { + if ( !m_inputfile.value().empty() ) { + setupInputFile( m_inputfile ); + } + if ( !m_outputfile.value().empty() ) { + setupOutputFile( m_outputfile ); + } + + m_delayConnect = false; + } + m_alreadyConnectedOutFiles.clear(); + m_alreadyConnectedInFiles.clear(); + + IIoComponentMgr* iomgr = nullptr; + if ( service( "IoComponentMgr", iomgr, true ).isFailure() ) { + error() << "unable to get the IoComponentMgr" << endmsg; + st = StatusCode::FAILURE; + } else { + if ( !iomgr->io_register( this ).isSuccess() ) { + error() << "could not register with the I/O component manager !" << endmsg; + st = StatusCode::FAILURE; + } else { + bool all_good = true; + // register input/output files... + for ( const auto& reg : m_files ) { + const std::string& fname = reg.second.first->GetName(); + const IIoComponentMgr::IoMode::Type iomode = + ( reg.second.second == THistSvcHLT::READ ? IIoComponentMgr::IoMode::READ : IIoComponentMgr::IoMode::WRITE ); + if ( !iomgr->io_register( this, iomode, fname ).isSuccess() ) { + warning() << "could not register file [" << fname << "] with the I/O component manager..." << endmsg; + all_good = false; + } else { + info() << "registered file [" << fname << "]... [ok]" << endmsg; + } + } + if ( !all_good ) { + error() << "problem while registering input/output files with " + << "the I/O component manager !" << endmsg; + st = StatusCode::FAILURE; + } + } + } + + if ( st.isFailure() ) { + fatal() << "Unable to initialize THistSvcHLT" << endmsg; + } + + return st; +} + +StatusCode THistSvcHLT::reinitialize() +{ + GlobalDirectoryRestore restore( m_svcMut ); + warning() << "reinitialize not implemented" << endmsg; + return StatusCode::SUCCESS; +} + +StatusCode THistSvcHLT::finalize() +{ + GlobalDirectoryRestore restore( m_svcMut ); + + if ( msgLevel( MSG::DEBUG ) ) { + dump(); + debug() << "THistSvcHLT::finalize" << endmsg; + } + +#ifndef NDEBUG + if ( msgLevel( MSG::DEBUG ) ) { + for ( const auto& itr : m_uids ) { + THistID& thid = itr.second->at( 0 ); + TObject* tobj = thid.obj; + + std::string dirname( "none" ); + if ( tobj && tobj->IsA()->InheritsFrom( "TTree" ) ) { + TTree* tree = dynamic_cast<TTree*>( tobj ); + if ( tree->GetDirectory() != 0 ) { + dirname = tree->GetDirectory()->GetPath(); + } + } else if ( tobj && tobj->IsA()->InheritsFrom( "TGraph" ) ) { + if ( !thid.temp ) { + dirname = thid.file->GetPath(); + std::string id2( thid.id ); + id2.erase( 0, id2.find( "/", 1 ) ); + id2.erase( id2.rfind( "/" ), id2.length() ); + if ( id2.find( "/" ) == 0 ) { + id2.erase( 0, 1 ); + } + dirname += id2; + } else { + dirname = "/tmp"; + } + } else if ( tobj && tobj->IsA()->InheritsFrom( "TH1" ) ) { + TH1* th = dynamic_cast<TH1*>( tobj ); + if ( th == nullptr ) { + error() << "Couldn't dcast: " << itr.first << endmsg; + } else { + if ( th->GetDirectory() != 0 ) { + dirname = th->GetDirectory()->GetPath(); + } + } + } else if ( !tobj ) { + warning() << itr.first << " has NULL TObject ptr" << endmsg; + } + debug() << "finalize: " << thid << endmsg; + } + } +#endif + + if ( writeObjectsToFile().isFailure() ) { + error() << "problems writing histograms" << endmsg; + } + + if ( m_print ) { + info() << "Listing contents of ROOT files: " << endmsg; + } + std::vector<TFile*> deleted_files; + for ( auto& itr : m_files ) { + if ( std::find( deleted_files.begin(), deleted_files.end(), itr.second.first ) == deleted_files.end() ) { + deleted_files.push_back( itr.second.first ); + +#ifndef NDEBUG + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "finalizing stream/file " << itr.first << ":" << itr.second.first->GetName() << endmsg; + } +#endif + } else { +#ifndef NDEBUG + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "already finalized stream " << itr.first << endmsg; + } +#endif + continue; + } + + if ( m_print && msgLevel( MSG::INFO ) ) { + info() << "==> File: " << itr.second.first->GetName() << " stream: " << itr.first << endmsg; + + itr.second.first->Print( "base" ); + } + + std::string tmpfn = itr.second.first->GetName(); + + p_fileMgr->close( itr.second.first, name() ); + + IIncidentSvc* pIncidentSvc = nullptr; + if ( service( "IncidentSvc", pIncidentSvc ).isFailure() ) { + error() << "Unable to get the IncidentSvc" << endmsg; + return StatusCode::FAILURE; + } + + if ( itr.second.second == SHARE ) { + // Merge File + void* vfile = nullptr; + int returncode = + p_fileMgr->open( Io::ROOT, name(), m_sharedFiles[itr.first], Io::WRITE | Io::APPEND, vfile, "HIST" ); + + if ( returncode ) { + error() << "unable to open Final Output File: \"" << m_sharedFiles[itr.first] << "\" for merging" << endmsg; + return StatusCode::FAILURE; + } + + TFile* outputfile = (TFile*)vfile; + pIncidentSvc->fireIncident( FileIncident( name(), IncidentType::WroteToOutputFile, m_sharedFiles[itr.first] ) ); + + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "THistSvcHLT::writeObjectsToFile()::Merging Rootfile " << endmsg; + } + + vfile = nullptr; + returncode = p_fileMgr->open( Io::ROOT, name(), tmpfn, Io::READ, vfile, "HIST" ); + + if ( returncode ) { + error() << "unable to open temporary file: \"" << tmpfn << endmsg; + return StatusCode::FAILURE; + } + + TFile* inputfile = (TFile*)vfile; + + outputfile->SetCompressionLevel( inputfile->GetCompressionLevel() ); + + MergeRootFile( outputfile, inputfile ); + + outputfile->Write(); + p_fileMgr->close( outputfile, name() ); + p_fileMgr->close( inputfile, name() ); + + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "Trying to remove temporary file \"" << tmpfn << "\"" << endmsg; + } + + std::remove( tmpfn.c_str() ); + } + delete itr.second.first; + } + + m_files.clear(); + m_sharedFiles.clear(); + m_fileStreams.clear(); + m_hlist.clear(); // vhid* is deleted in m_tobjs + m_uids.clear(); // vhid* is deleted in m_tobjs + m_ids.clear(); // vhid* is deleted in m_tobjs + + for ( auto& obj : m_tobjs ) { + // TObject*'s are already dealt with through root file i/o + delete obj.second.first; // delete vhid* + } + m_tobjs.clear(); + + return Service::finalize(); +} + +//*************************************************************************// + +StatusCode THistSvcHLT::regHist( const std::string& id ) +{ + std::unique_ptr<TH1> hist = nullptr; + return regHist_i( std::move( hist ), id, false ); +} + +StatusCode THistSvcHLT::regHist( const std::string& id, std::unique_ptr<TH1> hist ) +{ + return regHist_i( std::move( hist ), id, false ); +} + +StatusCode THistSvcHLT::regHist( const std::string& id, std::unique_ptr<TH1> hist, TH1* hist_ptr ) +{ + // This is only to support a common use case where the histogram is used after its registration + if ( hist_ptr != nullptr ) { + hist_ptr = hist.get(); + } + return regHist_i( std::move( hist ), id, false ); +} + +StatusCode THistSvcHLT::regHist( const std::string& id, TH1* hist_ptr ) +{ + std::unique_ptr<TH1> hist( hist_ptr ); + return regHist_i( std::move( hist ), id, false ); +} + +StatusCode THistSvcHLT::getHist( const std::string& id, TH1*& hist, size_t ind ) const +{ + hist = getHist_i<TH1>( id, ind ); + if ( hist != nullptr ) { + return StatusCode::SUCCESS; + } else { + return StatusCode::FAILURE; + } +} + +StatusCode THistSvcHLT::getHist( const std::string& id, TH2*& hist, size_t ind ) const +{ + hist = getHist_i<TH2>( id, ind ); + if ( hist != nullptr ) { + return StatusCode::SUCCESS; + } else { + return StatusCode::FAILURE; + } +} + +StatusCode THistSvcHLT::getHist( const std::string& id, TH3*& hist, size_t ind ) const +{ + hist = getHist_i<TH3>( id, ind ); + if ( hist != nullptr ) { + return StatusCode::SUCCESS; + } else { + return StatusCode::FAILURE; + } +} + +StatusCode THistSvcHLT::regTree( const std::string& id ) +{ + std::unique_ptr<TTree> tree = nullptr; + return regHist_i( std::move( tree ), id, false ); +} + +StatusCode THistSvcHLT::regTree( const std::string& id, std::unique_ptr<TTree> tree ) +{ + StatusCode sc = regHist_i( std::move( tree ), id, false ); + TTree* tr = nullptr; + if ( getTree( id, tr ).isSuccess() && sc.isSuccess() ) { + if ( m_autoSave != 0 ) { + tr->SetAutoSave( m_autoSave ); + } + tr->SetAutoFlush( m_autoFlush ); + } + return sc; +} + +StatusCode THistSvcHLT::regTree( const std::string& id, TTree* tree_ptr ) +{ + std::unique_ptr<TTree> tree( tree_ptr ); + StatusCode sc = regHist_i( std::move( tree ), id, false ); + TTree* tr = nullptr; + if ( getTree( id, tr ).isSuccess() && sc.isSuccess() ) { + if ( m_autoSave != 0 ) { + tr->SetAutoSave( m_autoSave ); + } + tr->SetAutoFlush( m_autoFlush ); + } + return sc; +} + +StatusCode THistSvcHLT::getTree( const std::string& id, TTree*& tree ) const +{ + tree = getHist_i<TTree>( id ); + if ( tree != nullptr ) { + return StatusCode::SUCCESS; + } else { + return StatusCode::FAILURE; + } +} + +StatusCode THistSvcHLT::regGraph( const std::string& id ) +{ + std::unique_ptr<TGraph> graph = std::make_unique<TGraph>(); + return regHist_i( std::move( graph ), id, false ); +} + +StatusCode THistSvcHLT::regGraph( const std::string& id, std::unique_ptr<TGraph> graph ) +{ + if ( strcmp( graph->GetName(), "Graph" ) == 0 ) { + std::string id2( id ); + std::string::size_type i = id2.rfind( "/" ); + if ( i != std::string::npos ) { + id2.erase( 0, i + 1 ); + } + + info() << "setting name of TGraph id: \"" << id << "\" to \"" << id2 << "\" since it is unset" << endmsg; + graph->SetName( id2.c_str() ); + } + + return regHist_i( std::move( graph ), id, false ); +} + +StatusCode THistSvcHLT::regGraph( const std::string& id, TGraph* graph_ptr ) +{ + std::unique_ptr<TGraph> graph( graph_ptr ); + if ( strcmp( graph->GetName(), "Graph" ) == 0 ) { + std::string id2( id ); + std::string::size_type i = id2.rfind( "/" ); + if ( i != std::string::npos ) { + id2.erase( 0, i + 1 ); + } + + info() << "setting name of TGraph id: \"" << id << "\" to \"" << id2 << "\" since it is unset" << endmsg; + graph->SetName( id2.c_str() ); + } + + return regHist_i( std::move( graph ), id, false ); +} + +StatusCode THistSvcHLT::getGraph( const std::string& id, TGraph*& graph ) const +{ + graph = getHist_i<TGraph>( id ); + if ( graph != nullptr ) { + return StatusCode::SUCCESS; + } else { + return StatusCode::FAILURE; + } +} + +StatusCode THistSvcHLT::regShared( const std::string& id, std::unique_ptr<TH1> hist, LockedHandle<TH1>& lh ) +{ + lh = regShared_i<TH1>( id, std::move( hist ) ); + if ( lh ) { + return StatusCode::SUCCESS; + } else { + return StatusCode::FAILURE; + } +} + +StatusCode THistSvcHLT::regShared( const std::string& id, std::unique_ptr<TH2> hist, LockedHandle<TH2>& lh ) +{ + lh = regShared_i<TH2>( id, std::move( hist ) ); + if ( lh ) { + return StatusCode::SUCCESS; + } else { + return StatusCode::FAILURE; + } +} + +StatusCode THistSvcHLT::regShared( const std::string& id, std::unique_ptr<TH3> hist, LockedHandle<TH3>& lh ) +{ + lh = regShared_i<TH3>( id, std::move( hist ) ); + if ( lh ) { + return StatusCode::SUCCESS; + } else { + return StatusCode::FAILURE; + } +} + +StatusCode THistSvcHLT::regShared( const std::string& id, std::unique_ptr<TGraph> graph, LockedHandle<TGraph>& lh ) +{ + lh = regShared_i<TGraph>( id, std::move( graph ) ); + if ( lh ) { + return StatusCode::SUCCESS; + } else { + return StatusCode::FAILURE; + } +} + +StatusCode THistSvcHLT::getShared( const std::string& name, LockedHandle<TH1>& lh ) const +{ + lh = getShared_i<TH1>( name ); + if ( lh ) { + return StatusCode::SUCCESS; + } else { + return StatusCode::FAILURE; + } +} + +StatusCode THistSvcHLT::getShared( const std::string& name, LockedHandle<TH2>& lh ) const +{ + lh = getShared_i<TH2>( name ); + if ( lh ) { + return StatusCode::SUCCESS; + } else { + return StatusCode::FAILURE; + } +} + +StatusCode THistSvcHLT::getShared( const std::string& name, LockedHandle<TH3>& lh ) const +{ + lh = getShared_i<TH3>( name ); + if ( lh ) { + return StatusCode::SUCCESS; + } else { + return StatusCode::FAILURE; + } +} + +StatusCode THistSvcHLT::getShared( const std::string& name, LockedHandle<TGraph>& lh ) const +{ + lh = getShared_i<TGraph>( name ); + if ( lh ) { + return StatusCode::SUCCESS; + } else { + return StatusCode::FAILURE; + } +} + +StatusCode THistSvcHLT::deReg( const std::string& id ) +{ + auto itr = m_uids.find( id ); + if ( itr == m_uids.end() ) { + error() << "Problem deregistering id \"" << id << "\": not found in registry" << endmsg; + return StatusCode::FAILURE; + } + + vhid_t* vh = itr->second; + debug() << "will deregister " << vh->size() << " elements of id \"" << id << "\"" << endmsg; + StatusCode sc( StatusCode::SUCCESS ); + while ( vh->size() > 0 ) { + if ( deReg( vh->back().obj ).isFailure() ) { + sc = StatusCode::FAILURE; + error() << "Problems deRegistering " << vh->size() << " element of id \"" << id << "\"" << endmsg; + break; + } + } + + return sc; +} + +StatusCode THistSvcHLT::deReg( TObject* obj ) +{ + objMap_t::iterator obj_itr = m_tobjs.find( obj ); + if ( obj_itr != m_tobjs.end() ) { + vhid_t* vhid = obj_itr->second.first; + THistID hid = obj_itr->second.first->at( obj_itr->second.second ); + + auto uid_itr = m_uids.find( hid.id ); + if ( uid_itr == m_uids.end() ) { + error() << "Problems deregistering TObject \"" << obj->GetName() << "\" with id \"" << hid.id + << "\": not in uidMap" << endmsg; + return StatusCode::FAILURE; + } + + if ( vhid->size() == 1 ) { + // We are the last object, so we have to delete vhid properly + debug() << "vhid for " << hid.id << " is empty. deleting" << endmsg; + + std::string root, rem; + parseString( hid.id, root, rem ); + + auto mitr = m_ids.equal_range( rem ); + auto id_itr = std::find_if( mitr.first, mitr.second, + [&]( idMap_t::const_reference i ) { return i.second->at( 0 ).obj == obj; } ); + if ( id_itr == mitr.second ) { + error() << "Problems deregistering TObject \"" << obj->GetName() << "\" with id \"" << hid.id + << "\": not in idMap" << endmsg; + return StatusCode::FAILURE; + } + + auto hlist_itr = std::find( m_hlist.begin(), m_hlist.end(), vhid ); + if ( hlist_itr == m_hlist.end() ) { + error() << "Problems deregistering TObject \"" << obj->GetName() << "\" with id \"" << hid.id + << "\": not in hlist" << endmsg; + return StatusCode::FAILURE; + } + + m_tobjs.erase( obj_itr ); + vhid->erase( vhid->begin() + obj_itr->second.second ); + + m_uids.erase( uid_itr ); + m_ids.erase( id_itr ); + m_hlist.erase( hlist_itr ); + + delete vhid; + + } else if ( vhid->size() > 1 ) { + m_tobjs.erase( obj_itr ); + vhid->erase( vhid->begin() + obj_itr->second.second ); + + // vector of THistID is still not empty (i.e. other instances with same name registered) + } else { + error() << "Deregistration failed unexpectedly. (bug in THistSvcHLT?)" << endmsg; + } + return StatusCode::SUCCESS; + } else { + error() << "Cannot unregister TObject \"" << obj->GetName() << "\": not known to THistSvcHLT" << endmsg; + return StatusCode::FAILURE; + } +} + +StatusCode THistSvcHLT::merge( const std::string& name ) +{ + uidMap_t::iterator itr = m_uids.find( name ); + if ( itr == m_uids.end() ) { + error() << "merge: id \"" << name << "\" not found" << endmsg; + return StatusCode::FAILURE; + } + + return merge( itr->second ); +} + +StatusCode THistSvcHLT::merge( TObject* obj ) +{ + objMap_t::iterator itr = m_tobjs.find( obj ); + if ( itr != m_tobjs.end() ) { + return merge( itr->second.first ); + } else { + error() << "merge: unknown object " << obj << endmsg; + return StatusCode::FAILURE; + } +} + +bool THistSvcHLT::exists( const std::string& name ) const { return ( getHist_i<TH1>( name, 0, true ) != nullptr ); } + +std::vector<std::string> THistSvcHLT::getHists() const +{ + std::vector<std::string> names; + names.reserve( m_uids.size() ); + transform_if( std::begin( m_uids ), std::end( m_uids ), std::back_inserter( names ), select1st, + []( uidMap_t::const_reference i ) { return i.second->at( 0 ).obj->IsA()->InheritsFrom( "TH1" ); } ); + return names; +} + +std::vector<std::string> THistSvcHLT::getTrees() const +{ + std::vector<std::string> names; + names.reserve( m_uids.size() ); + transform_if( std::begin( m_uids ), std::end( m_uids ), std::back_inserter( names ), select1st, + []( uidMap_t::const_reference i ) { return i.second->at( 0 ).obj->IsA()->InheritsFrom( "TTree" ); } ); + return names; +} + +std::vector<std::string> THistSvcHLT::getGraphs() const +{ + std::vector<std::string> names; + names.reserve( m_uids.size() ); + transform_if( std::begin( m_uids ), std::end( m_uids ), std::back_inserter( names ), select1st, + []( uidMap_t::const_reference i ) { return i.second->at( 0 ).obj->IsA()->InheritsFrom( "TGraph" ); } ); + return names; +} + +StatusCode THistSvcHLT::getTHists( TDirectory* td, TList& tl, bool rcs ) const +{ + GlobalDirectoryRestore restore( m_svcMut ); + + gErrorIgnoreLevel = kBreak; + + if ( !td->cd() ) { + error() << "getTHists: No such TDirectory \"" << td->GetPath() << "\"" << endmsg; + return StatusCode::FAILURE; + } + + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "getTHists: \"" << td->GetPath() << "\": found " << td->GetListOfKeys()->GetSize() << " keys" << endmsg; + } + + TIter nextkey( td->GetListOfKeys() ); + while ( TKey* key = (TKey*)nextkey() ) { + auto& log = debug(); + if ( msgLevel( MSG::DEBUG ) ) log << " key: " << key->GetName(); + TObject* obj = key->ReadObj(); + if ( obj != 0 && obj->IsA()->InheritsFrom( "TDirectory" ) ) { + if ( msgLevel( MSG::DEBUG ) ) log << " (" << obj->IsA()->GetName() << ")"; + } else if ( obj != 0 && obj->IsA()->InheritsFrom( "TH1" ) ) { + if ( msgLevel( MSG::DEBUG ) ) log << " (" << obj->IsA()->GetName() << ")"; + tl.Add( obj ); + } else if ( obj != 0 ) { + if ( msgLevel( MSG::DEBUG ) ) log << " [" << obj->IsA()->GetName() << "]"; + } + if ( msgLevel( MSG::DEBUG ) ) log << endmsg; + } + + // operate recursively + if ( rcs ) { + nextkey = td->GetListOfKeys(); + while ( TKey* key = (TKey*)nextkey() ) { + TObject* obj = key->ReadObj(); + if ( obj && obj->IsA()->InheritsFrom( "TDirectory" ) ) { + TDirectory* tt = dynamic_cast<TDirectory*>( obj ); + getTHists( tt, tl, rcs ); + } + } + } + + return StatusCode::SUCCESS; +} + +StatusCode THistSvcHLT::getTHists( const std::string& dir, TList& tl, bool rcs ) const +{ + + GlobalDirectoryRestore restore( m_svcMut ); + + gErrorIgnoreLevel = kBreak; + + StatusCode sc; + + std::string stream, rem, r2; + parseString( dir, stream, rem ); + + auto itr = m_files.find( stream ); + if ( itr != m_files.end() ) { + r2 = itr->second.first->GetName(); + r2 += ":/"; + r2 += rem; + + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "getTHists: \"" << dir << "\" looks like a stream name." + << " associated TFile: \"" << itr->second.first->GetName() << "\"" << endmsg; + } + + if ( gDirectory->cd( r2.c_str() ) ) { + m_curstream = stream; + sc = getTHists( gDirectory, tl, rcs ); + m_curstream = ""; + return sc; + } else { + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "getTHists: no such TDirectory \"" << r2 << "\"" << endmsg; + } + } + + } else { + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "getTHists: stream \"" << stream << "\" not found" << endmsg; + } + } + + if ( !gDirectory->cd( dir.c_str() ) ) { + error() << "getTHists: No such TDirectory/stream \"" << dir << "\"" << endmsg; + sc = StatusCode::FAILURE; + } else { + sc = getTHists( gDirectory, tl, rcs ); + } + + return sc; +} + +StatusCode THistSvcHLT::getTHists( TDirectory* td, TList& tl, bool rcs, bool reg ) +{ + GlobalDirectoryRestore restore( m_svcMut ); + + gErrorIgnoreLevel = kBreak; + + if ( !td->cd() ) { + error() << "getTHists: No such TDirectory \"" << td->GetPath() << "\"" << endmsg; + return StatusCode::FAILURE; + } + + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "getTHists: \"" << td->GetPath() << "\": found " << td->GetListOfKeys()->GetSize() << " keys" << endmsg; + } + + TIter nextkey( td->GetListOfKeys() ); + while ( TKey* key = (TKey*)nextkey() ) { + auto& log = debug(); + if ( msgLevel( MSG::DEBUG ) ) log << " key: " << key->GetName(); + TObject* obj = key->ReadObj(); + if ( obj && obj->IsA()->InheritsFrom( "TDirectory" ) ) { + if ( msgLevel( MSG::DEBUG ) ) log << " (" << obj->IsA()->GetName() << ")"; + } else if ( obj && obj->IsA()->InheritsFrom( "TH1" ) ) { + if ( msgLevel( MSG::DEBUG ) ) log << " (" << obj->IsA()->GetName() << ")"; + tl.Add( obj ); + if ( reg && m_curstream != "" ) { + std::string dir = td->GetPath(); + std::string fil = td->GetFile()->GetName(); + dir.erase( 0, fil.length() + 1 ); + std::string id = "/" + m_curstream; + if ( dir == "/" ) { + id = id + "/" + key->GetName(); + } else { + id = id + dir + "/" + key->GetName(); + } + if ( !exists( id ) ) { + if ( msgLevel( MSG::DEBUG ) ) log << " reg as \"" << id << "\""; + regHist( id ).ignore(); + } else { + if ( msgLevel( MSG::DEBUG ) ) log << " already registered"; + } + } + } else if ( obj ) { + if ( msgLevel( MSG::DEBUG ) ) log << " [" << obj->IsA()->GetName() << "]"; + } + if ( msgLevel( MSG::DEBUG ) ) log << endmsg; + } + + // operate recursively + if ( rcs ) { + nextkey = td->GetListOfKeys(); + while ( TKey* key = (TKey*)nextkey() ) { + TObject* obj = key->ReadObj(); + if ( obj && obj->IsA()->InheritsFrom( "TDirectory" ) ) { + TDirectory* tt = dynamic_cast<TDirectory*>( obj ); + getTHists( tt, tl, rcs, reg ); + } + } + } + + return StatusCode::SUCCESS; +} + +StatusCode THistSvcHLT::getTHists( const std::string& dir, TList& tl, bool rcs, bool reg ) +{ + GlobalDirectoryRestore restore( m_svcMut ); + + gErrorIgnoreLevel = kBreak; + + StatusCode sc; + + std::string stream, rem, r2; + parseString( dir, stream, rem ); + + auto itr = m_files.find( stream ); + if ( itr != m_files.end() ) { + r2 = itr->second.first->GetName(); + r2 += ":/"; + r2 += rem; + + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "getTHists: \"" << dir << "\" looks like a stream name." + << " associated TFile: \"" << itr->second.first->GetName() << "\"" << endmsg; + } + + if ( gDirectory->cd( r2.c_str() ) ) { + m_curstream = stream; + sc = getTHists( gDirectory, tl, rcs, reg ); + m_curstream.clear(); + return sc; + } + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "getTHists: no such TDirectory \"" << r2 << "\"" << endmsg; + } + } else { + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "getTHists: stream \"" << stream << "\" not found" << endmsg; + } + } + + if ( !gDirectory->cd( dir.c_str() ) ) { + error() << "getTHists: No such TDirectory/stream \"" << dir << "\"" << endmsg; + sc = StatusCode::FAILURE; + } else { + if ( reg ) { + warning() << "Unable to register histograms automatically " + << "without a valid stream name" << endmsg; + reg = false; + } + sc = getTHists( gDirectory, tl, rcs, reg ); + } + + return sc; +} + +StatusCode THistSvcHLT::getTTrees( TDirectory* td, TList& tl, bool rcs ) const +{ + GlobalDirectoryRestore restore( m_svcMut ); + + gErrorIgnoreLevel = kBreak; + + if ( !td->cd() ) { + error() << "getTTrees: No such TDirectory \"" << td->GetPath() << "\"" << endmsg; + return StatusCode::FAILURE; + } + + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "getTHists: \"" << td->GetPath() << "\": found " << td->GetListOfKeys()->GetSize() << " keys" << endmsg; + } + + TIter nextkey( td->GetListOfKeys() ); + while ( TKey* key = (TKey*)nextkey() ) { + auto& log = debug(); + if ( msgLevel( MSG::DEBUG ) ) log << " key: " << key->GetName(); + TObject* obj = key->ReadObj(); + if ( obj != 0 && obj->IsA()->InheritsFrom( "TDirectory" ) ) { + if ( msgLevel( MSG::DEBUG ) ) log << " (" << obj->IsA()->GetName() << ")"; + } else if ( obj != 0 && obj->IsA()->InheritsFrom( "TTree" ) ) { + if ( msgLevel( MSG::DEBUG ) ) log << " (" << obj->IsA()->GetName() << ")"; + tl.Add( obj ); + } else if ( obj != 0 ) { + if ( msgLevel( MSG::DEBUG ) ) log << " [" << obj->IsA()->GetName() << "]"; + } + log << endmsg; + } + + // operate recursively + if ( rcs ) { + nextkey = td->GetListOfKeys(); + while ( TKey* key = (TKey*)nextkey() ) { + TObject* obj = key->ReadObj(); + if ( obj && obj->IsA()->InheritsFrom( "TDirectory" ) ) { + TDirectory* tt = dynamic_cast<TDirectory*>( obj ); + getTTrees( tt, tl, rcs ); + } + } + } + + return StatusCode::SUCCESS; +} + +StatusCode THistSvcHLT::getTTrees( const std::string& dir, TList& tl, bool rcs ) const +{ + GlobalDirectoryRestore restore( m_svcMut ); + + gErrorIgnoreLevel = kBreak; + + StatusCode sc; + + std::string stream, rem, r2; + parseString( dir, stream, rem ); + + auto itr = m_files.find( stream ); + if ( itr != m_files.end() ) { + r2 = itr->second.first->GetName(); + r2 += ":/"; + r2 += rem; + + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "getTTrees: \"" << dir << "\" looks like a stream name." + << " associated TFile: \"" << itr->second.first->GetName() << "\"" << endmsg; + } + + if ( gDirectory->cd( r2.c_str() ) ) { + return getTTrees( gDirectory, tl, rcs ); + } + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "getTTrees: no such TDirectory \"" << r2 << "\"" << endmsg; + } + } else { + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "getTTrees: stream \"" << stream << "\" not found" << endmsg; + } + } + + if ( !gDirectory->cd( dir.c_str() ) ) { + error() << "getTTrees: No such TDirectory/stream \"" << dir << "\"" << endmsg; + sc = StatusCode::FAILURE; + } else { + sc = getTTrees( gDirectory, tl, rcs ); + } + return sc; +} + +StatusCode THistSvcHLT::getTTrees( TDirectory* td, TList& tl, bool rcs, bool reg ) +{ + GlobalDirectoryRestore restore( m_svcMut ); + + gErrorIgnoreLevel = kBreak; + + if ( !td->cd() ) { + error() << "getTTrees: No such TDirectory \"" << td->GetPath() << "\"" << endmsg; + return StatusCode::FAILURE; + } + + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "getTHists: \"" << td->GetPath() << "\": found " << td->GetListOfKeys()->GetSize() << " keys" << endmsg; + } + + TIter nextkey( td->GetListOfKeys() ); + while ( TKey* key = (TKey*)nextkey() ) { + auto& log = debug(); + if ( msgLevel( MSG::DEBUG ) ) log << " key: " << key->GetName(); + TObject* obj = key->ReadObj(); + if ( obj && obj->IsA()->InheritsFrom( "TDirectory" ) ) { + if ( msgLevel( MSG::DEBUG ) ) log << " (" << obj->IsA()->GetName() << ")"; + } else if ( obj && obj->IsA()->InheritsFrom( "TTree" ) ) { + if ( msgLevel( MSG::DEBUG ) ) log << " (" << obj->IsA()->GetName() << ")"; + tl.Add( obj ); + if ( reg && m_curstream != "" ) { + std::string dir = td->GetPath(); + std::string fil = td->GetFile()->GetName(); + dir.erase( 0, fil.length() + 1 ); + std::string id = "/" + m_curstream; + if ( dir == "/" ) { + id = id + "/" + key->GetName(); + } else { + id = id + dir + "/" + key->GetName(); + } + if ( !exists( id ) ) { + if ( msgLevel( MSG::DEBUG ) ) log << " reg as \"" << id << "\""; + regHist( id ).ignore(); + } else { + if ( msgLevel( MSG::DEBUG ) ) log << " already registered"; + } + } + } else if ( obj != 0 ) { + if ( msgLevel( MSG::DEBUG ) ) log << " [" << obj->IsA()->GetName() << "]"; + } + if ( msgLevel( MSG::DEBUG ) ) log << endmsg; + } + + // operate recursively + if ( rcs ) { + nextkey = td->GetListOfKeys(); + while ( TKey* key = (TKey*)nextkey() ) { + TObject* obj = key->ReadObj(); + if ( obj && obj->IsA()->InheritsFrom( "TDirectory" ) ) { + TDirectory* tt = dynamic_cast<TDirectory*>( obj ); + getTTrees( tt, tl, rcs, reg ); + } + } + } + + return StatusCode::SUCCESS; +} + +StatusCode THistSvcHLT::getTTrees( const std::string& dir, TList& tl, bool rcs, bool reg ) +{ + GlobalDirectoryRestore restore( m_svcMut ); + + gErrorIgnoreLevel = kBreak; + + StatusCode sc; + + std::string stream, rem, r2; + parseString( dir, stream, rem ); + + auto itr = m_files.find( stream ); + if ( itr != m_files.end() ) { + r2 = itr->second.first->GetName(); + r2 += ":/"; + r2 += rem; + + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "getTTrees: \"" << dir << "\" looks like a stream name." + << " associated TFile: \"" << itr->second.first->GetName() << "\"" << endmsg; + } + + if ( gDirectory->cd( r2.c_str() ) ) { + return getTTrees( gDirectory, tl, rcs, reg ); + } else { + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "getTTrees: no such TDirectory \"" << r2 << "\"" << endmsg; + } + } + } else { + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "getTTrees: stream \"" << stream << "\" not found" << endmsg; + } + } + + if ( !gDirectory->cd( dir.c_str() ) ) { + error() << "getTTrees: No such TDirectory/stream \"" << dir << "\"" << endmsg; + return StatusCode::FAILURE; + } + + return getTTrees( gDirectory, tl, rcs, reg ); +} + +//*************************************************************************// + +void THistSvcHLT::handle( const Incident& /* inc */ ) +{ + if ( m_signaledStop ) return; + + if ( m_maxFileSize.value() == -1 ) return; + + // convert to bytes. + Long64_t mfs = (Long64_t)m_maxFileSize.value() * (Long64_t)1048576; + Long64_t mfs_warn = mfs * 95 / 100; + + updateFiles(); + + std::map<std::string, std::pair<TFile*, Mode>>::const_iterator itr; + for ( const auto& f : m_files ) { + TFile* tf = f.second.first; + +#ifndef NDEBUG + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "stream: " << f.first << " name: " << tf->GetName() << " size: " << tf->GetSize() << endmsg; + } +#endif + + // Signal job to terminate if output file is too large + if ( tf->GetSize() > mfs ) { + + m_signaledStop = true; + + fatal() << "file \"" << tf->GetName() << "\" associated with stream \"" << f.first + << "\" has exceeded the max file size of " << m_maxFileSize.value() << "MB. Terminating Job." << endmsg; + + IEventProcessor* evt = nullptr; + if ( service( "ApplicationMgr", evt, true ).isSuccess() ) { + evt->stopRun(); + evt->release(); + } else { + abort(); + } + } else if ( tf->GetSize() > mfs_warn ) { + warning() << "file \"" << tf->GetName() << "\" associated with stream \"" << f.first + << "\" is at 95% of its maximum allowable file size of " << m_maxFileSize.value() << "MB" << endmsg; + } + } +} + +/** @brief callback method to reinitialize the internal state of + * the component for I/O purposes (e.g. upon @c fork(2)) + */ +StatusCode THistSvcHLT::io_reinit() +{ + bool all_good = true; + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "reinitializing I/O..." << endmsg; + } + + // retrieve the I/O component manager... + + IIoComponentMgr* iomgr = nullptr; + + if ( service( "IoComponentMgr", iomgr, true ).isFailure() ) { + error() << "could not retrieve I/O component manager !" << endmsg; + return StatusCode::FAILURE; + } + + GlobalDirectoryRestore restore( m_svcMut ); + // to hide the expected errors upon closing the files whose + // file descriptors have been swept under the rug... + gErrorIgnoreLevel = kFatal; + + for ( auto& ifile : m_files ) { + TFile* f = ifile.second.first; + std::string fname = f->GetName(); + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "file [" << fname << "] mode: [" << f->GetOption() << "] r:" << f->GetFileBytesRead() + << " w:" << f->GetFileBytesWritten() << " cnt:" << f->GetFileCounter() << endmsg; + } + + if ( ifile.second.second == READ ) { + if ( msgLevel( MSG::DEBUG ) ) { + debug() << " TFile opened in READ mode: not reassigning names" << endmsg; + } + continue; + } + + if ( !iomgr->io_retrieve( this, fname ).isSuccess() ) { + error() << "could not retrieve new name for [" << fname << "] !!" << endmsg; + all_good = false; + continue; + } else { + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "got a new name [" << fname << "]..." << endmsg; + } + } + + void* vf = nullptr; + Option_t* opts = f->GetOption(); + int r = p_fileMgr->open( Io::ROOT, name(), fname, Io::WRITE, vf, "HIST" ); + if ( r != 0 ) { + error() << "unable to open file \"" << fname << "\" for writing" << endmsg; + return StatusCode::FAILURE; + } + TFile* newfile = (TFile*)vf; + newfile->SetOption( opts ); + + if ( ifile.second.second != THistSvcHLT::READ ) { + copyFileLayout( newfile, f ); + ifile.second.first = newfile; + } + + // loop over all uids and migrate them to the new file + for ( auto& uid : m_uids ) { + for ( auto& hid : *uid.second ) { + if ( hid.file != f ) continue; + TDirectory* olddir = this->changeDir( hid ); + hid.file = newfile; + // side-effect: create needed directories... + TDirectory* newdir = this->changeDir( hid ); + TClass* cl = hid.obj->IsA(); + + // migrate the objects to the new file. + // thanks to the object model of ROOT, it is super easy. + if ( cl->InheritsFrom( "TTree" ) ) { + dynamic_cast<TTree*>( hid.obj )->SetDirectory( newdir ); + dynamic_cast<TTree*>( hid.obj )->Reset(); + } else if ( cl->InheritsFrom( "TH1" ) ) { + dynamic_cast<TH1*>( hid.obj )->SetDirectory( newdir ); + dynamic_cast<TH1*>( hid.obj )->Reset(); + } else if ( cl->InheritsFrom( "TGraph" ) ) { + olddir->Remove( hid.obj ); + newdir->Append( hid.obj ); + } else { + error() << "id: \"" << hid.id << "\" is not a inheriting from a class " + << "we know how to handle (received [" << cl->GetName() << "], " + << "expected [TTree, TH1 or TGraph]) !" << endmsg << "attaching to current dir [" << newdir->GetPath() + << "] " + << "nonetheless..." << endmsg; + olddir->Remove( hid.obj ); + newdir->Append( hid.obj ); + } + } + } + f->ReOpen( "READ" ); + p_fileMgr->close( f, name() ); + f = newfile; + } + + return all_good ? StatusCode::SUCCESS : StatusCode::FAILURE; +} + +//*************************************************************************// + +THistSvcHLT::GlobalDirectoryRestore::GlobalDirectoryRestore( THistSvcMutex_t& mut ) : m_lock( mut ) +{ + m_gDirectory = gDirectory; + m_gFile = gFile; + m_gErrorIgnoreLevel = gErrorIgnoreLevel; +} + +THistSvcHLT::GlobalDirectoryRestore::~GlobalDirectoryRestore() +{ + gDirectory = m_gDirectory; + gFile = m_gFile; + gErrorIgnoreLevel = m_gErrorIgnoreLevel; +} + +//*************************************************************************// + +template <typename T> +T* THistSvcHLT::readHist( const std::string& id ) const +{ + return dynamic_cast<T*>( readHist_i<T>( id ) ); +} + +TTree* THistSvcHLT::readTree( const std::string& id ) const { return dynamic_cast<TTree*>( readHist_i<TTree>( id ) ); } + +void THistSvcHLT::updateFiles() +{ + // If TTrees grow beyond TTree::fgMaxTreeSize, a new file is + // automatically created by root, and the old one closed. We + // need to migrate all the UIDs over to show the correct file + // pointer. This is ugly. + + if ( msgLevel( MSG::DEBUG ) ) debug() << "updateFiles()" << endmsg; + + for ( auto uitr = m_uids.begin(); uitr != m_uids.end(); ++uitr ) { + for ( auto& hid : *( uitr->second ) ) { +#ifndef NDEBUG + if ( msgLevel( MSG::VERBOSE ) ) + verbose() << " update: " << uitr->first << " " << hid.id << " " << hid.mode << endmsg; +#endif + TObject* to = hid.obj; + TFile* oldFile = hid.file; + if ( !to ) { + warning() << uitr->first << ": TObject == 0" << endmsg; + } else if ( hid.temp || hid.mode == READ ) { +// do nothing - no need to check how big the file is since we +// are just reading it. +#ifndef NDEBUG + if ( msgLevel( MSG::VERBOSE ) ) verbose() << " skipping" << endmsg; +#endif + } else if ( to->IsA()->InheritsFrom( "TTree" ) ) { + TTree* tr = dynamic_cast<TTree*>( to ); + TFile* newFile = tr->GetCurrentFile(); + + if ( oldFile != newFile ) { + std::string newFileName = newFile->GetName(); + std::string oldFileName, streamName, rem; + TFile* dummy = nullptr; + findStream( hid.id, streamName, rem, dummy ); + + for ( auto& itr : m_files ) { + if ( itr.second.first == oldFile ) { + itr.second.first = newFile; + } + } + + for ( auto uitr2 = uitr; uitr2 != m_uids.end(); ++uitr2 ) { + for ( auto& hid2 : *( uitr2->second ) ) { + if ( hid2.file == oldFile ) { + hid2.file = newFile; + } + } + } + + auto sitr = std::find_if( std::begin( m_fileStreams ), std::end( m_fileStreams ), + [&]( streamMap::const_reference s ) { return s.second == streamName; } ); + if ( sitr != std::end( m_fileStreams ) ) oldFileName = sitr->first; + +#ifndef NDEBUG + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "migrating uid: " << hid.id << " stream: " << streamName << " oldFile: " << oldFileName + << " newFile: " << newFileName << endmsg; + } +#endif + + if ( !oldFileName.empty() ) { + auto i = m_fileStreams.lower_bound( oldFileName ); + while ( i != std::end( m_fileStreams ) && i->first == oldFileName ) { +#ifndef NDEBUG + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "changing filename \"" << i->first << "\" to \"" << newFileName << "\" for stream \"" + << i->second << "\"" << endmsg; + } +#endif + std::string nm = std::move( i->second ); + i = m_fileStreams.erase( i ); + m_fileStreams.emplace( newFileName, std::move( nm ) ); + } + } else { + error() << "Problems updating fileStreams with new file name" << endmsg; + } + } + } + } + } +} + +StatusCode THistSvcHLT::writeObjectsToFile() +{ + updateFiles(); + + std::for_each( m_files.begin(), m_files.end(), []( std::pair<const std::string, std::pair<TFile*, Mode>>& i ) { + auto mode = i.second.second; + auto file = i.second.first; + if ( mode == WRITE || mode == UPDATE || mode == SHARE ) { + file->Write( "", TObject::kOverwrite ); + } else if ( mode == APPEND ) { + file->Write( "" ); + } + } ); + + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "THistSvcHLT::writeObjectsToFile()::List of Files connected in ROOT " << endmsg; + TSeqCollection* filelist = gROOT->GetListOfFiles(); + for ( int ii = 0; ii < filelist->GetEntries(); ii++ ) { + debug() << "THistSvcHLT::writeObjectsToFile()::List of Files connected in ROOT: \"" << filelist->At( ii )->GetName() + << "\"" << endmsg; + } + } + + return StatusCode::SUCCESS; +} + +StatusCode THistSvcHLT::connect( const std::string& ident ) +{ + auto loc = ident.find( " " ); + std::string stream = ident.substr( 0, loc ); + char typ( 0 ); + typedef std::pair<std::string, std::string> Prop; + std::vector<Prop> props; + std::string filename, db_typ( "ROOT" ); + int cl( 1 ); + + if ( loc != std::string::npos ) { + using Parser = Gaudi::Utils::AttribStringParser; + for ( auto attrib : Parser( ident.substr( loc + 1 ) ) ) { + auto TAG = boost::algorithm::to_upper_copy( attrib.tag ); + auto VAL = boost::algorithm::to_upper_copy( attrib.value ); + + if ( TAG == "FILE" || TAG == "DATAFILE" ) { + filename = attrib.value; + removeDoubleSlash( filename ); + } else if ( TAG == "OPT" ) { + if ( VAL == "APPEND" || VAL == "UPDATE" ) { + typ = 'A'; + } else if ( VAL == "CREATE" || VAL == "NEW" || VAL == "WRITE" ) { + typ = 'N'; + } else if ( VAL == "RECREATE" ) { + typ = 'R'; + } else if ( VAL == "SHARE" ) { + typ = 'S'; + } else if ( VAL == "OLD" || VAL == "READ" ) { + typ = 'O'; + } else { + error() << "Unknown OPT: \"" << attrib.value << "\"" << endmsg; + typ = 0; + } + } else if ( TAG == "TYP" ) { + db_typ = std::move( attrib.value ); + } else if ( TAG == "CL" ) { + cl = std::stoi( attrib.value ); + } else { + props.emplace_back( attrib.tag, attrib.value ); + } + } + } + + if ( stream == "temp" ) { + error() << "in JobOption \"" << ident << "\": stream name \"temp\" reserved." << endmsg; + return StatusCode::FAILURE; + } + + if ( db_typ != "ROOT" ) { + error() << "in JobOption \"" << ident << "\": technology type \"" << db_typ << "\" not supported." << endmsg; + return StatusCode::FAILURE; + } + + if ( m_files.find( stream ) != m_files.end() ) { + error() << "in JobOption \"" << ident << "\":\n stream \"" << stream << "\" already connected to file: \"" + << m_files[stream].first->GetName() << "\"" << endmsg; + return StatusCode::FAILURE; + } + + Mode newMode; + if ( typ == 'O' ) { + newMode = THistSvcHLT::READ; + } else if ( typ == 'N' ) { + newMode = THistSvcHLT::WRITE; + } else if ( typ == 'A' ) { + newMode = THistSvcHLT::APPEND; + } else if ( typ == 'R' ) { + newMode = THistSvcHLT::UPDATE; + } else if ( typ == 'S' ) { + newMode = THistSvcHLT::SHARE; + } else { + // something else? + error() << "No OPT= specified or unknown access mode in: " << ident << endmsg; + return StatusCode::FAILURE; + } + + // Is this file already connected to another stream? + if ( m_fileStreams.find( filename ) != m_fileStreams.end() ) { + auto fitr = m_fileStreams.equal_range( filename ); + + const std::string& oldstream = fitr.first->second; + + const auto& f_info = m_files[oldstream]; + + if ( newMode != f_info.second ) { + error() << "in JobOption \"" << ident << "\":\n file \"" << filename << "\" already opened by stream: \"" + << oldstream << "\" with different access mode." << endmsg; + return StatusCode::FAILURE; + } else { + TFile* f2 = f_info.first; + m_files[stream] = std::make_pair( f2, newMode ); + if ( msgLevel( MSG::DEBUG ) ) + debug() << "Connecting stream: \"" << stream << "\" to previously opened TFile: \"" << filename << "\"" + << endmsg; + return StatusCode::SUCCESS; + } + } + + IIncidentSvc* pi = nullptr; + if ( service( "IncidentSvc", pi ).isFailure() ) { + error() << "Unable to get the IncidentSvc" << endmsg; + return StatusCode::FAILURE; + } + + void* vf = nullptr; + TFile* f = nullptr; + + if ( newMode == THistSvcHLT::READ ) { + // old file + int r = p_fileMgr->open( Io::ROOT, name(), filename, Io::READ, vf, "HIST" ); + + if ( r != 0 ) { + error() << "Unable to open ROOT file " << filename << " for reading" << endmsg; + return StatusCode::FAILURE; + } + + f = (TFile*)vf; + + // FIX ME! + pi->fireIncident( FileIncident( name(), "BeginHistFile", filename ) ); + + } else if ( newMode == THistSvcHLT::WRITE ) { + // new file. error if file exists + int r = p_fileMgr->open( Io::ROOT, name(), filename, ( Io::WRITE | Io::CREATE | Io::EXCL ), vf, "HIST" ); + + if ( r != 0 ) { + error() << "Unable to open ROOT file " << filename << " for writing" << endmsg; + return StatusCode::FAILURE; + } + + f = (TFile*)vf; + + } else if ( newMode == THistSvcHLT::APPEND ) { + // update file + int r = p_fileMgr->open( Io::ROOT, name(), filename, ( Io::WRITE | Io::APPEND ), vf, "HIST" ); + if ( r != 0 ) { + error() << "unable to open file \"" << filename << "\" for appending" << endmsg; + return StatusCode::FAILURE; + } + + f = (TFile*)vf; + + } else if ( newMode == THistSvcHLT::SHARE ) { + // SHARE file type + // For SHARE files, all data will be stored in a temp file and will be + // merged into the target file in writeObjectsToFile() when finalize(), + // this help to solve some confliction. e.g. with storegate + static int ishared = 0; + std::string realfilename = filename; + filename = "tmp_THistSvcHLT_" + std::to_string( ishared++ ) + ".root"; + + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "Creating temp file \"" << filename << "\" and realfilename=" << realfilename << endmsg; + } + m_sharedFiles[stream] = realfilename; + + int r = p_fileMgr->open( Io::ROOT, name(), filename, ( Io::WRITE | Io::CREATE | Io::EXCL ), vf, "HIST" ); + + if ( r != 0 ) { + error() << "Unable to open ROOT file " << filename << " for writing" << endmsg; + return StatusCode::FAILURE; + } + + f = (TFile*)vf; + + } else if ( newMode == THistSvcHLT::UPDATE ) { + // update file + int r = p_fileMgr->open( Io::ROOT, name(), filename, ( Io::WRITE | Io::CREATE ), vf, "HIST" ); + + if ( r != 0 ) { + error() << "Unable to open ROOT file " << filename << " for appending" << endmsg; + return StatusCode::FAILURE; + } + + f = (TFile*)vf; + } + + m_files[stream] = std::make_pair( f, newMode ); + m_fileStreams.insert( std::make_pair( filename, stream ) ); + + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "Opening TFile \"" << filename << "\" stream: \"" << stream << "\" mode: \"" << typ << "\"" + << " comp level: " << cl << endmsg; + } + + return StatusCode::SUCCESS; +} + +TDirectory* THistSvcHLT::changeDir( const THistSvcHLT::THistID& hid ) const +{ + std::string uid = hid.id; + TFile* file = hid.file; + std::string stream, fdir, bdir, dir, id; + + if ( file ) { + file->cd( "/" ); + } else { + gROOT->cd(); + } + + fdir = uid; + bdir = stripDirectoryName( fdir ); + + while ( ( dir = stripDirectoryName( fdir ) ) != "" ) { + if ( !gDirectory->GetKey( dir.c_str() ) ) { + gDirectory->mkdir( dir.c_str() ); + } + gDirectory->cd( dir.c_str() ); + } + + return gDirectory; +} + +std::string THistSvcHLT::stripDirectoryName( std::string& dir ) const +{ + std::string::size_type i = dir.find( "/" ); + + if ( i == std::string::npos ) return {}; + + if ( i == 0 ) { + dir.erase( 0, 1 ); + return stripDirectoryName( dir ); + } + + std::string root = dir.substr( 0, i ); + dir.erase( 0, i ); + + return root; +} + +void THistSvcHLT::removeDoubleSlash( std::string& id ) const +{ + while ( id.find( "//" ) != std::string::npos ) { + id.replace( id.find( "//" ), 2, "/" ); + } +} + +void THistSvcHLT::MergeRootFile( TDirectory* target, TDirectory* source ) +{ + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "Target path: " << target->GetPath() << endmsg; + } + TString path( (char*)strstr( target->GetPath(), ":" ) ); + path.Remove( 0, 2 ); + + source->cd( path ); + TDirectory* current_sourcedir = gDirectory; + + // loop over all keys in this directory + TList* lkeys = current_sourcedir->GetListOfKeys(); + int nkeys = lkeys->GetEntries(); + TKey* key = nullptr; + for ( int jj = 0; jj < nkeys; jj++ ) { + key = (TKey*)lkeys->At( jj ); + std::string pathnameinsource = current_sourcedir->GetPath() + std::string( "/" ) + key->GetName(); + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "Reading Key:" << pathnameinsource << endmsg; + } + TObject* obj = source->Get( pathnameinsource.c_str() ); + + if ( obj ) { + if ( obj->IsA()->InheritsFrom( "TDirectory" ) ) { + // it's a subdirectory + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "Found subdirectory " << obj->GetName() << endmsg; + } + + // create a new subdir of same name and title in the target file + target->cd(); + TDirectory* newtargetdir = target->mkdir( obj->GetName(), obj->GetTitle() ); + + MergeRootFile( newtargetdir, source ); + + } else if ( obj->IsA()->InheritsFrom( "TTree" ) ) { + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "Found TTree " << obj->GetName() << endmsg; + } + TTree* mytree = dynamic_cast<TTree*>( obj ); + int nentries = (int)mytree->GetEntries(); + mytree->SetBranchStatus( "*", 1 ); + + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "Dumping TTree " << nentries << " entries" << endmsg; + } + target->cd(); + mytree->CloneTree(); + + } else { + target->cd(); + obj->Write( key->GetName() ); + } + } + } +} + +bool THistSvcHLT::findStream( const std::string& id, std::string& stream, std::string& rem, TFile*& file ) const +{ + auto pos = id.find( "/" ); + + if ( pos == std::string::npos ) { + // no "/" in id + stream = "temp"; + rem = id; + } else if ( pos != 0 ) { + // id does not start with "/" + stream = "temp"; + rem = id; + } else { + // id starts with "/" + + auto pos2 = id.find( "/", pos + 1 ); + + if ( pos2 == std::string::npos ) { + // need at least 2 "/" in format "/STREAM/name" or "/STREAM/dir/name" + error() << "badly formed Hist/Tree id: \"" << id << "\"" << endmsg; + return false; + } + parseString( id, stream, rem ); + } + + if ( stream == "temp" ) { + file = nullptr; + return true; + } + + auto itr = m_files.find( stream ); + file = ( itr != m_files.end() ? itr->second.first : nullptr ); + if ( !file ) { + warning() << "no stream \"" << stream << "\" associated with id: \"" << id << "\"" << endmsg; + } + + return true; +} + +void THistSvcHLT::parseString( const std::string& id, std::string& root, std::string& rem ) const +{ + auto pos = id.find( "/" ); + + if ( pos == std::string::npos ) { + root.clear(); + rem = id; + } else if ( pos == 0 ) { + parseString( id.substr( 1 ), root, rem ); + } else { + root = id.substr( 0, pos ); + rem = id.substr( pos + 1 ); + } +} + +void THistSvcHLT::setupInputFile( Gaudi::Details::PropertyBase& + /*m_inputfile*/ ) +{ + if ( FSMState() < Gaudi::StateMachine::CONFIGURED || !m_okToConnect ) { + debug() << "Delaying connection of Input Files until Initialize" + << ". now in " << FSMState() << endmsg; + + m_delayConnect = true; + } else { + debug() << "Now connecting of Input Files" << endmsg; + + StatusCode sc = StatusCode::SUCCESS; + + for ( const auto& itr : m_inputfile.value() ) { + if ( m_alreadyConnectedInFiles.end() != m_alreadyConnectedInFiles.find( itr ) ) { + continue; + } + if ( connect( itr ).isFailure() ) { + sc = StatusCode::FAILURE; + } else { + m_alreadyConnectedInFiles.insert( itr ); + } + } + + if ( !sc.isSuccess() ) { + throw GaudiException( "Problem connecting inputfile !!", name(), StatusCode::FAILURE ); + } + } +} + +void THistSvcHLT::setupOutputFile( Gaudi::Details::PropertyBase& + /*m_outputfile*/ ) +{ + if ( FSMState() < Gaudi::StateMachine::CONFIGURED || !m_okToConnect ) { + debug() << "Delaying connection of Input Files until Initialize" + << ". now in " << FSMState() << endmsg; + m_delayConnect = true; + } else { + StatusCode sc = StatusCode::SUCCESS; + for ( const auto& itr : m_outputfile.value() ) { + if ( m_alreadyConnectedOutFiles.end() != m_alreadyConnectedOutFiles.find( itr ) ) { + continue; + } + if ( connect( itr ).isFailure() ) { + sc = StatusCode::FAILURE; + } else { + m_alreadyConnectedOutFiles.insert( itr ); + } + } + + if ( !sc.isSuccess() ) { + throw GaudiException( "Problem connecting outputfile !!", name(), StatusCode::FAILURE ); + } + } +} + +void THistSvcHLT::setupCompressionLevel( Gaudi::Details::PropertyBase& + /* cl */ ) +{ + warning() << "\"CompressionLevel\" Property has been deprecated. " + << "Set it via the \"CL=\" parameter in the \"Output\" Property" << endmsg; +} + +void THistSvcHLT::copyFileLayout( TDirectory* destination, TDirectory* source ) +{ + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "copyFileLayout() to destination path: " << destination->GetPath() << endmsg; + } + + // strip out URLs + TString path( (char*)strstr( destination->GetPath(), ":" ) ); + path.Remove( 0, 2 ); + + source->cd( path ); + TDirectory* current_source_dir = gDirectory; + + // loop over all keys in this directory + TList* key_list = current_source_dir->GetListOfKeys(); + int n = key_list->GetEntries(); + for ( int j = 0; j < n; ++j ) { + TKey* k = (TKey*)key_list->At( j ); + const std::string source_pathname = current_source_dir->GetPath() + std::string( "/" ) + k->GetName(); + TObject* o = source->Get( source_pathname.c_str() ); + + if ( o && o->IsA()->InheritsFrom( "TDirectory" ) ) { + if ( msgLevel( MSG::VERBOSE ) ) { + verbose() << " subdir [" << o->GetName() << "]..." << endmsg; + } + destination->cd(); + TDirectory* destination_dir = destination->mkdir( o->GetName(), o->GetTitle() ); + copyFileLayout( destination_dir, source ); + } + } // loop over keys + return; +} + +size_t THistSvcHLT::findHistID( const std::string& id, const THistID*& hid, const size_t& index ) const +{ + GlobalDirectoryRestore restore( m_svcMut ); + + std::string idr( id ); + removeDoubleSlash( idr ); + + hid = 0; + + if ( idr.find( "/" ) == 0 ) { + // fully specified name, starts with "/" + auto itr = m_uids.find( idr ); + if ( itr == m_uids.end() ) { + // no matches found + return 0; + } else { + // one or more matches found (clones). + if ( index >= itr->second->size() ) { + error() << "no index " << index << " found for Hist " << idr << endmsg; + return 0; + } + hid = &( itr->second->at( index ) ); + return 1; + } + } else { + // name not fully specified. + auto mitr = m_ids.equal_range( idr ); + if ( mitr.first == mitr.second ) { + // not found + return 0; + } else if ( distance( mitr.first, mitr.second ) == 1 ) { + // one found + if ( index >= mitr.first->second->size() ) { + error() << "no index " << index << " found for Hist " << idr << endmsg; + return 0; + } + hid = &( mitr.first->second->at( 0 ) ); + return 1; + } else { + // multiple matches + hid = &( mitr.first->second->at( 0 ) ); + return distance( mitr.first, mitr.second ); + } + } +} + +void THistSvcHLT::dump() const +{ + std::ostringstream ost; + + // list< vector<THistID> > + ost << "m_hlist: size: " << m_hlist.size() << "\n"; + for ( auto& vh : m_hlist ) { + ost << " - " << vh->at( 0 ) << " :: [" << vh << "] " << vh->size() << " {"; + for ( auto& e : *vh ) { + TObject* o = e.obj; + ost << "[" << o << "]"; + } + ost << "}\n"; + } + + // map uid -> vector<THistID>* + ost << "\n" + << "m_uids: " << m_uids.size() << "\n"; + for ( auto& e : m_uids ) { + ost << " - " << e.first << " [" << e.second << "]" << std::endl; + } + + // multimap id -> vector<THistID>* + ost << "\n" + << "m_ids: " << m_ids.size() << "\n"; + for ( auto& e : m_ids ) { + ost << " - " << e.first << " [" << e.second << "]" << std::endl; + } + + // map TObject* -> THistID* + ost << "\n" + << "m_tobjs: " << m_tobjs.size() << "\n"; + for ( auto& e : m_tobjs ) { + TObject* o = e.first; + THistID& i = e.second.first->at( e.second.second ); + ost << " - " << o << " -> " << i << std::endl; + } + + debug() << "dumping THistSvcHLT contents\n" << ost.str() << endmsg; +} + +StatusCode THistSvcHLT::merge( const THistID& hid ) { return merge( hid.id ); } + +StatusCode THistSvcHLT::merge( vhid_t* vh ) +{ + const std::string& name = vh->at( 0 ).id; + if ( vh->size() == 1 ) { + debug() << "merge: id: \"" << name << "\" is size 1. nothing to do" << endmsg; + return StatusCode::SUCCESS; + } + + if ( !vh->at( 0 ).obj->IsA()->InheritsFrom( "TH1" ) ) { + error() << "merge: id \"" << name << "\" is not a THn. Cannot merge" << endmsg; + return StatusCode::FAILURE; + } + + TList* l = new TList(); + for ( size_t i = 1; i < vh->size(); ++i ) { + debug() << "merge: id: \"" << name << "\" (" << vh->at( i ).obj << ") adding index " << i << endmsg; + l->Add( vh->at( i ).obj ); + } + + TH1* t0 = dynamic_cast<TH1*>( vh->at( 0 ).obj ); + if ( t0 == 0 ) { + error() << "merge: could not dcast " << name << "(" << t0 << ") index " << 0 << " to TH1" << endmsg; + return StatusCode::FAILURE; + } + + Long64_t n = t0->Merge( l ); + + debug() << "merge: id: \"" << name << "\" merged " << n << " entries" << endmsg; + + for ( size_t i = 1; i < vh->size(); ++i ) { + TH1* th = dynamic_cast<TH1*>( vh->at( i ).obj ); + if ( th != 0 ) { + debug() << "clearing index " << i << "(" << th << ")" << endmsg; + th->SetDirectory( nullptr ); + th->Reset(); + } else { + error() << "merge: could not dcast " << name << " index " << i << " to TH1" << endmsg; + return StatusCode::FAILURE; + } + } + return StatusCode::SUCCESS; +} + +StatusCode THistSvcHLT::rootOpenAction( const Io::FileAttr* fa, const std::string& caller ) +{ + if ( fa->tech() != Io::ROOT ) { + // This should never happen + return StatusCode::SUCCESS; + } + + if ( fa->desc() != "HIST" ) { + return StatusCode::SUCCESS; + } + + p_incSvc->fireIncident( FileIncident( caller, "OpenHistFile", fa->name() ) ); + + if ( fa->flags().isRead() ) { + p_incSvc->fireIncident( FileIncident( caller, "BeginHistFile", fa->name() ) ); + } else if ( fa->flags().isWrite() ) { + p_incSvc->fireIncident( FileIncident( caller, IncidentType::BeginOutputFile, fa->name() ) ); + } else { + // for Io::RW + p_incSvc->fireIncident( FileIncident( caller, IncidentType::BeginOutputFile, fa->name() ) ); + } + + return StatusCode::SUCCESS; +} + +StatusCode THistSvcHLT::rootOpenErrAction( const Io::FileAttr* fa, const std::string& caller ) +{ + if ( fa->tech() != Io::ROOT ) { + // This should never happen + return StatusCode::SUCCESS; + } + + if ( fa->desc() != "HIST" ) { + return StatusCode::SUCCESS; + } + + if ( fa->flags().isRead() ) { + p_incSvc->fireIncident( FileIncident( caller, IncidentType::FailInputFile, fa->name() ) ); + } else if ( fa->flags().isWrite() ) { + p_incSvc->fireIncident( FileIncident( caller, IncidentType::FailOutputFile, fa->name() ) ); + } else { + // for Io::RW + p_incSvc->fireIncident( FileIncident( caller, "FailRWFile", fa->name() ) ); + } + + return StatusCode::SUCCESS; +} diff --git a/HLT/Trigger/TrigControl/TrigServices/src/THistSvcHLT.cxx.bak b/HLT/Trigger/TrigControl/TrigServices/src/THistSvcHLT.cxx.bak deleted file mode 100644 index eafaf3e89009bca51cf5e2cd582dffa87ce68357..0000000000000000000000000000000000000000 --- a/HLT/Trigger/TrigControl/TrigServices/src/THistSvcHLT.cxx.bak +++ /dev/null @@ -1,2087 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -#ifdef __ICC -// disable icc remark #2259: non-pointer conversion from "X" to "Y" may lose significant bits -// TODO: To be removed, since it comes from ROOT TMathBase.h -#pragma warning(disable:2259) -#endif - -#include "THistSvcHLT.h" - -#include "GaudiKernel/ISvcLocator.h" -#include "GaudiKernel/AttribStringParser.h" -#include "GaudiKernel/GaudiException.h" -#include "GaudiKernel/Property.h" -#include "GaudiKernel/IIncidentSvc.h" -#include "GaudiKernel/FileIncident.h" -#include "GaudiKernel/IEventProcessor.h" -#include "GaudiKernel/IJobOptionsSvc.h" -#include "GaudiKernel/IIoComponentMgr.h" -#include "GaudiKernel/IFileMgr.h" -#include "boost/algorithm/string/case_conv.hpp" - -#include "TROOT.h" -#include "TFile.h" -#include "TDirectory.h" -#include "TKey.h" -#include "TError.h" -#include "TGraph.h" - -#include <sstream> -#include <streambuf> -#include <cstdio> - -using namespace std; - - -DECLARE_COMPONENT(THistSvcHLT) - -namespace { - -template <typename InputIterator, typename OutputIterator, typename UnaryOperation, typename UnaryPredicate> -OutputIterator transform_if( InputIterator first, InputIterator last, - OutputIterator result, - UnaryOperation op, - UnaryPredicate pred) { - while (first != last) { - if (pred(*first)) *result++ = op(*first); - ++first; - } - return result; -} - -constexpr struct select1st_t { - template <typename T, typename S> - const T& operator()(const std::pair<T,S>& p) const { return p.first; } -} select1st {} ; - - -} - - -//*************************************************************************// - -THistSvcHLT::THistSvcHLT( const std::string& name, ISvcLocator* svc ) - : base_class(name, svc), m_log(msgSvc(), name ) -{ - declareProperty ("AutoSave", m_autoSave=0 ); - declareProperty ("AutoFlush", m_autoFlush=0 ); - declareProperty ("PrintAll", m_print=false); - declareProperty ("MaxFileSize", m_maxFileSize=10240, - "maximum file size in MB. if exceeded, will cause an abort. -1 to never check."); - declareProperty ("CompressionLevel", m_compressionLevel=1 )->declareUpdateHandler( &THistSvcHLT::setupCompressionLevel, this ); - declareProperty ("Output", m_outputfile )->declareUpdateHandler( &THistSvcHLT::setupOutputFile, this ); - declareProperty ("Input", m_inputfile )->declareUpdateHandler ( &THistSvcHLT::setupInputFile, this ); -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::initialize() { - GlobalDirectoryRestore restore; - - // Super ugly hack to make sure we have the OutputLevel set first, so we - // can see DEBUG printouts in update handlers. - auto jos = serviceLocator()->service<IJobOptionsSvc>( "JobOptionsSvc", true ); - if( jos ) { - const auto props = jos->getProperties( name() ); - - if ( props ) { - auto i = std::find_if(std::begin(*props),std::end(*props), - [](const Property* p) { return p->name() == "OutputLevel"; } ); - if ( i != std::end(*props)) { - setProperty( **i ).ignore(); - m_log.setLevel( m_outputLevel.value() ); - } - } - } - - - StatusCode status = Service::initialize(); - m_log.setLevel( m_outputLevel.value() ); - - if (status.isFailure()) { - m_log << MSG::ERROR << "initializing service" << endmsg; - return status; - } - - StatusCode st(StatusCode::SUCCESS); - - try { - setupOutputFile( m_outputfile ); - } catch ( GaudiException& err ) { - m_log << MSG::ERROR - << "Caught: " << err << endmsg; - st = StatusCode::FAILURE; - } - - try { - setupInputFile( m_inputfile ); - } catch ( GaudiException& err ) { - m_log << MSG::ERROR - << "Caught: " << err << endmsg; - st = StatusCode::FAILURE; - } - - // Protect against multiple instances of TROOT - if ( !gROOT ) { - static TROOT root("root","ROOT I/O"); - // gDebug = 99; - } else { - if (m_log.level() <= MSG::VERBOSE) - m_log << MSG::VERBOSE << "ROOT already initialized, debug = " - << gDebug<< endmsg; - } - - if (service("IncidentSvc", p_incSvc, true).isFailure()) { - m_log << MSG::ERROR << "unable to get the IncidentSvc" << endmsg; - st = StatusCode::FAILURE; - } else { - p_incSvc->addListener( this, "EndEvent", 100, true); - } - - if (service("FileMgr",p_fileMgr,true).isFailure()) { - m_log << MSG::ERROR << "unable to get the FileMgr" << endmsg; - st = StatusCode::FAILURE; - } else { - m_log << MSG::DEBUG << "got the FileMgr" << endmsg; - } - - - // Register open/close callback actions - - using namespace std::placeholders; - auto boa = [this](const Io::FileAttr* fa, const std::string& caller) { return this->rootOpenAction(fa,caller); }; - if (p_fileMgr->regAction(boa, Io::OPEN, Io::ROOT).isFailure()) { - m_log << MSG::ERROR - << "unable to register ROOT file open action with FileMgr" - << endmsg; - } - auto bea = [this](const Io::FileAttr* fa, const std::string& caller) { return this->rootOpenErrAction(fa,caller); }; - if (p_fileMgr->regAction(bea, Io::OPEN_ERR, Io::ROOT).isFailure()) { - m_log << MSG::ERROR - << "unable to register ROOT file open Error action with FileMgr" - << endmsg; - } - - - m_okToConnect = true; - - if (m_delayConnect) { - if (!m_inputfile.value().empty()) { setupInputFile(m_inputfile); } - if (!m_outputfile.value().empty()) { setupOutputFile(m_outputfile); } - - m_delayConnect = false; - - } - m_alreadyConnectedOutFiles.clear(); - m_alreadyConnectedInFiles.clear(); - - - IIoComponentMgr* iomgr = nullptr; - - if (service("IoComponentMgr", iomgr, true).isFailure()) { - m_log << MSG::ERROR << "unable to get the IoComponentMgr" << endmsg; - st = StatusCode::FAILURE; - } else { - - if ( !iomgr->io_register (this).isSuccess() ) { - m_log << MSG::ERROR - << "could not register with the I/O component manager !" - << endmsg; - st = StatusCode::FAILURE; - } else { - bool all_good = true; - // register input/output files... - for ( const auto& reg : m_files ) { - const std::string& fname = reg.second.first->GetName(); - const IIoComponentMgr::IoMode::Type iomode = - ( reg.second.second==THistSvcHLT::READ - ? IIoComponentMgr::IoMode::READ - : IIoComponentMgr::IoMode::WRITE ); - if ( !iomgr->io_register (this, iomode, fname).isSuccess () ) { - m_log << MSG::WARNING << "could not register file [" - << fname << "] with the I/O component manager..." << endmsg; - all_good = false; - } else { - m_log << MSG::INFO << "registered file [" << fname << "]... [ok]" - << endmsg; - } - } - if (!all_good) { - m_log << MSG::ERROR - << "problem while registering input/output files with " - << "the I/O component manager !" << endmsg; - st = StatusCode::FAILURE; - } - } - - } - - if (st.isFailure()) { - m_log << MSG::FATAL << "Unable to initialize THistSvcHLT" << endmsg; - } - - return st; - -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::reinitialize() { - - GlobalDirectoryRestore restore; - m_log << MSG::WARNING << "reinitialize not implemented" << endmsg; - return StatusCode::SUCCESS; - -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::finalize() { - - GlobalDirectoryRestore restore; - - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "THistSvcHLT::finalize" << endmsg; - -#ifndef NDEBUG - if (m_log.level() <= MSG::DEBUG) { - for (const auto& uid : m_uids ) { - - TObject* to = uid.second.obj; - - string dirname("none"); - if (to && to->IsA()->InheritsFrom("TTree")) { - TTree* tr = dynamic_cast<TTree*>(to); - if (tr->GetDirectory() != 0) { - dirname = tr->GetDirectory()->GetPath(); - } - } else if (to && to->IsA()->InheritsFrom("TGraph")) { - if (!uid.second.temp) { - dirname = uid.second.file->GetPath(); - string id2(uid.second.id); - id2.erase(0,id2.find("/",1)); - id2.erase(id2.rfind("/"), id2.length()); - if (id2.find("/") == 0) { - id2.erase(0,1); - } - dirname += id2; - } else { - dirname = "/tmp"; - } - } else if (to && to->IsA()->InheritsFrom("TH1")) { - TH1* th = dynamic_cast<TH1*>(to); - if (th == 0) { - m_log << MSG::ERROR << "Couldn't dcast: " << uid.first << endmsg; - } else { - if (th->GetDirectory() != 0) { - dirname = th->GetDirectory()->GetPath(); - } - } - } else if (! to ) { - m_log << MSG::WARNING << uid.first << " has NULL TObject ptr" - << endmsg; - } - - m_log << MSG::DEBUG << "uid: \"" << uid.first << "\" temp: " - << uid.second.temp << " dir: " << dirname - << endmsg; - } - } -#endif - - StatusCode sc = write(); - if (sc.isFailure()) { - m_log << MSG::ERROR << "problems writing histograms" << endmsg; - } - - if (m_print) { - m_log << MSG::INFO << "Listing contents of ROOT files: " << endmsg; - } - vector<TFile*> deleted_files; - for (auto& itr : m_files ) { - - if (find(deleted_files.begin(), deleted_files.end(), itr.second.first) == - deleted_files.end()) { - deleted_files.push_back(itr.second.first); - -#ifndef NDEBUG - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "finalizing stream/file " << itr.first << ":" - << itr.second.first->GetName() - << endmsg; -#endif - } else { -#ifndef NDEBUG - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "already finalized stream " << itr.first << endmsg; -#endif - continue; - } - - - if (m_print && m_log.level() <= MSG::INFO) { - - m_log << MSG::INFO; - m_log << "==> File: " << itr.second.first->GetName() - << " stream: " << itr.first << endmsg; - - itr.second.first->Print("base"); - } - - string tmpfn=itr.second.first->GetName(); - - p_fileMgr->close(itr.second.first, name()); - - IIncidentSvc *pi = nullptr; - if (service("IncidentSvc",pi).isFailure()) { - m_log << MSG::ERROR << "Unable to get the IncidentSvc" << endmsg; - return StatusCode::FAILURE; - } - - if (itr.second.second==SHARE) { - - //Merge File - void* vf = nullptr; - int r = p_fileMgr->open(Io::ROOT,name(), m_sharedFiles[itr.first], - Io::WRITE|Io::APPEND,vf,"HIST"); - - if (r) { - m_log << MSG::ERROR << "unable to open Final Output File: \"" - << m_sharedFiles[itr.first] << "\" for merging" - << endmsg; - return StatusCode::FAILURE; - } - - TFile *outputfile = (TFile*) vf; - pi->fireIncident(FileIncident(name(), IncidentType::WroteToOutputFile, - m_sharedFiles[itr.first])); - - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "THistSvcHLT::write()::Merging Rootfile "<<endmsg; - - vf = nullptr; - r = p_fileMgr->open(Io::ROOT,name(),tmpfn,Io::READ,vf,"HIST"); - - if (r) { - m_log << MSG::ERROR << "unable to open temporary file: \"" - << tmpfn << endmsg; - return StatusCode::FAILURE; - } - - TFile *inputfile = (TFile*) vf; - - outputfile->SetCompressionLevel( inputfile->GetCompressionLevel() ); - - MergeRootFile(outputfile, inputfile); - - outputfile->Write(); - p_fileMgr->close(outputfile,name()); - p_fileMgr->close(inputfile,name()); - - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "Trying to remove temporary file \"" << tmpfn - << "\""<<endmsg; - - std::remove(tmpfn.c_str()); - } - delete itr.second.first; - } - - m_sharedFiles.clear(); - m_fileStreams.clear(); - m_files.clear(); - m_uids.clear(); - m_ids.clear(); - m_tobjs.clear(); - - return Service::finalize(); -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -bool -THistSvcHLT::browseTDir(TDirectory *dir) const { - - if (!dir) { - std::cerr << "TDirectory == 0" << std::endl; - return false; - } - - GlobalDirectoryRestore restore; - - dir->cd(); - - - cout << "-> " << dir->GetPath() << " " - << dir->GetListOfKeys()->GetSize() << endl; - - // TIter nextkey(dir->GetListOfKeys()); - TIter nextkey(dir->GetList()); - while (TKey *key = (TKey*)nextkey()) { - - TObject *obj = key->ReadObj(); - if (!obj) { cout << key->GetName() << " obj==0"<< endl; continue; } - // if (obj->IsA()->InheritsFrom("TDirectory")) { - cout << " Key: " << key->GetName() << " " - << " tit: " << obj->GetTitle() << " " - << " (" << key->GetClassName() << ")" << endl; - // } - } - - nextkey = dir->GetListOfKeys(); - while (TKey *key = (TKey*)nextkey()) { - - TObject *obj = key->ReadObj(); - if (!obj) { cout << key->GetName() << " obj==0"<< endl; continue; } - if (obj->IsA()->InheritsFrom("TDirectory")) { - TDirectory *tt = dynamic_cast<TDirectory*>(obj); - browseTDir(tt); - } - } - - return true; -} - - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::getTHists(TDirectory *td, TList & tl, bool rcs) const { - GlobalDirectoryRestore restore; - - gErrorIgnoreLevel = kBreak; - - if (!td->cd()) { - m_log << MSG::ERROR << "getTHists: No such TDirectory \"" << td->GetPath() - << "\"" << endmsg; - return StatusCode::FAILURE; - } - - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "getTHists: \"" << td->GetPath() << "\": found " - << td->GetListOfKeys()->GetSize() << " keys" << endmsg; - - TIter nextkey(td->GetListOfKeys()); - while (TKey *key = (TKey*)nextkey()) { - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << " key: " << key->GetName(); - TObject *obj = key->ReadObj(); - if (obj != 0 && obj->IsA()->InheritsFrom("TDirectory")) { - if (m_log.level() <= MSG::DEBUG) - m_log << " (" << obj->IsA()->GetName() << ")"; - } else if (obj != 0 && obj->IsA()->InheritsFrom("TH1")) { - if (m_log.level() <= MSG::DEBUG) - m_log << " (" << obj->IsA()->GetName() << ")"; - tl.Add(obj); - } else if (obj != 0) { - if (m_log.level() <= MSG::DEBUG) - m_log << " [" << obj->IsA()->GetName() << "]"; - } - if (m_log.level() <= MSG::DEBUG) - m_log << endmsg; - } - - // operate recursively - if (rcs) { - nextkey = td->GetListOfKeys(); - while (TKey *key = (TKey*)nextkey()) { - TObject *obj = key->ReadObj(); - if (obj && obj->IsA()->InheritsFrom("TDirectory")) { - TDirectory *tt = dynamic_cast<TDirectory*>(obj); - getTHists(tt, tl, rcs); - } - } - } - - return StatusCode::SUCCESS; - - -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::getTHists(const std::string& dir, TList & tl, bool rcs) const { - - GlobalDirectoryRestore restore; - - gErrorIgnoreLevel = kBreak; - - StatusCode sc; - - std::string stream,rem,r2; - parseString(dir,stream,rem); - - auto itr = m_files.find(stream); - if (itr != m_files.end()) { - r2 = itr->second.first->GetName(); - r2 += ":/"; - r2 += rem; - - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "getTHists: \"" << dir - << "\" looks like a stream name." << " associated TFile: \"" - << itr->second.first->GetName() << "\"" << endmsg; - - if (gDirectory->cd(r2.c_str())) { - m_curstream = stream; - sc = getTHists(gDirectory,tl,rcs); - m_curstream = ""; - return sc; - } else { - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "getTHists: no such TDirectory \"" - << r2 << "\"" << endmsg; - } - - } else { - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "getTHists: stream \"" << stream << "\" not found" - << endmsg; - } - - if (!gDirectory->cd(dir.c_str())) { - m_log << MSG::ERROR << "getTHists: No such TDirectory/stream \"" << dir - << "\"" << endmsg; - sc = StatusCode::FAILURE; - } else { - sc = getTHists(gDirectory,tl,rcs); - } - - return sc; - -} -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::getTTrees(TDirectory *td, TList & tl, bool rcs) const { - GlobalDirectoryRestore restore; - - gErrorIgnoreLevel = kBreak; - - if (!td->cd()) { - m_log << MSG::ERROR << "getTTrees: No such TDirectory \"" - << td->GetPath() << "\"" << endmsg; - return StatusCode::FAILURE; - } - - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "getTHists: \"" << td->GetPath() << "\": found " - << td->GetListOfKeys()->GetSize() << " keys" << endmsg; - - TIter nextkey(td->GetListOfKeys()); - while (TKey *key = (TKey*)nextkey()) { - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << " key: " << key->GetName(); - TObject *obj = key->ReadObj(); - if (obj != 0 && obj->IsA()->InheritsFrom("TDirectory")) { - if (m_log.level() <= MSG::DEBUG) - m_log << " (" << obj->IsA()->GetName() << ")"; - } else if (obj != 0 && obj->IsA()->InheritsFrom("TTree")) { - if (m_log.level() <= MSG::DEBUG) - m_log << " (" << obj->IsA()->GetName() << ")"; - tl.Add(obj); - } else if (obj != 0) { - if (m_log.level() <= MSG::DEBUG) - m_log << " [" << obj->IsA()->GetName() << "]"; - } - m_log << endmsg; - } - - // operate recursively - if (rcs) { - nextkey = td->GetListOfKeys(); - while (TKey *key = (TKey*)nextkey()) { - TObject *obj = key->ReadObj(); - if (obj && obj->IsA()->InheritsFrom("TDirectory")) { - TDirectory *tt = dynamic_cast<TDirectory*>(obj); - getTTrees(tt, tl, rcs); - } - } - } - - return StatusCode::SUCCESS; - -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::getTTrees(const std::string& dir, TList & tl, bool rcs) const { - GlobalDirectoryRestore restore; - - gErrorIgnoreLevel = kBreak; - - StatusCode sc; - - std::string stream,rem,r2; - parseString(dir,stream,rem); - - auto itr = m_files.find(stream); - if (itr != m_files.end()) { - r2 = itr->second.first->GetName(); - r2 += ":/"; - r2 += rem; - - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "getTTrees: \"" << dir - << "\" looks like a stream name." << " associated TFile: \"" - << itr->second.first->GetName() << "\"" << endmsg; - - if (gDirectory->cd(r2.c_str())) { - return getTTrees(gDirectory,tl,rcs); - } - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "getTTrees: no such TDirectory \"" - << r2 << "\"" << endmsg; - } else { - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "getTTrees: stream \"" << stream << "\" not found" - << endmsg; - } - - if (!gDirectory->cd(dir.c_str())) { - m_log << MSG::ERROR << "getTTrees: No such TDirectory/stream \"" << dir - << "\"" << endmsg; - sc = StatusCode::FAILURE; - } else { - sc = getTTrees(gDirectory,tl,rcs); - } - return sc; -} - - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::getTHists(TDirectory *td, TList & tl, bool rcs, bool reg) { - - GlobalDirectoryRestore restore; - - gErrorIgnoreLevel = kBreak; - - if (!td->cd()) { - m_log << MSG::ERROR << "getTHists: No such TDirectory \"" << td->GetPath() - << "\"" << endmsg; - return StatusCode::FAILURE; - } - - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "getTHists: \"" << td->GetPath() << "\": found " - << td->GetListOfKeys()->GetSize() << " keys" << endmsg; - - TIter nextkey(td->GetListOfKeys()); - while (TKey *key = (TKey*)nextkey()) { - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << " key: " << key->GetName(); - TObject *obj = key->ReadObj(); - if (obj && obj->IsA()->InheritsFrom("TDirectory")) { - if (m_log.level() <= MSG::DEBUG) - m_log << " (" << obj->IsA()->GetName() << ")"; - } else if (obj && obj->IsA()->InheritsFrom("TH1")) { - if (m_log.level() <= MSG::DEBUG) - m_log << " (" << obj->IsA()->GetName() << ")"; - tl.Add(obj); - if (reg && m_curstream != "") { - string dir = td->GetPath(); - string fil = td->GetFile()->GetName(); - dir.erase(0,fil.length()+1); - string id = "/" + m_curstream; - if ( dir == "/" ) { - id = id + "/" + key->GetName(); - } else { - id = id + dir + "/" + key->GetName(); - } - if (!exists(id)) { - if (m_log.level() <= MSG::DEBUG) - m_log << " reg as \"" << id << "\""; - regHist(id).ignore(); - } else { - if (m_log.level() <= MSG::DEBUG) - m_log << " already registered"; - } - } - } else if (obj) { - if (m_log.level() <= MSG::DEBUG) - m_log << " [" << obj->IsA()->GetName() << "]"; - } - if (m_log.level() <= MSG::DEBUG) - m_log << endmsg; - } - - // operate recursively - if (rcs) { - nextkey = td->GetListOfKeys(); - while (TKey *key = (TKey*)nextkey()) { - TObject *obj = key->ReadObj(); - if (obj && obj->IsA()->InheritsFrom("TDirectory")) { - TDirectory *tt = dynamic_cast<TDirectory*>(obj); - getTHists(tt, tl, rcs, reg); - } - } - } - - return StatusCode::SUCCESS; - -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::getTHists(const std::string& dir, TList & tl, bool rcs, bool reg) { - - GlobalDirectoryRestore restore; - - gErrorIgnoreLevel = kBreak; - - StatusCode sc; - - std::string stream,rem,r2; - parseString(dir,stream,rem); - - auto itr = m_files.find(stream); - if (itr != m_files.end()) { - r2 = itr->second.first->GetName(); - r2 += ":/"; - r2 += rem; - - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "getTHists: \"" << dir - << "\" looks like a stream name." << " associated TFile: \"" - << itr->second.first->GetName() << "\"" << endmsg; - - if (gDirectory->cd(r2.c_str())) { - m_curstream = stream; - sc = getTHists(gDirectory,tl,rcs,reg); - m_curstream.clear(); - return sc; - } - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "getTHists: no such TDirectory \"" - << r2 << "\"" << endmsg; - - } else { - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "getTHists: stream \"" << stream << "\" not found" - << endmsg; - } - - if (!gDirectory->cd(dir.c_str())) { - m_log << MSG::ERROR << "getTHists: No such TDirectory/stream \"" << dir - << "\"" << endmsg; - sc = StatusCode::FAILURE; - } else { - if (reg) { - m_log << MSG::WARNING << "Unable to register histograms automatically " - << "without a valid stream name" << endmsg; - reg = false; - } - sc = getTHists(gDirectory,tl,rcs,reg); - } - - return sc; - -} -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::getTTrees(TDirectory *td, TList & tl, bool rcs, bool reg) { - - GlobalDirectoryRestore restore; - - gErrorIgnoreLevel = kBreak; - - if (!td->cd()) { - m_log << MSG::ERROR << "getTTrees: No such TDirectory \"" - << td->GetPath() << "\"" << endmsg; - return StatusCode::FAILURE; - } - - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "getTHists: \"" << td->GetPath() << "\": found " - << td->GetListOfKeys()->GetSize() << " keys" << endmsg; - - TIter nextkey(td->GetListOfKeys()); - while (TKey *key = (TKey*)nextkey()) { - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << " key: " << key->GetName(); - TObject *obj = key->ReadObj(); - if (obj && obj->IsA()->InheritsFrom("TDirectory")) { - if (m_log.level() <= MSG::DEBUG) - m_log << " (" << obj->IsA()->GetName() << ")"; - } else if (obj && obj->IsA()->InheritsFrom("TTree")) { - if (m_log.level() <= MSG::DEBUG) - m_log << " (" << obj->IsA()->GetName() << ")"; - tl.Add(obj); - if (reg && m_curstream != "") { - string dir = td->GetPath(); - string fil = td->GetFile()->GetName(); - dir.erase(0,fil.length()+1); - string id = "/" + m_curstream; - if ( dir == "/" ) { - id = id + "/" + key->GetName(); - } else { - id = id + dir + "/" + key->GetName(); - } - if (!exists(id)) { - if (m_log.level() <= MSG::DEBUG) - m_log << " reg as \"" << id << "\""; - regHist(id).ignore(); - } else { - if (m_log.level() <= MSG::DEBUG) - m_log << " already registered"; - } - } - } else if (obj != 0) { - if (m_log.level() <= MSG::DEBUG) - m_log << " [" << obj->IsA()->GetName() << "]"; - } - if (m_log.level() <= MSG::DEBUG) - m_log << endmsg; - } - - // operate recursively - if (rcs) { - nextkey = td->GetListOfKeys(); - while (TKey *key = (TKey*)nextkey()) { - TObject *obj = key->ReadObj(); - if (obj && obj->IsA()->InheritsFrom("TDirectory")) { - TDirectory *tt = dynamic_cast<TDirectory*>(obj); - getTTrees(tt, tl, rcs, reg); - } - } - } - - return StatusCode::SUCCESS; - -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::getTTrees(const std::string& dir, TList & tl, bool rcs, bool reg) { - - GlobalDirectoryRestore restore; - - gErrorIgnoreLevel = kBreak; - - StatusCode sc; - - std::string stream,rem,r2; - parseString(dir,stream,rem); - - auto itr = m_files.find(stream); - if (itr != m_files.end()) { - r2 = itr->second.first->GetName(); - r2 += ":/"; - r2 += rem; - - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "getTTrees: \"" << dir - << "\" looks like a stream name." << " associated TFile: \"" - << itr->second.first->GetName() << "\"" << endmsg; - - if (gDirectory->cd(r2.c_str())) { - return getTTrees(gDirectory,tl,rcs,reg); - } else { - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "getTTrees: no such TDirectory \"" - << r2 << "\"" << endmsg; - } - - } else { - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "getTTrees: stream \"" << stream << "\" not found" - << endmsg; - } - - if (!gDirectory->cd(dir.c_str())) { - m_log << MSG::ERROR << "getTTrees: No such TDirectory/stream \"" << dir - << "\"" << endmsg; - return StatusCode::FAILURE; - } - - return getTTrees(gDirectory,tl,rcs,reg); - -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::deReg(TObject* obj) { - - auto itr = m_tobjs.find(obj); - if (itr != m_tobjs.end()) { - THistID hid = itr->second; - - auto itr2 = m_uids.find(hid.id); - if (itr2 == m_uids.end()) { - m_log << MSG::ERROR << "Problems deregistering TObject \"" - << obj->GetName() - << "\" with id \"" << hid.id << "\"" << endmsg; - return StatusCode::FAILURE; - } - - std::string id,root,rem; - parseString(hid.id, root, rem); - - auto mitr = m_ids.equal_range(rem); - auto itr3 = std::find_if( mitr.first, mitr.second, [&](idMap::const_reference i) - { return i.second.obj == obj; } ) ; - if (itr3 != mitr.second ) { - m_log << MSG::ERROR << "Problems deregistering TObject \"" - << obj->GetName() - << "\" with id \"" << hid.id << "\"" << endmsg; - return StatusCode::FAILURE; - } - - m_tobjs.erase(itr); - m_uids.erase(itr2); - m_ids.erase(itr3); - - return StatusCode::SUCCESS; - - } else { - m_log << MSG::ERROR << "Cannot unregister TObject \"" << obj->GetName() - << "\": not known to THistSvcHLT" << endmsg; - return StatusCode::FAILURE; - } - -} - - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::deReg(const std::string& id) { - - auto itr = m_uids.find(id); - if (itr == m_uids.end()) { - m_log << MSG::ERROR << "Problems deregistering id \"" - << id << "\"" << endmsg; - return StatusCode::FAILURE; - } - - TObject* obj = itr->second.obj; - return deReg(obj); -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::regHist(const std::string& id) { - - TH1 *hist = nullptr; - return regHist_i(hist, id); -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::regHist(const std::string& id, TH1* hist) { - return regHist_i(hist, id); -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::regHist(const std::string& id, TH2* hist) { - return regHist_i(hist, id); -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::regHist(const std::string& id, TH3* hist) { - return regHist_i(hist, id); -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::regTree(const std::string& id) { - TTree *hist = nullptr; - return regHist_i(hist, id); -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::regTree(const std::string& id, TTree* hist) { - StatusCode sc = regHist_i(hist, id); - if (hist && sc.isSuccess()) { - if (m_autoSave != 0) hist->SetAutoSave(m_autoSave); - hist->SetAutoFlush(m_autoFlush); - } - return sc; -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::regGraph(const std::string& id) { - TGraph *hist = nullptr; - return regHist_i(hist, id); -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::regGraph(const std::string& id, TGraph* hist) { - if ( strcmp(hist->GetName(),"Graph") == 0 ) { - - std::string id2(id); - string::size_type i = id2.rfind("/"); - if (i != string::npos) { - id2.erase(0,i+1); - } - - m_log << MSG::INFO << "setting name of TGraph id: \"" << id << "\" to \"" - << id2 << "\" since it is unset" << endmsg; - hist->SetName(id2.c_str()); - } - - return regHist_i(hist, id); -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::getHist(const std::string& id, TH1*& hist) const { - return getHist_i(id, hist); -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::getHist(const std::string& id, TH2*& hist) const { - return getHist_i(id, hist); -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::getHist(const std::string& id, TH3*& hist) const { - return getHist_i(id, hist); -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -std::vector<std::string> -THistSvcHLT::getHists() const { - - std::vector<std::string> names; - names.reserve(m_uids.size()); - transform_if( std::begin(m_uids), std::end(m_uids), - std::back_inserter(names), select1st, - [](uidMap::const_reference i) { - return i.second.obj->IsA()->InheritsFrom("TH11"); } - ); - return names; - -} -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::getTree(const std::string& id, TTree*& hist) const { - return getHist_i(id, hist); -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -std::vector<std::string> -THistSvcHLT::getTrees() const { - - std::vector<std::string> names; - names.reserve(m_uids.size()); - transform_if( std::begin(m_uids), std::end(m_uids), - std::back_inserter(names), - select1st, - [](uidMap::const_reference i) { - return i.second.obj->IsA()->InheritsFrom("TTree"); } - ); - return names; - -} -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::getGraph(const std::string& id, TGraph*& hist) const { - return getHist_i(id, hist); -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -std::vector<std::string> -THistSvcHLT::getGraphs() const { - - std::vector<std::string> names; - names.reserve(m_uids.size()); - transform_if( std::begin(m_uids), std::end(m_uids), - std::back_inserter(names), select1st, - [](uidMap::const_reference i) { - return i.second.obj->IsA()->InheritsFrom("TTree"); } - ); - return names; - -} -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::readHist(const std::string& id, TH1*& hist) const { - return readHist_i(id, hist); -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::readHist(const std::string& id, TH2*& hist) const { - return readHist_i(id, hist); -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::readHist(const std::string& id, TH3*& hist) const { - return readHist_i(id, hist); -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::readTree(const std::string& id, TTree*& hist) const { - return readHist_i(id, hist); -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -bool -THistSvcHLT::findStream(const string& id, string& stream, string& rem, - TFile*& file) const { - - auto pos = id.find("/"); - - if (pos == string::npos) { - stream = "temp"; - rem = id; - } else if (pos != 0) { - stream = "temp"; - rem = id; - } else { - - auto pos2 = id.find("/",pos+1); - - if (pos2 == string::npos) { - m_log << MSG::ERROR << "badly formed Hist/Tree id: \"" << id << "\"" - << endmsg; - return false; - } - - parseString(id,stream,rem); - - } - - if (stream == "temp") { - file = nullptr; - return true; - } - - auto itr = m_files.find(stream); - file = (itr != m_files.end() ? itr->second.first : nullptr ); - if (!file) { - m_log << MSG::WARNING << "no stream \"" << stream - << "\" associated with id: \"" << id << "\"" - << endmsg; - } - - return true; -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -void -THistSvcHLT::parseString(const string& id, string& root, string& rem) const { - auto pos = id.find("/"); - - if (pos == string::npos) { - root.clear(); - rem = id; - } else if (pos == 0) { - parseString(id.substr(1),root,rem); - } else { - root = id.substr(0,pos); - rem = id.substr(pos+1); - } - -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -void -THistSvcHLT::setupCompressionLevel( Property& /* cl */ ) -{ - - m_log << MSG::WARNING << "\"CompressionLevel\" Property has been deprecated. " - << "Set it via the \"CL=\" parameter in the \"Output\" Property" - << endmsg; - -} - - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -void -THistSvcHLT::setupInputFile( Property& /*m_inputfile*/ ) -{ - - if (FSMState() < Gaudi::StateMachine::CONFIGURED || !m_okToConnect ) { - - m_log <<MSG::DEBUG << "Delaying connection of Input Files until Initialize" - << ". now in " << FSMState() - << endmsg; - - m_delayConnect = true; - } else { - - m_log <<MSG::DEBUG << "Now connecting of Input Files" - << endmsg; - - StatusCode sc = StatusCode::SUCCESS; - - for ( const auto& itr : m_inputfile.value() ) { - if ( m_alreadyConnectedInFiles.end() != - m_alreadyConnectedInFiles.find( itr ) ) continue; - if ( connect(itr).isFailure() ) { - sc = StatusCode::FAILURE; - } else { - m_alreadyConnectedInFiles.insert( itr ); - } - - } - - if ( !sc.isSuccess() ) { - throw GaudiException( "Problem connecting inputfile !!", name(), - StatusCode::FAILURE ); - } - - } -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -void -THistSvcHLT::setupOutputFile( Property& /*m_outputfile*/ ) -{ - if (FSMState() < Gaudi::StateMachine::CONFIGURED || !m_okToConnect) { - m_log <<MSG::DEBUG << "Delaying connection of Input Files until Initialize" - << ". now in " << FSMState() - << endmsg; - m_delayConnect = true; - } else { - - StatusCode sc = StatusCode::SUCCESS; - for ( const auto & itr : m_outputfile.value() ) { - if ( m_alreadyConnectedOutFiles.end() != - m_alreadyConnectedOutFiles.find( itr ) ) continue; - if ( connect(itr).isFailure() ) { - sc = StatusCode::FAILURE; - } else { - m_alreadyConnectedOutFiles.insert( itr ); - } - } - - if ( !sc.isSuccess() ) { - throw GaudiException( "Problem connecting outputfile !!", name(), - StatusCode::FAILURE ); - } - } -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -void -THistSvcHLT::updateFiles() { - - // If TTrees grow beyond TTree::fgMaxTreeSize, a new file is - // automatically created by root, and the old one closed. We - // need to migrate all the UIDs over to show the correct file - // pointer. This is ugly. - - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "updateFiles()" << endmsg; - - - for (auto uitr=m_uids.begin(); uitr != m_uids.end(); ++uitr) { -#ifndef NDEBUG - if (m_log.level() <= MSG::VERBOSE) - m_log << MSG::VERBOSE << " update: " << uitr->first << " " - << uitr->second.id << " " << uitr->second.mode << endmsg; -#endif - TObject* to = uitr->second.obj; - TFile* oldFile = uitr->second.file; - if (!to) { - m_log << MSG::WARNING << uitr->first << ": TObject == 0" << endmsg; - } else if ( uitr->second.temp || uitr->second.mode == READ ) { - // do nothing - no need to check how big the file is since we - // are just reading it. -#ifndef NDEBUG - if (m_log.level() <= MSG::VERBOSE) - m_log << MSG::VERBOSE << " skipping" << endmsg; -#endif - - } else if (to->IsA()->InheritsFrom("TTree")) { - TTree* tr = dynamic_cast<TTree*>(to); - TFile* newFile = tr->GetCurrentFile(); - - if (oldFile != newFile) { - std::string newFileName = newFile->GetName(); - std::string oldFileName, streamName, rem; - TFile* dummy = nullptr; - findStream(uitr->second.id, streamName, rem, dummy); - - for (auto& itr : m_files ) { - if (itr.second.first == oldFile) itr.second.first = newFile; - } - - for (auto uitr2 = uitr; uitr2 != m_uids.end(); ++uitr2) { - if (uitr2->second.file == oldFile) { - uitr2->second.file = newFile; - } - } - - auto sitr = std::find_if( std::begin(m_fileStreams), std::end(m_fileStreams), - [&](streamMap::const_reference s) { - return s.second == streamName; - }); - if (sitr!=std::end(m_fileStreams)) oldFileName = sitr->first; - -#ifndef NDEBUG - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "migrating uid: " << uitr->second.id - << " stream: " << streamName - << " oldFile: " << oldFileName - << " newFile: " << newFileName - << endmsg; -#endif - - - if (!oldFileName.empty()) { - auto i = m_fileStreams.lower_bound(oldFileName); - while (i != std::end(m_fileStreams) && i->first == oldFileName) { - -#ifndef NDEBUG - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "changing filename \"" << i->first - << "\" to \"" << newFileName << "\" for stream \"" - << i->second << "\"" << endmsg; -#endif - std::string nm = std::move(i->second); - i = m_fileStreams.erase(i); - m_fileStreams.emplace( newFileName, std::move(nm) ); - } - - - } else { - m_log << MSG::ERROR - << "Problems updating fileStreams with new file name" << endmsg; - } - - } - } - } -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::write() { - - updateFiles(); - - std::for_each( m_files.begin(), m_files.end(), [](std::pair<const std::string,std::pair<TFile*,Mode>>& i) { - auto mode = i.second.second; - auto file = i.second.first; - if ( mode == WRITE || mode == UPDATE || mode == SHARE ) { - file->Write("",TObject::kOverwrite); - } else if ( mode == APPEND ) { - file->Write(""); - } - } ); - - if (m_log.level() <= MSG::DEBUG) { - m_log << MSG::DEBUG << "THistSvcHLT::write()::List of Files connected in ROOT " - << endmsg; - TSeqCollection *filelist=gROOT->GetListOfFiles(); - for (int ii=0; ii<filelist->GetEntries(); ii++) { - m_log << MSG::DEBUG - << "THistSvcHLT::write()::List of Files connected in ROOT: \"" - << filelist->At(ii)->GetName()<<"\""<<endmsg; - } - } - - return StatusCode::SUCCESS; - -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::connect(const std::string& ident) { - - auto loc = ident.find(" "); - string stream = ident.substr(0,loc); - char typ(0); - typedef std::pair<std::string,std::string> Prop; - std::vector<Prop> props; - string filename, db_typ("ROOT"); - int cl(1); - - if (loc != string::npos) { - using Parser = Gaudi::Utils::AttribStringParser; - for (auto attrib: Parser(ident.substr(loc + 1))) { - auto TAG = boost::algorithm::to_upper_copy(attrib.tag); - auto VAL = boost::algorithm::to_upper_copy(attrib.value); - - if (TAG == "FILE" || TAG == "DATAFILE") { - filename = attrib.value; - removeDoubleSlash( filename ); - } else if ( TAG == "OPT" ) { - if ( VAL == "APPEND" || VAL == "UPDATE" ) { - typ = 'A'; - } else if ( VAL == "CREATE" || VAL == "NEW" || VAL == "WRITE" ) { - typ = 'N'; - } else if ( VAL == "RECREATE" ) { - typ = 'R'; - } else if (VAL == "SHARE") { - typ = 'S'; - } else if ( VAL == "OLD" || VAL == "READ" ) { - typ = 'O'; - } else { - m_log << MSG::ERROR << "Unknown OPT: \"" << attrib.value << "\"" - << endmsg; - typ = 0; - } - } else if (TAG == "TYP") { - db_typ = std::move(attrib.value); - } else if (TAG == "CL") { - cl = std::stoi(attrib.value); - } else { - props.emplace_back( attrib.tag, attrib.value); - } - - } - } - - if (stream == "temp") { - m_log << MSG::ERROR << "in JobOption \"" << ident - << "\": stream name \"temp\" reserved." - << endmsg; - return StatusCode::FAILURE; - } - - if (db_typ != "ROOT") { - m_log << MSG::ERROR << "in JobOption \"" << ident - << "\": technology type \"" << db_typ << "\" not supported." - << endmsg; - return StatusCode::FAILURE; - } - - - if (m_files.find(stream) != m_files.end()) { - m_log << MSG::ERROR << "in JobOption \"" << ident - << "\":\n stream \"" << stream << "\" already connected to file: \"" - << m_files[stream].first->GetName() << "\"" - << endmsg; - return StatusCode::FAILURE; - } - - Mode newMode; - if (typ == 'O') { - newMode = THistSvcHLT::READ; - } else if (typ == 'N') { - newMode = THistSvcHLT::WRITE; - } else if (typ == 'A') { - newMode = THistSvcHLT::APPEND; - } else if (typ == 'R') { - newMode = THistSvcHLT::UPDATE; - } else if (typ == 'S') { - newMode = THistSvcHLT::SHARE; - } else { - // something else? - m_log << MSG::ERROR << "No OPT= specified or unknown access mode in: " - << ident << endmsg; - return StatusCode::FAILURE; - } - - // Is this file already connected to another stream? - if (m_fileStreams.find(filename) != m_fileStreams.end()) { - auto fitr = m_fileStreams.equal_range(filename); - - const std::string& oldstream = fitr.first->second; - - const auto& f_info = m_files[oldstream]; - - if (newMode != f_info.second) { - m_log << MSG::ERROR << "in JobOption \"" << ident - << "\":\n file \"" << filename << "\" already opened by stream: \"" - << oldstream << "\" with different access mode." - << endmsg; - return StatusCode::FAILURE; - } else { - TFile *f2 = f_info.first; - m_files[stream] = make_pair(f2,newMode); - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "Connecting stream: \"" << stream - << "\" to previously opened TFile: \"" << filename << "\"" - << endmsg; - return StatusCode::SUCCESS; - } - } - - - IIncidentSvc *pi = nullptr; - if (service("IncidentSvc",pi).isFailure()) { - m_log << MSG::ERROR << "Unable to get the IncidentSvc" << endmsg; - return StatusCode::FAILURE; - } - - void* vf = nullptr; - TFile *f = nullptr; - - if (newMode == THistSvcHLT::READ) { - // old file - - int r = p_fileMgr->open(Io::ROOT,name(), filename,Io::READ,vf,"HIST"); - - if (r != 0) { - m_log << "Unable to open ROOT file " << filename << " for reading" - << endmsg; - return StatusCode::FAILURE; - } - - - f = (TFile*) vf; - - // FIX ME! - pi->fireIncident(FileIncident(name(), "BeginHistFile", filename)); - - - } else if (newMode == THistSvcHLT::WRITE) { - // new file. error if file exists - - int r = p_fileMgr->open(Io::ROOT,name(),filename, (Io::WRITE|Io::CREATE|Io::EXCL), - vf,"HIST"); - - if (r != 0) { - m_log << "Unable to open ROOT file " << filename << " for writing" - << endmsg; - return StatusCode::FAILURE; - } - - f = (TFile*)vf; - - } else if (newMode == THistSvcHLT::APPEND) { - // update file - - int r = p_fileMgr->open(Io::ROOT,name(),filename, (Io::WRITE | Io::APPEND), - vf,"HIST"); - if (r != 0) { - m_log << MSG::ERROR << "unable to open file \"" << filename - << "\" for appending" << endmsg; - return StatusCode::FAILURE; - } - - f = (TFile*) vf; - - - } else if (newMode == THistSvcHLT::SHARE) { - // SHARE file type - //For SHARE files, all data will be stored in a temp file and will be merged into the target file - //in write() when finalize(), this help to solve some confliction. e.g. with storegate - - static int ishared = 0; - string realfilename=filename; - filename = "tmp_THistSvcHLT_"+ std::to_string(ishared++)+".root"; - - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "Creating temp file \"" << filename - << "\" and realfilename="<<realfilename << endmsg; - m_sharedFiles[stream]=realfilename; - - - int r = p_fileMgr->open(Io::ROOT,name(), filename, (Io::WRITE|Io::CREATE|Io::EXCL), - vf,"HIST"); - - if (r != 0) { - m_log << "Unable to open ROOT file " << filename << " for writing" - << endmsg; - return StatusCode::FAILURE; - } - - f = (TFile*)vf; - - } else if (newMode == THistSvcHLT::UPDATE) { - // update file - - int r = p_fileMgr->open(Io::ROOT,name(), filename, (Io::WRITE|Io::CREATE), - vf, "HIST"); - - if (r != 0) { - m_log << "Unable to open ROOT file " << filename << " for appending" - << endmsg; - return StatusCode::FAILURE; - } - - f = (TFile*)vf; - - } - - m_files[stream] = make_pair(f,newMode); - m_fileStreams.insert(make_pair(filename,stream)); - - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "Opening TFile \"" << filename << "\" stream: \"" - << stream << "\" mode: \"" << typ << "\"" << " comp level: " << cl - << endmsg; - - return StatusCode::SUCCESS; -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -TDirectory* -THistSvcHLT::changeDir(const THistSvcHLT::THistID& hid) const { - - string uid = hid.id; - TFile* file = hid.file; - string stream, fdir, bdir, dir, id; - - if (file) { - file->cd("/"); - } else { - gROOT->cd(); - } - - fdir = uid; - bdir = dirname(fdir); - - while ( (dir = dirname(fdir)) != "") { - if (! gDirectory->GetKey(dir.c_str())) { - gDirectory->mkdir(dir.c_str()); - } - gDirectory->cd(dir.c_str()); - } - - return gDirectory; - -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -std::string -THistSvcHLT::dirname(std::string& dir) const { - - - string::size_type i = dir.find("/"); - - if (i == string::npos) return {}; - - if ( i == 0 ) { - dir.erase(0,1); - return dirname(dir); - } - - string root = dir.substr(0,i); - dir.erase(0,i); - - return root; - -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -THistSvcHLT::GlobalDirectoryRestore::GlobalDirectoryRestore() { - m_gd = gDirectory; - m_gf = gFile; - m_ge = gErrorIgnoreLevel; -} - -THistSvcHLT::GlobalDirectoryRestore::~GlobalDirectoryRestore() { - gDirectory = m_gd; - gFile = m_gf; - gErrorIgnoreLevel = m_ge; -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -void -THistSvcHLT::removeDoubleSlash(std::string& id) const { - - while (id.find("//") != std::string::npos) { - id.replace(id.find("//"),2,"/"); - } - -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -void THistSvcHLT::MergeRootFile(TDirectory *target, TDirectory *source) { - - if (m_log.level() <= MSG::DEBUG) - m_log <<MSG::DEBUG << "Target path: " << target->GetPath() << endmsg; - TString path( (char*)strstr(target->GetPath(), ":") ); - path.Remove( 0, 2); - - source->cd(path); - TDirectory *current_sourcedir = gDirectory; - - // loop over all keys in this directory - TList *lkeys=current_sourcedir->GetListOfKeys(); - int nkeys=lkeys->GetEntries(); - TKey *key; - for (int jj=0; jj<nkeys; jj++) { - key=(TKey*) lkeys->At(jj); - string pathnameinsource=current_sourcedir->GetPath()+string("/")+key->GetName(); - if (m_log.level() <= MSG::DEBUG) - m_log <<MSG::DEBUG << "Reading Key:" << pathnameinsource << endmsg; - //key->Dump(); - //TObject *obj=key->ReadObj(); - TObject *obj=source->Get(pathnameinsource.c_str()); - - if (obj) { - if (obj->IsA()->InheritsFrom("TDirectory") ) { - // it's a subdirectory - - if (m_log.level() <= MSG::DEBUG) - m_log <<MSG::DEBUG << "Found subdirectory " << obj->GetName() - << endmsg; - - // create a new subdir of same name and title in the target file - target->cd(); - TDirectory *newtargetdir = - target->mkdir(obj->GetName(), obj->GetTitle() ); - - MergeRootFile(newtargetdir, source); - - } else if (obj->IsA()->InheritsFrom("TTree")) { - if (m_log.level() <= MSG::DEBUG) - m_log <<MSG::DEBUG << "Found TTree " << obj->GetName() << endmsg; - TTree *mytree=dynamic_cast<TTree*>(obj); - int nentries=(int) mytree->GetEntries(); - mytree->SetBranchStatus("*",1); - - if (m_log.level() <= MSG::DEBUG) - m_log <<MSG::DEBUG << "Dumping TTree " << nentries <<" entries" - << endmsg; - //mytree->Print(); - //for (int ij=0; ij<nentries; ij++) { - //m_log <<MSG::DEBUG << "Dumping TTree Show( " << ij <<" )" - //<< endmsg; - //mytree->Show(ij); - //} - target->cd(); - mytree->CloneTree(); - - //m_log <<MSG::DEBUG << "Writing TTree to target file: ( " - //<< mycopiedtree->Write(key->GetName()) <<" ) bytes written" - //<< endmsg; - - } else { - target->cd(); - obj->Write(key->GetName() ); - } - } - - } // while ( ( TKey *key = (TKey*)nextkey() ) ) - - // save modifications to target file - -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -bool -THistSvcHLT::exists( const std::string& name ) const { - - TH1* h; - return getHist_i(name,h,true).isSuccess(); - -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -void -THistSvcHLT::handle( const Incident& /* inc */ ) { - - if (signaledStop) return ; - - if (m_maxFileSize.value() == -1) return; - - // convert to bytes. - Long64_t mfs = (Long64_t)m_maxFileSize.value() * (Long64_t)1048576; - Long64_t mfs_warn = mfs * 95 / 100; - - updateFiles(); - - map<string, pair<TFile*,Mode> >::const_iterator itr; - for (const auto& f : m_files) { - TFile* tf = f.second.first; - -#ifndef NDEBUG - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "stream: " << f.first << " name: " - << tf->GetName() << " size: " << tf->GetSize() - << endmsg; -#endif - - // Signal job to terminate if output file is too large - if (tf->GetSize() > mfs) { - - signaledStop = true; - - m_log << MSG::FATAL << "file \"" << tf->GetName() - << "\" associated with stream \"" << f.first - << "\" has exceeded the max file size of " - << m_maxFileSize.value() << "MB. Terminating Job." - << endmsg; - - IEventProcessor* evt = nullptr; - if (service("ApplicationMgr", evt, true).isSuccess()) { - evt->stopRun(); - evt->release(); - } else { - abort(); - } - } else if (tf->GetSize() > mfs_warn) { - m_log << MSG::WARNING << "file \"" << tf->GetName() - << "\" associated with stream \"" << f.first - << "\" is at 95% of its maximum allowable file size of " - << m_maxFileSize.value() << "MB" - << endmsg; - } - } -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -/** helper function to recursively copy the layout of a TFile into a new TFile - */ -void -THistSvcHLT::copyFileLayout (TDirectory *dst, TDirectory *src) { - - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "copyFileLayout() to dst path: " << dst->GetPath () << endmsg; - - // strip out URLs - TString path ((char*)strstr (dst->GetPath(), ":")); - path.Remove (0, 2); - - src->cd (path); - TDirectory *cur_src_dir = gDirectory; - - // loop over all keys in this directory - TList *key_list = cur_src_dir->GetListOfKeys (); - int n = key_list->GetEntries (); - for ( int j = 0; j < n; ++j ) { - TKey *k = (TKey*)key_list->At (j); - const std::string src_pathname = cur_src_dir->GetPath() - + std::string("/") - + k->GetName(); - TObject *o=src->Get (src_pathname.c_str()); - - if ( o && o->IsA()->InheritsFrom ("TDirectory")) { - if (m_log.level() <= MSG::VERBOSE) - m_log << MSG::VERBOSE << " subdir [" << o->GetName() << "]..." << endmsg; - dst->cd (); - TDirectory * dst_dir = dst->mkdir (o->GetName(), o->GetTitle()); - copyFileLayout (dst_dir, src); - } - } // loop over keys - return; -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// -/** @brief callback method to reinitialize the internal state of - * the component for I/O purposes (e.g. upon @c fork(2)) - */ -StatusCode -THistSvcHLT::io_reinit () -{ - bool all_good = true; - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "reinitializing I/O..." << endmsg; - - // retrieve the I/O component manager... - - IIoComponentMgr* iomgr = nullptr; - - if (service("IoComponentMgr", iomgr, true).isFailure()) { - m_log << MSG::ERROR << "could not retrieve I/O component manager !" - << endmsg; - return StatusCode::FAILURE; - } - - GlobalDirectoryRestore restore; - // to hide the expected errors upon closing the files whose - // file descriptors have been swept under the rug... - gErrorIgnoreLevel = kFatal; - - typedef std::map<std::string, std::pair<TFile*,Mode> > FileReg_t; - - for (auto & ifile : m_files ) { - TFile *f = ifile.second.first; - std::string fname = f->GetName(); - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "file [" << fname << "] mode: [" - << f->GetOption() << "] r:" - << f->GetFileBytesRead() - << " w:" << f->GetFileBytesWritten() - << " cnt:" << f->GetFileCounter() - << endmsg; - - if ( ifile.second.second == READ ) { - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG - << " TFile opened in READ mode: not reassigning names" << endmsg; - continue; - } - - if ( !iomgr->io_retrieve (this, fname).isSuccess () ) { - m_log << MSG::ERROR << "could not retrieve new name for [" << fname - << "] !!" << endmsg; - all_good = false; - continue; - } else { - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "got a new name [" << fname << "]..." << endmsg; - } - // create a new TFile - // TFile *newfile = TFile::Open (fname.c_str(), f->GetOption()); - - void* vf; - Option_t *opts = f->GetOption(); - int r = p_fileMgr->open(Io::ROOT,name(),fname,Io::WRITE,vf,"HIST"); - if (r != 0) { - m_log << MSG::ERROR << "unable to open file \"" << fname - << "\" for writing" << endmsg; - return StatusCode::FAILURE; - } - TFile *newfile = (TFile*) vf; - newfile->SetOption(opts); - - - if (ifile.second.second != THistSvcHLT::READ) { - copyFileLayout (newfile, f); - ifile.second.first = newfile; - } - - // loop over all uids and migrate them to the new file - // XXX FIXME: this double loop sucks... - for ( auto& uid : m_uids ) { - THistID& hid = uid.second; - if ( hid.file != f ) continue; - TDirectory *olddir = this->changeDir (hid); - hid.file = newfile; - // side-effect: create needed directories... - TDirectory *newdir = this->changeDir (hid); - TClass *cl = hid.obj->IsA(); - - // migrate the objects to the new file. - // thanks to the object model of ROOT, it is super easy. - if (cl->InheritsFrom ("TTree")) { - dynamic_cast<TTree*> (hid.obj)->SetDirectory (newdir); - dynamic_cast<TTree*> (hid.obj)->Reset(); - } - else if (cl->InheritsFrom ("TH1")) { - dynamic_cast<TH1*> (hid.obj)->SetDirectory (newdir); - dynamic_cast<TH1*> (hid.obj)->Reset(); - } - else if (cl->InheritsFrom ("TGraph")) { - olddir->Remove (hid.obj); - newdir->Append (hid.obj); - } else { - m_log << MSG::ERROR - << "id: \"" << hid.id << "\" is not a inheriting from a class " - << "we know how to handle (received [" << cl->GetName() - << "], " << "expected [TTree, TH1 or TGraph]) !" - << endmsg - << "attaching to current dir [" << newdir->GetPath() << "] " - << "nonetheless..." << endmsg; - olddir->Remove (hid.obj); - newdir->Append (hid.obj); - } - } - f->ReOpen ("READ"); - p_fileMgr->close(f,name()); - f = newfile; - } - - return all_good ? StatusCode::SUCCESS : StatusCode::FAILURE; -} - - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::rootOpenAction( const Io::FileAttr* fa, const std::string& caller) { - - if (fa->tech() != Io::ROOT) { - // This should never happen - return StatusCode::SUCCESS; - } - - if (fa->desc() != "HIST") { - return StatusCode::SUCCESS; - } - - p_incSvc->fireIncident(FileIncident(caller, "OpenHistFile", fa->name())); - - if ( fa->flags().isRead() ) { - p_incSvc->fireIncident(FileIncident(caller, "BeginHistFile", fa->name())); - } else if ( fa->flags().isWrite() ) { - p_incSvc->fireIncident(FileIncident(caller, IncidentType::BeginOutputFile, - fa->name())); - } else { - // for Io::RW - p_incSvc->fireIncident(FileIncident(caller, IncidentType::BeginOutputFile, - fa->name())); - } - - return StatusCode::SUCCESS; - - -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -StatusCode -THistSvcHLT::rootOpenErrAction( const Io::FileAttr* fa, const std::string& caller) { - - if (fa->tech() != Io::ROOT) { - // This should never happen - return StatusCode::SUCCESS; - } - - if (fa->desc() != "HIST") { - return StatusCode::SUCCESS; - } - - if ( fa->flags().isRead() ) { - p_incSvc->fireIncident(FileIncident(caller, IncidentType::FailInputFile, - fa->name())); - } else if ( fa->flags().isWrite() ) { - p_incSvc->fireIncident(FileIncident(caller, IncidentType::FailOutputFile, - fa->name())); - } else { - // for Io::RW - p_incSvc->fireIncident(FileIncident(caller, "FailRWFile", fa->name())); - } - - return StatusCode::SUCCESS; -} diff --git a/HLT/Trigger/TrigControl/TrigServices/src/THistSvcHLT.h b/HLT/Trigger/TrigControl/TrigServices/src/THistSvcHLT.h new file mode 100644 index 0000000000000000000000000000000000000000..9ff4a578f276ff5c752ba50195169f4282c7b4b7 --- /dev/null +++ b/HLT/Trigger/TrigControl/TrigServices/src/THistSvcHLT.h @@ -0,0 +1,361 @@ +/* + * This is a copy of GaudiSvc/src/THistSvc with THistSvc renamed to THistSvcHLT + * to allow inheritance of this class by TrigMonTHistSvc. + */ +#ifndef THISTSVCHLT_H +#define THISTSVCHLT_H + +// system includes: +#include <map> +#include <set> +#include <string> +#include <vector> + +// Gaudi includes: +#include "GaudiKernel/IFileMgr.h" +#include "GaudiKernel/IIncidentListener.h" +#include "GaudiKernel/IIoComponent.h" +#include "GaudiKernel/ITHistSvc.h" +#include "GaudiKernel/MsgStream.h" +#include "GaudiKernel/Service.h" + +//Â ROOT includes: +#include "TGraph.h" +#include "TH1.h" +#include "TH2.h" +#include "TH3.h" +#include "TList.h" +#include "TObject.h" +#include "TTree.h" + +class IIncidentSvc; + +class THistSvcHLT : public extends<Service, ITHistSvc, IIncidentListener, IIoComponent> +{ +public: + THistSvcHLT( const std::string& name, ISvcLocator* svc ); + + StatusCode initialize() override; + StatusCode reinitialize() override; + StatusCode finalize() override; + +public: + // Methods from ITHistSvc + /// @name Functions to manage ROOT histograms of any kind + /// @{ + + /// Register a new ROOT histogram TH*X with a name + StatusCode regHist( const std::string& name ) override; + /// Register an existing ROOT histogram TH*X with name and moved unique_ptr + /// @param [in] name defines the histogram id/name under which it is recorded + /// @param [in] hist transfers ownership of the histogram to the THistSvc + StatusCode regHist( const std::string& name, std::unique_ptr<TH1> hist ) override; + /// Register an existing ROOT histogram TH*X with name and moved unique_ptr + /// @param [in] name defines the histogram id/name under which it is recorded + /// @param [in] hist transfers ownership of the histogram to the THistSvc + /// @param [out] hist_ptr for compatibility: return raw pointer to managed object to support common usage in Athena + StatusCode regHist( const std::string& name, std::unique_ptr<TH1> hist, TH1* hist_ptr ) override; + /// @deprecated {Just for compatibility purposes. Ownership should be clearly managed.} + /// Register an existing ROOT histogram TH*X with name and pointer + StatusCode regHist( const std::string& name, TH1* ) override; + + /// Return histogram with given name as TH1*, THistSvcMT still owns object. + StatusCode getHist( const std::string& name, TH1*&, size_t index = 0 ) const override; + /// Return histogram with given name as TH2*, THistSvcMT still owns object. + StatusCode getHist( const std::string& name, TH2*&, size_t index = 0 ) const override; + /// Return histogram with given name as TH3*, THistSvcMT still owns object. + StatusCode getHist( const std::string& name, TH3*&, size_t index = 0 ) const override; + + /// @} + + /// @name Functions to manage TTrees + /// @{ + + /// Register a new TTree with a given name + StatusCode regTree( const std::string& name ) override; + /// Register an existing TTree with a given name and moved unique_ptr + StatusCode regTree( const std::string& name, std::unique_ptr<TTree> ) override; + /// @deprecated {Just kept for compatibiltiy to current ATLAS code. Pleas use std::unique_ptrs instead!} + /// Register a new TTree with a given name and a raw pointer + StatusCode regTree( const std::string& name, TTree* ) override; + /// Return TTree with given name + StatusCode getTree( const std::string& name, TTree*& ) const override; + + /// @} + + /// @name Functions to manage TGraphs + /// @{ + + /// Register a new TGraph with a given name + StatusCode regGraph( const std::string& name ) override; + /// Register an existing TGraph with a given name and moved unique_ptr + StatusCode regGraph( const std::string& name, std::unique_ptr<TGraph> ) override; + /// @deprecated {Just kept for compatibiltiy to current ATLAS code. Pleas use std::unique_ptrs instead!} + /// Register a new TGraph with a given name and a raw pointer + virtual StatusCode regGraph( const std::string& name, TGraph* ) override; + /// Return TGraph with given name + StatusCode getGraph( const std::string& name, TGraph*& ) const override; + + /// @} + + /// @name Functions managing shared objects + /// @{ + + /// Register shared object of type TH1 and return LockedHandle for that object + StatusCode regShared( const std::string& name, std::unique_ptr<TH1>, LockedHandle<TH1>& ) override; + /// Register shared object of type TH2 and return LockedHandle for that object + StatusCode regShared( const std::string& name, std::unique_ptr<TH2>, LockedHandle<TH2>& ) override; + /// Register shared object of type TH3 and return LockedHandle for that object + StatusCode regShared( const std::string& name, std::unique_ptr<TH3>, LockedHandle<TH3>& ) override; + /// Register shared object of type TGraph and return LockedHandle for that object + StatusCode regShared( const std::string& name, std::unique_ptr<TGraph>, LockedHandle<TGraph>& ) override; + /// Retrieve shared object with given name as TH1 through LockedHandle + StatusCode getShared( const std::string& name, LockedHandle<TH1>& ) const override; + /// Retrieve shared object with given name as TH2 through LockedHandle + StatusCode getShared( const std::string& name, LockedHandle<TH2>& ) const override; + /// Retrieve shared object with given name as TH3 through LockedHandle + StatusCode getShared( const std::string& name, LockedHandle<TH3>& ) const override; + /// Retrieve shared object with given name as TGraph through LockedHandle + StatusCode getShared( const std::string& name, LockedHandle<TGraph>& ) const override; + + /// @} + + /// @name Functions that work on any TObject in the THistSvcMT + /// @{ + + /// Deregister object with given name and give up ownership (without deletion!) + StatusCode deReg( const std::string& name ) override; + /// Deregister obejct identified by TObject* and give up ownership (without deletion!) + StatusCode deReg( TObject* obj ) override; + + /// Merge all clones for object with a given id + StatusCode merge( const std::string& id ) override; + /// Merge all clones for given TObject* + StatusCode merge( TObject* ) override; + + /// Check if object with given name is managed by THistSvcMT + bool exists( const std::string& name ) const override; + + /// @} + + /// @name Functions returning lists of all histograms, trees and graphs + /// @{ + + std::vector<std::string> getHists() const override; + std::vector<std::string> getTrees() const override; + std::vector<std::string> getGraphs() const override; + + StatusCode getTHists( TDirectory* td, TList&, bool recurse = false ) const override; + StatusCode getTHists( const std::string& name, TList&, bool recurse = false ) const override; + StatusCode getTHists( TDirectory* td, TList& tl, bool recurse = false, bool reg = false ) override; + StatusCode getTHists( const std::string& name, TList& tl, bool recurse = false, bool reg = false ) override; + + StatusCode getTTrees( TDirectory* td, TList&, bool recurse = false ) const override; + StatusCode getTTrees( const std::string& name, TList&, bool recurse = false ) const override; + StatusCode getTTrees( TDirectory* td, TList& tl, bool recurse = false, bool reg = false ) override; + StatusCode getTTrees( const std::string& name, TList& tl, bool recurse = false, bool reg = false ) override; + + /// @} + +public: + // Methods from other interfaces + // From IIncidentListener + void handle( const Incident& ) override; + + // From IIoComponent + StatusCode io_reinit() override; + +private: + typedef std::recursive_mutex THistSvcMutex_t; + typedef std::mutex histMut_t; + + /// Helper class that manages ROOts global directory and file + class GlobalDirectoryRestore + { + public: + GlobalDirectoryRestore( THistSvcMutex_t& mut ); + ~GlobalDirectoryRestore(); + + private: + TDirectory* m_gDirectory; + TFile* m_gFile; + int m_gErrorIgnoreLevel; + std::lock_guard<THistSvcMutex_t> m_lock; + }; + + /// Enumerating all possible file access modes + enum Mode { READ, WRITE, UPDATE, APPEND, SHARE, INVALID }; + + /// Helper struct that bundles the histogram ID with a mutex, TFile and TObject* + struct THistID { + std::string id{""}; + bool temp{true}; + TObject* obj{nullptr}; + TFile* file{nullptr}; + Mode mode{INVALID}; + histMut_t* mutex{nullptr}; + bool shared{false}; + + THistID() = default; + THistID( const THistID& rhs ) = default; + THistID( std::string& i, bool& t, TObject* o, TFile* f ) : id( i ), temp( t ), obj( o ), file( f ) {} + THistID( std::string& i, bool& t, TObject* o, TFile* f, Mode m ) + : id( i ), temp( t ), obj( o ), file( f ), mode( m ) + { + } + + void reset() + { + id = ""; + temp = true; + obj = nullptr; + file = nullptr; + mode = INVALID; + mutex = nullptr; + shared = false; + } + + bool operator<( THistID const& rhs ) const { return ( obj < rhs.obj ); } + + friend std::ostream& operator<<( std::ostream& ost, const THistID& hid ) + { + ost << "id: " << hid.id << " t: " << hid.temp << " s: " << hid.shared << " M: " << hid.mode << " m: " << hid.mutex + << " o: " << hid.obj << " " << hid.obj->IsA()->GetName(); + return ost; + } + }; + + /// @name Container definitions + /// @{ + + std::vector<std::string> m_Rstream, m_Wstream; + + /// list of already connected files. This is to keep track of files + /// registered by the setupInputFile callback method + std::set<std::string> m_alreadyConnectedInFiles; + + /// list of already connected files. This is to keep track of files + /// registered by the setupOutputFile callback method + std::set<std::string> m_alreadyConnectedOutFiles; + + // containers for fast lookups + // same uid for all elements in vec + typedef std::vector<THistID> vhid_t; + // all THistIDs + typedef std::list<vhid_t*> hlist_t; + // uid: /stream/name -> vhid + typedef std::unordered_map<std::string, vhid_t*> uidMap_t; + // name -> vhid + typedef std::unordered_multimap<std::string, vhid_t*> idMap_t; + typedef std::unordered_map<TObject*, std::pair<vhid_t*, size_t>> objMap_t; + + hlist_t m_hlist; + uidMap_t m_uids; + idMap_t m_ids; + + // Container holding all TObjects and vhid*s + objMap_t m_tobjs; + + std::map<std::string, std::pair<TFile*, Mode>> m_files; // stream->file + typedef std::multimap<std::string, std::string> streamMap; + streamMap m_fileStreams; // fileName->streams + + // stream->filename of shared files + std::map<std::string, std::string> m_sharedFiles; + + /// @} + + /// @name Templated helper functions to register and retrieve Histograms and TObjects + /// @{ + + template <typename T> + StatusCode regHist_i( std::unique_ptr<T> hist, const std::string& name, bool shared ); + template <typename T> + StatusCode regHist_i( std::unique_ptr<T> hist, const std::string& name, bool shared, THistID*& hid ); + template <typename T> + T* getHist_i( const std::string& name, const size_t& ind = 0, bool quiet = false ) const; + template <typename T> + T* readHist_i( const std::string& name ) const; + + template <typename T> + LockedHandle<T> regShared_i( const std::string& id, std::unique_ptr<T> hist ); + template <typename T> + LockedHandle<T> getShared_i( const std::string& name ) const; + + /// @} + + /// @name Collection of private helper methods + /// @{ + + template <typename T> + T* readHist( const std::string& name ) const; + TTree* readTree( const std::string& name ) const; + + /// Handle case where TTree grows beyond TTree::fgMaxTreeSize + void updateFiles(); + StatusCode writeObjectsToFile(); + StatusCode connect( const std::string& ); + TDirectory* changeDir( const THistSvcHLT::THistID& hid ) const; + std::string stripDirectoryName( std::string& dir ) const; + void removeDoubleSlash( std::string& ) const; + + void MergeRootFile( TDirectory*, TDirectory* ); + + bool findStream( const std::string& name, std::string& root, std::string& rem, TFile*& file ) const; + void parseString( const std::string& id, std::string& root, std::string& rem ) const; + + /// call-back method to handle input stream property + void setupInputFile( Gaudi::Details::PropertyBase& inputfile ); + + /// call-back method to handle output stream property + void setupOutputFile( Gaudi::Details::PropertyBase& outputfile ); + + void setupCompressionLevel( Gaudi::Details::PropertyBase& cmp ); + + /// helper function to recursively copy the layout of a TFile into a new TFile + void copyFileLayout( TDirectory*, TDirectory* ); + + size_t findHistID( const std::string& id, const THistID*& hid, const size_t& index = 0 ) const; + + void dump() const; + + /// Helper method to merge THistID objects + StatusCode merge( const THistID& ); + /// Helper method to merge vectors of THistID + StatusCode merge( vhid_t* ); + + StatusCode rootOpenAction( FILEMGR_CALLBACK_ARGS ); + StatusCode rootOpenErrAction( FILEMGR_CALLBACK_ARGS ); + + /// @} + + /// @name Gaudi properties + /// @{ + + Gaudi::Property<int> m_autoSave{this, "AutoSave", 0}; + Gaudi::Property<int> m_autoFlush{this, "AutoFlush", 0}; + Gaudi::Property<bool> m_print{this, "PrintAll", false}; + Gaudi::Property<int> m_maxFileSize{this, "MaxFileSize", 10240, "maximum file size in MB. if exceeded," + " will cause an abort. -1 to never check."}; + Gaudi::Property<int> m_compressionLevel{this, "CompressionLevel", 1}; + Gaudi::Property<std::vector<std::string>> m_outputfile{this, "Output", {}}; + Gaudi::Property<std::vector<std::string>> m_inputfile{this, "Input", {}}; + + /// @} + + IIncidentSvc* p_incSvc = nullptr; + IFileMgr* p_fileMgr = nullptr; + + bool m_signaledStop = false; + bool m_delayConnect = false; + bool m_okToConnect = false; + + mutable std::string m_curstream; + + mutable THistSvcMutex_t m_svcMut; +}; + +// Include template implementation +#include "THistSvcHLT.icc" + +#endif // THISTSVCHLT_H diff --git a/HLT/Trigger/TrigControl/TrigServices/src/THistSvcHLT.h.bak b/HLT/Trigger/TrigControl/TrigServices/src/THistSvcHLT.h.bak deleted file mode 100644 index cec1ef7d50e4cf042c4af0b0a480426b2caab66b..0000000000000000000000000000000000000000 --- a/HLT/Trigger/TrigControl/TrigServices/src/THistSvcHLT.h.bak +++ /dev/null @@ -1,230 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -#ifndef THISTSVCHLT_H -#define THISTSVCHLT_H - -#include "GaudiKernel/Service.h" -#include "GaudiKernel/ITHistSvc.h" -#include "GaudiKernel/IFileMgr.h" -#include "GaudiKernel/IIncidentListener.h" -#include "GaudiKernel/IIoComponent.h" -#include "GaudiKernel/MsgStream.h" - -#include "TObject.h" -#include "TH1.h" -#include "TH2.h" -#include "TH3.h" -#include "TTree.h" -#include "TGraph.h" -#include "TList.h" - - -#include <vector> -#include <string> -#include <set> -#include <map> - -class IIncidentSvc; -class THistSvcHLT: public extends3<Service, ITHistSvc, IIncidentListener, - IIoComponent> { - -public: - - StatusCode initialize() override; - StatusCode reinitialize() override; - StatusCode finalize() override; - - StatusCode regHist(const std::string& name) override; - StatusCode regHist(const std::string& name, TH1*) override; - StatusCode regHist(const std::string& name, TH2*) override; - StatusCode regHist(const std::string& name, TH3*) override; - - StatusCode getHist(const std::string& name, TH1*&) const override; - StatusCode getHist(const std::string& name, TH2*&) const override; - StatusCode getHist(const std::string& name, TH3*&) const override; - - StatusCode regTree(const std::string& name) override; - StatusCode regTree(const std::string& name, TTree*) override; - StatusCode getTree(const std::string& name, TTree*&) const override; - - StatusCode regGraph(const std::string& name) override; - StatusCode regGraph(const std::string& name, TGraph*) override; - StatusCode getGraph(const std::string& name, TGraph*&) const override; - - StatusCode deReg(TObject* obj) override; - StatusCode deReg(const std::string& name) override; - - std::vector<std::string> getHists() const override; - std::vector<std::string> getTrees() const override; - std::vector<std::string> getGraphs() const override; - - StatusCode getTHists(TDirectory *td, TList &, - bool recurse=false) const override; - StatusCode getTHists(const std::string& name, TList &, - bool recurse=false) const override; - - StatusCode getTHists(TDirectory *td, TList &tl, - bool recurse=false, bool reg=false) override; - StatusCode getTHists(const std::string& name, TList &tl, - bool recurse=false, bool reg=false) override; - - StatusCode getTTrees(TDirectory *td, TList &, - bool recurse=false) const override; - StatusCode getTTrees(const std::string& name, TList &, - bool recurse=false) const override; - - StatusCode getTTrees(TDirectory *td, TList & tl, - bool recurse=false, bool reg=false) override; - StatusCode getTTrees(const std::string& name, TList & tl, - bool recurse=false, bool reg=false) override; - - bool exists(const std::string& name) const override; - - THistSvcHLT(const std::string& name, ISvcLocator *svc ); - - void handle(const Incident&) override; - - // From IIoComponent - StatusCode io_reinit () override; - - -protected: - - ~THistSvcHLT() override = default; - -private: - - class GlobalDirectoryRestore { - public: - GlobalDirectoryRestore(); - ~GlobalDirectoryRestore(); - private: - TDirectory* m_gd; - TFile* m_gf; - int m_ge; - }; - - enum Mode { - READ, - WRITE, - UPDATE, - APPEND, - SHARE, - INVALID - }; - - struct THistID { - std::string id; - bool temp; - TObject* obj; - TFile* file; - Mode mode; - - THistID():id(""),temp(true),obj(0),file(0),mode(INVALID) {} - THistID(const THistID& rhs):id(rhs.id), temp(rhs.temp), - obj(rhs.obj), file(rhs.file), mode(rhs.mode) {} - THistID(std::string& i, bool& t, TObject* o, TFile* f) - : id(i), temp(t), obj(o), file(f), mode(INVALID){ - } - THistID(std::string& i, bool& t, TObject* o, TFile* f, Mode m) - : id(i), temp(t), obj(o), file(f), mode(m){ - } - - bool operator < (THistID const &rhs) const { - return (obj < rhs.obj); - } - }; - - - template <typename T> - StatusCode regHist_i(T* hist, const std::string& name); - template <typename T> - StatusCode getHist_i(const std::string& name, T*& hist, bool quiet=false) const; - template <typename T> - StatusCode readHist_i(const std::string& name, T*& hist) const; - - - StatusCode readHist(const std::string& name, TH1*&) const; - StatusCode readHist(const std::string& name, TH2*&) const; - StatusCode readHist(const std::string& name, TH3*&) const; - StatusCode readTree(const std::string& name, TTree*&) const; - - void updateFiles(); - StatusCode write(); - StatusCode connect(const std::string&); - TDirectory* changeDir(const THistSvcHLT::THistID& hid) const; - std::string dirname(std::string& dir) const; - void removeDoubleSlash(std::string&) const; - - bool browseTDir(TDirectory* dir) const; - - bool findStream(const std::string& name, std::string& root, - std::string& rem, TFile*& file) const; - void parseString(const std::string& id, std::string& root, std::string& rem) - const; - - /// call-back method to handle input stream property - void setupInputFile( Property& inputfile ); - - /// call-back method to handle output stream property - void setupOutputFile( Property& outputfile ); - - void setupCompressionLevel( Property& cmp ); - - void copyFileLayout(TDirectory*, TDirectory*); - - void MergeRootFile( TDirectory *target, TDirectory *source); - - //////// - - mutable MsgStream m_log; - - StringArrayProperty m_inputfile, m_outputfile; - std::vector<std::string> m_Rstream, m_Wstream; - IntegerProperty m_autoSave, m_autoFlush, m_compressionLevel, m_maxFileSize; - BooleanProperty m_print; - - /// list of already connected files. This is to keep track of files - /// registered by the setupInputFile callback method - std::set<std::string> m_alreadyConnectedInFiles; - - /// list of already connected files. This is to keep track of files - /// registered by the setupOutputFile callback method - std::set<std::string> m_alreadyConnectedOutFiles; - - - typedef std::map<std::string, THistID> uidMap; - typedef std::multimap<std::string, THistID> idMap; - typedef std::map<TObject*, THistID> objMap; - typedef std::multimap<std::string, std::string> streamMap; - - uidMap m_uids; - idMap m_ids; - objMap m_tobjs; - - std::map<std::string, std::pair<TFile*,Mode> > m_files; // stream->file - streamMap m_fileStreams; // fileName->streams - - std::map<std::string, std::string > m_sharedFiles; // stream->filename of shared files - - bool signaledStop = false; - bool m_delayConnect = false, m_okToConnect = false; - - mutable std::string m_curstream; - - IIncidentSvc* p_incSvc = nullptr; - IFileMgr* p_fileMgr = nullptr; - - StatusCode rootOpenAction( FILEMGR_CALLBACK_ARGS ); - StatusCode rootOpenErrAction( FILEMGR_CALLBACK_ARGS ); - -}; - -#ifndef THISTSVCHLT_ICC - #include "THistSvcHLT.icc" -#endif - - -#endif diff --git a/HLT/Trigger/TrigControl/TrigServices/src/THistSvcHLT.icc b/HLT/Trigger/TrigControl/TrigServices/src/THistSvcHLT.icc new file mode 100644 index 0000000000000000000000000000000000000000..9595c3a580e6b9b9c1d288618d742daf6e098e03 --- /dev/null +++ b/HLT/Trigger/TrigControl/TrigServices/src/THistSvcHLT.icc @@ -0,0 +1,338 @@ +/* + * This is a copy of GaudiSvc/src/THistSvc with THistSvc renamed to THistSvcHLT + * to allow inheritance of this class by TrigMonTHistSvc. + */ +#ifndef THISTSVCHLT_ICC +#define THISTSVCHLT_ICC + +#include <map> +#include <string> + +#include "TFile.h" +#include "TObject.h" + +#ifndef GAUDIKERNEL_MSGSTREAM_H +#include "GaudiKernel/MsgStream.h" +#endif + +#include "GaudiKernel/System.h" + +template <typename T> +StatusCode THistSvcHLT::regHist_i( std::unique_ptr<T> hist, const std::string& id, bool shared ) +{ + THistID* hid = nullptr ; + return regHist_i( std::move(hist), id, shared, hid ); +} + +template <typename T> +StatusCode THistSvcHLT::regHist_i( std::unique_ptr<T> hist_unique, const std::string& id, bool shared, THistID*& phid ) +{ + GlobalDirectoryRestore restore( m_svcMut ); + phid = nullptr; + + // It is sad that we lose propper memory management here + T* hist = nullptr; + if( hist_unique.get() != nullptr ) { + hist = hist_unique.release(); + } + debug() << "regHist_i obj: " << hist << " id: " << id << " s: " << shared << endmsg; + + std::string idr( id ); + removeDoubleSlash( idr ); + + if ( idr.find( "/" ) == idr.length() ) { + error() << "Badly formed identifier \"" << idr << "\": " + << "Must not end with a /" << endmsg; + delete hist; + return StatusCode::FAILURE; + } + + TFile* f = nullptr; + std::string stream, name; + if ( !findStream( idr, stream, name, f ) ) { + error() << "Could not register id: \"" << idr << "\"" << endmsg; + delete hist; + return StatusCode::FAILURE; + } + + std::string uid = "/" + stream + "/" + name; + + uidMap_t::iterator uitr = m_uids.find( uid ); + bool exists( false ); + if ( uitr != m_uids.end() ) { + exists = true; + TObject* t1 = uitr->second->at( 0 ).obj; + if ( hist->Compare( t1 ) != 0 ) { + error() << "previously registered object with identifier \"" << uid << "\" does not compare to this one" + << endmsg; + delete hist; + return StatusCode::FAILURE; + } else { + debug() << "previously registered id \"" << uid << "\": num " << uitr->second->size() << endmsg; + } + } + + bool temp = false; + if ( !f ) { + temp = true; + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "Historgram with id \"" << idr << "\" is temporary" << endmsg; + } + } + + TObject* to = nullptr; + THistID hid; + // check to see if this hist is to be read in; + if ( !temp && m_files.find( stream )->second.second == READ ) { + if ( hist != 0 ) { + warning() << "Registering id: \"" << idr << "\" with non zero pointer!" << endmsg; + } + + hist = readHist_i<T>( idr ); + if ( hist == nullptr ) { + error() << "Unable to read in hist" << endmsg; + delete hist; + return StatusCode::FAILURE; + } + to = dynamic_cast<TObject*>( hist ); + hid = THistID( uid, temp, to, f, m_files.find( stream )->second.second ); + } else if ( !hist ) { + error() << "Unable to read in hist with id: \"" << idr << "\"" << endmsg; + delete hist; + return StatusCode::FAILURE; + } else { + to = dynamic_cast<TObject*>( hist ); + if ( to == nullptr ) { + error() << "Could not dcast to TObject. id: \"" << idr << "\"" << endmsg; + delete hist; + return StatusCode::FAILURE; + } + + auto oitr = m_tobjs.find( to ); + if ( oitr != m_tobjs.end() ) { + error() << "already registered id: \"" << idr << "\" with identifier \"" + << oitr->second.first->at( oitr->second.second ).id << "\"" << endmsg; + delete hist; + return StatusCode::FAILURE; + } + + hid = THistID( uid, temp, to, f, m_files.find( stream )->second.second ); + hid.shared = shared; + TDirectory* dir = changeDir( hid ); + + if ( dynamic_cast<TTree*>( hist ) ) { + dynamic_cast<TTree*>( hist )->SetDirectory( dir ); + } else if ( dynamic_cast<TH1*>( hist) ) { + dynamic_cast<TH1*>( hist )->SetDirectory( dir ); + } else if ( dynamic_cast<TGraph*>( hist ) ) { + dir->Append( hist ); + } else { + error() << "id: \"" << idr << "\" is not a TH, TTree, or TGraph. Attaching it to current dir." << endmsg; + dir->Append( hist ); + } + } + + std::string fname; + if ( !f ) { + fname = "none"; + } else { + fname = f->GetName(); + } + + debug() << "Registering" << ( shared ? " shared " : " " ) << System::typeinfoName( typeid( *hist ) ) << " title: \"" + << hist->GetTitle() << "\" id: \"" << uid + << "\" dir: " + // << hist->GetDirectory()->GetPath() << " " + << changeDir( hid )->GetPath() << " file: " << fname << endmsg; + + // create a mutex for all shared histograms + if ( shared ) { + hid.mutex = new histMut_t; + } + + if ( exists ) { + vhid_t* vi = uitr->second; + vi->push_back( hid ); + phid = &( vi->back() ); + + m_tobjs.emplace( to, std::pair<vhid_t*, size_t>( vi, vi->size() - 1 ) ); + } else { + vhid_t* vi = new vhid_t{hid}; + m_hlist.emplace( m_hlist.end(), vi ); + + phid = &( vi->back() ); + m_uids.emplace( uid, vi ); + m_ids.emplace( name, vi ); + + m_tobjs.emplace( to, std::pair<vhid_t*, size_t>( vi, 0 ) ); + } + + debug() << "regHist_i THistID: " << hid << endmsg; + + return StatusCode::SUCCESS; +} + +template <typename T> +T* THistSvcHLT::getHist_i( const std::string& id, const size_t& ind, bool quiet ) const +{ + // id starts with "/": unique + + GlobalDirectoryRestore restore( m_svcMut ); + + T* hist = nullptr; + const THistID* hid = nullptr; + size_t num = findHistID( id, hid, ind ); + if ( num == 0 ) { + // no matches found + if ( !quiet ) { + error() << "could not locate Hist with id \"" << id << "\"" << endmsg; + } + return nullptr; + } else if ( num > 1 ) { + if ( !quiet ) { + // return failure if trying to GET a single hist + error() << "Multiple matches with id \"" << id << "\"." + << " Further specifications required." << endmsg; + return nullptr; + } else { + info() << "Found multiple matches with id \"" << id << "\"" << endmsg; + // return first match if just INQUIRING (i.e. != nullptr) + hist = dynamic_cast<T*>( hid->obj ); + if ( hist == nullptr ) { + error() << "dcast failed, Hist id: \"" << id << "\"" << endmsg; + return nullptr; + } + } + } else { + hist = dynamic_cast<T*>( hid->obj ); + if ( hist == nullptr ) { + error() << "dcast failed, Hist id: \"" << id << "\"" << endmsg; + return nullptr; + } + verbose() << "found unique Hist title: \"" << hist->GetTitle() << "\" id: \"" << id << "\"" << endmsg; + } + + return hist; +} + +template <typename T> +T* THistSvcHLT::readHist_i( const std::string& id ) const +{ + GlobalDirectoryRestore restore( m_svcMut ); + + std::string idr( id ); + removeDoubleSlash( idr ); + + std::string stream, rem, dir, fdir, bdir, fdir2; + TFile* file = nullptr; + + if ( !findStream( idr, stream, rem, file ) ) { + return nullptr; + } + + if ( !file ) { + error() << "no associated file found" << endmsg; + return nullptr; + } + + file->cd( "/" ); + + fdir = idr; + bdir = stripDirectoryName( fdir ); + fdir2 = fdir; + while ( ( dir = stripDirectoryName( fdir ) ) != "" ) { + if ( !gDirectory->GetKey( dir.c_str() ) ) { + error() << "Directory \"" << fdir2 << "\" doesnt exist in " << file->GetName() << endmsg; + return nullptr; + } + gDirectory->cd( dir.c_str() ); + } + + TObject* to = nullptr; + gDirectory->GetObject( fdir.c_str(), to ); + + if ( !to ) { + error() << "Could not get obj \"" << fdir << "\" in " << gDirectory->GetPath() << endmsg; + return nullptr; + } + + T* hist = dynamic_cast<T*>( to ); + if ( hist == nullptr ) { + error() << "Could not convert \"" << idr << "\" to a " << System::typeinfoName( typeid( *hist ) ) << " as is a " + << to->IsA()->GetName() << endmsg; + return nullptr; + } + + if ( msgLevel( MSG::DEBUG ) ) { + debug() << "Read in " << hist->IsA()->GetName() << " \"" << hist->GetName() << "\" from file " << file->GetName() + << endmsg; + hist->Print(); + } + + return hist; +} + +template <typename T> +LockedHandle<T> THistSvcHLT::regShared_i( const std::string& id, std::unique_ptr<T> hist ) +{ + LockedHandle<T> lh( nullptr, nullptr ); + const THistID* hid = nullptr; + if ( findHistID( id, hid ) == 0 ) { + T* phist = hist.get(); + THistID* phid = nullptr; + if ( regHist_i( std::move(hist), id, true, phid ).isSuccess() ) { + lh.set( phist, phid->mutex ); + + } else { + error() << "regSharedHist: unable to register shared hist with id \"" << id << "\"" << endmsg; + } + } else { + if ( !hid->shared ) { + error() << "regSharedHist: previously register Hist with id \"" << id << "\" was not marked shared" << endmsg; + } + + if ( hist->Compare( hid->obj ) != 0 ) { + error() << "regSharedHist: Histogram " << id << " does not compare with " << hid << endmsg; + } else { + T* phist = dynamic_cast<T*>( hid->obj ); + if ( phist == 0 ) { + error() << "regSharedHist: unable to dcast retrieved shared hist \"" << id << "\" of type " + << hid->obj->IsA()->GetName() << " to requested type " << System::typeinfoName( typeid( T ) ) << endmsg; + } else { + lh.set( phist, hid->mutex ); + delete hist.release(); + } + } + } + return lh; +} + +template <typename T> +LockedHandle<T> THistSvcHLT::getShared_i( const std::string& name ) const +{ + GlobalDirectoryRestore restore( m_svcMut ); + + const THistID* hid = nullptr; + size_t i = findHistID( name, hid ); + + LockedHandle<T> hist( nullptr, nullptr ); + + if ( i == 1 ) { + if ( !hid->shared ) { + error() << "getSharedHist: found Hist with id \"" << name << "\", but it's not marked as shared" << endmsg; + return hist; + } + T* h1 = dynamic_cast<T*>( hid->obj ); + hist = LockedHandle<T>( h1, hid->mutex ); + + debug() << "getSharedHist: found THistID: " << *hid << endmsg; + } else if ( i == 0 ) { + error() << "no histograms matching id \"" << name << "\" found" << endmsg; + } else { + info() << "multiple matches for id \"" << name << "\" found [" << i << "], probably from different streams" + << endmsg; + } + return hist; +} + +#endif // GAUDISVC_THISTSVC_ICC diff --git a/HLT/Trigger/TrigControl/TrigServices/src/THistSvcHLT.icc.bak b/HLT/Trigger/TrigControl/TrigServices/src/THistSvcHLT.icc.bak deleted file mode 100644 index 45c635ac545365cbc98b7b409b21daec6fcaeca2..0000000000000000000000000000000000000000 --- a/HLT/Trigger/TrigControl/TrigServices/src/THistSvcHLT.icc.bak +++ /dev/null @@ -1,311 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -#ifndef THISTSVCHLT_ICC -#define THISTSVCHLT_ICC - -#ifndef GAUDIKERNEL_MSGSTREAM_H - #include "GaudiKernel/MsgStream.h" -#endif - -#include "GaudiKernel/System.h" - -#include <string> -#include <map> - -#include "TObject.h" -#include "TFile.h" - -template <typename T> -StatusCode THistSvcHLT::regHist_i(T* hist, const std::string& id) { - - GlobalDirectoryRestore restore; - - std::string idr(id); - removeDoubleSlash( idr ); - - if (idr.find("/") == idr.length()) { - m_log << MSG::ERROR << "Badly formed identifier \"" << idr << "\": " - << "Must not end with a /" << endmsg; - return StatusCode::FAILURE; - } - - - TFile *f = nullptr; - std::string stream,rem; - if (!findStream(idr, stream, rem, f)) { - m_log << MSG::ERROR << "Could not register id: \"" << idr << "\"" - << endmsg; - return StatusCode::FAILURE; - } - - std::string uid = "/" + stream + "/" + rem; - auto itr = m_uids.find(uid); - if (itr != m_uids.end()) { - m_log << MSG::ERROR << "already registered an object with identifier \"" - << idr << "\"" << endmsg; - return StatusCode::FAILURE; - } - - - bool temp = false; - if ( !f ) { - temp = true; - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "Historgram with id \"" << idr << "\" is temporary" - << endmsg; - } - - - TObject *to = nullptr; - THistID hid; - - // check to see if this hist is to be read in; - if (!temp && m_files.find(stream)->second.second == READ) { - - if (hist != 0) { - m_log << MSG::WARNING << "Registering id: \"" << idr - << "\" with non zero pointer!" << endmsg; - } - - if (readHist_i(idr,hist).isFailure()) { - m_log << MSG::ERROR << "Unable to read in hist" << endmsg; - return StatusCode::FAILURE; - } - to = dynamic_cast<TObject*>(hist); - hid = THistID(uid,temp,to,f,m_files.find(stream)->second.second); - - } else if (hist == 0) { - m_log << MSG::ERROR << "Unable to read in hist with id: \"" - << idr << "\"" << endmsg; - return StatusCode::FAILURE; - - } else { - - to = dynamic_cast<TObject*>(hist); - if (to == 0) { - m_log << MSG::ERROR << "Could not dcast to TObject. id: \"" << idr - << "\"" << endmsg; - return StatusCode::FAILURE; - } - - auto oitr = m_tobjs.find(to); - if (oitr != m_tobjs.end()) { - m_log << MSG::ERROR << "already registered id: \"" << idr - << "\" with identifier \"" << oitr->second.id << "\"" << endmsg; - return StatusCode::FAILURE; - } - - hid = THistID(uid,temp,to,f,m_files.find(stream)->second.second); - TDirectory* dir = changeDir(hid); - - if ( dynamic_cast<TTree*>(hist) ) { - dynamic_cast<TTree*>(hist)->SetDirectory(dir); - } else if ( dynamic_cast<TH1*>(hist) ) { - dynamic_cast<TH1*>(hist)->SetDirectory(dir); - } else if ( dynamic_cast<TGraph*>(hist) ) { - dir->Append(hist); - } else { - m_log << MSG::ERROR << "id: \"" << idr - << "\" is not a TH, TTree, or TGraph. Attaching it to current dir." - << endmsg; - dir->Append(hist); - } - - } - - std::string fname; - if ( !f ) { - fname = "none"; - } else { - fname = f->GetName(); - } - - if (m_log.level() <= MSG::DEBUG) - m_log << MSG::DEBUG << "Registering " << System::typeinfoName(typeid(*hist)) - << " title: \"" << hist->GetTitle() - << "\" id: \"" << uid << "\" dir: " - // << hist->GetDirectory()->GetPath() << " " - << changeDir(hid)->GetPath() - << " file: " << fname - << endmsg; - - m_ids.emplace(rem, hid); - m_uids[uid] = hid; - m_tobjs[to] = hid; - - return StatusCode::SUCCESS; - -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -template <typename T> -StatusCode -THistSvcHLT::getHist_i(const std::string& id, T*& hist, bool quiet) const { - // id starts with "/": unique - - GlobalDirectoryRestore restore; - - std::string idr(id); - removeDoubleSlash( idr ); - - if (idr.find("/") == 0) { - auto itr = m_uids.find(id); - if (itr == m_uids.end()) { - if (!quiet) { - m_log << MSG::ERROR << "Could not locate Hist with id \"" << idr << "\"" - << endmsg; - } - hist = nullptr; - return StatusCode::FAILURE; - } - - THistID hid = itr->second; - if (!quiet) { - hist = dynamic_cast<T*>(hid.obj); - if ( !hist ) { - m_log << MSG::ERROR << "dcast failed, Hist id: \"" << idr << "\"" - << endmsg; - return StatusCode::FAILURE; - } - if (m_log.level() <= MSG::VERBOSE) { - m_log << MSG::VERBOSE << "found unique Hist title: \"" - << hist->GetTitle() - << "\" id: \"" << idr << "\"" << endmsg; - } - } else { - if (m_log.level() <= MSG::VERBOSE) { - m_log << MSG::VERBOSE << "found unique Hist id: \"" << idr - << "\" type: \"" << hid.obj->IsA()->GetName() << "\"" - << endmsg; - } - } - - return StatusCode::SUCCESS; - - - // not necessarily unique - } else { - - auto mitr = m_ids.equal_range(idr); - - - if (mitr.first == mitr.second) { - m_log << MSG::ERROR << "Could not locate Hist with id \"" << idr << "\"" - << endmsg; - hist = nullptr; - return StatusCode::FAILURE; - } else { - - if (distance(mitr.first,mitr.second) == 1) { - THistID hid = mitr.first->second; - if (!quiet) { - hist = dynamic_cast<T*>(hid.obj); - if (hist == 0) { - m_log << MSG::ERROR << "dcast failed" << endmsg; - return StatusCode::FAILURE; - } - if (m_log.level() <= MSG::VERBOSE) { - m_log << MSG::VERBOSE << "found Hist title: \"" << hist->GetTitle() - << "\" id: \"" << idr << "\"" << endmsg; - } - } else { - if (m_log.level() <= MSG::VERBOSE) { - m_log << MSG::VERBOSE << "found Hist id: \"" << idr << "\" type: \"" - << hid.obj->IsA()->GetName() << "\"" - << endmsg; - } - } - return StatusCode::SUCCESS; - } else { - if (!quiet) { - // return failure if trying to GET a single hist - m_log << MSG::ERROR << "Multiple matches with id \"" << idr << "\"." - << " Further specifications required." - << endmsg; - hist = nullptr; - return StatusCode::FAILURE; - } else { - // return a SUCCESS if just INQUIRING - m_log << MSG::INFO << "Found multiple matches with id \"" << idr - << "\"" << endmsg; - hist = nullptr; - return StatusCode::SUCCESS; - } - } - } - } -} - -//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// - -template <typename T> -StatusCode -THistSvcHLT::readHist_i(const std::string& id, T*& hist) const { - - GlobalDirectoryRestore restore; - - std::string idr(id); - removeDoubleSlash( idr ); - - std::string stream, rem, dir, fdir, bdir, fdir2; - TFile *file; - - if (!findStream(idr, stream, rem, file) ) { - return StatusCode::FAILURE; - } - - if ( !file ) { - m_log << MSG::ERROR << "no associated file found" << endmsg; - return StatusCode::FAILURE; - } - - file->cd("/"); - - fdir = idr; - bdir = dirname(fdir); - fdir2 = fdir; - while ( (dir=dirname(fdir)) != "" ) { - if (! gDirectory->GetKey(dir.c_str())) { - m_log << MSG::ERROR << "Directory \"" << fdir2 << "\" doesnt exist in " - << file->GetName() << endmsg; - return StatusCode::FAILURE; - } - gDirectory->cd(dir.c_str()); - } - - TObject *to=nullptr; - gDirectory->GetObject(fdir.c_str(), to); - - if ( !to ) { - m_log << MSG::ERROR << "Could not get obj \"" << fdir << "\" in " - << gDirectory->GetPath() << endmsg; - return StatusCode::FAILURE; - } - - - - hist = dynamic_cast<T*>(to); - if ( !hist ) { - m_log << MSG::ERROR << "Could not convert \"" << idr << "\" to a " - << System::typeinfoName(typeid(*hist)) << " as is a " - << to->IsA()->GetName() - << endmsg; - return StatusCode::FAILURE; - } - - - if (m_log.level() <= MSG::DEBUG) { - m_log << MSG::DEBUG << "Read in " << hist->IsA()->GetName() << " \"" - << hist->GetName() << "\" from file " - << file->GetName() << endmsg; - hist->Print(); - } - - return StatusCode::SUCCESS; - -} - -#endif diff --git a/HLT/Trigger/TrigControl/TrigServices/src/TrigMonTHistSvc.cxx.bak b/HLT/Trigger/TrigControl/TrigServices/src/TrigMonTHistSvc.cxx similarity index 81% rename from HLT/Trigger/TrigControl/TrigServices/src/TrigMonTHistSvc.cxx.bak rename to HLT/Trigger/TrigControl/TrigServices/src/TrigMonTHistSvc.cxx index ad52ec62fcf32f0c462e92a31dfc365694431d5b..18d55195216e4de726513dad35c0860f9898959e 100644 --- a/HLT/Trigger/TrigControl/TrigServices/src/TrigMonTHistSvc.cxx.bak +++ b/HLT/Trigger/TrigControl/TrigServices/src/TrigMonTHistSvc.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration */ @@ -113,57 +113,59 @@ StatusCode TrigMonTHistSvc::regHist(const std::string& id) { return THistSvcHLT::regHist(id); } -StatusCode TrigMonTHistSvc::regHist(const std::string& id, TH1* hist) { - return regHist_i(hist, id); -} -StatusCode TrigMonTHistSvc::regHist(const std::string& id, TH2* hist) { - return regHist_i(hist, id); +StatusCode TrigMonTHistSvc::regHist(const std::string& id, std::unique_ptr<TH1> hist) { + return regHist_i(std::move(hist), id, false); } -StatusCode TrigMonTHistSvc::regHist(const std::string& id, TH3* hist) { - return regHist_i(hist, id); +StatusCode TrigMonTHistSvc::regHist(const std::string& id, std::unique_ptr<TH1> hist, TH1* hist_ptr) { + // This is only to support a common use case where the histogram is used after its registration + if ( hist_ptr != nullptr ) { + hist_ptr = hist.get(); + } + return regHist_i( std::move( hist ), id, false ); +} + +StatusCode TrigMonTHistSvc::regHist(const std::string& id, TH1* hist_ptr) { + std::unique_ptr<TH1> hist( hist_ptr ); + return regHist_i( std::move( hist ), id, false ); } + + StatusCode TrigMonTHistSvc::regTree(const std::string& id) { return THistSvcHLT::regTree(id); } -StatusCode TrigMonTHistSvc::regTree(const std::string&, TTree* hist) { - // we do not support the trees; then let's make them not to be memory consumers +StatusCode TrigMonTHistSvc::regTree(const std::string&, std::unique_ptr<TTree> tree) { + // we do not support the trees; then let's make them not to be memory consumers ATH_MSG_WARNING("The ROOT TTree is not supported by this service" - << " TTree \"" << hist->GetName() << "\" will be unsaved but will not consume all memory as well" + << " TTree \"" << tree->GetName() << "\" will be unsaved but will not consume all memory as well" ); - hist->SetCircular(1); + tree->SetCircular(1); return StatusCode::SUCCESS; } -StatusCode TrigMonTHistSvc::getHist(const std::string& id, TH1*& hist) const { - return THistSvcHLT::getHist(id, hist); -} - - -StatusCode TrigMonTHistSvc::getHist(const std::string& id, TH2*& hist) const { - return THistSvcHLT::getHist(id, hist); -} - - -StatusCode TrigMonTHistSvc::getHist(const std::string& id, TH3*& hist) const { - return THistSvcHLT::getHist(id, hist); +StatusCode TrigMonTHistSvc::regTree(const std::string& id, TTree* tree_ptr) { + std::unique_ptr<TTree> tree( tree_ptr ); + return regTree(id, std::move(tree)); } -StatusCode TrigMonTHistSvc::getTree(const std::string& id, TTree*& hist) const { - return THistSvcHLT::getTree(id, hist); +StatusCode TrigMonTHistSvc::getTree(const std::string&, TTree*&) const { + ATH_MSG_WARNING("The ROOT TTree is not supported by this service"); + return StatusCode::SUCCESS; } -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// Needs proper implementation -// StatusCode TrigMonTHistSvc::regGraph(const std::string& id) { return THistSvcHLT::regGraph(id); } +StatusCode TrigMonTHistSvc::regGraph(const std::string&, std::unique_ptr<TGraph>) { + ATH_MSG_WARNING("The regGraph is not suported by this service"); + return StatusCode::SUCCESS; +} + StatusCode TrigMonTHistSvc::regGraph(const std::string&, TGraph*) { ATH_MSG_WARNING("The regGraph is not suported by this service"); return StatusCode::SUCCESS; @@ -174,24 +176,30 @@ StatusCode TrigMonTHistSvc::getGraph(const std::string& id, TGraph*& g) const { } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -template <typename T> StatusCode TrigMonTHistSvc::regHist_i(T* hist, const std::string& id) { +template <typename T> StatusCode TrigMonTHistSvc::regHist_i(std::unique_ptr<T> hist_unique, const std::string& id, bool /*shared*/) { - std::string regid; - if ( isObjectAllowed(id, hist).isFailure() ) { + // We need to pass ownership to the hist registry now + T* hist = nullptr; + if( hist_unique.get() != nullptr ) { + hist = hist_unique.release(); + } + + std::string regid; + if ( isObjectAllowed(id, hist).isFailure() ) { return StatusCode::FAILURE; - } - regid = id; - - if (hist->Class()->InheritsFrom(TH1::Class())) { - hltinterface::IInfoRegister::instance()->registerTObject(name(), regid, hist); - ATH_MSG_DEBUG("Histogram " << hist->GetName() - << " registered under " << regid << " " << name()); - } else { - ATH_MSG_ERROR("Trying to register " << hist->ClassName() - << " but this does not inherit from TH1 histogram"); - return StatusCode::SUCCESS; - } + } + regid = id; + + if (hist->Class()->InheritsFrom(TH1::Class())) { + hltinterface::IInfoRegister::instance()->registerTObject(name(), regid, hist); + ATH_MSG_DEBUG("Histogram " << hist->GetName() + << " registered under " << regid << " " << name()); + } else { + ATH_MSG_ERROR("Trying to register " << hist->ClassName() + << " but this does not inherit from TH1 histogram"); return StatusCode::SUCCESS; + } + return StatusCode::SUCCESS; } StatusCode TrigMonTHistSvc::deReg(TObject* optr) { @@ -271,7 +279,7 @@ StatusCode TrigMonTHistSvc::getTTrees(const std::string&, TList &) const { // internal methods //========================================================================== // -StatusCode TrigMonTHistSvc::isObjectAllowed(std::string path, const TObject *o) { +StatusCode TrigMonTHistSvc::isObjectAllowed(std::string path, const TObject *o) { boost::cmatch what; @@ -379,3 +387,8 @@ StatusCode TrigMonTHistSvc::getTTrees(const std::string&, TList &, bool, bool) { bool TrigMonTHistSvc::exists( const std::string& name ) const { return THistSvcHLT::exists(name); } + +StatusCode TrigMonTHistSvc::notSupported() const { + ATH_MSG_WARNING("Shared histograms are not yet supported in TrigMonTHistSvc"); + return StatusCode::SUCCESS; +} diff --git a/HLT/Trigger/TrigControl/TrigServices/src/TrigMonTHistSvc.h.bak b/HLT/Trigger/TrigControl/TrigServices/src/TrigMonTHistSvc.h similarity index 69% rename from HLT/Trigger/TrigControl/TrigServices/src/TrigMonTHistSvc.h.bak rename to HLT/Trigger/TrigControl/TrigServices/src/TrigMonTHistSvc.h index ea1aa382df8e5ec1fa53b6b261a7a94dd22a5bc1..fe23b7e7c6d2b7f82d4146726fbdd6a6c6d10b1a 100644 --- a/HLT/Trigger/TrigControl/TrigServices/src/TrigMonTHistSvc.h.bak +++ b/HLT/Trigger/TrigControl/TrigServices/src/TrigMonTHistSvc.h @@ -1,7 +1,7 @@ // -*- c++ -*- /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration */ #ifndef TRIGMONTHISTSVC_THISTSVC_H @@ -33,9 +33,6 @@ class TTree; #include <boost/regex.hpp> -// Forward declarations -template <class TYPE> class SvcFactory; - class TrigMonTHistSvc: virtual public THistSvcHLT, public AthMessaging { @@ -44,30 +41,27 @@ public: // fwd compat w/ gaudi-21 using AthMessaging::msg; + TrigMonTHistSvc(const std::string& name, ISvcLocator *svc ); + virtual ~TrigMonTHistSvc(); + + virtual StatusCode queryInterface( const InterfaceID& riid, + void** ppvInterface ); + // implemenataion of the interface from TrigNetTHistSvc virtual StatusCode initialize(); virtual StatusCode reinitialize(); virtual StatusCode finalize(); - // Query the interfaces. - virtual StatusCode queryInterface( const InterfaceID& riid, - void** ppvInterface ); - - virtual StatusCode regHist(const std::string& name); + virtual StatusCode regHist(const std::string& name, std::unique_ptr<TH1> hist); + virtual StatusCode regHist(const std::string& name, std::unique_ptr<TH1> hist, TH1* hist_ptr); virtual StatusCode regHist(const std::string& name, TH1*); - virtual StatusCode regHist(const std::string& name, TH2*); - virtual StatusCode regHist(const std::string& name, TH3*); - - virtual StatusCode getHist(const std::string& name, TH1*&) const; - virtual StatusCode getHist(const std::string& name, TH2*&) const; - virtual StatusCode getHist(const std::string& name, TH3*&) const; virtual StatusCode regTree(const std::string& name); + virtual StatusCode regTree(const std::string& name, std::unique_ptr<TTree>); virtual StatusCode regTree(const std::string& name, TTree*); virtual StatusCode getTree(const std::string& name, TTree*&) const; - // new since Gaudi 0.16.1.11 virtual StatusCode deReg(TObject* obj); //<! very slow virtual StatusCode deReg(const std::string& name); //<! use this instead @@ -80,14 +74,19 @@ public: virtual StatusCode getTTrees(TDirectory *td, TList &) const; virtual StatusCode getTTrees(const std::string& name, TList &) const; - // new since Gaudi 19 virtual StatusCode regGraph(const std::string& name); + virtual StatusCode regGraph(const std::string& name, std::unique_ptr<TGraph>); virtual StatusCode regGraph(const std::string& name, TGraph*); virtual StatusCode getGraph(const std::string& name, TGraph*&) const; - TrigMonTHistSvc(const std::string& name, ISvcLocator *svc ); - - // new since Gaudi 20 + virtual StatusCode regShared( const std::string&, std::unique_ptr<TH1>, LockedHandle<TH1>& ) { return notSupported(); } + virtual StatusCode regShared( const std::string&, std::unique_ptr<TH2>, LockedHandle<TH2>& ) { return notSupported(); } + virtual StatusCode regShared( const std::string&, std::unique_ptr<TH3>, LockedHandle<TH3>& ) { return notSupported(); } + virtual StatusCode regShared( const std::string&, std::unique_ptr<TGraph>, LockedHandle<TGraph>& ) { return notSupported(); } + virtual StatusCode getShared( const std::string&, LockedHandle<TH1>& ) const { return notSupported(); } + virtual StatusCode getShared( const std::string&, LockedHandle<TH2>& ) const { return notSupported(); } + virtual StatusCode getShared( const std::string&, LockedHandle<TH3>& ) const { return notSupported(); } + virtual StatusCode getShared( const std::string&, LockedHandle<TGraph>& ) const { return notSupported(); } virtual StatusCode getTHists(TDirectory *td, TList &, bool recurse=false) const; @@ -110,15 +109,16 @@ public: virtual bool exists(const std::string& name) const; protected: - StatusCode isObjectAllowed(std::string path, const TObject *o); + StatusCode isObjectAllowed(std::string path, const TObject *o); StatusCode getTHists_i(const std::string& name, TList &) const; - virtual ~TrigMonTHistSvc(); private: template <typename T> - StatusCode regHist_i(T* hist, const std::string& name); + StatusCode regHist_i(std::unique_ptr<T> hist, const std::string& name, bool shared); + StatusCode notSupported() const; + std::string m_excludeType; std::string m_includeType; std::string m_excludeName; diff --git a/HLT/Trigger/TrigControl/TrigServices/src/TrigPreFlightCheck.cxx b/HLT/Trigger/TrigControl/TrigServices/src/TrigPreFlightCheck.cxx deleted file mode 100644 index 2f890c6dd803b0d1c7ff4231784e57ff40ac7b97..0000000000000000000000000000000000000000 --- a/HLT/Trigger/TrigControl/TrigServices/src/TrigPreFlightCheck.cxx +++ /dev/null @@ -1,87 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -/** - * @file TrigPreFlightCheck.cxx - * @brief Does some generic checks to make sure we can run the HLT - * @author Frank Winklmeier - * - * $Id: TrigPreFlightCheck.cxx 5 2013-05-14 10:33:04Z ricab $ - */ - -#include "TrigPreFlightCheck.h" - -#include <boost/tokenizer.hpp> -#include <boost/filesystem.hpp> - -#include <stdlib.h> - -using namespace std; -namespace fs = boost::filesystem; - -//========================================================================= -// Standard methods -//========================================================================= -TrigPreFlightCheck::TrigPreFlightCheck(const std::string &type, - const std::string &name, - const IInterface *parent) - : AthAlgTool(type, name, parent) -{ - // No abstract interface - declareInterface<TrigPreFlightCheck>(this); - - declareProperty("ReleaseDirs", - m_releaseDirs, - "Directories within LD_LIBRARY_PATH to check for existence"); -} - - -TrigPreFlightCheck::~TrigPreFlightCheck() -{} - - -StatusCode TrigPreFlightCheck::initialize() -{ - return StatusCode::SUCCESS; -} - -StatusCode TrigPreFlightCheck::check(const MSG::Level& errLvl) -{ - // Only one check so far - return checkRelease(errLvl); -} - - -StatusCode TrigPreFlightCheck::checkRelease(const MSG::Level& errLvl) -{ - const char* ld_lib_path = getenv("LD_LIBRARY_PATH"); - if ( ld_lib_path==0 ) { - msg() << errLvl << "Cannot read LD_LIBRARY_PATH" << endmsg; - return StatusCode::FAILURE; - } - - typedef boost::tokenizer<boost::char_separator<char> > Tokenizer; - string s(ld_lib_path); - Tokenizer tok(s, boost::char_separator<char>(":")); - - // Loop over elements of LD_LIBRARY_PATH - for (Tokenizer::iterator it = tok.begin(); it!=tok.end(); ++it) { - - // Loop over directories to check - for (vector<string>::const_iterator dir = m_releaseDirs.begin(); - dir != m_releaseDirs.end(); ++dir) { - - if ( it->find(*dir)!=string::npos ) { - if ( fs::exists(*it) ) { - ATH_MSG_DEBUG("Checking " << (*it) << ": OK"); - } - else { - msg() << errLvl << (*it) << " does not exist" << endmsg; - return StatusCode::FAILURE; - } - } - } - } - return StatusCode::SUCCESS; -} diff --git a/HLT/Trigger/TrigControl/TrigServices/src/TrigPreFlightCheck.h b/HLT/Trigger/TrigControl/TrigServices/src/TrigPreFlightCheck.h deleted file mode 100644 index cf4f301d2abf1cf1fa796d717b8dc04e1d2399b9..0000000000000000000000000000000000000000 --- a/HLT/Trigger/TrigControl/TrigServices/src/TrigPreFlightCheck.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -#ifndef TRIGSERVICES_TRIGPREFLIGHTCHECK_H -#define TRIGSERVICES_TRIGPREFLIGHTCHECK_H -/** - * @file TrigPreFlightCheck.h - * @brief Does some generic checks to make sure we can run the HLT - * @author Frank Winklmeier - * - * $Id: TrigPreFlightCheck.h 5 2013-05-14 10:33:04Z ricab $ - */ - -// STL includes -#include <string> -#include <vector> - -// Framework includes -#include "AthenaBaseComps/AthAlgTool.h" -#include "GaudiKernel/StatusCode.h" - -/** - * @brief Tool to do some basic checks ensuring the HLT is usable - * - * The tool has several checkXYZ() methods each returning a StatusCode for - * the specific check it is doing. In addition, the check() method performs - * all the checks and returns the logical AND of the individual checks. - */ -class TrigPreFlightCheck : public AthAlgTool { - -public: - - TrigPreFlightCheck(const std::string &type, const std::string &name, const IInterface *parent); - virtual ~TrigPreFlightCheck(); - - static const InterfaceID& interfaceID(); - virtual StatusCode initialize(); - - /** - * @brief Check whether the relase is installed properly - * - * @param errLvl Message level used for failure messages - * @return SUCCESS Release properly installed - * FAILURE Some parts of the release is missing - */ - StatusCode checkRelease(const MSG::Level& errLvl); - - /** - * @brief Perform all checks - * - * @param errLvl Message level used for failure messages - * @return SUCCESS All checks OK - * FAILURE At least one check failed - */ - StatusCode check(const MSG::Level& errLvl); - -private: - /** Directories to check for existence in checkRelease() */ - std::vector<std::string> m_releaseDirs; -}; - - -inline const InterfaceID& TrigPreFlightCheck::interfaceID() -{ - static const InterfaceID IID("TrigPreFlightCheck", 1, 0); - return IID; -} - -#endif diff --git a/HLT/Trigger/TrigControl/TrigServices/src/components/TrigServices_entries.cxx b/HLT/Trigger/TrigControl/TrigServices/src/components/TrigServices_entries.cxx index 50cf70610717330d35d53b910828e939123167b3..a1845cfcb1fce4bb6a81d0a34f558b2956f3103e 100644 --- a/HLT/Trigger/TrigControl/TrigServices/src/components/TrigServices_entries.cxx +++ b/HLT/Trigger/TrigControl/TrigServices/src/components/TrigServices_entries.cxx @@ -1,18 +1,16 @@ #include "TrigServices/TrigMessageSvc.h" -//#include "../TrigMonTHistSvc.h" +#include "../TrigMonTHistSvc.h" #include "TrigServices/HltEventLoopMgr.h" #include "TrigServices/HltROBDataProviderSvc.h" #include "TrigServices/TrigIS.h" #include "TrigServices/TrigISHelper.h" -#include "../TrigPreFlightCheck.h" #include "../TrigCOOLUpdateHelper.h" DECLARE_COMPONENT( TrigMessageSvc ) -//DECLARE_COMPONENT( TrigMonTHistSvc ) +DECLARE_COMPONENT( TrigMonTHistSvc ) DECLARE_COMPONENT( TrigIS ) DECLARE_COMPONENT( HltEventLoopMgr ) DECLARE_COMPONENT( HltROBDataProviderSvc ) DECLARE_COMPONENT( TrigISHelper ) -DECLARE_COMPONENT( TrigPreFlightCheck ) DECLARE_COMPONENT( TrigCOOLUpdateHelper )