The Gaudi Framework  v29r0 (ff2e7097)
MultiFileCatalog.cpp
Go to the documentation of this file.
1 #include "MultiFileCatalog.h"
4 #include "createGuidAsString.h"
5 #include <Gaudi/PluginService.h>
6 #include <algorithm>
7 #include <functional>
8 #include <stdexcept>
9 
10 using namespace Gaudi;
11 using namespace std;
12 
13 namespace
14 {
15  template <typename C, typename F>
16  F for_each( C& c, F&& f )
17  {
18  return std::for_each( std::begin( c ), std::end( c ), std::forward<F>( f ) );
19  }
20 }
21 
23 
24 // ----------------------------------------------------------------------------
25 MultiFileCatalog::MultiFileCatalog( const std::string& nam, ISvcLocator* svc ) : base_class( nam, svc )
26 {
27  m_catalogNames.declareUpdateHandler( &Gaudi::MultiFileCatalog::propHandler, this );
28 }
29 // ----------------------------------------------------------------------------
31 {
32  if ( !Service::initialize().isSuccess() ) {
33  printError( "Failed to initialize service base class.", false );
34  return StatusCode::SUCCESS;
35  }
36  std::string current;
37  try {
38  for ( const auto& i : m_catalogNames ) {
39  current = i;
40  addCatalog( i );
41  }
42  init();
43  return StatusCode::SUCCESS;
44  } catch ( const std::exception& /* e */ ) {
45  printError( "Cannot add file catalog:" + current, false );
46  }
47  return StatusCode::FAILURE;
48 }
49 // ----------------------------------------------------------------------------
51 {
52  commit();
53  for_each( m_catalogs, []( IFileCatalog* i ) { i->release(); } );
54  m_catalogs.clear();
55  m_started = false;
56  return Service::finalize();
57 }
58 // ----------------------------------------------------------------------------
61 // ----------------------------------------------------------------------------
63 {
64  static const string s( "MultiCatalog" );
65  return s;
66 }
67 // ----------------------------------------------------------------------------
68 IFileCatalog* MultiFileCatalog::getCatalog( CSTR fid, bool throw_if_not, bool writable, bool prt ) const
69 {
70  for ( const auto& c : m_catalogs ) {
71  if ( !c || ( writable && c->readOnly() ) ) continue;
72  if ( fid.empty() || ( !fid.empty() && c->existsFID( fid ) ) ) return c;
73  }
74  if ( prt ) {
75  printError( "No writable file catalog found which contains FID:" + fid, throw_if_not );
76  } else {
77  debug() << "No writable file catalog found which contains FID:" << fid << endmsg;
78  }
79  return nullptr;
80 }
81 // ----------------------------------------------------------------------------
82 IFileCatalog* MultiFileCatalog::findCatalog( CSTR connect, bool must_be_writable ) const
83 {
84  auto i = std::find_if( m_catalogs.begin(), m_catalogs.end(),
85  [&]( const IFileCatalog* f ) { return connect == f->connectInfo(); } );
86  return ( i != m_catalogs.end() && ( !must_be_writable || !( *i )->readOnly() ) ) ? *i : nullptr;
87 }
88 // ----------------------------------------------------------------------------
89 MultiFileCatalog::Catalogs::iterator MultiFileCatalog::i_findCatalog( CSTR connect, bool must_be_writable )
90 {
91  auto i = std::find_if( m_catalogs.begin(), m_catalogs.end(),
92  [&]( const IFileCatalog* f ) { return connect == f->connectInfo(); } );
93  if ( i != m_catalogs.end() && must_be_writable && ( *i )->readOnly() ) {
94  i = m_catalogs.end();
95  }
96  return i;
97 }
98 // ----------------------------------------------------------------------------
99 void MultiFileCatalog::printError( CSTR msg, bool rethrow ) const
100 {
101  if ( rethrow ) {
102  fatal() << msg << endmsg;
103  throw runtime_error( "Catalog> " + msg );
104  }
105  error() << msg << endmsg;
106 }
107 // ----------------------------------------------------------------------------
109 {
110  if ( !con.empty() ) {
111  if ( !findCatalog( con, false ) ) {
112  static const string xml_typ = "Gaudi::XMLFileCatalog";
113  auto id0 = con.find( "_" );
114  string typ = con.substr( 0, id0 );
115  string url = con.substr( id0 + 1 );
116  IInterface* cat = nullptr;
117  if ( strncasecmp( "xml", typ.c_str(), 3 ) == 0 ) {
118  cat = IFileCatalog::Factory::create( xml_typ, url, msgSvc().get() );
119  } else {
121  Registry& registry = Registry::instance();
122  if ( registry.getInfo( typ ).type == typeid( Service::Factory::FuncType ).name() ) {
123  cat = Service::Factory::create( typ, url, serviceLocator().get() );
124  } else if ( registry.getInfo( typ ).type == typeid( IFileCatalog::Factory::FuncType ).name() ) {
125  cat = IFileCatalog::Factory::create( typ, url, msgSvc().get() );
126  }
127  }
128  if ( cat ) {
129  auto fileCat = SmartIF<IFileCatalog>( cat );
130  if ( fileCat ) {
131  addCatalog( fileCat.get() ); // addCatalog will take care of the refCount of fileCat...
132  return;
133  }
134  }
135  printError( "Failed to create catalog connection:" + con, true );
136  }
138  return;
139  }
140  printError( "Got invalid (empty) catalog connection string.", true );
141 }
142 // ----------------------------------------------------------------------------
144 {
145  if ( cat ) {
146  cat->addRef();
147  m_catalogs.push_back( cat );
148  return;
149  }
150  printError( "Got invalid catalog to be added to multi catalog.", true );
151 }
152 // ----------------------------------------------------------------------------
154 {
155  if ( con.empty() || con == "*" ) {
156  for_each( m_catalogs, []( IFileCatalog* i ) { i->release(); } );
157  m_catalogs.clear();
158  return;
159  }
160  removeCatalog( findCatalog( con, false ) );
161 }
162 // ----------------------------------------------------------------------------
164 {
165  if ( cat ) {
166  auto i = find( m_catalogs.begin(), m_catalogs.end(), cat );
167  if ( i != m_catalogs.end() ) {
168  ( *i )->release();
169  m_catalogs.erase( i );
170  return;
171  }
172  printError( "Unknown file catalog -- cannot be removed.", true );
173  }
174  printError( "Invalid file catalog.", true );
175 }
176 // ----------------------------------------------------------------------------
178 {
179  if ( cat ) {
180  if ( !cat->readOnly() ) {
181  auto i = find( m_catalogs.begin(), m_catalogs.end(), cat );
182  if ( i != m_catalogs.end() ) {
183  m_catalogs.erase( i );
184  m_catalogs.insert( m_catalogs.begin(), cat );
185  return;
186  }
187  printError( "The catalog " + cat->connectInfo() + " is not known.", true );
188  }
189  printError( "The catalog " + cat->connectInfo() + " is not writable.", true );
190  }
191  printError( "Invalid file catalog.", true );
192 }
193 // ----------------------------------------------------------------------------
195 {
196  auto i = i_findCatalog( connect, true );
197  if ( i == m_catalogs.end() ) {
198  addCatalog( connect );
199  setWriteCatalog( findCatalog( connect, true ) );
200  return;
201  }
202  setWriteCatalog( *i );
203 }
204 // ----------------------------------------------------------------------------
205 string MultiFileCatalog::getMetaDataItem( CSTR fid, CSTR attr ) const
206 {
207  std::string result;
208  for ( const auto& i : m_catalogs ) {
209  result = i->getMetaDataItem( fid, attr );
210  if ( !result.empty() ) break;
211  }
212  return result;
213 }
215 void MultiFileCatalog::registerPFN( CSTR fid, CSTR pfn, CSTR ftype ) const
216 {
217  IFileCatalog* c = getCatalog( fid, false, true, false );
218  if ( !c ) c = getCatalog( "", true, true, true );
219  c->registerPFN( fid, pfn, ftype );
220 }
223 {
224  IFileCatalog* c = getCatalog( fid, false, true, false );
225  if ( !c ) c = getCatalog( "", true, true, true );
226  c->registerLFN( fid, lfn );
227 }
228 // ----------------------------------------------------------------------------
230 {
231  return std::all_of( std::begin( m_catalogs ), std::end( m_catalogs ),
232  []( const IFileCatalog* i ) { return i->readOnly(); } );
233 }
234 // ----------------------------------------------------------------------------
236 {
237  return std::any_of( std::begin( m_catalogs ), std::end( m_catalogs ),
238  []( const IFileCatalog* i ) { return i->dirty(); } );
239 }
240 // ----------------------------------------------------------------------------
242 {
243  for_each( m_catalogs, []( IFileCatalog* i ) { i->init(); } );
244  m_started = true;
245 }
246 // ----------------------------------------------------------------------------
248 {
249  for_each( m_catalogs, []( IFileCatalog* i ) { i->commit(); } );
250 }
251 // ----------------------------------------------------------------------------
253 {
254  for_each( m_catalogs, []( IFileCatalog* i ) { i->rollback(); } );
255 }
256 // ----------------------------------------------------------------------------
258 {
259  // not yet initialized
260  if ( !m_started ) {
261  m_oldNames = m_catalogNames;
262  return;
263  } // RETURN
264  // no real change - no action
265  if ( m_catalogNames == m_oldNames ) {
266  return;
267  }
268  m_oldNames = m_catalogNames;
269  // remove ALL catalogs
270  removeCatalog( "" );
271  // add new catalogs
272  for ( const auto& inew : m_catalogNames ) addCatalog( inew );
273  // start
274  init();
275  //
276  debug() << "New catalogs to be used: " << Gaudi::Utils::toString( m_catalogNames ) << endmsg;
277 }
StatusCode initialize() override
Definition: Service.cpp:64
Small smart pointer class with automatic reference counting for IInterface.
Definition: IConverter.h:15
T empty(T...args)
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:25
std::string createFID() const override
Catalog interface.
StatusCode finalize() override
Definition: Service.cpp:174
void registerPFN(CSTR fid, CSTR pfn, CSTR ftype) const override
Create a FileID and DOM Node of the PFN with all the attributes.
std::string getMetaDataItem(CSTR fid, CSTR name) const override
Access metadata item.
std::string toString(const TYPE &obj)
the generic implementation of the type conversion to the string
Definition: ToStream.h:346
void printError(CSTR msg, bool throw_exc=true) const
virtual void commit()=0
Save catalog to file.
STL namespace.
virtual const std::string & connectInfo() const =0
Access to connect string.
void setWriteCatalog(IFileCatalog *cat) override
Define the writable catalog identified by reference.
T end(T...args)
#define DECLARE_COMPONENT(type)
Definition: PluginService.h:33
STL class.
virtual bool readOnly() const =0
Check if the catalog is read-only.
Catalogs::iterator i_findCatalog(CSTR connect, bool must_be_writable)
Find catalog by connect string.
IFileCatalog * getCatalog(CSTR fid, bool throw_if_not, bool writable=true, bool prt=true) const
Find catalog containing a given file identifier.
StatusCode initialize() override
IService implementation.
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:28
Definition of the basic interface.
Definition: IInterface.h:277
PropertyBase base class allowing PropertyBase* collections to be "homogeneous".
Definition: Property.h:32
STL class.
CSTR connectInfo() const override
Access to connect string.
File catalog interface.
Definition: IFileCatalog.h:25
void registerLFN(CSTR fid, CSTR lfn) const override
Create a FileID and DOM Node of the LFN with all the attributes.
T find_if(T...args)
IFileCatalog * findCatalog(CSTR connect, bool must_be_writable) const override
Catalog management.
virtual unsigned long release()=0
Release Interface instance.
std::string createGuidAsString()
Helper function creating file identifier using the UUID mechanism.
bool dirty() const override
Check if the catalog should be updated.
T begin(T...args)
void rollback() override
Save DOM catalog to file.
StatusCode finalize() override
Finalize service object.
T all_of(T...args)
T c_str(T...args)
void init() override
Parse the DOM tree of the XML catalog.
void addCatalog(CSTR connect) override
Add new catalog identified by name to the existing ones.
string s
Definition: gaudirun.py:253
virtual void rollback()=0
Save catalog to file.
In-memory database of the loaded factories.
bool readOnly() const override
Check if the catalog is read-only.
virtual unsigned long addRef()=0
Increment the reference count of Interface instance.
T substr(T...args)
virtual void registerPFN(const std::string &fid, const std::string &pfn, const std::string &ftype) const =0
Create a Node for a FileID and DOM Node of the PFN with all the attributes.
virtual void init()=0
Parse the DOM tree of the XML catalog.
virtual void registerLFN(const std::string &fid, const std::string &lfn) const =0
Create a Node for a FileID and DOM Node of the LFN with all the attributes.
T for_each(T...args)
void commit() override
Save DOM catalog to file.
void removeCatalog(CSTR connect) override
Remove catalog identified by name from the existing ones.
Helper functions to set/get the application return code.
Definition: __init__.py:1
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:209
void propHandler(Details::PropertyBase &)
simple property handle to allow interactive modification of list of the file catalogs ...
virtual bool dirty() const =0
Check if the catalog should be updated.
This class constitutes the core of the XML based FileCatalog API for using POOL within Gaudi...