EventFileChain.cc
Go to the documentation of this file.
1 #include <utl/ErrorLogger.h>
2 #include <utl/AugerException.h>
3 #include <utl/Branch.h>
4 
5 #include <io/EventFileChain.h>
6 #include <io/EventFile.h>
7 #include <io/VEventFile.h>
8 
9 #include <sstream>
10 #include <cstdio>
11 #include <boost/process.hpp>
12 #include <boost/format.hpp>
13 
14 
15 namespace io {
16 
17  std::map<std::string, std::string> EventFileChain::fgXMLDictionary;
18 
19 
21  fBranch(branch)
22  {
23  const std::string fileTypeName = fBranch.GetName();
24 
26  if (fileTypeName == "Offline")
27  fileType = eOffline;
28  else if (fileTypeName == "FDAS")
29  fileType = eFDas;
30  else if (fileTypeName == "CDAS")
31  fileType = eCDas;
32  else if (fileTypeName == "CORSIKA")
33  fileType = eCorsika;
34  #ifdef HAVE_AIRES
35  else if (fileTypeName == "AIRES")
36  fileType = eAires;
37  #endif
38  else if (fileTypeName == "IoAuger")
39  fileType = eIoAuger;
40  else if (fileTypeName == "CONEX")
41  fileType = eCONEX;
42  else if (fileTypeName == "CONEXRandom")
43  fileType = eCONEXRandom;
44  else if (fileTypeName == "SENECA")
45  fileType = eSeneca;
46  else if (fileTypeName == "Seneca")
47  fileType = eSeneca;
48  else if (fileTypeName == "Artificial" || fileTypeName == "ARTIFICIAL")
49  fileType = eArtificial;
50  else if (fileTypeName == "ZHAireS")
51  fileType = eZHAireS;
52  else if (fileTypeName == "REAS")
53  fileType = eREAS;
54  else if (fileTypeName == "REASH5")
55  fileType = eREASH5;
56  //else if (fileTypeName == "ReAires")
57  // fileType = eReAires;
58  else if (fileTypeName == "EVA")
59  fileType = eEVA;
60  else if (fileTypeName == "RadioAERA")
61  fileType = eRadioAERA;
62  else if (fileTypeName == "RadioAERAroot")
63  fileType = eRadioAERAroot;
64  else if (fileTypeName == "SELFAS")
65  fileType = eSELFAS;
66  else {
67  fileType = eUnknownType;
68  std::stringstream err;
69  err << " Unknown file type '" << fileTypeName << "'.";
70  ERROR(err.str());
71  throw utl::IOFailureException(err.str());
72  }
73  fType = fileType;
74 
75  const auto filelist =
76  fBranch.GetChild("InputFilenames").Get<std::vector<std::string>>();
77  SetFileList(filelist);
78  }
79 
80 
81  EventFileChain::EventFileChain(const std::string& filenames, const Type type) :
82  fType(type)
83  {
84  std::istringstream iss(filenames);
85  std::string name;
86  while (iss >> name)
87  fFileList.push_back(name);
88 
89  Parse();
90 
91  fFileIterator = fFileList.begin();
92  }
93 
94 
95  EventFileChain::EventFileChain(const std::vector<std::string>& filenames,
96  const Type type) :
97  fFileList(filenames),
98  fFileIterator(fFileList.begin()),
99  fType(type)
100  {
101  Parse();
102  }
103 
104 
106  {
107  delete fOpenFile;
108  }
109 
110 
111  void
112  EventFileChain::SetFileList(const std::vector<std::string>& filenames)
113  {
114  delete fOpenFile;
115  fOpenFile = nullptr;
116 
117  if (filenames.empty())
118  throw utl::IOFailureException("EventFileChain::SetFileList called with empty filelist");
119 
120  fFileList = filenames;
121 
122  Parse();
123 
124  fFileIterator = fFileList.begin();
125  }
126 
127 
128  Status
130  {
131  for (;;) {
132 
133  if (fOpenFile)
134  switch (const Status stat = fOpenFile->Read(event)) {
135  case eFail:
136  {
137  std::ostringstream warn;
138  warn << "file '"
139  << GetCurrentFilename() << "' is skipped due to IO problems";
140  WARNING(warn);
141  }
142  // fall through
143  case eEOF:
144  delete fOpenFile;
145  fOpenFile = nullptr;
146  ++fFileIterator;
147  break;
148  default:
149  return stat;
150  }
151 
152  if (fFileIterator == fFileList.end())
153  return eEOF;
154 
155  while (OpenCurrent() != eSuccess) {
156  ++fFileIterator;
157  if (fFileIterator == fFileList.end())
158  return eEOF;
159  }
160  }
161  }
162 
163 
164  const std::string&
166  const
167  {
168  if (fFileIterator != fFileList.end())
169  return *fFileIterator;
170  else {
171  static const std::string empty("");
172  return empty;
173  }
174  }
175 
176 
177  inline
178  Status
180  {
181  // Exception handling, to support empty or corrput data files
182  try {
183 
184  delete fOpenFile;
185  fOpenFile = new EventFile(*fFileIterator, eRead, fType, &fBranch);
186 
187  } catch (utl::IOFailureException& ex) {
188 
189  fOpenFile = nullptr;
190  std::ostringstream err;
191  err << "File '" << *fFileIterator
192  << "' is not readable/corrupt: " << ex.GetMessage()
193  << " Skipping...";
194 
195  if (fCatchExceptions) {
196  WARNING(err);
197  return eFail;
198  } else {
199  // re-throw
200  ERROR(err);
201  throw ex;
202  }
203 
204  }
205 
206  return eSuccess;
207  }
208 
209 
210  void
212  {
213  if (fgXMLDictionary.empty())
215 
216  // replace xml constructs
217  for (auto& s : fFileList) {
218  for (const auto& d : fgXMLDictionary) {
219  const auto n = d.first.size();
220  for (std::string::size_type begin = 0, pos = s.find(d.first, 0);
221  pos != std::string::npos; pos = s.find(d.first, begin)) {
222  s.replace(pos, n, d.second);
223  begin = pos + n;
224  }
225  }
226  }
227 
228  // find backticks or $( to execute
229  for (auto sIt = fFileList.begin(); sIt != fFileList.end(); ) {
230 
231  const auto& line = *sIt;
232  if (line.length() < 2 ||
233  !(line[0] == '`' || (line[0] == '$' && line[1] == '('))) {
234  // skip lines that do not start a shell command
235  ++sIt;
236  continue;
237  }
238 
239  std::string command;
240 
241  if (line[0] == '`') {
242 
243  // `bash code`
244  // we assume the shell code does not contain any backticks
245 
246  std::string assemble;
247  while (sIt != fFileList.end() && (*sIt)[sIt->length()-1] != '`') {
248  assemble += *sIt;
249  assemble += ' ';
250  sIt = fFileList.erase(sIt);
251  }
252  if (sIt == fFileList.end())
253  throw utl::IOFailureException("unmatched closing backtick ` in file list");
254  assemble += *sIt;
255  sIt = fFileList.erase(sIt);
256  // remove starting and ending backtick
257  command = assemble.substr(1, assemble.length()-2);
258 
259  if (command.find_first_of("`") != std::string::npos)
260  throw utl::IOFailureException("additional backticks in shell script are not supported");
261 
262  } else {
263 
264  // $(bash code)
265 
266  std::string assemble;
267  int bracket = 0;
268  while (sIt != fFileList.end()) {
269  const auto& line = *sIt;
270  for (const auto c : line)
271  bracket += (c == '(') - (c == ')');
272  if (!assemble.empty())
273  assemble += ' ';
274  assemble += line;
275  sIt = fFileList.erase(sIt);
276  if (!bracket)
277  break;
278  }
279  if (assemble.back() != ')')
280  throw utl::IOFailureException("'$(' shell command has to be terminated with ')'");
281 
282  // remove $( and )
283  const int skipFront = 2;
284  const int skipBack = 1;
285  command = assemble.substr(skipFront, assemble.length()-(skipFront + skipBack));
286 
287  }
288 
289  INFO("executing command $(" + command + ")");
290 
291  namespace bp = boost::process;
292  bp::ipstream is;
293  // bp::child assumes first argument is the executable to run, we must call bash explicitly
294  bp::child pipe(bp::search_path("sh"), std::vector<std::string>{ "-e", "-c", command }, bp::std_out > is);
295  std::string word;
296  while (is >> word) {
297  sIt = fFileList.insert(sIt, word);
298  ++sIt;
299  }
300  pipe.wait();
301  if (pipe.exit_code())
302  throw utl::IOFailureException(str(boost::format("file-list command `%1%` returned status %2%") % command % pipe.exit_code()));
303 
304  }
305 
306  if (fFileList.empty())
307  WARNING("filelist is empty");
308 
309  }
310 
311 
312  void
314  {
315  if (!fgXMLDictionary.empty())
316  return;
317 
318  fgXMLDictionary = {
319  { "&amp;", "&" },
320  { "&quot;", "\"" },
321  { "&apos;", "'" },
322  { "&lt;", "<" },
323  { "&gt;", ">" }
324  };
325  }
326 
327 }
conex file, with random access (NOT sequencial, NO EOF)
Definition: IoCodes.h:42
Status Read(evt::Event &event)
read current event and advance cursor by 1
IoAuger file format.
Definition: IoCodes.h:40
FDas file format.
Definition: IoCodes.h:36
FileContainer fFileList
const std::string & GetCurrentFilename() const
Seneca File Format. Added by Jeff Allen (jda292@nyu.edu) on Dec. 5th, 2006.
Definition: IoCodes.h:43
bool is(const double a, const double b)
Definition: testlib.cc:113
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
Definition: Branch.cc:211
EventFileChain(utl::Branch &branch)
static std::map< std::string, std::string > fgXMLDictionary
Base class to report exceptions in IO.
Offline native file format.
Definition: IoCodes.h:35
T Get() const
Definition: Branch.h:271
air shower radio simulations generated with EVA
Definition: IoCodes.h:49
Class representing a document branch.
Definition: Branch.h:107
Status
Return code for seek operation.
Definition: IoCodes.h:24
constexpr double s
Definition: AugerUnits.h:163
air shower radio simulations generated with REAS
Definition: IoCodes.h:46
data-format of SELFAS
Definition: IoCodes.h:52
static void InitXMLDictionary()
utl::Branch fBranch
void SetFileList(const std::vector< std::string > &filenames)
Status Read(evt::Event &event)
read current event, advance cursor by 1
Definition: EventFile.cc:148
#define WARNING(message)
Macro for logging warning messages.
Definition: ErrorLogger.h:163
std::string GetName() const
function to get the Branch name
Definition: Branch.cc:374
air shower radio simulations generated with ZHAireS
Definition: IoCodes.h:45
Interface to file I/O objects.
Definition: EventFile.h:34
EventFile * fOpenFile
Type
The type of file that we are acutally opening.
Definition: IoCodes.h:33
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
data-format of AERA
Definition: IoCodes.h:50
CDas file format.
Definition: IoCodes.h:37
root-format of AERA
Definition: IoCodes.h:51
const std::string & GetMessage() const
Retrieve the message from the exception.
air shower radio simulations generated with REAS
Definition: IoCodes.h:48

, generated on Tue Sep 26 2023.