diff --git a/Control/SGMon/SGAudSvc/CMakeLists.txt b/Control/SGMon/SGAudSvc/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..05221c1806f2124a68d158aa6870629ec4a3e325 --- /dev/null +++ b/Control/SGMon/SGAudSvc/CMakeLists.txt @@ -0,0 +1,29 @@ +################################################################################ +# Package: SGAudSvc +################################################################################ + +# Declare the package name: +atlas_subdir( SGAudSvc ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( PUBLIC + Control/AthenaBaseComps + Control/AthenaKernel + Control/SGMon/SGAudCore + GaudiKernel + PRIVATE + Control/StoreGate ) + +# Component(s) in the package: +atlas_add_component( SGAudSvc + src/*.cxx + src/components/*.cxx + LINK_LIBRARIES AthenaBaseComps AthenaKernel SGAudCore GaudiKernel StoreGateLib SGtests ) + +# Install files from the package: +atlas_install_headers( SGAudSvc ) +atlas_install_scripts( share/SGout2dot.py ) + +# Aliases: +atlas_add_alias( SGout2dot "SGout2dot.py" ) + diff --git a/Control/SGMon/SGAudSvc/SGAudSvc/SGAudSvc.h b/Control/SGMon/SGAudSvc/SGAudSvc/SGAudSvc.h new file mode 100644 index 0000000000000000000000000000000000000000..6ca8008517eab0736498eb63125ac0eee9c473fa --- /dev/null +++ b/Control/SGMon/SGAudSvc/SGAudSvc/SGAudSvc.h @@ -0,0 +1,164 @@ +///////////////////////// -*- C++ -*- ///////////////////////////// + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// SGAudSvc.h +// Header file for class SGAudSvc +// Author: Ilija Vukotic <ivukotic@cern.ch> +/////////////////////////////////////////////////////////////////// +#ifndef SGMONITORING_SGAUDSVC_H +#define SGMONITORING_SGAUDSVC_H + +// STL includes +#include <string> +#include <iosfwd> +#include <map> +#include <set> +#include <fstream> + +// HepMC / CLHEP includes + +// FrameWork includes +#include "AthenaBaseComps/AthService.h" +#include "GaudiKernel/ServiceHandle.h" +#include "GaudiKernel/ToolHandle.h" +#include "GaudiKernel/IIncidentListener.h" +#include "GaudiKernel/MsgStream.h" +#include "GaudiKernel/Algorithm.h" +#include "AthenaKernel/IClassIDSvc.h" + +#include "SGAudCore/ISGAudSvc.h" + +// Forward declaration +class ISvcLocator; +template <class TYPE> class SvcFactory; +class IChronoStatSvc; +class IAlgContextSvc; +class AlgContextSvc; + +class SGAudSvc : virtual public ISGAudSvc, + virtual public IIncidentListener, + public AthService +{ + +protected: + + friend class SvcFactory<SGAudSvc>; + + +public: + + /// Constructor with parameters: + SGAudSvc( const std::string& name, ISvcLocator* pSvcLocator ); + + /// Destructor: + virtual ~SGAudSvc(); + + /// Gaudi Service Implementation + //@{ + StatusCode initialize(); + StatusCode finalize(); + virtual StatusCode queryInterface( const InterfaceID& riid, void** ppvInterface ); + //@} + + static const InterfaceID& interfaceID(); + + +/** incident service handle for EndEvent. Calls monitor. There should be more elegant way to get number of events passed. +*/ + void handle( const Incident& incident ); + + // do the auditing, called from DataStore.cxx + virtual void SGAudit(const std::string& key, const CLID& id, + const int& fnc, const int& store_id); + + +/** +* @brief Gets name of curently running algorithm from AlgContextSvc. +*/ + bool SGGetCurrentAlg(); +/** +* @brief For implementing custom increased granularity auditing of for instance tools. +*/ + void setFakeCurrentAlg(const std::string&); +/** +* @brief For implementing custom increased granularity auditing of for instance tools. +*/ + void clearFakeCurrentAlg(); + + private: + + /// Default constructor: + SGAudSvc(); + + void SGAudRETRIEVE(std::string SGobject); + void SGAudRECORD(std::string SGobject); + + void getNobj(std::string name); + void addRead(); + void addWrite(); + + /// just counts events. called at EndEvent incident + void monitor(); + + void writeJSON(); + + /////////////////////////////////////////////////////////////////// + // Private data: + /////////////////////////////////////////////////////////////////// + private: + + /// MsgStream for talking with the outside world + MsgStream m_msg; + + /// Pointer to the @c AlgContextScv + IAlgContextSvc *p_algCtxSvc; + IClassIDSvc* m_pCID; + + /// Name of the output file + std::string m_outFileName, m_allFileName, m_sumFileName; + + /// Whether to ignore fake current algs + bool m_ignoreFakeAlgs; + + /// Whether to use CLID or Data Obj Name in JSON output file + bool m_useCLID; + + /// Vector of accessed SG objects names + std::vector<std::string> m_vObj; + /// Vector of names of algorithms accessing SG + std::vector<std::string> m_vAlg; + /// map counting Reads of each object by each algorithm. + std::map<int,int> m_timesRead; + /// map counting Writes of each object by each algorithm. + std::map<int,int> m_timesWritten; + std::string m_currAlg; + std::string m_currObj; + std::string m_fakeCurrAlg; + int m_nCurrAlg; + int m_nCurrObj; + int m_nEvents; + int m_startEvent; + + // map<"alg_name", set<"cid/key"> > + typedef std::map<std::string, std::set<std::string> > DataMap; + DataMap m_read; + DataMap m_write; + + std::ofstream m_ofa, m_ofs; + bool m_inExec; +}; + + +/////////////////////////////////////////////////////////////////// +/// Inline methods: +/////////////////////////////////////////////////////////////////// + +inline const InterfaceID& SGAudSvc::interfaceID() +{ + return ISGAudSvc::interfaceID(); +} + +#endif diff --git a/Control/SGMon/SGAudSvc/cmt/requirements b/Control/SGMon/SGAudSvc/cmt/requirements new file mode 100644 index 0000000000000000000000000000000000000000..3b70a3755a41a23b49346591786f9b47c3171861 --- /dev/null +++ b/Control/SGMon/SGAudSvc/cmt/requirements @@ -0,0 +1,31 @@ +package SGAudSvc + +author Ilija Vukotic <ivukotic@cern.ch> + +use AtlasPolicy AtlasPolicy-* +use AthenaKernel AthenaKernel-* Control +use AthenaBaseComps AthenaBaseComps-* Control + +## For Gaudi tools, services and objects +use GaudiInterface GaudiInterface-* External + +## Put here your package dependencies... +use SGAudCore SGAudCore-* Control/SGMon + +private +use StoreGate StoreGate-* Control + +public +branches src src/components doc share + + +## make a component library +library SGAudSvc *.cxx components/*.cxx + +apply_pattern component_library +#apply_pattern declare_joboptions files="*.py" +apply_pattern declare_python_modules files="*.py" + +apply_pattern declare_scripts files="SGout2dot.py" + +alias SGout2dot SGout2dot.py diff --git a/Control/SGMon/SGAudSvc/doc/mainpage.h b/Control/SGMon/SGAudSvc/doc/mainpage.h new file mode 100644 index 0000000000000000000000000000000000000000..9f5cedb871d1c07a9f8d6edcf261798d51edfc6e --- /dev/null +++ b/Control/SGMon/SGAudSvc/doc/mainpage.h @@ -0,0 +1,32 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** +@mainpage SGAudSvc +@author ivukotic@cern.ch + +@section MyPackageIntro Introduction + +This package gives a graphical representation of algorithms accessing StoreGate. +SGAudSvc instruments retrieve and record functions of StoreGate and from there gets name of object accessed. Upon getting an object name it asks AlgContexSvc for a name of current algorithm. At the end of run, ascii file is produced (default name SGAudSvc.out). +This file is further used by SGout2dot.py to produce .dot file. +To obtain ps file from dot file you may use:'dot -Tps graph1.dot -o graph1.ps'. Still it is nicer to use Graphviz to directly see the plots and if needed edit them by hand. + +Please keep in mind that data are not collected for the first three events. + + +@ref used_MyPackage + +@ref requirements_MyPackage +*/ + +/** +@page used_MyPackage Used Packages +@htmlinclude used_packages.html +*/ + +/** +@page requirements_MyPackage Requirements +@include requirements +*/ diff --git a/Control/SGMon/SGAudSvc/share/SGout2dot.py b/Control/SGMon/SGAudSvc/share/SGout2dot.py new file mode 100755 index 0000000000000000000000000000000000000000..01537df5262e3b1c12c0b7c43b2a9a4b23b60794 --- /dev/null +++ b/Control/SGMon/SGAudSvc/share/SGout2dot.py @@ -0,0 +1,277 @@ +#!/usr/bin/env python +#TODO : prune standalone alg and objects +# remove number of read write +# remove monitoring, L1, CTP +# arrow show be single side ! +# @file: SGout2dot.py +# @purpose: read a SGAudSvc produced file and make dot file. +# @author: Ilija Vukotic <ivukotic@cern.ch> +# @date: May 2007 +# +# @example: +# +# checkFile SGAudSvc.out + +__version__ = "$Revision: 1.2 $" +__author__ = "Ilija Vukotic <ivukotic@cern.ch>" + +import sys +import os +import shutil +import glob + +# some configuration booleans +debug=True +debugRemove=False +drawNReadWrite=False # if draw on each line the number of read and write + + +#Algorithms to be masked. Might need to be tuned +lRemove=[] +lRemove+= ["MboyMuonChamberT0"] +lRemove+= ['Stream','StreamAOD','noKey',"basic_"] +lRemove+= ["Trig","HLT","EF","L1","Mon","CTP","RoIB","GlobalManager"] +#lRemove += ['LArRawChannelCollection','TileRawChannelCollection','DetStatusAlg','DetectorStatus','_Data','_Link'] +#lRemove+= ['EventSelector','Input'] +#lRemove+= ['iPatStatistics'] +def chLabel(inpVal): + result=inpVal + result=result.replace('>','_GT_') + result=result.replace('<','_LT_') + result=result.replace('::','_') + result=result.replace('.','_') + result=result.replace('+','_') + return result + + + +def isNumb(inpVal): + result = False + try: + stripped = str(int(inpVal)) + result=True + except: + result=False + return result + +def toRemove(inpVal): + result=False + if isNumb(inpVal)==True: + if debugRemove: + print "remove ", inpVal, "is a number" + result=True + for thing in lRemove: + if inpVal.count(thing)>0: + if debugRemove: + print "remove ", inpVal ,"since it contains", thing + result=True + return result + +nArgs= len (sys.argv) +outFN="dot.dot" +inFN="" +if nArgs==1: + print "Usage: SGout2dot.py input_filename [output dot file]" + sys.exit() +if nArgs>1: + print "Input file",sys.argv[1] + inFN=sys.argv[1] +if nArgs==3: + print "Output file",sys.argv[2] + outFN=sys.argv[2] +try: + fi = open (inFN) +except: + print "No such file!" + sys.exit() + +fo = open (outFN, 'w' ) + +lines = fi.readlines() +fi.close() + +# get number of algs +line=lines.pop(0) +words=line.split(' ') +nAlgs=int(words[1]) +print '%(a)d algorithms found'%{'a':nAlgs} + +#read all algs +#note that algs to be removed cannot be masked before reading the alg <-> obj relation +algs=[] +nGoodAlgs=0 +for i in range(nAlgs): + line=lines.pop(0).strip('\n') + line=line.replace('/','_') + algs.append(line) + if toRemove(line): + print "alg %s to be removed" % line + else: + nGoodAlgs+=1 + +print " number of good algs ",nGoodAlgs," bad algs ",nAlgs-nGoodAlgs +if debug: + print algs + +# get number of objs +line=lines.pop(0) +words=line.split(' ') +nObjs=int(words[1]) +print '%(a)d objects found'%{'a':nObjs} + +# get all object names, and replace possible annoying characters +#note that objs to be removed cannot be masked before reading the alg <-> obj relation +objs=[] +nGoodObjs=0 +for i in range(nObjs): + line=lines.pop(0).strip('\n') + line=line.replace('/','_') + line=line.replace('<','LT') + line=line.replace('>','GT') + line=line.replace('+','_') + objs.append(line) + if toRemove(line): + print "obj %s to be removed" % line + else: + nGoodObjs+=1 + +print " number of good objs ",nGoodObjs," bad objs ",nObjs-nGoodObjs +if debug: + print objs + +fo.write("// %s algorithms and %s objects \n" % (nGoodAlgs,nGoodObjs)) + + +#write out dot file header +fo.write("digraph SGAudSvc{\nrankdir=LR;\n") # begining and graph stuff +fo.write("ratio=0.7;\nnodesep=0.05;\n") +fo.write("subgraph c_0{\nnode[style=filled,color=red];\n") # alg subgraph +fo.write("label=\"Algs READING\";\ncolor=red;\n") + +# get the relations betwen alg and obj +# TODO number write or read not kept at this point +objsWrittenByAlg={} #A->many O (A write O may read it as well) +objsReadByAlg={} #many O->A (A read O may do not read it ) +algsWritingObj={} #many A->O (A write O may read it as well). +algsReadingObj={} # O->many A (A does not write O) +for alg in algs: + line=lines.pop(0) + words=line.strip('\n').split('\t') + for obj in objs: + rw=words.pop(0).split(':') + reads=int(rw[0]) + writes=int(rw[1]) + if reads==0 and writes==0: + continue + if toRemove(obj) or toRemove(alg): + continue + #print alg,obj,reads, writes + + if writes==0 and reads>0: + if not obj in algsReadingObj.keys(): + algsReadingObj[obj]=[] + algsReadingObj[obj]+=[(alg,reads,writes)] + if not alg in objsReadByAlg.keys(): + objsReadByAlg[alg]=[] + objsReadByAlg[alg]+=[obj] + elif writes>0: + if not obj in algsWritingObj.keys(): + algsWritingObj[obj]=[] + algsWritingObj[obj]+=[alg] + + if not alg in objsWrittenByAlg.keys(): + objsWrittenByAlg[alg]=[] + objsWrittenByAlg[alg]+=[(obj,reads,writes)] + + +#write out all algorithms, but only the ones that have at least one connection (and are not masked) +for alg in algs: + if toRemove(alg)==False: + if alg in objsWrittenByAlg or alg in objsReadByAlg: + towrite='a_%(a)s [label=\"%(a)s\"];\n'%{'a':chLabel(alg),'b':alg} + fo.write(towrite) + else: + print "alg %s masked because not connected" % alg + +fo.write("}\n\nsubgraph c_1{\nnode[style=filled,shape=box];\ncolor=green;label=\"Objects\";\n") +#write out all objecs +for obj in objs: + if toRemove(obj)==False: + if obj in algsWritingObj or obj in algsReadingObj: + towrite='o_%(a)s [label=\"%(b)s\"];\n'%{'a':chLabel(obj),'b':obj} + fo.write(towrite) + else: + print "obj %s masked because not connected" % obj +fo.write("}\n\n") + + +if debug: + print " " + print "objsWrittenByAlg:", objsWrittenByAlg + print " " + print "objsReadByAlg:", objsReadByAlg + print " " + print "algsWritingObj:", algsWritingObj + print " " + print "algsReadingObj:", algsReadingObj + print " " + +#write the connection a to obj +for alg in objsWrittenByAlg.keys(): + for objrec in objsWrittenByAlg[alg]: + obj=objrec[0] + reads=objrec[1] + writes=objrec[2] + towrite='a_%(ALG)s -> o_%(OBJ)s [ '%{'ALG':chLabel(alg),'OBJ':chLabel(obj)} + if drawNReadWrite: + if reads==0: + towrite+='label=\"%s\" ' % writes + else: + # if read in addition to write, write both number of read and write plus double arrow + # this happen when an alg writes an object and read it back to modify it + towrite+='label=\"w:%(WRITES)s r:%(READS)s\" arrowtail=\"normal\" '%{'WRITES':writes,'READS':reads} + else: + if reads>0: # double arrow + towrite+='arrowtail=\"normal\" ' + towrite+='];\n' + fo.write(towrite) + +#write the connection obj to alg +# by definition only read no write +for obj in algsReadingObj.keys(): + for algrec in algsReadingObj[obj]: + alg=algrec[0] + reads=algrec[1] + writes=algrec[2] + + towrite='o_%(OBJ)s -> a_%(ALG)s [ '%{'ALG':chLabel(alg),'OBJ':chLabel(obj)} + if drawNReadWrite: + towrite+='label=\"%s\" ' % reads + towrite+='];\n' + fo.write(towrite) + +## # get the relations betwen alg and obj, and write them out +## for alg in algs: +## alg=chLabel(alg) +## line=lines.pop(0) +## words=line.strip('\n').split('\t') +## for obj in objs: +## rw=words.pop(0).split(':') +## reads=rw[0] +## writes=rw[1] +## #print alg,obj,reads, writes +## if toRemove(obj)==False and toRemove(alg)==False: +## if int(writes)>0 and int(reads)>0: +## towrite='a_%(ALG)s -> o_%(OBJ)s [label=\"w:%(WRITES)s r:%(READS)s\" '%{'ALG':alg,'OBJ':obj,'WRITES':writes,'READS':reads} +## towrite+='arrowtail=\"normal\"];\n' +## fo.write(towrite) +## else: +## if int(writes)>0: +## towrite='a_%(ALG)s -> o_%(OBJ)s [label=\"%(WRITES)s\"];\n'%{'ALG':alg,'OBJ':obj,'WRITES':writes} +## fo.write(towrite) +## if int(reads)>0: +## towrite='o_%(OBJ)s -> a_%(ALG)s [label=\"%(READS)s\"];\n'%{'ALG':alg,'OBJ':obj,'READS':reads} +## fo.write(towrite) + +fo.write("}") +fo.close() diff --git a/Control/SGMon/SGAudSvc/share/checkFileSG.py b/Control/SGMon/SGAudSvc/share/checkFileSG.py new file mode 100755 index 0000000000000000000000000000000000000000..20095fe7ed59edf3ddb6b5fee64ed1c8ae0c9273 --- /dev/null +++ b/Control/SGMon/SGAudSvc/share/checkFileSG.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python + +# @file: checkFileSG.py +# @purpose: answers queries on a SGAudSvc produced file +# @author: Ilija Vukotic <ivukotic@cern.ch> +# @date: October 2007 +# +# @example: +# +# checkFileSG SGAudSvc.out + +__version__ = "$Revision: 1.1 $" +__author__ = "Ilija Vukotic <ivukotic@cern.ch>" + +import sys +import os +import shutil +import glob + +lRemove = ['_Data','_Link','noKey','HLTAuto','CBNT_'] + +def toSkip(inpName): + for comp in lRemove: + if inpName.count(comp)>0: + return True + return False + +def toRemove(inpVal): + result=False + if isNumb(inpVal)==True: + print "remove ", inpVal, "is a number" + result=True + for thing in lRemove: + if inpVal.count(thing)>0: + print "remove ", inpVal ,"since it contains", thing + result=True + return result + +def findMatches(iAlg, iObj, F, Fa, Fo): + n=0 + print "---- algos -----" + for alg in iAlg: #----------------> find matching algos + if alg.count(F)>0 and not toSkip(alg): + Fa.append(alg) + print alg + n+=1 + print '---- objects ----' + for obj in iObj: #---------------> find matching objects + if obj.count(F)>0 and not toSkip(obj): + Fobj.append(obj) + print obj + n+=1 + print '-----------------' + return n + +nArgs= len (sys.argv) +inFN='' +if nArgs==1: + print "Usage: checkFileSG.py input_filename " + sys.exit() +if nArgs>1: + print "Input file: ",sys.argv[1] + inFN=sys.argv[1] +try: + fi = open (inFN) +except: + print "No such file!" + sys.exit() + + +lines = fi.readlines() +fi.close() + +#=================================================================== +line=lines.pop(0) +words=line.split(' ') +nAlgs=int(words[1]) +print '%(a)d algorithms found'%{'a':nAlgs} + +algs=[] +for i in range(nAlgs): # -------------------> reading alg names + line=lines.pop(0).strip('\n') + line=line.replace('/','_') + algs.append(line) + +#print algs + +line=lines.pop(0) +words=line.split(' ') +nObjs=int(words[1]) +print '%(a)d objects found'%{'a':nObjs} + +objs=[] +for i in range(nObjs): # ----------------> reading object names + line=lines.pop(0).strip('\n') + line=line.replace('/','_') + line=line.replace('<','LT') + line=line.replace('>','GT') + objs.append(line) +#================================================================== + + +Falg=[]; Fobj=[] +LF=raw_input('Please enter algorithm or SG object name: ') + + +while (findMatches(algs, objs, LF, Falg, Fobj)!=1): #----------> getting single input + LF=raw_input('Please enter algorithm or SG object name. To exit type \'x\' : ') + if LF=='x': + sys.exit(0) + Falg=[];Fobj=[] + + + +print 'Calculating calls for:',LF,' ' +if len(Falg)>0: + #print 'algorithms', Falg + ind=algs.index(Falg[0])+1 + for i in range(ind): + line=lines.pop(0) + #print line + words=line.strip('\n').split('\t') + for obj in objs: + rw=words.pop(0).split(':') + #print rw + reads=int(rw[0]) + writes=int(rw[1]) + if (reads+writes)>0: + print 'Object:',obj, "has been accessed",reads,"times and written",writes,"times." + +else: + #print 'objects',Fobj + ind=objs.index(Fobj[0]) + for i in range(len(algs)): + line=lines.pop(0) + words=line.strip('\n').split('\t') + rw=words[ind].split(':') + reads=int(rw[0]) + writes=int(rw[1]) + if (reads+writes)>0: + print 'Algorithm',algs[i],'accessed object',reads,'times and wrote it',writes,'times' + +sys.exit(0) diff --git a/Control/SGMon/SGAudSvc/src/SGAudSvc.cxx b/Control/SGMon/SGAudSvc/src/SGAudSvc.cxx new file mode 100644 index 0000000000000000000000000000000000000000..8b2e42758df2043a3255bea508365c23407cf329 --- /dev/null +++ b/Control/SGMon/SGAudSvc/src/SGAudSvc.cxx @@ -0,0 +1,523 @@ +///////////////////////// -*- C++ -*- ///////////////////////////// + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// SGAudSvc.cxx +// Implementation file for class SGAudSvc +// Author: Ilija Vukotic<ivukotic@cern.ch> +/////////////////////////////////////////////////////////////////// + + +// STL includes +#include <sstream> +#include <fstream> +#include <vector> +#include <set> +#include <utility> + +// FrameWork includes +#include "GaudiKernel/Property.h" +#include "GaudiKernel/SvcFactory.h" +#include "GaudiKernel/IIncidentSvc.h" +#include "GaudiKernel/Incident.h" +#include "GaudiKernel/IAlgContextSvc.h" + +// StoreGate includes +#include "StoreGate/StoreGateSvc.h" +#include "StoreGate/DataHandle.h" + +// SGAudSvc includes +#include "SGAudSvc/SGAudSvc.h" +/////////////////////////////////////////////////////////////////// +// Public methods: +/////////////////////////////////////////////////////////////////// + +/*----------------------------------------------------------------------------*/ +// Constructors +//////////////// +SGAudSvc::SGAudSvc( const std::string& name, ISvcLocator* pSvcLocator ) : + AthService ( name, pSvcLocator ), + m_msg ( msgSvc(), name ), + p_algCtxSvc(0), m_pCID(0), m_useCLID(true), + m_nCurrAlg(0), + m_nCurrObj(0), + m_nEvents(0), m_startEvent(3), m_inExec(false) +{ + // + // Property declaration + // + declareProperty( "OutFileName", m_outFileName = "SGAudSvc.out", + "Name of the output file to hold SGAudSvc data" ); + + declareProperty( "FullFileName", m_allFileName = "", + "Name of the output file to hold the full SG aud data"); + + declareProperty( "SummaryFileName", m_sumFileName = "", + "Name of the output file to hold the summary output in json format"); + + declareProperty( "IgnoreFakeAlgs", m_ignoreFakeAlgs = false, + "Set to ignore any attempts to override current-alg" ); + + declareProperty( "StartEvent", m_startEvent = 3, + "Event number to start recording data" ); + + declareProperty( "UseCLID", m_useCLID = true, + "Use CLID or DataObj name in Summary File" ); +} + +/*----------------------------------------------------------------------------*/ +// Destructor +/////////////// +SGAudSvc::~SGAudSvc() +{ + m_msg << MSG::DEBUG << "Calling destructor" << endreq; +} + +/*----------------------------------------------------------------------------*/ + +// Athena Algorithm's Hooks +//////////////////////////// +StatusCode +SGAudSvc::initialize() { + + // initialize MsgStream + m_msg.setLevel( m_outputLevel.value() ); + + m_msg << MSG::INFO << "Initializing " << name() << "..." << endreq; + + if ( AthService::initialize().isFailure() ) { + m_msg << MSG::ERROR << "Could not intialize base class !!" << endreq; + return StatusCode::FAILURE; + } + + static const bool CREATEIF(true); + + if ( service("AlgContextSvc",p_algCtxSvc,CREATEIF).isFailure() ) { + m_msg << MSG::ERROR << "Unable to retrieve the AlgContextSvc" << endreq; + return StatusCode::FAILURE; + } + + assert(p_algCtxSvc); + + if ( service("ClassIDSvc",m_pCID,CREATEIF).isFailure() ) { + m_msg << MSG::ERROR << "Unable to retrieve the ClassIDSvc" << endmsg; + return StatusCode::FAILURE; + } + + if (m_allFileName != "") { + m_ofa.open(m_allFileName.c_str()); + } + + if (m_sumFileName != "") { + m_ofs.open(m_sumFileName.c_str()); + } + + // Set to be listener for end-of-event + ServiceHandle<IIncidentSvc> incSvc( "IncidentSvc", this->name() ); + if ( !incSvc.retrieve().isSuccess() ) { + m_msg << MSG::ERROR << "Unable to get the IncidentSvc" << endreq; + return StatusCode::FAILURE; + } + incSvc->addListener( this, IncidentType::BeginRun ); + incSvc->addListener( this, IncidentType::BeginEvent ); + incSvc->addListener( this, IncidentType::EndEvent ); + + return StatusCode::SUCCESS; +} + +/*----------------------------------------------------------------------------*/ + +StatusCode +SGAudSvc::finalize() { + + m_msg << MSG::INFO << "Finalizing " << name() <<"..."<< endreq; + + if (m_vAlg.size()==0) { + m_msg << MSG::WARNING<<"No data gathered. This might be because you did not run over at least 3 events."<<endreq; + return StatusCode::SUCCESS; + } + + m_msg << MSG::INFO<<"Writing output to: "<<m_outFileName<<endreq; + std::ofstream f( m_outFileName.c_str() ); + + f << "Algs: " << m_vAlg.size() << std::endl; + std::vector<std::string>::iterator i; + for (i=m_vAlg.begin();i<m_vAlg.end();i++) { + f << (*i) << std::endl; + } + + f << "Obj: "<< m_vObj.size()<<std::endl; + for (i=m_vObj.begin();i<m_vObj.end();i++) { + f << (*i) << std::endl; + } + + + for (unsigned int w=0;w<m_vAlg.size();w++){ + for(unsigned int q=0;q<m_vObj.size();q++){ + int oaHash=q*1000 + w; + if (m_timesRead.find(oaHash)==m_timesRead.end()) + f << "0:"; + else + f << m_timesRead.find(oaHash)->second << ":"; + if (m_timesWritten.find(oaHash)==m_timesWritten.end()) + f << "0\t"; + else + f << m_timesWritten.find(oaHash)->second << "\t"; + } + f << std::endl; + } + + f.close(); + + if (m_ofa.is_open()) m_ofa.close(); + + if (m_ofs.is_open()) { + + writeJSON(); + + m_ofs.close(); + } + + + return StatusCode::SUCCESS; +} + +/*----------------------------------------------------------------------------*/ + +// Query the interfaces. +StatusCode +SGAudSvc::queryInterface(const InterfaceID& riid, void** ppvInterface) +{ + if ( ISGAudSvc::interfaceID().versionMatch(riid) ) { + *ppvInterface = dynamic_cast<ISGAudSvc*>(this); + } else { + // Interface is not directly available : try out a base class + return AthService::queryInterface(riid, ppvInterface); + } + addRef(); + return StatusCode::SUCCESS; +} + +/////////////////////////////////////////////////////////////////// +// Const methods: +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +// Non-const methods: +/////////////////////////////////////////////////////////////////// + +/*----------------------------------------------------------------------------*/ + +void +SGAudSvc::handle( const Incident& inc ) +{ + if ( m_msg.level() <= MSG::VERBOSE ) { + m_msg << MSG::VERBOSE << "Entering handle(): " << endreq + << " Incidence type: " << inc.type() << endreq + << " from: " << inc.source() << endreq; + } + + if (inc.type() == IncidentType::BeginEvent) { + if (m_ofa.is_open()) + m_ofa << "---- BEGIN EVENT " << m_nEvents << " ----" << std::endl; + m_inExec = true; + + } + + // Performing performance-monitoring for EndEvent incident + if ( inc.type() == IncidentType::EndEvent ) { + monitor(); + + if (m_ofa.is_open()) + m_ofa << "---- END EVENT " << m_nEvents << " ----" << std::endl; + m_inExec = false; + + } + + // Performing performance-monitoring for BeginRun incident + // at this point everybody has been initialized, we can harvest performance + // data for the initialize step. + + if ( inc.type() == IncidentType::BeginRun ) { + monitor(); + } + + return; +} + +/////////////////////////////////////////////////////////////////// +// Protected methods: +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +// Const methods: +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +// Non-const methods: +/////////////////////////////////////////////////////////////////// + +/*----------------------------------------------------------------------------*/ + +void +SGAudSvc::monitor(){ + m_nEvents++; + return; +} + +/*----------------------------------------------------------------------------*/ + +void +SGAudSvc::SGAudRETRIEVE(std::string SGobject){ + // if (m_nEvents<3) return; + if (SGobject=="") SGobject="noKey"; + bool isAnumb=true; + for (unsigned int i = 0; i < SGobject.length(); i++) + if (!std::isdigit(SGobject[i])){ + isAnumb=false; + break; + } + + if (!isAnumb){ + if (m_currObj==SGobject) + addRead(); + else { + getNobj(SGobject); + addRead(); + } + } + return; +} + +/*----------------------------------------------------------------------------*/ + +void +SGAudSvc::SGAudRECORD(std::string SGobject){ + // if (m_nEvents<3) return; + if (SGobject=="") SGobject="noKey"; + for (unsigned int i = 0; i < SGobject.length(); i++) + if (!std::isdigit(SGobject[i])){ + //isAnumb=false; + break; + } + + if (m_currObj==SGobject) + addWrite(); + else { + getNobj(SGobject); + addWrite(); + } + + return; +} + +/*----------------------------------------------------------------------------*/ +void +SGAudSvc::SGAudit(const std::string& key, const CLID& id, + const int& typ, const int& store_id) { + + // we can sometimes get here really early, before initialization. + if (m_pCID == 0) { return; } + + bool a = SGGetCurrentAlg(); + + if (m_nEvents >= m_startEvent && store_id == 0 && a) { + if (typ == 0) { + SGAudRETRIEVE(key); + } else { + SGAudRECORD(key); + } + } + + std::string idname; + + if (m_ofa.is_open() || ( m_ofs.is_open() && ! m_useCLID ) ) { + if( ! m_pCID->getTypeNameOfID(id,idname).isSuccess()) { + std::ostringstream ost; + ost << id; + idname = ost.str(); + } + } + + if (m_ofa.is_open()) { + m_ofa << ( (typ == 1) ? "RECORD" : "RETRIEVE" ) << " clid: " << id + << " | "; + + m_ofa << idname; + + m_ofa << " key: " << key << " alg: " << m_currAlg + << " store: " << store_id + << std:: endl; + } + + // store stuff for the summary + + if (!m_ofs.is_open()) return; + + if (m_nEvents < m_startEvent || !m_inExec) return; + + if (m_currAlg == "----") return; + + std::string kk; + if (m_useCLID) { + std::ostringstream ost; + ost << id << "/" << key; + kk = ost.str(); + } else { + kk = idname + "/" + key; + } + + DataMap::iterator itr; + if (typ == 0) { + itr = m_read.find(m_currAlg); + if (itr != m_read.end()) { + itr->second.insert(kk); + } else { + m_read[m_currAlg] = std::set<std::string> ( {kk} ); + } + } else { + itr = m_write.find(m_currAlg); + if (itr != m_write.end()) { + itr->second.insert(kk); + } else { + m_write[m_currAlg] = std::set<std::string> ( {kk} ); + } + } +} + +/*----------------------------------------------------------------------------*/ + +bool +SGAudSvc::SGGetCurrentAlg(){ + + IAlgorithm *asdf = p_algCtxSvc->currentAlg(); + if (!asdf || m_nEvents==0) { // to skip before first event + m_currAlg="----"; + m_nCurrAlg=-1; + return false; + } + std::string name = asdf->name(); + + if ( !m_ignoreFakeAlgs && !m_fakeCurrAlg.empty() ) + name=m_fakeCurrAlg; + + if (name!=m_currAlg){ + std::vector<std::string>::iterator i; + int index=0; + for (i=m_vAlg.begin();i<m_vAlg.end();i++){ + if (*i==name) { + m_nCurrAlg=index; + m_currAlg=name; + return true; + } + index++; + } + m_vAlg.push_back(name); + m_nCurrAlg=index; + m_currAlg=name; + return true; + } + return true; +} + +/*----------------------------------------------------------------------------*/ + +void +SGAudSvc::getNobj(std::string name){ + std::vector<std::string>::iterator i; + int index=0; + for (i=m_vObj.begin();i<m_vObj.end();i++){ + if (*i==name) { + m_nCurrObj=index; + m_currObj=name; + return; + } + index++; + } + m_vObj.push_back(name); + m_nCurrObj=index; + m_currObj=name; +return; +} + +/*----------------------------------------------------------------------------*/ + +void +SGAudSvc::addRead(){ + int oaHash=m_nCurrObj*1000 + m_nCurrAlg; + if (m_timesRead.end()!=m_timesRead.find(oaHash)){ + m_timesRead.find(oaHash)->second++; + } + else{ + std::pair<int,int> p(oaHash,1); + m_timesRead.insert(p); + } + return; +} + +/*----------------------------------------------------------------------------*/ + +void +SGAudSvc::addWrite(){ + int oaHash=m_nCurrObj*1000 + m_nCurrAlg; + if (m_timesWritten.end()!=m_timesWritten.find(oaHash)){ + m_timesWritten.find(oaHash)->second++; + } + else{ + std::pair<int,int> p(oaHash,1); + m_timesWritten.insert(p); + } + return; +} + +/*----------------------------------------------------------------------------*/ + +void +SGAudSvc::setFakeCurrentAlg( const std::string& s ) { m_fakeCurrAlg=s; } + +/*----------------------------------------------------------------------------*/ + +void +SGAudSvc::clearFakeCurrentAlg() { m_fakeCurrAlg.clear(); } + +/*----------------------------------------------------------------------------*/ + +void +SGAudSvc::writeJSON() { + + DataMap::const_iterator itr; + std::set<std::string>::const_iterator it2; + std::vector<std::string>::const_iterator ia; + + m_ofs << "{ \"algorithms\" : [" << std::endl; + for (ia = m_vAlg.begin(); ia != m_vAlg.end(); ++ia) { + m_ofs << " {" << std::endl; + m_ofs << " \"name\" : \"" << *ia << "\"," << std::endl; + m_ofs << " \"inputs\" : ["; + + itr = m_read.find(*ia); + if (itr != m_read.end()) { + for (it2 = itr->second.begin(); it2 != itr->second.end(); ++it2) { + if (it2 != itr->second.begin()) m_ofs << ","; + m_ofs << "\"" << *it2 << "\""; + } + } + m_ofs << "]," << std::endl; + + m_ofs << " \"outputs\" : ["; + + itr = m_write.find(*ia); + if (itr != m_write.end()) { + for (it2 = itr->second.begin(); it2 != itr->second.end(); ++it2) { + if (it2 != itr->second.begin()) m_ofs << ","; + m_ofs << "\"" << *it2 << "\""; + } + } + m_ofs << "]," << std::endl; + m_ofs << " }," << std::endl; + } + m_ofs << " ]" << std::endl << "}" << std::endl; + +} diff --git a/Control/SGMon/SGAudSvc/src/components/SGAudSvc_entries.cxx b/Control/SGMon/SGAudSvc/src/components/SGAudSvc_entries.cxx new file mode 100644 index 0000000000000000000000000000000000000000..719c6b7d6b39793760226428e3d54a05cf7bdcf9 --- /dev/null +++ b/Control/SGMon/SGAudSvc/src/components/SGAudSvc_entries.cxx @@ -0,0 +1,13 @@ +#include "SGAudSvc/SGAudSvc.h" +//#include "../PerfMonAuditor.h" + +#include "GaudiKernel/DeclareFactoryEntries.h" + +DECLARE_SERVICE_FACTORY( SGAudSvc ) +//DECLARE_AUDITOR_FACTORY( PerfMonAuditor ) + +DECLARE_FACTORY_ENTRIES( SGAudSvc ) { + DECLARE_SERVICE( SGAudSvc ) +// DECLARE_AUDITOR( PerfMonAuditor ) + +} diff --git a/Control/SGMon/SGAudSvc/src/components/SGAudSvc_load.cxx b/Control/SGMon/SGAudSvc/src/components/SGAudSvc_load.cxx new file mode 100644 index 0000000000000000000000000000000000000000..7412b1c6c75fa7f65130fed74ea6f3cff5e4a7e9 --- /dev/null +++ b/Control/SGMon/SGAudSvc/src/components/SGAudSvc_load.cxx @@ -0,0 +1,3 @@ +#include "GaudiKernel/LoadFactoryEntries.h" + +LOAD_FACTORY_ENTRIES( SGAudSvc )