MultiFileCatalog.cpp
Go to the documentation of this file.
3 #include <Gaudi/PluginService.h>
4 #include "MultiFileCatalog.h"
5 #include <stdexcept>
6 #include <algorithm>
7 #include <functional>
8 
9 namespace Gaudi { std::string createGuidAsString(); }
10 
11 using namespace Gaudi;
12 using namespace std;
13 
14 namespace {
15  template <typename C, typename F>
16  F for_each( C& c, F&& f ) {
17  return std::for_each( std::begin(c), std::end(c), std::forward<F>(f) );
18  }
19 }
20 
22 
23 // ----------------------------------------------------------------------------
25  : base_class(nam, svc)
26 {
27  declareProperty("Catalogs", m_catalogNames, "The list of Catalogs")
28  -> declareUpdateHandler ( &Gaudi::MultiFileCatalog::propHandler, this ) ;
29 }
30 // ----------------------------------------------------------------------------
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  }
45  catch(const std::exception& /* e */) {
46  printError("Cannot add file catalog:"+current,false);
47  }
48  return StatusCode::FAILURE;
49 }
50 // ----------------------------------------------------------------------------
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  return createGuidAsString();
62 }
63 // ----------------------------------------------------------------------------
65  static const string s("MultiCatalog");
66  return s;
67 }
68 // ----------------------------------------------------------------------------
70  bool throw_if_not,
71  bool writable,
72  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) ) )
77  return c;
78  }
79  if ( prt ) {
80  printError("No writable file catalog found which contains FID:"+fid,throw_if_not);
81  }
82  else {
83  debug() << "No writable file catalog found which contains FID:" << fid << endmsg;
84  }
85  return nullptr;
86 }
87 // ----------------------------------------------------------------------------
88 IFileCatalog* MultiFileCatalog::findCatalog(CSTR connect, bool must_be_writable) const {
89  auto i = std::find_if(m_catalogs.begin(), m_catalogs.end(),
90  [&](const IFileCatalog* f){
91  return connect == f->connectInfo();
92  } );
93  return ( i!=m_catalogs.end() &&
94  ( !must_be_writable || !(*i)->readOnly() ) ) ? *i : nullptr;
95 }
96 // ----------------------------------------------------------------------------
97 MultiFileCatalog::Catalogs::iterator
98 MultiFileCatalog::i_findCatalog(CSTR connect, bool must_be_writable) {
99  auto i = std::find_if(m_catalogs.begin(), m_catalogs.end(),
100  [&](const IFileCatalog* f){
101  return connect == f->connectInfo();
102  } );
103  if ( i!=m_catalogs.end() && must_be_writable && (*i)->readOnly() ) {
104  i = m_catalogs.end();
105  }
106  return i;
107 }
108 // ----------------------------------------------------------------------------
109 void MultiFileCatalog::printError(CSTR msg, bool rethrow) const {
110  if ( rethrow ) {
111  fatal() << msg << endmsg;
112  throw runtime_error("Catalog> "+msg);
113  }
114  error() << msg << endmsg;
115 }
116 // ----------------------------------------------------------------------------
118  if ( !con.empty() ) {
119  if ( !findCatalog(con,false) ) {
120  static const string xml_typ = "Gaudi::XMLFileCatalog";
121  auto id0 = con.find("_");
122  string typ = con.substr(0,id0);
123  string url = con.substr(id0+1);
124  IInterface* cat = nullptr;
125  if ( strncasecmp("xml",typ.c_str(),3) == 0 ) {
126  cat = IFileCatalog::Factory::create(xml_typ,url,msgSvc().get());
127  } else {
129  Registry& registry = Registry::instance();
130  if (registry.getInfo(typ).type ==
131  typeid(Service::Factory::FuncType).name()) {
132  cat = Service::Factory::create(typ,url,serviceLocator().get());
133  } else if (registry.getInfo(typ).type ==
134  typeid(IFileCatalog::Factory::FuncType).name()) {
135  cat = IFileCatalog::Factory::create(typ,url,msgSvc().get());
136  }
137  }
138  if ( cat ) {
139  auto fileCat = SmartIF<IFileCatalog>( cat ) ;
140  if ( fileCat ) {
141  addCatalog(fileCat.get()); //addCatalog will take care of the refCount of fileCat...
142  return;
143  }
144  }
145  printError("Failed to create catalog connection:"+con,true);
146  }
148  return;
149  }
150  printError("Got invalid (empty) catalog connection string.",true);
151 }
152 // ----------------------------------------------------------------------------
154  if ( cat ) {
155  cat->addRef();
156  m_catalogs.push_back(cat);
157  return;
158  }
159  printError("Got invalid catalog to be added to multi catalog.",true);
160 }
161 // ----------------------------------------------------------------------------
163  if ( con.empty() || con == "*" ) {
164  for_each(m_catalogs, [](IFileCatalog* i) { i->release(); } );
165  m_catalogs.clear();
166  return;
167  }
168  removeCatalog(findCatalog(con,false));
169 }
170 // ----------------------------------------------------------------------------
172  if ( cat ) {
173  auto i=find(m_catalogs.begin(),m_catalogs.end(),cat);
174  if ( i != m_catalogs.end() ) {
175  (*i)->release();
176  m_catalogs.erase(i);
177  return;
178  }
179  printError("Unknown file catalog -- cannot be removed.",true);
180  }
181  printError("Invalid file catalog.",true);
182 }
183 // ----------------------------------------------------------------------------
185  if ( cat ) {
186  if ( !cat->readOnly() ) {
187  auto i=find(m_catalogs.begin(),m_catalogs.end(),cat);
188  if ( i != m_catalogs.end() ) {
189  m_catalogs.erase(i);
190  m_catalogs.insert(m_catalogs.begin(),cat);
191  return;
192  }
193  printError("The catalog "+cat->connectInfo()+" is not known.",true);
194  }
195  printError("The catalog "+cat->connectInfo()+" is not writable.",true);
196  }
197  printError("Invalid file catalog.",true);
198 }
199 // ----------------------------------------------------------------------------
201  auto i = i_findCatalog(connect,true);
202  if ( i == m_catalogs.end() ) {
203  addCatalog(connect);
204  setWriteCatalog(findCatalog(connect,true));
205  return;
206  }
207  setWriteCatalog(*i);
208 }
209 // ----------------------------------------------------------------------------
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  IFileCatalog* c = getCatalog(fid,false,true,false);
221  if ( !c ) c = getCatalog("",true,true,true);
222  c->registerPFN(fid, pfn, ftype);
223 }
226  IFileCatalog* c = getCatalog(fid,false,true,false);
227  if ( !c ) c = getCatalog("",true,true,true);
228  c->registerLFN(fid, lfn);
229 }
230 // ----------------------------------------------------------------------------
232 { return std::all_of( std::begin(m_catalogs), std::end(m_catalogs),
233  [](const IFileCatalog* i) { return i->readOnly(); } );
234 }
235 // ----------------------------------------------------------------------------
237 { return std::any_of( std::begin(m_catalogs), std::end(m_catalogs),
238  [](const IFileCatalog* i) { return i->dirty();} ) ;
239 }
240 // ----------------------------------------------------------------------------
242 { for_each(m_catalogs,[](IFileCatalog* i) { i->init(); }); m_started=true; }
243 // ----------------------------------------------------------------------------
245 { for_each(m_catalogs,[](IFileCatalog* i) { i->commit(); } ); }
246 // ----------------------------------------------------------------------------
248 { for_each(m_catalogs, [](IFileCatalog* i) { i->rollback(); } ); }
249 // ----------------------------------------------------------------------------
251 {
252  // not yet initialized
253  if ( !m_started ) { m_oldNames = m_catalogNames; return; } // RETURN
254  // no real change - no action
255  if ( m_catalogNames == m_oldNames ) { return; }
256  m_oldNames = m_catalogNames ;
257  // remove ALL catalogs
258  removeCatalog("") ;
259  // add new catalogs
260  for ( const auto& inew : m_catalogNames ) addCatalog ( inew ) ;
261  // start
262  init() ;
263  //
264  debug()
265  << "New catalogs to be used: "
266  << Gaudi::Utils::toString ( m_catalogNames ) << endmsg ;
267 }
StatusCode initialize() override
Definition: Service.cpp:68
Small smart pointer class with automatic reference counting for IInterface.
Definition: IConverter.h:14
T empty(T...args)
IFileCatalog * findCatalog(CSTR connect, bool must_be_writable) const override
Catalog management.
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:25
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.
StatusCode finalize() override
Definition: Service.cpp:193
void registerLFN(CSTR fid, CSTR lfn) const override
Create a FileID and DOM Node of the LFN with all the attributes.
tuple c
Definition: gaudirun.py:391
std::string toString(const TYPE &obj)
the generic implementation of the type conversion to the string
Definition: ToStream.h:371
void printError(CSTR msg, bool throw_exc=true) const
virtual void commit()=0
Save catalog to file.
STL namespace.
void propHandler(Property &)
simple property handle to allow interactive modification of list of the file catalogs ...
void setWriteCatalog(IFileCatalog *cat) override
Define the writable catalog identified by reference.
T end(T...args)
virtual const std::string & connectInfo() const =0
Access to connect string.
#define DECLARE_COMPONENT(type)
Definition: PluginService.h:36
STL class.
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
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.
STL class.
File catalog interface.
Definition: IFileCatalog.h:24
void registerPFN(CSTR fid, CSTR pfn, CSTR ftype) const override
Create a FileID and DOM Node of the PFN with all the attributes.
CSTR connectInfo() const override
Access to connect string.
T find_if(T...args)
Property base class allowing Property* collections to be "homogeneous".
Definition: Property.h:38
virtual unsigned long release()=0
Release Interface instance.
std::string createGuidAsString()
Create file identifier using UUID mechanism.
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.
bool readOnly() const override
Check if the catalog is read-only.
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.
virtual unsigned long addRef()=0
Increment the reference count of Interface instance.
T substr(T...args)
std::string getMetaDataItem(CSTR fid, CSTR name) const override
Access metadata item.
virtual bool readOnly() const =0
Check if the catalog is read-only.
std::string createFID() const override
Catalog interface.
virtual void init()=0
Parse the DOM tree of the XML catalog.
T for_each(T...args)
void commit() override
Save DOM catalog to file.
list i
Definition: ana.py:128
virtual bool dirty() const =0
Check if the catalog should be updated.
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
bool dirty() const override
Check if the catalog should be updated.
This class constitutes the core of the XML based FileCatalog API for using POOL within Gaudi...