MultiFileCatalog.cpp
Go to the documentation of this file.
1 #include "MultiFileCatalog.h"
4 #include <Gaudi/PluginService.h>
5 #include <algorithm>
6 #include <functional>
7 #include <stdexcept>
8 
9 namespace Gaudi
10 {
12 }
13 
14 using namespace Gaudi;
15 using namespace std;
16 
17 namespace
18 {
19  template <typename C, typename F>
20  F for_each( C& c, F&& f )
21  {
22  return std::for_each( std::begin( c ), std::end( c ), std::forward<F>( f ) );
23  }
24 }
25 
27 
28 // ----------------------------------------------------------------------------
29 MultiFileCatalog::MultiFileCatalog( const std::string& nam, ISvcLocator* svc ) : base_class( nam, svc )
30 {
31  m_catalogNames.declareUpdateHandler( &Gaudi::MultiFileCatalog::propHandler, this );
32 }
33 // ----------------------------------------------------------------------------
35 {
36  if ( !Service::initialize().isSuccess() ) {
37  printError( "Failed to initialize service base class.", false );
38  return StatusCode::SUCCESS;
39  }
40  std::string current;
41  try {
42  for ( const auto& i : m_catalogNames ) {
43  current = i;
44  addCatalog( i );
45  }
46  init();
47  return StatusCode::SUCCESS;
48  } catch ( const std::exception& /* e */ ) {
49  printError( "Cannot add file catalog:" + current, false );
50  }
51  return StatusCode::FAILURE;
52 }
53 // ----------------------------------------------------------------------------
55 {
56  commit();
57  for_each( m_catalogs, []( IFileCatalog* i ) { i->release(); } );
58  m_catalogs.clear();
59  m_started = false;
60  return Service::finalize();
61 }
62 // ----------------------------------------------------------------------------
65 // ----------------------------------------------------------------------------
67 {
68  static const string s( "MultiCatalog" );
69  return s;
70 }
71 // ----------------------------------------------------------------------------
72 IFileCatalog* MultiFileCatalog::getCatalog( CSTR fid, bool throw_if_not, bool writable, bool prt ) const
73 {
74  for ( const auto& c : m_catalogs ) {
75  if ( !c || ( writable && c->readOnly() ) ) continue;
76  if ( fid.empty() || ( !fid.empty() && c->existsFID( fid ) ) ) return c;
77  }
78  if ( prt ) {
79  printError( "No writable file catalog found which contains FID:" + fid, throw_if_not );
80  } else {
81  debug() << "No writable file catalog found which contains FID:" << fid << endmsg;
82  }
83  return nullptr;
84 }
85 // ----------------------------------------------------------------------------
86 IFileCatalog* MultiFileCatalog::findCatalog( CSTR connect, bool must_be_writable ) const
87 {
88  auto i = std::find_if( m_catalogs.begin(), m_catalogs.end(),
89  [&]( const IFileCatalog* f ) { return connect == f->connectInfo(); } );
90  return ( i != m_catalogs.end() && ( !must_be_writable || !( *i )->readOnly() ) ) ? *i : nullptr;
91 }
92 // ----------------------------------------------------------------------------
93 MultiFileCatalog::Catalogs::iterator MultiFileCatalog::i_findCatalog( CSTR connect, bool must_be_writable )
94 {
95  auto i = std::find_if( m_catalogs.begin(), m_catalogs.end(),
96  [&]( const IFileCatalog* f ) { return connect == f->connectInfo(); } );
97  if ( i != m_catalogs.end() && must_be_writable && ( *i )->readOnly() ) {
98  i = m_catalogs.end();
99  }
100  return i;
101 }
102 // ----------------------------------------------------------------------------
103 void MultiFileCatalog::printError( CSTR msg, bool rethrow ) const
104 {
105  if ( rethrow ) {
106  fatal() << msg << endmsg;
107  throw runtime_error( "Catalog> " + msg );
108  }
109  error() << msg << endmsg;
110 }
111 // ----------------------------------------------------------------------------
113 {
114  if ( !con.empty() ) {
115  if ( !findCatalog( con, false ) ) {
116  static const string xml_typ = "Gaudi::XMLFileCatalog";
117  auto id0 = con.find( "_" );
118  string typ = con.substr( 0, id0 );
119  string url = con.substr( id0 + 1 );
120  IInterface* cat = nullptr;
121  if ( strncasecmp( "xml", typ.c_str(), 3 ) == 0 ) {
122  cat = IFileCatalog::Factory::create( xml_typ, url, msgSvc().get() );
123  } else {
125  Registry& registry = Registry::instance();
126  if ( registry.getInfo( typ ).type == typeid( Service::Factory::FuncType ).name() ) {
127  cat = Service::Factory::create( typ, url, serviceLocator().get() );
128  } else if ( registry.getInfo( typ ).type == typeid( IFileCatalog::Factory::FuncType ).name() ) {
129  cat = IFileCatalog::Factory::create( typ, url, msgSvc().get() );
130  }
131  }
132  if ( cat ) {
133  auto fileCat = SmartIF<IFileCatalog>( cat );
134  if ( fileCat ) {
135  addCatalog( fileCat.get() ); // addCatalog will take care of the refCount of fileCat...
136  return;
137  }
138  }
139  printError( "Failed to create catalog connection:" + con, true );
140  }
142  return;
143  }
144  printError( "Got invalid (empty) catalog connection string.", true );
145 }
146 // ----------------------------------------------------------------------------
148 {
149  if ( cat ) {
150  cat->addRef();
151  m_catalogs.push_back( cat );
152  return;
153  }
154  printError( "Got invalid catalog to be added to multi catalog.", true );
155 }
156 // ----------------------------------------------------------------------------
158 {
159  if ( con.empty() || con == "*" ) {
160  for_each( m_catalogs, []( IFileCatalog* i ) { i->release(); } );
161  m_catalogs.clear();
162  return;
163  }
164  removeCatalog( findCatalog( con, false ) );
165 }
166 // ----------------------------------------------------------------------------
168 {
169  if ( cat ) {
170  auto i = find( m_catalogs.begin(), m_catalogs.end(), cat );
171  if ( i != m_catalogs.end() ) {
172  ( *i )->release();
173  m_catalogs.erase( i );
174  return;
175  }
176  printError( "Unknown file catalog -- cannot be removed.", true );
177  }
178  printError( "Invalid file catalog.", true );
179 }
180 // ----------------------------------------------------------------------------
182 {
183  if ( cat ) {
184  if ( !cat->readOnly() ) {
185  auto i = find( m_catalogs.begin(), m_catalogs.end(), cat );
186  if ( i != m_catalogs.end() ) {
187  m_catalogs.erase( i );
188  m_catalogs.insert( m_catalogs.begin(), cat );
189  return;
190  }
191  printError( "The catalog " + cat->connectInfo() + " is not known.", true );
192  }
193  printError( "The catalog " + cat->connectInfo() + " is not writable.", true );
194  }
195  printError( "Invalid file catalog.", true );
196 }
197 // ----------------------------------------------------------------------------
199 {
200  auto i = i_findCatalog( connect, true );
201  if ( i == m_catalogs.end() ) {
202  addCatalog( connect );
203  setWriteCatalog( findCatalog( connect, true ) );
204  return;
205  }
206  setWriteCatalog( *i );
207 }
208 // ----------------------------------------------------------------------------
209 string MultiFileCatalog::getMetaDataItem( CSTR fid, CSTR attr ) const
210 {
211  std::string result;
212  for ( const auto& i : m_catalogs ) {
213  result = i->getMetaDataItem( fid, attr );
214  if ( !result.empty() ) break;
215  }
216  return result;
217 }
219 void MultiFileCatalog::registerPFN( CSTR fid, CSTR pfn, CSTR ftype ) const
220 {
221  IFileCatalog* c = getCatalog( fid, false, true, false );
222  if ( !c ) c = getCatalog( "", true, true, true );
223  c->registerPFN( fid, pfn, ftype );
224 }
227 {
228  IFileCatalog* c = getCatalog( fid, false, true, false );
229  if ( !c ) c = getCatalog( "", true, true, true );
230  c->registerLFN( fid, lfn );
231 }
232 // ----------------------------------------------------------------------------
234 {
235  return std::all_of( std::begin( m_catalogs ), std::end( m_catalogs ),
236  []( const IFileCatalog* i ) { return i->readOnly(); } );
237 }
238 // ----------------------------------------------------------------------------
240 {
241  return std::any_of( std::begin( m_catalogs ), std::end( m_catalogs ),
242  []( const IFileCatalog* i ) { return i->dirty(); } );
243 }
244 // ----------------------------------------------------------------------------
246 {
247  for_each( m_catalogs, []( IFileCatalog* i ) { i->init(); } );
248  m_started = true;
249 }
250 // ----------------------------------------------------------------------------
252 {
253  for_each( m_catalogs, []( IFileCatalog* i ) { i->commit(); } );
254 }
255 // ----------------------------------------------------------------------------
257 {
258  for_each( m_catalogs, []( IFileCatalog* i ) { i->rollback(); } );
259 }
260 // ----------------------------------------------------------------------------
262 {
263  // not yet initialized
264  if ( !m_started ) {
265  m_oldNames = m_catalogNames;
266  return;
267  } // RETURN
268  // no real change - no action
269  if ( m_catalogNames == m_oldNames ) {
270  return;
271  }
272  m_oldNames = m_catalogNames;
273  // remove ALL catalogs
274  removeCatalog( "" );
275  // add new catalogs
276  for ( const auto& inew : m_catalogNames ) addCatalog( inew );
277  // start
278  init();
279  //
280  debug() << "New catalogs to be used: " << Gaudi::Utils::toString( m_catalogNames ) << endmsg;
281 }
StatusCode initialize() override
Definition: Service.cpp:64
Small smart pointer class with automatic reference counting for IInterface.
Definition: IConverter.h:14
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:367
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:36
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:26
Definition of the basic interface.
Definition: IInterface.h:234
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:24
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()
Create file identifier using 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:245
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:244
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...