CMS 3D CMS Logo

LegacyIOHelper.cc
Go to the documentation of this file.
3 
4 #include <cstdio>
5 #include <cfloat>
6 #include <vector>
7 #include <string>
8 
9 #include "TString.h"
10 #include "TSystem.h"
11 #include "TFile.h"
12 #include "TKey.h"
13 #include <sys/stat.h>
14 
16  std::string const &path /* = "" */,
17  uint32_t const run /* = 0 */,
18  bool saveall /* = true */,
19  std::string const &fileupdate /* = "RECREATE" */) {
20  // TFile flushes to disk with fsync() on every TDirectory written to
21  // the file. This makes DQM file saving painfully slow, and
22  // ironically makes it _more_ likely the file saving gets
23  // interrupted and corrupts the file. The utility class below
24  // simply ignores the flush synchronisation.
25  class TFileNoSync : public TFile {
26  public:
27  TFileNoSync(char const *file, char const *opt) : TFile{file, opt} {}
28  Int_t SysSync(Int_t) override { return 0; }
29  };
30 
31  std::cout << "DQMFileSaver::globalEndRun()" << std::endl;
32 
33  char suffix[64];
34  sprintf(suffix, "R%09d", run);
35  TFileNoSync *file = new TFileNoSync(filename.c_str(), fileupdate.c_str()); // open file
36 
37  // Traverse all MEs
38  std::vector<MonitorElement *> mes;
39  if (saveall) {
40  // this is typically used, at endJob there will only be JOB histos here
41  mes = dbe_->getAllContents(path);
42  } else {
43  // at endRun it might make sense to use this, to not save JOB histos yet.
44  mes = dbe_->getAllContents(path, run, 0);
45  }
46 
47  for (auto me : mes) {
48  // Modify dirname to comply with DQM GUI format. Change:
49  // A/B/C/plot
50  // into:
51  // DQMData/Run X/A/Run summary/B/C/plot
52  std::string dirName = me->getPathname();
53  uint64_t firstSlashPos = dirName.find('/');
54  if (firstSlashPos == std::string::npos) {
55  firstSlashPos = dirName.length();
56  }
57 
58  if (run) {
59  // Rewrite paths to "Run Summary" format when given a run number.
60  // Else, write a simple, flat TDirectory for local usage.
61  dirName = dirName.substr(0, firstSlashPos) + "/Run summary" + dirName.substr(firstSlashPos, dirName.size());
62  dirName = "DQMData/Run " + std::to_string(run) + "/" + dirName;
63  }
64 
65  std::string objectName = me->getName();
66 
67  // Create dir if it doesn't exist and cd into it
69 
70  // INTs are saved as strings in this format: <objectName>i=value</objectName>
71  // REALs are saved as strings in this format: <objectName>f=value</objectName>
72  // STRINGs are saved as strings in this format: <objectName>s="value"</objectName>
73  if (me->kind() == MonitorElement::Kind::INT) {
74  int value = me->getIntValue();
75  std::string content = "<" + objectName + ">i=" + std::to_string(value) + "</" + objectName + ">";
76  TObjString str(content.c_str());
77  str.Write();
78  } else if (me->kind() == MonitorElement::Kind::REAL) {
79  double value = me->getFloatValue();
80  char buf[64];
81  // use printf here to preserve exactly the classic formatting.
82  std::snprintf(buf, sizeof(buf), "%.*g", DBL_DIG + 2, value);
83  std::string content = "<" + objectName + ">f=" + buf + "</" + objectName + ">";
84  TObjString str(content.c_str());
85  str.Write();
86  } else if (me->kind() == MonitorElement::Kind::STRING) {
87  const std::string &value = me->getStringValue();
88  std::string content = "<" + objectName + ">s=" + value + "</" + objectName + ">";
89  TObjString str(content.c_str());
90  str.Write();
91  } else {
92  // Write a histogram
93  TH1 *value = me->getTH1();
94  value->Write();
95 
96  if (me->getEfficiencyFlag()) {
97  std::string content = "<" + objectName + ">e=1</" + objectName + ">";
98  TObjString str(content.c_str());
99  str.Write();
100  }
101 
102  for (QReport *qr : me->getQReports()) {
104  // TODO: 64 is likely too short; memory corruption in the old code?
105  char buf[64];
106  std::snprintf(buf, sizeof(buf), "qr=st:%d:%.*g:", qr->getStatus(), DBL_DIG + 2, qr->getQTresult());
107  result = '<' + objectName + '.' + qr->getQRName() + '>';
108  result += buf;
109  result += qr->getAlgorithm() + ':' + qr->getMessage();
110  result += "</" + objectName + '.' + qr->getQRName() + '>';
111  TObjString str(result.c_str());
112  str.Write();
113  }
114  }
115 
116  // Go back to the root directory
117  gDirectory->cd("/");
118  }
119 
120  file->Close();
121 }
122 
123 // Use this for saving monitoring objects in ROOT files with dir structure;
124 // cds into directory (creates it first if it doesn't exist);
125 // returns a success flag
127  assert(!path.empty());
128 
129  // Find the first path component.
130  size_t start = 0;
131  size_t end = path.find('/', start);
132  if (end == std::string::npos)
133  end = path.size();
134 
135  while (true) {
136  // Check if this subdirectory component exists. If yes, make sure
137  // it is actually a subdirectory. Otherwise create or cd into it.
139  TObject *o = gDirectory->Get(part.c_str());
140  if (o && !dynamic_cast<TDirectory *>(o))
141  throw cms::Exception("DQMFileSaver") << "Attempt to create directory '" << path
142  << "' in a file"
143  " fails because the part '"
144  << part
145  << "' already exists and is not"
146  " directory";
147  else if (!o)
148  gDirectory->mkdir(part.c_str());
149 
150  if (!gDirectory->cd(part.c_str()))
151  throw cms::Exception("DQMFileSaver") << "Attempt to create directory '" << path
152  << "' in a file"
153  " fails because could not cd into subdirectory '"
154  << part << "'";
155 
156  // Stop if we reached the end, ignoring any trailing '/'.
157  if (end + 1 >= path.size())
158  break;
159 
160  // Find the next path component.
161  start = end + 1;
162  end = path.find('/', start);
163  if (end == std::string::npos)
164  end = path.size();
165  }
166 
167  return true;
168 }
169 
170 bool LegacyIOHelper::readdir(TDirectory *dir, const std::string &toppath) {
171  TDirectory *dirsav = gDirectory;
172  LogDebug("LegacyIOHelper") << "Inside:" << gDirectory->GetPath() << std::endl;
173  TIter next(dir->GetListOfKeys());
174  TKey *key;
175  while ((key = (TKey *)next())) {
176  if (key->IsFolder()) {
177  LogDebug("LegacyIOHelper") << key->GetName() << std::endl;
178  dir->cd(key->GetName());
179  TDirectory *subdir = gDirectory;
180  readdir(subdir, toppath);
181  dirsav->cd();
182  continue;
183  } else {
184  TClass *cl = gROOT->GetClass(key->GetClassName());
185  std::string meName;
186  if (cl->InheritsFrom("TProfile")) {
187  TProfile *h = dynamic_cast<TProfile *>(key->ReadObject<TProfile>()->Clone());
188  h->SetDirectory(nullptr);
189  if (h) {
190  getMEName<TProfile>(h, toppath, meName);
191  data_.insert(dbe_->bookProfile(meName, h));
192  }
193  } else if (cl->InheritsFrom("TProfile2D")) {
194  TProfile2D *h = dynamic_cast<TProfile2D *>(key->ReadObject<TProfile2D>()->Clone());
195  h->SetDirectory(nullptr);
196  if (h) {
197  getMEName<TProfile2D>(h, toppath, meName);
198  data_.insert(dbe_->bookProfile2D(meName, h));
199  }
200  } else if (cl->InheritsFrom("TH1F")) {
201  TH1F *h = dynamic_cast<TH1F *>(key->ReadObject<TH1F>()->Clone());
202  h->SetDirectory(nullptr);
203  if (h) {
204  getMEName<TH1F>(h, toppath, meName);
205  data_.insert(dbe_->book1D(meName, h));
206  }
207  } else if (cl->InheritsFrom("TH1S")) {
208  TH1S *h = dynamic_cast<TH1S *>(key->ReadObject<TH1S>()->Clone());
209  h->SetDirectory(nullptr);
210  if (h) {
211  getMEName<TH1S>(h, toppath, meName);
212  data_.insert(dbe_->book1S(meName, h));
213  }
214  } else if (cl->InheritsFrom("TH1D")) {
215  TH1D *h = dynamic_cast<TH1D *>(key->ReadObject<TH1D>()->Clone());
216  h->SetDirectory(nullptr);
217  if (h) {
218  getMEName<TH1D>(h, toppath, meName);
219  data_.insert(dbe_->book1DD(meName, h));
220  }
221  } else if (cl->InheritsFrom("TH1I")) {
222  TH1I *h = dynamic_cast<TH1I *>(key->ReadObject<TH1I>()->Clone());
223  h->SetDirectory(nullptr);
224  if (h) {
225  getMEName<TH1I>(h, toppath, meName);
226  data_.insert(dbe_->book1I(meName, h));
227  }
228  } else if (cl->InheritsFrom("TH2F")) {
229  TH2F *h = dynamic_cast<TH2F *>(key->ReadObject<TH2F>()->Clone());
230  h->SetDirectory(nullptr);
231  if (h) {
232  getMEName<TH2F>(h, toppath, meName);
233  data_.insert(dbe_->book2D(meName, h));
234  }
235  } else if (cl->InheritsFrom("TH2S")) {
236  TH2S *h = dynamic_cast<TH2S *>(key->ReadObject<TH2S>()->Clone());
237  h->SetDirectory(nullptr);
238  if (h) {
239  getMEName<TH2S>(h, toppath, meName);
240  data_.insert(dbe_->book2S(meName, h));
241  }
242  } else if (cl->InheritsFrom("TH2D")) {
243  TH2D *h = dynamic_cast<TH2D *>(key->ReadObject<TH2D>()->Clone());
244  h->SetDirectory(nullptr);
245  if (h) {
246  getMEName<TH2D>(h, toppath, meName);
247  data_.insert(dbe_->book2DD(meName, h));
248  }
249  } else if (cl->InheritsFrom("TH2I")) {
250  TH2I *h = dynamic_cast<TH2I *>(key->ReadObject<TH2I>()->Clone());
251  h->SetDirectory(nullptr);
252  if (h) {
253  getMEName<TH2I>(h, toppath, meName);
254  data_.insert(dbe_->book2I(meName, h));
255  }
256  } else if (cl->InheritsFrom("TH3F")) {
257  TH3F *h = dynamic_cast<TH3F *>(key->ReadObject<TH3F>()->Clone());
258  h->SetDirectory(nullptr);
259  if (h) {
260  getMEName<TH3F>(h, toppath, meName);
261  data_.insert(dbe_->book3D(meName, h));
262  }
263  }
264  }
265  }
266  if (!data_.empty())
267  return true;
268  return false;
269 }
270 
271 bool LegacyIOHelper::open(std::string const &filename, std::string const &path, uint32_t const run) {
272  TFile *f1 = TFile::Open(filename.c_str());
273  if (!f1)
274  return false;
275  std::ostringstream toppath;
276  toppath << filename << ":/DQMData/Run " << run << "/";
277  std::string dirpath = toppath.str();
278  edm::LogPrint("LegacyIOHelper") << dirpath << std::endl;
279  bool flag = readdir(f1, dirpath);
280  f1->Close();
281  return flag;
282 }
Definition: start.py:1
bool createDirectoryIfNeededAndCd(const std::string &path)
MonitorElement * bookProfile2D(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, double lowZ, double highZ, char const *option="s", FUNC onbooking=NOOP())
Definition: DQMStore.h:476
void save(std::string const &filename, std::string const &path="", uint32_t const run=0, bool saveall=true, std::string const &fileupdate="RECREATE")
MonitorElement * book1I(TString const &name, TString const &title, int const nchX, double const lowX, double const highX, FUNC onbooking=NOOP())
Definition: DQMStore.h:177
MonitorElement * book2S(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, FUNC onbooking=NOOP())
Definition: DQMStore.h:254
assert(be >=bs)
static std::string to_string(const XMLCh *ch)
bool open(std::string const &filename, std::string const &path="", uint32_t const run=0)
MonitorElement * book1DD(TString const &name, TString const &title, int nchX, double lowX, double highX, FUNC onbooking=NOOP())
Definition: DQMStore.h:155
DQMStore * dbe_
MonitorElement * bookProfile(TString const &name, TString const &title, int nchX, double lowX, double highX, int, double lowY, double highY, char const *option="s", FUNC onbooking=NOOP())
Definition: DQMStore.h:399
bool readdir(TDirectory *dir, const std::string &toppath)
virtual std::vector< dqm::harvesting::MonitorElement * > getAllContents(std::string const &path) const
Definition: DQMStore.cc:641
MonitorElement * book1S(TString const &name, TString const &title, int nchX, double lowX, double highX, FUNC onbooking=NOOP())
Definition: DQMStore.h:133
Definition: value.py:1
Log< level::Warning, true > LogPrint
unsigned long long uint64_t
Definition: Time.h:13
part
Definition: HCALResponse.h:20
MonitorElement * book2D(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, FUNC onbooking=NOOP())
Definition: DQMStore.h:212
MonitorElement * book2DD(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, FUNC onbooking=NOOP())
Definition: DQMStore.h:338
MonitorElement * book1D(TString const &name, TString const &title, int const nchX, double const lowX, double const highX, FUNC onbooking=NOOP())
Definition: DQMStore.h:98
The Signals That Services Can Subscribe To This is based on ActivityRegistry h
Helper function to determine trigger accepts.
Definition: Activities.doc:4
#define str(s)
MonitorElement * book3D(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, int nchZ, double lowZ, double highZ, FUNC onbooking=NOOP())
Definition: DQMStore.h:367
MonitorElement * book2I(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, FUNC onbooking=NOOP())
Definition: DQMStore.h:296
#define LogDebug(id)