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