Loading [MathJax]/extensions/tex2jax.js
The Gaudi Framework  v31r0 (aeb156f0)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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  switch ( m ) {
35  os << "READ";
36  break;
38  os << "WRITE";
39  break;
41  os << "RW";
42  break;
43  default:
44  os << "INVALID";
45  break;
46  }
47 
48  return os;
49 }
50 
51 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
52 
54  DEBMSG << "--> initialize()" << endmsg;
55 
56  if ( Service::initialize().isFailure() ) {
57  error() << "Unable to initialize Service base class" << endmsg;
58  return StatusCode::FAILURE;
59  }
60 
61  IIncidentSvc* p_incSvc( 0 );
62 
63  if ( service( "IncidentSvc", p_incSvc, true ).isFailure() ) {
64  error() << "unable to get the IncidentSvc" << endmsg;
65  return StatusCode::FAILURE;
66  } else {
67  p_incSvc->addListener( this, IncidentType::BeginOutputFile, 100, true );
68  p_incSvc->addListener( this, IncidentType::BeginInputFile, 100, true );
69  }
70 
71  return StatusCode::SUCCESS;
72 }
73 
74 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
75 
77  DEBMSG << "--> finalize()" << endmsg;
78 
79  return StatusCode::SUCCESS;
80 }
81 
82 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
83 
86 bool IoComponentMgr::io_hasitem( IIoComponent* iocomponent ) const {
87  DEBMSG << "--> io_hasitem()" << endmsg;
88  if ( 0 == iocomponent ) { return false; }
89  const std::string& ioname = iocomponent->name();
90  IoRegistry_t::const_iterator io = m_ioregistry.find( ioname );
91  return io != m_ioregistry.end();
92 }
93 
94 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
95 
99 bool IoComponentMgr::io_contains( IIoComponent* iocomponent, const std::string& fname ) const {
100  DEBMSG << "--> io_contains()" << endmsg;
101  if ( 0 == iocomponent ) { return false; }
102  const std::string& ioname = iocomponent->name();
103 
104  DEBMSG << "io_contains: c: " << ioname << " f: " << fname << endmsg;
105 
106  pair<iodITR, iodITR> fit = m_cdict.equal_range( iocomponent );
107  if ( fit.first == fit.second ) {
108  return false;
109  } else {
110  iodITR it;
111  for ( it = fit.first; it != fit.second; ++it ) {
112  IoComponentEntry ioe = it->second;
113  DEBMSG << " " << ioe << endmsg;
114  if ( ioe.m_oldfname == "" ) {
115  error() << "IIoComponent " << ioname << " has empty old filename" << endmsg;
116  return false;
117  } else if ( ioe.m_oldfname == fname ) {
118  return true;
119  }
120  }
121  }
122 
123  return false;
124 }
125 
126 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
127 
135  if ( !iocomponent ) {
136  error() << "io_register (component) received a NULL pointer !" << endmsg;
137  return StatusCode::FAILURE;
138  }
139  const std::string& ioname = iocomponent->name();
140  DEBMSG << "--> io_register(" << ioname << ")" << endmsg;
141  auto itr = m_ioregistry.find( ioname );
142  if ( itr == m_ioregistry.end() ) {
143  DEBMSG << " registering IoComponent \"" << ioname << "\"" << endmsg;
144  iocomponent->addRef(); // ownership...
145  m_ioregistry[ioname] = iocomponent;
146  m_iostack.push_back( iocomponent );
147  } else {
148  info() << "IoComponent[" << iocomponent->name() << "] already registered @" << (void*)itr->second << endmsg;
149  }
150  return StatusCode::SUCCESS;
151 }
152 
153 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
154 
162  const std::string& fname, const std::string& pfn ) {
163  if ( 0 == iocomponent ) { return StatusCode::FAILURE; }
164  const std::string& ioname = iocomponent->name();
165 
166  DEBMSG << "--> io_register(" << ioname << "," << ( ( iomode == IIoComponentMgr::IoMode::READ ) ? "R" : "W" ) << ","
167  << fname << ")" << endmsg;
168 
169  if ( !io_hasitem( iocomponent ) ) {
170  if ( !io_register( iocomponent ).isSuccess() ) {
171  error() << "could not register component [" << iocomponent->name() << "] "
172  << "with the I/O component manager !" << endmsg;
173  return StatusCode::FAILURE;
174  }
175  }
176 
177  pair<iodITR, iodITR> fit = m_cdict.equal_range( iocomponent );
178  if ( fit.first != fit.second ) {
179  for ( iodITR it = fit.first; it != fit.second; ++it ) {
180  IoComponentEntry ioe = it->second;
181  if ( ioe.m_oldfname == fname ) {
182  if ( ioe.m_iomode == iomode ) {
183  info() << "IoComponent " << ioname << " has already had file " << fname << " registered with i/o mode "
184  << iomode << endmsg;
185  return StatusCode::SUCCESS;
186  } else {
187  warning() << "IoComponent " << ioname << " has already had file " << fname
188  << " registered with a different i/o mode " << ioe.m_iomode << " - now trying " << iomode << endmsg;
189  }
190  }
191  }
192  }
193 
194  // We need to take into account that boost::filesystem::absolute() does not work with direct I/O inputs
195  const std::string& tmp_name = ( pfn.empty() ? fname : pfn );
196  bool special_case =
198  [&]( const std::string& pf ) { return boost::algorithm::contains( tmp_name, pf ); } );
199  IoComponentEntry ioc( fname, ( special_case ? tmp_name : boost::filesystem::absolute( tmp_name ).string() ), iomode );
201 
202  return StatusCode::SUCCESS;
203 }
204 
210 
211  // Find component and copy all registered file names
212  if ( iocomponent != nullptr && findComp( iocomponent, pit ) ) {
213  std::transform( pit.first, pit.second, std::back_inserter( fnames ),
214  []( const auto& itr ) { return itr.second.m_oldfname; } );
215  }
216  return fnames;
217 }
218 
219 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
220 
225  if ( 0 == iocomponent ) { return StatusCode::FAILURE; }
226 
227  std::string ofname = fname;
228  const std::string& ioname = iocomponent->name();
229 
230  DEBMSG << "--> io_retrieve(" << ioname << "," << fname << ")" << endmsg;
231 
232  iodITR it;
233  if ( !findComp( iocomponent, ofname, it ) ) {
234  DEBMSG << "could not find c: " << ioname << " old_f: " << ofname << endmsg;
235  return StatusCode::FAILURE;
236  } else {
237 
238  IoDict_t::iterator it;
239  for ( it = m_cdict.equal_range( iocomponent ).first; it != m_cdict.equal_range( iocomponent ).second; ++it ) {
240 
241  if ( it->second.m_oldfname == ofname ) {
242  DEBMSG << "retrieving new name for the component " << iocomponent->name() << " old name: " << ofname
243  << ", new name: " << it->second.m_newfname << endmsg;
244  fname = it->second.m_newfname;
245  return StatusCode::SUCCESS;
246  }
247  }
248  }
249 
250  DEBMSG << "Unexpected error! Unable to find entry in the dictionary corresponding to old filename: " << ofname
251  << endmsg;
252  return StatusCode::FAILURE;
253 }
254 
255 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
256 
262  ON_DEBUG {
263  debug() << "--> io_reinitialize()" << endmsg;
264  debug() << "reinitializing I/O subsystem..." << endmsg;
265  debug() << "Listing all monitored entries: " << std::endl;
266  debug() << list() << endmsg;
267  }
268 
269  bool allgood = true;
270  for ( auto& io : m_iostack ) {
271  DEBMSG << " [" << io->name() << "]->io_reinit()..." << endmsg;
272  if ( !io->io_reinit().isSuccess() ) {
273  allgood = false;
274  error() << "problem in [" << io->name() << "]->io_reinit() !" << endmsg;
275  }
276  // we are done with this guy... release it
277  io->release();
278  }
279 
280  // we are done.
281  // FIXME: shall we allow for multiple io_reinitialize ?
282  // m_iostack.clear();
283  // m_ioregistry.clear();
284  // m_cdict.clear();
285 
286  return allgood ? StatusCode::SUCCESS : StatusCode::FAILURE;
287 }
288 
289 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
290 
291 StatusCode IoComponentMgr::io_update( IIoComponent* ioc, const std::string& old_fname, const std::string& new_fname ) {
292 
293  DEBMSG << "--> io_update(" << ioc->name() << "," << old_fname << "," << new_fname << ")" << endmsg;
294 
295  IoDict_t::iterator it;
296  for ( it = m_cdict.equal_range( ioc ).first; it != m_cdict.equal_range( ioc ).second; ++it ) {
297 
298  if ( it->second.m_oldfname == old_fname ) {
299  DEBMSG << "updating " << ioc->name() << " f: " << old_fname << " -> " << new_fname << endmsg;
300  it->second.m_newfname = new_fname;
301  return StatusCode::SUCCESS;
302  }
303  }
304 
305  return StatusCode::FAILURE;
306 }
307 
308 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
309 
311 
312  DEBMSG << "--> io_update(" << ioc->name() << "," << work_dir << ")" << endmsg;
313 
314  IoDict_t::iterator it;
315  for ( it = m_cdict.equal_range( ioc ).first; it != m_cdict.equal_range( ioc ).second; ++it ) {
316 
317  switch ( it->second.m_iomode ) {
319  it->second.m_newfname = it->second.m_oldabspath;
320  break;
321  }
323  boost::filesystem::path oldPath( it->second.m_oldfname );
324  if ( oldPath.is_relative() && oldPath.filename() == oldPath.relative_path() ) {
325 
326  // Only file name was provided for writing. This is the usual mode of operation
327  // ***
328  // NB. In such cases it would make sense to set newfname=oldfname, however this will break
329  // existing client codes, which assume that newfname contains "/"
330  // Thus we set newfname=workdir/oldfname
331  // ***
332 
333  boost::filesystem::path newfname( work_dir );
334  newfname /= oldPath;
335  it->second.m_newfname = newfname.string();
336  } else {
337  // New name should be the old absolute path
338  it->second.m_newfname = it->second.m_oldabspath;
339  }
340 
341  break;
342  }
343  default: {
344  // Don't know how to deal with either RW or INVALID
345  error() << "Unable to update IoComponent for the mode " << it->second.m_iomode << endmsg;
346  return StatusCode::FAILURE;
347  }
348  }
349 
350  } // for
351 
352  return StatusCode::SUCCESS;
353 }
354 
355 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
356 
358  DEBMSG << "-->io_update_all for the directory " << work_dir << endmsg;
359  bool allgood = true;
360  for ( IoStack_t::iterator io = m_iostack.begin(), ioEnd = m_iostack.end(); io != ioEnd; ++io ) {
361  if ( !io_update( *io, work_dir ).isSuccess() ) {
362  allgood = false;
363  error() << "problem in [" << ( *io )->name() << "]->io_update() !" << endmsg;
364  }
365  }
366  return allgood ? StatusCode::SUCCESS : StatusCode::FAILURE;
367 }
368 
369 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
370 
376  ON_DEBUG {
377  debug() << "--> io_finalize()" << endmsg;
378  debug() << "finalizing I/O subsystem..." << endmsg;
379  debug() << "Listing all monitored entries: " << std::endl;
380  debug() << list() << endmsg;
381  }
382 
383  bool allgood = true;
384  // reverse iteration to unwind component dependencies
385  for ( IoStack_t::reverse_iterator io = m_iostack.rbegin(), ioEnd = m_iostack.rend(); io != ioEnd; ++io ) {
386  DEBMSG << " [" << ( *io )->name() << "]->io_finalize()..." << endmsg;
387  if ( !( *io )->io_finalize().isSuccess() ) {
388  allgood = false;
389  error() << "problem in [" << ( *io )->name() << "]->io_finalize() !" << endmsg;
390  }
391  }
392 
393  return allgood ? StatusCode::SUCCESS : StatusCode::FAILURE;
394 }
395 
396 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
397 
398 bool IoComponentMgr::findComp( IIoComponent* c, const std::string& f, iodITR& itr ) const {
399 
401  if ( !findComp( c, pit ) ) {
402  itr = pit.first;
403  return false;
404  }
405  return std::any_of( pit.first, pit.second, [&]( IoDict_t::const_reference i ) { return i.second.m_oldfname == f; } );
406 }
407 
408 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
409 
411 
412  pit = m_cdict.equal_range( c );
413  return pit.first != pit.second;
414 }
415 
416 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
417 
419 
420  pit.first = m_cdict.end();
421  pit.second = m_cdict.end();
422 
423  auto itr = m_ioregistry.find( c );
424  return ( itr != m_ioregistry.end() ) && findComp( itr->second, pit );
425 }
426 
427 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
428 
430 
431  ostringstream ost;
432 
433  ost << "Listing all IoComponents (" << m_cdict.size() << "): " << endl;
434  for ( const auto& i : m_cdict ) { ost << " " << i.first->name() << " " << i.second << endl; }
435 
436  return ost.str();
437 }
438 
439 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
440 
442 
444 
445  if ( i.type() == IncidentType::BeginInputFile ) {
446 
447  const FileIncident* fi = dynamic_cast<const FileIncident*>( &i );
448  DEBMSG << "BeginInputFile: s: " << fi->source() << " t: " << fi->type() << " n: " << fi->fileName()
449  << " g: " << fi->fileGuid() << endmsg;
450 
451  if ( findComp( fi->source(), pit ) ) {
452  DEBMSG << " found component: " << endmsg;
453  while ( pit.first != pit.second ) {
454  IIoComponent* c = pit.first->first;
455  IoComponentEntry e = pit.first->second;
456  DEBMSG << " c: " << c->name() << " " << e << endmsg;
457 
458  ++pit.first;
459  }
460  } else {
461  DEBMSG << " could not find component \"" << fi->source() << "\"!" << endmsg;
462  }
463 
464  } else if ( i.type() == IncidentType::BeginOutputFile ) {
465 
466  const FileIncident* fi = dynamic_cast<const FileIncident*>( &i );
467  DEBMSG << "BeginOutputFile: 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 }
StatusCode finalize() override
StatusCode initialize() override
Definition: Service.cpp:60
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:38
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:44
bool isSuccess() const
Definition: StatusCode.h:267
const std::string & fileName() const
Definition: FileIncident.h:23
T endl(T...args)
std::vector< std::string > io_retrieve(IIoComponent *iocomponent) override
: retrieve all registered filenames for a given IIoComponent
constexpr static const auto SUCCESS
Definition: StatusCode.h:85
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
STL class.
#define DECLARE_COMPONENT(type)
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:50
constexpr double m
Definition: SystemOfUnits.h:92
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 ...
#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 back_inserter(T...args)
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.
constexpr static const auto FAILURE
Definition: StatusCode.h:86
Gaudi::Property< std::vector< std::string > > m_directio_patterns
search patterns for special file names (direct I/O protocols)
virtual unsigned long addRef()=0
Increment the reference count of Interface instance.
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:83
StatusCode io_finalize() override
: finalize the I/O subsystem.
T transform(T...args)
StatusCode io_reinitialize() override
: reinitialize the I/O subsystem.
const std::string & fileGuid() const
Definition: FileIncident.h:24
AttribStringParser::Iterator begin(const AttribStringParser &parser)
IoStack_t m_iostack
Stack of IIoComponents to properly handle order of registration.
Type
the list of available types for ntuples
Definition: TupleObj.h:80
STL class.
T equal_range(T...args)
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:192
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)