IODA Bundle
FileCollector.cc
Go to the documentation of this file.
1 /*
2  * (C) Copyright 1996-2013 ECMWF.
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  * In applying this licence, ECMWF does not waive the privileges and immunities
7  * granted to it by virtue of its status as an intergovernmental organisation nor
8  * does it submit to any jurisdiction.
9  */
10 
11 #include <ctype.h>
12 
13 #include "eckit/filesystem/PathName.h"
14 #include "eckit/log/Timer.h"
15 #include "eckit/config/Resource.h"
16 
17 #include "odc/FileCollector.h"
18 #include "odc/FileMapper.h"
19 
20 using namespace eckit;
21 using namespace std;
22 
23 FileCollector::FileCollector(const FileMapper& fm, MultiHandle& mh)
24 : mapper_(fm),
25  multiHandle_(mh),
26  allFound_()
27 {}
28 
29 string FileCollector::expandTilde(const string& s)
30 {
31  string dhsHome (::getenv("DHSHOME") ? ::getenv("DHSHOME")
32  : ::getenv("TEST_DHSHOME") ? ::getenv("TEST_DHSHOME")
33  : "");
34 
35  if (! dhsHome.size())
36  throw UserError("expandTilde: DHSHOME or TEST_DHSHOME must be set");
37 
38  if (s.size() && s[0] == '~')
39  return dhsHome + "/" + s.substr(1);
40 
41  return s;
42 }
43 
45 
46 string FileCollector::prestageScriptPath(const std::map<std::string,std::vector<std::string> >& r) const
47 {
48  string prestageScript;
49  if (r.find("odbServerPrestageScript") != r.end())
50  {
51  vector<string> odbServerPrestageScripts (r.at("odbServerPrestageScript"));
52  if (odbServerPrestageScripts.size() > 1)
53  throw UserError("odbServerPrestageScript must be one value at most");
54  if (odbServerPrestageScripts.size() == 1)
55  prestageScript = odbServerPrestageScripts[0];
56  }
57  if (prestageScript.size() == 0)
58  prestageScript = string(Resource<string>("$ODB_SERVER_PRESTAGE_SCRIPT", ""));
59  if (prestageScript.size() == 0)
60  prestageScript = string(Resource<string>("odbServerPrestageScript", ""));
61 
62  return expandTilde(prestageScript);
63 }
64 
65 void FileCollector::prestage(const std::map<std::string,std::vector<std::string> >& r, const string& fileName)
66 {
67  static string prestageScript (prestageScriptPath(r));
68  if (prestageScript.size() == 0)
69  return;
70 
71  Timer timer("Prestage " + fileName);
72  stringstream cmd;
73  cmd << prestageScript << " " << fileName;
74  Log::debug() << "Calling prestage script: '" << cmd.str() << "'" << endl;
75  int rc (::system(cmd.str().c_str()));
76  if (rc != 0) {
77  stringstream ss;
78  ss << "prestage command '" << cmd.str() << "' failed (return code: " << rc << ")";
79  Log::error() << ss.str() << endl;
80  throw SeriousBug(ss.str());
81  }
82 }
83 
84 std::vector<std::string> FileCollector::foundFiles() const { return allFound_; }
85 
86 std::vector<eckit::PathName> FileCollector::foundFilesAsPathNames() const
87 {
88  std::vector<eckit::PathName> r;
89  for (size_t i(0); i < allFound_.size(); ++i)
90  r.push_back(allFound_[i]);
91  return r;
92 }
93 
94 void FileCollector::collectFile(const std::map<std::string,std::vector<std::string> >& r, const map<string,string>& values)
95 {
96  const string relativePath (mapper_.encodeRelative(values));
97 
98  vector<string> foundFiles, files (mapper_.encode(values));
99  ASSERT(files.size() > 0);
100  for (size_t i (0); i < files.size(); ++i)
101  {
102  const string& p (expandTilde(files[i]));
103  prestage(r, p);
104  if (PathName(p).exists())
105  {
106  Log::info() << "FileCollector::collectFile: FOUND " << p << endl;
107  foundFiles.push_back(p);
108  } else {
109  Log::info() << "FileCollector::collectFile: NOT found " << p << endl;
110  }
111  }
112 
113  if (foundFiles.size() > 1)
114  {
115  stringstream ss;
116  ss << "File " << relativePath << " found in more than one root directory: " << foundFiles;
117  throw UserError(ss.str());
118  }
119 
120  if (foundFiles.size() == 1)
121  {
122  allFound_.push_back(foundFiles[0]);
123  multiHandle_ += PathName(foundFiles[0]).fileHandle();
124  }
125 }
126 
127 void FileCollector::findFiles(const vector<string>& keywords, const map<string, vector<string> >& request)
128 {
129  product(0, keywords, request, map<string,string>());
130 }
131 
132 void FileCollector::product(size_t k,
133  const vector<string>& keywords,
134  const map<string, vector<string> >& request,
135  const map<string,string>& combination)
136 {
137  if (k == keywords.size())
138  return collectFile(request, combination);
139 
140  const string& keyword (keywords[k]);
141  const vector<string>& values (request.find(keyword)->second);
142  for (size_t i (0); i < values.size(); ++i)
143  {
144  map<string,string> newCombination(combination);
145  newCombination[keyword] = values[i];
146  product(k + 1, keywords, request, newCombination);
147  }
148 }
149 
virtual ~FileCollector()
std::vector< std::string > foundFiles() const
void product(size_t k, const std::vector< std::string > &keywords, const std::map< std::string, std::vector< std::string > > &, const std::map< std::string, std::string > &)
std::vector< std::string > allFound_
Definition: FileCollector.h:46
void findFiles(const std::vector< std::string > &, const std::map< std::string, std::vector< std::string > > &)
std::vector< eckit::PathName > foundFilesAsPathNames() const
virtual void collectFile(const std::map< std::string, std::vector< std::string > > &, const std::map< std::string, std::string > &values)
const FileMapper & mapper_
Definition: FileCollector.h:44
static std::string expandTilde(const std::string &s)
std::string prestageScriptPath(const std::map< std::string, std::vector< std::string > > &r) const
eckit::MultiHandle & multiHandle_
Definition: FileCollector.h:45
void prestage(const std::map< std::string, std::vector< std::string > > &, const std::string &fileName)
FileCollector(const FileMapper &, eckit::MultiHandle &)
std::vector< std::string > encode(const std::map< std::string, std::string > &values) const
Definition: FileMapper.cc:193
std::string encodeRelative(const std::map< std::string, std::string > &values) const
Definition: FileMapper.cc:146
Definition: encode.cc:30