The Gaudi Framework  master (37c0b60a)
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>
22 #include <GaudiKernel/IFileMgr.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 
40 using namespace std;
41 
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;
68  return StatusCode::FAILURE;
69  }
70 
71  auto p_incSvc = service<IIncidentSvc>( "IncidentSvc", true );
72 
73  if ( !p_incSvc ) {
74  error() << "unable to get the IncidentSvc" << endmsg;
75  return StatusCode::FAILURE;
76  } else {
77  p_incSvc->addListener( this, IncidentType::BeginOutputFile, 100, true );
78  p_incSvc->addListener( this, IncidentType::BeginInputFile, 100, true );
79  }
80 
81  return StatusCode::SUCCESS;
82 }
83 
84 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
85 
87  DEBMSG << "--> finalize()" << endmsg;
88 
89  for ( auto& io : m_iostack ) { io->release(); }
90 
91  return StatusCode::SUCCESS;
92 }
93 
94 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
95 
98 bool 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 
111 bool 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 
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 
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 
295 StatusCode 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 
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 
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 
402 bool IoComponentMgr::findComp( IIoComponent* c, const std::string& f, iodITR& itr ) const {
403 
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 
415 
416  pit = m_cdict.equal_range( c );
417  return pit.first != pit.second;
418 }
419 
420 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
421 
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 
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 
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 }
IIoComponentMgr::IoMode::READ
@ READ
Definition: IIoComponentMgr.h:41
IoComponentMgr::findComp
bool findComp(IIoComponent *, const std::string &, iodITR &) const
Definition: IoComponentMgr.cpp:402
Service::initialize
StatusCode initialize() override
Definition: Service.cpp:118
Incident::source
const std::string & source() const
Access to the source of the incident.
Definition: Incident.h:54
std::string
STL class.
IoComponentMgr::io_retrieve
std::vector< std::string > io_retrieve(IIoComponent *iocomponent) override
: retrieve all registered filenames for a given IIoComponent
Definition: IoComponentMgr.cpp:219
IoComponentMgr::iodITR
IoDict_t::const_iterator iodITR
Definition: IoComponentMgr.h:172
IIoComponent
Definition: IIoComponent.h:26
std::list
STL class.
AtlasMCRecoFullPrecedenceDump.path
path
Definition: AtlasMCRecoFullPrecedenceDump.py:49
IoComponentMgr.h
std::pair
IoComponentMgr::finalize
StatusCode finalize() override
Definition: IoComponentMgr.cpp:86
std::vector< std::string >
std::string::find
T find(T... args)
std::back_inserter
T back_inserter(T... args)
IoComponentMgr::handle
void handle(const Incident &) override
Definition: IoComponentMgr.cpp:445
DEBMSG
#define DEBMSG
Definition: IoComponentMgr.cpp:35
IIoComponentMgr::IoMode::RW
@ RW
Definition: IIoComponentMgr.h:41
INamedInterface::name
virtual const std::string & name() const =0
Retrieve the name of the instance.
FileIncident.h
This file contains the class definition for the FileIncident class.
IoComponentMgr::io_hasitem
bool io_hasitem(IIoComponent *iocomponent) const override
: check if the registry contains a given IIoComponent
Definition: IoComponentMgr.cpp:98
std::operator<<
ostream & operator<<(ostream &s, const MyCustomType &m)
Definition: CustomPropertiesAlg.cpp:47
gaudirun.c
c
Definition: gaudirun.py:525
IFileMgr.h
std::any_of
T any_of(T... args)
ServiceHandle.h
FileIncident::fileGuid
const std::string & fileGuid() const
Definition: FileIncident.h:34
IIoComponentMgr::IoMode::Type
Type
Definition: IIoComponentMgr.h:41
IoComponentMgr::initialize
StatusCode initialize() override
Gaudi Service Implementation.
Definition: IoComponentMgr.cpp:63
IIncidentSvc.h
IoComponentMgr::io_register
StatusCode io_register(IIoComponent *iocomponent) override
: allow a IIoComponent to register itself with this manager so appropriate actions can be taken when ...
Definition: IoComponentMgr.cpp:146
StatusCode
Definition: StatusCode.h:65
Gaudi::Units::m
constexpr double m
Definition: SystemOfUnits.h:108
std::ostream
STL class.
IoComponentMgr::io_update
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
Definition: IoComponentMgr.cpp:295
IoComponentMgr
Definition: IoComponentMgr.h:39
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:202
IoComponentMgr::list
std::string list() const
Definition: IoComponentMgr.cpp:433
std::transform
T transform(T... args)
IoComponentMgr::IoComponentEntry::m_iomode
IIoComponentMgr::IoMode::Type m_iomode
Definition: IoComponentMgr.h:133
FileIncident::fileName
const std::string & fileName() const
Definition: FileIncident.h:33
std::ostringstream
STL class.
IoComponentMgr::io_update_all
StatusCode io_update_all(const std::string &work_dir) override
: Update all IIoComponents with a new work directory
Definition: IoComponentMgr.cpp:361
FileIncident
This class is the FileIncident.
Definition: FileIncident.h:27
StatusCode::SUCCESS
constexpr static const auto SUCCESS
Definition: StatusCode.h:100
std::endl
T endl(T... args)
std::begin
T begin(T... args)
std
STL namespace.
DECLARE_COMPONENT
#define DECLARE_COMPONENT(type)
Definition: PluginServiceV1.h:46
IoComponentMgr::IoComponentEntry::m_oldfname
std::string m_oldfname
Definition: IoComponentMgr.h:130
IoComponentMgr::io_finalize
StatusCode io_finalize() override
: finalize the I/O subsystem.
Definition: IoComponentMgr.cpp:379
std::string::empty
T empty(T... args)
std::ostringstream::str
T str(T... args)
IoComponentMgr::IoComponentEntry
Definition: IoComponentMgr.h:129
Incident::type
const std::string & type() const
Access to the incident type.
Definition: Incident.h:48
std::end
T end(T... args)
StatusCode::FAILURE
constexpr static const auto FAILURE
Definition: StatusCode.h:101
ON_DEBUG
#define ON_DEBUG
Definition: IoComponentMgr.cpp:32
Incident
Definition: Incident.h:27
IoComponentMgr::io_contains
bool io_contains(IIoComponent *iocomponent, const std::string &fname) const override
: check if the registry contains a given IIoComponent and that component had
Definition: IoComponentMgr.cpp:111
IInterface::addRef
virtual unsigned long addRef()=0
Increment the reference count of Interface instance.
Property.h
IIoComponentMgr::IoMode::WRITE
@ WRITE
Definition: IIoComponentMgr.h:41
IoComponentMgr::io_reinitialize
StatusCode io_reinitialize() override
: reinitialize the I/O subsystem.
Definition: IoComponentMgr.cpp:273