Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
OnlMonHtml.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file OnlMonHtml.cc
1 #include "OnlMonHtml.h"
2 
3 #include <onlmon/RunDBodbc.h>
4 
5 #include <dirent.h>
6 #include <sys/stat.h>
7 #include <algorithm>
8 #include <cstddef> // for size_t
9 #include <fstream>
10 #include <iomanip>
11 #include <iostream>
12 #include <iterator>
13 #include <set>
14 #include <sstream>
15 #include <vector>
16 
17 namespace
18 {
19  //___________________________________________________________________________
20  std::vector<std::string> split(const char sep, const std::string& s)
21  {
22  std::string str = s;
23  std::vector<size_t> slashes_pos;
24 
25  if (str[0] != sep)
26  {
27  str.insert(str.begin(), sep);
28  }
29 
30  if (str[str.size() - 1] != sep)
31  {
32  str.push_back(sep);
33  }
34 
35  for (size_t i = 0; i < str.size(); i++)
36  {
37  if (str[i] == sep)
38  {
39  slashes_pos.push_back(i);
40  }
41  }
42 
43  std::vector<std::string> parts;
44 
45  if (slashes_pos.size() > 0)
46  {
47  for (size_t i = 0; i < slashes_pos.size() - 1; i++)
48  {
49  parts.push_back(str.substr(slashes_pos[i] + 1,
50  slashes_pos[i + 1] - slashes_pos[i] - 1));
51  }
52  }
53 
54  return parts;
55  }
56 
57  //___________________________________________________________________________
58  std::string join(const char sep, const std::vector<std::string>& parts)
59  {
60  std::string rv;
61  for (size_t i = 0; i < parts.size(); ++i)
62  {
63  rv += parts[i];
64  if (i + 1 < parts.size())
65  {
66  rv += sep;
67  }
68  }
69  return rv;
70  }
71 } // namespace
72 
73 //_____________________________________________________________________________
75  : fHtmlDir(topdir)
76 {
77  if (fHtmlDir.empty())
78  {
79  fHtmlDir = "./";
80  }
81  rundb = new RunDBodbc();
82 }
83 
85 {
86  if (rundb)
87  {
88  delete rundb;
89  }
90 }
91 
92 //_____________________________________________________________________________
93 void OnlMonHtml::addMenu(const std::string& header, const std::string& path,
94  const std::string& relfilename)
95 {
96  std::ostringstream menufile;
97 
98  menufile << fHtmlRunDir << "/menu";
99 
100  std::ifstream in(menufile.str().c_str());
101 
102  if (!in.good())
103  {
104  if (verbosity())
105  {
106  std::cout << __PRETTY_FUNCTION__ << "File " << menufile.str() << " does not exist."
107  << "I'm creating it now" << std::endl;
108  }
109  std::ofstream out(menufile.str().c_str());
110  out.close();
111  }
112  else
113  {
114  if (verbosity())
115  {
116  std::cout << __PRETTY_FUNCTION__ << "Reading file " << menufile.str() << std::endl;
117  }
118  }
119 
120  // we read back the old menu file...
121  std::vector<std::string> lines;
122  char str[1024];
123  while (in.getline(str, 1024, '\n'))
124  {
125  lines.emplace_back(str);
126  }
127  in.close();
128 
129  // ... we then append the requested new entry...
130  std::ostringstream sline;
131  sline << header << "/" << path << "/" << relfilename;
132 
133  lines.push_back(sline.str());
134 
135  // ... and we sort this out...
136  sort(lines.begin(), lines.end());
137 
138  // ... and we remove duplicates lines...
139  std::set<std::string> olines;
140  copy(lines.begin(), lines.end(),
141  std::insert_iterator<std::set<std::string> >(olines, olines.begin()));
142 
143  // ... and finally we write the full new menu file out.
144  std::ofstream out(menufile.str());
145  copy(olines.begin(), olines.end(), std::ostream_iterator<std::string>(out, "\n"));
146  out.close();
147 
148  // --end of normal menu generation--
149 
150  // -- For those who do not have javascript (and thus the menu file
151  // created by addMenu will be useless) or
152  // in case cgi script(s) won't be allowed for some reason,
153  // make a plain html menu file too.
154  plainHtmlMenu(olines);
155 }
156 
157 //_____________________________________________________________________________
158 void OnlMonHtml::plainHtmlMenu(const std::set<std::string>& olines)
159 {
160  std::ostringstream htmlmenufile;
161 
162  htmlmenufile << fHtmlRunDir << "/menu.html";
163 
164  // First get the list of directories found in menu file above (contained
165  // in olines set). The olines are of the form:
166  // D1/D2/TITLE/link (where link is generally somefile.gif)
167  // The dir in this case is D1/D2, which is why we look for 2 slashes
168  // below (the one before TITLE and the one before link).
169  std::set<std::string> dirlist;
170  std::set<std::string>::const_iterator it;
171  for (it = olines.begin(); it != olines.end(); ++it)
172  {
173  const std::string& line = *it;
174  std::string::size_type pos = line.find_last_of('/');
175  pos = line.substr(0, pos).find_last_of('/');
176  std::string dir = line.substr(0, pos);
177  std::vector<std::string> parts = split('/', dir);
178  for (size_t i = 0; i <= parts.size(); ++i)
179  {
180  std::string dir2 = join('/', parts);
181  dirlist.insert(dir2);
182  parts.pop_back();
183  }
184  }
185 
186  // We now generate the menu.html file.
187  std::ofstream out(htmlmenufile.str().c_str());
188  if (!out.good())
189  {
190  std::cout << __PRETTY_FUNCTION__ << " cannot open output file "
191  << htmlmenufile.str() << std::endl;
192  return;
193  }
194 
195  for (it = dirlist.begin(); it != dirlist.end(); ++it)
196  {
197  // in the example above, dir is D1/D2
198  const std::string& dir = *it;
199  int nslashes = count(dir.begin(), dir.end(), '/') + 1;
200  std::string name = dir;
201  std::string::size_type pos = dir.find_last_of('/');
202  if (pos < dir.size())
203  {
204  name = dir.substr(pos + 1);
205  }
206  else
207  {
208  out << "<HR><BR>\n";
209  }
210  out << "<H" << nslashes << ">" << name
211  << "</H" << nslashes << "><BR>\n";
212 
213  // We then loop on all the olines, and for those matching the
214  // dir pattern, we generate link <A HREF="link">TITLE</A>
215  std::set<std::string>::const_iterator it2;
216  for (it2 = olines.begin(); it2 != olines.end(); ++it2)
217  {
218  const std::string& line = *it2;
219  std::string::size_type pos2 = line.find_last_of('/');
220  pos2 = line.substr(0, pos2).find_last_of('/');
221  std::string ldir = line.substr(0, pos2);
222  if (ldir == dir) // we get a matching line
223  {
224  std::string sline = line.substr(dir.size() + 1);
225  // in the example above, sline is TITLE/link...
226  pos2 = sline.find('/');
227  // ...which we split at the slash pos
228  if (pos2 < sline.size())
229  {
230  out << "<A HREF=\""
231  << sline.substr(pos + 1) << "\">"
232  << sline.substr(0, pos) << "</A><BR>\n";
233  }
234  }
235  }
236  }
237  out.close();
238 }
239 
240 //_____________________________________________________________________________
241 void OnlMonHtml::namer(const std::string& header,
242  const std::string& basefilename,
243  const std::string& ext,
244  std::string& fullfilename,
246 {
247  std::ostringstream sfilename;
248 
249  sfilename << header << "_";
250  if (!basefilename.empty())
251  {
252  sfilename << basefilename << "_";
253  }
254  sfilename << runNumber() << "." << ext;
255 
256  std::ostringstream sfullfilename;
257 
258  sfullfilename << fHtmlRunDir << "/" << sfilename.str();
259 
260  fullfilename = sfullfilename.str();
261  filename = sfilename.str();
262 
263  if (verbosity())
264  {
265  std::cout << __PRETTY_FUNCTION__ << "namer: header=" << header
266  << " basefilename=" << basefilename << " ext=" << ext
267  << std::endl
268  << "fullfilename=" << fullfilename
269  << " filename=" << filename
270  << std::endl;
271  }
272 }
273 
274 //_____________________________________________________________________________
277  const std::string& path,
278  const std::string& basefilename,
279  const std::string& ext)
280 {
281  std::string fullfilename;
283 
284  namer(header, basefilename, ext, fullfilename, filename);
285  addMenu(header, path, filename);
286  return fullfilename;
287 }
288 
289 //_____________________________________________________________________________
291 {
292  // Check if html output directory for this run exist.
293  // If not create it.
294  // Then check (and create if necessary) the "menu" template file.
295  std::string runtype = "unknowndata";
296  std::string runtmp = rundb->RunType(fRunNumber);
297  if (runtmp == "JUNK")
298  {
299  runtype = "junkdata";
300  }
301  else if (runtmp == "PHYSICS")
302  {
303  runtype = "eventdata";
304  }
305  else if (runtmp == "CALIBRATION")
306  {
307  runtype = "calibdata";
308  }
309  else if (runtmp == "PREJECTED")
310  {
311  runtype = "prejecteddata";
312  }
313  else if (runtmp == "LOCALPOLARIMETER")
314  {
315  runtype = "localpoldata";
316  }
317  else if (runtmp == "PEDESTAL")
318  {
319  runtype = "pedestaldata";
320  }
321  else if (runtmp == "VERNIERSCAN")
322  {
323  runtype = "vernierscandata";
324  }
325  else if (runtmp == "ZEROFIELD")
326  {
327  runtype = "zerofielddata";
328  }
329  std::cout << "runtype is " << runtype << std::endl;
330 
331  std::ostringstream fulldir;
332 
333  fulldir << fHtmlDir << "/" << runtype << "/"
334  << runRange() << "/" << runNumber();
335 
336  fHtmlRunDir = fulldir.str();
337  DIR* htdir = opendir(fulldir.str().c_str());
338  if (!htdir)
339  {
340  std::vector<std::string> mkdirlist;
341  mkdirlist.push_back(fulldir.str());
342  std::string updir = fulldir.str();
343  std::string::size_type pos1;
344  while ((pos1 = updir.rfind('/')) != std::string::npos)
345  {
346  updir.erase(pos1, updir.size());
347  htdir = opendir(updir.c_str());
348  if (!htdir)
349  {
350  mkdirlist.push_back(updir);
351  }
352  else
353  {
354  closedir(htdir);
355  break;
356  }
357  }
358  while (mkdirlist.rbegin() != mkdirlist.rend())
359  {
360  std::string md = *(mkdirlist.rbegin());
361  if (verbosity())
362  {
363  std::cout << __PRETTY_FUNCTION__ << "Trying to create dir " << md << std::endl;
364  }
365  if (mkdir(md.c_str(), S_IRWXU | S_IRWXG | S_IRWXO))
366  {
367  std::cout << __PRETTY_FUNCTION__ << "Error creating directory " << md << std::endl;
369  break;
370  }
371  mkdirlist.pop_back();
372  }
373  fHtmlRunDir = fulldir.str();
374  // use ostringstream fulldir which contains the full directory
375  // to create .htaccess file for automatic gunzipping
376  fulldir << "/.htaccess";
377  std::ofstream htaccess;
378  htaccess.open(fulldir.str().c_str(), std::ios::trunc); // overwrite if exists
379  htaccess << "<Files *.html.gz>" << std::endl;
380  htaccess << " AddEncoding x-gzip .gz" << std::endl;
381  htaccess << " AddType text/html .gz" << std::endl;
382  htaccess << "</Files>" << std::endl;
383  htaccess << "<Files *.txt.gz>" << std::endl;
384  htaccess << " AddEncoding x-gzip .gz" << std::endl;
385  htaccess << " AddType text/html .gz" << std::endl;
386  htaccess << "</Files>" << std::endl;
387  htaccess.close();
388  }
389  else
390  {
391  closedir(htdir);
392  }
393 
394  if (verbosity())
395  {
396  std::cout << __PRETTY_FUNCTION__ << "OK. fHtmlRunDir=" << fHtmlRunDir << std::endl;
397  }
398 }
399 
400 //_____________________________________________________________________________
402 {
404  runInit();
405 }
406 
407 //_____________________________________________________________________________
410 {
411  const int range = 1000;
412  int start = runNumber() / range;
413 
414  std::ostringstream s;
415 
416  s << "run_" << std::setw(10) << std::setfill('0') << start * range
417  << "_" << std::setw(10) << std::setfill('0') << (start + 1) * range;
418 
419  return s.str();
420 }