00001
00002
00003 #include "DuplicateChecker.h"
00004 #include "PoolSource.h"
00005 #include "RootFile.h"
00006 #include "RootInputFileSequence.h"
00007 #include "RootTree.h"
00008
00009 #include "DataFormats/Provenance/interface/ProductRegistry.h"
00010 #include "FWCore/Catalog/interface/SiteLocalConfig.h"
00011 #include "FWCore/Framework/interface/EventPrincipal.h"
00012 #include "FWCore/Framework/interface/FileBlock.h"
00013 #include "FWCore/Framework/src/PrincipalCache.h"
00014 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00015 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00016 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
00017 #include "FWCore/ServiceRegistry/interface/Service.h"
00018 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
00019 #include "Utilities/StorageFactory/interface/StorageFactory.h"
00020
00021 #include "CLHEP/Random/RandFlat.h"
00022 #include "InputFile.h"
00023 #include "TSystem.h"
00024
00025 namespace edm {
00026 RootInputFileSequence::RootInputFileSequence(
00027 ParameterSet const& pset,
00028 PoolSource const& input,
00029 InputFileCatalog const& catalog,
00030 PrincipalCache& cache,
00031 InputType::InputType inputType) :
00032 input_(input),
00033 inputType_(inputType),
00034 catalog_(catalog),
00035 firstFile_(true),
00036 fileIterBegin_(fileCatalogItems().begin()),
00037 fileIterEnd_(fileCatalogItems().end()),
00038 fileIter_(fileIterEnd_),
00039 fileIterLastOpened_(fileIterEnd_),
00040 rootFile_(),
00041 parametersMustMatch_(BranchDescription::Permissive),
00042 branchesMustMatch_(BranchDescription::Permissive),
00043 flatDistribution_(),
00044 indexesIntoFiles_(fileCatalogItems().size()),
00045 orderedProcessHistoryIDs_(),
00046 eventSkipperByID_(inputType == InputType::Primary ? EventSkipperByID::create(pset).release() : 0),
00047 eventsRemainingInFile_(0),
00048
00049
00050
00051
00052
00053
00054
00055 numberOfEventsToSkip_(inputType == InputType::Primary ? pset.getUntrackedParameter<unsigned int>("skipEvents", 0U) : 0U),
00056 noEventSort_(inputType == InputType::Primary ? pset.getUntrackedParameter<bool>("noEventSort", true) : false),
00057 skipBadFiles_(pset.getUntrackedParameter<bool>("skipBadFiles", false)),
00058 treeCacheSize_(noEventSort_ ? pset.getUntrackedParameter<unsigned int>("cacheSize", roottree::defaultCacheSize) : 0U),
00059 treeMaxVirtualSize_(pset.getUntrackedParameter<int>("treeMaxVirtualSize", -1)),
00060 setRun_(pset.getUntrackedParameter<unsigned int>("setRunNumber", 0U)),
00061 groupSelectorRules_(pset, "inputCommands", "InputSource"),
00062 duplicateChecker_(inputType == InputType::Primary ? new DuplicateChecker(pset) : 0),
00063 dropDescendants_(pset.getUntrackedParameter<bool>("dropDescendantsOfDroppedBranches", inputType != InputType::SecondarySource)),
00064 usingGoToEvent_(false) {
00065
00066
00067 Service<SiteLocalConfig> pSLC;
00068 if(treeCacheSize_ != 0U && pSLC.isAvailable() && pSLC->sourceTTreeCacheSize()) {
00069 treeCacheSize_ = *(pSLC->sourceTTreeCacheSize());
00070 }
00071
00072 if(inputType_ == InputType::Primary) {
00073
00074
00075 StorageFactory *factory = StorageFactory::get();
00076 for(fileIter_ = fileIterBegin_; fileIter_ != fileIterEnd_; ++fileIter_) {
00077 factory->activateTimeout(fileIter_->fileName());
00078 factory->stagein(fileIter_->fileName());
00079 }
00080 }
00081
00082 std::string parametersMustMatch = pset.getUntrackedParameter<std::string>("parametersMustMatch", std::string("permissive"));
00083 if(parametersMustMatch == std::string("strict")) parametersMustMatch_ = BranchDescription::Strict;
00084
00085 std::string branchesMustMatch = pset.getUntrackedParameter<std::string>("branchesMustMatch", std::string("permissive"));
00086 if(branchesMustMatch == std::string("strict")) branchesMustMatch_ = BranchDescription::Strict;
00087
00088 if(inputType != InputType::SecondarySource) {
00089 for(fileIter_ = fileIterBegin_; fileIter_ != fileIterEnd_; ++fileIter_) {
00090 initFile(skipBadFiles_);
00091 if(rootFile_) break;
00092 }
00093 if(rootFile_) {
00094 productRegistryUpdate().updateFromInput(rootFile_->productRegistry()->productList());
00095 if(numberOfEventsToSkip_ != 0) {
00096 skipEvents(numberOfEventsToSkip_, cache);
00097 }
00098 }
00099 }
00100 }
00101
00102 std::vector<FileCatalogItem> const&
00103 RootInputFileSequence::fileCatalogItems() const {
00104 return catalog_.fileCatalogItems();
00105 }
00106
00107 void
00108 RootInputFileSequence::endJob() {
00109 closeFile_();
00110 }
00111
00112 boost::shared_ptr<FileBlock>
00113 RootInputFileSequence::readFile_(PrincipalCache& cache) {
00114 if(firstFile_) {
00115
00116 firstFile_ = false;
00117 if(!rootFile_) {
00118 initFile(skipBadFiles_);
00119 }
00120 } else {
00121 if(!nextFile(cache)) {
00122 assert(0);
00123 }
00124 }
00125 if(!rootFile_) {
00126 return boost::shared_ptr<FileBlock>(new FileBlock);
00127 }
00128 return rootFile_->createFileBlock();
00129 }
00130
00131 void RootInputFileSequence::closeFile_() {
00132
00133 if(rootFile_) {
00134 if(inputType_ != InputType::SecondarySource) {
00135 std::auto_ptr<InputSource::FileCloseSentry>
00136 sentry((inputType_ == InputType::Primary) ? new InputSource::FileCloseSentry(input_) : 0);
00137 rootFile_->close();
00138 if(duplicateChecker_) duplicateChecker_->inputFileClosed();
00139 }
00140 rootFile_.reset();
00141 }
00142 }
00143
00144 void RootInputFileSequence::initFile(bool skipBadFiles) {
00145
00146
00147
00148
00149
00150
00151 if(fileIterLastOpened_ != fileIterEnd_) {
00152 size_t currentIndexIntoFile = fileIterLastOpened_ - fileIterBegin_;
00153 bool needIndexesForDuplicateChecker = duplicateChecker_ && duplicateChecker_->checkingAllFiles() && !duplicateChecker_->checkDisabled();
00154 bool deleteIndexIntoFile = inputType_ == InputType::Primary &&
00155 !needIndexesForDuplicateChecker &&
00156 !usingGoToEvent_;
00157 if(deleteIndexIntoFile) {
00158 indexesIntoFiles_[currentIndexIntoFile].reset();
00159 } else {
00160 if(indexesIntoFiles_[currentIndexIntoFile]) indexesIntoFiles_[currentIndexIntoFile]->inputFileClosed();
00161 }
00162 fileIterLastOpened_ = fileIterEnd_;
00163 }
00164 closeFile_();
00165
00166
00167 if(fileIter_->fileName().empty()) {
00168
00169 InputFile::reportSkippedFile(fileIter_->fileName(), fileIter_->logicalFileName());
00170 if(!skipBadFiles) {
00171 throw cms::Exception("LogicalFileNameNotFound", "RootInputFileSequence::initFile()\n")
00172 << "Logical file name '" << fileIter_->logicalFileName() << "' was not found in the file catalog.\n"
00173 << "If you wanted a local file, you forgot the 'file:' prefix\n"
00174 << "before the file name in your configuration file.\n";
00175 }
00176 LogWarning("") << "Input logical file: " << fileIter_->logicalFileName() << " was not found in the catalog, and will be skipped.\n";
00177 return;
00178 }
00179
00180
00181
00182 std::string fallbackName = fileIter_->fallbackFileName();
00183 bool hasFallbackUrl = !fallbackName.empty() && fallbackName != fileIter_->fileName();
00184
00185 boost::shared_ptr<InputFile> filePtr;
00186 try {
00187 std::auto_ptr<InputSource::FileOpenSentry>
00188 sentry(inputType_ == InputType::Primary ? new InputSource::FileOpenSentry(input_) : 0);
00189 filePtr.reset(new InputFile(gSystem->ExpandPathName(fileIter_->fileName().c_str()), " Initiating request to open file "));
00190 }
00191 catch (cms::Exception const& e) {
00192 if(!skipBadFiles && !hasFallbackUrl) {
00193 InputFile::reportSkippedFile(fileIter_->fileName(), fileIter_->logicalFileName());
00194 Exception ex(errors::FileOpenError, "", e);
00195 ex.addContext("Calling RootInputFileSequence::initFile()");
00196 ex.clearMessage();
00197 ex << "Input file " << fileIter_->fileName() << " was not found, could not be opened, or is corrupted.\n";
00198 throw ex;
00199 }
00200 }
00201 if(!filePtr && (hasFallbackUrl)) {
00202 try {
00203 std::auto_ptr<InputSource::FileOpenSentry>
00204 sentry(inputType_ == InputType::Primary ? new InputSource::FileOpenSentry(input_) : 0);
00205 filePtr.reset(new InputFile(gSystem->ExpandPathName(fallbackName.c_str()), " Fallback request to file "));
00206 }
00207 catch (cms::Exception const& e) {
00208 if(!skipBadFiles) {
00209 InputFile::reportSkippedFile(fileIter_->fileName(), fileIter_->logicalFileName());
00210 Exception ex(errors::FileOpenError, "", e);
00211 ex.addContext("Calling RootInputFileSequence::initFile()");
00212 ex.clearMessage();
00213 ex << "Input file " << fileIter_->fileName() << " was not found, could not be opened, or is corrupted.\n";
00214 ex << "Fallback Input file " << fallbackName << " also was not found, could not be opened, or is corrupted.\n";
00215 throw ex;
00216 }
00217 }
00218 }
00219 if(filePtr) {
00220 std::vector<boost::shared_ptr<IndexIntoFile> >::size_type currentIndexIntoFile = fileIter_ - fileIterBegin_;
00221 rootFile_ = RootFileSharedPtr(new RootFile(fileIter_->fileName(),
00222 processConfiguration(), fileIter_->logicalFileName(), filePtr,
00223 eventSkipperByID_, numberOfEventsToSkip_ != 0,
00224 remainingEvents(), remainingLuminosityBlocks(), treeCacheSize_, treeMaxVirtualSize_,
00225 input_.processingMode(),
00226 setRun_,
00227 noEventSort_,
00228 groupSelectorRules_,
00229 inputType_,
00230 duplicateChecker_,
00231 dropDescendants_,
00232 indexesIntoFiles_, currentIndexIntoFile, orderedProcessHistoryIDs_, usingGoToEvent_));
00233
00234 fileIterLastOpened_ = fileIter_;
00235 indexesIntoFiles_[currentIndexIntoFile] = rootFile_->indexIntoFileSharedPtr();
00236 char const* inputType = 0;
00237 switch(inputType_) {
00238 case InputType::Primary: inputType = "primaryFiles"; break;
00239 case InputType::SecondaryFile: inputType = "secondaryFiles"; break;
00240 case InputType::SecondarySource: inputType = "mixingFiles"; break;
00241 }
00242 rootFile_->reportOpened(inputType);
00243 } else {
00244 InputFile::reportSkippedFile(fileIter_->fileName(), fileIter_->logicalFileName());
00245 if(!skipBadFiles) {
00246 throw Exception(errors::FileOpenError) <<
00247 "RootInputFileSequence::initFile(): Input file " << fileIter_->fileName() << " was not found or could not be opened.\n";
00248 }
00249 LogWarning("") << "Input file: " << fileIter_->fileName() << " was not found or could not be opened, and will be skipped.\n";
00250 }
00251 }
00252
00253 boost::shared_ptr<ProductRegistry const>
00254 RootInputFileSequence::fileProductRegistry() const {
00255 return rootFile_->productRegistry();
00256 }
00257
00258 bool RootInputFileSequence::nextFile(PrincipalCache& cache) {
00259 if(fileIter_ != fileIterEnd_) ++fileIter_;
00260 if(fileIter_ == fileIterEnd_) {
00261 if(inputType_ == InputType::Primary) {
00262 return false;
00263 } else {
00264 fileIter_ = fileIterBegin_;
00265 }
00266 }
00267
00268 initFile(skipBadFiles_);
00269
00270 if(inputType_ == InputType::Primary && rootFile_) {
00271 size_t size = productRegistry()->size();
00272
00273 std::string mergeInfo = productRegistryUpdate().merge(*rootFile_->productRegistry(),
00274 fileIter_->fileName(),
00275 parametersMustMatch_,
00276 branchesMustMatch_);
00277 if(!mergeInfo.empty()) {
00278 throw Exception(errors::MismatchedInputFiles,"RootInputFileSequence::nextFile()") << mergeInfo;
00279 }
00280 if(productRegistry()->size() > size) {
00281 cache.adjustIndexesAfterProductRegistryAddition();
00282 }
00283 cache.adjustEventToNewProductRegistry(productRegistry());
00284 }
00285 return true;
00286 }
00287
00288 bool RootInputFileSequence::previousFile(PrincipalCache& cache) {
00289 if(fileIter_ == fileIterBegin_) {
00290 if(inputType_ == InputType::Primary) {
00291 return false;
00292 } else {
00293 fileIter_ = fileIterEnd_;
00294 }
00295 }
00296 --fileIter_;
00297
00298 initFile(false);
00299
00300 if(inputType_ == InputType::Primary && rootFile_) {
00301 size_t size = productRegistry()->size();
00302
00303 std::string mergeInfo = productRegistryUpdate().merge(*rootFile_->productRegistry(),
00304 fileIter_->fileName(),
00305 parametersMustMatch_,
00306 branchesMustMatch_);
00307 if(!mergeInfo.empty()) {
00308 throw Exception(errors::MismatchedInputFiles,"RootInputFileSequence::previousEvent()") << mergeInfo;
00309 }
00310 if(productRegistry()->size() > size) {
00311 cache.adjustIndexesAfterProductRegistryAddition();
00312 }
00313 cache.adjustEventToNewProductRegistry(productRegistry());
00314 }
00315 if(rootFile_) rootFile_->setToLastEntry();
00316 return true;
00317 }
00318
00319 RootInputFileSequence::~RootInputFileSequence() {
00320 }
00321
00322 boost::shared_ptr<RunAuxiliary>
00323 RootInputFileSequence::readRunAuxiliary_() {
00324 boost::shared_ptr<RunAuxiliary> aux = rootFile_->readRunAuxiliary_();
00325 return aux;
00326 }
00327
00328 boost::shared_ptr<LuminosityBlockAuxiliary>
00329 RootInputFileSequence::readLuminosityBlockAuxiliary_() {
00330 boost::shared_ptr<LuminosityBlockAuxiliary> aux = rootFile_->readLuminosityBlockAuxiliary_();
00331 return aux;
00332 }
00333
00334 boost::shared_ptr<RunPrincipal>
00335 RootInputFileSequence::readRun_(boost::shared_ptr<RunPrincipal> rpCache) {
00336 return rootFile_->readRun_(rpCache);
00337 }
00338
00339 boost::shared_ptr<LuminosityBlockPrincipal>
00340 RootInputFileSequence::readLuminosityBlock_(boost::shared_ptr<LuminosityBlockPrincipal> lbCache) {
00341 return rootFile_->readLumi(lbCache);
00342 }
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 EventPrincipal*
00358 RootInputFileSequence::readEvent(EventPrincipal& cache, boost::shared_ptr<LuminosityBlockPrincipal> lb) {
00359 return rootFile_->readEvent(cache, lb);
00360 }
00361
00362 InputSource::ItemType
00363 RootInputFileSequence::getNextItemType() {
00364 if(fileIter_ == fileIterEnd_) {
00365 return InputSource::IsStop;
00366 }
00367 if(firstFile_) {
00368 return InputSource::IsFile;
00369 }
00370 if(rootFile_) {
00371 IndexIntoFile::EntryType entryType = rootFile_->getNextEntryTypeWanted();
00372 if(entryType == IndexIntoFile::kEvent) {
00373 return InputSource::IsEvent;
00374 } else if(entryType == IndexIntoFile::kLumi) {
00375 return InputSource::IsLumi;
00376 } else if(entryType == IndexIntoFile::kRun) {
00377 return InputSource::IsRun;
00378 }
00379 assert(entryType == IndexIntoFile::kEnd);
00380 }
00381 if(fileIter_ + 1 == fileIterEnd_) {
00382 return InputSource::IsStop;
00383 }
00384 return InputSource::IsFile;
00385 }
00386
00387
00388 void
00389 RootInputFileSequence::rewind_() {
00390 if(fileIter_ != fileIterBegin_) {
00391 closeFile_();
00392 fileIter_ = fileIterBegin_;
00393 }
00394 if(!rootFile_) {
00395 initFile(false);
00396 }
00397 rewindFile();
00398 firstFile_ = true;
00399 }
00400
00401
00402 void
00403 RootInputFileSequence::rewindFile() {
00404 rootFile_->rewind();
00405 }
00406
00407 void
00408 RootInputFileSequence::reset(PrincipalCache& cache) {
00409
00410
00411 if(inputType_ != InputType::SecondarySource) {
00412 firstFile_ = true;
00413 for(fileIter_ = fileIterBegin_; fileIter_ != fileIterEnd_; ++fileIter_) {
00414 initFile(skipBadFiles_);
00415 if(rootFile_) break;
00416 }
00417 if(rootFile_) {
00418 if(numberOfEventsToSkip_ != 0) {
00419 skipEvents(numberOfEventsToSkip_, cache);
00420 }
00421 }
00422 }
00423 }
00424
00425
00426 bool
00427 RootInputFileSequence::skipEvents(int offset, PrincipalCache& cache) {
00428 assert (numberOfEventsToSkip_ == 0 || numberOfEventsToSkip_ == offset);
00429 numberOfEventsToSkip_ = offset;
00430 while(numberOfEventsToSkip_ != 0) {
00431 bool atEnd = rootFile_->skipEvents(numberOfEventsToSkip_);
00432 if((numberOfEventsToSkip_ > 0 || atEnd) && !nextFile(cache)) {
00433 numberOfEventsToSkip_ = 0;
00434 return false;
00435 }
00436 if(numberOfEventsToSkip_ < 0 && !previousFile(cache)) {
00437 numberOfEventsToSkip_ = 0;
00438 fileIter_ = fileIterEnd_;
00439 return false;
00440 }
00441 }
00442 return true;
00443 }
00444
00445 bool
00446 RootInputFileSequence::goToEvent(EventID const& eventID) {
00447 usingGoToEvent_ = true;
00448 if(rootFile_) {
00449 if(rootFile_->goToEvent(eventID)) {
00450 return true;
00451 }
00452
00453 if(rootFile_ && indexesIntoFiles_.size() == 1) {
00454 return false;
00455 }
00456
00457
00458 bool closedOriginalFile = false;
00459 std::vector<FileCatalogItem>::const_iterator originalFile = fileIter_;
00460 IndexIntoFile::IndexIntoFileItr originalPosition = rootFile_->indexIntoFileIter();
00461
00462
00463 typedef std::vector<boost::shared_ptr<IndexIntoFile> >::const_iterator Iter;
00464 for(Iter it = indexesIntoFiles_.begin(), itEnd = indexesIntoFiles_.end(); it != itEnd; ++it) {
00465 if(*it && (*it)->containsItem(eventID.run(), eventID.luminosityBlock(), eventID.event())) {
00466
00467 fileIter_ = fileIterBegin_ + (it - indexesIntoFiles_.begin());
00468 initFile(false);
00469
00470 bool found = rootFile_->goToEvent(eventID);
00471 assert (found);
00472 return true;
00473 }
00474 }
00475
00476 for(Iter it = indexesIntoFiles_.begin(), itEnd = indexesIntoFiles_.end(); it != itEnd; ++it) {
00477 if(!*it) {
00478 fileIter_ = fileIterBegin_ + (it - indexesIntoFiles_.begin());
00479 initFile(false);
00480 closedOriginalFile = true;
00481 if((*it)->containsItem(eventID.run(), eventID.luminosityBlock(), eventID.event())) {
00482 if (rootFile_->goToEvent(eventID)) {
00483 return true;
00484 }
00485 }
00486 }
00487 }
00488 if(closedOriginalFile) {
00489 fileIter_ = originalFile;
00490 initFile(false);
00491 rootFile_->setPosition(originalPosition);
00492 }
00493 }
00494 return false;
00495 }
00496
00497 bool
00498 RootInputFileSequence::skipToItem(RunNumber_t run, LuminosityBlockNumber_t lumi, EventNumber_t event) {
00499
00500 bool found = rootFile_ && rootFile_->setEntryAtItem(run, lumi, event);
00501 if(!found) {
00502
00503 if(rootFile_ && indexesIntoFiles_.size() == 1) {
00504 return false;
00505 }
00506
00507 typedef std::vector<boost::shared_ptr<IndexIntoFile> >::const_iterator Iter;
00508 for(Iter it = indexesIntoFiles_.begin(), itEnd = indexesIntoFiles_.end(); it != itEnd; ++it) {
00509 if(*it && (*it)->containsItem(run, lumi, event)) {
00510
00511 fileIter_ = fileIterBegin_ + (it - indexesIntoFiles_.begin());
00512 initFile(false);
00513
00514 found = rootFile_->setEntryAtItem(run, lumi, event);
00515 assert (found);
00516 return true;
00517 }
00518 }
00519
00520 for(Iter it = indexesIntoFiles_.begin(), itEnd = indexesIntoFiles_.end(); it != itEnd; ++it) {
00521 if(!*it) {
00522 fileIter_ = fileIterBegin_ + (it - indexesIntoFiles_.begin());
00523 initFile(false);
00524 found = rootFile_->setEntryAtItem(run, lumi, event);
00525 if(found) {
00526 return true;
00527 }
00528 }
00529 }
00530
00531 return false;
00532 }
00533 return true;
00534 }
00535
00536 ProcessConfiguration const&
00537 RootInputFileSequence::processConfiguration() const {
00538 return input_.processConfiguration();
00539 }
00540
00541 int
00542 RootInputFileSequence::remainingEvents() const {
00543 return input_.remainingEvents();
00544 }
00545
00546 int
00547 RootInputFileSequence::remainingLuminosityBlocks() const {
00548 return input_.remainingLuminosityBlocks();
00549 }
00550
00551 ProductRegistry &
00552 RootInputFileSequence::productRegistryUpdate() const{
00553 return input_.productRegistryUpdate();
00554 }
00555
00556 boost::shared_ptr<ProductRegistry const>
00557 RootInputFileSequence::productRegistry() const{
00558 return input_.productRegistry();
00559 }
00560
00561 void
00562 RootInputFileSequence::dropUnwantedBranches_(std::vector<std::string> const& wantedBranches) {
00563 std::vector<std::string> rules;
00564 rules.reserve(wantedBranches.size() + 1);
00565 rules.push_back(std::string("drop *"));
00566 for(std::vector<std::string>::const_iterator it = wantedBranches.begin(), itEnd = wantedBranches.end();
00567 it != itEnd; ++it) {
00568 rules.push_back("keep " + *it + "_*");
00569 }
00570 ParameterSet pset;
00571 pset.addUntrackedParameter("inputCommands", rules);
00572 groupSelectorRules_ = GroupSelectorRules(pset, "inputCommands", "InputSource");
00573 }
00574
00575 EventPrincipal*
00576 RootInputFileSequence::readOneSequential() {
00577 skipBadFiles_ = false;
00578 if(fileIter_ == fileIterEnd_ || !rootFile_) {
00579 if(fileIterEnd_ == fileIterBegin_) {
00580 throw Exception(errors::Configuration) << "RootInputFileSequence::readOneSequential(): no input files specified.\n";
00581 }
00582 fileIter_ = fileIterBegin_;
00583 initFile(false);
00584 rootFile_->setAtEventEntry(-1);
00585 }
00586 rootFile_->nextEventEntry();
00587 EventPrincipal* ep = rootFile_->clearAndReadCurrentEvent(rootFile_->secondaryEventPrincipal());
00588 if(ep == 0) {
00589 ++fileIter_;
00590 if(fileIter_ == fileIterEnd_) {
00591 return 0;
00592 }
00593 initFile(false);
00594 rootFile_->setAtEventEntry(-1);
00595 return readOneSequential();
00596 }
00597 return ep;
00598 }
00599
00600 EventPrincipal*
00601 RootInputFileSequence::readOneSpecified(EventID const& id) {
00602 skipBadFiles_ = false;
00603 bool found = skipToItem(id.run(), id.luminosityBlock(), id.event());
00604 if(!found) {
00605 throw Exception(errors::NotFound) <<
00606 "RootInputFileSequence::readOneSpecified(): Secondary Input file " <<
00607 fileIter_->fileName() <<
00608 " does not contain specified event:\n" << id << "\n";
00609 }
00610 EventPrincipal* ep = rootFile_->clearAndReadCurrentEvent(rootFile_->secondaryEventPrincipal());
00611 assert(ep != 0);
00612 return ep;
00613 }
00614
00615 EventPrincipal*
00616 RootInputFileSequence::readOneRandom() {
00617 if(fileIterEnd_ == fileIterBegin_) {
00618 throw Exception(errors::Configuration) << "RootInputFileSequence::readOneRandom(): no input files specified.\n";
00619 }
00620 if(!flatDistribution_) {
00621 Service<RandomNumberGenerator> rng;
00622 CLHEP::HepRandomEngine& engine = rng->getEngine();
00623 flatDistribution_.reset(new CLHEP::RandFlat(engine));
00624 }
00625 skipBadFiles_ = false;
00626 unsigned int currentSeqNumber = fileIter_ - fileIterBegin_;
00627 while(eventsRemainingInFile_ == 0) {
00628 fileIter_ = fileIterBegin_ + flatDistribution_->fireInt(fileCatalogItems().size());
00629 unsigned int newSeqNumber = fileIter_ - fileIterBegin_;
00630 if(newSeqNumber != currentSeqNumber) {
00631 initFile(false);
00632 currentSeqNumber = newSeqNumber;
00633 }
00634 eventsRemainingInFile_ = rootFile_->eventTree().entries();
00635 if(eventsRemainingInFile_ == 0) {
00636 throw Exception(errors::NotFound) <<
00637 "RootInputFileSequence::readOneRandom(): Secondary Input file " << fileIter_->fileName() << " contains no events.\n";
00638 }
00639 rootFile_->setAtEventEntry(flatDistribution_->fireInt(eventsRemainingInFile_) - 1);
00640 }
00641 rootFile_->nextEventEntry();
00642
00643 EventPrincipal* ep = rootFile_->clearAndReadCurrentEvent(rootFile_->secondaryEventPrincipal());
00644 if(ep == 0) {
00645 rootFile_->setAtEventEntry(0);
00646 ep = rootFile_->clearAndReadCurrentEvent(rootFile_->secondaryEventPrincipal());
00647 assert(ep != 0);
00648 }
00649 --eventsRemainingInFile_;
00650 return ep;
00651 }
00652
00653 void
00654 RootInputFileSequence::fillDescription(ParameterSetDescription & desc) {
00655 desc.addUntracked<unsigned int>("skipEvents", 0U)
00656 ->setComment("Skip the first 'skipEvents' events that otherwise would have been processed.");
00657 desc.addUntracked<bool>("noEventSort", true)
00658 ->setComment("True: Process runs, lumis and events in the order they appear in the file (but see notes 1 and 2).\n"
00659 "False: Process runs, lumis and events in each file in numerical order (run#, lumi#, event#) (but see note 3).\n"
00660 "Note 1: Events within the same lumi will always be processed contiguously.\n"
00661 "Note 2: Lumis within the same run will always be processed contiguously.\n"
00662 "Note 3: Any sorting occurs independently in each input file (no sorting across input files).");
00663 desc.addUntracked<bool>("skipBadFiles", false)
00664 ->setComment("True: Ignore any missing or unopenable input file.\n"
00665 "False: Throw exception if missing or unopenable input file.");
00666 desc.addUntracked<unsigned int>("cacheSize", roottree::defaultCacheSize)
00667 ->setComment("Size of ROOT TTree prefetch cache. Affects performance.");
00668 desc.addUntracked<int>("treeMaxVirtualSize", -1)
00669 ->setComment("Size of ROOT TTree TBasket cache. Affects performance.");
00670 desc.addUntracked<unsigned int>("setRunNumber", 0U)
00671 ->setComment("If non-zero, change number of first run to this number. Apply same offset to all runs. Allowed only for simulation.");
00672 desc.addUntracked<bool>("dropDescendantsOfDroppedBranches", true)
00673 ->setComment("If True, also drop on input any descendent of any branch dropped on input.");
00674 std::string defaultString("permissive");
00675 desc.addUntracked<std::string>("parametersMustMatch", defaultString)
00676 ->setComment("'strict': Values of tracked parameters must be unique across all input files.\n"
00677 "'permissive': Values of tracked parameters may differ across or within files.");
00678 desc.addUntracked<std::string>("branchesMustMatch", defaultString)
00679 ->setComment("'strict': Branches in each input file must match those in the first file.\n"
00680 "'permissive': Branches in each input file may be any subset of those in the first file.");
00681
00682 GroupSelectorRules::fillDescription(desc, "inputCommands");
00683 EventSkipperByID::fillDescription(desc);
00684 DuplicateChecker::fillDescription(desc);
00685 }
00686
00687 ProcessingController::ForwardState
00688 RootInputFileSequence::forwardState() const {
00689 if(rootFile_) {
00690 if(!rootFile_->wasLastEventJustRead()) {
00691 return ProcessingController::kEventsAheadInFile;
00692 }
00693 std::vector<FileCatalogItem>::const_iterator itr(fileIter_);
00694 if(itr != fileIterEnd_) ++itr;
00695 if(itr != fileIterEnd_) {
00696 return ProcessingController::kNextFileExists;
00697 }
00698 return ProcessingController::kAtLastEvent;
00699 }
00700 return ProcessingController::kUnknownForward;
00701 }
00702
00703 ProcessingController::ReverseState
00704 RootInputFileSequence::reverseState() const {
00705 if(rootFile_) {
00706 if(!rootFile_->wasFirstEventJustRead()) {
00707 return ProcessingController::kEventsBackwardsInFile;
00708 }
00709 if(fileIter_ != fileIterBegin_) {
00710 return ProcessingController::kPreviousFileExists;
00711 }
00712 return ProcessingController::kAtFirstEvent;
00713 }
00714 return ProcessingController::kUnknownReverse;
00715 }
00716 }