The Gaudi Framework  v36r1 (3e2fb5a8)
THistSvc.icc
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 #ifndef GAUDISVC_THISTSVC_ICC
12 #define GAUDISVC_THISTSVC_ICC
13 
14 #include <map>
15 #include <string>
16 
17 #include "TFile.h"
18 #include "TObject.h"
19 
20 #ifndef GAUDIKERNEL_MSGSTREAM_H
21 # include "GaudiKernel/MsgStream.h"
22 #endif
23 
24 #include "GaudiKernel/System.h"
25 
26 template <typename T>
28  THistID* hid = nullptr;
29  return regHist_i( std::move( hist ), id, shared, hid );
30 }
31 
32 template <typename T>
33 StatusCode THistSvc::regHist_i( std::unique_ptr<T> hist_unique, const std::string& id, bool shared, THistID*& phid ) {
35  phid = nullptr;
36 
37  // It is sad that we lose propper memory management here
38  T* hist = nullptr;
39  if ( hist_unique.get() != nullptr ) { hist = hist_unique.release(); }
40  debug() << "regHist_i obj: " << hist << " id: " << id << " s: " << shared << endmsg;
41 
42  std::string idr( id );
43  removeDoubleSlash( idr );
44 
45  if ( idr.find( "/" ) == idr.length() ) {
46  error() << "Badly formed identifier \"" << idr << "\": "
47  << "Must not end with a /" << endmsg;
48  delete hist;
49  return StatusCode::FAILURE;
50  }
51 
52  TFile* f = nullptr;
54  if ( !findStream( idr, stream, name, f ) ) {
55  error() << "Could not register id: \"" << idr << "\"" << endmsg;
56  delete hist;
57  return StatusCode::FAILURE;
58  }
59 
60  std::string uid = "/" + stream + "/" + name;
61 
62  uidMap_t::iterator uitr = m_uids.find( uid );
63  bool exists( false );
64  if ( uitr != m_uids.end() ) {
65  exists = true;
66  TObject* t1 = uitr->second->at( 0 ).obj;
67  if ( hist->Compare( t1 ) != 0 ) {
68  error() << "previously registered object with identifier \"" << uid << "\" does not compare to this one"
69  << endmsg;
70  delete hist;
71  return StatusCode::FAILURE;
72  } else {
73  debug() << "previously registered id \"" << uid << "\": num " << uitr->second->size() << endmsg;
74  }
75  }
76 
77  bool temp = false;
78  if ( !f ) {
79  temp = true;
80  if ( msgLevel( MSG::DEBUG ) ) { debug() << "Historgram with id \"" << idr << "\" is temporary" << endmsg; }
81  }
82 
83  TObject* to = nullptr;
84  THistID hid;
85  // check to see if this hist is to be read in;
86  if ( !temp && m_files.find( stream )->second.second == READ ) {
87  if ( hist != 0 ) { warning() << "Registering id: \"" << idr << "\" with non zero pointer!" << endmsg; }
88 
89  hist = readHist_i<T>( idr );
90  if ( hist == nullptr ) {
91  error() << "Unable to read in hist" << endmsg;
92  delete hist;
93  return StatusCode::FAILURE;
94  }
95  to = dynamic_cast<TObject*>( hist );
96  hid = THistID( uid, temp, to, f, m_files.find( stream )->second.second );
97  } else if ( !hist ) {
98  error() << "Unable to read in hist with id: \"" << idr << "\"" << endmsg;
99  delete hist;
100  return StatusCode::FAILURE;
101  } else {
102  to = dynamic_cast<TObject*>( hist );
103  if ( to == nullptr ) {
104  error() << "Could not dcast to TObject. id: \"" << idr << "\"" << endmsg;
105  delete hist;
106  return StatusCode::FAILURE;
107  }
108 
109  auto oitr = m_tobjs.find( to );
110  if ( oitr != m_tobjs.end() ) {
111  error() << "already registered id: \"" << idr << "\" with identifier \""
112  << oitr->second.first->at( oitr->second.second ).id << "\"" << endmsg;
113  delete hist;
114  return StatusCode::FAILURE;
115  }
116 
117  const auto findF = m_files.find( stream );
118  hid = ( findF != m_files.end() ? THistID( uid, temp, to, f, findF->second.second ) : THistID( uid, temp, to, f ) );
119 
120  hid.shared = shared;
121  TDirectory* dir = changeDir( hid );
122 
123  if ( TTree* tree = dynamic_cast<TTree*>( hist ) ) {
124  tree->SetDirectory( dir );
125  } else if ( TH1* th1 = dynamic_cast<TH1*>( hist ) ) {
126  th1->SetDirectory( dir );
127  } else if ( TEfficiency* teff = dynamic_cast<TEfficiency*>( hist ) ) {
128  teff->SetDirectory( dir );
129  } else if ( dynamic_cast<TGraph*>( hist ) ) {
130  dir->Append( hist );
131  } else {
132  error() << "id: \"" << idr << "\" is not a TH, TTree, TGraph, or TEfficiency. Attaching it to current dir."
133  << endmsg;
134  dir->Append( hist );
135  }
136  }
137 
138  std::string fname;
139  if ( !f ) {
140  fname = "none";
141  } else {
142  fname = f->GetName();
143  }
144 
145  debug() << "Registering" << ( shared ? " shared " : " " ) << System::typeinfoName( typeid( *hist ) ) << " title: \""
146  << hist->GetTitle() << "\" id: \"" << uid
147  << "\" dir: "
148  // << hist->GetDirectory()->GetPath() << " "
149  << changeDir( hid )->GetPath() << " file: " << fname << endmsg;
150 
151  // create a mutex for all shared histograms
152  if ( shared ) { hid.mutex = new histMut_t; }
153 
154  if ( exists ) {
155  vhid_t* vi = uitr->second;
156  vi->push_back( hid );
157  phid = &( vi->back() );
158 
159  m_tobjs.emplace( to, std::pair<vhid_t*, size_t>( vi, vi->size() - 1 ) );
160  } else {
161  vhid_t* vi = new vhid_t{hid};
162  m_hlist.emplace( m_hlist.end(), vi );
163 
164  phid = &( vi->back() );
165  m_uids.emplace( uid, vi );
166  m_ids.emplace( name, vi );
167 
169  }
170 
171  debug() << "regHist_i THistID: " << hid << endmsg;
172 
173  return StatusCode::SUCCESS;
174 }
175 
176 template <typename T>
177 T* THistSvc::getHist_i( const std::string& id, const size_t& ind, bool quiet ) const {
178  // id starts with "/": unique
179 
180  GlobalDirectoryRestore restore( m_svcMut );
181 
182  T* hist = nullptr;
183  const THistID* hid = nullptr;
184  size_t num = findHistID( id, hid, ind );
185  if ( num == 0 ) {
186  // no matches found
187  if ( !quiet ) { error() << "could not locate Hist with id \"" << id << "\"" << endmsg; }
188  return nullptr;
189  } else if ( num > 1 ) {
190  if ( !quiet ) {
191  // return failure if trying to GET a single hist
192  error() << "Multiple matches with id \"" << id << "\"."
193  << " Further specifications required." << endmsg;
194  return nullptr;
195  } else {
196  info() << "Found multiple matches with id \"" << id << "\"" << endmsg;
197  // return first match if just INQUIRING (i.e. != nullptr)
198  hist = dynamic_cast<T*>( hid->obj );
199  if ( hist == nullptr ) {
200  error() << "dcast failed, Hist id: \"" << id << "\"" << endmsg;
201  return nullptr;
202  }
203  }
204  } else {
205  hist = dynamic_cast<T*>( hid->obj );
206  if ( hist == nullptr ) {
207  error() << "dcast failed, Hist id: \"" << id << "\"" << endmsg;
208  return nullptr;
209  }
210  verbose() << "found unique Hist title: \"" << hist->GetTitle() << "\" id: \"" << id << "\"" << endmsg;
211  }
212 
213  return hist;
214 }
215 
216 template <typename T>
217 T* THistSvc::readHist_i( const std::string& id ) const {
218  GlobalDirectoryRestore restore( m_svcMut );
219 
220  std::string idr( id );
221  removeDoubleSlash( idr );
222 
223  std::string stream, rem, dir, fdir, bdir, fdir2;
224  TFile* file = nullptr;
225 
226  if ( !findStream( idr, stream, rem, file ) ) { return nullptr; }
227 
228  if ( !file ) {
229  error() << "no associated file found" << endmsg;
230  return nullptr;
231  }
232 
233  file->cd( "/" );
234 
235  fdir = idr;
236  bdir = stripDirectoryName( fdir );
237  fdir2 = fdir;
238  while ( ( dir = stripDirectoryName( fdir ) ) != "" ) {
239  if ( !gDirectory->GetKey( dir.c_str() ) ) {
240  error() << "Directory \"" << fdir2 << "\" doesnt exist in " << file->GetName() << endmsg;
241  return nullptr;
242  }
243  gDirectory->cd( dir.c_str() );
244  }
245 
246  TObject* to = nullptr;
247  gDirectory->GetObject( fdir.c_str(), to );
248 
249  if ( !to ) {
250  error() << "Could not get obj \"" << fdir << "\" in " << gDirectory->GetPath() << endmsg;
251  return nullptr;
252  }
253 
254  T* hist = dynamic_cast<T*>( to );
255  if ( hist == nullptr ) {
256  error() << "Could not convert \"" << idr << "\" to a " << System::typeinfoName( typeid( *hist ) ) << " as is a "
257  << to->IsA()->GetName() << endmsg;
258  return nullptr;
259  }
260 
261  if ( msgLevel( MSG::DEBUG ) ) {
262  debug() << "Read in " << hist->IsA()->GetName() << " \"" << hist->GetName() << "\" from file " << file->GetName()
263  << endmsg;
264  hist->Print();
265  }
266 
267  return hist;
268 }
269 
270 template <typename T>
272  LockedHandle<T> lh( nullptr, nullptr );
273  const THistID* hid = nullptr;
274  if ( findHistID( id, hid ) == 0 ) {
275  T* phist = hist.get();
276  THistID* phid = nullptr;
277  if ( regHist_i( std::move( hist ), id, true, phid ).isSuccess() ) {
278  lh.set( phist, phid->mutex );
279 
280  } else {
281  error() << "regSharedHist: unable to register shared hist with id \"" << id << "\"" << endmsg;
282  }
283  } else {
284  if ( !hid->shared ) {
285  error() << "regSharedHist: previously register Hist with id \"" << id << "\" was not marked shared" << endmsg;
286  }
287 
288  if ( hist->Compare( hid->obj ) != 0 ) {
289  error() << "regSharedHist: Histogram " << id << " does not compare with " << hid << endmsg;
290  } else {
291  T* phist = dynamic_cast<T*>( hid->obj );
292  if ( phist == 0 ) {
293  error() << "regSharedHist: unable to dcast retrieved shared hist \"" << id << "\" of type "
294  << hid->obj->IsA()->GetName() << " to requested type " << System::typeinfoName( typeid( T ) ) << endmsg;
295  } else {
296  lh.set( phist, hid->mutex );
297  delete hist.release();
298  }
299  }
300  }
301  return lh;
302 }
303 
304 template <typename T>
306  GlobalDirectoryRestore restore( m_svcMut );
307 
308  const THistID* hid = nullptr;
309  size_t i = findHistID( name, hid );
310 
311  LockedHandle<T> hist( nullptr, nullptr );
312 
313  if ( i == 1 ) {
314  if ( !hid->shared ) {
315  error() << "getSharedHist: found Hist with id \"" << name << "\", but it's not marked as shared" << endmsg;
316  return hist;
317  }
318  T* h1 = dynamic_cast<T*>( hid->obj );
319  hist = LockedHandle<T>( h1, hid->mutex );
320 
321  debug() << "getSharedHist: found THistID: " << *hid << endmsg;
322  } else if ( i == 0 ) {
323  error() << "no histograms matching id \"" << name << "\" found" << endmsg;
324  } else {
325  info() << "multiple matches for id \"" << name << "\" found [" << i << "], probably from different streams"
326  << endmsg;
327  }
328  return hist;
329 }
330 
331 #endif // GAUDISVC_THISTSVC_ICC
MSG::DEBUG
@ DEBUG
Definition: IMessageSvc.h:25
THistSvc::readHist_i
T * readHist_i(const std::string &name) const
Definition: THistSvc.icc:217
THistSvc::regShared_i
LockedHandle< T > regShared_i(const std::string &id, std::unique_ptr< T > hist)
Definition: THistSvc.icc:271
Write.stream
stream
Definition: Write.py:31
std::string
STL class.
THistSvc::histMut_t
std::mutex histMut_t
Definition: THistSvc.h:206
std::move
T move(T... args)
System.h
std::pair< vhid_t *, size_t >
std::vector
STL class.
std::string::find
T find(T... args)
std::string::length
T length(T... args)
LockedHandle::set
void set(T *ptr, MutexType *mut)
Definition: LockedHandle.h:45
std::unordered_map::emplace
T emplace(T... args)
std::unique_ptr::get
T get(T... args)
std::unique_ptr::release
T release(T... args)
THistSvc::m_hlist
hlist_t m_hlist
Definition: THistSvc.h:299
std::vector::back
T back(T... args)
System::typeinfoName
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:308
CommonMessaging< implements< IService, IProperty, IStateful > >::msgLevel
MSG::Level msgLevel() const
get the cached level (originally extracted from the embedded MsgStream)
Definition: CommonMessaging.h:148
THistSvc::stripDirectoryName
std::string stripDirectoryName(std::string &dir) const
Definition: THistSvc.cpp:1780
std::vector::push_back
T push_back(T... args)
THistSvc::getShared_i
LockedHandle< T > getShared_i(const std::string &name) const
Definition: THistSvc.icc:305
TimingHistograms.name
name
Definition: TimingHistograms.py:23
Service::name
const std::string & name() const override
Retrieve name of the service
Definition: Service.cpp:332
StatusCode
Definition: StatusCode.h:65
std::string::at
T at(T... args)
THistSvc::findStream
bool findStream(const std::string &name, std::string &root, std::string &rem, TFile *&file) const
Definition: THistSvc.cpp:1847
TemplatedAlg
Definition: TemplatedAlg.h:25
THistSvc::m_tobjs
objMap_t m_tobjs
Definition: THistSvc.h:304
std::string::c_str
T c_str(T... args)
THistSvc::changeDir
TDirectory * changeDir(const THistSvc::THistID &hid) const
Definition: THistSvc.cpp:1758
THistSvc::m_ids
idMap_t m_ids
Definition: THistSvc.h:301
genconfuser.verbose
verbose
Definition: genconfuser.py:29
THistSvc::removeDoubleSlash
void removeDoubleSlash(std::string &) const
Definition: THistSvc.cpp:1796
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:203
THistSvc::THistID::obj
TObject * obj
Definition: THistSvc.h:244
THistSvc::THistID::mutex
histMut_t * mutex
Definition: THistSvc.h:247
THistSvc::GlobalDirectoryRestore
Helper class that manages ROOts global directory and file.
Definition: THistSvc.h:209
THistSvc::READ
@ READ
Definition: THistSvc.h:222
THistSvc::getHist_i
T * getHist_i(const std::string &name, const size_t &ind=0, bool quiet=false) const
Definition: THistSvc.icc:177
THistSvc::regHist_i
StatusCode regHist_i(std::unique_ptr< T > hist, const std::string &name, bool shared)
Definition: THistSvc.icc:27
StatusCode::SUCCESS
constexpr static const auto SUCCESS
Definition: StatusCode.h:100
THistSvc::m_files
std::map< std::string, std::pair< TFile *, Mode > > m_files
Definition: THistSvc.h:306
THistSvc::exists
bool exists(const std::string &name) const override
Check if object with given name is managed by THistSvcMT exists calls existsHist and only works for T...
Definition: THistSvc.cpp:680
HistoDumpEx.h1
h1
Definition: HistoDumpEx.py:22
THistSvc::m_uids
uidMap_t m_uids
Definition: THistSvc.h:300
std::unordered_map::end
T end(T... args)
StatusCode::FAILURE
constexpr static const auto FAILURE
Definition: StatusCode.h:101
LockedHandle
Definition: LockedHandle.h:38
THistSvc::m_svcMut
THistSvcMutex_t m_svcMut
Definition: THistSvc.h:411
THistSvc::findHistID
size_t findHistID(const std::string &id, const THistID *&hid, const size_t &index=0) const
Definition: THistSvc.cpp:1973
std::unique_ptr
STL class.
THistSvc::THistID::shared
bool shared
Definition: THistSvc.h:248
THistSvc::THistID
Helper struct that bundles the histogram ID with a mutex, TFile and TObject*.
Definition: THistSvc.h:241
MsgStream.h