CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
FileLocator.cc
Go to the documentation of this file.
4 
5 #include <boost/algorithm/string.hpp>
6 #include <boost/algorithm/string/replace.hpp>
7 
8 #include <cstdlib>
9 #include <stdexcept>
10 #include <fstream>
11 #include <iostream>
12 #include <sstream>
13 
14 namespace {
15 
16  std::string replaceWithRegexp(std::smatch const& matches, std::string const& outputFormat) {
17  std::string result = outputFormat;
18  std::stringstream str;
19 
20  // std::cerr << "Output format: "<< outputFormat << std::endl;
21  for (size_t i = 1; i < matches.size(); ++i) {
22  str.str("");
23  str << "$" << i;
24  // std::cerr << "Current match: " << matches[i] << std::endl;
25  std::string const matchedString(matches[i].first, matches[i].second);
26  if (!matchedString.empty())
27  boost::algorithm::replace_all(result, str.str(), matchedString);
28  }
29  // std::cerr << "Final string: " << result << std::endl;
30  return result;
31  }
32 
33  constexpr char const* const kEmptyString = "";
34 
35  const char* safe(const char* iCheck) {
36  if (iCheck == nullptr) {
37  return kEmptyString;
38  }
39  return iCheck;
40  }
41 
42 } // namespace
43 
44 namespace edm {
45  FileLocator::FileLocator(std::string const& catUrl, unsigned iCatalog) : m_destination("any") {
46  init(catUrl, iCatalog);
47 
48  // std::cout << m_protocols.size() << " protocols" << std::endl;
49  // std::cout << m_directRules[m_protocols[0]].size() << " rules" << std::endl;
50  }
51 
53 
54  std::string FileLocator::pfn(std::string const& ilfn) const { return convert(ilfn, m_directRules, true); }
55 
56  std::string FileLocator::lfn(std::string const& ipfn) const { return convert(ipfn, m_inverseRules, false); }
57 
59  std::string out = "";
60 
61  for (size_t pi = 0, pe = m_protocols.size(); pi != pe; ++pi) {
62  out = applyRules(rules, m_protocols[pi], m_destination, direct, input);
63  if (!out.empty())
64  return out;
65  }
66  return out;
67  }
68 
69  void FileLocator::parseRule(tinyxml2::XMLElement* ruleElement, ProtocolRules& rules) {
70  if (!ruleElement) {
71  throw cms::Exception("TrivialFileCatalog", std::string("TrivialFileCatalog::connect: Malformed trivial catalog"));
72  }
73 
74  auto const protocol = safe(ruleElement->Attribute("protocol"));
75  auto destinationMatchRegexp = ruleElement->Attribute("destination-match");
76  if (destinationMatchRegexp == nullptr or destinationMatchRegexp[0] == 0) {
77  destinationMatchRegexp = ".*";
78  }
79 
80  auto const pathMatchRegexp = safe(ruleElement->Attribute("path-match"));
81  auto const result = safe(ruleElement->Attribute("result"));
82  auto const chain = safe(ruleElement->Attribute("chain"));
83 
84  Rule rule;
85  rule.pathMatch.assign(pathMatchRegexp);
86  rule.destinationMatch.assign(destinationMatchRegexp);
87  rule.result = result;
88  rule.chain = chain;
89  rules[protocol].emplace_back(std::move(rule));
90  }
91 
92  void FileLocator::init(std::string const& catUrl, unsigned iCatalog) {
93  std::string m_url = catUrl;
94 
95  if (m_url.empty()) {
96  Service<SiteLocalConfig> localconfservice;
97  if (!localconfservice.isAvailable())
98  throw cms::Exception("TrivialFileCatalog", "edm::SiteLocalConfigService is not available");
99  if (iCatalog >= localconfservice->dataCatalogs().size())
100  throw cms::Exception("TrivialFileCatalog", "edm::FileLocator: Request nonexistence data catalog");
101  m_url = localconfservice->dataCatalogs()[iCatalog];
102  }
103 
104  if (m_url.find("file:") == std::string::npos) {
105  throw cms::Exception("TrivialFileCatalog",
106  "TrivialFileCatalog::connect: Malformed url for file catalog configuration");
107  }
108 
109  m_url = m_url.erase(0, m_url.find(':') + 1);
110 
111  std::vector<std::string> tokens;
112  boost::algorithm::split(tokens, m_url, boost::is_any_of(std::string("?")));
113  m_filename = tokens[0];
114 
115  if (tokens.size() == 2) {
116  std::string const options = tokens[1];
117  std::vector<std::string> optionTokens;
118  boost::algorithm::split(optionTokens, options, boost::is_any_of(std::string("&")));
119 
120  std::string const equalSign("=");
121  std::string const comma(",");
122 
123  for (size_t oi = 0, oe = optionTokens.size(); oi != oe; ++oi) {
124  std::string const option = optionTokens[oi];
125  std::vector<std::string> argTokens;
126  boost::algorithm::split(argTokens, option, boost::is_any_of(equalSign));
127 
128  if (argTokens.size() != 2) {
129  throw cms::Exception("TrivialFileCatalog",
130  "TrivialFileCatalog::connect: Malformed url for file catalog configuration");
131  }
132 
133  if (argTokens[0] == "protocol") {
134  boost::algorithm::split(m_protocols, argTokens[1], boost::is_any_of(comma));
135  } else if (argTokens[0] == "destination") {
136  m_destination = argTokens[1];
137  }
138  }
139  }
140 
141  if (m_protocols.empty()) {
142  throw cms::Exception("TrivialFileCatalog",
143  "TrivialFileCatalog::connect: protocol was not supplied in the contact string");
144  }
145 
146  std::ifstream configFile;
147  configFile.open(m_filename.c_str());
148 
149  //
150  // std::cout << "Using catalog configuration " << m_filename << std::endl;
151 
152  if (!configFile.good() || !configFile.is_open()) {
153  throw cms::Exception("TrivialFileCatalog",
154  "TrivialFileCatalog::connect: Unable to open trivial file catalog " + m_filename);
155  }
156 
157  configFile.close();
158 
159  tinyxml2::XMLDocument doc;
160  auto loadErr = doc.LoadFile(m_filename.c_str());
161  if (loadErr != tinyxml2::XML_SUCCESS) {
162  throw cms::Exception("TrivialFileCatalog")
163  << "tinyxml file load failed with error : " << doc.ErrorStr() << std::endl;
164  }
165  /* trivialFileCatalog matches the following xml schema
166  FIXME: write a proper DTD
167  <storage-mapping>
168  <lfn-to-pfn protocol="direct" destination-match=".*"
169  path-match="lfn/guid match regular expression"
170  result="/castor/cern.ch/cms/$1"/>
171  <pfn-to-lfn protocol="srm"
172  path-match="lfn/guid match regular expression"
173  result="$1"/>
174  </storage-mapping>
175  */
176  auto rootElement = doc.RootElement();
177  /*first of all do the lfn-to-pfn bit*/
178  for (auto el = rootElement->FirstChildElement("lfn-to-pfn"); el != nullptr;
179  el = el->NextSiblingElement("lfn-to-pfn")) {
181  }
182 
183  /*Then we handle the pfn-to-lfn bit*/
184  for (auto el = rootElement->FirstChildElement("pfn-to-lfn"); el != nullptr;
185  el = el->NextSiblingElement("pfn-to-lfn")) {
187  }
188  }
189 
191  std::string const& protocol,
192  std::string const& destination,
193  bool direct,
194  std::string name) const {
195  // std::cerr << "Calling apply rules with protocol: " << protocol << "\n destination: " << destination << "\n " << " on name " << name << std::endl;
196 
197  ProtocolRules::const_iterator const rulesIterator = protocolRules.find(protocol);
198  if (rulesIterator == protocolRules.end()) {
199  return "";
200  }
201 
202  Rules const& rules = (*(rulesIterator)).second;
203 
204  std::smatch destinationMatches;
205  std::smatch nameMatches;
206 
207  /* Look up for a matching rule*/
208  for (Rules::const_iterator i = rules.begin(); i != rules.end(); ++i) {
209  if (!std::regex_match(destination, destinationMatches, i->destinationMatch)) {
210  continue;
211  }
212 
213  if (!std::regex_match(name, i->pathMatch)) {
214  continue;
215  }
216 
217  // std::cerr << "Rule " << i->pathMatch << "matched! " << std::endl;
218 
219  std::string const chain = i->chain;
220  if ((direct == true) && (!chain.empty())) {
221  name = applyRules(protocolRules, chain, destination, direct, name);
222  if (name.empty()) {
223  return "";
224  }
225  }
226 
227  std::regex_match(name, nameMatches, i->pathMatch);
228  name = replaceWithRegexp(nameMatches, i->result);
229 
230  if ((direct == false) && (!chain.empty())) {
231  name = applyRules(protocolRules, chain, destination, direct, name);
232  }
233  return name;
234  }
235  return "";
236  }
237 } // namespace edm
std::map< std::string, Rules > ProtocolRules
Definition: FileLocator.h:35
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventIDconst &, edm::Timestampconst & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
std::string lfn(std::string const &ipfn) const
Definition: FileLocator.cc:56
std::string m_destination
Definition: FileLocator.h:57
void init(std::string const &catUrl, unsigned iCatalog)
Definition: FileLocator.cc:92
static std::string const input
Definition: EdmProvDump.cc:47
tuple result
Definition: mps_fire.py:311
const Double_t pi
U second(std::pair< T, U > const &p)
ProtocolRules m_inverseRules
Definition: FileLocator.h:52
def move
Definition: eostools.py:511
bool isAvailable() const
Definition: Service.h:40
std::string convert(std::string const &input, ProtocolRules const &rules, bool direct) const
Definition: FileLocator.cc:58
std::string pfn(std::string const &ilfn) const
Definition: FileLocator.cc:54
std::string m_filename
Definition: FileLocator.h:55
FileLocator(std::string const &catUrl, unsigned iCatalog=0)
Definition: FileLocator.cc:45
ProtocolRules m_directRules
Definition: FileLocator.h:50
static const char kEmptyString[1]
std::vector< Rule > Rules
Definition: FileLocator.h:34
std::vector< std::string > m_protocols
Definition: FileLocator.h:56
void parseRule(tinyxml2::XMLElement *ruleNode, ProtocolRules &rules)
Definition: FileLocator.cc:69
std::string applyRules(ProtocolRules const &protocolRules, std::string const &protocol, std::string const &destination, bool direct, std::string name) const
Definition: FileLocator.cc:190
#define str(s)