The Gaudi Framework  v33r0 (d5ea422b)
RootEvtSelector.cpp
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 //====================================================================
12 // RootEvtSelector.cpp
13 //--------------------------------------------------------------------
14 //
15 // Package : RootCnv
16 //
17 // Author : M.Frank
18 //====================================================================
19 #ifndef GAUDIROOTCNV_ROOTEVTSELECTORCONTEXT_H
20 # define GAUDIROOTCNV_ROOTEVTSELECTORCONTEXT_H
21 
22 // Include files
23 # include "RootCnv/RootEvtSelector.h"
24 # include <vector>
25 
26 // Forward declarations
27 class TBranch;
28 
29 // FIXME - method below generates leak errors with sanitizer
30 //
31 // clang-format off
32 // Direct leak of 176 byte(s) in 1 object(s) allocated from:
33 // #0 0x7f56e2dc2da8 in operator new(unsigned long) /afs/cern.ch/cms/CAF/CMSCOMM/COMM_ECAL/dkonst/GCC/build/contrib/gcc-8.2.0/src/gcc/8.2.0/libsanitizer/lsan/lsan_interceptors.cc:229
34 // #1 0x7f56cb992ae4 in Gaudi::RootCnvSvc::createAddress(long, unsigned int const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const*, unsigned long const*, IOpaqueAddress*&) ../RootCnv/src/RootCnvSvc.cpp:349
35 // #2 0x7f56cb993530 in Gaudi::RootCnvSvc::connectDatabase(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, Gaudi::RootDataConnection**) ../RootCnv/src/RootCnvSvc.cpp:242
36 // #3 0x7f56cb9b5230 in Gaudi::RootEvtSelector::next(IEvtSelector::Context&) const ../RootCnv/src/RootEvtSelector.cpp:168
37 // #4 0x7f56d2e748b3 in EventSelector::next(IEvtSelector::Context&, int) const ../GaudiCoreSvc/src/EventSelector/EventSelector.cpp:188
38 // #5 0x7f56d2e737bf in EventSelector::next(IEvtSelector::Context&) const ../GaudiCoreSvc/src/EventSelector/EventSelector.cpp:177
39 // #6 0x7f56d2e4c68f in EventLoopMgr::getEventRoot(IOpaqueAddress*&) ../GaudiCoreSvc/src/ApplicationMgr/EventLoopMgr.cpp:350
40 // #7 0x7f56d2e4dab5 in EventLoopMgr::nextEvent(int) ../GaudiCoreSvc/src/ApplicationMgr/EventLoopMgr.cpp:307
41 // #8 0x7f56d3fd5a5a in MinimalEventLoopMgr::executeRun(int) ../GaudiKernel/src/Lib/MinimalEventLoopMgr.cpp:296
42 // #9 0x7f56d2e289ac in ApplicationMgr::executeRun(int) ../GaudiCoreSvc/src/ApplicationMgr/ApplicationMgr.cpp:824
43 // #10 0x7f56d3f5a21c in Gaudi::Application::run() ../GaudiKernel/src/Lib/Application.cpp:81
44 // clang-format on
45 //
46 // These leaks are currently suppressed in Gaudi/job/Gaudi-LSan.supp - remove entry there to reactivate
47 
48 /*
49  * Gaudi namespace declaration
50  */
51 namespace Gaudi {
52 
62  public:
65 
66  private:
72  Files::const_iterator m_fiter;
74  long m_entry;
76  TBranch* m_branch;
79 
80  public:
82  RootEvtSelectorContext( const RootEvtSelector* s ) : m_sel( s ), m_entry( -1 ), m_branch( nullptr ) {}
84  const Files& files() const { return m_files; }
86  void setFiles( const Files& f ) {
87  m_files = f;
88  m_fiter = m_files.begin();
89  }
91  void* identifier() const override { return const_cast<RootEvtSelector*>( m_sel ); }
93  Files::const_iterator fileIterator() const { return m_fiter; }
95  void setFileIterator( Files::const_iterator i ) { m_fiter = i; }
97  long entry() const { return m_entry; }
99  void setEntry( long e ) { m_entry = e; }
101  void setFID( const std::string& fid ) { m_fid = fid; }
103  const std::string& fid() const { return m_fid; }
105  TBranch* branch() const { return m_branch; }
107  void setBranch( TBranch* b ) { m_branch = b; }
108  };
109 } // namespace Gaudi
110 #endif // GAUDIROOTCNV_ROOTEVTSELECTORCONTEXT_H
111 
112 // Include files
114 #include "GaudiKernel/ClassID.h"
117 #include "GaudiKernel/ISvcLocator.h"
118 #include "GaudiKernel/MsgStream.h"
120 #include "RootCnv/RootCnvSvc.h"
122 #include "TBranch.h"
123 
124 using namespace Gaudi;
125 using namespace std;
126 
127 // Helper method to issue error messages
128 StatusCode RootEvtSelector::error( const string& msg ) const {
129  MsgStream log( msgSvc(), name() );
130  log << MSG::ERROR << msg << endmsg;
131  return StatusCode::FAILURE;
132 }
133 
134 // IService implementation: Db event selector override
136  // Initialize base class
137  StatusCode status = Service::initialize();
138  if ( !status.isSuccess() ) { return error( "Error initializing base class Service!" ); }
139 
140  auto ipers = serviceLocator()->service<IPersistencySvc>( m_persName );
141  if ( !ipers ) { return error( "Unable to locate IPersistencySvc interface of " + m_persName ); }
142  IConversionSvc* cnvSvc = nullptr;
143  Gaudi::Utils::TypeNameString itm( m_cnvSvcName );
144  status = ipers->getService( itm.name(), cnvSvc );
145  if ( !status.isSuccess() ) {
146  status = ipers->getService( itm.type(), cnvSvc );
147  if ( !status.isSuccess() ) {
148  return error( "Unable to locate IConversionSvc interface of database type " + m_cnvSvcName );
149  }
150  }
151  m_dbMgr = dynamic_cast<RootCnvSvc*>( cnvSvc );
152  if ( !m_dbMgr ) {
153  cnvSvc->release();
154  return error( "Unable to localize service:" + m_cnvSvcName );
155  }
156  m_dbMgr->addRef();
157 
158  // Get DataSvc
159  auto eds = serviceLocator()->service<IDataManagerSvc>( "EventDataSvc" );
160  if ( !eds ) { return error( "Unable to localize service EventDataSvc" ); }
161  m_rootCLID = eds->rootCLID();
162  m_rootName = eds->rootName();
163  MsgStream log( msgSvc(), name() );
164  log << MSG::DEBUG << "Selection root:" << m_rootName << " CLID:" << m_rootCLID << endmsg;
165  return status;
166 }
167 
168 // IService implementation: Service finalization
170  // Initialize base class
171  if ( m_dbMgr ) m_dbMgr->release();
172  m_dbMgr = nullptr; // release
173  return Service::finalize();
174 }
175 
176 // Create a new event loop context
177 StatusCode RootEvtSelector::createContext( Context*& refpCtxt ) const {
178  refpCtxt = new RootEvtSelectorContext( this );
179  return StatusCode::SUCCESS;
180 }
181 
182 // Access last item in the iteration
183 StatusCode RootEvtSelector::last( Context& /*refContext*/ ) const { return StatusCode::FAILURE; }
184 
185 // Get next iteration item from the event loop context
186 StatusCode RootEvtSelector::next( Context& ctxt ) const {
187  RootEvtSelectorContext* pCtxt = dynamic_cast<RootEvtSelectorContext*>( &ctxt );
188  if ( pCtxt ) {
189  TBranch* b = pCtxt->branch();
190  if ( !b ) {
191  auto fileit = pCtxt->fileIterator();
192  pCtxt->setBranch( nullptr );
193  pCtxt->setEntry( -1 );
194  if ( fileit != pCtxt->files().end() ) {
195  RootDataConnection* con = nullptr;
196  string in = *fileit;
197  StatusCode sc = m_dbMgr->connectDatabase( in, IDataConnection::READ, &con );
198  if ( sc.isSuccess() ) {
199  string section = m_rootName[0] == '/' ? m_rootName.substr( 1 ) : m_rootName;
200  b = con->getBranch( section, m_rootName );
201  if ( b ) {
202  pCtxt->setFID( con->fid() );
203  pCtxt->setBranch( b );
204  return next( ctxt );
205  }
206  }
207  m_dbMgr->disconnect( in ).ignore();
208  pCtxt->setFileIterator( ++fileit );
209  return next( ctxt );
210  }
211  return StatusCode::FAILURE;
212  }
213  long ent = pCtxt->entry();
214  Long64_t nent = b->GetEntries();
215  if ( nent > ( ent + 1 ) ) {
216  pCtxt->setEntry( ++ent );
217  return StatusCode::SUCCESS;
218  }
219  auto fit = pCtxt->fileIterator();
220  pCtxt->setFileIterator( ++fit );
221  pCtxt->setEntry( -1 );
222  pCtxt->setBranch( nullptr );
223  pCtxt->setFID( "" );
224  return next( ctxt );
225  }
226  return StatusCode::FAILURE;
227 }
228 
229 // Get next iteration item from the event loop context
230 StatusCode RootEvtSelector::next( Context& ctxt, int jump ) const {
231  if ( jump > 0 ) {
232  for ( int i = 0; i < jump; ++i ) {
233  StatusCode status = next( ctxt );
234  if ( !status.isSuccess() ) { return status; }
235  }
236  return StatusCode::SUCCESS;
237  }
238  return StatusCode::FAILURE;
239 }
240 
241 // Get previous iteration item from the event loop context
242 StatusCode RootEvtSelector::previous( Context& /* ctxt */ ) const {
243  return error( "EventSelector Iterator, operator -- not supported " );
244 }
245 
246 // Get previous iteration item from the event loop context
247 StatusCode RootEvtSelector::previous( Context& ctxt, int jump ) const {
248  if ( jump > 0 ) {
249  for ( int i = 0; i < jump; ++i ) {
250  StatusCode status = previous( ctxt );
251  if ( !status.isSuccess() ) { return status; }
252  }
253  return StatusCode::SUCCESS;
254  }
255  return StatusCode::FAILURE;
256 }
257 
258 // Rewind the dataset
259 StatusCode RootEvtSelector::rewind( Context& ctxt ) const {
260  RootEvtSelectorContext* pCtxt = dynamic_cast<RootEvtSelectorContext*>( &ctxt );
261  if ( pCtxt ) {
262  auto fileit = pCtxt->fileIterator();
263  if ( fileit != pCtxt->files().end() ) {
264  string input = *fileit;
265  m_dbMgr->disconnect( input ).ignore();
266  }
267  pCtxt->setFID( "" );
268  pCtxt->setEntry( -1 );
269  pCtxt->setBranch( nullptr );
270  pCtxt->setFileIterator( pCtxt->files().begin() );
271  return StatusCode::SUCCESS;
272  }
273  return StatusCode::FAILURE;
274 }
275 
276 // Create new Opaque address corresponding to the current record
277 StatusCode RootEvtSelector::createAddress( const Context& ctxt, IOpaqueAddress*& pAddr ) const {
278  const RootEvtSelectorContext* pctxt = dynamic_cast<const RootEvtSelectorContext*>( &ctxt );
279  if ( pctxt ) {
280  long ent = pctxt->entry();
281  if ( ent >= 0 ) {
282  auto fileit = pctxt->fileIterator();
283  if ( fileit != pctxt->files().end() ) {
284  const string par[2] = {pctxt->fid(), m_rootName};
285  const unsigned long ipar[2] = {0, (unsigned long)ent};
286  return m_dbMgr->createAddress( m_dbMgr->repSvcType(), m_rootCLID, &par[0], &ipar[0], pAddr );
287  }
288  }
289  }
290  pAddr = nullptr;
291  return StatusCode::FAILURE;
292 }
293 
294 // Release existing event iteration context
296  RootEvtSelectorContext* pCtxt = dynamic_cast<RootEvtSelectorContext*>( ctxt );
297  if ( pCtxt ) {
298  delete pCtxt;
299  return StatusCode::SUCCESS;
300  }
301  return StatusCode::FAILURE;
302 }
303 
304 // Will set a new criteria for the selection of the next list of events and will change
305 // the state of the context in a way to point to the new list.
306 StatusCode RootEvtSelector::resetCriteria( const string& criteria, Context& context ) const {
307  MsgStream log( msgSvc(), name() );
308  RootEvtSelectorContext* ctxt = dynamic_cast<RootEvtSelectorContext*>( &context );
309  string db, typ, item, sel, stmt, aut, addr;
310  if ( ctxt ) {
311  if ( criteria.compare( 0, 5, "FILE " ) == 0 ) {
312  // The format for the criteria is:
313  // FILE filename1, filename2 ...
314  db = criteria.substr( 5 );
315  } else {
316  using Parser = Gaudi::Utils::AttribStringParser;
317  for ( auto attrib : Parser( criteria ) ) {
318  string tmp = attrib.tag.substr( 0, 3 );
319  if ( tmp == "DAT" ) {
320  db = std::move( attrib.value );
321  } else if ( tmp == "OPT" ) {
322  if ( attrib.value.compare( 0, 3, "REA" ) != 0 ) {
323  log << MSG::ERROR << "Option:\"" << attrib.value << "\" not valid" << endmsg;
324  return StatusCode::FAILURE;
325  }
326  } else if ( tmp == "TYP" ) {
327  typ = std::move( attrib.value );
328  } else if ( tmp == "ADD" ) {
329  item = std::move( attrib.value );
330  } else if ( tmp == "SEL" ) {
331  sel = std::move( attrib.value );
332  } else if ( tmp == "FUN" ) {
333  stmt = std::move( attrib.value );
334  } else if ( tmp == "AUT" ) {
335  aut = std::move( attrib.value );
336  } else if ( tmp == "COL" ) {
337  addr = std::move( attrib.value );
338  }
339  }
340  }
341  // It's now time to parse the criteria for the event selection
342  // The format for the criteria is:
343  // FILE filename1, filename2 ...
344  // JOBID number1-number2, number3, ...
346  string rest = db;
347  files.clear();
348  while ( true ) {
349  int ipos = rest.find_first_not_of( " ," );
350  if ( ipos == -1 ) break;
351  rest = rest.substr( ipos, string::npos ); // remove blanks before
352  int lpos = rest.find_first_of( " ," ); // locate next blank
353  files.push_back( rest.substr( 0, lpos ) ); // insert in list
354  if ( lpos == -1 ) break;
355  rest = rest.substr( lpos, string::npos ); // get the rest
356  }
357  ctxt->setFiles( files );
358  ctxt->setFileIterator( ctxt->files().begin() );
359  return StatusCode::SUCCESS;
360  }
361  return error( "Invalid iteration context." );
362 }
Parse attribute strings allowing iteration over the various attributes.
StatusCode next(Context &refCtxt) const override
Get next iteration item from the event loop context.
Definition of the MsgStream class used to transmit messages.
Definition: MsgStream.h:34
StatusCode initialize() override
Definition: Service.cpp:70
TBranch * getBranch(std::string_view section, std::string_view branch_name)
Access data branch by name: Get existing branch in read only mode.
RootEvtSelectorContext(const RootEvtSelector *s)
Standard constructor with initialization.
T find_first_not_of(T... args)
StatusCode finalize() override
Definition: Service.cpp:174
std::vector< std::string > Files
Definition of the file container.
std::string m_fid
Connection fid.
constexpr static const auto SUCCESS
Definition: StatusCode.h:96
STL namespace.
const std::string & fid() const
Access file id.
StatusCode rewind(Context &refCtxt) const override
Rewind the dataset.
const std::string & type() const
T end(T... args)
StatusCode createContext(Context *&refpCtxt) const override
Create a new event loop context.
StatusCode previous(Context &refCtxt) const override
Get previous iteration item from the event loop context.
Files::const_iterator fileIterator() const
Access to the file iterator.
STL class.
void * identifier() const override
Context identifier.
StatusCode releaseContext(Context *&refCtxt) const override
Release existing event iteration context.
T push_back(T... args)
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
Helper class to parse a string of format "type/name".
ROOT specific event selector context.
StatusCode resetCriteria(const std::string &cr, Context &c) const override
Will set a new criteria for the selection of the next list of events and will change the state of the...
T next(T... args)
const std::string & name() const
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:61
StatusCode finalize() override
IService implementation: Service finalization.
T find_first_of(T... args)
T clear(T... args)
bool isSuccess() const
Definition: StatusCode.h:361
T move(T... args)
const RootEvtSelector * m_sel
Reference to the hosting event selector instance.
void setFiles(const Files &f)
Set the file container.
StatusCode createAddress(const Context &refCtxt, IOpaqueAddress *&) const override
Create new Opaque address corresponding to the current record.
void setBranch(TBranch *b)
Set the top level branch (typically /Event) used to iterate.
Concrete event selector implementation to access ROOT files.
void setEntry(long e)
Set current event entry number.
long entry() const
Access to the current event entry number.
virtual unsigned long release()=0
Release Interface instance.
StatusCode last(Context &refContext) const override
Access last item in the iteration.
T begin(T... args)
void setFID(const std::string &fid)
Set connection FID.
Files::const_iterator m_fiter
The iterator to the.
string s
Definition: gaudirun.py:328
constexpr static const auto FAILURE
Definition: StatusCode.h:97
T substr(T... args)
Data persistency service interface.
void setFileIterator(Files::const_iterator i)
Set file iterator.
Opaque address interface definition.
StatusCode initialize() override
IService implementation: Db event selector override.
Files m_files
The file container managed by this context.
Concrete implementation of the IDataConnection interface to access ROOT files.
TBranch * m_branch
Reference to the top level branch (typically /Event) used to iterate.
TBranch * branch() const
Access to the top level branch (typically /Event) used to iterate.
Header file for std:chrono::duration-based Counters.
Definition: __init__.py:1
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:202
T compare(T... args)
const std::string & fid() const
Access connection fid.
long m_entry
Current entry of current file.
const Files & files() const
Access to the file container.