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