00001 #include "DQMServices/Components/src/DQMFileSaver.h"
00002 #include "DQMServices/Core/interface/DQMStore.h"
00003 #include "DQMServices/Core/interface/MonitorElement.h"
00004 #include "FWCore/Framework/interface/Event.h"
00005 #include "FWCore/Framework/interface/Run.h"
00006 #include "FWCore/Framework/interface/LuminosityBlock.h"
00007 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00008 #include "FWCore/Version/interface/GetReleaseVersion.h"
00009 #include "FWCore/ServiceRegistry/interface/Service.h"
00010 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00011 #include "FWCore/MessageLogger/interface/JobReport.h"
00012 #include <sys/stat.h>
00013 #include <unistd.h>
00014 #include <iostream>
00015 #include <vector>
00016 #include <string>
00017 #include <TString.h>
00018 #include <TSystem.h>
00019
00020
00021 static void
00022 getAnInt(const edm::ParameterSet &ps, int &value, const std::string &name)
00023 {
00024 value = ps.getUntrackedParameter<int>(name, value);
00025 if (value < 1 && value != -1)
00026 throw cms::Exception("DQMFileSaver")
00027 << "Invalid '" << name << "' parameter '" << value
00028 << "'. Must be -1 or >= 1.";
00029 }
00030
00031 void
00032 DQMFileSaver::saveForOffline(const std::string &workflow, int run, int lumi)
00033 {
00034
00035 char suffix[64];
00036 sprintf(suffix, "R%09d", run);
00037
00038 char rewrite[128];
00039 if (lumi == 0)
00040 sprintf(rewrite, "\\1Run %d/\\2/Run summary", run);
00041 else
00042 sprintf(rewrite, "\\1Run %d/\\2/By Lumi Section %d-%d", irun_, ilumi_, ilumi_);
00043
00044 size_t pos = 0;
00045 std::string wflow;
00046 wflow.reserve(workflow.size() + 3);
00047 wflow = workflow;
00048 while ((pos = wflow.find('/', pos)) != std::string::npos)
00049 wflow.replace(pos++, 1, "__");
00050
00051 std::string filename = fileBaseName_ + suffix + wflow + ".root";
00052
00053 if (lumi == 0)
00054 {
00055
00056 dbe_->cd();
00057 dbe_->setCurrentFolder("Info/ProvInfo");
00058
00059
00060 MonitorElement* me = dbe_->get("Info/ProvInfo/CMSSW");
00061 if (!me) me = dbe_->bookString("CMSSW",edm::getReleaseVersion().c_str() );
00062
00063 me = dbe_->get("Info/ProvInfo/runIsComplete");
00064 if (!me) me = dbe_->bookFloat("runIsComplete");
00065
00066 if (me)
00067 {
00068 if (runIsComplete_)
00069 me->Fill(1.);
00070 else
00071 me->Fill(0.);
00072 }
00073
00074 dbe_->save(filename,
00075 "",
00076 "^(Reference/)?([^/]+)",
00077 rewrite,
00078 (DQMStore::SaveReferenceTag) saveReference_,
00079 saveReferenceQMin_,
00080 fileUpdate_);
00081 }
00082 else
00083 {
00084 std::vector<std::string> systems = (dbe_->cd(), dbe_->getSubdirs());
00085
00086 std::cout << " DQMFileSaver: storing EventInfo folders for Run: "
00087 << irun_ << ", Lumi Section: " << ilumi_ << ", Subsystems: " ;
00088
00089 for (size_t i = 0, e = systems.size(); i != e; ++i) {
00090 if (systems[i] != "Reference") {
00091 dbe_->cd();
00092 std::cout << systems[i] << " " ;
00093 dbe_->save(filename,
00094 systems[i]+"/EventInfo", "^(Reference/)?([^/]+)", rewrite,
00095 DQMStore::SaveWithoutReference,
00096 dqm::qstatus::STATUS_OK,
00097 fileUpdate_);
00098
00099 if (fileUpdate_=="RECREATE") fileUpdate_="UPDATE";
00100 }
00101 }
00102 std::cout << "\n";
00103 }
00104
00105 if (pastSavedFiles_.size() == 0)
00106 {
00107
00108 saveJobReport(filename);
00109 pastSavedFiles_.push_back(filename);
00110 }
00111
00112 }
00113
00114 static void
00115 doSaveForOnline(std::list<std::string> &pastSavedFiles,
00116 size_t numKeepSavedFiles,
00117 DQMStore *store,
00118 const std::string &filename,
00119 const std::string &directory,
00120 const std::string &rxpat,
00121 const std::string &rewrite,
00122 DQMStore::SaveReferenceTag saveref,
00123 int saveRefQMin)
00124 {
00125 store->save(filename, directory , rxpat,
00126 rewrite, saveref, saveRefQMin);
00127 pastSavedFiles.push_back(filename);
00128 if (pastSavedFiles.size() > numKeepSavedFiles)
00129 {
00130 remove(pastSavedFiles.front().c_str());
00131 pastSavedFiles.pop_front();
00132 }
00133 }
00134
00135 void
00136 DQMFileSaver::saveForOnline(const std::string &suffix, const std::string &rewrite)
00137 {
00138 std::vector<std::string> systems = (dbe_->cd(), dbe_->getSubdirs());
00139
00140 for (size_t i = 0, e = systems.size(); i != e; ++i)
00141 {
00142 if (systems[i] != "Reference")
00143 {
00144 dbe_->cd();
00145 if (MonitorElement* me = dbe_->get(systems[i] + "/EventInfo/processName"))
00146 {
00147 doSaveForOnline(pastSavedFiles_, numKeepSavedFiles_, dbe_,
00148 fileBaseName_ + me->getStringValue() + suffix + ".root",
00149 "", "^(Reference/)?([^/]+)", rewrite,
00150 (DQMStore::SaveReferenceTag) saveReference_,
00151 saveReferenceQMin_);
00152 return;
00153 }
00154 }
00155 }
00156
00157
00158 for (size_t i = 0, e = systems.size(); i != e; ++i)
00159 if (systems[i] != "Reference")
00160 {
00161 dbe_->cd();
00162 std::vector<MonitorElement*> pNamesVector = dbe_->getMatchingContents("^" + systems[i] + "/.*/EventInfo/processName",lat::Regexp::Perl);
00163 std::cout << "pNames vector size:" << pNamesVector.size() << std::endl ;
00164 if (pNamesVector.size() > 0){
00165 doSaveForOnline(pastSavedFiles_, numKeepSavedFiles_, dbe_,
00166 fileBaseName_ + systems[i] + suffix + ".root",
00167 "", "^(Reference/)?([^/]+)", rewrite,
00168 (DQMStore::SaveReferenceTag) saveReference_,
00169 saveReferenceQMin_);
00170 pNamesVector.clear();
00171 return;
00172 }
00173 }
00174
00175
00176 for (size_t i = 0, e = systems.size(); i != e; ++i)
00177 if (systems[i] != "Reference")
00178 doSaveForOnline(pastSavedFiles_, numKeepSavedFiles_, dbe_,
00179 fileBaseName_ + systems[i] + suffix + ".root",
00180 systems[i], "^(Reference/)?([^/]+)", rewrite,
00181 (DQMStore::SaveReferenceTag) saveReference_,
00182 saveReferenceQMin_);
00183 }
00184
00185 void
00186 DQMFileSaver::saveJobReport(const std::string &filename)
00187 {
00188
00189
00190 edm::Service<edm::JobReport> jr;
00191 if (jr.isAvailable())
00192 {
00193 std::map<std::string, std::string> info;
00194 info["Source"] = "DQMStore";
00195 info["FileClass"] = "DQM";
00196 jr->reportAnalysisFile(filename, info);
00197 }
00198
00199 }
00200
00201
00202 DQMFileSaver::DQMFileSaver(const edm::ParameterSet &ps)
00203 : convention_ (Offline),
00204 workflow_ (""),
00205 producer_ ("DQM"),
00206 dirName_ ("."),
00207 version_ (1),
00208 runIsComplete_ (false),
00209 saveByLumiSection_ (-1),
00210 saveByEvent_ (-1),
00211 saveByMinute_ (-1),
00212 saveByTime_ (-1),
00213 saveByRun_ (1),
00214 saveAtJobEnd_ (false),
00215 saveReference_ (DQMStore::SaveWithReference),
00216 saveReferenceQMin_ (dqm::qstatus::STATUS_OK),
00217 forceRunNumber_ (-1),
00218 fileBaseName_ (""),
00219 fileUpdate_ ("RECREATE"),
00220 dbe_ (&*edm::Service<DQMStore>()),
00221 irun_ (-1),
00222 ilumi_ (-1),
00223 ilumiprev_ (-1),
00224 ievent_ (-1),
00225 nrun_ (0),
00226 nlumi_ (0),
00227 nevent_ (0),
00228 numKeepSavedFiles_ (5)
00229 {
00230
00231 std::string convention = ps.getUntrackedParameter<std::string>("convention", "Offline");
00232 if (convention == "Offline")
00233 convention_ = Offline;
00234 else if (convention == "Online")
00235 convention_ = Online;
00236 else
00237 throw cms::Exception("DQMFileSaver")
00238 << "Invalid 'convention' parameter '" << convention << "'."
00239 << " Expected one of 'Online' or 'Offline'.";
00240
00241
00242 if (convention_ != Online)
00243 {
00244 workflow_ = ps.getUntrackedParameter<std::string>("workflow", workflow_);
00245 if (workflow_.empty()
00246 || workflow_[0] != '/'
00247 || *workflow_.rbegin() == '/'
00248 || std::count(workflow_.begin(), workflow_.end(), '/') != 3
00249 || workflow_.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
00250 "abcdefghijklmnopqrstuvwxyz"
00251 "0123456789"
00252 "-_/") != std::string::npos)
00253 throw cms::Exception("DQMFileSaver")
00254 << "Invalid 'workflow' parameter '" << workflow_
00255 << "'. Expected '/A/B/C'.";
00256 }
00257 else if (! ps.getUntrackedParameter<std::string>("workflow", "").empty())
00258 throw cms::Exception("DQMFileSaver")
00259 << "The 'workflow' parameter must be empty in 'Online' convention.";
00260 else
00261 {
00262 workflow_="/Global/Online/P5";
00263 }
00264
00265
00266 producer_ = ps.getUntrackedParameter<std::string>("producer", producer_);
00267 if (convention_ == Online
00268 && producer_ != "DQM"
00269 && producer_ != "HLTDQM"
00270 && producer_ != "Playback")
00271 {
00272 throw cms::Exception("DQMFileSaver")
00273 << "Invalid 'producer' parameter '" << producer_
00274 << "'. Expected 'DQM', 'HLTDQM' or 'Playback'.";
00275 }
00276 else if (convention_ != Online && producer_ != "DQM")
00277 {
00278 throw cms::Exception("DQMFileSaver")
00279 << "Invalid 'producer' parameter '" << producer_
00280 << "'. Expected 'DQM'.";
00281 }
00282
00283
00284 version_ = ps.getUntrackedParameter<int>("version", version_);
00285
00286 runIsComplete_ = ps.getUntrackedParameter<bool>("runIsComplete", runIsComplete_);
00287
00288
00289 std::string refsave = ps.getUntrackedParameter<std::string>("referenceHandling", "default");
00290 if (refsave == "default")
00291 ;
00292 else if (refsave == "skip")
00293 {
00294 saveReference_ = DQMStore::SaveWithoutReference;
00295
00296 }
00297 else if (refsave == "all")
00298 {
00299 saveReference_ = DQMStore::SaveWithReference;
00300
00301 }
00302 else if (refsave == "qtests")
00303 {
00304 saveReference_ = DQMStore::SaveWithReferenceForQTest;
00305
00306 }
00307 else
00308 throw cms::Exception("DQMFileSaver")
00309 << "Invalid 'referenceHandling' parameter '" << refsave
00310 << "'. Expected 'default', 'skip', 'all' or 'qtests'.";
00311
00312
00313 saveReferenceQMin_ = ps.getUntrackedParameter<int>("referenceRequireStatus", saveReferenceQMin_);
00314
00315
00316 struct stat s;
00317 dirName_ = ps.getUntrackedParameter<std::string>("dirName", dirName_);
00318 if (dirName_.empty() || stat(dirName_.c_str(), &s) == -1)
00319 throw cms::Exception("DQMFileSaver")
00320 << "Invalid 'dirName' parameter '" << dirName_ << "'.";
00321
00322
00323
00324
00325
00326 if (convention_ == Online)
00327 {
00328 getAnInt(ps, saveByEvent_, "saveByEvent");
00329 getAnInt(ps, saveByMinute_, "saveByMinute");
00330 getAnInt(ps, saveByTime_, "saveByTime");
00331 getAnInt(ps, numKeepSavedFiles_, "maxSavedFilesCount");
00332 }
00333
00334 if (convention_ == Online || convention_ == Offline)
00335 {
00336 getAnInt(ps, saveByRun_, "saveByRun");
00337 getAnInt(ps, saveByLumiSection_, "saveByLumiSection");
00338 }
00339
00340 if (convention_ != Online)
00341 {
00342 getAnInt(ps, forceRunNumber_, "forceRunNumber");
00343 saveAtJobEnd_ = ps.getUntrackedParameter<bool>("saveAtJobEnd", saveAtJobEnd_);
00344 }
00345
00346 if (saveAtJobEnd_ && forceRunNumber_ < 1)
00347 throw cms::Exception("DQMFileSaver")
00348 << "If saving at the end of the job, the run number must be"
00349 << " overridden to a specific value using 'forceRunNumber'.";
00350
00351
00352
00353 char version[8];
00354 sprintf(version, "_V%04d_", int(version_));
00355 version[7]='\0';
00356 fileBaseName_ = dirName_ + "/" + producer_ + version;
00357 gettimeofday(&start_, 0);
00358 saved_ = start_;
00359
00360
00361 edm::LogInfo("DQMFileSaver")
00362 << "DQM file saving settings:\n"
00363 << " using base file name '" << fileBaseName_ << "'\n"
00364 << " forcing run number " << forceRunNumber_ << "\n"
00365 << " saving every " << saveByLumiSection_ << " lumi section(s)\n"
00366 << " saving every " << saveByEvent_ << " event(s)\n"
00367 << " saving every " << saveByMinute_ << " minute(s)\n"
00368 << " saving every 2^n*" << saveByTime_ << " minutes \n"
00369 << " saving every " << saveByRun_ << " run(s)\n"
00370 << " saving at job end: " << (saveAtJobEnd_ ? "yes" : "no") << "\n"
00371 << " keeping at most " << numKeepSavedFiles_ << " files\n";
00372 }
00373
00374
00375 void
00376 DQMFileSaver::beginJob()
00377 {
00378 irun_ = ilumi_ = ilumiprev_ = ievent_ = -1;
00379 nrun_ = nlumi_ = nevent_ = 0;
00380 }
00381
00382 void
00383 DQMFileSaver::beginRun(const edm::Run &r, const edm::EventSetup &)
00384 {
00385 irun_ = (forceRunNumber_ == -1 ? r.id().run() : forceRunNumber_);
00386 ++nrun_;
00387 }
00388
00389 void
00390 DQMFileSaver::beginLuminosityBlock(const edm::LuminosityBlock &l, const edm::EventSetup &)
00391 {
00392 ilumi_ = l.id().luminosityBlock();
00393 if (ilumiprev_ == -1) ilumiprev_ = ilumi_;
00394 ++nlumi_;
00395 }
00396
00397 void DQMFileSaver::analyze(const edm::Event &e, const edm::EventSetup &)
00398 {
00399 ++nevent_;
00400
00401 ievent_ = e.id().event();
00402
00403
00404 char suffix[64];
00405 if (ievent_ > 0 && saveByEvent_ > 0 && nevent_ == saveByEvent_)
00406 {
00407 if (convention_ != Online)
00408 throw cms::Exception("DQMFileSaver")
00409 << "Internal error, can save files by event"
00410 << " only in Online mode.";
00411
00412 sprintf(suffix, "_R%09d_E%08d", irun_, ievent_);
00413 saveForOnline(suffix, "\\1\\2");
00414 nevent_ = 0;
00415 }
00416
00417
00418 if ( ievent_ > 0 && ( saveByMinute_ > 0 || saveByTime_ > 0 ) )
00419 {
00420 if (convention_ != Online)
00421 throw cms::Exception("DQMFileSaver")
00422 << "Internal error, can save files by time"
00423 << " only in Online mode.";
00424
00425
00426 struct timeval tv;
00427 gettimeofday(&tv, 0);
00428
00429 double totalelapsed = ((tv.tv_sec + tv.tv_usec*1e-6)
00430 - (start_.tv_sec + start_.tv_usec*1e-6)) / 60;
00431 double elapsed = ((tv.tv_sec + tv.tv_usec*1e-6)
00432 - (saved_.tv_sec + saved_.tv_usec*1e-6)) / 60;
00433
00434
00435 if ( (saveByMinute_ > 0 && elapsed > saveByMinute_ ) ||
00436 (saveByTime_ > 0 && totalelapsed > saveByTime_ ) )
00437 {
00438 if ( saveByTime_ > 0 ) saveByTime_ *= 2;
00439 saved_ = tv;
00440 sprintf(suffix, "_R%09d_T%08d", irun_, int(totalelapsed));
00441 char rewrite[64]; sprintf(rewrite, "\\1Run %d/\\2/Run summary", irun_);
00442 saveForOnline(suffix, rewrite);
00443 }
00444 }
00445 }
00446
00447 void
00448 DQMFileSaver::endLuminosityBlock(const edm::LuminosityBlock &, const edm::EventSetup &)
00449 {
00450
00451 if (ilumi_ > 0 && saveByLumiSection_ > 0 )
00452 {
00453 if (convention_ != Online && convention_ != Offline )
00454 throw cms::Exception("DQMFileSaver")
00455 << "Internal error, can save files at end of lumi block"
00456 << " only in Online or Offline mode.";
00457
00458 if (convention_ == Online && nlumi_ == saveByLumiSection_)
00459 {
00460 char suffix[64];
00461 char rewrite[128];
00462 sprintf(suffix, "_R%09d_L%06d", irun_, ilumi_);
00463 sprintf(rewrite, "\\1Run %d/\\2/By Lumi Section %d-%d", irun_, ilumiprev_, ilumi_);
00464 saveForOnline(suffix, rewrite);
00465 ilumiprev_ = -1;
00466 nlumi_ = 0;
00467 }
00468 if (convention_ == Offline)
00469 saveForOffline(workflow_, irun_, ilumi_);
00470 }
00471 }
00472
00473 void
00474 DQMFileSaver::endRun(const edm::Run &, const edm::EventSetup &)
00475 {
00476 if (irun_ > 0 && saveByRun_ > 0 && nrun_ == saveByRun_)
00477 {
00478 if (convention_ == Online)
00479 {
00480 char suffix[64]; sprintf(suffix, "_R%09d", irun_);
00481 char rewrite[64]; sprintf(rewrite, "\\1Run %d/\\2/Run summary", irun_);
00482 saveForOnline(suffix, rewrite);
00483 }
00484 else if (convention_ == Offline)
00485 saveForOffline(workflow_, irun_, 0);
00486 else
00487 throw cms::Exception("DQMFileSaver")
00488 << "Internal error. Can only save files in endRun()"
00489 << " in Online and Offline modes.";
00490
00491 nrun_ = 0;
00492 }
00493 }
00494
00495 void
00496 DQMFileSaver::endJob(void)
00497 {
00498 if (saveAtJobEnd_)
00499 {
00500 if (convention_ == Offline && forceRunNumber_ > 0)
00501 saveForOffline(workflow_, forceRunNumber_, 0);
00502 else
00503 throw cms::Exception("DQMFileSaver")
00504 << "Internal error. Can only save files at the end of the"
00505 << " job in Offline mode with run number overridden.";
00506 }
00507
00508 }