The Gaudi Framework  master (181af51f)
Loading...
Searching...
No Matches
IoComponentMgr.cpp
Go to the documentation of this file.
1/***********************************************************************************\
2* (c) Copyright 1998-2024 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// IoComponentMgr.cxx
13// Implementation file for class IoComponentMgr
14// Author: S.Binet<binet@cern.ch>
16
17// GaudiMP includes
18#include "IoComponentMgr.h"
19// FrameWork includes
20#include <Gaudi/Property.h>
25// BOOST includes
26#include <boost/algorithm/string/predicate.hpp>
27#include <boost/filesystem.hpp>
28// STL includes
29#include <algorithm>
30#include <array>
31
32#define ON_DEBUG if ( outputLevel() <= MSG::DEBUG )
33#define ON_VERBOSE if ( outputLevel() <= MSG::VERBOSE )
34
35#define DEBMSG ON_DEBUG debug()
36#define VERMSG ON_VERBOSE verbose()
37
39
40using namespace std;
41
42std::ostream& operator<<( std::ostream& os, const IIoComponentMgr::IoMode::Type& m ) {
43 switch ( m ) {
45 os << "READ";
46 break;
48 os << "WRITE";
49 break;
51 os << "RW";
52 break;
53 default:
54 os << "INVALID";
55 break;
56 }
57
58 return os;
59}
60
61/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
62
64 DEBMSG << "--> initialize()" << endmsg;
65
66 if ( Service::initialize().isFailure() ) {
67 error() << "Unable to initialize Service base class" << endmsg;
69 }
70
71 auto p_incSvc = service<IIncidentSvc>( "IncidentSvc", true );
72
73 if ( !p_incSvc ) {
74 error() << "unable to get the IncidentSvc" << endmsg;
76 } else {
77 p_incSvc->addListener( this, IncidentType::BeginOutputFile, 100, true );
78 p_incSvc->addListener( this, IncidentType::BeginInputFile, 100, true );
79 }
80
82}
83
84/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
85
87 DEBMSG << "--> finalize()" << endmsg;
88
89 for ( auto& io : m_iostack ) { io->release(); }
90
92}
93
94/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
95
98bool IoComponentMgr::io_hasitem( IIoComponent* iocomponent ) const {
99 DEBMSG << "--> io_hasitem()" << endmsg;
100 if ( 0 == iocomponent ) { return false; }
101 const std::string& ioname = iocomponent->name();
102 IoRegistry_t::const_iterator io = m_ioregistry.find( ioname );
103 return io != m_ioregistry.end();
104}
105
106/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
107
111bool IoComponentMgr::io_contains( IIoComponent* iocomponent, const std::string& fname ) const {
112 DEBMSG << "--> io_contains()" << endmsg;
113 if ( 0 == iocomponent ) { return false; }
114 const std::string& ioname = iocomponent->name();
115
116 DEBMSG << "io_contains: c: " << ioname << " f: " << fname << endmsg;
117
118 pair<iodITR, iodITR> fit = m_cdict.equal_range( iocomponent );
119 if ( fit.first == fit.second ) {
120 return false;
121 } else {
122 iodITR it;
123 for ( it = fit.first; it != fit.second; ++it ) {
124 IoComponentEntry ioe = it->second;
125 DEBMSG << " " << ioe << endmsg;
126 if ( ioe.m_oldfname == "" ) {
127 error() << "IIoComponent " << ioname << " has empty old filename" << endmsg;
128 return false;
129 } else if ( ioe.m_oldfname == fname ) {
130 return true;
131 }
132 }
133 }
134
135 return false;
136}
137
138/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
139
147 if ( !iocomponent ) {
148 error() << "io_register (component) received a NULL pointer !" << endmsg;
149 return StatusCode::FAILURE;
150 }
151 const std::string& ioname = iocomponent->name();
152 DEBMSG << "--> io_register(" << ioname << ")" << endmsg;
153 auto itr = m_ioregistry.find( ioname );
154 if ( itr == m_ioregistry.end() ) {
155 DEBMSG << " registering IoComponent \"" << ioname << "\"" << endmsg;
156 iocomponent->addRef(); // ownership...
157 m_ioregistry[ioname] = iocomponent;
158 m_iostack.push_back( iocomponent );
159 } else {
160 info() << "IoComponent[" << iocomponent->name() << "] already registered @" << (void*)itr->second << endmsg;
161 }
162 return StatusCode::SUCCESS;
163}
164
165/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
166
174 const std::string& fname, const std::string& pfn ) {
175 if ( 0 == iocomponent ) { return StatusCode::FAILURE; }
176 const std::string& ioname = iocomponent->name();
177
178 DEBMSG << "--> io_register(" << ioname << "," << ( ( iomode == IIoComponentMgr::IoMode::READ ) ? "R" : "W" ) << ","
179 << fname << ")" << endmsg;
180
181 if ( !io_hasitem( iocomponent ) ) {
182 if ( !io_register( iocomponent ).isSuccess() ) {
183 error() << "could not register component [" << iocomponent->name() << "] "
184 << "with the I/O component manager !" << endmsg;
185 return StatusCode::FAILURE;
186 }
187 }
188
189 pair<iodITR, iodITR> fit = m_cdict.equal_range( iocomponent );
190 if ( fit.first != fit.second ) {
191 for ( iodITR it = fit.first; it != fit.second; ++it ) {
192 IoComponentEntry ioe = it->second;
193 if ( ioe.m_oldfname == fname ) {
194 if ( ioe.m_iomode == iomode ) {
195 info() << "IoComponent " << ioname << " has already had file " << fname << " registered with i/o mode "
196 << iomode << endmsg;
197 return StatusCode::SUCCESS;
198 } else {
199 warning() << "IoComponent " << ioname << " has already had file " << fname
200 << " registered with a different i/o mode " << ioe.m_iomode << " - now trying " << iomode << endmsg;
201 }
202 }
203 }
204 }
205
206 // We need to take into account that boost::filesystem::absolute() does not work with direct I/O inputs
207 const std::string& tmp_name = ( pfn.empty() ? fname : pfn );
208 bool special_case =
209 std::any_of( begin( m_directio_patterns.value() ), end( m_directio_patterns.value() ),
210 [&]( const std::string& pf ) { return boost::algorithm::contains( tmp_name, pf ); } );
211 IoComponentEntry ioc( fname, ( special_case ? tmp_name : boost::filesystem::absolute( tmp_name ).string() ), iomode );
212 m_cdict.insert( pair<IIoComponent*, IoComponentEntry>( iocomponent, ioc ) );
213
214 return StatusCode::SUCCESS;
215}
216
219std::vector<std::string> IoComponentMgr::io_retrieve( IIoComponent* iocomponent ) {
220 std::vector<std::string> fnames;
221 pair<iodITR, iodITR> pit;
222
223 // Find component and copy all registered file names
224 if ( iocomponent != nullptr && findComp( iocomponent, pit ) ) {
225 std::transform( pit.first, pit.second, std::back_inserter( fnames ),
226 []( const auto& itr ) { return itr.second.m_oldfname; } );
227 }
228 return fnames;
229}
230
231/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
232
236StatusCode IoComponentMgr::io_retrieve( IIoComponent* iocomponent, std::string& fname ) {
237 if ( 0 == iocomponent ) { return StatusCode::FAILURE; }
238
239 std::string ofname = fname;
240 const std::string& ioname = iocomponent->name();
241
242 DEBMSG << "--> io_retrieve(" << ioname << "," << fname << ")" << endmsg;
243
244 iodITR it;
245 if ( !findComp( iocomponent, ofname, it ) ) {
246 DEBMSG << "could not find c: " << ioname << " old_f: " << ofname << endmsg;
247 return StatusCode::FAILURE;
248 } else {
249
250 IoDict_t::iterator it;
251 for ( it = m_cdict.equal_range( iocomponent ).first; it != m_cdict.equal_range( iocomponent ).second; ++it ) {
252
253 if ( it->second.m_oldfname == ofname ) {
254 DEBMSG << "retrieving new name for the component " << iocomponent->name() << " old name: " << ofname
255 << ", new name: " << it->second.m_newfname << endmsg;
256 fname = it->second.m_newfname;
257 return StatusCode::SUCCESS;
258 }
259 }
260 }
261
262 DEBMSG << "Unexpected error! Unable to find entry in the dictionary corresponding to old filename: " << ofname
263 << endmsg;
264 return StatusCode::FAILURE;
265}
266
267/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
268
274 ON_DEBUG {
275 debug() << "--> io_reinitialize()" << endmsg;
276 debug() << "reinitializing I/O subsystem..." << endmsg;
277 debug() << "Listing all monitored entries: " << std::endl;
278 debug() << list() << endmsg;
279 }
280
281 bool allgood = true;
282 for ( auto& io : m_iostack ) {
283 DEBMSG << " [" << io->name() << "]->io_reinit()..." << endmsg;
284 if ( !io->io_reinit().isSuccess() ) {
285 allgood = false;
286 error() << "problem in [" << io->name() << "]->io_reinit() !" << endmsg;
287 }
288 }
289
290 return allgood ? StatusCode::SUCCESS : StatusCode::FAILURE;
291}
292
293/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
294
295StatusCode IoComponentMgr::io_update( IIoComponent* ioc, const std::string& old_fname, const std::string& new_fname ) {
296
297 DEBMSG << "--> io_update(" << ioc->name() << "," << old_fname << "," << new_fname << ")" << endmsg;
298
299 IoDict_t::iterator it;
300 for ( it = m_cdict.equal_range( ioc ).first; it != m_cdict.equal_range( ioc ).second; ++it ) {
301
302 if ( it->second.m_oldfname == old_fname ) {
303 DEBMSG << "updating " << ioc->name() << " f: " << old_fname << " -> " << new_fname << endmsg;
304 it->second.m_newfname = new_fname;
305 return StatusCode::SUCCESS;
306 }
307 }
308
309 return StatusCode::FAILURE;
310}
311
312/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
313
314StatusCode IoComponentMgr::io_update( IIoComponent* ioc, const std::string& work_dir ) {
315
316 DEBMSG << "--> io_update(" << ioc->name() << "," << work_dir << ")" << endmsg;
317
318 IoDict_t::iterator it;
319 for ( it = m_cdict.equal_range( ioc ).first; it != m_cdict.equal_range( ioc ).second; ++it ) {
320
321 switch ( it->second.m_iomode ) {
323 it->second.m_newfname = it->second.m_oldabspath;
324 break;
325 }
327 boost::filesystem::path oldPath( it->second.m_oldfname );
328 if ( oldPath.is_relative() && oldPath.filename() == oldPath.relative_path() ) {
329
330 // Only file name was provided for writing. This is the usual mode of operation
331 // ***
332 // NB. In such cases it would make sense to set newfname=oldfname, however this will break
333 // existing client codes, which assume that newfname contains "/"
334 // Thus we set newfname=workdir/oldfname
335 // ***
336
337 boost::filesystem::path newfname( work_dir );
338 newfname /= oldPath;
339 it->second.m_newfname = newfname.string();
340 } else {
341 // New name should be the old absolute path
342 it->second.m_newfname = it->second.m_oldabspath;
343 }
344
345 break;
346 }
347 default: {
348 // Don't know how to deal with either RW or INVALID
349 error() << "Unable to update IoComponent for the mode " << it->second.m_iomode << endmsg;
350 return StatusCode::FAILURE;
351 }
352 }
353
354 } // for
355
356 return StatusCode::SUCCESS;
357}
358
359/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
360
361StatusCode IoComponentMgr::io_update_all( const std::string& work_dir ) {
362 DEBMSG << "-->io_update_all for the directory " << work_dir << endmsg;
363 bool allgood = true;
364 for ( IoStack_t::iterator io = m_iostack.begin(), ioEnd = m_iostack.end(); io != ioEnd; ++io ) {
365 if ( !io_update( *io, work_dir ).isSuccess() ) {
366 allgood = false;
367 error() << "problem in [" << ( *io )->name() << "]->io_update() !" << endmsg;
368 }
369 }
370 return allgood ? StatusCode::SUCCESS : StatusCode::FAILURE;
371}
372
373/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
374
380 ON_DEBUG {
381 debug() << "--> io_finalize()" << endmsg;
382 debug() << "finalizing I/O subsystem..." << endmsg;
383 debug() << "Listing all monitored entries: " << std::endl;
384 debug() << list() << endmsg;
385 }
386
387 bool allgood = true;
388 // reverse iteration to unwind component dependencies
389 for ( IoStack_t::reverse_iterator io = m_iostack.rbegin(), ioEnd = m_iostack.rend(); io != ioEnd; ++io ) {
390 DEBMSG << " [" << ( *io )->name() << "]->io_finalize()..." << endmsg;
391 if ( !( *io )->io_finalize().isSuccess() ) {
392 allgood = false;
393 error() << "problem in [" << ( *io )->name() << "]->io_finalize() !" << endmsg;
394 }
395 }
396
397 return allgood ? StatusCode::SUCCESS : StatusCode::FAILURE;
398}
399
400/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
401
402bool IoComponentMgr::findComp( IIoComponent* c, const std::string& f, iodITR& itr ) const {
403
404 pair<iodITR, iodITR> pit;
405 if ( !findComp( c, pit ) ) {
406 itr = pit.first;
407 return false;
408 }
409 return std::any_of( pit.first, pit.second, [&]( IoDict_t::const_reference i ) { return i.second.m_oldfname == f; } );
410}
411
412/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
413
414bool IoComponentMgr::findComp( IIoComponent* c, std::pair<iodITR, iodITR>& pit ) const {
415
416 pit = m_cdict.equal_range( c );
417 return pit.first != pit.second;
418}
419
420/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
421
422bool IoComponentMgr::findComp( const std::string& c, std::pair<iodITR, iodITR>& pit ) const {
423
424 pit.first = m_cdict.end();
425 pit.second = m_cdict.end();
426
427 auto itr = m_ioregistry.find( c );
428 return ( itr != m_ioregistry.end() ) && findComp( itr->second, pit );
429}
430
431/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
432
433std::string IoComponentMgr::list() const {
434
435 ostringstream ost;
436
437 ost << "Listing all IoComponents (" << m_cdict.size() << "): " << endl;
438 for ( const auto& i : m_cdict ) { ost << " " << i.first->name() << " " << i.second << endl; }
439
440 return ost.str();
441}
442
443/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
444
446
447 pair<iodITR, iodITR> pit;
448
449 if ( i.type() == IncidentType::BeginInputFile ) {
450
451 const FileIncident* fi = dynamic_cast<const FileIncident*>( &i );
452 DEBMSG << "BeginInputFile: s: " << fi->source() << " t: " << fi->type() << " n: " << fi->fileName()
453 << " g: " << fi->fileGuid() << endmsg;
454
455 if ( findComp( fi->source(), pit ) ) {
456 DEBMSG << " found component: " << endmsg;
457 while ( pit.first != pit.second ) {
458 IIoComponent* c = pit.first->first;
459 IoComponentEntry e = pit.first->second;
460 DEBMSG << " c: " << c->name() << " " << e << endmsg;
461
462 ++pit.first;
463 }
464 } else {
465 DEBMSG << " could not find component \"" << fi->source() << "\"!" << endmsg;
466 }
467
468 } else if ( i.type() == IncidentType::BeginOutputFile ) {
469
470 const FileIncident* fi = dynamic_cast<const FileIncident*>( &i );
471 DEBMSG << "BeginOutputFile: s: " << fi->source() << " t: " << fi->type() << " n: " << fi->fileName()
472 << " g: " << fi->fileGuid() << endmsg;
473
474 if ( findComp( fi->source(), pit ) ) {
475 DEBMSG << " found component: " << endmsg;
476 while ( pit.first != pit.second ) {
477 IIoComponent* c = pit.first->first;
478 IoComponentEntry e = pit.first->second;
479 DEBMSG << " c: " << c->name() << " " << e << endmsg;
480
481 ++pit.first;
482 }
483 } else {
484 DEBMSG << " could not find component \"" << fi->source() << "\"!" << endmsg;
485 }
486 }
487}
#define DEBMSG
This file contains the class definition for the FileIncident class.
std::ostream & operator<<(std::ostream &os, const IIoComponentMgr::IoMode::Type &m)
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition MsgStream.h:198
#define ON_DEBUG
#define DECLARE_COMPONENT(type)
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
MsgStream & warning() const
shortcut for the method msgStream(MSG::WARNING)
MsgStream & debug() const
shortcut for the method msgStream(MSG::DEBUG)
MsgStream & info() const
shortcut for the method msgStream(MSG::INFO)
This class is the FileIncident.
const std::string & fileName() const
const std::string & fileGuid() const
virtual unsigned long addRef() const =0
Increment the reference count of Interface instance.
virtual const std::string & name() const =0
Retrieve the name of the instance.
Base class for all Incidents (computing events).
Definition Incident.h:24
const std::string & type() const
Access to the incident type.
Definition Incident.h:43
const std::string & source() const
Access to the source of the incident.
Definition Incident.h:49
bool io_hasitem(IIoComponent *iocomponent) const override
: check if the registry contains a given IIoComponent
StatusCode io_register(IIoComponent *iocomponent) override
: allow a IIoComponent to register itself with this manager so appropriate actions can be taken when ...
Gaudi::Property< std::vector< std::string > > m_directio_patterns
search patterns for special file names (direct I/O protocols)
StatusCode finalize() override
StatusCode io_update_all(const std::string &work_dir) override
: Update all IIoComponents with a new work directory
StatusCode initialize() override
Gaudi Service Implementation.
std::vector< std::string > io_retrieve(IIoComponent *iocomponent) override
: retrieve all registered filenames for a given IIoComponent
bool findComp(IIoComponent *, const std::string &, iodITR &) const
IoDict_t::const_iterator iodITR
StatusCode io_update(IIoComponent *iocomponent, const std::string &old_fname, const std::string &new_fname) override
: allow a IIoComponent to update the contents of the registry with a new file name
StatusCode io_reinitialize() override
: reinitialize the I/O subsystem.
bool io_contains(IIoComponent *iocomponent, const std::string &fname) const override
: check if the registry contains a given IIoComponent and that component had
IoRegistry_t m_ioregistry
Registry of IIoComponents.
std::string list() const
IoStack_t m_iostack
Stack of IIoComponents to properly handle order of registration.
StatusCode io_finalize() override
: finalize the I/O subsystem.
void handle(const Incident &) override
SmartIF< IFace > service(const std::string &name, bool createIf=true) const
Definition Service.h:79
StatusCode initialize() override
Definition Service.cpp:118
This class is used for returning status codes from appropriate routines.
Definition StatusCode.h:64
constexpr static const auto SUCCESS
Definition StatusCode.h:99
constexpr static const auto FAILURE
Definition StatusCode.h:100
STL namespace.
std::string m_oldfname
IIoComponentMgr::IoMode::Type m_iomode