MultiFileCatalog.cpp
Go to the documentation of this file.
1 #include "GaudiKernel/strcasecmp.h"
2 #include "GaudiKernel/MsgStream.h"
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 // ----------------------------------------------------------------------------
60 std::string MultiFileCatalog::createFID() const {
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  MsgStream log(msgSvc(),name());
84  log << MSG::DEBUG << "No writable file catalog found which contains FID:" << fid << endmsg;
85  }
86  return nullptr;
87 }
88 // ----------------------------------------------------------------------------
89 IFileCatalog* MultiFileCatalog::findCatalog(CSTR connect, bool must_be_writable) const {
90  auto i = std::find_if(m_catalogs.begin(), m_catalogs.end(),
91  [&](const IFileCatalog* f){
92  return connect == f->connectInfo();
93  } );
94  return ( i!=m_catalogs.end() &&
95  ( !must_be_writable || !(*i)->readOnly() ) ) ? *i : nullptr;
96 }
97 // ----------------------------------------------------------------------------
98 MultiFileCatalog::Catalogs::iterator
99 MultiFileCatalog::i_findCatalog(CSTR connect, bool must_be_writable) {
100  auto i = std::find_if(m_catalogs.begin(), m_catalogs.end(),
101  [&](const IFileCatalog* f){
102  return connect == f->connectInfo();
103  } );
104  if ( i!=m_catalogs.end() && must_be_writable && (*i)->readOnly() ) {
105  i = m_catalogs.end();
106  }
107  return i;
108 }
109 // ----------------------------------------------------------------------------
110 void MultiFileCatalog::printError(CSTR msg, bool rethrow) const {
111  MsgStream log(msgSvc(),name());
112  if ( rethrow ) {
113  log << MSG::FATAL << msg << endmsg;
114  throw runtime_error("Catalog> "+msg);
115  }
116  log << MSG::ERROR << msg << endmsg;
117 }
118 // ----------------------------------------------------------------------------
120  if ( !con.empty() ) {
121  if ( !findCatalog(con,false) ) {
122  static const string xml_typ = "Gaudi::XMLFileCatalog";
123  auto id0 = con.find("_");
124  string typ = con.substr(0,id0);
125  string url = con.substr(id0+1);
126  IInterface* cat = nullptr;
127  if ( strncasecmp("xml",typ.c_str(),3) == 0 ) {
128  cat = IFileCatalog::Factory::create(xml_typ,url,msgSvc().get());
129  } else {
131  Registry& registry = Registry::instance();
132  if (registry.getInfo(typ).type ==
133  typeid(Service::Factory::FuncType).name()) {
134  cat = Service::Factory::create(typ,url,serviceLocator().get());
135  } else if (registry.getInfo(typ).type ==
136  typeid(IFileCatalog::Factory::FuncType).name()) {
137  cat = IFileCatalog::Factory::create(typ,url,msgSvc().get());
138  }
139  }
140  if ( cat ) {
141  auto fileCat = SmartIF<IFileCatalog>( cat ) ;
142  if ( fileCat ) {
143  addCatalog(fileCat.get()); //addCatalog will take care of the refCount of fileCat...
144  return;
145  }
146  }
147  printError("Failed to create catalog connection:"+con,true);
148  }
150  return;
151  }
152  printError("Got invalid (empty) catalog connection string.",true);
153 }
154 // ----------------------------------------------------------------------------
156  if ( cat ) {
157  cat->addRef();
158  m_catalogs.push_back(cat);
159  return;
160  }
161  printError("Got invalid catalog to be added to multi catalog.",true);
162 }
163 // ----------------------------------------------------------------------------
165  if ( con.empty() || con == "*" ) {
166  for_each(m_catalogs, [](IFileCatalog* i) { i->release(); } );
167  m_catalogs.clear();
168  return;
169  }
170  removeCatalog(findCatalog(con,false));
171 }
172 // ----------------------------------------------------------------------------
174  if ( cat ) {
175  auto i=find(m_catalogs.begin(),m_catalogs.end(),cat);
176  if ( i != m_catalogs.end() ) {
177  (*i)->release();
178  m_catalogs.erase(i);
179  return;
180  }
181  printError("Unknown file catalog -- cannot be removed.",true);
182  }
183  printError("Invalid file catalog.",true);
184 }
185 // ----------------------------------------------------------------------------
187  if ( cat ) {
188  if ( !cat->readOnly() ) {
189  auto i=find(m_catalogs.begin(),m_catalogs.end(),cat);
190  if ( i != m_catalogs.end() ) {
191  m_catalogs.erase(i);
192  m_catalogs.insert(m_catalogs.begin(),cat);
193  return;
194  }
195  printError("The catalog "+cat->connectInfo()+" is not known.",true);
196  }
197  printError("The catalog "+cat->connectInfo()+" is not writable.",true);
198  }
199  printError("Invalid file catalog.",true);
200 }
201 // ----------------------------------------------------------------------------
203  auto i = i_findCatalog(connect,true);
204  if ( i == m_catalogs.end() ) {
205  addCatalog(connect);
206  setWriteCatalog(findCatalog(connect,true));
207  return;
208  }
209  setWriteCatalog(*i);
210 }
211 // ----------------------------------------------------------------------------
213  std::string result;
214  for(const auto& i : m_catalogs ) {
215  result = i->getMetaDataItem(fid,attr);
216  if ( !result.empty() ) break;
217  }
218  return result;
219 }
221 void MultiFileCatalog::registerPFN(CSTR fid, CSTR pfn, CSTR ftype) const {
222  IFileCatalog* c = getCatalog(fid,false,true,false);
223  if ( !c ) c = getCatalog("",true,true,true);
224  c->registerPFN(fid, pfn, ftype);
225 }
228  IFileCatalog* c = getCatalog(fid,false,true,false);
229  if ( !c ) c = getCatalog("",true,true,true);
230  c->registerLFN(fid, lfn);
231 }
232 // ----------------------------------------------------------------------------
234 { return std::all_of( std::begin(m_catalogs), std::end(m_catalogs),
235  [](const IFileCatalog* i) { return i->readOnly(); } );
236 }
237 // ----------------------------------------------------------------------------
239 { return std::any_of( std::begin(m_catalogs), std::end(m_catalogs),
240  [](const IFileCatalog* i) { return i->dirty();} ) ;
241 }
242 // ----------------------------------------------------------------------------
244 { for_each(m_catalogs,[](IFileCatalog* i) { i->init(); }); m_started=true; }
245 // ----------------------------------------------------------------------------
247 { for_each(m_catalogs,[](IFileCatalog* i) { i->commit(); } ); }
248 // ----------------------------------------------------------------------------
250 { for_each(m_catalogs, [](IFileCatalog* i) { i->rollback(); } ); }
251 // ----------------------------------------------------------------------------
253 {
254  // not yet initialized
255  if ( !m_started ) { m_oldNames = m_catalogNames; return; } // RETURN
256  // no real change - no action
257  if ( m_catalogNames == m_oldNames ) { return; }
258  m_oldNames = m_catalogNames ;
259  // remove ALL catalogs
260  removeCatalog("") ;
261  // add new catalogs
262  for ( const auto& inew : m_catalogNames ) addCatalog ( inew ) ;
263  // start
264  init() ;
265  //
266  MsgStream log ( msgSvc() , name() ) ;
267  log << MSG::DEBUG
268  << "New catalogs to be used: "
269  << Gaudi::Utils::toString ( m_catalogNames ) << endmsg ;
270 }
tuple c
Definition: gaudirun.py:391
Definition of the MsgStream class used to transmit messages.
Definition: MsgStream.h:24
StatusCode initialize() override
Definition: Service.cpp:63
Small smart pointer class with automatic reference counting for IInterface.
Definition: IConverter.h:14
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.
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:244
StatusCode finalize() override
Definition: Service.cpp:188
void registerLFN(CSTR fid, CSTR lfn) const override
Create a FileID and DOM Node of the LFN with all the attributes.
auto begin(reverse_wrapper< T > &w)
Definition: reverse.h:45
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.
virtual const std::string & connectInfo() const =0
Access to connect string.
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.
auto end(reverse_wrapper< T > &w)
Definition: reverse.h:47
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:26
#define DECLARE_COMPONENT(type)
Definition: PluginService.h:36
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.
const std::string & CSTR
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.
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.
Base class used to extend a class implementing other interfaces.
Definition: extends.h:10
void rollback() override
Save DOM catalog to file.
StatusCode finalize() override
Finalize service object.
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.
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.
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
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...