CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
DQMStore.cc
Go to the documentation of this file.
8 #include "classlib/utils/RegexpMatch.h"
9 #include "classlib/utils/Regexp.h"
10 #include "classlib/utils/StringOps.h"
11 #include <google/protobuf/io/coded_stream.h>
12 #include <google/protobuf/io/gzip_stream.h>
13 #include <google/protobuf/io/zero_copy_stream_impl.h>
14 #include "TFile.h"
15 #include "TROOT.h"
16 #include "TKey.h"
17 #include "TClass.h"
18 #include "TSystem.h"
19 #include "TBufferFile.h"
20 #include <iterator>
21 #include <cerrno>
22 #include <boost/algorithm/string.hpp>
23 #include <fstream>
24 
51 static const std::string s_monitorDirName = "DQMData";
54 static const std::string s_referenceDirName = "Reference";
55 static const std::string s_collateDirName = "Collate";
56 static const std::string s_safe = "/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+=_()# ";
57 
58 static const lat::Regexp s_rxmeval ("^<(.*)>(i|f|s|e|t|qr)=(.*)</\\1>$");
59 static const lat::Regexp s_rxmeqr1 ("^st:(\\d+):([-+e.\\d]+):([^:]*):(.*)$");
60 static const lat::Regexp s_rxmeqr2 ("^st\\.(\\d+)\\.(.*)$");
61 static const lat::Regexp s_rxtrace ("(.*)\\((.*)\\+0x.*\\).*");
62 static const lat::Regexp s_rxpbfile (".*\\.pb$");
63 
67 static bool
69 {
70  return (ofdir.empty()
71  || (path.size() >= ofdir.size()
72  && path.compare(0, ofdir.size(), ofdir) == 0
73  && (path.size() == ofdir.size()
74  || path[ofdir.size()] == '/')));
75 }
76 
77 static void
79 {
80  clean.clear();
81  cleaned = &path;
82 
83  size_t len = path.size();
84  for ( ; len > 0 && path[len-1] == '/'; --len)
85  ;
86 
87  if (len != path.size())
88  {
89  clean = path.substr(0, len);
90  cleaned = &clean;
91  }
92 }
93 
94 static void
96 {
97  size_t slash = path.rfind('/');
98  if (slash != std::string::npos)
99  {
100  dir.append(path, 0, slash);
101  name.append(path, slash+1, std::string::npos);
102  }
103  else
104  name = path;
105 }
106 
107 static void
109 {
110  path.reserve(dir.size() + name.size() + 2);
111  path += dir;
112  if (! path.empty())
113  path += '/';
114  path += name;
115 }
116 
117 template <class T>
118 QCriterion *
120 { return new T(qtname); }
121 
122 template <class T>
123 void
125 { m[T::getAlgoName()] = &makeQCriterion<T>; }
126 
127 
129 fastmatch::fastmatch (std::string const& _fastString) :
130  fastString_ (_fastString), matching_ (UseFull)
131 {
132  try
133  {
134  regexp_ = NULL;
135  regexp_ = new lat::Regexp(fastString_, 0, lat::Regexp::Wildcard);
136  regexp_->study();
137  }
138  catch (lat::Error &e)
139  {
140  delete regexp_;
141  raiseDQMError("DQMStore", "Invalid wildcard pattern '%s' in quality"
142  " test specification", fastString_.c_str());
143  }
144 
145  // count stars ( "*" )
146  size_t starCount = 0;
147  int pos = -1;
148  while (true)
149  {
150  pos = fastString_.find("*", pos + 1 );
151  if ((size_t)pos == std::string::npos)
152  break;
153  starCount ++;
154  }
155 
156  // investigate for heuristics
157  if ((fastString_.find('"') != std::string::npos) ||
158  (fastString_.find(']') != std::string::npos) ||
159  (fastString_.find('?') != std::string::npos) ||
160  (fastString_.find('\\') != std::string::npos) ||
161  (starCount > 2))
162  {
163  // no fast version can be used
164  return;
165  }
166 
167  // match for pattern "*MyString" and "MyString*"
168  if (starCount == 1)
169  {
170  if (boost::algorithm::starts_with(fastString_, "*"))
171  {
173  fastString_.erase(0,1);
174  return;
175  }
176 
177  if (boost::algorithm::ends_with(fastString_, "*"))
178  {
180  fastString_.erase(fastString_.length()-1,1);
181  return;
182  }
183  }
184 
185  // match for pattern "*MyString*"
186  if (starCount == 2)
187  {
188  if (boost::algorithm::starts_with(fastString_, "*") &&
189  boost::algorithm::ends_with(fastString_, "*"))
190  {
191  matching_ = TwoStar;
192  fastString_.erase(0,1);
193  fastString_.erase(fastString_.size() - 1, 1);
194  return;
195  }
196  }
197 }
198 
200 {
201  if (regexp_ != NULL)
202  delete regexp_;
203 }
204 
206  std::string const& input) const
207 {
208  if (input.size() < pattern.size())
209  return false;
210 
211  // compare the two strings character by character for equalness:
212  // this does not create uneeded copies of std::string. The
213  // boost::algorithm implementation does
214  std::string::const_reverse_iterator rit_pattern = pattern.rbegin();
215  std::string::const_reverse_iterator rit_input = input.rbegin();
216 
217  for (; rit_pattern < pattern.rend(); rit_pattern++, rit_input++)
218  {
219  if (*rit_pattern != *rit_input)
220  // found a difference, fail
221  return false;
222  }
223  return true;
224 }
225 
227  std::string const& input) const
228 {
229  if (input.size() < pattern.size())
230  return false;
231 
232  // compare the two strings character by character for equalness:
233  // this does not create uneeded copies of std::string. The
234  // boost::algorithm implementation does.
235  std::string::const_iterator rit_pattern = pattern.begin();
236  std::string::const_iterator rit_input = input.begin();
237 
238  for (; rit_pattern < pattern.end(); rit_pattern++, rit_input++)
239  {
240  if (*rit_pattern != *rit_input)
241  // found a difference, fail
242  return false;
243  }
244  return true;
245 }
246 
247 bool fastmatch::match(std::string const& s) const
248 {
249  switch (matching_)
250  {
251  case OneStarStart:
253 
254  case OneStarEnd:
255  return compare_strings(fastString_, s);
256 
257  case TwoStar:
258  return (s.find(fastString_) != std::string::npos);
259 
260  default:
261  return regexp_->match(s);
262  }
263 }
264 
265 //IBooker methods
267  owner_->cd();
268 }
269 
271  owner_->cd(dir);
272 }
273 
275  owner_->setCurrentFolder(fullpath);
276 }
277 
279  owner_->goUp();
280 }
281 
283  return owner_->pwd();
284 }
285 
286 void DQMStore::IBooker::tag(MonitorElement *me, unsigned int tag) {
287  owner_->tag(me, tag);
288 }
289 
290 //IGetter methods
291 std::vector<MonitorElement*>
293  uint32_t runNumber /* = 0 */,
294  uint32_t lumi /* = 0 */) {
295  return owner_->getAllContents(path, runNumber, lumi);
296 }
297 
299  return owner_->get(path);
300 }
301 
302 std::vector<std::string> DQMStore::IGetter::getSubdirs(void) {
303  return owner_->getSubdirs();
304 }
305 
306 std::vector<std::string> DQMStore::IGetter::getMEs(void) {
307  return owner_->getMEs();
308 }
309 
311  return owner_->containsAnyMonitorable(path);
312 }
313 
315  return owner_->dirExists(path);
316 }
317 
319  owner_->cd();
320 }
321 
323  owner_->cd(dir);
324 }
325 
327  owner_->setCurrentFolder(fullpath);
328 }
329 
340  uint32_t streamId,
341  uint32_t moduleId) {
342  if (verbose_ > 1)
343  std::cout << "DQMStore::mergeAndResetMEsRunSummaryCache - Merging objects from run: "
344  << run
345  << ", stream: " << streamId
346  << " module: " << moduleId << std::endl;
347 
348  if (LSbasedMode_) {
349  return;
350  }
351 
352  std::string null_str("");
353  MonitorElement proto(&null_str, null_str, run, streamId, moduleId);
354  std::set<MonitorElement>::const_iterator e = data_.end();
355  std::set<MonitorElement>::const_iterator i = data_.lower_bound(proto);
356  while (i != e) {
357  if (i->data_.run != run
358  || i->data_.streamId != streamId
359  || i->data_.moduleId != moduleId)
360  break;
361 
362  // Handle Run-based histograms only.
363  if (i->getLumiFlag() || LSbasedMode_) {
364  ++i;
365  continue;
366  }
367 
368  MonitorElement global_me(*i);
369  global_me.globalize();
370  // Since this accesses the data, the operation must be
371  // be locked.
372  std::lock_guard<std::mutex> guard(book_mutex_);
373  std::set<MonitorElement>::const_iterator me = data_.find(global_me);
374  if (me != data_.end()) {
375  if (verbose_ > 1)
376  std::cout << "Found global Object, using it --> " << me->getFullname() << std::endl;
377 
378  //don't take any action if the ME is an INT || FLOAT || STRING
379  if(me->kind() >= MonitorElement::DQM_KIND_TH1F)
380  me->getTH1()->Add(i->getTH1());
381 
382  } else {
383  if (verbose_ > 1)
384  std::cout << "No global Object found. " << std::endl;
385  std::pair<std::set<MonitorElement>::const_iterator, bool> gme;
386  gme = data_.insert(global_me);
387  assert(gme.second);
388  }
389  // TODO(rovere): eventually reset the local object and mark it as reusable??
390  ++i;
391  }
392 }
393 
395  uint32_t lumi,
396  uint32_t streamId,
397  uint32_t moduleId) {
398  if (verbose_ > 1)
399  std::cout << "DQMStore::mergeAndResetMEsLuminositySummaryCache - Merging objects from run: "
400  << run << " lumi: " << lumi
401  << ", stream: " << streamId
402  << " module: " << moduleId << std::endl;
403  std::string null_str("");
404  MonitorElement proto(&null_str, null_str, run, streamId, moduleId);
405  std::set<MonitorElement>::const_iterator e = data_.end();
406  std::set<MonitorElement>::const_iterator i = data_.lower_bound(proto);
407 
408  while (i != e) {
409  if (i->data_.run != run
410  || i->data_.streamId != streamId
411  || i->data_.moduleId != moduleId)
412  break;
413 
414  // Handle LS-based histograms only.
415  if (not (i->getLumiFlag() || LSbasedMode_)) {
416  ++i;
417  continue;
418  }
419 
420  MonitorElement global_me(*i);
421  global_me.globalize();
422  global_me.setLumi(lumi);
423  // Since this accesses the data, the operation must be
424  // be locked.
425  std::lock_guard<std::mutex> guard(book_mutex_);
426  std::set<MonitorElement>::const_iterator me = data_.find(global_me);
427  if (me != data_.end()) {
428  if (verbose_ > 1)
429  std::cout << "Found global Object, using it --> " << me->getFullname() << std::endl;
430 
431  //don't take any action if the ME is an INT || FLOAT || STRING
432  if (me->kind() >= MonitorElement::DQM_KIND_TH1F)
433  me->getTH1()->Add(i->getTH1());
434  } else {
435  if (verbose_ > 1)
436  std::cout << "No global Object found. " << std::endl;
437  std::pair<std::set<MonitorElement>::const_iterator, bool> gme;
438  gme = data_.insert(global_me);
439  assert(gme.second);
440  }
441  // make the ME reusable for the next LS
442  const_cast<MonitorElement*>(&*i)->Reset();
443  ++i;
444 
445  // check and remove the global lumi based histo belonging to the previous LSs
446  // if properly flagged as DQMNet::DQM_PROP_MARKTODELETE
447  global_me.setLumi(1);
448  std::set<MonitorElement>::const_iterator i_lumi = data_.lower_bound(global_me);
449  while (i_lumi->data_.lumi != lumi) {
450  auto temp = i_lumi++;
451  if (i_lumi->getFullname() == i->getFullname() && i_lumi->markedToDelete())
452  {
453  data_.erase(temp);
454  }
455  }
456  }
457 }
458 
461  : verbose_ (1),
462  verboseQT_ (1),
463  reset_ (false),
468  run_(0),
469  streamId_(0),
470  moduleId_(0),
471  stream_(nullptr),
472  pwd_ (""),
473  ibooker_(0),
474  igetter_(0)
475 {
476  if (!ibooker_)
477  ibooker_ = new DQMStore::IBooker(this);
478  if (!igetter_)
479  igetter_ = new DQMStore::IGetter(this);
480  initializeFrom(pset);
481 
482  if(pset.getUntrackedParameter<bool>("forceResetOnBeginRun",false)) {
484  }
485  ar.preallocateSignal_.connect([this](edm::service::SystemBounds const& iBounds) {
486  if(iBounds.maxNumberOfStreams() > 1 ) {
487  enableMultiThread_ = true;
488  }
489  });
490  if(pset.getUntrackedParameter<bool>("forceResetOnBeginLumi",false) && enableMultiThread_ == false) {
491  forceResetOnBeginLumi_ = true;
493  }
494 }
495 
497  : verbose_ (1),
498  verboseQT_ (1),
499  reset_ (false),
500  collateHistograms_ (false),
501  enableMultiThread_(false),
502  readSelectedDirectory_ (""),
503  run_(0),
504  streamId_(0),
505  moduleId_(0),
506  stream_(nullptr),
507  pwd_ (""),
508  ibooker_(0),
509  igetter_(0)
510 {
511  if (!ibooker_)
512  ibooker_ = new DQMStore::IBooker(this);
513  if (!igetter_)
514  igetter_ = new DQMStore::IGetter(this);
515  initializeFrom(pset);
516 }
517 
519 {
520  for (QCMap::iterator i = qtests_.begin(), e = qtests_.end(); i != e; ++i)
521  delete i->second;
522 
523  for (QTestSpecs::iterator i = qtestspecs_.begin(), e = qtestspecs_.end(); i != e; ++i)
524  delete i->first;
525 
526  if (stream_)
527  stream_->close();
528  delete stream_;
529 }
530 
531 void
533  makeDirectory("");
534  reset();
535 
536  // set steerable parameters
537  verbose_ = pset.getUntrackedParameter<int>("verbose", 0);
538  if (verbose_ > 0)
539  std::cout << "DQMStore: verbosity set to " << verbose_ << std::endl;
540 
541  verboseQT_ = pset.getUntrackedParameter<int>("verboseQT", 0);
542  if (verbose_ > 0)
543  std::cout << "DQMStore: QTest verbosity set to " << verboseQT_ << std::endl;
544 
545  collateHistograms_ = pset.getUntrackedParameter<bool>("collateHistograms", false);
546  if (collateHistograms_)
547  std::cout << "DQMStore: histogram collation is enabled\n";
548 
549  enableMultiThread_ = pset.getUntrackedParameter<bool>("enableMultiThread", false);
550  if (enableMultiThread_)
551  std::cout << "DQMStore: MultiThread option is enabled\n";
552 
553  LSbasedMode_ = pset.getUntrackedParameter<bool>("LSbasedMode", false);
554  if (LSbasedMode_)
555  std::cout << "DQMStore: LSbasedMode option is enabled\n";
556 
557  std::string ref = pset.getUntrackedParameter<std::string>("referenceFileName", "");
558  if (! ref.empty())
559  {
560  std::cout << "DQMStore: using reference file '" << ref << "'\n";
561  readFile(ref, true, "", s_referenceDirName, StripRunDirs, false);
562  }
563 
564  initQCriterion<Comp2RefChi2>(qalgos_);
565  initQCriterion<Comp2RefKolmogorov>(qalgos_);
566  initQCriterion<ContentsXRange>(qalgos_);
567  initQCriterion<ContentsYRange>(qalgos_);
568  initQCriterion<MeanWithinExpected>(qalgos_);
569  initQCriterion<Comp2RefEqualH>(qalgos_);
570  initQCriterion<DeadChannel>(qalgos_);
571  initQCriterion<NoisyChannel>(qalgos_);
572  initQCriterion<ContentsWithinExpected>(qalgos_);
573  initQCriterion<CompareToMedian>(qalgos_);
574  initQCriterion<CompareLastFilledBin>(qalgos_);
575  initQCriterion<CheckVariance>(qalgos_);
576 
577  scaleFlag_ = pset.getUntrackedParameter<double>("ScalingFlag", 0.0);
578  if (verbose_ > 0)
579  std::cout << "DQMStore: Scaling Flag set to " << scaleFlag_ << std::endl;
580 }
581 
582 /* Generic method to do a backtrace and print it to stdout. It is
583  customised to properly get the routine that called the booking of the
584  histograms, which, following the usual stack, is at position 4. The
585  name of the calling function is properly demangled and the original
586  shared library including this function is also printed. For a more
587  detailed explanation of the routines involved, see here:
588  http://www.gnu.org/software/libc/manual/html_node/Backtraces.html
589  http://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html.*/
590 
591 void
593 {
594  // the access to the member stream_ is implicitely protected against
595  // concurrency problems because the print_trace method is always called behind
596  // a lock (see bookTransaction).
597  if (!stream_)
598  stream_ = new ofstream("histogramBookingBT.log");
599 
600  void *array[10];
601  size_t size;
602  char **strings;
603  int r=0;
604  lat::RegexpMatch m;
605  m.reset();
606 
607  size = backtrace (array, 10);
608  strings = backtrace_symbols (array, size);
609 
610  if ((size > 4)
611  &&s_rxtrace.match(strings[4], 0, 0, &m))
612  {
613  char * demangled = abi::__cxa_demangle(m.matchString(strings[4], 2).c_str(), 0, 0, &r);
614  *stream_ << "\"" << dir << "/"
615  << name << "\" "
616  << (r ? m.matchString(strings[4], 2) : demangled) << " "
617  << m.matchString(strings[4], 1) << "\n";
618  free(demangled);
619  }
620  else
621  *stream_ << "Skipping "<< dir << "/" << name
622  << " with stack size " << size << "\n";
623  /* In this case print the full stack trace, up to main or to the
624  * maximum stack size, i.e. 10. */
625  if (verbose_ > 4)
626  {
627  size_t i;
628  m.reset();
629 
630  for (i = 0; i < size; i++)
631  if (s_rxtrace.match(strings[i], 0, 0, &m))
632  {
633  char * demangled = abi::__cxa_demangle(m.matchString(strings[i], 2).c_str(), 0, 0, &r);
634  *stream_ << "\t\t" << i << "/" << size << " "
635  << (r ? m.matchString(strings[i], 2) : demangled) << " "
636  << m.matchString(strings[i], 1) << std::endl;
637  free (demangled);
638  }
639  }
640  free (strings);
641 }
642 
647 void
648 DQMStore::setVerbose(unsigned /* level */)
649 { return; }
650 
655 const std::string &
656 DQMStore::pwd(void) const
657 { return pwd_; }
658 
660 void
662 { setCurrentFolder(""); }
663 
665 void
666 DQMStore::cd(const std::string &subdir)
667 {
669  const std::string *cleaned = 0;
670  cleanTrailingSlashes(subdir, clean, cleaned);
671 
672  if (! dirExists(*cleaned))
673  raiseDQMError("DQMStore", "Cannot 'cd' into non-existent directory '%s'",
674  cleaned->c_str());
675 
676  setCurrentFolder(*cleaned);
677 }
678 
683 void
685 {
687  const std::string *cleaned = 0;
688  cleanTrailingSlashes(fullpath, clean, cleaned);
689  makeDirectory(*cleaned);
690  pwd_ = *cleaned;
691 }
692 
694 void
696 {
697  size_t pos = pwd_.rfind('/');
698  if (pos == std::string::npos)
699  setCurrentFolder("");
700  else
701  setCurrentFolder(pwd_.substr(0, pos));
702 }
703 
704 // -------------------------------------------------------------------
707 void
709 {
710  std::string prev;
711  std::string subdir;
713  prev.reserve(path.size());
714  subdir.reserve(path.size());
715  name.reserve(path.size());
716  size_t prevname = 0;
717  size_t slash = 0;
718 
719  while (true)
720  {
721  // Create this subdirectory component.
722  subdir.clear();
723  subdir.append(path, 0, slash);
724  name.clear();
725  name.append(subdir, prevname, std::string::npos);
726  if (! prev.empty() && findObject(prev, name))
727  raiseDQMError("DQMStore", "Attempt to create subdirectory '%s'"
728  " which already exists as a monitor element",
729  subdir.c_str());
730 
731  if (! dirs_.count(subdir))
732  dirs_.insert(subdir);
733 
734  // Stop if we've reached the end (including possibly a trailing slash).
735  if (slash+1 >= path.size())
736  break;
737 
738  // Find the next slash, making sure we progress. If reach the end,
739  // process the last path component; the next loop round will terminate.
740  prevname = slash ? slash+1 : slash;
741  prev = subdir;
742  if ((slash = path.find('/', ++slash)) == std::string::npos)
743  slash = path.size();
744  }
745 }
746 
748 bool
750 { return dirs_.count(path) > 0; }
751 
755 template <class HISTO, class COLLATE>
758  const char *context, int kind,
759  HISTO *h, COLLATE collate)
760 {
761  assert(name.find('/') == std::string::npos);
762  if (verbose_ > 3)
763  print_trace(dir, name);
765  mergePath(path, dir, name);
766 
767  // Put us in charge of h.
768  h->SetDirectory(0);
769 
770  // Check if the request monitor element already exists.
771  MonitorElement *me = findObject(dir, name, run_, 0, streamId_, moduleId_);
772  if (me)
773  {
774  if (collateHistograms_)
775  {
776  collate(me, h, verbose_);
777  delete h;
778  return me;
779  }
780  else
781  {
782  if (verbose_ > 1)
783  std::cout << "DQMStore: "
784  << context << ": monitor element '"
785  << path << "' already exists, collating" << std::endl;
786  me->Reset();
787  collate(me, h, verbose_);
788  delete h;
789  return me;
790  }
791  }
792  else
793  {
794  // Create and initialise core object.
795  assert(dirs_.count(dir));
796  MonitorElement proto(&*dirs_.find(dir), name, run_, streamId_, moduleId_);
797  me = const_cast<MonitorElement &>(*data_.insert(proto).first)
799 
800  // Initialise quality test information.
801  QTestSpecs::iterator qi = qtestspecs_.begin();
802  QTestSpecs::iterator qe = qtestspecs_.end();
803  for ( ; qi != qe; ++qi)
804  {
805  if ( qi->first->match(path) )
806  me->addQReport(qi->second);
807  }
808 
809  // Assign reference if we have one.
810  std::string refdir;
811  refdir.reserve(s_referenceDirName.size() + dir.size() + 2);
812  refdir += s_referenceDirName;
813  refdir += '/';
814  refdir += dir;
815 
816  if (findObject(refdir, name))
817  {
818  me->data_.flags |= DQMNet::DQM_PROP_HAS_REFERENCE;
819  }
820  // Return the monitor element.
821  return me;
822  }
823 }
824 
827  const std::string &name,
828  const char *context)
829 {
830  assert(name.find('/') == std::string::npos);
831  if (verbose_ > 3)
832  print_trace(dir, name);
833 
834  // Check if the request monitor element already exists.
835  if (MonitorElement *me = findObject(dir, name, run_, 0, streamId_, moduleId_))
836  {
837  if (verbose_ > 1)
838  {
840  mergePath(path, dir, name);
841 
842  std::cout << "DQMStore: "
843  << context << ": monitor element '"
844  << path << "' already exists, resetting" << std::endl;
845  }
846  me->Reset();
847  return me;
848  }
849  else
850  {
851  // Create it and return for initialisation.
852  assert(dirs_.count(dir));
853  MonitorElement proto(&*dirs_.find(dir), name, run_, streamId_, moduleId_);
854  return &const_cast<MonitorElement &>(*data_.insert(proto).first);
855  }
856 }
857 
858 // -------------------------------------------------------------------
862 {
863  if (collateHistograms_)
864  {
865  if (MonitorElement *me = findObject(dir, name, run_, 0, streamId_, moduleId_))
866  {
867  me->Fill(0);
868  return me;
869  }
870  }
871 
872  return book(dir, name, "bookInt")
874 }
875 
879 { return bookInt(pwd_, name); }
880 
884 {
885  return bookInt(pwd_, name);
886 }
887 
888 // -------------------------------------------------------------------
892 {
893  if (collateHistograms_)
894  {
895  if (MonitorElement *me = findObject(dir, name, run_, 0, streamId_, moduleId_))
896  {
897  me->Fill(0.);
898  return me;
899  }
900  }
901 
902  return book(dir, name, "bookFloat")
904 }
905 
909 { return bookFloat(pwd_, name); }
910 
914 {
915  return bookFloat(pwd_, name);
916 }
917 
918 // -------------------------------------------------------------------
922  const std::string &name,
923  const std::string &value)
924 {
925  if (collateHistograms_)
926  {
927  if (MonitorElement *me = findObject(dir, name, run_, 0, streamId_, moduleId_))
928  return me;
929  }
930 
931  return book(dir, name, "bookString")
933 }
934 
937 DQMStore::bookString(const char *name, const char *value)
938 { return bookString(pwd_, name, value); }
939 
943 {
944  return bookString(pwd_, name, value);
945 }
946 
947 // -------------------------------------------------------------------
951 {
952  return book(dir, name, "book1D", MonitorElement::DQM_KIND_TH1F, h, collate1D);
953 }
954 
958 {
959  return book(dir, name, "book1S", MonitorElement::DQM_KIND_TH1S, h, collate1S);
960 }
961 
965 {
966  return book(dir, name, "book1DD", MonitorElement::DQM_KIND_TH1D, h, collate1DD);
967 }
968 
971 DQMStore::book1D(const char *name, const char *title,
972  int nchX, double lowX, double highX)
973 {
974  return book1D(pwd_, name, new TH1F(name, title, nchX, lowX, highX));
975 }
976 
980  int nchX, double lowX, double highX)
981 {
982  return book1D(pwd_, name, new TH1F(name.c_str(), title.c_str(), nchX, lowX, highX));
983 }
984 
987 DQMStore::book1S(const char *name, const char *title,
988  int nchX, double lowX, double highX)
989 {
990  return book1S(pwd_, name, new TH1S(name, title, nchX, lowX, highX));
991 }
992 
996  int nchX, double lowX, double highX)
997 {
998  return book1S(pwd_, name, new TH1S(name.c_str(), title.c_str(), nchX, lowX, highX));
999 }
1000 
1003 DQMStore::book1DD(const char *name, const char *title,
1004  int nchX, double lowX, double highX)
1005 {
1006  return book1DD(pwd_, name, new TH1D(name, title, nchX, lowX, highX));
1007 }
1008 
1012  int nchX, double lowX, double highX)
1013 {
1014  return book1DD(pwd_, name, new TH1D(name.c_str(), title.c_str(), nchX, lowX, highX));
1015 }
1016 
1019 DQMStore::book1D(const char *name, const char *title,
1020  int nchX, const float *xbinsize)
1021 {
1022  return book1D(pwd_, name, new TH1F(name, title, nchX, xbinsize));
1023 }
1024 
1028  int nchX, const float *xbinsize)
1029 {
1030  return book1D(pwd_, name, new TH1F(name.c_str(), title.c_str(), nchX, xbinsize));
1031 }
1032 
1035 DQMStore::book1D(const char *name, TH1F *source)
1036 {
1037  return book1D(pwd_, name, static_cast<TH1F *>(source->Clone(name)));
1038 }
1039 
1043 {
1044  return book1D(pwd_, name, static_cast<TH1F *>(source->Clone(name.c_str())));
1045 }
1046 
1049 DQMStore::book1S(const char *name, TH1S *source)
1050 {
1051  return book1S(pwd_, name, static_cast<TH1S *>(source->Clone(name)));
1052 }
1053 
1057 {
1058  return book1S(pwd_, name, static_cast<TH1S *>(source->Clone(name.c_str())));
1059 }
1060 
1063 DQMStore::book1DD(const char *name, TH1D *source)
1064 {
1065  return book1DD(pwd_, name, static_cast<TH1D *>(source->Clone(name)));
1066 }
1067 
1071 {
1072  return book1DD(pwd_, name, static_cast<TH1D *>(source->Clone(name.c_str())));
1073 }
1074 
1075 // -------------------------------------------------------------------
1079 {
1080  return book(dir, name, "book2D", MonitorElement::DQM_KIND_TH2F, h, collate2D);
1081 }
1082 
1086 {
1087  return book(dir, name, "book2S", MonitorElement::DQM_KIND_TH2S, h, collate2S);
1088 }
1089 
1093 {
1094  return book(dir, name, "book2DD", MonitorElement::DQM_KIND_TH2D, h, collate2DD);
1095 }
1096 
1099 DQMStore::book2D(const char *name, const char *title,
1100  int nchX, double lowX, double highX,
1101  int nchY, double lowY, double highY)
1102 {
1103  return book2D(pwd_, name, new TH2F(name, title,
1104  nchX, lowX, highX,
1105  nchY, lowY, highY));
1106 }
1107 
1111  int nchX, double lowX, double highX,
1112  int nchY, double lowY, double highY)
1113 {
1114  return book2D(pwd_, name, new TH2F(name.c_str(), title.c_str(),
1115  nchX, lowX, highX,
1116  nchY, lowY, highY));
1117 }
1118 
1121 DQMStore::book2S(const char *name, const char *title,
1122  int nchX, double lowX, double highX,
1123  int nchY, double lowY, double highY)
1124 {
1125  return book2S(pwd_, name, new TH2S(name, title,
1126  nchX, lowX, highX,
1127  nchY, lowY, highY));
1128 }
1129 
1133  int nchX, double lowX, double highX,
1134  int nchY, double lowY, double highY)
1135 {
1136  return book2S(pwd_, name, new TH2S(name.c_str(), title.c_str(),
1137  nchX, lowX, highX,
1138  nchY, lowY, highY));
1139 }
1140 
1143 DQMStore::book2DD(const char *name, const char *title,
1144  int nchX, double lowX, double highX,
1145  int nchY, double lowY, double highY)
1146 {
1147  return book2DD(pwd_, name, new TH2D(name, title,
1148  nchX, lowX, highX,
1149  nchY, lowY, highY));
1150 }
1151 
1155  int nchX, double lowX, double highX,
1156  int nchY, double lowY, double highY)
1157 {
1158  return book2DD(pwd_, name, new TH2D(name.c_str(), title.c_str(),
1159  nchX, lowX, highX,
1160  nchY, lowY, highY));
1161 }
1162 
1165 DQMStore::book2D(const char *name, const char *title,
1166  int nchX, const float *xbinsize, int nchY, const float *ybinsize)
1167 {
1168  return book2D(pwd_, name, new TH2F(name, title,
1169  nchX, xbinsize, nchY, ybinsize));
1170 }
1171 
1175  int nchX, const float *xbinsize, int nchY, const float *ybinsize)
1176 {
1177  return book2D(pwd_, name, new TH2F(name.c_str(), title.c_str(),
1178  nchX, xbinsize, nchY, ybinsize));
1179 }
1180 
1183 DQMStore::book2D(const char *name, TH2F *source)
1184 {
1185  return book2D(pwd_, name, static_cast<TH2F *>(source->Clone(name)));
1186 }
1187 
1191 {
1192  return book2D(pwd_, name, static_cast<TH2F *>(source->Clone(name.c_str())));
1193 }
1194 
1197 DQMStore::book2S(const char *name, TH2S *source)
1198 {
1199  return book2S(pwd_, name, static_cast<TH2S *>(source->Clone(name)));
1200 }
1201 
1205 {
1206  return book2S(pwd_, name, static_cast<TH2S *>(source->Clone(name.c_str())));
1207 }
1208 
1211 DQMStore::book2DD(const char *name, TH2D *source)
1212 {
1213  return book2DD(pwd_, name, static_cast<TH2D *>(source->Clone(name)));
1214 }
1215 
1219 {
1220  return book2DD(pwd_, name, static_cast<TH2D *>(source->Clone(name.c_str())));
1221 }
1222 
1223 // -------------------------------------------------------------------
1227 {
1228  return book(dir, name, "book3D", MonitorElement::DQM_KIND_TH3F, h, collate3D);
1229 }
1230 
1233 DQMStore::book3D(const char *name, const char *title,
1234  int nchX, double lowX, double highX,
1235  int nchY, double lowY, double highY,
1236  int nchZ, double lowZ, double highZ)
1237 {
1238  return book3D(pwd_, name, new TH3F(name, title,
1239  nchX, lowX, highX,
1240  nchY, lowY, highY,
1241  nchZ, lowZ, highZ));
1242 }
1243 
1247  int nchX, double lowX, double highX,
1248  int nchY, double lowY, double highY,
1249  int nchZ, double lowZ, double highZ)
1250 {
1251  return book3D(pwd_, name, new TH3F(name.c_str(), title.c_str(),
1252  nchX, lowX, highX,
1253  nchY, lowY, highY,
1254  nchZ, lowZ, highZ));
1255 }
1256 
1259 DQMStore::book3D(const char *name, TH3F *source)
1260 {
1261  return book3D(pwd_, name, static_cast<TH3F *>(source->Clone(name)));
1262 }
1263 
1267 {
1268  return book3D(pwd_, name, static_cast<TH3F *>(source->Clone(name.c_str())));
1269 }
1270 
1271 // -------------------------------------------------------------------
1275 {
1276  return book(dir, name, "bookProfile",
1278  h, collateProfile);
1279 }
1280 
1285 DQMStore::bookProfile(const char *name, const char *title,
1286  int nchX, double lowX, double highX,
1287  int /* nchY */, double lowY, double highY,
1288  const char *option /* = "s" */)
1289 {
1290  return bookProfile(pwd_, name, new TProfile(name, title,
1291  nchX, lowX, highX,
1292  lowY, highY,
1293  option));
1294 }
1295 
1301  int nchX, double lowX, double highX,
1302  int /* nchY */, double lowY, double highY,
1303  const char *option /* = "s" */)
1304 {
1305  return bookProfile(pwd_, name, new TProfile(name.c_str(), title.c_str(),
1306  nchX, lowX, highX,
1307  lowY, highY,
1308  option));
1309 }
1310 
1315 DQMStore::bookProfile(const char *name, const char *title,
1316  int nchX, double lowX, double highX,
1317  double lowY, double highY,
1318  const char *option /* = "s" */)
1319 {
1320  return bookProfile(pwd_, name, new TProfile(name, title,
1321  nchX, lowX, highX,
1322  lowY, highY,
1323  option));
1324 }
1325 
1331  int nchX, double lowX, double highX,
1332  double lowY, double highY,
1333  const char *option /* = "s" */)
1334 {
1335  return bookProfile(pwd_, name, new TProfile(name.c_str(), title.c_str(),
1336  nchX, lowX, highX,
1337  lowY, highY,
1338  option));
1339 }
1340 
1345 DQMStore::bookProfile(const char *name, const char *title,
1346  int nchX, const double *xbinsize,
1347  int /* nchY */, double lowY, double highY,
1348  const char *option /* = "s" */)
1349 {
1350  return bookProfile(pwd_, name, new TProfile(name, title,
1351  nchX, xbinsize,
1352  lowY, highY,
1353  option));
1354 }
1355 
1361  int nchX, const double *xbinsize,
1362  int /* nchY */, double lowY, double highY,
1363  const char *option /* = "s" */)
1364 {
1365  return bookProfile(pwd_, name, new TProfile(name.c_str(), title.c_str(),
1366  nchX, xbinsize,
1367  lowY, highY,
1368  option));
1369 }
1370 
1375 DQMStore::bookProfile(const char *name, const char *title,
1376  int nchX, const double *xbinsize,
1377  double lowY, double highY,
1378  const char *option /* = "s" */)
1379 {
1380  return bookProfile(pwd_, name, new TProfile(name, title,
1381  nchX, xbinsize,
1382  lowY, highY,
1383  option));
1384 }
1385 
1391  int nchX, const double *xbinsize,
1392  double lowY, double highY,
1393  const char *option /* = "s" */)
1394 {
1395  return bookProfile(pwd_, name, new TProfile(name.c_str(), title.c_str(),
1396  nchX, xbinsize,
1397  lowY, highY,
1398  option));
1399 }
1400 
1403 DQMStore::bookProfile(const char *name, TProfile *source)
1404 {
1405  return bookProfile(pwd_, name, static_cast<TProfile *>(source->Clone(name)));
1406 }
1407 
1411 {
1412  return bookProfile(pwd_, name, static_cast<TProfile *>(source->Clone(name.c_str())));
1413 }
1414 
1415 // -------------------------------------------------------------------
1419 {
1420  return book(dir, name, "bookProfile2D",
1422  h, collateProfile2D);
1423 }
1424 
1429 DQMStore::bookProfile2D(const char *name, const char *title,
1430  int nchX, double lowX, double highX,
1431  int nchY, double lowY, double highY,
1432  int /* nchZ */, double lowZ, double highZ,
1433  const char *option /* = "s" */)
1434 {
1435  return bookProfile2D(pwd_, name, new TProfile2D(name, title,
1436  nchX, lowX, highX,
1437  nchY, lowY, highY,
1438  lowZ, highZ,
1439  option));
1440 }
1441 
1447  int nchX, double lowX, double highX,
1448  int nchY, double lowY, double highY,
1449  int /* nchZ */, double lowZ, double highZ,
1450  const char *option /* = "s" */)
1451 {
1452  return bookProfile2D(pwd_, name, new TProfile2D(name.c_str(), title.c_str(),
1453  nchX, lowX, highX,
1454  nchY, lowY, highY,
1455  lowZ, highZ,
1456  option));
1457 }
1458 
1463 DQMStore::bookProfile2D(const char *name, const char *title,
1464  int nchX, double lowX, double highX,
1465  int nchY, double lowY, double highY,
1466  double lowZ, double highZ,
1467  const char *option /* = "s" */)
1468 {
1469  return bookProfile2D(pwd_, name, new TProfile2D(name, title,
1470  nchX, lowX, highX,
1471  nchY, lowY, highY,
1472  lowZ, highZ,
1473  option));
1474 }
1475 
1481  int nchX, double lowX, double highX,
1482  int nchY, double lowY, double highY,
1483  double lowZ, double highZ,
1484  const char *option /* = "s" */)
1485 {
1486  return bookProfile2D(pwd_, name, new TProfile2D(name.c_str(), title.c_str(),
1487  nchX, lowX, highX,
1488  nchY, lowY, highY,
1489  lowZ, highZ,
1490  option));
1491 }
1492 
1495 DQMStore::bookProfile2D(const char *name, TProfile2D *source)
1496 {
1497  return bookProfile2D(pwd_, name, static_cast<TProfile2D *>(source->Clone(name)));
1498 }
1499 
1503 {
1504  return bookProfile2D(pwd_, name, static_cast<TProfile2D *>(source->Clone(name.c_str())));
1505 }
1506 
1510 bool
1512 {
1513  if (me->getTH1()->GetNbinsX() != h->GetNbinsX()
1514  || me->getTH1()->GetNbinsY() != h->GetNbinsY()
1515  || me->getTH1()->GetNbinsZ() != h->GetNbinsZ()
1516  || me->getTH1()->GetXaxis()->GetXmin() != h->GetXaxis()->GetXmin()
1517  || me->getTH1()->GetYaxis()->GetXmin() != h->GetYaxis()->GetXmin()
1518  || me->getTH1()->GetZaxis()->GetXmin() != h->GetZaxis()->GetXmin()
1519  || me->getTH1()->GetXaxis()->GetXmax() != h->GetXaxis()->GetXmax()
1520  || me->getTH1()->GetYaxis()->GetXmax() != h->GetYaxis()->GetXmax()
1521  || me->getTH1()->GetZaxis()->GetXmax() != h->GetZaxis()->GetXmax()
1522  || !MonitorElement::CheckBinLabels((TAxis*)me->getTH1()->GetXaxis(),(TAxis*)h->GetXaxis())
1523  || !MonitorElement::CheckBinLabels((TAxis*)me->getTH1()->GetYaxis(),(TAxis*)h->GetYaxis())
1524  || !MonitorElement::CheckBinLabels((TAxis*)me->getTH1()->GetZaxis(),(TAxis*)h->GetZaxis()) )
1525  {
1526  if(verbose > 0)
1527  std::cout << "*** DQMStore: WARNING:"
1528  << "checkBinningMatches: different binning - cannot add object '"
1529  << h->GetName() << "' of type "
1530  << h->IsA()->GetName() << " to existing ME: '"
1531  << me->getFullname() << "'\n";
1532  return false;
1533  }
1534  return true;
1535 }
1536 
1537 void
1539 {
1540  if (checkBinningMatches(me,h,verbose))
1541  me->getTH1F()->Add(h);
1542 }
1543 
1544 void
1546 {
1547  if (checkBinningMatches(me,h,verbose))
1548  me->getTH1S()->Add(h);
1549 }
1550 
1551 void
1553 {
1554  if (checkBinningMatches(me,h,verbose))
1555  me->getTH1D()->Add(h);
1556 }
1557 
1558 void
1560 {
1561  if (checkBinningMatches(me,h,verbose))
1562  me->getTH2F()->Add(h);
1563 }
1564 
1565 void
1567 {
1568  if (checkBinningMatches(me,h,verbose))
1569  me->getTH2S()->Add(h);
1570 }
1571 
1572 void
1574 {
1575  if (checkBinningMatches(me,h,verbose))
1576  me->getTH2D()->Add(h);
1577 }
1578 
1579 void
1581 {
1582  if (checkBinningMatches(me,h,verbose))
1583  me->getTH3F()->Add(h);
1584 }
1585 
1586 void
1588 {
1589  if (checkBinningMatches(me,h,verbose))
1590  {
1591  TProfile *meh = me->getTProfile();
1592  me->addProfiles(h, meh, meh, 1, 1);
1593  }
1594 }
1595 
1596 void
1598 {
1599  if (checkBinningMatches(me,h,verbose))
1600  {
1601  TProfile2D *meh = me->getTProfile2D();
1602  me->addProfiles(h, meh, meh, 1, 1);
1603  }
1604 }
1605 
1610 void
1611 DQMStore::tag(MonitorElement *me, unsigned int myTag)
1612 {
1613  if (! myTag)
1614  raiseDQMError("DQMStore", "Attempt to tag monitor element '%s'"
1615  " with a zero tag", me->getFullname().c_str());
1616  if ((me->data_.flags & DQMNet::DQM_PROP_TAGGED) && myTag != me->data_.tag)
1617  raiseDQMError("DQMStore", "Attempt to tag monitor element '%s'"
1618  " twice with multiple tags", me->getFullname().c_str());
1619 
1620  me->data_.tag = myTag;
1622 }
1623 
1625 void
1626 DQMStore::tag(const std::string &path, unsigned int myTag)
1627 {
1628  std::string dir;
1629  std::string name;
1630  splitPath(dir, name, path);
1631 
1632  if (MonitorElement *me = findObject(dir, name))
1633  tag(me, myTag);
1634  else
1635  raiseDQMError("DQMStore", "Attempt to tag non-existent monitor element"
1636  " '%s' with tag %u", path.c_str(), myTag);
1637 
1638 }
1639 
1641 void
1642 DQMStore::tagContents(const std::string &path, unsigned int myTag)
1643 {
1644  MonitorElement proto(&path, std::string());
1645  MEMap::iterator e = data_.end();
1646  MEMap::iterator i = data_.lower_bound(proto);
1647  for ( ; i != e && path == *i->data_.dirname; ++i)
1648  tag(const_cast<MonitorElement *>(&*i), myTag);
1649 }
1650 
1653 void
1654 DQMStore::tagAllContents(const std::string &path, unsigned int myTag)
1655 {
1657  const std::string *cleaned = 0;
1658  cleanTrailingSlashes(path, clean, cleaned);
1659  MonitorElement proto(cleaned, std::string());
1660 
1661  // FIXME: WILDCARDS? Old one supported them, but nobody seemed to use them.
1662  MEMap::iterator e = data_.end();
1663  MEMap::iterator i = data_.lower_bound(proto);
1664  while (i != e && isSubdirectory(*cleaned, *i->data_.dirname))
1665  {
1666  tag(const_cast<MonitorElement *>(&*i), myTag);
1667  ++i;
1668  }
1669 }
1670 
1675 std::vector<std::string>
1677 {
1678  std::vector<std::string> result;
1679  std::set<std::string>::const_iterator e = dirs_.end();
1680  std::set<std::string>::const_iterator i = dirs_.find(pwd_);
1681 
1682  // If we didn't find current directory, the tree is empty, so quit.
1683  if (i == e)
1684  return result;
1685 
1686  // Skip the current directory and then start looking for immediate
1687  // subdirectories in the dirs_ list. Stop when we are no longer in
1688  // (direct or indirect) subdirectories of pwd_. Note that we don't
1689  // "know" which order the set will sort A/B, A/B/C and A/D.
1690  while (++i != e && isSubdirectory(pwd_, *i))
1691  if (i->find('/', pwd_.size()+1) == std::string::npos)
1692  result.push_back(*i);
1693 
1694  return result;
1695 }
1696 
1698 std::vector<std::string>
1699 DQMStore::getMEs(void) const
1700 {
1701  MonitorElement proto(&pwd_, std::string());
1702  std::vector<std::string> result;
1703  MEMap::const_iterator e = data_.end();
1704  MEMap::const_iterator i = data_.lower_bound(proto);
1705  for ( ; i != e && isSubdirectory(pwd_, *i->data_.dirname); ++i)
1706  if (pwd_ == *i->data_.dirname)
1707  result.push_back(i->getName());
1708 
1709  return result;
1710 }
1711 
1714 bool
1716 {
1717  MonitorElement proto(&path, std::string());
1718  MEMap::const_iterator e = data_.end();
1719  MEMap::const_iterator i = data_.lower_bound(proto);
1720  return (i != e && isSubdirectory(path, *i->data_.dirname));
1721 }
1722 
1726 {
1727  std::string dir;
1728  std::string name;
1729  splitPath(dir, name, path);
1730  MonitorElement proto(&dir, name);
1731  MEMap::const_iterator mepos = data_.find(proto);
1732  return (mepos == data_.end() ? 0
1733  : const_cast<MonitorElement *>(&*mepos));
1734 }
1735 
1737 std::vector<MonitorElement *>
1738 DQMStore::get(unsigned int tag) const
1739 {
1740  // FIXME: Use reverse map [tag -> path] / [tag -> dir]?
1741  std::vector<MonitorElement *> result;
1742  for (MEMap::const_iterator i = data_.begin(), e = data_.end(); i != e; ++i)
1743  {
1744  const MonitorElement &me = *i;
1745  if ((me.data_.flags & DQMNet::DQM_PROP_TAGGED) && me.data_.tag == tag)
1746  result.push_back(const_cast<MonitorElement *>(&me));
1747  }
1748  return result;
1749 }
1750 
1753 std::vector<MonitorElement *>
1755 {
1757  const std::string *cleaned = 0;
1758  cleanTrailingSlashes(path, clean, cleaned);
1759  MonitorElement proto(cleaned, std::string());
1760 
1761  std::vector<MonitorElement *> result;
1762  MEMap::const_iterator e = data_.end();
1763  MEMap::const_iterator i = data_.lower_bound(proto);
1764  for ( ; i != e && isSubdirectory(*cleaned, *i->data_.dirname); ++i)
1765  if (*cleaned == *i->data_.dirname)
1766  result.push_back(const_cast<MonitorElement *>(&*i));
1767 
1768  return result;
1769 }
1770 
1772 std::vector<MonitorElement *>
1773 DQMStore::getContents(const std::string &path, unsigned int tag) const
1774 {
1776  const std::string *cleaned = 0;
1777  cleanTrailingSlashes(path, clean, cleaned);
1778  MonitorElement proto(cleaned, std::string());
1779 
1780  std::vector<MonitorElement *> result;
1781  MEMap::const_iterator e = data_.end();
1782  MEMap::const_iterator i = data_.lower_bound(proto);
1783  for ( ; i != e && isSubdirectory(*cleaned, *i->data_.dirname); ++i)
1784  if (*cleaned == *i->data_.dirname
1785  && (i->data_.flags & DQMNet::DQM_PROP_TAGGED)
1786  && i->data_.tag == tag)
1787  result.push_back(const_cast<MonitorElement *>(&*i));
1788 
1789  return result;
1790 }
1791 
1796 void
1797 DQMStore::getContents(std::vector<std::string> &into, bool showContents /* = true */) const
1798 {
1799  into.clear();
1800  into.reserve(dirs_.size());
1801 
1802  MEMap::const_iterator me = data_.end();
1803  std::set<std::string>::const_iterator di = dirs_.begin();
1804  std::set<std::string>::const_iterator de = dirs_.end();
1805  for ( ; di != de; ++di)
1806  {
1807  MonitorElement proto(&*di, std::string());
1808  MEMap::const_iterator mi = data_.lower_bound(proto);
1809  MEMap::const_iterator m = mi;
1810  size_t sz = di->size() + 2;
1811  size_t nfound = 0;
1812  for ( ; m != me && isSubdirectory(*di, *m->data_.dirname); ++m)
1813  if (*di == *m->data_.dirname)
1814  {
1815  sz += m->data_.objname.size() + 1;
1816  ++nfound;
1817  }
1818 
1819  if (! nfound)
1820  continue;
1821 
1822  std::vector<std::string>::iterator istr
1823  = into.insert(into.end(), std::string());
1824 
1825  if (showContents)
1826  {
1827  istr->reserve(sz);
1828 
1829  *istr += *di;
1830  *istr += ':';
1831  for (sz = 0; mi != m; ++mi)
1832  {
1833  if (*di != *mi->data_.dirname)
1834  continue;
1835 
1836  if (sz > 0)
1837  *istr += ',';
1838 
1839  *istr += mi->data_.objname;
1840  ++sz;
1841  }
1842  }
1843  else
1844  {
1845  istr->reserve(di->size() + 2);
1846  *istr += *di;
1847  *istr += ':';
1848  }
1849  }
1850 }
1851 
1856  const std::string &name,
1857  const uint32_t run /* = 0 */,
1858  const uint32_t lumi /* = 0 */,
1859  const uint32_t streamId /* = 0 */,
1860  const uint32_t moduleId /* = 0 */) const
1861 {
1862  if (dir.find_first_not_of(s_safe) != std::string::npos)
1863  raiseDQMError("DQMStore", "Monitor element path name '%s' uses"
1864  " unacceptable characters", dir.c_str());
1865  if (name.find_first_not_of(s_safe) != std::string::npos)
1866  raiseDQMError("DQMStore", "Monitor element path name '%s' uses"
1867  " unacceptable characters", name.c_str());
1868 
1869  MonitorElement proto;
1870  proto.data_.dirname = &dir;
1871  proto.data_.objname = name;
1872  proto.data_.run = run;
1873  proto.data_.lumi = lumi;
1874  proto.data_.streamId = streamId;
1875  proto.data_.moduleId = moduleId;
1876 
1877  MEMap::const_iterator mepos = data_.find(proto);
1878  return (mepos == data_.end() ? 0
1879  : const_cast<MonitorElement *>(&*mepos));
1880 }
1881 
1884 void
1885 DQMStore::getAllTags(std::vector<std::string> &into) const
1886 {
1887  into.clear();
1888  into.reserve(dirs_.size());
1889 
1890  MEMap::const_iterator me = data_.end();
1891  std::set<std::string>::const_iterator di = dirs_.begin();
1892  std::set<std::string>::const_iterator de = dirs_.end();
1893  char tagbuf[32]; // more than enough for '/' and up to 10 digits
1894 
1895  for ( ; di != de; ++di)
1896  {
1897  MonitorElement proto(&*di, std::string());
1898  MEMap::const_iterator mi = data_.lower_bound(proto);
1899  MEMap::const_iterator m = mi;
1900  size_t sz = di->size() + 2;
1901  size_t nfound = 0;
1902  for ( ; m != me && isSubdirectory(*di, *m->data_.dirname); ++m)
1903  if (*di == *m->data_.dirname && (m->data_.flags & DQMNet::DQM_PROP_TAGGED))
1904  {
1905  // the tags count for '/' + up to 10 digits, otherwise ',' + ME name
1906  sz += 1 + m->data_.objname.size() + 11;
1907  ++nfound;
1908  }
1909 
1910  if (! nfound)
1911  continue;
1912 
1913  std::vector<std::string>::iterator istr
1914  = into.insert(into.end(), std::string());
1915 
1916  istr->reserve(sz);
1917 
1918  *istr += *di;
1919  *istr += ':';
1920  for (sz = 0; mi != m; ++mi)
1921  {
1922  if (*di == *m->data_.dirname && (m->data_.flags & DQMNet::DQM_PROP_TAGGED))
1923  {
1924  sprintf(tagbuf, "/%u", mi->data_.tag);
1925  if (sz > 0)
1926  *istr += ',';
1927  *istr += m->data_.objname;
1928  *istr += tagbuf;
1929  ++sz;
1930  }
1931  }
1932  }
1933 }
1934 
1937 std::vector<MonitorElement*>
1939  uint32_t runNumber /* = 0 */,
1940  uint32_t lumi /* = 0 */) const
1941 {
1943  const std::string *cleaned = 0;
1944  cleanTrailingSlashes(path, clean, cleaned);
1945  MonitorElement proto(cleaned, std::string(), runNumber);
1946  proto.setLumi(lumi);
1947 
1948  std::vector<MonitorElement *> result;
1949  MEMap::const_iterator e = data_.end();
1950  MEMap::const_iterator i = data_.lower_bound(proto);
1951  for ( ; i != e && isSubdirectory(*cleaned, *i->data_.dirname); ++i) {
1952  if (runNumber != 0) {
1953  if (i->data_.run > runNumber // TODO[rovere]: pleonastic? first we encounter local ME of the same run ...
1954  || i->data_.streamId != 0
1955  || i->data_.moduleId != 0)
1956  break;
1957  }
1958  if (lumi != 0) {
1959  if (i->data_.lumi > lumi
1960  || i->data_.streamId != 0
1961  || i->data_.moduleId != 0)
1962  break;
1963  }
1964  if (runNumber != 0 or lumi !=0) {
1965  assert(i->data_.streamId == 0);
1966  assert(i->data_.moduleId == 0);
1967  }
1968  result.push_back(const_cast<MonitorElement *>(&*i));
1969  }
1970  return result;
1971 }
1972 
1975 std::vector<MonitorElement*>
1976 DQMStore::getMatchingContents(const std::string &pattern, lat::Regexp::Syntax syntaxType /* = Wildcard */) const
1977 {
1978  lat::Regexp rx;
1979  try
1980  {
1981  rx = lat::Regexp(pattern, 0, syntaxType);
1982  rx.study();
1983  }
1984  catch (lat::Error &e)
1985  {
1986  raiseDQMError("DQMStore", "Invalid regular expression '%s': %s",
1987  pattern.c_str(), e.explain().c_str());
1988  }
1989 
1990  std::string path;
1991  std::vector<MonitorElement *> result;
1992  MEMap::const_iterator i = data_.begin();
1993  MEMap::const_iterator e = data_.end();
1994  for ( ; i != e; ++i)
1995  {
1996  path.clear();
1997  mergePath(path, *i->data_.dirname, i->data_.objname);
1998  if (rx.match(path))
1999  result.push_back(const_cast<MonitorElement *>(&*i));
2000  }
2001 
2002  return result;
2003 }
2004 
2008 
2011 void
2013 {
2014  MEMap::iterator mi = data_.begin();
2015  MEMap::iterator me = data_.end();
2016  for ( ; mi != me; ++mi)
2017  {
2018  MonitorElement &me = const_cast<MonitorElement &>(*mi);
2019  if (mi->wasUpdated())
2020  {
2021  if (me.resetMe())
2022  me.Reset();
2023  me.resetUpdate();
2024  }
2025  }
2026 
2027  reset_ = true;
2028 }
2029 
2033 
2035 void
2037 {
2038  MEMap::iterator mi = data_.begin();
2039  MEMap::iterator me = data_.end();
2040  for ( ; mi != me; ++mi)
2041  {
2042  if (forceResetOnBeginLumi_ && ((*mi).getLumiFlag() == false))
2043  continue;
2044  MonitorElement &me = const_cast<MonitorElement &>(*mi);
2045  me.Reset();
2046  me.resetUpdate();
2047  }
2048 
2049  reset_ = true;
2050 }
2051 
2055 
2056 void
2058  uint32_t lumi)
2059 {
2060 
2061  std::string null_str("");
2062  MonitorElement proto(&null_str, null_str, run, 0, 0);
2063  if (enableMultiThread_)
2064  proto.setLumi(lumi);
2065 
2066  std::set<MonitorElement>::const_iterator e = data_.end();
2067  std::set<MonitorElement>::const_iterator i = data_.lower_bound(proto);
2068 
2069  while (i != e) {
2070  if (i->data_.streamId != 0 ||
2071  i->data_.moduleId != 0)
2072  break;
2073  if ((i->data_.lumi != lumi) && enableMultiThread_)
2074  break;
2075  if (i->data_.run != run)
2076  break;
2077 
2078  const_cast<MonitorElement*>(&*i)->markToDelete();
2079 
2080  if (verbose_ > 1)
2081  std::cout << "DQMStore::markForDeletion: marked monitor element '"
2082  << *i->data_.dirname << "/" << i->data_.objname << "'"
2083  << "flags " << i->data_.flags << "\n";
2084 
2085  ++i;
2086  }
2087 }
2088 
2089 
2095 bool
2097  bool overwrite, bool collateHistograms)
2098 {
2099  // NB: Profile histograms inherit from TH*D, checking order matters.
2100  MonitorElement *refcheck = 0;
2101  if (TProfile *h = dynamic_cast<TProfile *>(obj))
2102  {
2103  MonitorElement *me = findObject(dir, h->GetName());
2104  if (! me)
2105  me = bookProfile(dir, h->GetName(), (TProfile *) h->Clone());
2106  else if (overwrite)
2107  me->copyFrom(h);
2108  else if (isCollateME(me) || collateHistograms)
2109  collateProfile(me, h, verbose_);
2110  refcheck = me;
2111  }
2112  else if (TProfile2D *h = dynamic_cast<TProfile2D *>(obj))
2113  {
2114  MonitorElement *me = findObject(dir, h->GetName());
2115  if (! me)
2116  me = bookProfile2D(dir, h->GetName(), (TProfile2D *) h->Clone());
2117  else if (overwrite)
2118  me->copyFrom(h);
2119  else if (isCollateME(me) || collateHistograms)
2120  collateProfile2D(me, h, verbose_);
2121  refcheck = me;
2122  }
2123  else if (TH1F *h = dynamic_cast<TH1F *>(obj))
2124  {
2125  MonitorElement *me = findObject(dir, h->GetName());
2126  if (! me)
2127  me = book1D(dir, h->GetName(), (TH1F *) h->Clone());
2128  else if (overwrite)
2129  me->copyFrom(h);
2130  else if (isCollateME(me) || collateHistograms)
2131  collate1D(me, h, verbose_);
2132  refcheck = me;
2133  }
2134  else if (TH1S *h = dynamic_cast<TH1S *>(obj))
2135  {
2136  MonitorElement *me = findObject(dir, h->GetName());
2137  if (! me)
2138  me = book1S(dir, h->GetName(), (TH1S *) h->Clone());
2139  else if (overwrite)
2140  me->copyFrom(h);
2141  else if (isCollateME(me) || collateHistograms)
2142  collate1S(me, h, verbose_);
2143  refcheck = me;
2144  }
2145  else if (TH1D *h = dynamic_cast<TH1D *>(obj))
2146  {
2147  MonitorElement *me = findObject(dir, h->GetName());
2148  if (! me)
2149  me = book1DD(dir, h->GetName(), (TH1D *) h->Clone());
2150  else if (overwrite)
2151  me->copyFrom(h);
2152  else if (isCollateME(me) || collateHistograms)
2153  collate1DD(me, h, verbose_);
2154  refcheck = me;
2155  }
2156  else if (TH2F *h = dynamic_cast<TH2F *>(obj))
2157  {
2158  MonitorElement *me = findObject(dir, h->GetName());
2159  if (! me)
2160  me = book2D(dir, h->GetName(), (TH2F *) h->Clone());
2161  else if (overwrite)
2162  me->copyFrom(h);
2163  else if (isCollateME(me) || collateHistograms)
2164  collate2D(me, h, verbose_);
2165  refcheck = me;
2166  }
2167  else if (TH2S *h = dynamic_cast<TH2S *>(obj))
2168  {
2169  MonitorElement *me = findObject(dir, h->GetName());
2170  if (! me)
2171  me = book2S(dir, h->GetName(), (TH2S *) h->Clone());
2172  else if (overwrite)
2173  me->copyFrom(h);
2174  else if (isCollateME(me) || collateHistograms)
2175  collate2S(me, h, verbose_);
2176  refcheck = me;
2177  }
2178  else if (TH2D *h = dynamic_cast<TH2D *>(obj))
2179  {
2180  MonitorElement *me = findObject(dir, h->GetName());
2181  if (! me)
2182  me = book2DD(dir, h->GetName(), (TH2D *) h->Clone());
2183  else if (overwrite)
2184  me->copyFrom(h);
2185  else if (isCollateME(me) || collateHistograms)
2186  collate2DD(me, h, verbose_);
2187  refcheck = me;
2188  }
2189  else if (TH3F *h = dynamic_cast<TH3F *>(obj))
2190  {
2191  MonitorElement *me = findObject(dir, h->GetName());
2192  if (! me)
2193  me = book3D(dir, h->GetName(), (TH3F *) h->Clone());
2194  else if (overwrite)
2195  me->copyFrom(h);
2196  else if (isCollateME(me) || collateHistograms)
2197  collate3D(me, h, verbose_);
2198  refcheck = me;
2199  }
2200  else if (dynamic_cast<TObjString *>(obj))
2201  {
2202  lat::RegexpMatch m;
2203  if (! s_rxmeval.match(obj->GetName(), 0, 0, &m))
2204  {
2205  if (strstr(obj->GetName(), "CMSSW"))
2206  {
2207  if (verbose_)
2208  std::cout << "Input file version: " << obj->GetName() << std::endl;
2209  return true;
2210  }
2211  else if (strstr(obj->GetName(), "DQMPATCH"))
2212  {
2213  if (verbose_)
2214  std::cout << "DQM patch version: " << obj->GetName() << std::endl;
2215  return true;
2216  }
2217  else
2218  {
2219  std::cout << "*** DQMStore: WARNING: cannot extract object '"
2220  << obj->GetName() << "' of type '"
2221  << obj->IsA()->GetName() << "'\n";
2222  return false;
2223  }
2224  }
2225 
2226  std::string label = m.matchString(obj->GetName(), 1);
2227  std::string kind = m.matchString(obj->GetName(), 2);
2228  std::string value = m.matchString(obj->GetName(), 3);
2229 
2230  if (kind == "i")
2231  {
2232  MonitorElement *me = findObject(dir, label);
2233  if (! me || overwrite)
2234  {
2235  if (! me) me = bookInt(dir, label);
2236  me->Fill(atoll(value.c_str()));
2237  }
2238  }
2239  else if (kind == "f")
2240  {
2241  MonitorElement *me = findObject(dir, label);
2242  if (! me || overwrite)
2243  {
2244  if (! me) me = bookFloat(dir, label);
2245  me->Fill(atof(value.c_str()));
2246  }
2247  }
2248  else if (kind == "s")
2249  {
2250  MonitorElement *me = findObject(dir, label);
2251  if (! me)
2252  me = bookString(dir, label, value);
2253  else if (overwrite)
2254  me->Fill(value);
2255  }
2256  else if (kind == "e")
2257  {
2258  MonitorElement *me = findObject(dir, label);
2259  if (! me)
2260  {
2261  std::cout << "*** DQMStore: WARNING: no monitor element '"
2262  << label << "' in directory '"
2263  << dir << "' to be marked as efficiency plot.\n";
2264  return false;
2265  }
2266  me->setEfficiencyFlag();
2267  }
2268  else if (kind == "t")
2269  {
2270  MonitorElement *me = findObject(dir, label);
2271  if (! me)
2272  {
2273  std::cout << "*** DQMStore: WARNING: no monitor element '"
2274  << label << "' in directory '"
2275  << dir << "' for a tag\n";
2276  return false;
2277  }
2278  errno = 0;
2279  char *endp = 0;
2280  unsigned long val = strtoul(value.c_str(), &endp, 10);
2281  if ((val == 0 && errno) || *endp || val > ~uint32_t(0))
2282  {
2283  std::cout << "*** DQMStore: WARNING: cannot restore tag '"
2284  << value << "' for monitor element '"
2285  << label << "' in directory '"
2286  << dir << "' - invalid value\n";
2287  return false;
2288  }
2289  tag(me, val);
2290  }
2291  else if (kind == "qr")
2292  {
2293  // Handle qreports, but skip them while reading in references.
2294  if (! isSubdirectory(s_referenceDirName, dir))
2295  {
2296  size_t dot = label.find('.');
2297  if (dot == std::string::npos)
2298  {
2299  std::cout << "*** DQMStore: WARNING: quality report label in '" << label
2300  << "' is missing a '.' and cannot be extracted\n";
2301  return false;
2302  }
2303 
2304  std::string mename (label, 0, dot);
2305  std::string qrname (label, dot+1, std::string::npos);
2306 
2307  m.reset();
2308  DQMNet::QValue qv;
2309  if (s_rxmeqr1.match(value, 0, 0, &m))
2310  {
2311  qv.code = atoi(m.matchString(value, 1).c_str());
2312  qv.qtresult = strtod(m.matchString(value, 2).c_str(), 0);
2313  qv.message = m.matchString(value, 4);
2314  qv.qtname = qrname;
2315  qv.algorithm = m.matchString(value, 3);
2316  }
2317  else if (s_rxmeqr2.match(value, 0, 0, &m))
2318  {
2319  qv.code = atoi(m.matchString(value, 1).c_str());
2320  qv.qtresult = 0; // unavailable in old format
2321  qv.message = m.matchString(value, 2);
2322  qv.qtname = qrname;
2323  // qv.algorithm unavailable in old format
2324  }
2325  else
2326  {
2327  std::cout << "*** DQMStore: WARNING: quality test value '"
2328  << value << "' is incorrectly formatted\n";
2329  return false;
2330  }
2331 
2332  MonitorElement *me = findObject(dir, mename);
2333  if (! me)
2334  {
2335  std::cout << "*** DQMStore: WARNING: no monitor element '"
2336  << mename << "' in directory '"
2337  << dir << "' for quality test '"
2338  << label << "'\n";
2339  return false;
2340  }
2341 
2342  me->addQReport(qv, /* FIXME: getQTest(qv.qtname)? */ 0);
2343  }
2344  }
2345  else
2346  {
2347  std::cout << "*** DQMStore: WARNING: cannot extract object '"
2348  << obj->GetName() << "' of type '"
2349  << obj->IsA()->GetName() << "'\n";
2350  return false;
2351  }
2352  }
2353  else if (TNamed *n = dynamic_cast<TNamed *>(obj))
2354  {
2355  // For old DQM data.
2356  std::string s;
2357  s.reserve(6 + strlen(n->GetTitle()) + 2*strlen(n->GetName()));
2358  s += '<'; s += n->GetName(); s += '>';
2359  s += n->GetTitle();
2360  s += '<'; s += '/'; s += n->GetName(); s += '>';
2361  TObjString os(s.c_str());
2362  return extract(&os, dir, overwrite, collateHistograms_);
2363  }
2364  else
2365  {
2366  std::cout << "*** DQMStore: WARNING: cannot extract object '"
2367  << obj->GetName() << "' of type '" << obj->IsA()->GetName()
2368  << "' and with title '" << obj->GetTitle() << "'\n";
2369  return false;
2370  }
2371 
2372  // If we just read in a reference monitor element, and there is a
2373  // monitor element with the same name, link the two together. The
2374  // other direction is handled by the initialise() method.
2375  if (refcheck && isSubdirectory(s_referenceDirName, dir))
2376  {
2377  std::string mdir(dir, s_referenceDirName.size()+1, std::string::npos);
2378  if (MonitorElement *master = findObject(mdir, obj->GetName()))
2379  {
2380  master->data_.flags |= DQMNet::DQM_PROP_HAS_REFERENCE;
2381  master->reference_ = refcheck->object_;
2382  }
2383  }
2384 
2385  return true;
2386 }
2387 
2391 bool
2393 {
2394  assert(! path.empty());
2395 
2396  // Find the first path component.
2397  size_t start = 0;
2398  size_t end = path.find('/', start);
2399  if (end == std::string::npos)
2400  end = path.size();
2401 
2402  while (true)
2403  {
2404  // Check if this subdirectory component exists. If yes, make sure
2405  // it is actually a subdirectory. Otherwise create or cd into it.
2406  std::string part(path, start, end-start);
2407  TObject *o = gDirectory->Get(part.c_str());
2408  if (o && ! dynamic_cast<TDirectory *>(o))
2409  raiseDQMError("DQMStore", "Attempt to create directory '%s' in a file"
2410  " fails because the part '%s' already exists and is not"
2411  " directory", path.c_str(), part.c_str());
2412  else if (! o)
2413  gDirectory->mkdir(part.c_str());
2414 
2415  if (! gDirectory->cd(part.c_str()))
2416  raiseDQMError("DQMStore", "Attempt to create directory '%s' in a file"
2417  " fails because could not cd into subdirectory '%s'",
2418  path.c_str(), part.c_str());
2419 
2420  // Stop if we reached the end, ignoring any trailing '/'.
2421  if (end+1 >= path.size())
2422  break;
2423 
2424  // Find the next path component.
2425  start = end+1;
2426  end = path.find('/', start);
2427  if (end == std::string::npos)
2428  end = path.size();
2429  }
2430 
2431  return true;
2432 }
2433 
2435  const std::string &path /* = "" */,
2436  const uint32_t run /* = 0 */,
2437  const uint32_t lumi /* = 0 */,
2438  const bool resetMEsAfterWriting /* = false */)
2439 {
2440  using google::protobuf::io::FileOutputStream;
2441  using google::protobuf::io::GzipOutputStream;
2442  using google::protobuf::io::StringOutputStream;
2443 
2444  std::set<std::string>::iterator di, de;
2445  MEMap::iterator mi, me = data_.end();
2446  dqmstorepb::ROOTFilePB dqmstore_message;
2447  int nme = 0;
2448 
2449  if (verbose_)
2450  std::cout << "\n DQMStore: Opening PBFile '"
2451  << filename << "'"<< std::endl;
2452 
2453  // Loop over the directory structure.
2454  for (di = dirs_.begin(), de = dirs_.end(); di != de; ++di)
2455  {
2456  // Check if we should process this directory. We process the
2457  // requested part of the object tree, including references.
2458  if (! path.empty()
2459  && ! isSubdirectory(path, *di))
2460  continue;
2461 
2462  // Loop over monitor elements in this directory.
2463  MonitorElement proto(&*di, std::string(), run, 0, 0);
2464  if (enableMultiThread_)
2465  proto.setLumi(lumi);
2466 
2467  mi = data_.lower_bound(proto);
2468  for ( ; mi != me && isSubdirectory(*di, *mi->data_.dirname); ++mi)
2469  {
2470  if (verbose_ > 1)
2471  std::cout << "Run: " << (*mi).run()
2472  << " Lumi: " << (*mi).lumi()
2473  << " LumiFlag: " << (*mi).getLumiFlag()
2474  << " streamId: " << (*mi).streamId()
2475  << " moduleId: " << (*mi).moduleId()
2476  << " fullpathname: " << (*mi).getFullname() << std::endl;
2477 
2478  // Upper bound in the loop over the MEs
2479  if (enableMultiThread_ && ((*mi).lumi() != lumi))
2480  break;
2481 
2482  // Skip if it isn't a direct child.
2483  if (*di != *mi->data_.dirname)
2484  continue;
2485 
2486  // Keep backward compatibility with the old way of
2487  // booking/handlind MonitorElements into the DQMStore. If run is
2488  // 0 it means that a booking happened w/ the old non-threadsafe
2489  // style, and we have to ignore the streamId and moduleId as a
2490  // consequence.
2491 
2492  if (run != 0 && (mi->data_.streamId !=0 || mi->data_.moduleId !=0))
2493  continue;
2494 
2495  if (verbose_ > 1)
2496  std::cout << "DQMStore::savePB: saving monitor element '"
2497  << *mi->data_.dirname << "/" << mi->data_.objname << "'"
2498  << "flags " << mi->data_.flags << "\n";
2499 
2500  nme++;
2501  dqmstorepb::ROOTFilePB::Histo* me = dqmstore_message.add_histo();
2502  me->set_full_pathname((*mi->data_.dirname) + '/' + mi->data_.objname);
2503  me->set_flags(mi->data_.flags);
2504 
2505  TObject *toWrite = nullptr;
2506  bool deleteObject = false;
2507 
2508  if (mi->kind() < MonitorElement::DQM_KIND_TH1F) {
2509  toWrite = new TObjString(mi->tagString().c_str());
2510  deleteObject = true;
2511  } else {
2512  toWrite = mi->object_;
2513  }
2514 
2515  TBufferFile buffer(TBufferFile::kWrite);
2516  buffer.WriteObject(toWrite);
2517  me->set_size(buffer.Length());
2518  me->set_streamed_histo((const void*)buffer.Buffer(),
2519  buffer.Length());
2520 
2521  if (deleteObject) {
2522  delete toWrite;
2523  }
2524 
2525  //reset the ME just written to make it available for the next LS (online)
2526  if (resetMEsAfterWriting)
2527  const_cast<MonitorElement*>(&*mi)->Reset();
2528  }
2529  }
2530 
2531  int filedescriptor = ::open(filename.c_str(),
2532  O_WRONLY | O_CREAT | O_TRUNC,
2533  S_IRUSR | S_IWUSR |
2534  S_IRGRP | S_IWGRP |
2535  S_IROTH);
2536  FileOutputStream file_stream(filedescriptor);
2538  options.format = GzipOutputStream::GZIP;
2539  options.compression_level = 6;
2540  GzipOutputStream gzip_stream(&file_stream,
2541  options);
2542  dqmstore_message.SerializeToZeroCopyStream(&gzip_stream);
2543 
2544  // we need to flush it before we close the fd
2545  gzip_stream.Close();
2546  file_stream.Close();
2547  ::close(filedescriptor);
2548 
2549  // Maybe make some noise.
2550  if (verbose_)
2551  std::cout << "DQMStore::savePB: successfully wrote " << nme
2552  << " objects from path '" << path
2553  << "' into DQM file '" << filename << "'\n";
2554 }
2555 
2556 
2561 void
2563  const std::string &path /* = "" */,
2564  const std::string &pattern /* = "" */,
2565  const std::string &rewrite /* = "" */,
2566  const uint32_t run /* = 0 */,
2567  const uint32_t lumi /* = 0 */,
2568  SaveReferenceTag ref /* = SaveWithReference */,
2569  int minStatus /* = dqm::qstatus::STATUS_OK */,
2570  const std::string &fileupdate /* = RECREATE */,
2571  const bool resetMEsAfterWriting /* = false */)
2572 {
2573  std::set<std::string>::iterator di, de;
2574  MEMap::iterator mi, me = data_.end();
2575  DQMNet::QReports::const_iterator qi, qe;
2576  int nme=0;
2577 
2578  // TFile flushes to disk with fsync() on every TDirectory written to
2579  // the file. This makes DQM file saving painfully slow, and
2580  // ironically makes it _more_ likely the file saving gets
2581  // interrupted and corrupts the file. The utility class below
2582  // simply ignores the flush synchronisation.
2583  class TFileNoSync : public TFile
2584  {
2585  public:
2586  TFileNoSync(const char *file, const char *opt) : TFile(file, opt) {}
2587  virtual Int_t SysSync(Int_t) override { return 0; }
2588  };
2589 
2590  // open output file, on 1st save recreate, later update
2591  if (verbose_)
2592  std::cout << "\n DQMStore: Opening TFile '" << filename
2593  << "' with option '" << fileupdate <<"'\n";
2594 
2595  TFileNoSync f(filename.c_str(), fileupdate.c_str()); // open file
2596  if(f.IsZombie())
2597  raiseDQMError("DQMStore", "Failed to create/update file '%s'", filename.c_str());
2598  f.cd();
2599 
2600  // Construct a regular expression from the pattern string.
2601  std::auto_ptr<lat::Regexp> rxpat;
2602  if (! pattern.empty())
2603  rxpat.reset(new lat::Regexp(pattern.c_str()));
2604 
2605  // Prepare a path for the reference object selection.
2606  std::string refpath;
2607  refpath.reserve(s_referenceDirName.size() + path.size() + 2);
2608  refpath += s_referenceDirName;
2609  if (! path.empty())
2610  {
2611  refpath += '/';
2612  refpath += path;
2613  }
2614 
2615  // Loop over the directory structure.
2616  for (di = dirs_.begin(), de = dirs_.end(); di != de; ++di)
2617  {
2618  // Check if we should process this directory. We process the
2619  // requested part of the object tree, including references.
2620  if (! path.empty()
2621  && ! isSubdirectory(path, *di)
2622  && ! isSubdirectory(refpath, *di))
2623  continue;
2624 
2625  // Loop over monitor elements in this directory.
2626  MonitorElement proto(&*di, std::string(), run, 0, 0);
2627  if (enableMultiThread_)
2628  proto.setLumi(lumi);
2629 
2630  mi = data_.lower_bound(proto);
2631  for ( ; mi != me && isSubdirectory(*di, *mi->data_.dirname); ++mi)
2632  {
2633  if (verbose_ > 1)
2634  std::cout << "DQMStore::save: Run: " << (*mi).run()
2635  << " Lumi: " << (*mi).lumi()
2636  << " LumiFlag: " << (*mi).getLumiFlag()
2637  << " streamId: " << (*mi).streamId()
2638  << " moduleId: " << (*mi).moduleId()
2639  << " fullpathname: " << (*mi).getFullname() << std::endl;
2640 
2641  // Upper bound in the loop over the MEs
2642  if (enableMultiThread_ && ((*mi).lumi() != lumi))
2643  break;
2644 
2645  // Skip if it isn't a direct child.
2646  if (*di != *mi->data_.dirname) {
2647  if (verbose_ > 1)
2648  std::cout << "DQMStore::save: isn't a direct child. Skipping" << std::endl;
2649  continue;
2650  }
2651 
2652  // Keep backward compatibility with the old way of
2653  // booking/handlind MonitorElements into the DQMStore. If run is
2654  // 0 it means that a booking happened w/ the old non-threadsafe
2655  // style, and we have to ignore the streamId and moduleId as a
2656  // consequence.
2657 
2658  if (run != 0 && (mi->data_.streamId !=0 || mi->data_.moduleId !=0)) {
2659  continue;
2660  }
2661 
2662  // Handle reference histograms, with three distinct cases:
2663  // 1) Skip all references entirely on saving.
2664  // 2) Blanket saving of all references.
2665  // 3) Save only references for monitor elements with qtests.
2666  // The latter two are affected by "path" sub-tree selection,
2667  // i.e. references are saved only in the selected tree part.
2668  if (isSubdirectory(refpath, *mi->data_.dirname))
2669  {
2670  if (ref == SaveWithoutReference)
2671  // Skip the reference entirely.
2672  continue;
2673  else if (ref == SaveWithReference)
2674  // Save all references regardless of qtests.
2675  ;
2676  else if (ref == SaveWithReferenceForQTest)
2677  {
2678  // Save only references for monitor elements with qtests
2679  // with an optional cut on minimum quality test result.
2680  int status = -1;
2681  std::string mname(mi->getFullname(), s_referenceDirName.size()+1, std::string::npos);
2682  MonitorElement *master = get(mname);
2683  if (master)
2684  for (size_t i = 0, e = master->data_.qreports.size(); i != e; ++i)
2685  status = std::max(status, master->data_.qreports[i].code);
2686 
2687  if (! master || status < minStatus)
2688  {
2689  if (verbose_ > 1)
2690  std::cout << "DQMStore::save: skipping monitor element '"
2691  << mi->data_.objname << "' while saving, status is "
2692  << status << ", required minimum status is "
2693  << minStatus << std::endl;
2694  continue;
2695  }
2696  }
2697  }
2698 
2699  if (verbose_ > 1)
2700  std::cout << "DQMStore::save: saving monitor element '"
2701  << mi->data_.objname << "'\n";
2702  nme++; // count saved histograms
2703 
2704  // Create the directory.
2705  gDirectory->cd("/");
2706  if (di->empty())
2708  else if (rxpat.get())
2709  cdInto(s_monitorDirName + '/' + lat::StringOps::replace(*di, *rxpat, rewrite));
2710  else
2711  cdInto(s_monitorDirName + '/' + *di);
2712 
2713  // Save the object.
2714  switch (mi->kind())
2715  {
2719  TObjString(mi->tagString().c_str()).Write();
2720  break;
2721 
2722  default:
2723  mi->object_->Write();
2724  break;
2725  }
2726 
2727  // Save quality reports if this is not in reference section.
2728  if (! isSubdirectory(s_referenceDirName, *mi->data_.dirname))
2729  {
2730  qi = mi->data_.qreports.begin();
2731  qe = mi->data_.qreports.end();
2732  for ( ; qi != qe; ++qi)
2733  TObjString(mi->qualityTagString(*qi).c_str()).Write();
2734  }
2735 
2736  // Save efficiency tag, if any
2737  if (mi->data_.flags & DQMNet::DQM_PROP_EFFICIENCY_PLOT)
2738  TObjString(mi->effLabelString().c_str()).Write();
2739 
2740  // Save tag if any
2741  if (mi->data_.flags & DQMNet::DQM_PROP_TAGGED)
2742  TObjString(mi->tagLabelString().c_str()).Write();
2743 
2744  //reset the ME just written to make it available for the next LS (online)
2745  if (resetMEsAfterWriting)
2746  const_cast<MonitorElement*>(&*mi)->Reset();
2747  }
2748  }
2749 
2750  f.Close();
2751 
2752  // Maybe make some noise.
2753  if (verbose_)
2754  std::cout << "DQMStore::save: successfully wrote " << nme
2755  << " objects from path '" << path
2756  << "' into DQM file '" << filename << "'\n";
2757 }
2758 
2761 unsigned int
2763  bool overwrite,
2764  const std::string &onlypath,
2765  const std::string &prepend,
2766  const std::string &curdir,
2767  OpenRunDirs stripdirs)
2768 {
2769  unsigned int ntot = 0;
2770  unsigned int count = 0;
2771 
2772  if (! file->cd(curdir.c_str()))
2773  raiseDQMError("DQMStore", "Failed to process directory '%s' while"
2774  " reading file '%s'", curdir.c_str(), file->GetName());
2775 
2776  // Figure out current directory name, but strip out the top
2777  // directory into which we dump everything.
2778  std::string dirpart = curdir;
2779  if (dirpart.compare(0, s_monitorDirName.size(), s_monitorDirName) == 0)
2780  {
2781  if (dirpart.size() == s_monitorDirName.size())
2782  dirpart.clear();
2783  else if (dirpart[s_monitorDirName.size()] == '/')
2784  dirpart.erase(0, s_monitorDirName.size()+1);
2785  }
2786 
2787  // See if we are going to skip this directory.
2788  bool skip = (! onlypath.empty() && ! isSubdirectory(onlypath, dirpart));
2789 
2790  if (prepend == s_collateDirName ||
2791  prepend == s_referenceDirName ||
2792  stripdirs == StripRunDirs )
2793  {
2794  // Remove Run # and RunSummary dirs
2795  // first look for Run summary,
2796  // if that is found and erased, also erase Run dir
2797  size_t slash = dirpart.find('/');
2798  size_t pos = dirpart.find("/Run summary");
2799  if (slash != std::string::npos && pos !=std::string::npos)
2800  {
2801  dirpart.erase(pos,12);
2802 
2803  pos = dirpart.find("Run ");
2804  size_t length = dirpart.find('/',pos+1)-pos+1;
2805  if (pos !=std::string::npos)
2806  dirpart.erase(pos,length);
2807  }
2808  }
2809 
2810  // If we are prepending, add it to the directory name,
2811  // and suppress reading of already existing reference histograms
2812  if (prepend == s_collateDirName ||
2813  prepend == s_referenceDirName)
2814  {
2815  size_t slash = dirpart.find('/');
2816  // If we are reading reference, skip previous reference.
2817  if (slash == std::string::npos // skip if Reference is toplevel folder, i.e. no slash
2818  && slash+1+s_referenceDirName.size() == dirpart.size()
2819  && dirpart.compare(slash+1, s_referenceDirName.size(), s_referenceDirName) == 0)
2820  return 0;
2821 
2822  slash = dirpart.find('/');
2823  // Skip reading of EventInfo subdirectory.
2824  if (slash != std::string::npos
2825  && slash + 10 == dirpart.size()
2826  && dirpart.compare( slash+1 , 9 , "EventInfo") == 0) {
2827  if (verbose_)
2828  std::cout << "DQMStore::readDirectory: skipping '" << dirpart << "'\n";
2829  return 0;
2830  }
2831 
2832  // Add prefix.
2833  if (dirpart.empty())
2834  dirpart = prepend;
2835  else
2836  dirpart = prepend + '/' + dirpart;
2837  }
2838  else if (! prepend.empty())
2839  {
2840  if (dirpart.empty())
2841  dirpart = prepend;
2842  else
2843  dirpart = prepend + '/' + dirpart;
2844  }
2845 
2846  // Loop over the contents of this directory in the file.
2847  // Post-pone string object handling to happen after other
2848  // objects have been read in so we are guaranteed to have
2849  // histograms by the time we read in quality tests and tags.
2850  TKey *key;
2851  TIter next (gDirectory->GetListOfKeys());
2852  std::list<TObject *> delayed;
2853  while ((key = (TKey *) next()))
2854  {
2855  std::auto_ptr<TObject> obj(key->ReadObj());
2856  if (dynamic_cast<TDirectory *>(obj.get()))
2857  {
2858  std::string subdir;
2859  subdir.reserve(curdir.size() + strlen(obj->GetName()) + 2);
2860  subdir += curdir;
2861  if (! curdir.empty())
2862  subdir += '/';
2863  subdir += obj->GetName();
2864 
2865  ntot += readDirectory(file, overwrite, onlypath, prepend, subdir, stripdirs);
2866  }
2867  else if (skip)
2868  ;
2869  else if (dynamic_cast<TObjString *>(obj.get()))
2870  {
2871  delayed.push_back(obj.release());
2872  }
2873  else
2874  {
2875  if (verbose_ > 2)
2876  std::cout << "DQMStore: reading object '" << obj->GetName()
2877  << "' of type '" << obj->IsA()->GetName()
2878  << "' from '" << file->GetName()
2879  << "' into '" << dirpart << "'\n";
2880 
2881  makeDirectory(dirpart);
2882  if (extract(obj.get(), dirpart, overwrite, collateHistograms_))
2883  ++count;
2884  }
2885  }
2886 
2887  while (! delayed.empty())
2888  {
2889  if (verbose_ > 2)
2890  std::cout << "DQMStore: reading object '" << delayed.front()->GetName()
2891  << "' of type '" << delayed.front()->IsA()->GetName()
2892  << "' from '" << file->GetName()
2893  << "' into '" << dirpart << "'\n";
2894 
2895  makeDirectory(dirpart);
2896  if (extract(delayed.front(), dirpart, overwrite, collateHistograms_))
2897  ++count;
2898 
2899  delete delayed.front();
2900  delayed.pop_front();
2901  }
2902 
2903  if (verbose_ > 1)
2904  std::cout << "DQMStore: read " << count << '/' << ntot
2905  << " objects from directory '" << dirpart << "'\n";
2906 
2907  return ntot + count;
2908 }
2909 
2916 bool
2918  bool overwrite /* = false */,
2919  const std::string &onlypath /* ="" */,
2920  const std::string &prepend /* ="" */,
2921  OpenRunDirs stripdirs /* =KeepRunDirs */,
2922  bool fileMustExist /* =true */)
2923 {
2924  return readFile(filename,overwrite,onlypath,prepend,stripdirs,fileMustExist);
2925 }
2926 
2931 bool
2933  OpenRunDirs stripdirs /* =StripRunDirs */,
2934  bool fileMustExist /* =true */)
2935 {
2936  bool overwrite = true;
2937  if (collateHistograms_) overwrite = false;
2938  if (verbose_)
2939  {
2940  std::cout << "DQMStore::load: reading from file '" << filename << "'\n";
2941  if (collateHistograms_)
2942  std::cout << "DQMStore::load: in collate mode " << "\n";
2943  else
2944  std::cout << "DQMStore::load: in overwrite mode " << "\n";
2945  }
2946 
2947  if (!s_rxpbfile.match(filename, 0, 0))
2948  return readFile(filename, overwrite, "", "", stripdirs, fileMustExist);
2949  else
2950  return readFilePB(filename, overwrite, "", "", stripdirs, fileMustExist);
2951 }
2952 
2958 bool
2960  bool overwrite /* = false */,
2961  const std::string &onlypath /* ="" */,
2962  const std::string &prepend /* ="" */,
2963  OpenRunDirs stripdirs /* =StripRunDirs */,
2964  bool fileMustExist /* =true */)
2965 {
2966 
2967  if (verbose_)
2968  std::cout << "DQMStore::readFile: reading from file '" << filename << "'\n";
2969 
2970  std::auto_ptr<TFile> f;
2971 
2972  try
2973  {
2974  f.reset(TFile::Open(filename.c_str()));
2975  if (! f.get() || f->IsZombie())
2976  raiseDQMError("DQMStore", "Failed to open file '%s'", filename.c_str());
2977  }
2978  catch (std::exception &)
2979  {
2980  if (fileMustExist)
2981  throw;
2982  else
2983  {
2984  if (verbose_)
2985  std::cout << "DQMStore::readFile: file '" << filename << "' does not exist, continuing\n";
2986  return false;
2987  }
2988  }
2989 
2990  unsigned n = readDirectory(f.get(), overwrite, onlypath, prepend, "", stripdirs);
2991  f->Close();
2992 
2993  MEMap::iterator mi = data_.begin();
2994  MEMap::iterator me = data_.end();
2995  for ( ; mi != me; ++mi)
2996  const_cast<MonitorElement &>(*mi).updateQReportStats();
2997 
2998  if (verbose_)
2999  {
3000  std::cout << "DQMStore::open: successfully read " << n
3001  << " objects from file '" << filename << "'";
3002  if (! onlypath.empty())
3003  std::cout << " from directory '" << onlypath << "'";
3004  if (! prepend.empty())
3005  std::cout << " into directory '" << prepend << "'";
3006  std::cout << std::endl;
3007  }
3008  return true;
3009 }
3010 
3014 inline TObject * DQMStore::extractNextObject(TBufferFile &buf) const {
3015  if (buf.Length() == buf.BufferSize())
3016  return 0;
3017  buf.InitMap();
3018  void *ptr = buf.ReadObjectAny(0);
3019  return reinterpret_cast<TObject *>(ptr);
3020 }
3021 
3023  std::string &dirname,
3024  std::string &objname,
3025  TObject ** obj) {
3026 
3027  size_t slash = h.full_pathname().rfind('/');
3028  size_t dirpos = (slash == std::string::npos ? 0 : slash);
3029  size_t namepos = (slash == std::string::npos ? 0 : slash+1);
3030  dirname.assign(h.full_pathname(), 0, dirpos);
3031  objname.assign(h.full_pathname(), namepos, std::string::npos);
3032  TBufferFile buf(TBufferFile::kRead, h.size(),
3033  (void*)h.streamed_histo().data(),
3034  kFALSE);
3035  buf.Reset();
3036  *obj = extractNextObject(buf);
3037  if (!*obj) {
3038  raiseDQMError("DQMStore", "Error reading element:'%s'" , h.full_pathname().c_str());
3039  }
3040 }
3041 
3042 bool
3044  bool overwrite /* = false */,
3045  const std::string &onlypath /* ="" */,
3046  const std::string &prepend /* ="" */,
3047  OpenRunDirs stripdirs /* =StripRunDirs */,
3048  bool fileMustExist /* =true */)
3049 {
3050  using google::protobuf::io::FileInputStream;
3051  using google::protobuf::io::FileOutputStream;
3052  using google::protobuf::io::GzipInputStream;
3053  using google::protobuf::io::GzipOutputStream;
3054  using google::protobuf::io::CodedInputStream;
3055  using google::protobuf::io::ArrayInputStream;
3056 
3057  if (verbose_)
3058  std::cout << "DQMStore::readFile: reading from file '" << filename << "'\n";
3059 
3060  int filedescriptor;
3061  if ((filedescriptor = ::open(filename.c_str(), O_RDONLY)) == -1) {
3062  if (fileMustExist)
3063  raiseDQMError("DQMStore", "Failed to open file '%s'", filename.c_str());
3064  else
3065  if (verbose_)
3066  std::cout << "DQMStore::readFile: file '" << filename << "' does not exist, continuing\n";
3067  return false;
3068  }
3069 
3070  dqmstorepb::ROOTFilePB dqmstore_message;
3071  FileInputStream fin(filedescriptor);
3072  GzipInputStream input(&fin);
3073  CodedInputStream input_coded(&input);
3074  input_coded.SetTotalBytesLimit(1024*1024*1024, -1);
3075  if (!dqmstore_message.ParseFromCodedStream(&input_coded)) {
3076  raiseDQMError("DQMStore", "Fatal parsing file '%s'", filename.c_str());
3077  return false;
3078  }
3079  ::close(filedescriptor);
3080 
3081  for (int i = 0; i < dqmstore_message.histo_size(); i++) {
3082  std::string path;
3083  std::string objname;
3084 
3085  TObject *obj = NULL;
3086  const dqmstorepb::ROOTFilePB::Histo &h = dqmstore_message.histo(i);
3087  get_info(h, path, objname, &obj);
3088 
3089  setCurrentFolder(path);
3090  if (obj)
3091  {
3092  /* Before calling the extract() check if histogram exists:
3093  * if it does - flags for the given monitor are already set (and merged)
3094  * else - set the flags after the histogram is created.
3095  */
3096  MonitorElement *me = findObject(path, objname);
3097 
3098  /* Run histograms should be collated and not overwritten,
3099  * Lumi histograms should be overwritten (and collate flag is not checked)
3100  */
3101  bool overwrite = h.flags() & DQMNet::DQM_PROP_LUMI;
3102  bool collate = !(h.flags() & DQMNet::DQM_PROP_LUMI);
3103  extract(static_cast<TObject *>(obj), path, overwrite, collate);
3104 
3105  if (me == nullptr) {
3106  me = findObject(path, objname);
3107  me->data_.flags = h.flags();
3108  }
3109 
3110  delete obj;
3111  }
3112  }
3113 
3114  cd();
3115  return true;
3116 }
3117 
3123 void
3125 {
3127  const std::string *cleaned = 0;
3128  cleanTrailingSlashes(path, clean, cleaned);
3129  MonitorElement proto(cleaned, std::string());
3130 
3131  MEMap::iterator e = data_.end();
3132  MEMap::iterator i = data_.lower_bound(proto);
3133  while (i != e && isSubdirectory(*cleaned, *i->data_.dirname))
3134  data_.erase(i++);
3135 
3136  std::set<std::string>::iterator de = dirs_.end();
3137  std::set<std::string>::iterator di = dirs_.lower_bound(*cleaned);
3138  while (di != de && isSubdirectory(*cleaned, *di))
3139  dirs_.erase(di++);
3140 }
3141 
3143 void
3145 {
3146  MonitorElement proto(&dir, std::string());
3147  MEMap::iterator e = data_.end();
3148  MEMap::iterator i = data_.lower_bound(proto);
3149  while (i != e && isSubdirectory(dir, *i->data_.dirname))
3150  if (dir == *i->data_.dirname)
3151  data_.erase(i++);
3152  else
3153  ++i;
3154 }
3155 
3157 void
3159 {
3161 }
3162 
3165 void
3167 {
3168  removeElement(pwd_, name);
3169 }
3170 
3173 void
3174 DQMStore::removeElement(const std::string &dir, const std::string &name, bool warning /* = true */)
3175 {
3176  MonitorElement proto(&dir, name);
3177  MEMap::iterator pos = data_.find(proto);
3178  if (pos == data_.end() && warning)
3179  std::cout << "DQMStore: WARNING: attempt to remove non-existent"
3180  << " monitor element '" << name << "' in '" << dir << "'\n";
3181  else
3182  data_.erase(pos);
3183 }
3184 
3190 QCriterion *
3192 {
3193  QCMap::const_iterator i = qtests_.find(qtname);
3194  QCMap::const_iterator e = qtests_.end();
3195  return (i == e ? 0 : i->second);
3196 }
3197 
3201 QCriterion *
3202 DQMStore::createQTest(const std::string &algoname, const std::string &qtname)
3203 {
3204  if (qtests_.count(qtname))
3205  raiseDQMError("DQMStore", "Attempt to create duplicate quality test '%s'",
3206  qtname.c_str());
3207 
3208  QAMap::iterator i = qalgos_.find(algoname);
3209  if (i == qalgos_.end())
3210  raiseDQMError("DQMStore", "Cannot create a quality test using unknown"
3211  " algorithm '%s'", algoname.c_str());
3212 
3213  QCriterion *qc = i->second(qtname);
3214  qc->setVerbose(verboseQT_);
3215 
3216  qtests_[qtname] = qc;
3217  return qc;
3218 }
3219 
3222 void
3224 {
3225  // Clean the path
3227  const std::string *cleaned = 0;
3228  cleanTrailingSlashes(dir, clean, cleaned);
3229 
3230  // Validate the path.
3231  if (cleaned->find_first_not_of(s_safe) != std::string::npos)
3232  raiseDQMError("DQMStore", "Monitor element path name '%s'"
3233  " uses unacceptable characters", cleaned->c_str());
3234 
3235  // Redirect to the pattern match version.
3236  useQTestByMatch(*cleaned + "/*", qtname);
3237 }
3238 
3240 int
3242 {
3243  QCriterion *qc = getQCriterion(qtname);
3244  if (! qc)
3245  raiseDQMError("DQMStore", "Cannot apply non-existent quality test '%s'",
3246  qtname.c_str());
3247 
3248  fastmatch * fm = new fastmatch( pattern );
3249 
3250  // Record the test for future reference.
3251  QTestSpec qts(fm, qc);
3252  qtestspecs_.push_back(qts);
3253 
3254  // Apply the quality test.
3255  MEMap::iterator mi = data_.begin();
3256  MEMap::iterator me = data_.end();
3257  std::string path;
3258  int cases = 0;
3259  for ( ; mi != me; ++mi)
3260  {
3261  path.clear();
3262  mergePath(path, *mi->data_.dirname, mi->data_.objname);
3263  if (fm->match(path))
3264  {
3265  ++cases;
3266  const_cast<MonitorElement &>(*mi).addQReport(qts.second);
3267  }
3268  }
3269 
3270  //return the number of matched cases
3271  return cases;
3272 }
3275 void
3277 {
3278 
3279  if (verbose_ > 0)
3280  std::cout << "DQMStore: running runQTests() with reset = "
3281  << ( reset_ ? "true" : "false" ) << std::endl;
3282 
3283  // Apply quality tests to each monitor element, skipping references.
3284  MEMap::iterator mi = data_.begin();
3285  MEMap::iterator me = data_.end();
3286  for ( ; mi != me; ++mi)
3287  if (! isSubdirectory(s_referenceDirName, *mi->data_.dirname))
3288  const_cast<MonitorElement &>(*mi).runQTests();
3289 
3290  reset_ = false;
3291 }
3292 
3296 int
3297 DQMStore::getStatus(const std::string &path /* = "" */) const
3298 {
3300  const std::string *cleaned = 0;
3301  cleanTrailingSlashes(path, clean, cleaned);
3302 
3304  MEMap::const_iterator mi = data_.begin();
3305  MEMap::const_iterator me = data_.end();
3306  for ( ; mi != me; ++mi)
3307  {
3308  if (! cleaned->empty() && ! isSubdirectory(*cleaned, *mi->data_.dirname))
3309  continue;
3310 
3311  if (mi->hasError())
3312  return dqm::qstatus::ERROR;
3313  else if (mi->hasWarning())
3314  status = dqm::qstatus::WARNING;
3315  else if (status < dqm::qstatus::WARNING
3316  && mi->hasOtherReport())
3317  status = dqm::qstatus::OTHER;
3318  }
3319  return status;
3320 }
3321 
3327 void
3329 {
3330  if (me)
3331  me->softReset();
3332 }
3333 
3334 // reverts action of softReset
3335 void
3337 {
3338  if (me)
3339  me->disableSoftReset();
3340 }
3341 
3344 void
3346 {
3347  if (me)
3348  me->setAccumulate(flag);
3349 }
3350 
3354 void
3356 {
3357  std::vector<std::string> contents;
3358  getContents(contents);
3359 
3360  std::cout << " ------------------------------------------------------------\n"
3361  << " Directory structure: \n"
3362  << " ------------------------------------------------------------\n";
3363 
3364  std::copy(contents.begin(), contents.end(),
3365  std::ostream_iterator<std::string>(std::cout, "\n"));
3366 
3367  std::cout << " ------------------------------------------------------------\n";
3368 }
3369 
3373 // check if the collate option is active on the DQMStore
3374 bool
3376 {
3377  return collateHistograms_;
3378 }
3382 // check if the monitor element is in auto-collation folder
3383 bool
3385 { return me && isSubdirectory(s_collateDirName, *me->data_.dirname); }
3389 
3391 void
3393 {
3394  if (scaleFlag_ == 0.0) return;
3395  if (verbose_ > 0)
3396  std::cout << " =========== " << " ScaleFlag " << scaleFlag_ << std::endl;
3397  double factor = scaleFlag_;
3398  int events = 1;
3399  if (dirExists("Info/EventInfo")) {
3400  if ( scaleFlag_ == -1.0) {
3401  MonitorElement * scale_me = get("Info/EventInfo/ScaleFactor");
3402  if (scale_me && scale_me->kind()==MonitorElement::DQM_KIND_REAL) factor = scale_me->getFloatValue();
3403  }
3404  MonitorElement * event_me = get("Info/EventInfo/processedEvents");
3405  if (event_me && event_me->kind()==MonitorElement::DQM_KIND_INT) events = event_me->getIntValue();
3406  }
3407  factor = factor/(events*1.0);
3408 
3409  MEMap::iterator mi = data_.begin();
3410  MEMap::iterator me = data_.end();
3411  for ( ; mi != me; ++mi)
3412  {
3413  MonitorElement &me = const_cast<MonitorElement &>(*mi);
3414  switch (me.kind())
3415  {
3417  {
3418  me.getTH1F()->Scale(factor);
3419  break;
3420  }
3422  {
3423  me.getTH1S()->Scale(factor);
3424  break;
3425  }
3427  {
3428  me.getTH1D()->Scale(factor);
3429  break;
3430  }
3432  {
3433  me.getTH2F()->Scale(factor);
3434  break;
3435  }
3437  {
3438  me.getTH2S()->Scale(factor);
3439  break;
3440  }
3442  {
3443  me.getTH2D()->Scale(factor);
3444  break;
3445  }
3447  {
3448  me.getTH3F()->Scale(factor);
3449  break;
3450  }
3452  {
3453  me.getTProfile()->Scale(factor);
3454  break;
3455  }
3457  {
3458  me.getTProfile2D()->Scale(factor);
3459  break;
3460  }
3461  default:
3462  if (verbose_ > 0)
3463  std::cout << " The DQM object '" << me.getFullname() << "' is not scalable object " << std::endl;
3464  continue;
3465  }
3466  }
3467 }
QCriterion * getQCriterion(const std::string &qtname) const
Definition: DQMStore.cc:3191
IGetter * igetter_
Definition: DQMStore.h:717
bool compare_strings_reverse(std::string const &pattern, std::string const &input) const
Definition: DQMStore.cc:205
std::pair< fastmatch *, QCriterion * > QTestSpec
Definition: DQMStore.h:687
TH2S * getTH2S(void) const
TH1S * getTH1S(void) const
T getUntrackedParameter(std::string const &, T const &) const
int i
Definition: DBlmapReader.cc:9
DQMStore(const edm::ParameterSet &pset, edm::ActivityRegistry &)
Definition: DQMStore.cc:460
static const lat::Regexp s_rxmeqr2("^st\\.(\\d+)\\.(.*)$")
MonitorElement * book2S(const char *name, const char *title, int nchX, double lowX, double highX, int nchY, double lowY, double highY)
Book 2S histogram.
Definition: DQMStore.cc:1121
bool containsAnyMonitorable(const std::string &path) const
Definition: DQMStore.cc:1715
uint32_t moduleId
Definition: DQMNet.h:104
inline::google::protobuf::uint32 size() const
bool isCollateME(MonitorElement *me) const
Definition: DQMStore.cc:3384
void resetUpdate(void)
reset &quot;was updated&quot; flag
tuple start
Check for commandline option errors.
Definition: dqm_diff.py:58
bool cdInto(const std::string &path) const
Definition: DQMStore.cc:2392
const ::std::string & full_pathname() const
void cd(void)
Definition: DQMStore.cc:318
int getStatus(const std::string &path="") const
Definition: DQMStore.cc:3297
void copyFrom(TH1 *from)
MonitorElement * initialise(Kind kind)
static const int OTHER
static void mergePath(std::string &path, const std::string &dir, const std::string &name)
Definition: DQMStore.cc:108
std::string algorithm
Definition: DQMNet.h:93
std::vector< std::string > getSubdirs(void) const
Definition: DQMStore.cc:1676
TProfile2D * getTProfile2D(void) const
MonitorElement * book1D(const char *name, const char *title, int nchX, double lowX, double highX)
Book 1D histogram.
Definition: DQMStore.cc:971
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventIDconst &, edm::Timestampconst & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
void rmdir(const std::string &fullpath)
Definition: DQMStore.cc:3124
static void collate3D(MonitorElement *me, TH3F *h, unsigned verbose)
Definition: DQMStore.cc:1580
bool match(std::string const &s) const
Definition: DQMStore.cc:247
bool readFile(const std::string &filename, bool overwrite=false, const std::string &path="", const std::string &prepend="", OpenRunDirs stripdirs=StripRunDirs, bool fileMustExist=true)
Definition: DQMStore.cc:2959
MonitorElement * findObject(const std::string &dir, const std::string &name, const uint32_t run=0, const uint32_t lumi=0, const uint32_t streamId=0, const uint32_t moduleId=0) const
Definition: DQMStore.cc:1855
static void collateProfile(MonitorElement *me, TProfile *h, unsigned verbose)
Definition: DQMStore.cc:1587
MonitorElement * book3D(const char *name, const char *title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, int nchZ, double lowZ, double highZ)
Book 3D histogram.
Definition: DQMStore.cc:1233
void setLumi(uint32_t ls)
void cd(void)
Definition: DQMStore.cc:266
void cd(void)
go to top directory (ie. root)
Definition: DQMStore.cc:661
MonitorElement * get(const std::string &path)
Definition: DQMStore.cc:298
MonitorElement * book2DD(const char *name, const char *title, int nchX, double lowX, double highX, int nchY, double lowY, double highY)
Book 2D double histogram.
Definition: DQMStore.cc:1143
uint32_t streamId_
Definition: DQMStore.h:703
tuple lumi
Definition: fjr2json.py:35
void markForDeletion(uint32_t run, uint32_t lumi)
Definition: DQMStore.cc:2057
static const std::string s_safe
Definition: DQMStore.cc:56
static void splitPath(std::string &dir, std::string &name, const std::string &path)
Definition: DQMStore.cc:95
uint32_t flags
Definition: DQMNet.h:98
const std::string & pwd(void)
Definition: DQMStore.cc:282
void disableSoftReset(void)
reverts action of softReset
static void collate2DD(MonitorElement *me, TH2D *h, unsigned verbose)
Definition: DQMStore.cc:1573
std::vector< MonitorElement * > getMatchingContents(const std::string &pattern, lat::Regexp::Syntax syntaxType=lat::Regexp::Wildcard) const
Definition: DQMStore.cc:1976
static const int WARNING
TH3F * getTH3F(void) const
static const uint32_t DQM_PROP_TAGGED
Definition: DQMNet.h:54
TH1D * getTH1D(void) const
MatchingHeuristicEnum matching_
Definition: DQMStore.h:72
void runQTests(void)
run all quality tests
#define NULL
Definition: scimark2.h:8
static const uint32_t DQM_PROP_EFFICIENCY_PLOT
Definition: DQMNet.h:63
list pattern
Definition: chain.py:104
void softReset(void)
TH2D * getTH2D(void) const
uint32_t tag
Definition: DQMNet.h:99
bool reset_
Definition: DQMStore.h:695
const std::string * dirname
Definition: DQMNet.h:105
MonitorElement * book1DD(const char *name, const char *title, int nchX, double lowX, double highX)
Book 1S histogram.
Definition: DQMStore.cc:1003
void initializeFrom(const edm::ParameterSet &)
Definition: DQMStore.cc:532
#define nullptr
OpenRunDirs
Definition: DQMStore.h:84
void set_flags(::google::protobuf::uint32 value)
uint32_t run
Definition: DQMNet.h:101
uint32_t moduleId_
Definition: DQMStore.h:704
const ::std::string & streamed_histo() const
void initQCriterion(std::map< std::string, QCriterion *(*)(const std::string &)> &m)
Definition: DQMStore.cc:124
QCMap qtests_
Definition: DQMStore.h:711
static const std::string s_collateDirName
Definition: DQMStore.cc:55
MonitorElement * book(const std::string &dir, const std::string &name, const char *context)
Definition: DQMStore.cc:826
static const std::string s_monitorDirName
name of global monitoring folder (containing all sources subdirectories)
Definition: DQMStore.cc:53
std::mutex book_mutex_
Definition: DQMStore.h:715
MonitorElement * bookFloat(const char *name)
Book float.
Definition: DQMStore.cc:908
static std::string const input
Definition: EdmProvDump.cc:44
SaveReferenceTag
Definition: DQMStore.h:78
static const lat::Regexp s_rxtrace("(.*)\\((.*)\\+0x.*\\).*")
void Fill(long long x)
static void cleanTrailingSlashes(const std::string &path, std::string &clean, const std::string *&cleaned)
Definition: DQMStore.cc:78
Preallocate preallocateSignal_
signal is emitted before beginJob
void tag(MonitorElement *me, unsigned int myTag)
Definition: DQMStore.cc:1611
~DQMStore(void)
Definition: DQMStore.cc:518
void disableSoftReset(MonitorElement *me)
Definition: DQMStore.cc:3336
unsigned int maxNumberOfStreams() const
Definition: SystemBounds.h:43
static const lat::Regexp s_rxmeval("^<(.*)>(i|f|s|e|t|qr)=(.*)</\\1>$")
void forceReset(void)
Definition: DQMStore.cc:2036
static bool isSubdirectory(const std::string &ofdir, const std::string &path)
Definition: DQMStore.cc:68
std::vector< MonitorElement * > getAllContents(const std::string &path, uint32_t runNumber=0, uint32_t lumi=0) const
Definition: DQMStore.cc:1938
fastmatch(std::string const &_fastString)
Definition: DQMStore.cc:129
unsigned verboseQT_
Definition: DQMStore.h:694
static const uint32_t DQM_PROP_HAS_REFERENCE
Definition: DQMNet.h:53
void removeContents(void)
erase all monitoring elements in current directory (not including subfolders);
Definition: DQMStore.cc:3158
QTestSpecs qtestspecs_
Definition: DQMStore.h:713
tuple path
else: Piece not in the list, fine.
double scaleFlag_
Definition: DQMStore.h:696
void get_info(const dqmstorepb::ROOTFilePB_Histo &, std::string &dirname, std::string &objname, TObject **obj)
Definition: DQMStore.cc:3022
void watchPostSourceRun(PostSourceRun::slot_type const &iSlot)
MonitorElement * bookString(const char *name, const char *value)
Book string.
Definition: DQMStore.cc:937
void setAccumulate(bool)
uint32_t lumi
Definition: DQMNet.h:102
bool isCollate(void) const
Definition: DQMStore.cc:3375
tuple result
Definition: query.py:137
void removeElement(const std::string &name)
Definition: DQMStore.cc:3166
void addProfiles(TProfile *h1, TProfile *h2, TProfile *sum, float c1, float c2)
static void collateProfile2D(MonitorElement *me, TProfile2D *h, unsigned verbose)
Definition: DQMStore.cc:1597
double getFloatValue(void) const
void tag(MonitorElement *, unsigned int)
Definition: DQMStore.cc:286
TH1 * getTH1(void) const
double f[11][100]
uint32_t run_
Definition: DQMStore.h:702
The Signals That Services Can Subscribe To This is based on ActivityRegistry h
Helper function to determine trigger accepts.
Definition: Activities.doc:4
MonitorElement * bookProfile(const char *name, const char *title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, const char *option="s")
Definition: DQMStore.cc:1285
QCriterion * makeQCriterion(const std::string &qtname)
Definition: DQMStore.cc:119
#define end
Definition: vmac.h:37
void setVerbose(unsigned level)
Definition: DQMStore.cc:648
void softReset(MonitorElement *me)
Definition: DQMStore.cc:3328
std::string pwd_
Definition: DQMStore.h:707
Kind kind(void) const
Get the type of the monitor element.
void runQTests(void)
Definition: DQMStore.cc:3276
TObject * extractNextObject(TBufferFile &) const
Definition: DQMStore.cc:3014
lat::Regexp * regexp_
Definition: DQMStore.h:70
IBooker * ibooker_
Definition: DQMStore.h:716
MonitorElement * get(const std::string &path) const
get ME from full pathname (e.g. &quot;my/long/dir/my_histo&quot;)
Definition: DQMStore.cc:1725
QAMap qalgos_
Definition: DQMStore.h:712
const std::string getFullname(void) const
get full name of ME including Pathname
std::vector< MonitorElement * > getContents(const std::string &path) const
Definition: DQMStore.cc:1754
std::string readSelectedDirectory_
Definition: DQMStore.h:701
std::vector< std::string > getMEs(void)
Definition: DQMStore.cc:306
std::string objname
Definition: DQMNet.h:106
void mergeAndResetMEsRunSummaryCache(uint32_t run, uint32_t streamId, uint32_t moduleId)
Definition: DQMStore.cc:339
std::string fastString_
Definition: DQMStore.h:71
std::vector< T * > clean
Definition: MVATrainer.cc:156
std::string qtname
Definition: DQMNet.h:92
DQMNet::CoreObject data_
bool dirExists(const std::string &path) const
true if directory exists
Definition: DQMStore.cc:749
void savePB(const std::string &filename, const std::string &path="", const uint32_t run=0, const uint32_t lumi=0, const bool resetMEsAfterWriting=false)
Definition: DQMStore.cc:2434
void getAllTags(std::vector< std::string > &into) const
Definition: DQMStore.cc:1885
bool dirExists(const std::string &path)
Definition: DQMStore.cc:314
bool load(const std::string &filename, OpenRunDirs stripdirs=StripRunDirs, bool fileMustExist=true)
Definition: DQMStore.cc:2932
void scaleElements(void)
Definition: DQMStore.cc:3392
~fastmatch()
Definition: DQMStore.cc:199
static void collate1DD(MonitorElement *me, TH1D *h, unsigned verbose)
Definition: DQMStore.cc:1552
void tagAllContents(const std::string &path, unsigned int myTag)
Definition: DQMStore.cc:1654
void setCurrentFolder(const std::string &fullpath)
Definition: DQMStore.cc:274
MonitorElement * initialise(MonitorElement *me, const std::string &path)
void watchPostSourceLumi(PostSourceLumi::slot_type const &iSlot)
void goUp(void)
Definition: DQMStore.cc:278
bool containsAnyMonitorable(const std::string &path)
Definition: DQMStore.cc:310
const ::dqmstorepb::ROOTFilePB_Histo & histo(int index) const
unsigned verbose_
Definition: DQMStore.h:693
void set_size(::google::protobuf::uint32 value)
MEMap data_
Definition: DQMStore.h:708
part
Definition: HCALResponse.h:20
int64_t getIntValue(void) const
static const std::string s_referenceDirName
Definition: DQMStore.cc:54
void print_trace(const std::string &dir, const std::string &name)
Definition: DQMStore.cc:592
int useQTestByMatch(const std::string &pattern, const std::string &qtname)
attach quality test &lt;qc&gt; to monitor elements matching &lt;pattern&gt;.
Definition: DQMStore.cc:3241
std::vector< MonitorElement * > getAllContents(const std::string &path, uint32_t runNumber=0, uint32_t lumi=0)
Definition: DQMStore.cc:292
TH1F * getTH1F(void) const
static void collate1D(MonitorElement *me, TH1F *h, unsigned verbose)
Definition: DQMStore.cc:1538
static const lat::Regexp s_rxpbfile(".*\\.pb$")
std::vector< std::string > getMEs(void) const
get list of (non-dir) MEs of current directory
Definition: DQMStore.cc:1699
std::vector< std::string > getSubdirs(void)
Definition: DQMStore.cc:302
DQMStore * owner_
Definition: DQMStore.h:186
void setCurrentFolder(const std::string &fullpath)
Definition: DQMStore.cc:326
bool resetMe(void) const
true if ME should be reset at end of monitoring cycle
void set_full_pathname(const ::std::string &value)
unsigned int readDirectory(TFile *file, bool overwrite, const std::string &path, const std::string &prepend, const std::string &curdir, OpenRunDirs stripdirs)
Definition: DQMStore.cc:2762
void setVerbose(int verbose)
probability limits for warnings, errors
Definition: QTest.h:116
bool extract(TObject *obj, const std::string &dir, bool overwrite, bool collateHistograms)
Definition: DQMStore.cc:2096
bool forceResetOnBeginLumi_
Definition: DQMStore.h:700
T dot(const Basic3DVector &v) const
Scalar product, or &quot;dot&quot; product, with a vector of same type.
std::vector< boost::shared_ptr< fireworks::OptionNode > > Options
void tagContents(const std::string &path, unsigned int myTag)
tag all children of folder (does NOT include subfolders)
Definition: DQMStore.cc:1642
list key
Definition: combine.py:13
tuple events
Definition: patZpeak.py:19
inline::dqmstorepb::ROOTFilePB_Histo * add_histo()
void save(const std::string &filename, const std::string &path="", const std::string &pattern="", const std::string &rewrite="", const uint32_t run=0, const uint32_t lumi=0, SaveReferenceTag ref=SaveWithReference, int minStatus=dqm::qstatus::STATUS_OK, const std::string &fileupdate="RECREATE", const bool resetMEsAfterWriting=false)
Definition: DQMStore.cc:2562
bool readFilePB(const std::string &filename, bool overwrite=false, const std::string &path="", const std::string &prepend="", OpenRunDirs stripdirs=StripRunDirs, bool fileMustExist=true)
Definition: DQMStore.cc:3043
TProfile * getTProfile(void) const
void useQTest(const std::string &dir, const std::string &qtname)
Definition: DQMStore.cc:3223
tuple filename
Definition: lut2db_cfg.py:20
std::string message
Definition: DQMNet.h:91
void goUp(void)
equivalent to &quot;cd ..&quot;
Definition: DQMStore.cc:695
bool open(const std::string &filename, bool overwrite=false, const std::string &path="", const std::string &prepend="", OpenRunDirs stripdirs=KeepRunDirs, bool fileMustExist=true)
Definition: DQMStore.cc:2917
inline::google::protobuf::uint32 flags() const
static const int STATUS_OK
void setAccumulate(MonitorElement *me, bool flag)
Definition: DQMStore.cc:3345
tuple cout
Definition: gather_cfg.py:121
void setEfficiencyFlag(void)
static void collate1S(MonitorElement *me, TH1S *h, unsigned verbose)
Definition: DQMStore.cc:1545
void Reset(std::vector< TH2F > &depth)
std::ofstream * stream_
Definition: DQMStore.h:705
QCriterion * createQTest(const std::string &algoname, const std::string &qtname)
Definition: DQMStore.cc:3202
static bool checkBinningMatches(MonitorElement *me, TH1 *h, unsigned verbose)
Definition: DQMStore.cc:1511
dbl *** dir
Definition: mlp_gen.cc:35
volatile std::atomic< bool > shutdown_flag false
void showDirStructure(void) const
Definition: DQMStore.cc:3355
void reset(void)
Definition: DQMStore.cc:2012
bool deleteObject(T *fObject, const std::string &fInput, const std::string &fInputTag, HcalDbTool::IOVRun fInputRun, bool fVerbose)
tuple status
Definition: ntuplemaker.py:245
TH2F * getTH2F(void) const
if(conf.exists("allCellsPositionCalc"))
static void collate2D(MonitorElement *me, TH2F *h, unsigned verbose)
Definition: DQMStore.cc:1559
MonitorElement * bookInt(const char *name)
Book int.
Definition: DQMStore.cc:878
MonitorElement * book2D(const char *name, const char *title, int nchX, double lowX, double highX, int nchY, double lowY, double highY)
Book 2D histogram.
Definition: DQMStore.cc:1099
tuple collateHistograms
for(const auto &isodef:isoDefs)
long double T
uint32_t streamId
Definition: DQMNet.h:103
void mergeAndResetMEsLuminositySummaryCache(uint32_t run, uint32_t lumi, uint32_t streamId, uint32_t moduleId)
Definition: DQMStore.cc:394
float qtresult
Definition: DQMNet.h:90
std::set< std::string > dirs_
Definition: DQMStore.h:709
bool collateHistograms_
Definition: DQMStore.h:697
void Reset(void)
reset ME (ie. contents, errors, etc)
static const uint32_t DQM_PROP_LUMI
Definition: DQMNet.h:60
static std::string const source
Definition: EdmProvDump.cc:43
bool LSbasedMode_
Definition: DQMStore.h:699
void addQReport(const DQMNet::QValue &desc, QCriterion *qc)
Add quality report, from DQMStore.
MonitorElement * book1S(const char *name, const char *title, int nchX, double lowX, double highX)
Book 1S histogram.
Definition: DQMStore.cc:987
tuple size
Write out results.
static const lat::Regexp s_rxmeqr1("^st:(\\d+):([-+e.\\d]+):([^:]*):(.*)$")
void makeDirectory(const std::string &path)
Definition: DQMStore.cc:708
void connect(U iFunc)
Definition: Signal.h:63
bool compare_strings(std::string const &pattern, std::string const &input) const
Definition: DQMStore.cc:226
void setCurrentFolder(const std::string &fullpath)
Definition: DQMStore.cc:684
static void collate2S(MonitorElement *me, TH2S *h, unsigned verbose)
Definition: DQMStore.cc:1566
static const int ERROR
const std::string & pwd(void) const
Definition: DQMStore.cc:656
bool enableMultiThread_
Definition: DQMStore.h:698
void set_streamed_histo(const ::std::string &value)
static bool CheckBinLabels(const TAxis *a1, const TAxis *a2)
Check the consistency of the axis labels.
MonitorElement * bookProfile2D(const char *name, const char *title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, int nchZ, double lowZ, double highZ, const char *option="s")
Definition: DQMStore.cc:1429
void raiseDQMError(const char *context, const char *fmt,...)
Definition: DQMError.cc:11