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