CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_2_7_hltpatch1/src/DQMServices/FwkIO/plugins/DQMRootSource.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:     FwkIO
00004 // Class  :     DQMRootSource
00005 // 
00006 // Implementation:
00007 //     [Notes on implementation]
00008 //
00009 // Original Author:  Chris Jones
00010 //         Created:  Tue May  3 11:13:47 CDT 2011
00011 // $Id: DQMRootSource.cc,v 1.28 2012/03/04 17:37:07 chrjones Exp $
00012 //
00013 
00014 // system include files
00015 #include <vector>
00016 #include <string>
00017 #include <map>
00018 #include <list>
00019 #include <set>
00020 #include "TFile.h"
00021 #include "TTree.h"
00022 #include "TString.h"
00023 #include "TH1.h"
00024 #include "TH2.h"
00025 #include "TProfile.h"
00026 
00027 // user include files
00028 #include "FWCore/Framework/interface/InputSource.h"
00029 #include "FWCore/Catalog/interface/InputFileCatalog.h"
00030 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00031 #include "DQMServices/Core/interface/DQMStore.h"
00032 #include "DQMServices/Core/interface/MonitorElement.h"
00033 #include "FWCore/ServiceRegistry/interface/Service.h"
00034 #include "FWCore/MessageLogger/interface/JobReport.h"
00035 //#include "FWCore/Utilities/interface/GlobalIdentifier.h"
00036 #include "FWCore/Utilities/interface/EDMException.h"
00037 
00038 #include "FWCore/Framework/interface/RunPrincipal.h"
00039 #include "FWCore/Framework/interface/LuminosityBlockPrincipal.h"
00040 
00041 #include "FWCore/Framework/interface/Run.h"
00042 #include "FWCore/Framework/interface/LuminosityBlock.h"
00043 
00044 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
00045 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
00046 
00047 #include "FWCore/Framework/interface/InputSourceMacros.h"
00048 #include "FWCore/Framework/interface/FileBlock.h"
00049 
00050 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00051 #include "FWCore/Utilities/interface/TimeOfDay.h"
00052 
00053 #include "DataFormats/Provenance/interface/ProcessHistory.h"
00054 #include "DataFormats/Provenance/interface/ProcessHistoryRegistry.h"
00055 #include "FWCore/ParameterSet/interface/Registry.h"
00056 
00057 #include "FWCore/Utilities/interface/Digest.h"
00058 
00059 #include "format.h"
00060 
00061 namespace {
00062   //adapter functions
00063   MonitorElement* createElement(DQMStore& iStore, const char* iName, TH1F* iHist) {
00064     //std::cout <<"create: hist size "<<iName <<" "<<iHist->GetEffectiveEntries()<<std::endl;
00065     return iStore.book1D(iName, iHist);
00066   }
00067   //NOTE: the merge logic comes from DataFormats/Histograms/interface/MEtoEDMFormat.h
00068   void mergeTogether(TH1* iOriginal,TH1* iToAdd) {
00069     if(iOriginal->TestBit(TH1::kCanRebin)==true && iToAdd->TestBit(TH1::kCanRebin) ==true) {
00070       TList list;
00071       list.Add(iToAdd);
00072       if( -1 == iOriginal->Merge(&list)) {
00073         edm::LogError("MergeFailure")<<"Failed to merge DQM element "<<iOriginal->GetName();
00074       }
00075     } else {
00076       if (iOriginal->GetNbinsX() == iToAdd->GetNbinsX() &&
00077           iOriginal->GetXaxis()->GetXmin() == iToAdd->GetXaxis()->GetXmin() &&
00078           iOriginal->GetXaxis()->GetXmax() == iToAdd->GetXaxis()->GetXmax() &&
00079           iOriginal->GetNbinsY() == iToAdd->GetNbinsY() &&
00080           iOriginal->GetYaxis()->GetXmin() == iToAdd->GetYaxis()->GetXmin() &&
00081           iOriginal->GetYaxis()->GetXmax() == iToAdd->GetYaxis()->GetXmax() &&
00082           iOriginal->GetNbinsZ() == iToAdd->GetNbinsZ() &&
00083           iOriginal->GetZaxis()->GetXmin() == iToAdd->GetZaxis()->GetXmin() &&
00084           iOriginal->GetZaxis()->GetXmax() == iToAdd->GetZaxis()->GetXmax()) {
00085         iOriginal->Add(iToAdd);
00086       } else {
00087         edm::LogError("MergeFailure")<<"Found histograms with different axis limits '"<<iOriginal->GetName()<<"' not merged.";
00088       }
00089     } 
00090   }
00091   void mergeWithElement(MonitorElement* iElement, TH1F* iHist) {
00092     //std::cout <<"merge: hist size "<<iElement->getName() <<" "<<iHist->GetEffectiveEntries()<<std::endl;
00093     mergeTogether(iElement->getTH1F(),iHist);
00094   }
00095   MonitorElement* createElement(DQMStore& iStore, const char* iName, TH1S* iHist) {
00096     return iStore.book1S(iName, iHist);
00097   }
00098   void mergeWithElement(MonitorElement* iElement, TH1S* iHist) {
00099     mergeTogether(iElement->getTH1S(),iHist);
00100   }  
00101   MonitorElement* createElement(DQMStore& iStore, const char* iName, TH1D* iHist) {
00102     return iStore.book1DD(iName, iHist);
00103   }
00104   void mergeWithElement(MonitorElement* iElement, TH1D* iHist) {
00105     mergeTogether(iElement->getTH1D(),iHist);
00106   }
00107   MonitorElement* createElement(DQMStore& iStore, const char* iName, TH2F* iHist) {
00108     return iStore.book2D(iName, iHist);
00109   }
00110   void mergeWithElement(MonitorElement* iElement, TH2F* iHist) {
00111     mergeTogether(iElement->getTH2F(),iHist);
00112   }
00113   MonitorElement* createElement(DQMStore& iStore, const char* iName, TH2S* iHist) {
00114     return iStore.book2S(iName, iHist);
00115   }
00116   void mergeWithElement(MonitorElement* iElement, TH2S* iHist) {
00117     mergeTogether(iElement->getTH2S(),iHist);
00118   }  
00119   MonitorElement* createElement(DQMStore& iStore, const char* iName, TH2D* iHist) {
00120     return iStore.book2DD(iName, iHist);
00121   }
00122   void mergeWithElement(MonitorElement* iElement, TH2D* iHist) {
00123     mergeTogether(iElement->getTH2D(),iHist);
00124   }
00125   MonitorElement* createElement(DQMStore& iStore, const char* iName, TH3F* iHist) {
00126     return iStore.book3D(iName, iHist);
00127   }
00128   void mergeWithElement(MonitorElement* iElement, TH3F* iHist) {
00129     mergeTogether(iElement->getTH3F(),iHist);
00130   }
00131   MonitorElement* createElement(DQMStore& iStore, const char* iName, TProfile* iHist) {
00132     return iStore.bookProfile(iName, iHist);
00133   }
00134   void mergeWithElement(MonitorElement* iElement, TProfile* iHist) {
00135     mergeTogether(iElement->getTProfile(),iHist);
00136   }
00137   MonitorElement* createElement(DQMStore& iStore, const char* iName, TProfile2D* iHist) {
00138     return iStore.bookProfile2D(iName, iHist);
00139   }
00140   void mergeWithElement(MonitorElement* iElement, TProfile2D* iHist) {
00141     mergeTogether(iElement->getTProfile2D(),iHist);
00142   }
00143 
00144   MonitorElement* createElement(DQMStore& iStore, const char* iName, Long64_t& iValue) {
00145     MonitorElement* e = iStore.bookInt(iName);
00146     e->Fill(iValue);
00147     return e;
00148   }
00149 
00150   //NOTE: the merge logic comes from DataFormats/Histograms/interface/MEtoEDMFormat.h
00151   void mergeWithElement(MonitorElement* iElement, Long64_t& iValue) {
00152     const std::string& name = iElement->getFullname();
00153     if(name.find("EventInfo/processedEvents") != std::string::npos) {
00154       iElement->Fill(iValue+iElement->getIntValue());
00155     } else {
00156       if(name.find("EventInfo/iEvent") != std::string::npos ||
00157          name.find("EventInfo/iLumiSection") != std::string::npos) {
00158         if(iValue > iElement->getIntValue()) {
00159           iElement->Fill(iValue);
00160         }
00161       }
00162     }
00163   }
00164 
00165   MonitorElement* createElement(DQMStore& iStore, const char* iName, double& iValue) {
00166     MonitorElement* e = iStore.bookFloat(iName);
00167     e->Fill(iValue);
00168     return e;
00169   }
00170   void mergeWithElement(MonitorElement* iElement, double& iValue) {
00171     //no merging
00172   }
00173   MonitorElement* createElement(DQMStore& iStore, const char* iName, std::string* iValue) {
00174     return iStore.bookString(iName,*iValue);
00175   }
00176   void mergeWithElement(MonitorElement* , std::string* ) {
00177     //no merging
00178   }
00179 
00180   void splitName(const std::string& iFullName, std::string& oPath,const char*& oName) {
00181     oPath = iFullName;
00182     size_t index = oPath.find_last_of('/');
00183     if(index == std::string::npos) {
00184       oPath = std::string();
00185       oName = iFullName.c_str();
00186     } else {
00187       oPath.resize(index);
00188       oName = iFullName.c_str()+index+1;
00189     }
00190   }
00191 
00192   struct RunLumiToRange {
00193     unsigned int m_run, m_lumi,m_historyIDIndex;
00194     ULong64_t m_beginTime;
00195     ULong64_t m_endTime;
00196     ULong64_t m_firstIndex, m_lastIndex; //last is inclusive
00197     unsigned int m_type; //A value in TypeIndex
00198   };
00199 
00200   class TreeReaderBase {
00201     public:
00202       TreeReaderBase() {}
00203       virtual ~TreeReaderBase() {}
00204 
00205       MonitorElement* read(ULong64_t iIndex, DQMStore& iStore, bool iIsLumi){
00206         return doRead(iIndex,iStore,iIsLumi);
00207       }
00208       virtual void setTree(TTree* iTree) =0;
00209     protected:
00210       TTree* m_tree;
00211     private:
00212       virtual MonitorElement* doRead(ULong64_t iIndex, DQMStore& iStore, bool iIsLumi)=0;
00213   };
00214 
00215   template<class T>
00216     class TreeObjectReader: public TreeReaderBase {
00217       public:
00218         TreeObjectReader():m_tree(0),m_fullName(0),m_buffer(0),m_tag(0){
00219         }
00220         virtual MonitorElement* doRead(ULong64_t iIndex, DQMStore& iStore, bool iIsLumi) {
00221           m_tree->GetEntry(iIndex);
00222           MonitorElement* element = iStore.get(*m_fullName);
00223           if(0 == element) {
00224             std::string path;
00225             const char* name;
00226             splitName(*m_fullName, path,name);
00227             iStore.setCurrentFolder(path);
00228             element = createElement(iStore,name,m_buffer);
00229             if(iIsLumi) { element->setLumiFlag();}
00230           } else {
00231             mergeWithElement(element,m_buffer);
00232           }
00233           if(0!= m_tag) {
00234             iStore.tag(element,m_tag);
00235           }
00236           return element;
00237         }
00238         virtual void setTree(TTree* iTree)  {
00239           m_tree = iTree;
00240           m_tree->SetBranchAddress(kFullNameBranch,&m_fullName);
00241           m_tree->SetBranchAddress(kFlagBranch,&m_tag);
00242           m_tree->SetBranchAddress(kValueBranch,&m_buffer);
00243         }
00244       private:
00245         TTree* m_tree;
00246         std::string* m_fullName;
00247         T* m_buffer;
00248         uint32_t m_tag;
00249     };
00250 
00251   template<class T>
00252     class TreeSimpleReader : public TreeReaderBase {
00253       public:
00254         TreeSimpleReader():m_tree(0),m_fullName(0),m_buffer(),m_tag(0){
00255         }
00256         virtual MonitorElement* doRead(ULong64_t iIndex, DQMStore& iStore,bool iIsLumi) {
00257           m_tree->GetEntry(iIndex);
00258           MonitorElement* element = iStore.get(*m_fullName);
00259           if(0 == element) {
00260             std::string path;
00261             const char* name;
00262             splitName(*m_fullName, path,name);
00263             iStore.setCurrentFolder(path);
00264             element = createElement(iStore,name,m_buffer);
00265             if(iIsLumi) { element->setLumiFlag();}
00266           } else {
00267             mergeWithElement(element, m_buffer);
00268           }
00269           if(0!=m_tag) {
00270             iStore.tag(element,m_tag);
00271           }
00272           return element;
00273         }
00274         virtual void setTree(TTree* iTree)  {
00275           m_tree = iTree;
00276           m_tree->SetBranchAddress(kFullNameBranch,&m_fullName);
00277           m_tree->SetBranchAddress(kFlagBranch,&m_tag);
00278           m_tree->SetBranchAddress(kValueBranch,&m_buffer);
00279         }
00280       private:
00281         TTree* m_tree;
00282         std::string* m_fullName;
00283         T m_buffer;
00284         uint32_t m_tag;
00285     };
00286 
00287 }
00288 
00289 class DQMRootSource : public edm::InputSource
00290 {
00291 
00292    public:
00293       DQMRootSource(edm::ParameterSet const&, const edm::InputSourceDescription&);
00294       virtual ~DQMRootSource();
00295 
00296       // ---------- const member functions ---------------------
00297 
00298       // ---------- static member functions --------------------
00299 
00300       // ---------- member functions ---------------------------
00301       static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
00302    protected:
00303      virtual void endLuminosityBlock(edm::LuminosityBlock&);
00304      virtual void endRun(edm::Run&);
00305      
00306    private:
00307       DQMRootSource(const DQMRootSource&); // stop default
00308 
00309       virtual edm::InputSource::ItemType getNextItemType();
00310       //NOTE: the following is really read next run auxiliary
00311       virtual boost::shared_ptr<edm::RunAuxiliary> readRunAuxiliary_() ;
00312       virtual boost::shared_ptr<edm::LuminosityBlockAuxiliary> readLuminosityBlockAuxiliary_() ;
00313       virtual boost::shared_ptr<edm::RunPrincipal> readRun_(boost::shared_ptr<edm::RunPrincipal> rpCache);
00314       virtual boost::shared_ptr<edm::LuminosityBlockPrincipal> readLuminosityBlock_( boost::shared_ptr<edm::LuminosityBlockPrincipal> lbCache);
00315       virtual edm::EventPrincipal* readEvent_() ;
00316       
00317       virtual boost::shared_ptr<edm::FileBlock> readFile_();
00318       virtual void closeFile_();
00319       
00320       void logFileAction(char const* msg, char const* fileName) const;
00321       
00322       void readNextItemType();
00323       void setupFile(unsigned int iIndex);
00324       void readElements();
00325       
00326       const DQMRootSource& operator=(const DQMRootSource&); // stop default
00327 
00328       // ---------- member data --------------------------------
00329       edm::InputFileCatalog m_catalog;
00330       edm::RunAuxiliary m_runAux;
00331       edm::LuminosityBlockAuxiliary m_lumiAux;
00332       edm::InputSource::ItemType m_nextItemType;
00333 
00334       size_t m_fileIndex;
00335       size_t m_presentlyOpenFileIndex;
00336       std::list<unsigned int>::iterator m_nextIndexItr;
00337       std::list<unsigned int>::iterator m_presentIndexItr;
00338       std::vector<RunLumiToRange> m_runlumiToRange;
00339       std::auto_ptr<TFile> m_file;
00340       std::vector<TTree*> m_trees;
00341       std::vector<boost::shared_ptr<TreeReaderBase> > m_treeReaders;
00342       
00343       std::list<unsigned int> m_orderedIndices;
00344       unsigned int m_lastSeenRun;
00345       unsigned int m_filterOnRun;
00346       bool m_justOpenedFileSoNeedToGenerateRunTransition;
00347       bool m_doNotReadRemainingPartsOfFileSinceFrameworkTerminating;
00348       bool m_shouldReadMEs;
00349       bool m_shouldResetRunMEs;
00350       bool m_shouldResetLumiMEs;
00351       std::set<MonitorElement*> m_lumiElements;
00352       std::set<MonitorElement*> m_runElements;
00353       std::vector<edm::ProcessHistoryID> m_historyIDs;
00354       
00355       edm::JobReport::Token m_jrToken;
00356 };
00357 
00358 //
00359 // constants, enums and typedefs
00360 //
00361 
00362 //
00363 // static data member definitions
00364 //
00365 
00366 void
00367 DQMRootSource::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
00368   edm::ParameterSetDescription desc;
00369   desc.addUntracked<std::vector<std::string> >("fileNames")
00370     ->setComment("Names of files to be processed.");
00371   desc.addUntracked<unsigned int>("filterOnRun",0)
00372     ->setComment("Just limit the process to the selected run.");
00373   desc.addUntracked<std::string>("overrideCatalog",std::string())
00374     ->setComment("An alternate file catalog to use instead of the standard site one.");
00375   descriptions.addDefault(desc);
00376 }
00377 //
00378 // constructors and destructor
00379 //
00380 DQMRootSource::DQMRootSource(edm::ParameterSet const& iPSet, const edm::InputSourceDescription& iDesc):
00381   edm::InputSource(iPSet,iDesc),
00382   m_catalog(iPSet.getUntrackedParameter<std::vector<std::string> >("fileNames"),
00383             iPSet.getUntrackedParameter<std::string>("overrideCatalog")),
00384   m_nextItemType(edm::InputSource::IsFile),
00385   m_fileIndex(0),
00386   m_presentlyOpenFileIndex(0),
00387   m_trees(kNIndicies,static_cast<TTree*>(0)),
00388   m_treeReaders(kNIndicies,boost::shared_ptr<TreeReaderBase>()),
00389   m_lastSeenRun(0),
00390   m_filterOnRun(iPSet.getUntrackedParameter<unsigned int>("filterOnRun", 0)),
00391   m_justOpenedFileSoNeedToGenerateRunTransition(false),
00392   m_doNotReadRemainingPartsOfFileSinceFrameworkTerminating(false),
00393   m_shouldReadMEs(true),
00394   m_shouldResetRunMEs(true),
00395   m_shouldResetLumiMEs(true)
00396 {
00397   if(m_fileIndex ==m_catalog.fileNames().size()) {
00398     m_nextItemType=edm::InputSource::IsStop;
00399   } else{
00400     m_treeReaders[kIntIndex].reset(new TreeSimpleReader<Long64_t>());
00401     m_treeReaders[kFloatIndex].reset(new TreeSimpleReader<double>());
00402     m_treeReaders[kStringIndex].reset(new TreeObjectReader<std::string>());
00403     m_treeReaders[kTH1FIndex].reset(new TreeObjectReader<TH1F>());
00404     m_treeReaders[kTH1SIndex].reset(new TreeObjectReader<TH1S>());
00405     m_treeReaders[kTH1DIndex].reset(new TreeObjectReader<TH1D>());
00406     m_treeReaders[kTH2FIndex].reset(new TreeObjectReader<TH2F>());
00407     m_treeReaders[kTH2SIndex].reset(new TreeObjectReader<TH2S>());
00408     m_treeReaders[kTH2DIndex].reset(new TreeObjectReader<TH2D>());
00409     m_treeReaders[kTH3FIndex].reset(new TreeObjectReader<TH3F>());
00410     m_treeReaders[kTProfileIndex].reset(new TreeObjectReader<TProfile>());
00411     m_treeReaders[kTProfile2DIndex].reset(new TreeObjectReader<TProfile2D>());
00412   }
00413 
00414 }
00415 
00416 // DQMRootSource::DQMRootSource(const DQMRootSource& rhs)
00417 // {
00418 //    // do actual copying here;
00419 // }
00420 
00421 DQMRootSource::~DQMRootSource()
00422 {
00423   if(m_file.get() != 0 && m_file->IsOpen()) {
00424     m_file->Close();
00425     logFileAction("  Closed file ", m_catalog.fileNames()[m_presentlyOpenFileIndex].c_str());
00426   }
00427 }
00428 
00429 //
00430 // assignment operators
00431 //
00432 // const DQMRootSource& DQMRootSource::operator=(const DQMRootSource& rhs)
00433 // {
00434 //   //An exception safe implementation is
00435 //   DQMRootSource temp(rhs);
00436 //   swap(rhs);
00437 //
00438 //   return *this;
00439 // }
00440 
00441 //
00442 // member functions
00443 //
00444 namespace {
00445   struct no_deleter {
00446     void operator()(void*) {}
00447   };
00448 }
00449 
00450 edm::EventPrincipal* DQMRootSource::readEvent_()
00451 {
00452   return 0;
00453 }
00454 
00455 edm::InputSource::ItemType DQMRootSource::getNextItemType()
00456 {
00457   //std::cout <<"getNextItemType "<<m_nextItemType<<std::endl;
00458   return m_nextItemType;
00459 }
00460 
00461 boost::shared_ptr<edm::RunAuxiliary> DQMRootSource::readRunAuxiliary_()
00462 {
00463   //std::cout <<"readRunAuxiliary_"<<std::endl;
00464   assert(m_nextIndexItr != m_orderedIndices.end());
00465   unsigned int index = *m_nextIndexItr;
00466   RunLumiToRange runLumiRange = m_runlumiToRange[index];
00467   //NOTE: this could be a lumi instead of the actual run. We need to find the time for the run
00468   // so we will scan forward
00469   while (runLumiRange.m_lumi !=0 && ++index<m_runlumiToRange.size())
00470   {
00471     const RunLumiToRange& next = m_runlumiToRange[index];
00472     if (runLumiRange.m_run == next.m_run)
00473       runLumiRange = next;
00474     else
00475       break;
00476   }
00477 
00478   //NOTE: the setBeginTime and setEndTime functions of RunAuxiliary only work if the previous value was invalid
00479   // therefore we must copy
00480   m_runAux = edm::RunAuxiliary(runLumiRange.m_run,edm::Timestamp(runLumiRange.m_beginTime),edm::Timestamp(runLumiRange.m_endTime));
00481   assert(m_historyIDs.size() > runLumiRange.m_historyIDIndex);
00482   //std::cout <<"readRunAuxiliary_ "<<m_historyIDs[runLumiRange.m_historyIDIndex]<<std::endl;
00483   m_runAux.setProcessHistoryID(m_historyIDs[runLumiRange.m_historyIDIndex]);    
00484   return boost::shared_ptr<edm::RunAuxiliary>( new edm::RunAuxiliary(m_runAux) );
00485 }
00486 
00487 boost::shared_ptr<edm::LuminosityBlockAuxiliary>
00488 DQMRootSource::readLuminosityBlockAuxiliary_()
00489 {
00490   //std::cout <<"readLuminosityBlockAuxiliary_"<<std::endl;
00491   assert(m_nextIndexItr != m_orderedIndices.end());
00492   const RunLumiToRange runLumiRange = m_runlumiToRange[*m_nextIndexItr];
00493   m_lumiAux = edm::LuminosityBlockAuxiliary(edm::LuminosityBlockID(runLumiRange.m_run,runLumiRange.m_lumi),
00494                                             edm::Timestamp(runLumiRange.m_beginTime),
00495                                             edm::Timestamp(runLumiRange.m_endTime));
00496   assert(m_historyIDs.size() > runLumiRange.m_historyIDIndex);
00497   //std::cout <<"lumi "<<m_lumiAux.beginTime().value()<<" "<<runLumiRange.m_beginTime<<std::endl;
00498   m_lumiAux.setProcessHistoryID(m_historyIDs[runLumiRange.m_historyIDIndex]);    
00499   
00500   return boost::shared_ptr<edm::LuminosityBlockAuxiliary>(new edm::LuminosityBlockAuxiliary(m_lumiAux));
00501 }
00502 
00503 boost::shared_ptr<edm::RunPrincipal>
00504 DQMRootSource::readRun_(boost::shared_ptr<edm::RunPrincipal> rpCache)
00505 {
00506   m_justOpenedFileSoNeedToGenerateRunTransition = false;
00507   unsigned int runID =rpCache->id().run();
00508   unsigned int lastRunID = m_lastSeenRun;
00509   m_shouldReadMEs = (m_filterOnRun == 0 ||
00510                      (m_filterOnRun != 0 && m_filterOnRun == runID)); 
00511   m_shouldResetRunMEs = m_shouldReadMEs;
00512   m_shouldResetLumiMEs = m_shouldReadMEs;
00513   //   std::cout <<"readRun_"<<std::endl;
00514   //   std::cout <<"m_shouldReadMEs " << m_shouldReadMEs <<std::endl;
00515   //   std::cout <<"m_shouldResetRunMEs " << m_shouldResetRunMEs <<std::endl;
00516   //   std::cout <<"m_shouldResetLumiMEs " << m_shouldResetLumiMEs <<std::endl;
00517   m_lastSeenRun = runID;
00518   readNextItemType();
00519 
00529   //NOTE: need to reset all run elements at this point
00530   if(lastRunID != runID && m_shouldResetRunMEs)
00531   {
00532     edm::Service<DQMStore> store;
00533     std::vector<MonitorElement*> allMEs = (*store).getAllContents("");
00534     std::vector<MonitorElement*>::iterator it    = allMEs.begin();
00535     std::vector<MonitorElement*>::iterator itEnd = allMEs.end();
00536     for(; it != itEnd; ++it)
00537     {
00538       // We do not want to reset here Lumi products, since a dedicated
00539       // resetting is done at every lumi transition.
00540       if ((*it)->getLumiFlag())
00541         continue;
00542 //       std::cout <<"RESETTING "<<(*it)->getFullname()<<std::endl;
00543       (*it)->Reset();
00544     }
00545   }
00546 
00547   if(m_presentIndexItr != m_orderedIndices.end()) {
00548     RunLumiToRange runLumiRange = m_runlumiToRange[*m_presentIndexItr];
00549     //NOTE: it is possible to have an Run when all we have stored is lumis
00550     if(runLumiRange.m_lumi == 0 &&
00551        runLumiRange.m_run == rpCache->id().run()) {
00552       readElements();
00553     }
00554   }
00555 
00556   edm::Service<edm::JobReport> jr;
00557   jr->reportInputRunNumber(rpCache->id().run());
00558 
00559   rpCache->fillRunPrincipal();
00560   return rpCache;
00561 }
00562 
00563 boost::shared_ptr<edm::LuminosityBlockPrincipal>
00564 DQMRootSource::readLuminosityBlock_( boost::shared_ptr<edm::LuminosityBlockPrincipal> lbCache)
00565 {
00566   //NOTE: need to reset all lumi block elements at this point
00567   edm::Service<DQMStore> store;
00568   std::vector<MonitorElement*> allMEs = (*store).getAllContents("");
00569   std::vector<MonitorElement*>::iterator it    = allMEs.begin();
00570   std::vector<MonitorElement*>::iterator itEnd = allMEs.end();
00571   if (m_shouldResetLumiMEs)
00572     for( ; it != itEnd; ++it)
00573     {
00574       // We do not want to reset Run Products here!
00575       if ((*it)->getLumiFlag())
00576       {
00577 //      std::cout <<"RESETTING "<<(*it)->getName()<<std::endl;
00578         (*it)->Reset();
00579       }
00580     }
00581   
00582   readNextItemType();
00583   //std::cout <<"readLuminosityBlock_"<<std::endl;
00584   RunLumiToRange runLumiRange = m_runlumiToRange[*m_presentIndexItr];
00585   if (runLumiRange.m_run == lbCache->id().run() &&
00586       runLumiRange.m_lumi == lbCache->id().luminosityBlock())
00587     readElements();
00588 
00589   edm::Service<edm::JobReport> jr;
00590   jr->reportInputLumiSection(lbCache->id().run(),lbCache->id().luminosityBlock());
00591 
00592   lbCache->fillLuminosityBlockPrincipal();
00593   return lbCache;
00594 }
00595 
00596 boost::shared_ptr<edm::FileBlock>
00597 DQMRootSource::readFile_() {
00598   //std::cout <<"readFile_"<<std::endl;
00599   setupFile(m_fileIndex);
00600   ++m_fileIndex;
00601   readNextItemType();
00602 
00603   edm::Service<edm::JobReport> jr;
00604   m_jrToken = jr->inputFileOpened(m_catalog.fileNames()[m_fileIndex-1],
00605       m_catalog.logicalFileNames()[m_fileIndex-1],
00606       std::string(),
00607       std::string(),
00608       "DQMRootSource",
00609       "source",
00610       m_file->GetUUID().AsString(),//edm::createGlobalIdentifier(),
00611       std::vector<std::string>()
00612       );
00613 
00614   m_doNotReadRemainingPartsOfFileSinceFrameworkTerminating = false;
00615   return boost::shared_ptr<edm::FileBlock>(new edm::FileBlock);
00616 }
00617 
00618 
00619 void 
00620 DQMRootSource::endLuminosityBlock(edm::LuminosityBlock& iLumi) {
00621   //std::cout <<"DQMRootSource::endLumi"<<std::endl;
00622 }
00623 void 
00624 DQMRootSource::endRun(edm::Run& iRun){
00625   //std::cout <<"DQMRootSource::endRun"<<std::endl;
00626   //NOTE: the framework will call endRun before closeFile in the case
00627   //where the frameworks is terminating
00628   m_doNotReadRemainingPartsOfFileSinceFrameworkTerminating=true;
00629 }
00630 
00631 
00632 void
00633 DQMRootSource::closeFile_() {
00634   //std::cout <<"closeFile_"<<std::endl;
00635   //when going from one file to the next the framework does not call
00636   // 'endRun' or 'endLumi' until it looks to see if the other file contains
00637   // a new run or lumi. If the other file doesn't then  
00638   if(not m_doNotReadRemainingPartsOfFileSinceFrameworkTerminating) {
00639     std::list<unsigned int>::iterator lastItr;
00640     while(m_presentIndexItr != m_orderedIndices.end()) {
00641       //if the last item in the file has no entries then readElement
00642       // will not advance so we have to do it ourselves
00643       lastItr = m_presentIndexItr;
00644       readElements();
00645       if(lastItr == m_presentIndexItr) {
00646         ++m_presentIndexItr;
00647       }
00648     }
00649   }
00650   edm::Service<edm::JobReport> jr;
00651   jr->inputFileClosed(m_jrToken);
00652 }
00653 
00654 void DQMRootSource::readElements() {
00655   edm::Service<DQMStore> store;
00656   RunLumiToRange runLumiRange = m_runlumiToRange[*m_presentIndexItr];
00657   bool shouldContinue = false;
00658   do
00659   {
00660     shouldContinue = false;
00661     if(runLumiRange.m_type == kNoTypesStored) {continue;}
00662     boost::shared_ptr<TreeReaderBase> reader = m_treeReaders[runLumiRange.m_type];
00663     ULong64_t index = runLumiRange.m_firstIndex;
00664     ULong64_t endIndex = runLumiRange.m_lastIndex+1;
00665     for (; index != endIndex; ++index)
00666     {
00667       bool isLumi = runLumiRange.m_lumi !=0;
00668       if (m_shouldReadMEs)
00669         reader->read(index,*store,isLumi);
00670 //       if (isLumi)
00671 //       {
00672 //         std::cout << runLumiRange.m_run << " " << runLumiRange.m_lumi << "  lumi element "<< element->getFullname()<<" "<<index<< " " << runLumiRange.m_type << std::endl;
00673 //         m_lumiElements.insert(element);
00674 //       }
00675 //       else
00676 //       {
00677 //         std::cout << runLumiRange.m_run << " " << runLumiRange.m_lumi << "  run element "<< element->getFullname()<<" "<<index<< " " << runLumiRange.m_type << std::endl;
00678 //         m_runElements.insert(element);
00679 //       }
00680     }
00681     ++m_presentIndexItr;
00682     if (m_presentIndexItr != m_orderedIndices.end())
00683     {
00684       //are there more parts to this same run/lumi?
00685       const RunLumiToRange nextRunLumiRange = m_runlumiToRange[*m_presentIndexItr];
00686       //continue to the next item if that item is either
00687       if ( (nextRunLumiRange.m_run == runLumiRange.m_run) &&
00688           (nextRunLumiRange.m_lumi == runLumiRange.m_lumi) )
00689       {
00690         shouldContinue= true;
00691         runLumiRange = nextRunLumiRange;
00692       }
00693     }
00694   } while(shouldContinue);
00695 }
00696 
00697 void DQMRootSource::readNextItemType()
00698 {
00699   //Do the work of actually figuring out where next to go
00700   RunLumiToRange runLumiRange = m_runlumiToRange[*m_nextIndexItr];
00701   if (m_nextItemType !=edm::InputSource::IsFile)
00702   {
00703     assert (m_nextIndexItr != m_orderedIndices.end());
00704 
00705     if(runLumiRange.m_lumi ==0) {
00706       //std::cout <<"reading run "<<runLumiRange.m_run<<std::endl;
00707       m_runAux.id() = edm::RunID(runLumiRange.m_run);    
00708     } else {
00709       if(m_nextItemType == edm::InputSource::IsRun) {
00710         //std::cout <<" proceeding with dummy run";
00711         m_nextItemType = edm::InputSource::IsLumi;
00712         return;
00713       }
00714       //std::cout <<"reading lumi "<<runLumiRange.m_run<<","<<runLumiRange.m_lumi<<std::endl;
00715       m_lumiAux.id() = edm::LuminosityBlockID(runLumiRange.m_run,runLumiRange.m_lumi);
00716     }
00717     ++m_nextIndexItr;
00718   }
00719   else
00720   {
00721     //NOTE: the following causes the iterator to move to before
00722     //'begin' but that is OK since the first thing in the 'do while'
00723     //loop is to advance the iterator which puts us at the first entry
00724     //in the file
00725     runLumiRange.m_run=0;
00726   }
00727 
00728   bool shouldContinue = false;
00729   do
00730   {
00731     shouldContinue = false;
00732     if (m_nextIndexItr == m_orderedIndices.end())
00733     {
00734       //go to next file
00735       m_nextItemType = edm::InputSource::IsFile;
00736       //std::cout <<"going to next file"<<std::endl;
00737       if(m_fileIndex == m_catalog.fileNames().size()) {
00738         m_nextItemType = edm::InputSource::IsStop;
00739       }       
00740       break;
00741     }
00742     const RunLumiToRange nextRunLumiRange = m_runlumiToRange[*m_nextIndexItr];
00743     //continue to the next item if that item is the same run or lumi as we just did
00744     if( (nextRunLumiRange.m_run == runLumiRange.m_run) && (
00745          nextRunLumiRange.m_lumi == runLumiRange.m_lumi) ) {
00746          shouldContinue= true;
00747          runLumiRange = nextRunLumiRange;
00748          ++m_nextIndexItr;
00749          //std::cout <<"  advancing " <<nextRunLumiRange.m_run<<" "<<nextRunLumiRange.m_lumi<<std::endl;
00750     } 
00751     
00752   } while(shouldContinue);
00753   
00754   if(m_nextIndexItr != m_orderedIndices.end()) {
00755     if(m_runlumiToRange[*m_nextIndexItr].m_lumi == 0 && (m_justOpenedFileSoNeedToGenerateRunTransition || m_lastSeenRun != m_runlumiToRange[*m_nextIndexItr].m_run) ) {
00756       m_nextItemType = edm::InputSource::IsRun;
00757       //std::cout <<"  next is run"<<std::endl;
00758     } else {
00759       if(m_runlumiToRange[*m_nextIndexItr].m_run != m_lastSeenRun || m_justOpenedFileSoNeedToGenerateRunTransition ) {
00760         //we have to create a dummy Run since we switched to a lumi in a new run
00761         //std::cout <<"  next is dummy run "<<m_justOpenedFileSoNeedToGenerateRunTransition<<std::endl;
00762         m_nextItemType = edm::InputSource::IsRun;
00763       } else {
00764         m_nextItemType = edm::InputSource::IsLumi;      
00765       }
00766     }
00767   }
00768 }
00769 
00770 namespace {
00771      std::string const streamerInfo = std::string("StreamerInfo");
00772 }
00773 
00774 void 
00775 DQMRootSource::setupFile(unsigned int iIndex)
00776 {
00777   if(m_file.get() != 0 && iIndex > 0) {
00778     m_file->Close();
00779     logFileAction("  Closed file ", m_catalog.fileNames()[iIndex-1].c_str());
00780   }
00781   logFileAction("  Initiating request to open file ", m_catalog.fileNames()[iIndex].c_str());
00782   m_presentlyOpenFileIndex = iIndex;
00783   try {
00784     m_file = std::auto_ptr<TFile>(TFile::Open(m_catalog.fileNames()[iIndex].c_str()));
00785   } catch(cms::Exception const& e) {
00786     edm::Exception ex(edm::errors::FileOpenError,"",e);
00787     ex.addContext("Opening DQM Root file");
00788     ex <<"\nInput file " << m_catalog.fileNames()[iIndex] << " was not found, could not be opened, or is corrupted.\n";
00789     throw ex;
00790   }
00791   if(not m_file->IsZombie()) {  
00792     logFileAction("  Successfully opened file ", m_catalog.fileNames()[iIndex].c_str());
00793   } else {
00794     edm::Exception ex(edm::errors::FileOpenError);
00795     ex<<"Input file "<<m_catalog.fileNames()[iIndex].c_str() <<" could not be opened.\n";
00796     ex.addContext("Opening DQM Root file");
00797     throw ex;
00798   }
00799   //Check file format version, which is encoded in the Title of the TFile
00800   if(0 != strcmp(m_file->GetTitle(),"1")) {
00801     edm::Exception ex(edm::errors::FileReadError);
00802     ex<<"Input file "<<m_catalog.fileNames()[iIndex].c_str() <<" does not appear to be a DQM Root file.\n";
00803   }
00804   
00805   //Get meta Data
00806   TDirectory* metaDir = m_file->GetDirectory(kMetaDataDirectoryAbsolute);
00807   if(0==metaDir) {
00808     edm::Exception ex(edm::errors::FileReadError);
00809     ex<<"Input file "<<m_catalog.fileNames()[iIndex].c_str() <<" appears to be corrupted since it does not have the proper internal structure.\n"
00810       " Check to see if the file was closed properly.\n";    
00811     ex.addContext("Opening DQM Root file");
00812     throw ex;    
00813   }
00814   TTree* parameterSetTree = dynamic_cast<TTree*>(metaDir->Get(kParameterSetTree));
00815   assert(0!=parameterSetTree);
00816 
00817   edm::pset::Registry* psr = edm::pset::Registry::instance();
00818   assert(0!=psr);
00819   {
00820     std::string blob;
00821     std::string* pBlob = &blob;
00822     parameterSetTree->SetBranchAddress(kParameterSetBranch,&pBlob);
00823     for(unsigned int index = 0; index != parameterSetTree->GetEntries();++index)
00824     {
00825       parameterSetTree->GetEntry(index);
00826       cms::Digest dg(blob);
00827       edm::ParameterSetID psID(dg.digest().toString());
00828       edm::ParameterSet temp(blob,psID);
00829     } 
00830   }
00831 
00832   {
00833     TTree* processHistoryTree = dynamic_cast<TTree*>(metaDir->Get(kProcessHistoryTree));
00834     assert(0!=processHistoryTree);
00835     unsigned int phIndex = 0;
00836     processHistoryTree->SetBranchAddress(kPHIndexBranch,&phIndex);
00837     std::string processName;
00838     std::string* pProcessName = &processName;
00839     processHistoryTree->SetBranchAddress(kProcessConfigurationProcessNameBranch,&pProcessName);
00840     std::string parameterSetIDBlob;
00841     std::string* pParameterSetIDBlob = &parameterSetIDBlob;
00842     processHistoryTree->SetBranchAddress(kProcessConfigurationParameterSetIDBranch,&pParameterSetIDBlob);
00843     std::string releaseVersion;
00844     std::string* pReleaseVersion = &releaseVersion;
00845     processHistoryTree->SetBranchAddress(kProcessConfigurationReleaseVersion,&pReleaseVersion);
00846     std::string passID;
00847     std::string* pPassID = &passID;
00848     processHistoryTree->SetBranchAddress(kProcessConfigurationPassID,&pPassID);
00849 
00850     edm::ProcessConfigurationRegistry* pcr = edm::ProcessConfigurationRegistry::instance();
00851     assert(0!=pcr);
00852     edm::ProcessHistoryRegistry* phr = edm::ProcessHistoryRegistry::instance();
00853     assert(0!=phr);
00854     std::vector<edm::ProcessConfiguration> configs;
00855     configs.reserve(5);
00856     for(unsigned int i=0; i != processHistoryTree->GetEntries(); ++i) {
00857       processHistoryTree->GetEntry(i);
00858       if(phIndex==0) {
00859         if(not configs.empty()) {
00860           edm::ProcessHistory ph(configs);
00861           m_historyIDs.push_back(ph.id());
00862           phr->insertMapped(ph);
00863         }
00864         configs.clear();
00865       }
00866       edm::ParameterSetID psetID(parameterSetIDBlob);
00867       edm::ProcessConfiguration pc(processName, psetID,releaseVersion,passID);
00868       pcr->insertMapped(pc);
00869       configs.push_back(pc);
00870     }
00871     if(not configs.empty()) {
00872       edm::ProcessHistory ph(configs);
00873       m_historyIDs.push_back(ph.id());
00874       phr->insertMapped( ph);
00875       //std::cout <<"inserted "<<ph.id()<<std::endl;
00876     }
00877   }
00878 
00879   //Setup the indices
00880   TTree* indicesTree = dynamic_cast<TTree*>(m_file->Get(kIndicesTree));
00881   assert(0!=indicesTree);
00882 
00883   m_runlumiToRange.clear();
00884   m_runlumiToRange.reserve(indicesTree->GetEntries());
00885   m_orderedIndices.clear();
00886 
00887   RunLumiToRange temp;
00888   indicesTree->SetBranchAddress(kRunBranch,&temp.m_run);
00889   indicesTree->SetBranchAddress(kLumiBranch,&temp.m_lumi);
00890   indicesTree->SetBranchAddress(kBeginTimeBranch,&temp.m_beginTime);
00891   indicesTree->SetBranchAddress(kEndTimeBranch,&temp.m_endTime);
00892   indicesTree->SetBranchAddress(kProcessHistoryIndexBranch,&temp.m_historyIDIndex);
00893   indicesTree->SetBranchAddress(kTypeBranch,&temp.m_type);
00894   indicesTree->SetBranchAddress(kFirstIndex,&temp.m_firstIndex);
00895   indicesTree->SetBranchAddress(kLastIndex,&temp.m_lastIndex);
00896 
00897   //Need to reorder items since if there was a merge done the same Run
00898   //and/or Lumi can appear multiple times but we want to process them
00899   //all at once
00900 
00901   //We use a std::list for m_orderedIndices since inserting into the
00902   //middle of a std::list does not disrupt the iterators to already
00903   //existing entries
00904 
00905   //The Map is used to see if a Run/Lumi pair has appeared before
00906   typedef std::map<std::pair<unsigned int, unsigned int>, std::list<unsigned int>::iterator > RunLumiToLastEntryMap;
00907   RunLumiToLastEntryMap runLumiToLastEntryMap;
00908 
00909   //Need to group all lumis for the same run together and move the run
00910   //entry to the beginning
00911   typedef std::map<unsigned int, std::pair< std::list<unsigned int>::iterator, std::list<unsigned int>::iterator> > RunToFirstLastEntryMap;
00912   RunToFirstLastEntryMap runToFirstLastEntryMap;
00913 
00914   for (Long64_t index = 0; index != indicesTree->GetEntries(); ++index)
00915   {
00916     indicesTree->GetEntry(index);
00917 //     std::cout <<"read r:"<<temp.m_run
00918 //            <<" l:"<<temp.m_lumi
00919 //            <<" b:"<<temp.m_beginTime
00920 //            <<" e:"<<temp.m_endTime
00921 //            <<" fi:" << temp.m_firstIndex
00922 //            <<" li:" << temp.m_lastIndex
00923 //            <<" type:" << temp.m_type << std::endl;
00924     m_runlumiToRange.push_back(temp);
00925 
00926     std::pair<unsigned int, unsigned int> runLumi(temp.m_run,temp.m_lumi);
00927 
00928     RunLumiToLastEntryMap::iterator itFind = runLumiToLastEntryMap.find(runLumi);
00929     if (itFind == runLumiToLastEntryMap.end())
00930     {
00931       //does not already exist
00932       //does the run for this already exist?
00933       std::list<unsigned int>::iterator itLastOfRun = m_orderedIndices.end();
00934       RunToFirstLastEntryMap::iterator itRunFirstLastEntryFind = runToFirstLastEntryMap.find(temp.m_run);
00935       bool needNewEntryInRunFirstLastEntryMap = true;
00936       if (itRunFirstLastEntryFind != runToFirstLastEntryMap.end())
00937       {
00938         needNewEntryInRunFirstLastEntryMap=false;
00939         if (temp.m_lumi!=0)
00940         {
00941           //lumis go to the end
00942           itLastOfRun = itRunFirstLastEntryFind->second.second;
00943           //we want to insert after this one so must advance the iterator
00944           ++itLastOfRun;
00945         }
00946         else
00947         {
00948           //runs go at the beginning
00949           itLastOfRun = itRunFirstLastEntryFind->second.first;
00950         }
00951       }
00952       std::list<unsigned int>::iterator iter = m_orderedIndices.insert(itLastOfRun,index);
00953       runLumiToLastEntryMap[runLumi]=iter;
00954       if (needNewEntryInRunFirstLastEntryMap)
00955         runToFirstLastEntryMap[temp.m_run]=std::make_pair(iter,iter);
00956       else
00957       {
00958         if(temp.m_lumi!=0)
00959         {
00960           //lumis go at end
00961           runToFirstLastEntryMap[temp.m_run].second = iter;
00962         }
00963         else
00964         {
00965           //since we haven't yet seen this run/lumi combination it means we haven't yet seen
00966           // a run so we can put this first
00967           runToFirstLastEntryMap[temp.m_run].first = iter;
00968         }
00969       }
00970     }
00971     else
00972     {
00973       //We need to do a merge since the run/lumi already appeared. Put it after the existing entry
00974       //std::cout <<" found a second instance of "<<runLumi.first<<" "<<runLumi.second<<" at "<<index<<std::endl;
00975       std::list<unsigned int>::iterator itNext = itFind->second;
00976       ++itNext;
00977       std::list<unsigned int>::iterator iter = m_orderedIndices.insert(itNext,index);
00978       RunToFirstLastEntryMap::iterator itRunFirstLastEntryFind = runToFirstLastEntryMap.find(temp.m_run);
00979       if (itRunFirstLastEntryFind->second.second == itFind->second)
00980       {
00981         //if the previous one was the last in the run, we need to update to make this one the last
00982         itRunFirstLastEntryFind->second.second = iter;
00983       }
00984       itFind->second = iter;
00985     }
00986   }
00987   m_nextIndexItr = m_orderedIndices.begin();
00988   m_presentIndexItr = m_orderedIndices.begin();
00989   
00990   if(m_nextIndexItr != m_orderedIndices.end()) {
00991     for( size_t index = 0; index < kNIndicies; ++index) {
00992       m_trees[index] = dynamic_cast<TTree*>(m_file->Get(kTypeNames[index]));
00993       assert(0!=m_trees[index]);
00994       m_treeReaders[index]->setTree(m_trees[index]);
00995     }
00996   }
00997   //After a file open, the framework expects to see a new 'IsRun'
00998   //m_lastSeenRun = 0;
00999   m_justOpenedFileSoNeedToGenerateRunTransition=true;
01000 }
01001 
01002 void
01003 DQMRootSource::logFileAction(char const* msg, char const* fileName) const {
01004   edm::LogAbsolute("fileAction") << std::setprecision(0) << edm::TimeOfDay() << msg << fileName;
01005   edm::FlushMessageLog();
01006 }
01007 
01008 //
01009 // const member functions
01010 //
01011 
01012 //
01013 // static member functions
01014 //
01015 DEFINE_FWK_INPUT_SOURCE(DQMRootSource);