The Gaudi Framework  master (181af51f)
Loading...
Searching...
No Matches
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>
18#include <RootCnv/RootCnvSvc.h>
21#include <TBranch.h>
22#include <vector>
23
24// Forward declarations
25class 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 */
49namespace 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:
80 RootEvtSelectorContext( const RootEvtSelector* s ) : m_sel( s ), m_entry( -1 ), m_branch( nullptr ) {}
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 }
88
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
109using namespace Gaudi;
110using namespace std;
111
112// Helper method to issue error messages
113StatusCode 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
123 if ( !status.isSuccess() ) { return error( "Error initializing base class Service!" ); }
124
126 if ( !ipers ) { return error( "Unable to locate IPersistencySvc interface of " + m_persName ); }
127 IConversionSvc* cnvSvc = nullptr;
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
162StatusCode RootEvtSelector::createContext( Context*& refpCtxt ) const {
163 refpCtxt = new RootEvtSelectorContext( this );
164 return StatusCode::SUCCESS;
165}
166
167// Access last item in the iteration
168StatusCode RootEvtSelector::last( Context& /*refContext*/ ) const { return StatusCode::FAILURE; }
169
170// Get next iteration item from the event loop context
171StatusCode 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
215StatusCode 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
227StatusCode 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
232StatusCode 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
244StatusCode 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
262StatusCode 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.
291StatusCode 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 {
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}
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition MsgStream.h:198
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
const SmartIF< IMessageSvc > & msgSvc() const
The standard message service.
MsgStream & msg() const
shortcut for the method msgStream(MSG::INFO)
const std::string & fid() const
Access file id.
Description:
Definition RootCnvSvc.h:61
Concrete implementation of the IDataConnection interface to access ROOT files.
TBranch * getBranch(std::string_view section, std::string_view branch_name)
Access data branch by name: Get existing branch in read only mode.
ROOT specific event selector context.
TBranch * m_branch
Reference to the top level branch (typically /Event) used to iterate.
Files::const_iterator fileIterator() const
Access to the file iterator.
long entry() const
Access to the current event entry number.
Files m_files
The file container managed by this context.
long m_entry
Current entry of current file.
const Files & files() const
Access to the file container.
void * identifier() const override
Context identifier.
TBranch * branch() const
Access to the top level branch (typically /Event) used to iterate.
const std::string & fid() const
Access connection fid.
void setFiles(const Files &f)
Set the file container.
std::string m_fid
Connection fid.
void setEntry(long e)
Set current event entry number.
Files::const_iterator m_fiter
The iterator to the.
void setFileIterator(Files::const_iterator i)
Set file iterator.
void setFID(const std::string &fid)
Set connection FID.
const RootEvtSelector * m_sel
Reference to the hosting event selector instance.
void setBranch(TBranch *b)
Set the top level branch (typically /Event) used to iterate.
RootEvtSelectorContext(const RootEvtSelector *s)
Standard constructor with initialization.
std::vector< std::string > Files
Definition of the file container.
Concrete event selector implementation to access ROOT files.
StatusCode rewind(Context &refCtxt) const override
Rewind the dataset.
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...
StatusCode releaseContext(Context *&refCtxt) const override
Release existing event iteration context.
CLID m_rootCLID
Class id of root node to create opaque address.
StatusCode next(Context &refCtxt) const override
Get next iteration item from the event loop context.
StatusCode initialize() override
IService implementation: Db event selector override.
StatusCode error(const std::string &msg) const
Helper method to issue error messages.
StatusCode createContext(Context *&refpCtxt) const override
Create a new event loop context.
StatusCode createAddress(const Context &refCtxt, IOpaqueAddress *&) const override
Create new Opaque address corresponding to the current record.
StatusCode previous(Context &refCtxt) const override
Get previous iteration item from the event loop context.
StatusCode last(Context &refContext) const override
Access last item in the iteration.
StatusCode finalize() override
IService implementation: Service finalization.
Gaudi::Property< std::string > m_persName
std::string m_cnvSvcName
Property; Name of the concversion service used to create opaque addresses.
std::string m_rootName
Property: Name of the ROOT entry name.
RootCnvSvc * m_dbMgr
Reference to the corresponding conversion service.
Parse attribute strings allowing iteration over the various attributes.
Helper class to parse a string of format "type/name".
const std::string & type() const
const std::string & name() const
virtual unsigned long release() const =0
Release Interface instance.
Opaque address interface definition.
Data persistency service interface.
virtual SmartIF< IService > & service(const Gaudi::Utils::TypeNameString &typeName, const bool createIf=true)=0
Returns a smart pointer to a service.
Definition of the MsgStream class used to transmit messages.
Definition MsgStream.h:29
SmartIF< ISvcLocator > & serviceLocator() const override
Retrieve pointer to service locator.
Definition Service.cpp:336
StatusCode finalize() override
Definition Service.cpp:223
const std::string & name() const override
Retrieve name of the service.
Definition Service.cpp:333
StatusCode initialize() override
Definition Service.cpp:118
This class is used for returning status codes from appropriate routines.
Definition StatusCode.h:64
bool isSuccess() const
Definition StatusCode.h:314
constexpr static const auto SUCCESS
Definition StatusCode.h:99
constexpr static const auto FAILURE
Definition StatusCode.h:100
This file provides a Grammar for the type Gaudi::Accumulators::Axis It allows to use that type from p...
Definition __init__.py:1
@ DEBUG
Definition IMessageSvc.h:22
@ ERROR
Definition IMessageSvc.h:22
STL namespace.