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/Utilities/interface/GetReleaseVersion.h"
00009 #include "FWCore/ServiceRegistry/interface/Service.h"
00010 #include <sys/stat.h>
00011 #include <unistd.h>
00012 #include <iostream>
00013 #include <vector>
00014
00015
00016 static void
00017 getAnInt(const edm::ParameterSet &ps, int &value, const std::string &name)
00018 {
00019 value = ps.getUntrackedParameter<int>(name, value);
00020 if (value < 1 && value != -1)
00021 throw cms::Exception("DQMFileSaver")
00022 << "Invalid '" << name << "' parameter '" << value
00023 << "'. Must be -1 or >= 1.";
00024 }
00025
00026 void
00027 DQMFileSaver::saveForOffline(const std::string &workflow, int run)
00028 {
00029 char suffix[64];
00030 sprintf(suffix, "R%09d", run);
00031
00032 char rewrite[64];
00033 sprintf(rewrite, "\\1Run %d/\\2/Run summary", run);
00034
00035 size_t pos = 0;
00036 std::string wflow;
00037 wflow.reserve(workflow.size() + 3);
00038 wflow = workflow;
00039 while ((pos = wflow.find('/', pos)) != std::string::npos)
00040 wflow.replace(pos++, 1, "__");
00041
00042 dbe_->save(fileBaseName_ + suffix + wflow + ".root",
00043 "", "^(Reference/)?([^/]+)", rewrite,
00044 (DQMStore::SaveReferenceTag) saveReference_,
00045 saveReferenceQMin_);
00046 }
00047
00048 void
00049 DQMFileSaver::saveForOnline(const std::string &suffix, const std::string &rewrite)
00050 {
00051 std::vector<std::string> systems = (dbe_->cd(), dbe_->getSubdirs());
00052
00053 for (size_t i = 0, e = systems.size(); i != e; ++i) {
00054 if (systems[i] != "Reference") {
00055 dbe_->cd();
00056 if (MonitorElement* me = dbe_->get(systems[i] + "/EventInfo/processName")){
00057 dbe_->save(fileBaseName_ + me->getStringValue() + suffix + ".root",
00058 "" , "^(Reference/)?([^/]+)", rewrite,
00059 (DQMStore::SaveReferenceTag) saveReference_,
00060 saveReferenceQMin_);
00061 return;
00062 }
00063 }
00064 }
00065
00066
00067 for (size_t i = 0, e = systems.size(); i != e; ++i)
00068 if (systems[i] != "Reference")
00069 dbe_->save(fileBaseName_ + systems[i] + suffix + ".root",
00070 systems[i] , "^(Reference/)?([^/]+)", rewrite,
00071 (DQMStore::SaveReferenceTag) saveReference_,
00072 saveReferenceQMin_);
00073
00074 }
00075
00076
00077 DQMFileSaver::DQMFileSaver(const edm::ParameterSet &ps)
00078 : convention_ (Offline),
00079 workflow_ (""),
00080 producer_ ("DQM"),
00081 dirName_ ("."),
00082 saveByLumiSection_ (-1),
00083 saveByEvent_ (-1),
00084 saveByMinute_ (-1),
00085 saveByTime_ (-1),
00086 saveByRun_ (1),
00087 saveAtJobEnd_ (false),
00088 saveReference_ (DQMStore::SaveWithReferenceForQTest),
00089 saveReferenceQMin_ (dqm::qstatus::STATUS_OK),
00090 forceRunNumber_ (-1),
00091 fileBaseName_ (""),
00092 dbe_ (&*edm::Service<DQMStore>()),
00093 irun_ (-1),
00094 ilumi_ (-1),
00095 ilumiprev_ (-1),
00096 ievent_ (-1),
00097 nrun_ (0),
00098 nlumi_ (0),
00099 nevent_ (0)
00100 {
00101
00102 std::string convention = ps.getUntrackedParameter<std::string>("convention", "Offline");
00103 if (convention == "Offline")
00104 convention_ = Offline;
00105 else if (convention == "Online")
00106 convention_ = Online;
00107 else if (convention == "RelVal")
00108 {
00109 convention_ = RelVal;
00110 saveByRun_ = -1;
00111 saveAtJobEnd_ = true;
00112 forceRunNumber_ = 1;
00113 }
00114 else
00115 throw cms::Exception("DQMFileSaver")
00116 << "Invalid 'convention' parameter '" << convention << "'."
00117 << " Expected one of 'Online', 'Offline' or 'RelVal'.";
00118
00119
00120 if (convention_ != Online)
00121 {
00122 workflow_ = ps.getUntrackedParameter<std::string>("workflow", workflow_);
00123 if (workflow_.empty()
00124 || workflow_[0] != '/'
00125 || *workflow_.rbegin() == '/'
00126 || std::count(workflow_.begin(), workflow_.end(), '/') != 3
00127 || workflow_.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
00128 "abcdefghijklmnopqrstuvwxyz"
00129 "0123456789"
00130 "-_/") != std::string::npos)
00131 throw cms::Exception("DQMFileSaver")
00132 << "Invalid 'workflow' parameter '" << workflow_
00133 << "'. Expected '/A/B/C'.";
00134 }
00135 else if (! ps.getUntrackedParameter<std::string>("workflow", "").empty())
00136 throw cms::Exception("DQMFileSaver")
00137 << "The 'workflow' parameter must be empty in 'Online' convention.";
00138
00139
00140 producer_ = ps.getUntrackedParameter<std::string>("producer", producer_);
00141 if (convention_ == Online
00142 && producer_ != "DQM"
00143 && producer_ != "HLTDQM"
00144 && producer_ != "Playback")
00145 {
00146 throw cms::Exception("DQMFileSaver")
00147 << "Invalid 'producer' parameter '" << producer_
00148 << "'. Expected 'DQM', 'HLTDQM' or 'Playback'.";
00149 }
00150 else if (convention_ != Online && producer_ != "DQM")
00151 {
00152 throw cms::Exception("DQMFileSaver")
00153 << "Invalid 'producer' parameter '" << producer_
00154 << "'. Expected 'DQM'.";
00155 }
00156
00157
00158 if (convention_ == RelVal)
00159 producer_ = workflow_.substr(1, workflow_.find('/', 1)-1);
00160
00161
00162 std::string refsave = ps.getUntrackedParameter<std::string>("referenceHandling", "default");
00163 if (refsave == "default")
00164 ;
00165 else if (refsave == "skip")
00166 saveReference_ = DQMStore::SaveWithoutReference;
00167 else if (refsave == "all")
00168 saveReference_ = DQMStore::SaveWithReference;
00169 else if (refsave == "qtests")
00170 saveReference_ = DQMStore::SaveWithReferenceForQTest;
00171 else
00172 throw cms::Exception("DQMFileSaver")
00173 << "Invalid 'referenceHandling' parameter '" << refsave
00174 << "'. Expected 'default', 'skip', 'all' or 'qtests'.";
00175
00176
00177 saveReferenceQMin_ = ps.getUntrackedParameter<int>("referenceRequireStatus", saveReferenceQMin_);
00178
00179
00180 struct stat s;
00181 dirName_ = ps.getUntrackedParameter<std::string>("dirName", dirName_);
00182 if (dirName_.empty() || stat(dirName_.c_str(), &s) == -1)
00183 throw cms::Exception("DQMFileSaver")
00184 << "Invalid 'dirName' parameter '" << dirName_ << "'.";
00185
00186
00187
00188
00189
00190
00191 if (convention_ == Online)
00192 {
00193 getAnInt(ps, saveByLumiSection_, "saveByLumiSection");
00194 getAnInt(ps, saveByEvent_, "saveByEvent");
00195 getAnInt(ps, saveByMinute_, "saveByMinute");
00196 getAnInt(ps, saveByTime_, "saveByTime");
00197 }
00198
00199 if (convention_ == Online || convention_ == Offline)
00200 getAnInt(ps, saveByRun_, "saveByRun");
00201
00202 if (convention_ != Online)
00203 {
00204 getAnInt(ps, forceRunNumber_, "forceRunNumber");
00205 saveAtJobEnd_ = ps.getUntrackedParameter<bool>("saveAtJobEnd", saveAtJobEnd_);
00206 if (convention_ == RelVal && ! saveAtJobEnd_)
00207 saveAtJobEnd_ = true;
00208 if (convention_ == RelVal && forceRunNumber_ == -1)
00209 forceRunNumber_ = 1;
00210 }
00211
00212 if (saveAtJobEnd_ && forceRunNumber_ < 1)
00213 throw cms::Exception("DQMFileSaver")
00214 << "If saving at the end of the job, the run number must be"
00215 << " overridden to a specific value using 'forceRunNumber'.";
00216
00217
00218 fileBaseName_ = dirName_ + "/" + producer_ + "_V0001_";
00219 gettimeofday(&start_, 0);
00220 saved_ = start_;
00221
00222
00223 edm::LogInfo("DQMFileSaver")
00224 << "DQM file saving settings:\n"
00225 << " using base file name '" << fileBaseName_ << "'\n"
00226 << " forcing run number " << forceRunNumber_ << "\n"
00227 << " saving every " << saveByLumiSection_ << " lumi section(s)\n"
00228 << " saving every " << saveByEvent_ << " event(s)\n"
00229 << " saving every " << saveByMinute_ << " minute(s)\n"
00230 << " saving every 2^n*" << saveByTime_ << " minutes \n"
00231 << " saving every " << saveByRun_ << " run(s)\n"
00232 << " saving at job end: " << (saveAtJobEnd_ ? "yes" : "no") << "\n";
00233 }
00234
00235
00236 void
00237 DQMFileSaver::beginJob(const edm::EventSetup &)
00238 {
00239 irun_ = ilumi_ = ilumiprev_ = ievent_ = -1;
00240 nrun_ = nlumi_ = nevent_ = 0;
00241 }
00242
00243 void
00244 DQMFileSaver::beginRun(const edm::Run &r, const edm::EventSetup &)
00245 {
00246 irun_ = (forceRunNumber_ == -1 ? r.id().run() : forceRunNumber_);
00247 ++nrun_;
00248 }
00249
00250 void
00251 DQMFileSaver::beginLuminosityBlock(const edm::LuminosityBlock &l, const edm::EventSetup &)
00252 {
00253 ilumi_ = l.id().luminosityBlock();
00254 if (ilumiprev_ == -1) ilumiprev_ = ilumi_;
00255 ++nlumi_;
00256 }
00257
00258 void DQMFileSaver::analyze(const edm::Event &e, const edm::EventSetup &)
00259 {
00260 ++nevent_;
00261
00262 ievent_ = e.id().event();
00263
00264
00265 char suffix[64];
00266 if (ievent_ > 0 && saveByEvent_ > 0 && nevent_ == saveByEvent_)
00267 {
00268 if (convention_ != Online)
00269 throw cms::Exception("DQMFileSaver")
00270 << "Internal error, can save files by event"
00271 << " only in Online mode.";
00272
00273 sprintf(suffix, "_R%09d_E%08d", irun_, ievent_);
00274 saveForOnline(suffix, "\\1\\2");
00275 nevent_ = 0;
00276 }
00277
00278
00279 if ( ievent_ > 0 && ( saveByMinute_ > 0 || saveByTime_ > 0 ) )
00280 {
00281 if (convention_ != Online)
00282 throw cms::Exception("DQMFileSaver")
00283 << "Internal error, can save files by time"
00284 << " only in Online mode.";
00285
00286
00287 struct timeval tv;
00288 gettimeofday(&tv, 0);
00289
00290 double totalelapsed = ((tv.tv_sec + tv.tv_usec*1e-6)
00291 - (start_.tv_sec + start_.tv_usec*1e-6)) / 60;
00292 double elapsed = ((tv.tv_sec + tv.tv_usec*1e-6)
00293 - (saved_.tv_sec + saved_.tv_usec*1e-6)) / 60;
00294
00295
00296 if ( (saveByMinute_ > 0 && elapsed > saveByMinute_ ) ||
00297 (saveByTime_ > 0 && totalelapsed > saveByTime_ ) )
00298 {
00299 if ( saveByTime_ > 0 ) saveByTime_ *= 2;
00300 saved_ = tv;
00301 sprintf(suffix, "_R%09d_T%08d", irun_, int(totalelapsed));
00302 char rewrite[64]; sprintf(rewrite, "\\1Run %d/\\2/Run summary", irun_);
00303 saveForOnline(suffix, rewrite);
00304 }
00305 }
00306 }
00307
00308 void
00309 DQMFileSaver::endLuminosityBlock(const edm::LuminosityBlock &, const edm::EventSetup &)
00310 {
00311 if (ilumi_ > 0 && saveByLumiSection_ > 0 && nlumi_ == saveByLumiSection_)
00312 {
00313 if (convention_ != Online)
00314 throw cms::Exception("DQMFileSaver")
00315 << "Internal error, can save files at end of lumi block"
00316 << " only in Online mode.";
00317
00318 char suffix[64];
00319 char rewrite[128];
00320 sprintf(suffix, "_R%09d_L%06d", irun_, ilumi_);
00321 sprintf(rewrite, "\\1Run %d/\\2/By Lumi Section %d-%d", irun_, ilumiprev_, ilumi_);
00322 saveForOnline(suffix, rewrite);
00323 ilumiprev_ = -1;
00324 nlumi_ = 0;
00325 }
00326 }
00327
00328 void
00329 DQMFileSaver::endRun(const edm::Run &, const edm::EventSetup &)
00330 {
00331 if (irun_ > 0 && saveByRun_ > 0 && nrun_ == saveByRun_)
00332 {
00333 if (convention_ == Online)
00334 {
00335 char suffix[64]; sprintf(suffix, "_R%09d", irun_);
00336 char rewrite[64]; sprintf(rewrite, "\\1Run %d/\\2/Run summary", irun_);
00337 saveForOnline(suffix, rewrite);
00338 }
00339 else if (convention_ == Offline)
00340 saveForOffline(workflow_, irun_);
00341 else
00342 throw cms::Exception("DQMFileSaver")
00343 << "Internal error. Can only save files in endRun()"
00344 << " in Online and Offline modes.";
00345
00346 nrun_ = 0;
00347 }
00348 }
00349
00350 void
00351 DQMFileSaver::endJob(void)
00352 {
00353 if (saveAtJobEnd_)
00354 {
00355 if (convention_ == RelVal)
00356 {
00357 size_t pos;
00358 std::string release = edm::getReleaseVersion();
00359 while ((pos = release.find('"')) != std::string::npos)
00360 release.erase(pos, 1);
00361
00362 pos = fileBaseName_.rfind('/');
00363 std::string stream = fileBaseName_.substr(pos+1, fileBaseName_.size()-pos-2);
00364 dbe_->save(fileBaseName_ + release + ".root",
00365 "", "^(Reference/)?([^/]+)", "\\1" + stream + "/\\2",
00366 (DQMStore::SaveReferenceTag) saveReference_,
00367 saveReferenceQMin_);
00368 }
00369 else if (convention_ == Offline && forceRunNumber_ > 0)
00370 saveForOffline(workflow_, forceRunNumber_);
00371 else
00372 throw cms::Exception("DQMFileSaver")
00373 << "Internal error. Can only save files at the end of the"
00374 << " job in RelVal and Offline modes with run number overridden.";
00375 }
00376 }