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