CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch12/src/IOPool/Output/src/RootOutputFile.cc

Go to the documentation of this file.
00001 
00002 #include "IOPool/Output/src/RootOutputFile.h"
00003 
00004 #include "FWCore/Utilities/interface/GlobalIdentifier.h"
00005 
00006 #include "DataFormats/Provenance/interface/EventAuxiliary.h"
00007 #include "FWCore/Version/interface/GetFileFormatVersion.h"
00008 #include "DataFormats/Provenance/interface/FileFormatVersion.h"
00009 #include "FWCore/Utilities/interface/EDMException.h"
00010 #include "FWCore/Utilities/interface/Algorithms.h"
00011 #include "FWCore/Utilities/interface/Digest.h"
00012 #include "FWCore/Framework/interface/FileBlock.h"
00013 #include "FWCore/Framework/interface/EventPrincipal.h"
00014 #include "FWCore/Framework/interface/LuminosityBlockPrincipal.h"
00015 #include "FWCore/Framework/interface/RunPrincipal.h"
00016 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00017 #include "DataFormats/Common/interface/OutputHandle.h"
00018 #include "DataFormats/Provenance/interface/BranchChildren.h"
00019 #include "DataFormats/Provenance/interface/BranchIDList.h"
00020 #include "DataFormats/Provenance/interface/Parentage.h"
00021 #include "DataFormats/Provenance/interface/ParentageRegistry.h"
00022 #include "DataFormats/Provenance/interface/EventID.h"
00023 #include "DataFormats/Provenance/interface/ParameterSetBlob.h"
00024 #include "DataFormats/Provenance/interface/ParameterSetID.h"
00025 #include "DataFormats/Provenance/interface/ProcessHistoryRegistry.h"
00026 #include "DataFormats/Provenance/interface/ProcessHistoryID.h"
00027 #include "DataFormats/Provenance/interface/ProductRegistry.h"
00028 #include "DataFormats/Provenance/interface/BranchIDListRegistry.h"
00029 #include "FWCore/Framework/interface/ConstProductRegistry.h"
00030 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00031 #include "FWCore/ParameterSet/interface/Registry.h"
00032 #include "FWCore/ServiceRegistry/interface/Service.h"
00033 
00034 #include "TROOT.h"
00035 #include "TTree.h"
00036 #include "TFile.h"
00037 #include "TClass.h"
00038 #include "Rtypes.h"
00039 
00040 #include <algorithm>
00041 #include <iomanip>
00042 #include <sstream>
00043 
00044 
00045 namespace edm {
00046 
00047   namespace {
00048     bool
00049     sorterForJobReportHash(BranchDescription const* lh, BranchDescription const* rh) {
00050       return
00051         lh->fullClassName() < rh->fullClassName() ? true :
00052         lh->fullClassName() > rh->fullClassName() ? false :
00053         lh->moduleLabel() < rh->moduleLabel() ? true :
00054         lh->moduleLabel() > rh->moduleLabel() ? false :
00055         lh->productInstanceName() < rh->productInstanceName() ? true :
00056         lh->productInstanceName() > rh->productInstanceName() ? false :
00057         lh->processName() < rh->processName() ? true :
00058         false;
00059     }
00060   }
00061 
00062   RootOutputFile::RootOutputFile(PoolOutputModule* om, std::string const& fileName, std::string const& logicalFileName) :
00063       file_(fileName),
00064       logicalFile_(logicalFileName),
00065       reportToken_(0),
00066       om_(om),
00067       whyNotFastClonable_(om_->whyNotFastClonable()),
00068       canFastCloneAux_(!om_->hasNewlyDroppedBranch()[InEvent]),
00069       filePtr_(TFile::Open(file_.c_str(), "recreate", "", om_->compressionLevel())),
00070       fid_(),
00071       eventEntryNumber_(0LL),
00072       lumiEntryNumber_(0LL),
00073       runEntryNumber_(0LL),
00074       indexIntoFile_(),
00075       metaDataTree_(0),
00076       parameterSetsTree_(0),
00077       parentageTree_(0),
00078       lumiAux_(),
00079       runAux_(),
00080       pEventAux_(0),
00081       pLumiAux_(&lumiAux_),
00082       pRunAux_(&runAux_),
00083       eventEntryInfoVector_(),
00084       lumiEntryInfoVector_(),
00085       runEntryInfoVector_(),
00086       pEventEntryInfoVector_(&eventEntryInfoVector_),
00087       pLumiEntryInfoVector_(&lumiEntryInfoVector_),
00088       pRunEntryInfoVector_(&runEntryInfoVector_),
00089       pBranchListIndexes_(0),
00090       pEventSelectionIDs_(0),
00091       eventTree_(filePtr_, InEvent, om_->basketSize(), om_->splitLevel(), om_->treeMaxVirtualSize()),
00092       lumiTree_(filePtr_, InLumi, om_->basketSize(), om_->splitLevel(), om_->treeMaxVirtualSize()),
00093       runTree_(filePtr_, InRun, om_->basketSize(), om_->splitLevel(), om_->treeMaxVirtualSize()),
00094       treePointers_(),
00095       dataTypeReported_(false),
00096       parentageIDs_(),
00097       branchesWithStoredHistory_() {
00098 
00099     if (-1 != om->eventAutoFlushSize()) {
00100       eventTree_.setAutoFlush(-1*om->eventAutoFlushSize());
00101     }
00102     eventTree_.addAuxiliary<EventAuxiliary>(BranchTypeToAuxiliaryBranchName(InEvent),
00103                                             pEventAux_, om_->auxItems()[InEvent].basketSize_);
00104     eventTree_.addAuxiliary<ProductProvenanceVector>(BranchTypeToBranchEntryInfoBranchName(InEvent),
00105                                                      pEventEntryInfoVector_, om_->auxItems()[InEvent].basketSize_);
00106     eventTree_.addAuxiliary<EventSelectionIDVector>(poolNames::eventSelectionsBranchName(),
00107                                                     pEventSelectionIDs_, om_->auxItems()[InEvent].basketSize_);
00108     eventTree_.addAuxiliary<BranchListIndexes>(poolNames::branchListIndexesBranchName(),
00109                                                pBranchListIndexes_, om_->auxItems()[InEvent].basketSize_);
00110 
00111     lumiTree_.addAuxiliary<LuminosityBlockAuxiliary>(BranchTypeToAuxiliaryBranchName(InLumi),
00112                                                      pLumiAux_, om_->auxItems()[InLumi].basketSize_);
00113     lumiTree_.addAuxiliary<ProductProvenanceVector>(BranchTypeToBranchEntryInfoBranchName(InLumi),
00114                                                     pLumiEntryInfoVector_, om_->auxItems()[InLumi].basketSize_);
00115 
00116     runTree_.addAuxiliary<RunAuxiliary>(BranchTypeToAuxiliaryBranchName(InRun),
00117                                         pRunAux_, om_->auxItems()[InRun].basketSize_);
00118     runTree_.addAuxiliary<ProductProvenanceVector>(BranchTypeToBranchEntryInfoBranchName(InRun),
00119                                                    pRunEntryInfoVector_, om_->auxItems()[InRun].basketSize_);
00120 
00121     treePointers_[InEvent] = &eventTree_;
00122     treePointers_[InLumi]  = &lumiTree_;
00123     treePointers_[InRun]   = &runTree_;
00124 
00125     for(int i = InEvent; i < NumBranchTypes; ++i) {
00126       BranchType branchType = static_cast<BranchType>(i);
00127       RootOutputTree *theTree = treePointers_[branchType];
00128       for(OutputItemList::const_iterator it = om_->selectedOutputItemList()[branchType].begin(),
00129           itEnd = om_->selectedOutputItemList()[branchType].end();
00130           it != itEnd; ++it) {
00131         BranchDescription const& desc = *it->branchDescription_;
00132         desc.init();
00133         theTree->addBranch(desc.branchName(),
00134                            desc.wrappedName(),
00135                            it->product_,
00136                            it->splitLevel_,
00137                            it->basketSize_,
00138                            it->branchDescription_->produced());
00139         //make sure we always store product registry info for all branches we create
00140         branchesWithStoredHistory_.insert(it->branchID());
00141       }
00142     }
00143     // Don't split metadata tree or event description tree
00144     metaDataTree_         = RootOutputTree::makeTTree(filePtr_.get(), poolNames::metaDataTreeName(), 0);
00145     parentageTree_ = RootOutputTree::makeTTree(filePtr_.get(), poolNames::parentageTreeName(), 0);
00146     parameterSetsTree_    = RootOutputTree::makeTTree(filePtr_.get(), poolNames::parameterSetsTreeName(), 0);
00147 
00148     fid_ = FileID(createGlobalIdentifier());
00149 
00150     // For the Job Report, get a vector of branch names in the "Events" tree.
00151     // Also create a hash of all the branch names in the "Events" tree
00152     // in a deterministic order, except use the full class name instead of the friendly class name.
00153     // To avoid extra string copies, we create a vector of pointers into the product registry,
00154     // and use a custom comparison operator for sorting.
00155     std::vector<std::string> branchNames;
00156     std::vector<BranchDescription const*> branches;
00157     branchNames.reserve(om_->selectedOutputItemList()[InEvent].size());
00158     branches.reserve(om->selectedOutputItemList()[InEvent].size());
00159     for(OutputItemList::const_iterator it = om_->selectedOutputItemList()[InEvent].begin(),
00160           itEnd = om_->selectedOutputItemList()[InEvent].end();
00161           it != itEnd; ++it) {
00162       branchNames.push_back(it->branchDescription_->branchName());
00163       branches.push_back(it->branchDescription_);
00164     }
00165     // Now sort the branches for the hash.
00166     sort_all(branches, sorterForJobReportHash);
00167     // Now, make a concatenated string.
00168     std::ostringstream oss;
00169     char const underscore = '_';
00170     for(std::vector<BranchDescription const*>::const_iterator it = branches.begin(), itEnd = branches.end(); it != itEnd; ++it) {
00171       BranchDescription const& bd = **it;
00172       oss << bd.fullClassName() << underscore
00173           << bd.moduleLabel() << underscore
00174           << bd.productInstanceName() << underscore
00175           << bd.processName() << underscore;
00176     }
00177     std::string stringrep = oss.str();
00178     cms::Digest md5alg(stringrep);
00179 
00180     // Register the output file with the JobReport service
00181     // and get back the token for it.
00182     std::string moduleName = "PoolOutputModule";
00183     Service<JobReport> reportSvc;
00184     reportToken_ = reportSvc->outputFileOpened(
00185                       file_, logicalFile_,  // PFN and LFN
00186                       om_->catalog(),  // catalog
00187                       moduleName,   // module class name
00188                       om_->moduleLabel(),  // module label
00189                       fid_.fid(), // file id (guid)
00190                       std::string(), // data type (not yet known, so string is empty).
00191                       md5alg.digest().toString(), // branch hash
00192                       branchNames); // branch names being written
00193   }
00194 
00195   namespace {
00196     void
00197     maybeIssueWarning(int whyNotFastClonable, std::string const& ifileName, std::string const& ofileName) {
00198 
00199       // No message if fast cloning was deliberately disabled, or if there are no events to copy anyway.
00200       if ((whyNotFastClonable &
00201         (FileBlock::DisabledInConfigFile | FileBlock::NoRootInputSource | FileBlock::NotProcessingEvents | FileBlock::NoEventsInFile)) != 0) {
00202         return;
00203       }
00204 
00205       // There will be a message stating every reason that fast cloning was not possible.
00206       // If at one or more of the reasons was because of something the user explicitly specified (e.g. event selection, skipping events),
00207       // or if the input file was in an old format, the message will be informational.  Otherwise, the message will be a warning.
00208       bool isWarning = true;
00209       std::ostringstream message;
00210       message << "Fast copying of file " << ifileName << " to file " << ofileName << " is disabled because:\n";
00211       if((whyNotFastClonable & FileBlock::HasSecondaryFileSequence) != 0) {
00212         message << "a SecondaryFileSequence was specified.\n";
00213         whyNotFastClonable &= ~(FileBlock::HasSecondaryFileSequence);
00214         isWarning = false;
00215       }
00216       if((whyNotFastClonable & FileBlock::FileTooOld) != 0) {
00217         message << "the input file is in an old format.\n";
00218         whyNotFastClonable &= ~(FileBlock::FileTooOld);
00219         isWarning = false;
00220       }
00221       if((whyNotFastClonable & FileBlock::EventsToBeSorted) != 0) {
00222         message << "events need to be sorted.\n";
00223         whyNotFastClonable &= ~(FileBlock::EventsToBeSorted);
00224       }
00225       if((whyNotFastClonable & FileBlock::EventsOrLumisSelectedByID) != 0) {
00226         message << "events or lumis were selected or skipped by ID.\n";
00227         whyNotFastClonable &= ~(FileBlock::EventsOrLumisSelectedByID);
00228         isWarning = false;
00229       }
00230       if((whyNotFastClonable & FileBlock::InitialEventsSkipped) != 0) {
00231         message << "initial events, lumis or runs were skipped.\n";
00232         whyNotFastClonable &= ~(FileBlock::InitialEventsSkipped);
00233         isWarning = false;
00234       }
00235       if((whyNotFastClonable & FileBlock::DuplicateEventsRemoved) != 0) {
00236         message << "some events were skipped because of duplicate checking.\n";
00237         whyNotFastClonable &= ~(FileBlock::DuplicateEventsRemoved);
00238       }
00239       if((whyNotFastClonable & FileBlock::MaxEventsTooSmall) != 0) {
00240         message << "some events were not copied because of maxEvents limit.\n";
00241         whyNotFastClonable &= ~(FileBlock::MaxEventsTooSmall);
00242         isWarning = false;
00243       }
00244       if((whyNotFastClonable & FileBlock::MaxLumisTooSmall) != 0) {
00245         message << "some events were not copied because of maxLumis limit.\n";
00246         whyNotFastClonable &= ~(FileBlock::MaxLumisTooSmall);
00247         isWarning = false;
00248       }
00249       if((whyNotFastClonable & FileBlock::ParallelProcesses) != 0) {
00250         message << "parallel processing was specified.\n";
00251         whyNotFastClonable &= ~(FileBlock::ParallelProcesses);
00252         isWarning = false;
00253       }
00254       if((whyNotFastClonable & FileBlock::EventSelectionUsed) != 0) {
00255         message << "an EventSelector was specified.\n";
00256         whyNotFastClonable &= ~(FileBlock::EventSelectionUsed);
00257         isWarning = false;
00258       }
00259       if((whyNotFastClonable & FileBlock::OutputMaxEventsTooSmall) != 0) {
00260         message << "some events were not copied because of maxEvents output limit.\n";
00261         whyNotFastClonable &= ~(FileBlock::OutputMaxEventsTooSmall);
00262         isWarning = false;
00263       }
00264       if((whyNotFastClonable & FileBlock::SplitLevelMismatch) != 0) {
00265         message << "the split level or basket size of a branch or branches was modified.\n";
00266         whyNotFastClonable &= ~(FileBlock::SplitLevelMismatch);
00267       }
00268       if((whyNotFastClonable & FileBlock::BranchMismatch) != 0) {
00269         message << "The format of a data product has changed.\n";
00270         whyNotFastClonable &= ~(FileBlock::BranchMismatch);
00271       }
00272       assert(whyNotFastClonable == FileBlock::CanFastClone);
00273       if (isWarning) {
00274         LogWarning("FastCloningDisabled") << message.str();
00275       } else {
00276         LogInfo("FastCloningDisabled") << message.str();
00277       }
00278     }
00279   }
00280 
00281   void RootOutputFile::beginInputFile(FileBlock const& fb, int remainingEvents) {
00282 
00283     // Reset per input file information
00284     whyNotFastClonable_ = om_->whyNotFastClonable();
00285     canFastCloneAux_ = false;
00286 
00287     if(fb.tree() != 0) {
00288 
00289       whyNotFastClonable_ |= fb.whyNotFastClonable();
00290 
00291       if(remainingEvents >= 0 && remainingEvents < fb.tree()->GetEntries()) {
00292         whyNotFastClonable_ |= FileBlock::OutputMaxEventsTooSmall;
00293       }
00294 
00295       bool match = eventTree_.checkSplitLevelsAndBasketSizes(fb.tree());
00296       if(!match) {
00297         if(om_->overrideInputFileSplitLevels()) {
00298           // We may be fast copying.  We must disable fast copying if the split levels
00299           // or basket sizes do not match.
00300           whyNotFastClonable_ |= FileBlock::SplitLevelMismatch;
00301         } else {
00302           // We are using the input split levels and basket sizes from the first input file
00303           // for copied output branches.  In this case, we throw an exception if any branches
00304           // have different split levels or basket sizes in a subsequent input file.
00305           // If the mismatch is in the first file, there is a bug somewhere, so we assert.
00306           assert(om_->inputFileCount() > 1);
00307           throw Exception(errors::MismatchedInputFiles, "RootOutputFile::beginInputFile()") <<
00308             "Merge failure because input file " << file_ << " has different ROOT split levels or basket sizes\n" <<
00309             "than previous files.  To allow merging in splite of this, use the configuration parameter\n" <<
00310             "overrideInputFileSplitLevels=cms.untracked.bool(True)\n" <<
00311             "in every PoolOutputModule.\n";
00312         }
00313       }
00314 
00315       // Since this check can be time consuming, we do it only if we would otherwise fast clone.
00316       if(whyNotFastClonable_ == FileBlock::CanFastClone) {
00317         if(!eventTree_.checkIfFastClonable(fb.tree())) {
00318           whyNotFastClonable_ |= FileBlock::BranchMismatch;
00319         }
00320       }
00321       // We now check if we can fast copy the auxiliary branches.
00322       // We can do so only if we can otherwise fast copy,
00323       // the input file has the current format (these branches are in the Events Tree),
00324       // there are no newly dropped or produced products,
00325       // and the branch list indexes do not need modification.
00326       Service<ConstProductRegistry> reg;
00327       canFastCloneAux_ = (whyNotFastClonable_ == FileBlock::CanFastClone) &&
00328                           fb.fileFormatVersion().noMetaDataTrees() &&
00329                           !om_->hasNewlyDroppedBranch()[InEvent] &&
00330                           !fb.hasNewlyDroppedBranch()[InEvent] &&
00331                           !reg->anyProductProduced() &&
00332                           fb.branchListIndexesUnchanged();
00333 
00334       // Report the fast copying status.
00335       Service<JobReport> reportSvc;
00336       reportSvc->reportFastCopyingStatus(reportToken_, fb.fileName(), whyNotFastClonable_ == FileBlock::CanFastClone);
00337     } else {
00338       whyNotFastClonable_ |= FileBlock::NoRootInputSource;
00339     }
00340 
00341     eventTree_.maybeFastCloneTree(whyNotFastClonable_ == FileBlock::CanFastClone, canFastCloneAux_, fb.tree(), om_->basketOrder());
00342 
00343     // Possibly issue warning or informational message if we haven't fast cloned.
00344     if(fb.tree() != 0 && whyNotFastClonable_ != FileBlock::CanFastClone) {
00345       maybeIssueWarning(whyNotFastClonable_, fb.fileName(), file_);
00346     }
00347   }
00348 
00349   void RootOutputFile::respondToCloseInputFile(FileBlock const&) {
00350     eventTree_.setEntries();
00351     lumiTree_.setEntries();
00352     runTree_.setEntries();
00353   }
00354 
00355   bool RootOutputFile::shouldWeCloseFile() const {
00356     unsigned int const oneK = 1024;
00357     Long64_t size = filePtr_->GetSize()/oneK;
00358     return(size >= om_->maxFileSize());
00359   }
00360 
00361   void RootOutputFile::writeOne(EventPrincipal const& e) {
00362     // Auxiliary branch
00363     pEventAux_ = &e.aux();
00364 
00365     // Because getting the data may cause an exception to be thrown we want to do that
00366     // first before writing anything to the file about this event
00367     // NOTE: pEventAux_, pBranchListIndexes_, pEventSelectionIDs_, and pEventEntryInfoVector_
00368     // must be set before calling fillBranches since they get written out in that routine.
00369     assert(pEventAux_->processHistoryID() == e.processHistoryID());
00370     pBranchListIndexes_ = &e.branchListIndexes();
00371 
00372     // Note: The EventSelectionIDVector should have a one to one correspondence with the processes in the process history.
00373     // Therefore, a new entry should be added if and only if the current process has been added to the process history,
00374     // which is done if and only if there is a produced product.
00375     Service<ConstProductRegistry> reg;
00376     EventSelectionIDVector esids = e.eventSelectionIDs();
00377     if (reg->anyProductProduced() || !om_->wantAllEvents()) {
00378       esids.push_back(om_->selectorConfig());
00379     }
00380     pEventSelectionIDs_ = &esids;
00381     fillBranches(InEvent, e, pEventEntryInfoVector_);
00382 
00383     // Add the dataType to the job report if it hasn't already been done
00384     if(!dataTypeReported_) {
00385       Service<JobReport> reportSvc;
00386       std::string dataType("MC");
00387       if(pEventAux_->isRealData())  dataType = "Data";
00388       reportSvc->reportDataType(reportToken_, dataType);
00389       dataTypeReported_ = true;
00390     }
00391 
00392     // Add event to index
00393     indexIntoFile_.addEntry(e.processHistoryID(), pEventAux_->run(), pEventAux_->luminosityBlock(), pEventAux_->event(), eventEntryNumber_);
00394     ++eventEntryNumber_;
00395 
00396     // Report event written
00397     Service<JobReport> reportSvc;
00398     reportSvc->eventWrittenToFile(reportToken_, e.id().run(), e.id().event());
00399   }
00400 
00401   void RootOutputFile::writeLuminosityBlock(LuminosityBlockPrincipal const& lb) {
00402     // Auxiliary branch
00403     // NOTE: lumiAux_ must be filled before calling fillBranches since it gets written out in that routine.
00404     lumiAux_ = lb.aux();
00405     // Use the updated process historyID
00406     lumiAux_.setProcessHistoryID(lb.processHistoryID());
00407     // Add lumi to index.
00408     indexIntoFile_.addEntry(lb.processHistoryID(), lumiAux_.run(), lumiAux_.luminosityBlock(), 0U, lumiEntryNumber_);
00409     ++lumiEntryNumber_;
00410     fillBranches(InLumi, lb, pLumiEntryInfoVector_);
00411     lumiTree_.optimizeBaskets(10ULL*1024*1024);
00412   }
00413 
00414   void RootOutputFile::writeRun(RunPrincipal const& r) {
00415     // Auxiliary branch
00416     // NOTE: runAux_ must be filled before calling fillBranches since it gets written out in that routine.
00417     runAux_ = r.aux();
00418     // Use the updated process historyID
00419     runAux_.setProcessHistoryID(r.processHistoryID());
00420     // Add run to index.
00421     indexIntoFile_.addEntry(r.processHistoryID(), runAux_.run(), 0U, 0U, runEntryNumber_);
00422     ++runEntryNumber_;
00423     fillBranches(InRun, r, pRunEntryInfoVector_);
00424     runTree_.optimizeBaskets(10ULL*1024*1024);
00425   }
00426 
00427   void RootOutputFile::writeParentageRegistry() {
00428     Parentage const* desc(0);
00429 
00430     if(!parentageTree_->Branch(poolNames::parentageBranchName().c_str(),
00431                                         &desc, om_->basketSize(), 0))
00432       throw Exception(errors::FatalRootError)
00433         << "Failed to create a branch for Parentages in the output file";
00434 
00435     ParentageRegistry& ptReg = *ParentageRegistry::instance();
00436     std::set<ParentageID>::const_iterator pidend = parentageIDs_.end();
00437     for(ParentageRegistry::const_iterator i = ptReg.begin(), e = ptReg.end(); i != e; ++i) {
00438       if(parentageIDs_.find(i->first) != pidend) {
00439         desc = &(i->second);
00440         parentageTree_->Fill();
00441       }
00442     }
00443   }
00444 
00445   void RootOutputFile::writeFileFormatVersion() {
00446     FileFormatVersion fileFormatVersion(getFileFormatVersion());
00447     FileFormatVersion* pFileFmtVsn = &fileFormatVersion;
00448     TBranch* b = metaDataTree_->Branch(poolNames::fileFormatVersionBranchName().c_str(), &pFileFmtVsn, om_->basketSize(), 0);
00449     assert(b);
00450     b->Fill();
00451   }
00452 
00453   void RootOutputFile::writeFileIdentifier() {
00454     FileID* fidPtr = &fid_;
00455     TBranch* b = metaDataTree_->Branch(poolNames::fileIdentifierBranchName().c_str(), &fidPtr, om_->basketSize(), 0);
00456     assert(b);
00457     b->Fill();
00458   }
00459 
00460   void RootOutputFile::writeIndexIntoFile() {
00461     indexIntoFile_.sortVector_Run_Or_Lumi_Entries();
00462     IndexIntoFile* iifPtr = &indexIntoFile_;
00463     TBranch* b = metaDataTree_->Branch(poolNames::indexIntoFileBranchName().c_str(), &iifPtr, om_->basketSize(), 0);
00464     assert(b);
00465     b->Fill();
00466   }
00467 
00468   void RootOutputFile::writeProcessConfigurationRegistry() {
00469     typedef ProcessConfigurationRegistry::collection_type Map;
00470     Map const& procConfigMap = ProcessConfigurationRegistry::instance()->data();
00471     ProcessConfigurationVector procConfigVector;
00472     for(Map::const_iterator i = procConfigMap.begin(), e = procConfigMap.end(); i != e; ++i) {
00473       procConfigVector.push_back(i->second);
00474     }
00475     sort_all(procConfigVector);
00476     ProcessConfigurationVector* p = &procConfigVector;
00477     TBranch* b = metaDataTree_->Branch(poolNames::processConfigurationBranchName().c_str(), &p, om_->basketSize(), 0);
00478     assert(b);
00479     b->Fill();
00480   }
00481 
00482   void RootOutputFile::writeProcessHistoryRegistry() {
00483     typedef ProcessHistoryRegistry::collection_type Map;
00484     Map const& procHistoryMap = ProcessHistoryRegistry::instance()->data();
00485     ProcessHistoryVector procHistoryVector;
00486     for(Map::const_iterator i = procHistoryMap.begin(), e = procHistoryMap.end(); i != e; ++i) {
00487       procHistoryVector.push_back(i->second);
00488     }
00489     ProcessHistoryVector* p = &procHistoryVector;
00490     TBranch* b = metaDataTree_->Branch(poolNames::processHistoryBranchName().c_str(), &p, om_->basketSize(), 0);
00491     assert(b);
00492     b->Fill();
00493   }
00494 
00495   void RootOutputFile::writeBranchIDListRegistry() {
00496     BranchIDListRegistry::collection_type* p = &BranchIDListRegistry::instance()->data();
00497     TBranch* b = metaDataTree_->Branch(poolNames::branchIDListBranchName().c_str(), &p, om_->basketSize(), 0);
00498     assert(b);
00499     b->Fill();
00500   }
00501 
00502   void RootOutputFile::writeParameterSetRegistry() {
00503     std::pair<ParameterSetID, ParameterSetBlob> idToBlob;
00504     std::pair<ParameterSetID, ParameterSetBlob>* pIdToBlob = &idToBlob;
00505     TBranch* b = parameterSetsTree_->Branch(poolNames::idToParameterSetBlobsBranchName().c_str(),&pIdToBlob,om_->basketSize(), 0);
00506 
00507     for(pset::Registry::const_iterator it = pset::Registry::instance()->begin(),
00508         itEnd = pset::Registry::instance()->end();
00509         it != itEnd;
00510         ++it) {
00511       idToBlob.first = it->first;
00512       idToBlob.second.pset() = it->second.toString();
00513 
00514       b->Fill();
00515     }
00516   }
00517 
00518   void RootOutputFile::writeProductDescriptionRegistry() {
00519     // Make a local copy of the ProductRegistry, removing any transient or pruned products.
00520     typedef ProductRegistry::ProductList ProductList;
00521     Service<ConstProductRegistry> reg;
00522     ProductRegistry pReg(reg->productList());
00523     ProductList& pList  = const_cast<ProductList &>(pReg.productList());
00524     std::set<BranchID>::iterator end = branchesWithStoredHistory_.end();
00525     for(ProductList::iterator it = pList.begin(); it != pList.end();) {
00526       if(branchesWithStoredHistory_.find(it->second.branchID()) == end) {
00527         // avoid invalidating iterator on deletion
00528         ProductList::iterator itCopy = it;
00529         ++it;
00530         pList.erase(itCopy);
00531 
00532       } else {
00533         ++it;
00534       }
00535     }
00536 
00537     ProductRegistry* ppReg = &pReg;
00538     TBranch* b = metaDataTree_->Branch(poolNames::productDescriptionBranchName().c_str(), &ppReg, om_->basketSize(), 0);
00539     assert(b);
00540     b->Fill();
00541   }
00542   void RootOutputFile::writeProductDependencies() {
00543     BranchChildren& pDeps = const_cast<BranchChildren&>(om_->branchChildren());
00544     BranchChildren* ppDeps = &pDeps;
00545     TBranch* b = metaDataTree_->Branch(poolNames::productDependenciesBranchName().c_str(), &ppDeps, om_->basketSize(), 0);
00546     assert(b);
00547     b->Fill();
00548   }
00549 
00550   void RootOutputFile::finishEndFile() {
00551     metaDataTree_->SetEntries(-1);
00552     RootOutputTree::writeTTree(metaDataTree_);
00553     RootOutputTree::writeTTree(parameterSetsTree_);
00554 
00555     RootOutputTree::writeTTree(parentageTree_);
00556 
00557     // Create branch aliases for all the branches in the
00558     // events/lumis/runs trees. The loop is over all types of data
00559     // products.
00560     for(int i = InEvent; i < NumBranchTypes; ++i) {
00561       BranchType branchType = static_cast<BranchType>(i);
00562       setBranchAliases(treePointers_[branchType]->tree(), om_->keptProducts()[branchType]);
00563       treePointers_[branchType]->writeTree();
00564     }
00565 
00566     // close the file -- mfp
00567     // Just to play it safe, zero all pointers to objects in the TFile to be closed.
00568     metaDataTree_ = parentageTree_ = 0;
00569     for(RootOutputTreePtrArray::iterator it = treePointers_.begin(), itEnd = treePointers_.end(); it != itEnd; ++it) {
00570       (*it)->close();
00571       (*it) = 0;
00572     }
00573     filePtr_->Close();
00574     filePtr_.reset();
00575 
00576     // report that file has been closed
00577     Service<JobReport> reportSvc;
00578     reportSvc->outputFileClosed(reportToken_);
00579 
00580   }
00581 
00582   void
00583   RootOutputFile::setBranchAliases(TTree* tree, Selections const& branches) const {
00584     if(tree && tree->GetNbranches() != 0) {
00585       for(Selections::const_iterator i = branches.begin(), iEnd = branches.end();
00586           i != iEnd; ++i) {
00587         BranchDescription const& pd = **i;
00588         std::string const& full = pd.branchName() + "obj";
00589         if(pd.branchAliases().empty()) {
00590           std::string const& alias =
00591               (pd.productInstanceName().empty() ? pd.moduleLabel() : pd.productInstanceName());
00592           tree->SetAlias(alias.c_str(), full.c_str());
00593         } else {
00594           std::set<std::string>::const_iterator it = pd.branchAliases().begin(), itEnd = pd.branchAliases().end();
00595           for(; it != itEnd; ++it) {
00596             tree->SetAlias((*it).c_str(), full.c_str());
00597           }
00598         }
00599       }
00600     }
00601   }
00602 
00603   void
00604   RootOutputFile::insertAncestors(ProductProvenance const& iGetParents,
00605                                   Principal const& principal,
00606                                   bool produced,
00607                                   std::set<ProductProvenance>& oToFill) {
00608     assert(om_->dropMetaData() != PoolOutputModule::DropAll);
00609     assert(produced || om_->dropMetaData() != PoolOutputModule::DropPrior);
00610     if(om_->dropMetaData() == PoolOutputModule::DropDroppedPrior && !produced) return;
00611     BranchMapper const& iMapper = *principal.branchMapperPtr();
00612     std::vector<BranchID> const& parentIDs = iGetParents.parentage().parents();
00613     for(std::vector<BranchID>::const_iterator it = parentIDs.begin(), itEnd = parentIDs.end();
00614           it != itEnd; ++it) {
00615       branchesWithStoredHistory_.insert(*it);
00616       boost::shared_ptr<ProductProvenance> info = iMapper.branchIDToProvenance(*it);
00617       if(info) {
00618         if(om_->dropMetaData() == PoolOutputModule::DropNone ||
00619                  principal.getProvenance(info->branchID()).product().produced()) {
00620           if(oToFill.insert(*info).second) {
00621             //haven't seen this one yet
00622             insertAncestors(*info, principal, produced, oToFill);
00623           }
00624         }
00625       }
00626     }
00627   }
00628 
00629   void RootOutputFile::fillBranches(
00630                 BranchType const& branchType,
00631                 Principal const& principal,
00632                 ProductProvenanceVector* productProvenanceVecPtr) {
00633 
00634     std::vector<boost::shared_ptr<EDProduct> > dummies;
00635 
00636     bool const fastCloning = (branchType == InEvent) && (whyNotFastClonable_ == FileBlock::CanFastClone);
00637 
00638     OutputItemList const& items = om_->selectedOutputItemList()[branchType];
00639 
00640     std::set<ProductProvenance> provenanceToKeep;
00641 
00642     // Loop over EDProduct branches, fill the provenance, and write the branch.
00643     for(OutputItemList::const_iterator i = items.begin(), iEnd = items.end(); i != iEnd; ++i) {
00644 
00645       BranchID const& id = i->branchDescription_->branchID();
00646       branchesWithStoredHistory_.insert(id);
00647 
00648       bool produced = i->branchDescription_->produced();
00649       bool keepProvenance = om_->dropMetaData() == PoolOutputModule::DropNone ||
00650                             om_->dropMetaData() == PoolOutputModule::DropDroppedPrior ||
00651                            (om_->dropMetaData() == PoolOutputModule::DropPrior && produced);
00652       bool getProd = (produced || !fastCloning ||
00653          treePointers_[branchType]->uncloned(i->branchDescription_->branchName()));
00654 
00655       EDProduct const* product = 0;
00656       OutputHandle const oh = principal.getForOutput(id, getProd);
00657       if(keepProvenance && oh.productProvenance()) {
00658         provenanceToKeep.insert(*oh.productProvenance());
00659         assert(principal.branchMapperPtr());
00660         insertAncestors(*oh.productProvenance(), principal, produced, provenanceToKeep);
00661       }
00662       product = oh.wrapper();
00663       if(getProd) {
00664         if(product == 0) {
00665           // No product with this ID is in the event.
00666           // Add a null product.
00667           TClass* cp = gROOT->GetClass(i->branchDescription_->wrappedName().c_str());
00668           boost::shared_ptr<EDProduct> dummy(static_cast<EDProduct*>(cp->New()));
00669           dummies.push_back(dummy);
00670           product = dummy.get();
00671         }
00672         i->product_ = product;
00673       }
00674     }
00675 
00676     for(std::set<ProductProvenance>::const_iterator it = provenanceToKeep.begin(), itEnd=provenanceToKeep.end();
00677         it != itEnd; ++it) {
00678       parentageIDs_.insert(it->parentageID());
00679     }
00680 
00681     productProvenanceVecPtr->assign(provenanceToKeep.begin(), provenanceToKeep.end());
00682     treePointers_[branchType]->fillTree();
00683     productProvenanceVecPtr->clear();
00684   }
00685 
00686 }