00001
00002
00003
00004
00005
00006 #include <set>
00007 #include <string>
00008 #include <stdexcept>
00009 #ifndef POOL_TRIVIALFILECATALOG_H
00010 #include "TrivialFileCatalog.h"
00011 #endif
00012 #include "POOLCore/PoolMessageStream.h"
00013 #include "FileCatalog/FCException.h"
00014
00015
00016 #include <xercesc/dom/DOM.hpp>
00017 #include <xercesc/parsers/XercesDOMParser.hpp>
00018 #include <xercesc/util/PlatformUtils.hpp>
00019
00020 #include <cstdlib>
00021 #include <fstream>
00022 #include <iostream>
00023 #include <SealBase/StringList.h>
00024 #include <SealBase/StringOps.h>
00025 #include <SealBase/DebugAids.h>
00026 #include <SealBase/Regexp.h>
00027
00028 using namespace xercesc;
00029
00030 int pool::TrivialFileCatalog::s_numberOfInstances = 0;
00031
00032 inline std::string _toString(const XMLCh *toTranscode)
00033 {
00034 std::string tmp(XMLString::transcode(toTranscode));
00035 return tmp;
00036 }
00037
00038 inline XMLCh* _toDOMS(std::string temp){
00039 XMLCh* buff = XMLString::transcode(temp.c_str());
00040 return buff;
00041 }
00042
00043 pool::TrivialFileCatalog::TrivialFileCatalog ()
00044 : m_connectionStatus (false),
00045 m_fileType ("ROOT_All"),
00046 m_destination ("any")
00047 {
00048 PoolMessageStream trivialLog("TrivialFileCatalog", seal::Msg::Nil);
00049 try {
00050 trivialLog <<seal::Msg::Info << "Xerces-c initialization Number "
00051 << s_numberOfInstances <<seal::endmsg;
00052 if (s_numberOfInstances==0)
00053 XMLPlatformUtils::Initialize();
00054 }
00055 catch (const XMLException& e) {
00056 trivialLog <<seal::Msg::Fatal << "Xerces-c error in initialization \n"
00057 << "Exception message is: \n"
00058 << _toString(e.getMessage()) << seal::endmsg;
00059 throw(std::runtime_error("Standard pool exception : Fatal Error on pool::TrivialFileCatalog"));
00060 }
00061 ++s_numberOfInstances;
00062
00063 }
00064
00065 pool::TrivialFileCatalog::~TrivialFileCatalog ()
00066 {
00067 }
00068
00069 void
00070 pool::TrivialFileCatalog::parseRule (DOMNode *ruleNode,
00071 ProtocolRules &rules)
00072 {
00073 if (! ruleNode)
00074 {
00075 throw FCTransactionException
00076 ("TrivialFileCatalog::connect",
00077 ":Malformed trivial catalog");
00078 }
00079
00080 DOMElement* ruleElement = static_cast<DOMElement *>(ruleNode);
00081
00082 if (! ruleElement)
00083 {
00084 throw FCTransactionException
00085 ("TrivialFileCatalog::connect",
00086 ":Malformed trivial catalog");
00087 }
00088
00089 std::string protocol
00090 = _toString (ruleElement->getAttribute (_toDOMS ("protocol")));
00091 std::string destinationMatchRegexp
00092 = _toString (ruleElement->getAttribute (_toDOMS ("destination-match")));
00093
00094 if (destinationMatchRegexp.empty ())
00095 destinationMatchRegexp = ".*";
00096
00097 std::string pathMatchRegexp
00098 = _toString (ruleElement->getAttribute (_toDOMS ("path-match")));
00099 std::string result
00100 = _toString (ruleElement->getAttribute (_toDOMS ("result")));
00101 std::string chain
00102 = _toString (ruleElement->getAttribute (_toDOMS ("chain")));
00103
00104 Rule rule;
00105 rule.pathMatch.setPattern (pathMatchRegexp);
00106 rule.pathMatch.compile ();
00107 rule.destinationMatch.setPattern (destinationMatchRegexp);
00108 rule.destinationMatch.compile ();
00109 rule.result = result;
00110 rule.chain = chain;
00111 rules[protocol].push_back (rule);
00112 }
00113
00114 void
00115 pool::TrivialFileCatalog::connect ()
00116 {
00117 try
00118 {
00119 PoolMessageStream trivialLog("TrivialFileCatalog", seal::Msg::Nil);
00120 trivialLog << seal::Msg::Info << "Connecting to the catalog "
00121 << m_url << seal::endmsg;
00122
00123 if (m_url.find ("file:") != std::string::npos)
00124 {
00125 m_url = m_url.erase (0,
00126 m_url.find (":") + 1);
00127 }
00128 else
00129 {
00130 throw FCTransactionException
00131 ("TrivialFileCatalog::connect",
00132 ": Malformed url for file catalog configuration");
00133 }
00134
00135 seal::StringList tokens = seal::StringOps::split (m_url, "?");
00136 m_filename = tokens[0];
00137
00138 if (tokens.size () == 2)
00139 {
00140 std::string options = tokens[1];
00141 seal::StringList optionTokens = seal::StringOps::split (options, "&");
00142
00143 for (seal::StringList::iterator option = optionTokens.begin ();
00144 option != optionTokens.end ();
00145 option++)
00146 {
00147 seal::StringList argTokens = seal::StringOps::split (*option, "=") ;
00148 if (argTokens.size () != 2)
00149 {
00150 throw FCTransactionException
00151 ("TrivialFileCatalog::connect",
00152 ": Malformed url for file catalog configuration");
00153 }
00154
00155 std::string key = argTokens[0];
00156 std::string value = argTokens[1];
00157
00158 if (key == "protocol")
00159 {
00160 m_protocols = seal::StringOps::split (value, ",");
00161 }
00162 else if (key == "destination")
00163 {
00164 m_destination = value;
00165 }
00166 }
00167 }
00168
00169 if (m_protocols.empty ())
00170 throw FCTransactionException
00171 ("TrivialFileCatalog::connect",
00172 ": protocol was not supplied in the contact string");
00173
00174 std::ifstream configFile;
00175 configFile.open (m_filename.c_str ());
00176
00177
00178 trivialLog << seal::Msg::Info
00179 << "Using catalog configuration "
00180 << m_filename << seal::endmsg;
00181
00182 if (!configFile.good () || !configFile.is_open ())
00183 {
00184 m_transactionsta = 0;
00185 throw FCTransactionException
00186 ("TrivialFileCatalog::connect",
00187 ": Unable to open trivial file catalog " + m_filename);
00188 }
00189
00190 configFile.close ();
00191
00192 XercesDOMParser* parser = new XercesDOMParser;
00193 parser->setValidationScheme(XercesDOMParser::Val_Auto);
00194 parser->setDoNamespaces(false);
00195 parser->parse(m_filename.c_str());
00196 DOMDocument* doc = parser->getDocument();
00197 ASSERT (doc);
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 {
00213 DOMNodeList *rules =doc->getElementsByTagName(_toDOMS("lfn-to-pfn"));
00214 unsigned int ruleTagsNum =
00215 rules->getLength();
00216
00217
00218
00219 for (unsigned int i=0; i<ruleTagsNum; i++) {
00220 DOMNode* ruleNode = rules->item(i);
00221 parseRule (ruleNode, m_directRules);
00222 }
00223 }
00224
00225 {
00226 DOMNodeList *rules =doc->getElementsByTagName(_toDOMS("pfn-to-lfn"));
00227 unsigned int ruleTagsNum =
00228 rules->getLength();
00229
00230 for (unsigned int i=0; i<ruleTagsNum; i++){
00231 DOMNode* ruleNode = rules->item(i);
00232 parseRule (ruleNode, m_inverseRules);
00233 }
00234 }
00235
00236 m_transactionsta = 1;
00237 }
00238 catch(std::exception& er)
00239 {
00240 m_transactionsta = 0;
00241 throw FCconnectionException("TrivialFileCatalog::connect",er.what());
00242 }
00243 }
00244
00245 void
00246 pool::TrivialFileCatalog::disconnect () const
00247 {
00248 m_transactionsta = 0;
00249 }
00250
00251 void
00252 pool::TrivialFileCatalog::start () const
00253 {
00254 }
00255
00256 void
00257 pool::TrivialFileCatalog::commit (FileCatalog::CommitMode ) const
00258 {
00259 }
00260
00261 void
00262 pool::TrivialFileCatalog::rollback () const
00263 {
00264 throw FCTransactionException
00265 ("TrivialFileCatalog::rollback",
00266 "Trivial catalogs cannot rollback");
00267 }
00268
00269 void
00270 pool::TrivialFileCatalog::registerPFN (const std::string& ,
00271 const std::string& ,
00272 FileCatalog::FileID& ) const
00273 {
00274 throw FCTransactionException
00275 ("TrivialFileCatalog::registerPFN",
00276 "It does not make sense to register PFN for TriviaFileCatalogs");
00277 }
00278
00279 void
00280 pool::TrivialFileCatalog::registerLFN (const std::string& ,
00281 const std::string& ) const
00282 {
00283 throw FCTransactionException
00284 ("TrivialFileCatalog::registerLFN",
00285 "It does not make sense to register LFN for TriviaFileCatalogs");
00286 }
00287
00288 void
00289 pool::TrivialFileCatalog::addReplicaPFN (const std::string& ,
00290 const std::string& ) const
00291 {
00292 throw FCTransactionException
00293 ("TrivialFileCatalog::registerLFN",
00294 "It does not make sense to register PFN for TriviaFileCatalogs");
00295 }
00296
00297 void
00298 pool::TrivialFileCatalog::addPFNtoGuid (const FileCatalog::FileID& ,
00299 const std::string& ,
00300 const std::string& ) const
00301 {
00302 throw FCTransactionException
00303 ("TrivialFileCatalog::addPFNtoGuid",
00304 "It does not make sense to register replicas for TriviaFileCatalogs");
00305 }
00306
00307 void
00308 pool::TrivialFileCatalog::renamePFN (const std::string& ,
00309 const std::string& ) const
00310 {
00311 throw FCTransactionException
00312 ("TrivialFileCatalog::renamePFN",
00313 "It does not make sense to rename PFNs for TrivialFileCatalogs");
00314 }
00315
00316 void
00317 pool::TrivialFileCatalog::lookupFileByPFN (const std::string & pfn,
00318 FileCatalog::FileID & fid,
00319 std::string& filetype) const
00320 {
00321 filetype = m_fileType;
00322 fid = "";
00323 std::string tmpPfn = pfn;
00324
00325 for (seal::StringList::const_iterator protocol = m_protocols.begin ();
00326 protocol != m_protocols.end ();
00327 protocol++)
00328 {
00329 fid = applyRules (m_inverseRules, *protocol, m_destination, false, tmpPfn);
00330 if (! fid.empty ())
00331 {
00332 return;
00333 }
00334 }
00335 }
00336
00337 void
00338 pool::TrivialFileCatalog::lookupFileByLFN (const std::string& lfn,
00339 FileCatalog::FileID& fid) const
00340 {
00341
00342 if (m_transactionsta == 0) {
00343 fid = FileCatalog::FileID();
00344 return;
00345 }
00346
00347
00348 fid = lfn;
00349 }
00350
00351 std::string
00352 replaceWithRegexp (const seal::RegexpMatch matches,
00353 const std::string inputString,
00354 const std::string outputFormat)
00355 {
00356
00357
00358 char buffer[8];
00359 std::string result = outputFormat;
00360
00361 for (int i = 1;
00362 i < matches.numMatches ();
00363 i++)
00364 {
00365
00366 ASSERT (i < 1000000);
00367 sprintf (buffer, "%i", i);
00368 std::string variableRegexp = std::string ("[$]") + buffer;
00369 std::string matchResult = matches.matchString (inputString, i);
00370
00371 seal::Regexp sustitutionToken (variableRegexp);
00372
00373
00374
00375 result = seal::StringOps::replace (result,
00376 sustitutionToken,
00377 matchResult);
00378 }
00379 return result;
00380 }
00381
00382
00383 std::string
00384 pool::TrivialFileCatalog::applyRules (const ProtocolRules& protocolRules,
00385 const std::string & protocol,
00386 const std::string & destination,
00387 bool direct,
00388 std::string name) const
00389 {
00390
00391
00392 const ProtocolRules::const_iterator rulesIterator = protocolRules.find (protocol);
00393 if (rulesIterator == protocolRules.end ())
00394 return "";
00395
00396 const Rules &rules=(*(rulesIterator)).second;
00397
00398
00399 for (Rules::const_iterator i = rules.begin ();
00400 i != rules.end ();
00401 i++)
00402 {
00403 if (! i->destinationMatch.exactMatch (destination))
00404 continue;
00405
00406 if (! i->pathMatch.exactMatch (name))
00407 continue;
00408
00409
00410
00411 std::string chain = i->chain;
00412 if ((direct==true) && (chain != ""))
00413 {
00414 name =
00415 applyRules (protocolRules, chain, destination, direct, name);
00416 }
00417
00418 seal::RegexpMatch matches;
00419 i->pathMatch.match (name, 0, 0, &matches);
00420
00421 name = replaceWithRegexp (matches,
00422 name,
00423 i->result);
00424
00425 if ((direct == false) && (chain !=""))
00426 {
00427 name =
00428 applyRules (protocolRules, chain, destination, direct, name);
00429 }
00430
00431 return name;
00432 }
00433 return "";
00434 }
00435
00436
00437 void
00438 pool::TrivialFileCatalog::lookupBestPFN (const FileCatalog::FileID& fid,
00439 const FileCatalog::FileOpenMode& ,
00440 const FileCatalog::FileAccessPattern& ,
00441 std::string& pfn,
00442 std::string& filetype) const
00443 {
00444 if (m_transactionsta == 0)
00445 throw FCconnectionException("TrivialFileCatalog::lookupBestPFN",
00446 "Catalog not connected");
00447 filetype = m_fileType;
00448
00449 pfn = "";
00450 std::string lfn = fid;
00451
00452 for (seal::StringList::const_iterator protocol = m_protocols.begin ();
00453 protocol != m_protocols.end ();
00454 protocol++)
00455 {
00456 pfn = applyRules (m_directRules,
00457 *protocol,
00458 m_destination,
00459 true,
00460 lfn);
00461 if (! pfn.empty ())
00462 {
00463 return;
00464 }
00465 }
00466 }
00467
00468 void
00469 pool::TrivialFileCatalog::insertPFN (PFNEntry& ) const
00470 {
00471 throw FCTransactionException
00472 ("TrivialFileCatalog::insertPFN",
00473 "It does not make sense to insert PFNs for TrivialFileCatalogs");
00474 }
00475
00476 void
00477 pool::TrivialFileCatalog::insertLFN (LFNEntry& ) const
00478 {
00479 throw FCTransactionException
00480 ("TrivialFileCatalog::insertLFN",
00481 "It does not make sense to insert LFNs for TrivialFileCatalogs");
00482 }
00483
00484 void
00485 pool::TrivialFileCatalog::deletePFN (const std::string& ) const
00486 {
00487 throw FCTransactionException
00488 ("TrivialFileCatalog::deletePFN",
00489 "It does not make sense to delete PFNs for TrivialFileCatalogs");
00490 }
00491
00492 void
00493 pool::TrivialFileCatalog::deleteLFN (const std::string& ) const
00494 {
00495 throw FCTransactionException
00496 ("TrivialFileCatalog::deleteLFN",
00497 "It does not make sense to delete LFNs for TrivialFileCatalogs");
00498 }
00499
00500 void
00501 pool::TrivialFileCatalog::deleteEntry (const FileCatalog::FileID& ) const
00502 {
00503 throw FCTransactionException
00504 ("TrivialFileCatalog::deleteEntry",
00505 "It does not make sense to delete GUIDs for TrivialFileCatalogs");
00506 }
00507
00508 bool
00509 pool::TrivialFileCatalog::isReadOnly () const
00510 {
00511 return true;
00512 }
00513
00514 bool
00515 pool::TrivialFileCatalog::retrievePFN (const std::string& query,
00516 FCBuf<PFNEntry>& buf,
00517 const size_t& )
00518 {
00519 if (m_transactionsta == 0)
00520 throw FCconnectionException("TrivialFileCatalog::lookupBestPFN",
00521 "Catalog not connected");
00522
00523
00524 seal::Regexp grammar ("(lfname|guid)='(.*)'");
00525 seal::RegexpMatch grammarMatches;
00526
00527 grammar.match (query, 0, 0, &grammarMatches);
00528
00529 if (grammarMatches.numMatches () != 3)
00530 {
00531 throw FCTransactionException
00532 ("TrivialFileCatalog::retrievePFN",
00533 "malformed query. the only supported one is lfname='something'"
00534 " or guid='something'");
00535 }
00536
00537 std::string lfn = grammarMatches.matchString (query, 2);
00538
00539 for (seal::StringList::iterator protocol = m_protocols.begin ();
00540 protocol != m_protocols.end ();
00541 protocol++)
00542 {
00543 std::string pfn = applyRules (m_directRules, *protocol, m_destination, true, lfn);
00544 if (! pfn.empty ())
00545 {
00546 buf.push_back (PFNEntry(pfn,
00547 lfn,
00548 m_fileType));
00549 return true;
00550 }
00551 }
00552
00553
00554
00555 buf.push_back (PFNEntry(lfn,
00556 lfn,
00557 m_fileType));
00558
00559 return false;
00560 }
00561
00562 bool
00563 pool::TrivialFileCatalog::retrieveLFN (const std::string& query,
00564 FCBuf<LFNEntry>& buf,
00565 const size_t& )
00566 {
00567 if (m_transactionsta == 0)
00568 throw FCconnectionException("TrivialFileCatalog::lookupBestPFN",
00569 "Catalog not connected");
00570
00571
00572
00573 seal::Regexp grammar ("(pfname|guid)='(.*)'");
00574 seal::RegexpMatch grammarMatches;
00575
00576 grammar.match (query, 0, 0, &grammarMatches);
00577
00578 if (grammarMatches.numMatches () != 3)
00579 {
00580 throw FCTransactionException
00581 ("TrivialFileCatalog::retrieveLFN",
00582 "malformed query. the only supported one is pfname='something'"
00583 " or guid='something'");
00584 }
00585
00586 std::string selector = grammarMatches.matchString (query, 1);
00587 std::string pfn = grammarMatches.matchString (query, 2);
00588
00589
00590 if (selector == "guid")
00591 {
00592 buf.push_back (LFNEntry (pfn,
00593 pfn));
00594 return true;
00595 }
00596
00597
00598 for (seal::StringList::iterator protocol = m_protocols.begin ();
00599 protocol != m_protocols.end ();
00600 protocol++)
00601 {
00602 std::string lfn = applyRules (m_inverseRules, *protocol, m_destination, false, pfn);
00603
00604
00605 if (! lfn.empty ())
00606 {
00607 buf.push_back (LFNEntry(lfn,
00608 lfn));
00609 return true;
00610 }
00611 }
00612
00613
00614
00615 buf.push_back (LFNEntry(pfn,
00616 pfn));
00617
00618 return false;
00619 }
00620
00621 bool
00622 pool::TrivialFileCatalog::retrieveGuid (const std::string& query,
00623 FCBuf<FileCatalog::FileID>& buf,
00624 const size_t& start)
00625 {
00626 typedef FCBuf<LFNEntry> Buffer;
00627
00628 Buffer tmpBuf (10);
00629 bool result = retrieveLFN (query, tmpBuf, start);
00630 std::vector<LFNEntry> tmpVect = tmpBuf.getData ();
00631
00632 for (std::vector<LFNEntry>::iterator i = tmpVect.begin ();
00633 i != tmpVect.end ();
00634 i++)
00635 {
00636 buf.push_back (i->lfname ());
00637 }
00638
00639 return result;
00640 }