CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_4_5_patch3/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.25 2011/10/23 22:39:49 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 limitsm '"<<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       bool m_justOpenedFileSoNeedToGenerateRunTransition;
00346       bool m_doNotReadRemainingPartsOfFileSinceFrameworkTerminating;
00347       std::set<MonitorElement*> m_lumiElements;
00348       std::set<MonitorElement*> m_runElements;
00349       std::vector<edm::ProcessHistoryID> m_historyIDs;
00350       
00351       edm::JobReport::Token m_jrToken;
00352 };
00353 
00354 //
00355 // constants, enums and typedefs
00356 //
00357 
00358 //
00359 // static data member definitions
00360 //
00361 
00362 void 
00363 DQMRootSource::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
00364   edm::ParameterSetDescription desc;
00365   desc.addUntracked<std::vector<std::string> >("fileNames")
00366     ->setComment("Names of files to be processed.");
00367   desc.addUntracked<std::string>("overrideCatalog",std::string())
00368     ->setComment("An alternate file catalog to use instead of the standard site one.");
00369   descriptions.addDefault(desc);
00370 }
00371 //
00372 // constructors and destructor
00373 //
00374 DQMRootSource::DQMRootSource(edm::ParameterSet const& iPSet, const edm::InputSourceDescription& iDesc):
00375 edm::InputSource(iPSet,iDesc),
00376 m_catalog(iPSet.getUntrackedParameter<std::vector<std::string> >("fileNames"), 
00377           iPSet.getUntrackedParameter<std::string>("overrideCatalog")),
00378 m_nextItemType(edm::InputSource::IsFile),
00379 m_fileIndex(0),
00380 m_presentlyOpenFileIndex(0),
00381 m_trees(kNIndicies,static_cast<TTree*>(0)),
00382 m_treeReaders(kNIndicies,boost::shared_ptr<TreeReaderBase>()),
00383 m_lastSeenRun(0),
00384 m_justOpenedFileSoNeedToGenerateRunTransition(false),
00385 m_doNotReadRemainingPartsOfFileSinceFrameworkTerminating(false)
00386 {
00387   if(m_fileIndex ==m_catalog.fileNames().size()) {
00388     m_nextItemType=edm::InputSource::IsStop;
00389   } else{
00390     m_treeReaders[kIntIndex].reset(new TreeSimpleReader<Long64_t>());
00391     m_treeReaders[kFloatIndex].reset(new TreeSimpleReader<double>());
00392     m_treeReaders[kStringIndex].reset(new TreeObjectReader<std::string>());
00393     m_treeReaders[kTH1FIndex].reset(new TreeObjectReader<TH1F>());
00394     m_treeReaders[kTH1SIndex].reset(new TreeObjectReader<TH1S>());
00395     m_treeReaders[kTH1DIndex].reset(new TreeObjectReader<TH1D>());
00396     m_treeReaders[kTH2FIndex].reset(new TreeObjectReader<TH2F>());
00397     m_treeReaders[kTH2SIndex].reset(new TreeObjectReader<TH2S>());
00398     m_treeReaders[kTH2DIndex].reset(new TreeObjectReader<TH2D>());
00399     m_treeReaders[kTH3FIndex].reset(new TreeObjectReader<TH3F>());
00400     m_treeReaders[kTProfileIndex].reset(new TreeObjectReader<TProfile>());
00401     m_treeReaders[kTProfile2DIndex].reset(new TreeObjectReader<TProfile2D>());
00402   }
00403   
00404 }
00405 
00406 // DQMRootSource::DQMRootSource(const DQMRootSource& rhs)
00407 // {
00408 //    // do actual copying here;
00409 // }
00410 
00411 DQMRootSource::~DQMRootSource()
00412 {
00413   if(m_file.get() != 0 && m_file->IsOpen()) {
00414     m_file->Close();
00415     logFileAction("  Closed file ", m_catalog.fileNames()[m_presentlyOpenFileIndex].c_str());
00416   }
00417 }
00418 
00419 //
00420 // assignment operators
00421 //
00422 // const DQMRootSource& DQMRootSource::operator=(const DQMRootSource& rhs)
00423 // {
00424 //   //An exception safe implementation is
00425 //   DQMRootSource temp(rhs);
00426 //   swap(rhs);
00427 //
00428 //   return *this;
00429 // }
00430 
00431 //
00432 // member functions
00433 //
00434 namespace {
00435   struct no_deleter {
00436     void operator()(void*) {}
00437   };
00438 }
00439 
00440 edm::EventPrincipal*
00441 DQMRootSource::readEvent_() 
00442 {
00443   return 0;
00444 }
00445 
00446 edm::InputSource::ItemType 
00447 DQMRootSource::getNextItemType()
00448 {
00449   //std::cout <<"getNextItemType "<<m_nextItemType<<std::endl;
00450   return m_nextItemType;
00451 }
00452 boost::shared_ptr<edm::RunAuxiliary> 
00453 DQMRootSource::readRunAuxiliary_()
00454 {
00455   //std::cout <<"readRunAuxiliary_"<<std::endl;
00456   assert(m_nextIndexItr != m_orderedIndices.end());
00457   unsigned int index = *m_nextIndexItr;
00458   RunLumiToRange runLumiRange = m_runlumiToRange[index];
00459   //NOTE: this could be a lumi instead of the actual run. We need to find the time for the run
00460   // so we will scan forward
00461   while(runLumiRange.m_lumi !=0 && ++index<m_runlumiToRange.size()) {
00462     const RunLumiToRange& next = m_runlumiToRange[index];
00463     if(runLumiRange.m_run == next.m_run) {
00464       runLumiRange = next;
00465     } else {
00466       break;
00467     }
00468   }
00469 
00470   //NOTE: the setBeginTime and setEndTime functions of RunAuxiliary only work if the previous value was invalid
00471   // therefore we must copy
00472   m_runAux = edm::RunAuxiliary(runLumiRange.m_run,edm::Timestamp(runLumiRange.m_beginTime),edm::Timestamp(runLumiRange.m_endTime));
00473   assert(m_historyIDs.size() > runLumiRange.m_historyIDIndex);
00474   //std::cout <<"readRunAuxiliary_ "<<m_historyIDs[runLumiRange.m_historyIDIndex]<<std::endl;
00475   m_runAux.setProcessHistoryID(m_historyIDs[runLumiRange.m_historyIDIndex]);    
00476   return boost::shared_ptr<edm::RunAuxiliary>( new edm::RunAuxiliary(m_runAux) );
00477 }
00478 boost::shared_ptr<edm::LuminosityBlockAuxiliary> 
00479 DQMRootSource::readLuminosityBlockAuxiliary_()
00480 {
00481   //std::cout <<"readLuminosityBlockAuxiliary_"<<std::endl;
00482   assert(m_nextIndexItr != m_orderedIndices.end());
00483   const RunLumiToRange runLumiRange = m_runlumiToRange[*m_nextIndexItr];
00484   m_lumiAux = edm::LuminosityBlockAuxiliary(edm::LuminosityBlockID(runLumiRange.m_run,runLumiRange.m_lumi),
00485                                             edm::Timestamp(runLumiRange.m_beginTime),
00486                                             edm::Timestamp(runLumiRange.m_endTime));
00487   assert(m_historyIDs.size() > runLumiRange.m_historyIDIndex);
00488   //std::cout <<"lumi "<<m_lumiAux.beginTime().value()<<" "<<runLumiRange.m_beginTime<<std::endl;
00489   m_lumiAux.setProcessHistoryID(m_historyIDs[runLumiRange.m_historyIDIndex]);    
00490   
00491   return boost::shared_ptr<edm::LuminosityBlockAuxiliary>(new edm::LuminosityBlockAuxiliary(m_lumiAux));
00492 }
00493 boost::shared_ptr<edm::RunPrincipal> 
00494 DQMRootSource::readRun_(boost::shared_ptr<edm::RunPrincipal> rpCache) 
00495 {
00496   m_justOpenedFileSoNeedToGenerateRunTransition = false;
00497   unsigned int runID =rpCache->id().run();
00498   unsigned int lastRunID = m_lastSeenRun;
00499   m_lastSeenRun = runID;
00500   readNextItemType();
00501   //std::cout <<"readRun_"<<std::endl;
00502   
00503   //NOTE: need to reset all run elements at this point
00504   if(lastRunID != runID) {
00505     for(std::set<MonitorElement*>::iterator it = m_runElements.begin(), itEnd = m_runElements.end();
00506         it != itEnd;
00507         ++it) {
00508           //std::cout <<"RESETTING "<<(*it)->getName()<<std::endl;
00509           (*it)->Reset();        
00510     }
00511   }
00512 
00513   if(m_presentIndexItr != m_orderedIndices.end()) {
00514     RunLumiToRange runLumiRange = m_runlumiToRange[*m_presentIndexItr];
00515     //NOTE: it is possible to have an Run when all we have stored is lumis
00516     if(runLumiRange.m_lumi == 0 && 
00517        runLumiRange.m_run == rpCache->id().run()) {
00518       readElements();
00519     }
00520   }
00521   
00522   edm::Service<edm::JobReport> jr;
00523   jr->reportInputRunNumber(rpCache->id().run());
00524 
00525   rpCache->fillRunPrincipal();
00526   return rpCache;
00527 }
00528 boost::shared_ptr<edm::LuminosityBlockPrincipal> 
00529 DQMRootSource::readLuminosityBlock_( boost::shared_ptr<edm::LuminosityBlockPrincipal> lbCache) 
00530 {
00531   //NOTE: need to reset all lumi block elements at this point
00532   for(std::set<MonitorElement*>::iterator it = m_lumiElements.begin(), itEnd = m_lumiElements.end();
00533       it != itEnd;
00534       ++it) {
00535         //std::cout <<"RESETTING "<<(*it)->getName()<<std::endl;      
00536       (*it)->Reset();
00537   }
00538   readNextItemType();
00539   //std::cout <<"readLuminosityBlock_"<<std::endl;
00540   RunLumiToRange runLumiRange = m_runlumiToRange[*m_presentIndexItr];
00541   if(runLumiRange.m_run == lbCache->id().run() &&
00542      runLumiRange.m_lumi == lbCache->id().luminosityBlock()) {
00543        readElements();
00544   }
00545   
00546   edm::Service<edm::JobReport> jr;
00547   jr->reportInputLumiSection(lbCache->id().run(),lbCache->id().luminosityBlock());
00548 
00549   lbCache->fillLuminosityBlockPrincipal();
00550   return lbCache;
00551 }
00552 
00553 boost::shared_ptr<edm::FileBlock>
00554 DQMRootSource::readFile_() {
00555   //std::cout <<"readFile_"<<std::endl;
00556   setupFile(m_fileIndex);
00557   ++m_fileIndex;
00558   readNextItemType();
00559 
00560   edm::Service<edm::JobReport> jr;
00561   m_jrToken = jr->inputFileOpened(m_catalog.fileNames()[m_fileIndex-1],
00562                                   m_catalog.logicalFileNames()[m_fileIndex-1],
00563                                   std::string(),
00564                                   std::string(),
00565                                   "DQMRootSource",
00566                                   "source",
00567                                   m_file->GetUUID().AsString(),//edm::createGlobalIdentifier(),
00568                                   std::vector<std::string>()
00569                                   );
00570   
00571   m_doNotReadRemainingPartsOfFileSinceFrameworkTerminating = false;
00572   return boost::shared_ptr<edm::FileBlock>(new edm::FileBlock);
00573 }
00574 
00575 
00576 void 
00577 DQMRootSource::endLuminosityBlock(edm::LuminosityBlock& iLumi) {
00578   //std::cout <<"DQMRootSource::endLumi"<<std::endl;
00579 }
00580 void 
00581 DQMRootSource::endRun(edm::Run& iRun){
00582   //std::cout <<"DQMRootSource::endRun"<<std::endl;
00583   //NOTE: the framework will call endRun before closeFile in the case
00584   // where the frameworks is terminating
00585   m_doNotReadRemainingPartsOfFileSinceFrameworkTerminating=true;
00586 }
00587 
00588 
00589 void
00590 DQMRootSource::closeFile_() {
00591   //std::cout <<"closeFile_"<<std::endl;
00592   //when going from one file to the next the framework does not call
00593   // 'endRun' or 'endLumi' until it looks to see if the other file contains
00594   // a new run or lumi. If the other file doesn't then  
00595   if(not m_doNotReadRemainingPartsOfFileSinceFrameworkTerminating) {
00596     std::list<unsigned int>::iterator lastItr;
00597     while(m_presentIndexItr != m_orderedIndices.end()) {
00598       //if the last item in the file has no entries then readElement
00599       // will not advance so we have to do it ourselves
00600       lastItr = m_presentIndexItr;
00601       readElements();
00602       if(lastItr == m_presentIndexItr) {
00603         ++m_presentIndexItr;
00604       }
00605     }
00606   }
00607   edm::Service<edm::JobReport> jr;
00608   jr->inputFileClosed(m_jrToken);
00609 }
00610 
00611 void 
00612 DQMRootSource::readElements() {
00613   edm::Service<DQMStore> store;
00614   RunLumiToRange runLumiRange = m_runlumiToRange[*m_presentIndexItr];
00615   bool shouldContinue = false;
00616   do {
00617     shouldContinue = false;
00618     if(runLumiRange.m_type == kNoTypesStored) {continue;}
00619     boost::shared_ptr<TreeReaderBase> reader = m_treeReaders[runLumiRange.m_type];
00620     for(ULong64_t index = runLumiRange.m_firstIndex, endIndex=runLumiRange.m_lastIndex+1;
00621     index != endIndex;
00622     ++index) {
00623       bool isLumi = runLumiRange.m_lumi !=0;
00624       MonitorElement* element = reader->read(index,*store,isLumi);
00625       if(isLumi) {
00626         //std::cout <<"  lumi element "<< element->getName()<<" "<<index<<std::endl;
00627         m_lumiElements.insert(element);
00628       } else {
00629         //std::cout <<"  run element "<< element->getName()<<" "<<index<<std::endl;
00630         m_runElements.insert(element);
00631       }
00632     }
00633     ++m_presentIndexItr;
00634     if(m_presentIndexItr != m_orderedIndices.end()) {
00635       //are there more parts to this same run/lumi?
00636       const RunLumiToRange nextRunLumiRange = m_runlumiToRange[*m_presentIndexItr];
00637       //continue to the next item if that item is either
00638       if( (nextRunLumiRange.m_run == runLumiRange.m_run) && 
00639           (nextRunLumiRange.m_lumi == runLumiRange.m_lumi) ) {
00640            shouldContinue= true;
00641            runLumiRange = nextRunLumiRange;
00642       } 
00643     }
00644   }while(shouldContinue);
00645 }
00646 
00647 
00648 void 
00649 DQMRootSource::readNextItemType()
00650 {
00651   //Do the work of actually figuring out where next to go
00652   RunLumiToRange runLumiRange = m_runlumiToRange[*m_nextIndexItr];
00653   if(m_nextItemType !=edm::InputSource::IsFile) {
00654     assert(m_nextIndexItr != m_orderedIndices.end());
00655 
00656     if(runLumiRange.m_lumi ==0) {
00657       //std::cout <<"reading run "<<runLumiRange.m_run<<std::endl;
00658       m_runAux.id() = edm::RunID(runLumiRange.m_run);    
00659     } else {
00660       if(m_nextItemType == edm::InputSource::IsRun) {
00661         //std::cout <<" proceeding with dummy run";
00662         m_nextItemType = edm::InputSource::IsLumi;
00663         return;
00664       }
00665       //std::cout <<"reading lumi "<<runLumiRange.m_run<<","<<runLumiRange.m_lumi<<std::endl;
00666       m_lumiAux.id() = edm::LuminosityBlockID(runLumiRange.m_run,runLumiRange.m_lumi);
00667     }
00668     ++m_nextIndexItr;
00669   } else {
00670     //NOTE: the following causes the iterator to move to before 'begin' but that is OK
00671     // since the first thing in the 'do while' loop is to advance the iterator which puts
00672     // us at the first entry in the file
00673     runLumiRange.m_run=0;
00674   } 
00675   
00676   bool shouldContinue = false;
00677   do {
00678     shouldContinue = false;
00679     if(m_nextIndexItr == m_orderedIndices.end()) {
00680       //go to next file
00681       m_nextItemType = edm::InputSource::IsFile;
00682       //std::cout <<"going to next file"<<std::endl;
00683       if(m_fileIndex == m_catalog.fileNames().size()) {
00684         m_nextItemType = edm::InputSource::IsStop;
00685       }       
00686       break;
00687     }
00688     const RunLumiToRange nextRunLumiRange = m_runlumiToRange[*m_nextIndexItr];
00689     //continue to the next item if that item is the same run or lumi as we just did
00690     if( (nextRunLumiRange.m_run == runLumiRange.m_run) && (
00691          nextRunLumiRange.m_lumi == runLumiRange.m_lumi) ) {
00692          shouldContinue= true;
00693          runLumiRange = nextRunLumiRange;
00694          ++m_nextIndexItr;
00695          //std::cout <<"  advancing " <<nextRunLumiRange.m_run<<" "<<nextRunLumiRange.m_lumi<<std::endl;
00696     } 
00697     
00698   } while(shouldContinue);
00699   
00700   if(m_nextIndexItr != m_orderedIndices.end()) {
00701     if(m_runlumiToRange[*m_nextIndexItr].m_lumi == 0 && (m_justOpenedFileSoNeedToGenerateRunTransition || m_lastSeenRun != m_runlumiToRange[*m_nextIndexItr].m_run) ) {
00702       m_nextItemType = edm::InputSource::IsRun;
00703       //std::cout <<"  next is run"<<std::endl;
00704     } else {
00705       if(m_runlumiToRange[*m_nextIndexItr].m_run != m_lastSeenRun || m_justOpenedFileSoNeedToGenerateRunTransition ) {
00706         //we have to create a dummy Run since we switched to a lumi in a new run
00707         //std::cout <<"  next is dummy run "<<m_justOpenedFileSoNeedToGenerateRunTransition<<std::endl;
00708         m_nextItemType = edm::InputSource::IsRun;
00709       } else {
00710         m_nextItemType = edm::InputSource::IsLumi;      
00711       }
00712     }
00713   }
00714 }
00715 
00716 namespace {
00717      std::string const streamerInfo = std::string("StreamerInfo");
00718 }
00719 
00720 void 
00721 DQMRootSource::setupFile(unsigned int iIndex)
00722 {
00723   if(m_file.get() != 0 && iIndex > 0) {
00724     m_file->Close();
00725     logFileAction("  Closed file ", m_catalog.fileNames()[iIndex-1].c_str());
00726   }
00727   logFileAction("  Initiating request to open file ", m_catalog.fileNames()[iIndex].c_str());
00728   m_presentlyOpenFileIndex = iIndex;
00729   try {
00730     m_file = std::auto_ptr<TFile>(TFile::Open(m_catalog.fileNames()[iIndex].c_str()));
00731   } catch(cms::Exception const& e) {
00732     edm::Exception ex(edm::errors::FileOpenError,"",e);
00733     ex.addContext("Opening DQM Root file");
00734     ex <<"Input file " << m_catalog.fileNames()[iIndex] << " was not found, could not be opened, or is corrupted.\n";
00735   }
00736   if(not m_file->IsZombie()) {  
00737     logFileAction("  Successfully opened file ", m_catalog.fileNames()[iIndex].c_str());
00738   } else {
00739     throw edm::Exception(edm::errors::FileReadError)<<"Input file "<<m_catalog.fileNames()[iIndex].c_str() <<" could not be opened.\n";
00740   }
00741   //Check file format version, which is encoded in the Title of the TFile
00742   if(0 != strcmp(m_file->GetTitle(),"1")) {
00743     throw edm::Exception(edm::errors::FileReadError)<<"Input file "<<m_catalog.fileNames()[iIndex].c_str() <<" does not appear to be a DQM Root file.\n";
00744   }
00745   
00746   //Get meta Data
00747   TDirectory* metaDir = m_file->GetDirectory(kMetaDataDirectoryAbsolute);
00748   if(0==metaDir) {
00749     throw edm::Exception(edm::errors::FileReadError)<<"Input file "<<m_catalog.fileNames()[iIndex].c_str() <<" appears to be corrupted since it does not have the proper internal structure.\n"
00750       " Check to see if the file was closed properly.\n";    
00751   }
00752   TTree* parameterSetTree = dynamic_cast<TTree*>(metaDir->Get(kParameterSetTree));
00753   assert(0!=parameterSetTree);
00754   
00755   edm::pset::Registry* psr = edm::pset::Registry::instance();
00756   assert(0!=psr);
00757   {
00758     std::string blob;
00759     std::string* pBlob = &blob;
00760     parameterSetTree->SetBranchAddress(kParameterSetBranch,&pBlob);
00761     for(unsigned int index = 0; index != parameterSetTree->GetEntries();++index) {
00762       parameterSetTree->GetEntry(index);
00763       cms::Digest dg(blob);
00764       edm::ParameterSetID psID(dg.digest().toString());
00765       edm::ParameterSet temp(blob,psID);
00766     } 
00767   }
00768 
00769   {
00770     TTree* processHistoryTree = dynamic_cast<TTree*>(metaDir->Get(kProcessHistoryTree));
00771     assert(0!=processHistoryTree);
00772     unsigned int phIndex = 0;
00773     processHistoryTree->SetBranchAddress(kPHIndexBranch,&phIndex);
00774     std::string processName;
00775     std::string* pProcessName = &processName;
00776     processHistoryTree->SetBranchAddress(kProcessConfigurationProcessNameBranch,&pProcessName);
00777     std::string parameterSetIDBlob;
00778     std::string* pParameterSetIDBlob = &parameterSetIDBlob;
00779     processHistoryTree->SetBranchAddress(kProcessConfigurationParameterSetIDBranch,&pParameterSetIDBlob);
00780     std::string releaseVersion;
00781     std::string* pReleaseVersion = &releaseVersion;
00782     processHistoryTree->SetBranchAddress(kProcessConfigurationReleaseVersion,&pReleaseVersion);
00783     std::string passID;
00784     std::string* pPassID = &passID;
00785     processHistoryTree->SetBranchAddress(kProcessConfigurationPassID,&pPassID);
00786 
00787     edm::ProcessConfigurationRegistry* pcr = edm::ProcessConfigurationRegistry::instance();
00788     assert(0!=pcr);
00789     edm::ProcessHistoryRegistry* phr = edm::ProcessHistoryRegistry::instance();
00790     assert(0!=phr);
00791     std::vector<edm::ProcessConfiguration> configs;
00792     configs.reserve(5);
00793     for(unsigned int i=0; i != processHistoryTree->GetEntries(); ++i) {
00794       processHistoryTree->GetEntry();
00795       if(phIndex==0) {
00796         if(not configs.empty()) {
00797           edm::ProcessHistory ph(configs);
00798           m_historyIDs.push_back(ph.id());
00799           phr->insertMapped(ph);
00800         }
00801         configs.clear();
00802       }
00803       edm::ParameterSetID psetID(parameterSetIDBlob);
00804       edm::ProcessConfiguration pc(processName, psetID,releaseVersion,passID);
00805       pcr->insertMapped(pc);
00806       configs.push_back(pc);
00807     }
00808     if(not configs.empty()) {
00809       edm::ProcessHistory ph(configs);
00810       m_historyIDs.push_back(ph.id());
00811       phr->insertMapped( ph);
00812       //std::cout <<"inserted "<<ph.id()<<std::endl;
00813     }
00814   }
00815   
00816   //Setup the indices
00817   TTree* indicesTree = dynamic_cast<TTree*>(m_file->Get(kIndicesTree));
00818   assert(0!=indicesTree);
00819   
00820   m_runlumiToRange.clear();
00821   m_runlumiToRange.reserve(indicesTree->GetEntries());
00822   m_orderedIndices.clear();
00823 
00824   RunLumiToRange temp;
00825   indicesTree->SetBranchAddress(kRunBranch,&temp.m_run);
00826   indicesTree->SetBranchAddress(kLumiBranch,&temp.m_lumi);
00827   indicesTree->SetBranchAddress(kBeginTimeBranch,&temp.m_beginTime);
00828   indicesTree->SetBranchAddress(kEndTimeBranch,&temp.m_endTime);
00829   indicesTree->SetBranchAddress(kProcessHistoryIndexBranch,&temp.m_historyIDIndex);
00830   indicesTree->SetBranchAddress(kTypeBranch,&temp.m_type);
00831   indicesTree->SetBranchAddress(kFirstIndex,&temp.m_firstIndex);
00832   indicesTree->SetBranchAddress(kLastIndex,&temp.m_lastIndex);
00833 
00834   //Need to reorder items since if there was a merge done the same  Run and/or Lumi can appear multiple times
00835   // but we want to process them all at once
00836   
00837   //We use a std::list for m_orderedIndices since inserting into the middle of a std::list does not 
00838   // disrupt the iterators to already existing entries
00839   
00840   //The Map is used to see if a Run/Lumi pair has appeared before
00841   typedef std::map<std::pair<unsigned int, unsigned int>, std::list<unsigned int>::iterator > RunLumiToLastEntryMap;
00842   RunLumiToLastEntryMap runLumiToLastEntryMap;
00843   
00844   //Need to group all lumis for the same run together and move the run entry to the beginning
00845   typedef std::map<unsigned int, std::pair<std::list<unsigned int>::iterator,std::list<unsigned int>::iterator> > RunToFirstLastEntryMap;
00846   RunToFirstLastEntryMap runToFirstLastEntryMap;
00847   
00848   for(Long64_t index = 0; index != indicesTree->GetEntries();++index) {
00849     indicesTree->GetEntry(index);
00850     //std::cout <<"read r:"<<temp.m_run<<" l:"<<temp.m_lumi<<" b:"<<temp.m_beginTime<<" e:"<<temp.m_endTime<<std::endl;
00851     m_runlumiToRange.push_back(temp);
00852     
00853     std::pair<unsigned int, unsigned int> runLumi(temp.m_run,temp.m_lumi);
00854     
00855     RunLumiToLastEntryMap::iterator itFind = runLumiToLastEntryMap.find(runLumi);
00856     if(itFind == runLumiToLastEntryMap.end()) {
00857       //does not already exist
00858 
00859       //does the run for this already exist?
00860       std::list<unsigned int>::iterator itLastOfRun = m_orderedIndices.end();
00861       RunToFirstLastEntryMap::iterator itRunFirstLastEntryFind = runToFirstLastEntryMap.find(temp.m_run);
00862       bool needNewEntryInRunFirstLastEntryMap = true;
00863       if(itRunFirstLastEntryFind != runToFirstLastEntryMap.end()) {
00864         needNewEntryInRunFirstLastEntryMap=false;
00865         if(temp.m_lumi!=0) {
00866           //lumis go to the end
00867           itLastOfRun = itRunFirstLastEntryFind->second.second;
00868           //we want to insert after this one so must advanced the iterator
00869           ++itLastOfRun;
00870         } else {
00871           //runs go at the beginning
00872           itLastOfRun = itRunFirstLastEntryFind->second.first;
00873         }
00874       } 
00875       
00876       std::list<unsigned int>::iterator iter = m_orderedIndices.insert(itLastOfRun,index);
00877       runLumiToLastEntryMap[runLumi]=iter;
00878       if(needNewEntryInRunFirstLastEntryMap) {
00879         runToFirstLastEntryMap[temp.m_run]=std::make_pair(iter,iter);
00880       } else {
00881         if(temp.m_lumi!=0) {
00882           //lumis go at end
00883           runToFirstLastEntryMap[temp.m_run].second = iter;
00884         } else {
00885           //since we haven't yet seen this run/lumi combination it means we haven't yet seen
00886           // a run so we can put this first
00887           runToFirstLastEntryMap[temp.m_run].first = iter;
00888         }
00889       }
00890     } else {
00891       //We need to do a merge since the run/lumi already appeared. Put it after the existing entry
00892       //std::cout <<" found a second instance of "<<runLumi.first<<" "<<runLumi.second<<" at "<<index<<std::endl;
00893       std::list<unsigned int>::iterator itNext = itFind->second;
00894       ++itNext;
00895       std::list<unsigned int>::iterator iter = m_orderedIndices.insert(itNext,index);
00896       RunToFirstLastEntryMap::iterator itRunFirstLastEntryFind = runToFirstLastEntryMap.find(temp.m_run);
00897       if(itRunFirstLastEntryFind->second.second == itFind->second) {
00898         //if the previous one was the last in the run, we need to update to make this one the last
00899         itRunFirstLastEntryFind->second.second = iter;
00900       }
00901       itFind->second = iter;
00902     }
00903   }
00904   m_nextIndexItr = m_orderedIndices.begin();
00905   m_presentIndexItr = m_orderedIndices.begin();
00906   
00907   if(m_nextIndexItr != m_orderedIndices.end()) {
00908     for( size_t index = 0; index < kNIndicies; ++index) {
00909       m_trees[index] = dynamic_cast<TTree*>(m_file->Get(kTypeNames[index]));
00910       assert(0!=m_trees[index]);
00911       m_treeReaders[index]->setTree(m_trees[index]);
00912     }
00913   }
00914   //After a file open, the framework expects to see a new 'IsRun'
00915   //m_lastSeenRun = 0;
00916   m_justOpenedFileSoNeedToGenerateRunTransition=true;
00917 }
00918 
00919 void
00920 DQMRootSource::logFileAction(char const* msg, char const* fileName) const {
00921   edm::LogAbsolute("fileAction") << std::setprecision(0) << edm::TimeOfDay() << msg << fileName;
00922   edm::FlushMessageLog();
00923 }
00924 
00925 //
00926 // const member functions
00927 //
00928 
00929 //
00930 // static member functions
00931 //
00932 DEFINE_FWK_INPUT_SOURCE(DQMRootSource);