00001 #include "GaudiKernel/DeclareFactoryEntries.h"
00002 #include "GaudiKernel/strcasecmp.h"
00003 #include "GaudiKernel/MsgStream.h"
00004 #include "Reflex/PluginService.h"
00005 #include "MultiFileCatalog.h"
00006 #include <stdexcept>
00007 #include <algorithm>
00008
00009 namespace Gaudi { std::string createGuidAsString(); }
00010
00011 using ROOT::Reflex::PluginService;
00012 using namespace Gaudi;
00013 using namespace std;
00014 DECLARE_NAMESPACE_SERVICE_FACTORY(Gaudi,MultiFileCatalog)
00015
00016 namespace {
00017 template <class V,class F>
00018 bool _findX0Bool(V& array, F pmf, bool invert) {
00019 for(typename V::const_iterator i=array.begin(); i != array.end(); ++i) {
00020 bool res = invert ? !((*i)->*pmf)() : ((*i)->*pmf)();
00021 if ( !res ) return false;
00022 }
00023 return true;
00024 }
00025 }
00026
00027 MultiFileCatalog::MultiFileCatalog(const std::string& nam, ISvcLocator* svc)
00028 : base_class(nam, svc), m_started(false), m_oldNames()
00029 {
00030 declareProperty("Catalogs", m_catalogNames, "The list of Catalogs")
00031 -> declareUpdateHandler ( &Gaudi::MultiFileCatalog::propHandler, this ) ;
00032 m_catalogNames.push_back("xmlcatalog_file:test_catalog.xml");
00033 }
00034
00035 MultiFileCatalog::~MultiFileCatalog() {
00036 }
00037
00038 StatusCode MultiFileCatalog::initialize() {
00039 CatalogNames::const_iterator i;
00040 std::string current = "";
00041 if ( !Service::initialize().isSuccess() ) {
00042 printError("Failed to initialize service base class.",false);
00043 return StatusCode::SUCCESS;
00044 }
00045 try {
00046 for(i=m_catalogNames.begin(); i != m_catalogNames.end(); ++i) {
00047 current = *i;
00048 addCatalog(*i);
00049 }
00050 init();
00051 return StatusCode::SUCCESS;
00052 }
00053 catch(const std::exception& ) {
00054 printError("Cannot add file catalog:"+current,false);
00055 }
00056 return StatusCode::FAILURE;
00057 }
00058
00059 StatusCode MultiFileCatalog::finalize() {
00060 commit();
00061 _exec(&IFileCatalog::release);
00062 m_catalogs.clear();
00063 m_started = false;
00064 return Service::finalize();
00065 }
00066
00068 std::string MultiFileCatalog::createFID() const {
00069 return createGuidAsString();
00070 }
00071
00072 MultiFileCatalog::CSTR MultiFileCatalog::connectInfo() const {
00073 static string s("MultiCatalog");
00074 return s;
00075 }
00076
00077 IFileCatalog* MultiFileCatalog::getCatalog(CSTR fid,
00078 bool throw_if_not,
00079 bool writable,
00080 bool prt) const
00081 {
00082 for(Catalogs::const_iterator i=m_catalogs.begin(); i != m_catalogs.end(); ++i) {
00083 IFileCatalog* c = *i;
00084 if ( c ) {
00085 if ( writable && c->readOnly() )
00086 continue;
00087 else if ( fid.empty() )
00088 return c;
00089 else if ( !fid.empty() && c->existsFID(fid) )
00090 return c;
00091 }
00092 }
00093 if ( prt ) {
00094 printError("No writable file catalog found which contains FID:"+fid,throw_if_not);
00095 }
00096 else {
00097 MsgStream log(msgSvc(),name());
00098 log << MSG::DEBUG << "No writable file catalog found which contains FID:" << fid << endmsg;
00099 }
00100 return 0;
00101 }
00102
00103 IFileCatalog* MultiFileCatalog::findCatalog(CSTR connect, bool must_be_writable) const {
00104 for(Catalogs::const_iterator i=m_catalogs.begin(); i != m_catalogs.end(); ++i) {
00105 if ( connect == (*i)->connectInfo() )
00106 return (must_be_writable && (*i)->readOnly()) ? 0 : *i;
00107 }
00108 return 0;
00109 }
00110
00111 MultiFileCatalog::Catalogs::iterator
00112 MultiFileCatalog::i_findCatalog(CSTR connect, bool must_be_writable) {
00113 for(Catalogs::iterator i=m_catalogs.begin(); i != m_catalogs.end(); ++i) {
00114 if ( connect == (*i)->connectInfo() ) {
00115 return (must_be_writable && (*i)->readOnly()) ? m_catalogs.end() : i;
00116 }
00117 }
00118 return m_catalogs.end();
00119 }
00120
00121 void MultiFileCatalog::printError(CSTR msg, bool rethrow) const {
00122 MsgStream log(msgSvc(),name());
00123 if ( rethrow ) {
00124 log << MSG::FATAL << msg << endmsg;
00125 throw runtime_error("Catalog> "+msg);
00126 }
00127 log << MSG::ERROR << msg << endmsg;
00128 }
00129
00130 void MultiFileCatalog::addCatalog(CSTR con) {
00131 if ( !con.empty() ) {
00132 if ( 0 == findCatalog(con,false) ) {
00133 static string xml_typ = "Gaudi::XMLFileCatalog";
00134 string::size_type id0 = con.find("_");
00135 string typ = con.substr(0,id0);
00136 string url = con.substr(id0+1);
00137 IInterface* cat = 0;
00138 if ( strncasecmp("xml",typ.c_str(),3) == 0 ) {
00139 cat = PluginService::Create<IInterface*>(xml_typ,url,msgSvc().get());
00140 }
00141 else {
00142 cat = PluginService::Create<IInterface*>(typ,url,serviceLocator().get());
00143 if ( !cat ) {
00144 cat = PluginService::Create<IInterface*>(typ,url,msgSvc().get());
00145 }
00146 }
00147 if ( cat ) {
00148 IFileCatalog* fileCat = 0;
00149 if ( cat->queryInterface(IFileCatalog::interfaceID(),pp_cast<void>(&fileCat)).isSuccess() ) {
00150 addCatalog(fileCat);
00151 cat->release();
00152 return;
00153 }
00154 }
00155 printError("Failed to create catalog connection:"+con,true);
00156 }
00158 return;
00159 }
00160 printError("Got invalid (empty) catalog connection string.",true);
00161 }
00162
00163 void MultiFileCatalog::addCatalog(IFileCatalog* cat) {
00164 if ( cat ) {
00165 cat->addRef();
00166 m_catalogs.push_back(cat);
00167 return;
00168 }
00169 printError("Got invalid catalog to be added to multi catalog.",true);
00170 }
00171
00172 void MultiFileCatalog::removeCatalog(CSTR con) {
00173 if ( con.empty() || con == "*" ) {
00174 _exec(&IFileCatalog::release);
00175 m_catalogs.clear();
00176 return;
00177 }
00178 removeCatalog(findCatalog(con,false));
00179 }
00180
00181 void MultiFileCatalog::removeCatalog(const IFileCatalog* cat) {
00182 if ( cat ) {
00183 Catalogs::iterator i=find(m_catalogs.begin(),m_catalogs.end(),cat);
00184 if ( i != m_catalogs.end() ) {
00185 (*i)->release();
00186 m_catalogs.erase(i);
00187 return;
00188 }
00189 printError("Unknown file catalog -- cannot be removed.",true);
00190 }
00191 printError("Invalid file catalog.",true);
00192 }
00193
00194 void MultiFileCatalog::setWriteCatalog(IFileCatalog* cat) {
00195 if ( cat ) {
00196 if ( !cat->readOnly() ) {
00197 Catalogs::iterator i=find(m_catalogs.begin(),m_catalogs.end(),cat);
00198 if ( i != m_catalogs.end() ) {
00199 m_catalogs.erase(i);
00200 m_catalogs.insert(m_catalogs.begin(),cat);
00201 return;
00202 }
00203 printError("The catalog "+cat->connectInfo()+" is not known.",true);
00204 }
00205 printError("The catalog "+cat->connectInfo()+" is not writable.",true);
00206 }
00207 printError("Invalid file catalog.",true);
00208 }
00209
00210 void MultiFileCatalog::setWriteCatalog(CSTR connect) {
00211 Catalogs::iterator i = i_findCatalog(connect,true);
00212 if ( i == m_catalogs.end() ) {
00213 addCatalog(connect);
00214 setWriteCatalog(findCatalog(connect,true));
00215 return;
00216 }
00217 setWriteCatalog(*i);
00218 }
00219
00220 string MultiFileCatalog::getMetaDataItem(CSTR fid,CSTR attr) const {
00221 std::string result;
00222 for(Catalogs::const_iterator i=m_catalogs.begin(); i != m_catalogs.end(); ++i)
00223 if ( !(result= (*i)->getMetaDataItem(fid,attr)).empty() ) break;
00224 return result;
00225 }
00227 void MultiFileCatalog::registerPFN(CSTR fid, CSTR pfn, CSTR ftype) const {
00228 IFileCatalog* c = getCatalog(fid,false,true,false);
00229 if ( !c ) c = getCatalog("",true,true,true);
00230 c->registerPFN(fid, pfn, ftype);
00231 }
00233 void MultiFileCatalog::registerLFN(CSTR fid, CSTR lfn) const {
00234 IFileCatalog* c = getCatalog(fid,false,true,false);
00235 if ( !c ) c = getCatalog("",true,true,true);
00236 c->registerLFN(fid, lfn);
00237 }
00238
00239 bool MultiFileCatalog::readOnly() const
00240 { return _findX0Bool(m_catalogs,&IFileCatalog::readOnly,false); }
00241
00242 bool MultiFileCatalog::dirty() const
00243 { return _findX0Bool(m_catalogs,&IFileCatalog::dirty,true); }
00244
00245 void MultiFileCatalog::propHandler(Property& )
00246 {
00247
00248 if ( !m_started ) { m_oldNames = m_catalogNames; return; }
00249
00250 if ( m_catalogNames == m_oldNames ) { return; }
00251 m_oldNames = m_catalogNames ;
00252
00253 removeCatalog("") ;
00254
00255 for ( CatalogNames::const_iterator inew = m_catalogNames.begin() ;
00256 m_catalogNames.end() != inew ; ++inew ) { addCatalog ( *inew ) ; }
00257
00258 init() ;
00259
00260 MsgStream log ( msgSvc() , name() ) ;
00261 log << MSG::DEBUG
00262 << "New catalogs to be used: "
00263 << Gaudi::Utils::toString ( m_catalogNames ) << endmsg ;
00264 }