The Gaudi Framework  master (b9786168)
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:
81 : m_sel( s ), m_fiter( m_files.begin() ), m_entry( -1 ), m_branch( nullptr ) {}
82
83 const Files& files() const { return m_files; }
85 void setFiles( const Files& f ) {
86 m_files = f;
87 m_fiter = m_files.begin();
88 }
89
90 void* identifier() const override { return const_cast<RootEvtSelector*>( m_sel ); }
92 Files::const_iterator fileIterator() const { return m_fiter; }
94 void setFileIterator( Files::const_iterator i ) { m_fiter = i; }
96 long entry() const { return m_entry; }
98 void setEntry( long e ) { m_entry = e; }
100 void setFID( const std::string& fid ) { m_fid = fid; }
102 const std::string& fid() const { return m_fid; }
104 TBranch* branch() const { return m_branch; }
106 void setBranch( TBranch* b ) { m_branch = b; }
107 };
108} // namespace Gaudi
109
110using namespace Gaudi;
111using namespace std;
112
113// Helper method to issue error messages
114StatusCode RootEvtSelector::error( const string& msg ) const {
115 MsgStream log( msgSvc(), name() );
116 log << MSG::ERROR << msg << endmsg;
117 return StatusCode::FAILURE;
118}
119
120// IService implementation: Db event selector override
122 // Initialize base class
124 if ( !status.isSuccess() ) { return error( "Error initializing base class Service!" ); }
125
127 if ( !ipers ) { return error( "Unable to locate IPersistencySvc interface of " + m_persName ); }
128 IConversionSvc* cnvSvc = nullptr;
130 status = ipers->getService( itm.name(), cnvSvc );
131 if ( !status.isSuccess() ) {
132 status = ipers->getService( itm.type(), cnvSvc );
133 if ( !status.isSuccess() ) {
134 return error( "Unable to locate IConversionSvc interface of database type " + m_cnvSvcName );
135 }
136 }
137 m_dbMgr = dynamic_cast<RootCnvSvc*>( cnvSvc );
138 if ( !m_dbMgr ) {
139 cnvSvc->release();
140 return error( "Unable to localize service:" + m_cnvSvcName );
141 }
142 m_dbMgr->addRef();
143
144 // Get DataSvc
145 auto eds = serviceLocator()->service<IDataManagerSvc>( "EventDataSvc" );
146 if ( !eds ) { return error( "Unable to localize service EventDataSvc" ); }
147 m_rootCLID = eds->rootCLID();
148 m_rootName = eds->rootName();
149 MsgStream log( msgSvc(), name() );
150 log << MSG::DEBUG << "Selection root:" << m_rootName << " CLID:" << m_rootCLID << endmsg;
151 return status;
152}
153
154// IService implementation: Service finalization
156 // Initialize base class
157 if ( m_dbMgr ) m_dbMgr->release();
158 m_dbMgr = nullptr; // release
159 return Service::finalize();
160}
161
162// Create a new event loop context
163StatusCode RootEvtSelector::createContext( Context*& refpCtxt ) const {
164 refpCtxt = new RootEvtSelectorContext( this );
165 return StatusCode::SUCCESS;
166}
167
168// Access last item in the iteration
169StatusCode RootEvtSelector::last( Context& /*refContext*/ ) const { return StatusCode::FAILURE; }
170
171// Get next iteration item from the event loop context
172StatusCode RootEvtSelector::next( Context& ctxt ) const {
173 RootEvtSelectorContext* pCtxt = dynamic_cast<RootEvtSelectorContext*>( &ctxt );
174 if ( pCtxt ) {
175 TBranch* b = pCtxt->branch();
176 if ( !b ) {
177 auto fileit = pCtxt->fileIterator();
178 pCtxt->setBranch( nullptr );
179 pCtxt->setEntry( -1 );
180 if ( fileit != pCtxt->files().end() ) {
181 RootDataConnection* con = nullptr;
182 string in = *fileit;
183 StatusCode sc = m_dbMgr->connectDatabase( in, IDataConnection::READ, &con );
184 if ( sc.isSuccess() ) {
185 string section = m_rootName[0] == '/' ? m_rootName.substr( 1 ) : m_rootName;
186 b = con->getBranch( section, m_rootName );
187 if ( b ) {
188 pCtxt->setFID( con->fid() );
189 pCtxt->setBranch( b );
190 return next( ctxt );
191 }
192 }
193 m_dbMgr->disconnect( in ).ignore();
194 pCtxt->setFileIterator( ++fileit );
195 return next( ctxt );
196 }
197 return StatusCode::FAILURE;
198 }
199 long ent = pCtxt->entry();
200 Long64_t nent = b->GetEntries();
201 if ( nent > ( ent + 1 ) ) {
202 pCtxt->setEntry( ++ent );
203 return StatusCode::SUCCESS;
204 }
205 auto fit = pCtxt->fileIterator();
206 pCtxt->setFileIterator( ++fit );
207 pCtxt->setEntry( -1 );
208 pCtxt->setBranch( nullptr );
209 pCtxt->setFID( "" );
210 return next( ctxt );
211 }
212 return StatusCode::FAILURE;
213}
214
215// Get next iteration item from the event loop context
216StatusCode RootEvtSelector::next( Context& ctxt, int jump ) const {
217 if ( jump > 0 ) {
218 for ( int i = 0; i < jump; ++i ) {
219 StatusCode status = next( ctxt );
220 if ( !status.isSuccess() ) { return status; }
221 }
222 return StatusCode::SUCCESS;
223 }
224 return StatusCode::FAILURE;
225}
226
227// Get previous iteration item from the event loop context
228StatusCode RootEvtSelector::previous( Context& /* ctxt */ ) const {
229 return error( "EventSelector Iterator, operator -- not supported " );
230}
231
232// Get previous iteration item from the event loop context
233StatusCode RootEvtSelector::previous( Context& ctxt, int jump ) const {
234 if ( jump > 0 ) {
235 for ( int i = 0; i < jump; ++i ) {
236 StatusCode status = previous( ctxt );
237 if ( !status.isSuccess() ) { return status; }
238 }
239 return StatusCode::SUCCESS;
240 }
241 return StatusCode::FAILURE;
242}
243
244// Rewind the dataset
245StatusCode RootEvtSelector::rewind( Context& ctxt ) const {
246 RootEvtSelectorContext* pCtxt = dynamic_cast<RootEvtSelectorContext*>( &ctxt );
247 if ( pCtxt ) {
248 auto fileit = pCtxt->fileIterator();
249 if ( fileit != pCtxt->files().end() ) {
250 string input = *fileit;
251 m_dbMgr->disconnect( input ).ignore();
252 }
253 pCtxt->setFID( "" );
254 pCtxt->setEntry( -1 );
255 pCtxt->setBranch( nullptr );
256 pCtxt->setFileIterator( pCtxt->files().begin() );
257 return StatusCode::SUCCESS;
258 }
259 return StatusCode::FAILURE;
260}
261
262// Create new Opaque address corresponding to the current record
263StatusCode RootEvtSelector::createAddress( const Context& ctxt, IOpaqueAddress*& pAddr ) const {
264 const RootEvtSelectorContext* pctxt = dynamic_cast<const RootEvtSelectorContext*>( &ctxt );
265 if ( pctxt ) {
266 long ent = pctxt->entry();
267 if ( ent >= 0 ) {
268 auto fileit = pctxt->fileIterator();
269 if ( fileit != pctxt->files().end() ) {
270 const string par[2] = { pctxt->fid(), m_rootName };
271 const unsigned long ipar[2] = { 0, (unsigned long)ent };
272 return m_dbMgr->createAddress( m_dbMgr->repSvcType(), m_rootCLID, &par[0], &ipar[0], pAddr );
273 }
274 }
275 }
276 pAddr = nullptr;
277 return StatusCode::FAILURE;
278}
279
280// Release existing event iteration context
282 RootEvtSelectorContext* pCtxt = dynamic_cast<RootEvtSelectorContext*>( ctxt );
283 if ( pCtxt ) {
284 delete pCtxt;
285 return StatusCode::SUCCESS;
286 }
287 return StatusCode::FAILURE;
288}
289
290// Will set a new criteria for the selection of the next list of events and will change
291// the state of the context in a way to point to the new list.
292StatusCode RootEvtSelector::resetCriteria( const string& criteria, Context& context ) const {
293 MsgStream log( msgSvc(), name() );
294 RootEvtSelectorContext* ctxt = dynamic_cast<RootEvtSelectorContext*>( &context );
295 string db, typ, item, sel, stmt, aut, addr;
296 if ( ctxt ) {
297 if ( criteria.compare( 0, 5, "FILE " ) == 0 ) {
298 // The format for the criteria is:
299 // FILE filename1, filename2 ...
300 db = criteria.substr( 5 );
301 } else {
303 for ( auto attrib : Parser( criteria ) ) {
304 string tmp = attrib.tag.substr( 0, 3 );
305 if ( tmp == "DAT" ) {
306 db = std::move( attrib.value );
307 } else if ( tmp == "OPT" ) {
308 if ( attrib.value.compare( 0, 3, "REA" ) != 0 ) {
309 log << MSG::ERROR << "Option:\"" << attrib.value << "\" not valid" << endmsg;
310 return StatusCode::FAILURE;
311 }
312 } else if ( tmp == "TYP" ) {
313 typ = std::move( attrib.value );
314 } else if ( tmp == "ADD" ) {
315 item = std::move( attrib.value );
316 } else if ( tmp == "SEL" ) {
317 sel = std::move( attrib.value );
318 } else if ( tmp == "FUN" ) {
319 stmt = std::move( attrib.value );
320 } else if ( tmp == "AUT" ) {
321 aut = std::move( attrib.value );
322 } else if ( tmp == "COL" ) {
323 addr = std::move( attrib.value );
324 }
325 }
326 }
327 // It's now time to parse the criteria for the event selection
328 // The format for the criteria is:
329 // FILE filename1, filename2 ...
330 // JOBID number1-number2, number3, ...
332 string rest = db;
333 files.clear();
334 while ( true ) {
335 int ipos = rest.find_first_not_of( " ," );
336 if ( ipos == -1 ) break;
337 rest = rest.substr( ipos, string::npos ); // remove blanks before
338 int lpos = rest.find_first_of( " ," ); // locate next blank
339
340 files.push_back( rest.substr( 0, lpos == -1 ? string::npos : lpos ) ); // insert in list
341 if ( lpos == -1 ) break;
342 rest = rest.substr( lpos, string::npos ); // get the rest
343 }
344 ctxt->setFiles( files );
345 ctxt->setFileIterator( ctxt->files().begin() );
346 return StatusCode::SUCCESS;
347 }
348 return error( "Invalid iteration context." );
349}
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.