Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-05-01 22:51:56

0001 #include "DQMServices/Core/interface/LegacyIOHelper.h"
0002 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0003 
0004 #include <cstdio>
0005 #include <cfloat>
0006 #include <vector>
0007 #include <string>
0008 
0009 #include "TString.h"
0010 #include "TSystem.h"
0011 #include "TFile.h"
0012 #include "TKey.h"
0013 #include <sys/stat.h>
0014 
0015 void LegacyIOHelper::save(std::string const &filename,
0016                           std::string const &path /* = "" */,
0017                           uint32_t const run /* = 0 */,
0018                           bool saveall /* = true */,
0019                           std::string const &fileupdate /* = "RECREATE" */) {
0020   // TFile flushes to disk with fsync() on every TDirectory written to
0021   // the file.  This makes DQM file saving painfully slow, and
0022   // ironically makes it _more_ likely the file saving gets
0023   // interrupted and corrupts the file.  The utility class below
0024   // simply ignores the flush synchronisation.
0025   class TFileNoSync : public TFile {
0026   public:
0027     TFileNoSync(char const *file, char const *opt) : TFile{file, opt} {}
0028     Int_t SysSync(Int_t) override { return 0; }
0029   };
0030 
0031   std::cout << "DQMFileSaver::globalEndRun()" << std::endl;
0032 
0033   char suffix[64];
0034   sprintf(suffix, "R%09d", run);
0035   TFileNoSync *file = new TFileNoSync(filename.c_str(), fileupdate.c_str());  // open file
0036 
0037   // Traverse all MEs
0038   std::vector<MonitorElement *> mes;
0039   if (saveall) {
0040     // this is typically used, at endJob there will only be JOB histos here
0041     mes = dbe_->getAllContents(path);
0042   } else {
0043     // at endRun it might make sense to use this, to not save JOB histos yet.
0044     mes = dbe_->getAllContents(path, run, 0);
0045   }
0046 
0047   for (auto me : mes) {
0048     // Modify dirname to comply with DQM GUI format. Change:
0049     // A/B/C/plot
0050     // into:
0051     // DQMData/Run X/A/Run summary/B/C/plot
0052     std::string dirName = me->getPathname();
0053     uint64_t firstSlashPos = dirName.find('/');
0054     if (firstSlashPos == std::string::npos) {
0055       firstSlashPos = dirName.length();
0056     }
0057 
0058     if (run) {
0059       // Rewrite paths to "Run Summary" format when given a run number.
0060       // Else, write a simple, flat TDirectory for local usage.
0061       dirName = dirName.substr(0, firstSlashPos) + "/Run summary" + dirName.substr(firstSlashPos, dirName.size());
0062       dirName = "DQMData/Run " + std::to_string(run) + "/" + dirName;
0063     }
0064 
0065     std::string objectName = me->getName();
0066 
0067     // Create dir if it doesn't exist and cd into it
0068     createDirectoryIfNeededAndCd(dirName);
0069 
0070     // INTs are saved as strings in this format: <objectName>i=value</objectName>
0071     // REALs are saved as strings in this format: <objectName>f=value</objectName>
0072     // STRINGs are saved as strings in this format: <objectName>s="value"</objectName>
0073     if (me->kind() == MonitorElement::Kind::INT) {
0074       int value = me->getIntValue();
0075       std::string content = "<" + objectName + ">i=" + std::to_string(value) + "</" + objectName + ">";
0076       TObjString str(content.c_str());
0077       str.Write();
0078     } else if (me->kind() == MonitorElement::Kind::REAL) {
0079       double value = me->getFloatValue();
0080       char buf[64];
0081       // use printf here to preserve exactly the classic formatting.
0082       std::snprintf(buf, sizeof(buf), "%.*g", DBL_DIG + 2, value);
0083       std::string content = "<" + objectName + ">f=" + buf + "</" + objectName + ">";
0084       TObjString str(content.c_str());
0085       str.Write();
0086     } else if (me->kind() == MonitorElement::Kind::STRING) {
0087       const std::string &value = me->getStringValue();
0088       std::string content = "<" + objectName + ">s=" + value + "</" + objectName + ">";
0089       TObjString str(content.c_str());
0090       str.Write();
0091     } else {
0092       // Write a histogram
0093       TH1 *value = me->getTH1();
0094       value->Write();
0095 
0096       if (me->getEfficiencyFlag()) {
0097         std::string content = "<" + objectName + ">e=1</" + objectName + ">";
0098         TObjString str(content.c_str());
0099         str.Write();
0100       }
0101 
0102       for (QReport *qr : me->getQReports()) {
0103         std::string result;
0104         // TODO: 64 is likely too short; memory corruption in the old code?
0105         char buf[64];
0106         std::snprintf(buf, sizeof(buf), "qr=st:%d:%.*g:", qr->getStatus(), DBL_DIG + 2, qr->getQTresult());
0107         result = '<' + objectName + '.' + qr->getQRName() + '>';
0108         result += buf;
0109         result += qr->getAlgorithm() + ':' + qr->getMessage();
0110         result += "</" + objectName + '.' + qr->getQRName() + '>';
0111         TObjString str(result.c_str());
0112         str.Write();
0113       }
0114     }
0115 
0116     // Go back to the root directory
0117     gDirectory->cd("/");
0118   }
0119 
0120   file->Close();
0121 }
0122 
0123 // Use this for saving monitoring objects in ROOT files with dir structure;
0124 // cds into directory (creates it first if it doesn't exist);
0125 // returns a success flag
0126 bool LegacyIOHelper::createDirectoryIfNeededAndCd(const std::string &path) {
0127   assert(!path.empty());
0128 
0129   // Find the first path component.
0130   size_t start = 0;
0131   size_t end = path.find('/', start);
0132   if (end == std::string::npos)
0133     end = path.size();
0134 
0135   while (true) {
0136     // Check if this subdirectory component exists.  If yes, make sure
0137     // it is actually a subdirectory.  Otherwise create or cd into it.
0138     std::string part(path, start, end - start);
0139     TObject *o = gDirectory->Get(part.c_str());
0140     if (o && !dynamic_cast<TDirectory *>(o))
0141       throw cms::Exception("DQMFileSaver") << "Attempt to create directory '" << path
0142                                            << "' in a file"
0143                                               " fails because the part '"
0144                                            << part
0145                                            << "' already exists and is not"
0146                                               " directory";
0147     else if (!o)
0148       gDirectory->mkdir(part.c_str());
0149 
0150     if (!gDirectory->cd(part.c_str()))
0151       throw cms::Exception("DQMFileSaver") << "Attempt to create directory '" << path
0152                                            << "' in a file"
0153                                               " fails because could not cd into subdirectory '"
0154                                            << part << "'";
0155 
0156     // Stop if we reached the end, ignoring any trailing '/'.
0157     if (end + 1 >= path.size())
0158       break;
0159 
0160     // Find the next path component.
0161     start = end + 1;
0162     end = path.find('/', start);
0163     if (end == std::string::npos)
0164       end = path.size();
0165   }
0166 
0167   return true;
0168 }
0169 
0170 bool LegacyIOHelper::readdir(TDirectory *dir, const std::string &toppath) {
0171   TDirectory *dirsav = gDirectory;
0172   LogDebug("LegacyIOHelper") << "Inside:" << gDirectory->GetPath() << std::endl;
0173   TIter next(dir->GetListOfKeys());
0174   TKey *key;
0175   while ((key = (TKey *)next())) {
0176     if (key->IsFolder()) {
0177       LogDebug("LegacyIOHelper") << key->GetName() << std::endl;
0178       dir->cd(key->GetName());
0179       TDirectory *subdir = gDirectory;
0180       readdir(subdir, toppath);
0181       dirsav->cd();
0182       continue;
0183     } else {
0184       TClass *cl = gROOT->GetClass(key->GetClassName());
0185       std::string meName;
0186       if (cl->InheritsFrom("TProfile")) {
0187         TProfile *h = dynamic_cast<TProfile *>(key->ReadObject<TProfile>()->Clone());
0188         h->SetDirectory(nullptr);
0189         if (h) {
0190           getMEName<TProfile>(h, toppath, meName);
0191           data_.insert(dbe_->bookProfile(meName, h));
0192         }
0193       } else if (cl->InheritsFrom("TProfile2D")) {
0194         TProfile2D *h = dynamic_cast<TProfile2D *>(key->ReadObject<TProfile2D>()->Clone());
0195         h->SetDirectory(nullptr);
0196         if (h) {
0197           getMEName<TProfile2D>(h, toppath, meName);
0198           data_.insert(dbe_->bookProfile2D(meName, h));
0199         }
0200       } else if (cl->InheritsFrom("TH1F")) {
0201         TH1F *h = dynamic_cast<TH1F *>(key->ReadObject<TH1F>()->Clone());
0202         h->SetDirectory(nullptr);
0203         if (h) {
0204           getMEName<TH1F>(h, toppath, meName);
0205           data_.insert(dbe_->book1D(meName, h));
0206         }
0207       } else if (cl->InheritsFrom("TH1S")) {
0208         TH1S *h = dynamic_cast<TH1S *>(key->ReadObject<TH1S>()->Clone());
0209         h->SetDirectory(nullptr);
0210         if (h) {
0211           getMEName<TH1S>(h, toppath, meName);
0212           data_.insert(dbe_->book1S(meName, h));
0213         }
0214       } else if (cl->InheritsFrom("TH1D")) {
0215         TH1D *h = dynamic_cast<TH1D *>(key->ReadObject<TH1D>()->Clone());
0216         h->SetDirectory(nullptr);
0217         if (h) {
0218           getMEName<TH1D>(h, toppath, meName);
0219           data_.insert(dbe_->book1DD(meName, h));
0220         }
0221       } else if (cl->InheritsFrom("TH1I")) {
0222         TH1I *h = dynamic_cast<TH1I *>(key->ReadObject<TH1I>()->Clone());
0223         h->SetDirectory(nullptr);
0224         if (h) {
0225           getMEName<TH1I>(h, toppath, meName);
0226           data_.insert(dbe_->book1I(meName, h));
0227         }
0228       } else if (cl->InheritsFrom("TH2F")) {
0229         TH2F *h = dynamic_cast<TH2F *>(key->ReadObject<TH2F>()->Clone());
0230         h->SetDirectory(nullptr);
0231         if (h) {
0232           getMEName<TH2F>(h, toppath, meName);
0233           data_.insert(dbe_->book2D(meName, h));
0234         }
0235       } else if (cl->InheritsFrom("TH2S")) {
0236         TH2S *h = dynamic_cast<TH2S *>(key->ReadObject<TH2S>()->Clone());
0237         h->SetDirectory(nullptr);
0238         if (h) {
0239           getMEName<TH2S>(h, toppath, meName);
0240           data_.insert(dbe_->book2S(meName, h));
0241         }
0242       } else if (cl->InheritsFrom("TH2D")) {
0243         TH2D *h = dynamic_cast<TH2D *>(key->ReadObject<TH2D>()->Clone());
0244         h->SetDirectory(nullptr);
0245         if (h) {
0246           getMEName<TH2D>(h, toppath, meName);
0247           data_.insert(dbe_->book2DD(meName, h));
0248         }
0249       } else if (cl->InheritsFrom("TH2I")) {
0250         TH2I *h = dynamic_cast<TH2I *>(key->ReadObject<TH2I>()->Clone());
0251         h->SetDirectory(nullptr);
0252         if (h) {
0253           getMEName<TH2I>(h, toppath, meName);
0254           data_.insert(dbe_->book2I(meName, h));
0255         }
0256       } else if (cl->InheritsFrom("TH3F")) {
0257         TH3F *h = dynamic_cast<TH3F *>(key->ReadObject<TH3F>()->Clone());
0258         h->SetDirectory(nullptr);
0259         if (h) {
0260           getMEName<TH3F>(h, toppath, meName);
0261           data_.insert(dbe_->book3D(meName, h));
0262         }
0263       }
0264     }
0265   }
0266   if (!data_.empty())
0267     return true;
0268   return false;
0269 }
0270 
0271 bool LegacyIOHelper::open(std::string const &filename, std::string const &path, uint32_t const run) {
0272   TFile *f1 = TFile::Open(filename.c_str());
0273   if (!f1)
0274     return false;
0275   std::ostringstream toppath;
0276   toppath << filename << ":/DQMData/Run " << run << "/";
0277   std::string dirpath = toppath.str();
0278   edm::LogPrint("LegacyIOHelper") << dirpath << std::endl;
0279   bool flag = readdir(f1, dirpath);
0280   f1->Close();
0281   return flag;
0282 }