CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/DataFormats/Provenance/src/IndexIntoFile.cc

Go to the documentation of this file.
00001 #include "DataFormats/Provenance/interface/IndexIntoFile.h"
00002 #include "DataFormats/Provenance/interface/FullHistoryToReducedHistoryMap.h"
00003 #include "DataFormats/Provenance/interface/ProcessHistoryRegistry.h"
00004 #include "FWCore/Utilities/interface/Algorithms.h"
00005 #include "FWCore/Utilities/interface/EDMException.h"
00006 
00007 #include <algorithm>
00008 #include <iomanip>
00009 #include <ostream>
00010 
00011 namespace edm {
00012 
00013   int const IndexIntoFile::invalidIndex;
00014   RunNumber_t const IndexIntoFile::invalidRun;
00015   LuminosityBlockNumber_t const IndexIntoFile::invalidLumi;
00016   EventNumber_t const IndexIntoFile::invalidEvent;
00017   IndexIntoFile::EntryNumber_t const IndexIntoFile::invalidEntry;
00018 
00019   IndexIntoFile::Transients::Transients() : previousAddedIndex_(invalidIndex),
00020                                             runToFirstEntry_(),
00021                                             lumiToFirstEntry_(),
00022                                             beginEvents_(invalidEntry),
00023                                             endEvents_(invalidEntry),
00024                                             currentIndex_(invalidIndex),
00025                                             currentRun_(invalidRun),
00026                                             currentLumi_(invalidLumi),
00027                                             numberOfEvents_(0),
00028                                             eventFinder_(),
00029                                             runOrLumiIndexes_(),
00030                                             eventNumbers_(),
00031                                             eventEntries_(),
00032                                             unsortedEventNumbers_() {
00033   }
00034 
00035   void
00036   IndexIntoFile::Transients::reset() {
00037     previousAddedIndex_ = invalidIndex;
00038     runToFirstEntry_.clear();
00039     lumiToFirstEntry_.clear();
00040     beginEvents_ = invalidEntry;
00041     endEvents_ = invalidEntry;
00042     currentIndex_ = invalidIndex;
00043     currentRun_ = invalidRun;
00044     currentLumi_ = invalidLumi;
00045     numberOfEvents_ = 0;
00046     eventFinder_.reset();
00047     runOrLumiIndexes_.clear();
00048     eventNumbers_.clear();
00049     eventEntries_.clear();
00050     unsortedEventNumbers_.clear();
00051   }
00052 
00053   IndexIntoFile::IndexIntoFile() : transient_(),
00054                                    processHistoryIDs_(),
00055                                    runOrLumiEntries_() {
00056   }
00057 
00058   IndexIntoFile::~IndexIntoFile() {
00059   }
00060 
00061   ProcessHistoryID const& IndexIntoFile::processHistoryID(int i) const {
00062     return processHistoryIDs_.at(i);
00063   }
00064 
00065   std::vector<ProcessHistoryID> const& IndexIntoFile::processHistoryIDs() const {
00066     return processHistoryIDs_;
00067   }
00068 
00069   void
00070   IndexIntoFile::addEntry(ProcessHistoryID const& processHistoryID,
00071                           RunNumber_t run,
00072                           LuminosityBlockNumber_t lumi,
00073                           EventNumber_t event,
00074                           EntryNumber_t entry) {
00075     int index = 0;
00076     // First see if the ProcessHistoryID is the same as the previous one.
00077     // This is just a performance optimization.  We expect to usually get
00078     // many in a row that are the same.
00079     if(previousAddedIndex() != invalidIndex &&
00080        processHistoryID == processHistoryIDs_[previousAddedIndex()]) {
00081       index = previousAddedIndex();
00082     } else {
00083       // If it was not the same as the previous one then search through the
00084       // entire vector.  If it is not there, it needs to be added at the
00085       // end.
00086       index = 0;
00087       while(index < static_cast<int>(processHistoryIDs_.size()) &&
00088             processHistoryIDs_[index] != processHistoryID) {
00089         ++index;
00090       }
00091       if(index == static_cast<int>(processHistoryIDs_.size())) {
00092         processHistoryIDs_.push_back(processHistoryID);
00093       }
00094     }
00095     previousAddedIndex() = index;
00096 
00097     assert((currentRun() == run && currentIndex() == index) || currentRun() == invalidRun);
00098     if(lumi == invalidLumi) {
00099       if(currentLumi() != invalidLumi) {
00100         throw Exception(errors::LogicError)
00101           << "In IndexIntoFile::addEntry. Entries were added in illegal order.\n"
00102           << "This means the IndexIntoFile product in the output file will be corrupted.\n"
00103           << "The output file will be unusable for most purposes.\n"
00104           << "If this occurs after an unrelated exception was thrown in\n"
00105           << "endLuminosityBlock or endRun then ignore this exception and fix\n"
00106           << "the primary exception. This is an expected side effect.\n"
00107           << "Otherwise please report this to the core framework developers\n";
00108       }
00109       currentIndex() = invalidIndex;
00110       currentRun() = invalidRun;
00111       currentLumi() = invalidLumi;
00112       std::pair<IndexRunKey, EntryNumber_t> firstRunEntry(IndexRunKey(index, run), entry);
00113       runToFirstEntry().insert(firstRunEntry);
00114       RunOrLumiEntry runEntry(runToFirstEntry()[IndexRunKey(index, run)], invalidEntry, entry, index, run, lumi, invalidEntry, invalidEntry);
00115       runOrLumiEntries_.push_back(runEntry);
00116     } else {
00117       assert(currentLumi() == lumi || currentLumi() == invalidLumi);
00118       if(currentRun() == invalidRun) {
00119         currentRun() = run;
00120         currentIndex() = index;
00121       }
00122       if(event == invalidEvent) {
00123         currentLumi() = invalidLumi;
00124         std::pair<IndexRunLumiKey, EntryNumber_t> firstLumiEntry(IndexRunLumiKey(index, run, lumi), entry);
00125         lumiToFirstEntry().insert(firstLumiEntry);
00126         RunOrLumiEntry lumiEntry(invalidEntry, lumiToFirstEntry()[IndexRunLumiKey(index, run, lumi)],
00127                                  entry, index, run, lumi, beginEvents(), endEvents());
00128         runOrLumiEntries_.push_back(lumiEntry);
00129         beginEvents() = invalidEntry;
00130         endEvents() = invalidEntry;
00131       } else {
00132         setNumberOfEvents(numberOfEvents() + 1);
00133         if(beginEvents() == invalidEntry) {
00134           currentLumi() = lumi;
00135           beginEvents() = entry;
00136           endEvents() = beginEvents() + 1;
00137         }
00138         else {
00139           assert(currentLumi() == lumi);
00140           assert(entry == endEvents());
00141           ++endEvents();
00142         }
00143       }
00144     }
00145   }
00146 
00147   void IndexIntoFile::fillRunOrLumiIndexes() const {
00148     if(runOrLumiEntries_.empty() || !runOrLumiIndexes().empty()) {
00149       return;
00150     }
00151     runOrLumiIndexes().reserve(runOrLumiEntries_.size());
00152 
00153     int index = 0;
00154     for(std::vector<RunOrLumiEntry>::const_iterator iter = runOrLumiEntries_.begin(),
00155                                                     iEnd = runOrLumiEntries_.end();
00156          iter != iEnd;
00157          ++iter, ++index) {
00158       runOrLumiIndexes().emplace_back(iter->processHistoryIDIndex(),
00159                                       iter->run(),
00160                                       iter->lumi(),
00161                                       index);
00162     }
00163     stable_sort_all(runOrLumiIndexes());
00164 
00165     long long beginEventNumbers = 0;
00166 
00167     std::vector<RunOrLumiIndexes>::iterator beginOfLumi = runOrLumiIndexes().begin();
00168     std::vector<RunOrLumiIndexes>::iterator endOfLumi = beginOfLumi;
00169     std::vector<RunOrLumiIndexes>::iterator iEnd = runOrLumiIndexes().end();
00170     while(true) {
00171       while(beginOfLumi != iEnd && beginOfLumi->isRun()) {
00172         ++beginOfLumi;
00173       }
00174       if(beginOfLumi == iEnd) break;
00175 
00176       endOfLumi = beginOfLumi + 1;
00177       while(endOfLumi != iEnd &&
00178              beginOfLumi->processHistoryIDIndex() == endOfLumi->processHistoryIDIndex() &&
00179              beginOfLumi->run() == endOfLumi->run() &&
00180              beginOfLumi->lumi() == endOfLumi->lumi()) {
00181         ++endOfLumi;
00182       }
00183       int nEvents = 0;
00184       for(std::vector<RunOrLumiIndexes>::iterator iter = beginOfLumi;
00185           iter != endOfLumi;
00186              ++iter) {
00187         if(runOrLumiEntries_[iter->indexToGetEntry()].beginEvents() != invalidEntry) {
00188           nEvents += runOrLumiEntries_[iter->indexToGetEntry()].endEvents() -
00189                      runOrLumiEntries_[iter->indexToGetEntry()].beginEvents();
00190         }
00191       }
00192       for(std::vector<RunOrLumiIndexes>::iterator iter = beginOfLumi;
00193           iter != endOfLumi;
00194              ++iter) {
00195         iter->setBeginEventNumbers(beginEventNumbers);
00196         iter->setEndEventNumbers(beginEventNumbers + nEvents);
00197       }
00198       beginEventNumbers += nEvents;
00199       beginOfLumi = endOfLumi;
00200     }
00201     assert(runOrLumiIndexes().size() == runOrLumiEntries_.size());
00202   }
00203 
00204   void
00205   IndexIntoFile::fillEventNumbers() const {
00206     fillEventNumbersOrEntries(true, false);
00207   }
00208 
00209   void
00210   IndexIntoFile::fillEventEntries() const {
00211     fillEventNumbersOrEntries(false, true);
00212   }
00213 
00214   void
00215   IndexIntoFile::fillEventNumbersOrEntries(bool needEventNumbers, bool needEventEntries) const {
00216     if(numberOfEvents() == 0) {
00217       return;
00218     }
00219 
00220     if(needEventNumbers && !eventNumbers().empty()) {
00221       needEventNumbers = false;
00222     }
00223 
00224     if(needEventEntries && !eventEntries().empty()) {
00225       needEventEntries = false;
00226     }
00227 
00228     if(needEventNumbers && !eventEntries().empty()) {
00229       assert(numberOfEvents() == eventEntries().size());
00230       eventNumbers().reserve(eventEntries().size());
00231       for(std::vector<EventNumber_t>::size_type entry = 0U; entry < numberOfEvents(); ++entry) {
00232         eventNumbers().push_back(eventEntries()[entry].event());
00233       }
00234       return;
00235     }
00236 
00237     if(!needEventNumbers && !needEventEntries) {
00238       return;
00239     }
00240 
00241     fillUnsortedEventNumbers();
00242 
00243     if(needEventNumbers) {
00244       eventNumbers().resize(numberOfEvents(), IndexIntoFile::invalidEvent);
00245     }
00246     if(needEventEntries) {
00247       eventEntries().resize(numberOfEvents());
00248     }
00249 
00250     long long offset = 0;
00251     long long previousBeginEventNumbers = -1LL;
00252 
00253     for(SortedRunOrLumiItr runOrLumi = beginRunOrLumi(), runOrLumiEnd = endRunOrLumi();
00254         runOrLumi != runOrLumiEnd; ++runOrLumi) {
00255 
00256       if(runOrLumi.isRun()) continue;
00257 
00258       long long beginEventNumbers = 0;
00259       long long endEventNumbers = 0;
00260       EntryNumber_t beginEventEntry = -1LL;
00261       EntryNumber_t endEventEntry = -1LL;
00262       runOrLumi.getRange(beginEventNumbers, endEventNumbers, beginEventEntry, endEventEntry);
00263 
00264       // This is true each time one hits a new lumi section (except if the previous lumi had
00265       // no events, in which case the offset is still 0 anyway)
00266       if(beginEventNumbers != previousBeginEventNumbers) offset = 0;
00267 
00268       for(EntryNumber_t entry = beginEventEntry; entry != endEventEntry; ++entry) {
00269         if(needEventNumbers) {
00270           eventNumbers().at((entry - beginEventEntry) + offset + beginEventNumbers) = unsortedEventNumbers().at(entry);
00271         }
00272         if(needEventEntries) {
00273           eventEntries().at((entry - beginEventEntry) + offset + beginEventNumbers) =
00274             EventEntry(unsortedEventNumbers().at(entry), entry);
00275         }
00276       }
00277 
00278       previousBeginEventNumbers = beginEventNumbers;
00279       offset += endEventEntry - beginEventEntry;
00280     }
00281     if(needEventNumbers) {
00282       sortEvents();
00283       assert(numberOfEvents() == eventNumbers().size());
00284     }
00285     if(needEventEntries) {
00286       sortEventEntries();
00287       assert(numberOfEvents() == eventEntries().size());
00288     }
00289   }
00290 
00291   void
00292   IndexIntoFile::fillUnsortedEventNumbers() const {
00293     if(numberOfEvents() == 0 || !unsortedEventNumbers().empty()) {
00294       return;
00295     }
00296     unsortedEventNumbers().reserve(numberOfEvents());
00297 
00298     // The main purpose for the existence of the unsortedEventNumbers
00299     // vector is that it can easily be filled by reading through
00300     // the EventAuxiliary branch in the same order as the TTree
00301     // entries. fillEventNumbersOrEntries can then use this information
00302     // instead of using getEventNumberOfEntry directly and reading
00303     // the branch in a different order.
00304     for(std::vector<EventNumber_t>::size_type entry = 0U; entry < numberOfEvents(); ++entry) {
00305       unsortedEventNumbers().push_back(getEventNumberOfEntry(entry));
00306     }
00307   }
00308 
00309   // We are closing the input file, but we need to keep event numbers.
00310   // We can delete the other transient collections by using the swap trick.
00311 
00312   void
00313   IndexIntoFile::inputFileClosed() const {
00314     std::vector<EventEntry>().swap(eventEntries());
00315     std::vector<RunOrLumiIndexes>().swap(runOrLumiIndexes());
00316     std::vector<EventNumber_t>().swap(unsortedEventNumbers());
00317     resetEventFinder();
00318   }
00319 
00320   void
00321   IndexIntoFile::doneFileInitialization() const {
00322     std::vector<EventNumber_t>().swap(unsortedEventNumbers());
00323   }
00324 
00325   void
00326   IndexIntoFile::reduceProcessHistoryIDs() {
00327 
00328     FullHistoryToReducedHistoryMap & phidConverter(ProcessHistoryRegistry::instance()->extra());
00329 
00330     std::vector<ProcessHistoryID> reducedPHIDs;
00331 
00332     std::map<ProcessHistoryID, int> reducedPHIDToIndex;
00333     std::pair<ProcessHistoryID, int> mapEntry(ProcessHistoryID(), 0);
00334     std::pair<std::map<ProcessHistoryID, int>::iterator, bool> insertResult;
00335 
00336     std::vector<int> phidIndexConverter;
00337     for(std::vector<ProcessHistoryID>::const_iterator phid = processHistoryIDs_.begin(),
00338          iEnd = processHistoryIDs_.end();
00339          phid != iEnd; ++phid) {
00340 
00341       ProcessHistoryID const& reducedPHID = phidConverter.reduceProcessHistoryID(*phid);
00342       mapEntry.first = reducedPHID;
00343       insertResult = reducedPHIDToIndex.insert(mapEntry);
00344 
00345       if(insertResult.second) {
00346         insertResult.first->second = reducedPHIDs.size();
00347         reducedPHIDs.push_back(reducedPHID);
00348       }
00349       phidIndexConverter.push_back(insertResult.first->second);
00350     }
00351     processHistoryIDs_.swap(reducedPHIDs);
00352 
00353     // If the size of the vector of IDs does not change
00354     // then their indexes and the ordering of the Runs and
00355     // and Lumis does not change, so we are done.
00356     if(processHistoryIDs_.size() == reducedPHIDs.size()) {
00357       return;
00358     }
00359 
00360     std::map<IndexIntoFile::IndexRunKey, int> runOrderMap;
00361     std::pair<std::map<IndexIntoFile::IndexRunKey, int>::iterator, bool> runInsertResult;
00362 
00363     std::map<IndexIntoFile::IndexRunLumiKey, int> lumiOrderMap;
00364     std::pair<std::map<IndexIntoFile::IndexRunLumiKey, int>::iterator, bool> lumiInsertResult;
00365 
00366     // loop over all the RunOrLumiEntry's
00367     for(std::vector<RunOrLumiEntry>::iterator i = runOrLumiEntries_.begin(),
00368          iterEnd = runOrLumiEntries_.end();
00369          i != iterEnd; ++i) {
00370 
00371       // Convert the process history index so it points into the new vector of reduced IDs
00372       i->setProcessHistoryIDIndex(phidIndexConverter.at(i->processHistoryIDIndex()));
00373 
00374       // Convert the phid-run order
00375       IndexIntoFile::IndexRunKey runKey(i->processHistoryIDIndex(), i->run());
00376       runInsertResult = runOrderMap.insert(std::pair<IndexIntoFile::IndexRunKey, int>(runKey,0));
00377       if(runInsertResult.second) {
00378         runInsertResult.first->second = i->orderPHIDRun();
00379       } else {
00380         i->setOrderPHIDRun(runInsertResult.first->second);
00381       }
00382 
00383       // Convert the phid-run-lumi order for the lumi entries
00384       if(i->lumi() != 0) {
00385         IndexIntoFile::IndexRunLumiKey lumiKey(i->processHistoryIDIndex(), i->run(), i->lumi());
00386         lumiInsertResult = lumiOrderMap.insert(std::pair<IndexIntoFile::IndexRunLumiKey, int>(lumiKey,0));
00387         if(lumiInsertResult.second) {
00388           lumiInsertResult.first->second = i->orderPHIDRunLumi();
00389         } else {
00390           i->setOrderPHIDRunLumi(lumiInsertResult.first->second);
00391         }
00392       }
00393     }
00394     std::stable_sort(runOrLumiEntries_.begin(), runOrLumiEntries_.end());
00395   }
00396 
00397   void
00398   IndexIntoFile::fixIndexes(std::vector<ProcessHistoryID> & processHistoryIDs) {
00399 
00400     std::map<int, int> oldToNewIndex;
00401     for(std::vector<ProcessHistoryID>::const_iterator iter = processHistoryIDs_.begin(),
00402                                                       iEnd = processHistoryIDs_.end();
00403          iter != iEnd;
00404          ++iter) {
00405       std::vector<ProcessHistoryID>::const_iterator iterExisting =
00406         std::find(processHistoryIDs.begin(), processHistoryIDs.end(), *iter);
00407       if(iterExisting == processHistoryIDs.end()) {
00408         oldToNewIndex[iter - processHistoryIDs_.begin()] = processHistoryIDs.size();
00409         processHistoryIDs.push_back(*iter);
00410       } else {
00411         oldToNewIndex[iter - processHistoryIDs_.begin()] = iterExisting - processHistoryIDs.begin();
00412       }
00413     }
00414     processHistoryIDs_ = processHistoryIDs;
00415 
00416     for(std::vector<RunOrLumiEntry>::iterator iter = runOrLumiEntries_.begin(),
00417                                                iEnd = runOrLumiEntries_.end();
00418          iter != iEnd;
00419          ++iter) {
00420       iter->setProcessHistoryIDIndex(oldToNewIndex[iter->processHistoryIDIndex()]);
00421     }
00422   }
00423 
00424   void IndexIntoFile::sortVector_Run_Or_Lumi_Entries() {
00425     for(std::vector<RunOrLumiEntry>::iterator iter = runOrLumiEntries_.begin(),
00426                                                iEnd = runOrLumiEntries_.end();
00427          iter != iEnd;
00428          ++iter) {
00429       std::map<IndexRunKey, EntryNumber_t>::const_iterator firstRunEntry =
00430         runToFirstEntry().find(IndexRunKey(iter->processHistoryIDIndex(), iter->run()));
00431       if(firstRunEntry == runToFirstEntry().end()) {
00432         throw Exception(errors::LogicError)
00433           << "In IndexIntoFile::sortVector_Run_Or_Lumi_Entries. A run entry is missing.\n"
00434           << "This means the IndexIntoFile product in the output file will be corrupted.\n"
00435           << "The output file will be unusable for most purposes.\n"
00436           << "If this occurs after an unrelated exception was thrown in\n"
00437           << "endLuminosityBlock or endRun then ignore this exception and fix\n"
00438           << "the primary exception. This is an expected side effect.\n"
00439           << "Otherwise please report this to the core framework developers\n";
00440       }
00441       iter->setOrderPHIDRun(firstRunEntry->second);
00442     }
00443     stable_sort_all(runOrLumiEntries_);
00444   }
00445 
00446   void IndexIntoFile::sortEvents() const {
00447     fillRunOrLumiIndexes();
00448     std::vector<RunOrLumiIndexes>::iterator beginOfLumi = runOrLumiIndexes().begin();
00449     std::vector<RunOrLumiIndexes>::iterator endOfLumi = beginOfLumi;
00450     std::vector<RunOrLumiIndexes>::iterator iEnd = runOrLumiIndexes().end();
00451     while(true) {
00452       while(beginOfLumi != iEnd && beginOfLumi->isRun()) {
00453         ++beginOfLumi;
00454       }
00455       if(beginOfLumi == iEnd) break;
00456 
00457       endOfLumi = beginOfLumi + 1;
00458       while(endOfLumi != iEnd &&
00459              beginOfLumi->processHistoryIDIndex() == endOfLumi->processHistoryIDIndex() &&
00460              beginOfLumi->run() == endOfLumi->run() &&
00461              beginOfLumi->lumi() == endOfLumi->lumi()) {
00462         ++endOfLumi;
00463       }
00464       assert(beginOfLumi->endEventNumbers() >= 0);
00465       assert(beginOfLumi->endEventNumbers() <= static_cast<long long>(eventNumbers().size()));
00466       std::sort(eventNumbers().begin() + beginOfLumi->beginEventNumbers(),
00467                 eventNumbers().begin() + beginOfLumi->endEventNumbers());
00468       beginOfLumi = endOfLumi;
00469     }
00470   }
00471 
00472   void IndexIntoFile::sortEventEntries() const {
00473     fillRunOrLumiIndexes();
00474     std::vector<RunOrLumiIndexes>::iterator beginOfLumi = runOrLumiIndexes().begin();
00475     std::vector<RunOrLumiIndexes>::iterator endOfLumi = beginOfLumi;
00476     std::vector<RunOrLumiIndexes>::iterator iEnd = runOrLumiIndexes().end();
00477     while(true) {
00478       while(beginOfLumi != iEnd && beginOfLumi->isRun()) {
00479         ++beginOfLumi;
00480       }
00481       if(beginOfLumi == iEnd) break;
00482 
00483       endOfLumi = beginOfLumi + 1;
00484       while(endOfLumi != iEnd &&
00485             beginOfLumi->processHistoryIDIndex() == endOfLumi->processHistoryIDIndex() &&
00486             beginOfLumi->run() == endOfLumi->run() &&
00487             beginOfLumi->lumi() == endOfLumi->lumi()) {
00488         ++endOfLumi;
00489       }
00490       assert(beginOfLumi->endEventNumbers() >= 0);
00491       assert(beginOfLumi->endEventNumbers() <=  static_cast<long long>(eventEntries().size()));
00492       std::sort(eventEntries().begin() + beginOfLumi->beginEventNumbers(),
00493                 eventEntries().begin() + beginOfLumi->endEventNumbers());
00494       beginOfLumi = endOfLumi;
00495     }
00496   }
00497 
00498   IndexIntoFile::IndexIntoFileItr IndexIntoFile::begin(SortOrder sortOrder) const {
00499     if(empty()) {
00500       return end(sortOrder);
00501     }
00502     IndexIntoFileItr iter(this,
00503                           sortOrder,
00504                           kRun,
00505                           0,
00506                           invalidIndex,
00507                           invalidIndex,
00508                           0,
00509                           0);
00510     iter.initializeRun();
00511     return iter;
00512   }
00513 
00514   IndexIntoFile::IndexIntoFileItr IndexIntoFile::end(SortOrder sortOrder) const {
00515     return IndexIntoFileItr(this,
00516                             sortOrder,
00517                             kEnd,
00518                             invalidIndex,
00519                             invalidIndex,
00520                             invalidIndex,
00521                             0,
00522                             0);
00523   }
00524 
00525   bool IndexIntoFile::iterationWillBeInEntryOrder(SortOrder sortOrder) const {
00526     EntryNumber_t maxEntry = invalidEntry;
00527     for(IndexIntoFileItr it = begin(sortOrder), itEnd = end(sortOrder); it != itEnd; ++it) {
00528       if(it.getEntryType() == kEvent) {
00529         if(it.entry() < maxEntry) {
00530           return false;
00531         }
00532         maxEntry = it.entry();
00533       }
00534     }
00535     return true;
00536   }
00537 
00538   bool IndexIntoFile::empty() const {
00539     return runOrLumiEntries().empty();
00540   }
00541 
00542   IndexIntoFile::IndexIntoFileItr
00543   IndexIntoFile::findPosition(RunNumber_t run, LuminosityBlockNumber_t lumi, EventNumber_t event) const {
00544     fillRunOrLumiIndexes();
00545 
00546     bool lumiMissing = (lumi == 0 && event != 0);
00547 
00548     std::vector<RunOrLumiIndexes>::const_iterator it;
00549     std::vector<RunOrLumiIndexes>::const_iterator iEnd = runOrLumiIndexes().end();
00550     std::vector<RunOrLumiIndexes>::const_iterator phEnd;
00551 
00552     // Loop over ranges of entries with the same ProcessHistoryID
00553     for(std::vector<RunOrLumiIndexes>::const_iterator phBegin = runOrLumiIndexes().begin();
00554          phBegin != iEnd;
00555          phBegin = phEnd) {
00556 
00557       RunOrLumiIndexes el(phBegin->processHistoryIDIndex(), run, lumi, 0);
00558       phEnd = std::upper_bound(phBegin, iEnd, el, Compare_Index());
00559 
00560       std::vector<RunOrLumiIndexes>::const_iterator iRun = std::lower_bound(phBegin, phEnd, el, Compare_Index_Run());
00561 
00562       if(iRun == phEnd || iRun->run() != run) continue;
00563 
00564       if(lumi == invalidLumi && event == invalidEvent) {
00565         IndexIntoFileItr indexItr(this,
00566                                   numericalOrder,
00567                                   kRun,
00568                                   iRun - runOrLumiIndexes().begin(),
00569                                   invalidIndex,
00570                                   invalidIndex,
00571                                   0,
00572                                   0);
00573         indexItr.initializeRun();
00574         return indexItr;
00575       }
00576 
00577       std::vector<RunOrLumiIndexes>::const_iterator iRunEnd = std::upper_bound(iRun, phEnd, el, Compare_Index_Run());
00578       if(!lumiMissing) {
00579 
00580         std::vector<RunOrLumiIndexes>::const_iterator iLumi = std::lower_bound(iRun, iRunEnd, el);
00581         if(iLumi == iRunEnd || iLumi->lumi() != lumi) continue;
00582 
00583         if(event == invalidEvent) {
00584           IndexIntoFileItr indexItr(this,
00585                                     numericalOrder,
00586                                     kRun,
00587                                     iRun - runOrLumiIndexes().begin(),
00588                                     iLumi - runOrLumiIndexes().begin(),
00589                                     invalidIndex,
00590                                     0,
00591                                     0);
00592           indexItr.initializeLumi();
00593           return indexItr;
00594         }
00595 
00596         long long beginEventNumbers = iLumi->beginEventNumbers();
00597         long long endEventNumbers = iLumi->endEventNumbers();
00598         if(beginEventNumbers >= endEventNumbers) continue;
00599 
00600 
00601         long long indexToEvent = 0;
00602         if(!eventEntries().empty()) {
00603           std::vector<EventEntry>::const_iterator eventIter = std::lower_bound(eventEntries().begin() + beginEventNumbers,
00604                                                                                eventEntries().begin() + endEventNumbers,
00605                                                                                EventEntry(event, invalidEntry));
00606           if(eventIter == (eventEntries().begin() + endEventNumbers) ||
00607               eventIter->event() != event) continue;
00608 
00609           indexToEvent = eventIter - eventEntries().begin() - beginEventNumbers;
00610         } else {
00611           fillEventNumbers();
00612           std::vector<EventNumber_t>::const_iterator eventIter = std::lower_bound(eventNumbers().begin() + beginEventNumbers,
00613                                                                                   eventNumbers().begin() + endEventNumbers,
00614                                                                                   event);
00615           if(eventIter == (eventNumbers().begin() + endEventNumbers) ||
00616               *eventIter != event) continue;
00617 
00618           indexToEvent = eventIter - eventNumbers().begin() - beginEventNumbers;
00619         }
00620         return IndexIntoFileItr(this,
00621                                 numericalOrder,
00622                                 kRun,
00623                                 iRun - runOrLumiIndexes().begin(),
00624                                 iLumi - runOrLumiIndexes().begin(),
00625                                 iLumi - runOrLumiIndexes().begin(),
00626                                 indexToEvent,
00627                                 endEventNumbers - beginEventNumbers);
00628       }
00629       if(lumiMissing) {
00630 
00631         std::vector<RunOrLumiIndexes>::const_iterator iLumi = iRun;
00632         while(iLumi != iRunEnd && iLumi->lumi() == invalidLumi) {
00633           ++iLumi;
00634         }
00635         if(iLumi == iRunEnd) continue;
00636 
00637         std::vector<RunOrLumiIndexes>::const_iterator lumiEnd;
00638         for( ;
00639              iLumi != iRunEnd;
00640              iLumi = lumiEnd) {
00641 
00642           RunOrLumiIndexes elWithLumi(phBegin->processHistoryIDIndex(), run, iLumi->lumi(), 0);
00643           lumiEnd = std::upper_bound(iLumi, iRunEnd, elWithLumi);
00644 
00645           long long beginEventNumbers = iLumi->beginEventNumbers();
00646           long long endEventNumbers = iLumi->endEventNumbers();
00647           if(beginEventNumbers >= endEventNumbers) continue;
00648 
00649           long long indexToEvent = 0;
00650           if(!eventEntries().empty()) {
00651             std::vector<EventEntry>::const_iterator eventIter = std::lower_bound(eventEntries().begin() + beginEventNumbers,
00652                                                                                  eventEntries().begin() + endEventNumbers,
00653                                                                                  EventEntry(event, invalidEntry));
00654             if(eventIter == (eventEntries().begin() + endEventNumbers) ||
00655                 eventIter->event() != event) continue;
00656             indexToEvent = eventIter - eventEntries().begin() - beginEventNumbers;
00657           } else {
00658             fillEventNumbers();
00659             std::vector<EventNumber_t>::const_iterator eventIter = std::lower_bound(eventNumbers().begin() + beginEventNumbers,
00660                                                                                     eventNumbers().begin() + endEventNumbers,
00661                                                                                     event);
00662             if(eventIter == (eventNumbers().begin() + endEventNumbers) ||
00663                 *eventIter != event) continue;
00664             indexToEvent = eventIter - eventNumbers().begin() - beginEventNumbers;
00665           }
00666           return IndexIntoFileItr(this,
00667                                   numericalOrder,
00668                                   kRun,
00669                                   iRun - runOrLumiIndexes().begin(),
00670                                   iLumi - runOrLumiIndexes().begin(),
00671                                   iLumi - runOrLumiIndexes().begin(),
00672                                   indexToEvent,
00673                                   endEventNumbers - beginEventNumbers);
00674         }
00675       }
00676     } // Loop over ProcessHistoryIDs
00677 
00678     return IndexIntoFileItr(this,
00679                             numericalOrder,
00680                             kEnd,
00681                             invalidIndex,
00682                             invalidIndex,
00683                             invalidIndex,
00684                             0,
00685                             0);
00686 
00687   }
00688 
00689   IndexIntoFile::IndexIntoFileItr
00690   IndexIntoFile::findPosition(SortOrder sortOrder, RunNumber_t run, LuminosityBlockNumber_t lumi, EventNumber_t event) const {
00691     if(sortOrder == IndexIntoFile::numericalOrder) {
00692       return findPosition(run, lumi, event); // a faster algorithm
00693     }
00694     IndexIntoFileItr itr = begin(sortOrder);
00695     IndexIntoFileItr itrEnd = end(sortOrder);
00696 
00697     while(itr != itrEnd) {
00698       if(itr.run() != run) {
00699         itr.advanceToNextRun();
00700       } else {
00701         if(lumi == invalidLumi && event == invalidEvent) {
00702           return itr;
00703         } else if(lumi != invalidLumi && itr.peekAheadAtLumi() != lumi) {
00704           if(!itr.skipLumiInRun()) {
00705             itr.advanceToNextRun();
00706           }
00707         } else {
00708           if(event == invalidEvent) {
00709             return itr;
00710           } else {
00711             EventNumber_t eventNumber = getEventNumberOfEntry(itr.peekAheadAtEventEntry());
00712             if(eventNumber == event) {
00713               return itr;
00714             } else {
00715               if(!itr.skipToNextEventInLumi()) {
00716                 if(!itr.skipLumiInRun()) {
00717                   itr.advanceToNextRun();
00718                 }
00719               }
00720             }
00721           }
00722         }
00723       }
00724     }
00725     return itrEnd;
00726   }
00727 
00728   IndexIntoFile::IndexIntoFileItr
00729   IndexIntoFile::findEventPosition(RunNumber_t run, LuminosityBlockNumber_t lumi, EventNumber_t event) const {
00730     assert(event != invalidEvent);
00731     IndexIntoFileItr iter = findPosition(run, lumi, event);
00732     iter.advanceToEvent();
00733     return iter;
00734   }
00735 
00736   IndexIntoFile::IndexIntoFileItr
00737   IndexIntoFile::findLumiPosition(RunNumber_t run, LuminosityBlockNumber_t lumi) const {
00738     assert(lumi != invalidLumi);
00739     IndexIntoFileItr iter = findPosition(run, lumi, 0U);
00740     iter.advanceToLumi();
00741     return iter;
00742   }
00743 
00744   IndexIntoFile::IndexIntoFileItr
00745   IndexIntoFile::findRunPosition(RunNumber_t run) const {
00746     return findPosition(run, 0U, 0U);
00747   }
00748 
00749   bool
00750   IndexIntoFile::containsItem(RunNumber_t run, LuminosityBlockNumber_t lumi, EventNumber_t event) const {
00751         return event ? containsEvent(run, lumi, event) : (lumi ? containsLumi(run, lumi) : containsRun(run));
00752   }
00753 
00754   bool
00755   IndexIntoFile::containsEvent(RunNumber_t run, LuminosityBlockNumber_t lumi, EventNumber_t event) const {
00756         return findEventPosition(run, lumi, event).getEntryType() != kEnd;
00757   }
00758 
00759   bool
00760   IndexIntoFile::containsLumi(RunNumber_t run, LuminosityBlockNumber_t lumi) const {
00761     return findLumiPosition(run, lumi).getEntryType() != kEnd;
00762   }
00763 
00764   bool
00765   IndexIntoFile::containsRun(RunNumber_t run) const {
00766     return findRunPosition(run).getEntryType() != kEnd;
00767   }
00768 
00769   IndexIntoFile::SortedRunOrLumiItr IndexIntoFile::beginRunOrLumi() const {
00770     return SortedRunOrLumiItr(this, 0);
00771   }
00772 
00773   IndexIntoFile::SortedRunOrLumiItr IndexIntoFile::endRunOrLumi() const {
00774     return SortedRunOrLumiItr(this, runOrLumiEntries().size());
00775   }
00776 
00777   void IndexIntoFile::set_intersection(IndexIntoFile const& indexIntoFile,
00778                                        std::set<IndexRunLumiEventKey> & intersection) const {
00779 
00780     if(empty() || indexIntoFile.empty()) return;
00781     fillRunOrLumiIndexes();
00782     indexIntoFile.fillRunOrLumiIndexes();
00783     RunOrLumiIndexes const& back1 = runOrLumiIndexes().back();
00784     RunOrLumiIndexes const& back2 = indexIntoFile.runOrLumiIndexes().back();
00785 
00786     // Very quick decision if the run ranges in the two files do not overlap
00787     if(back2 < runOrLumiIndexes().front()) return;
00788     if(back1 < indexIntoFile.runOrLumiIndexes().front()) return;
00789 
00790     SortedRunOrLumiItr iter1 = beginRunOrLumi();
00791     SortedRunOrLumiItr iEnd1 = endRunOrLumi();
00792 
00793     SortedRunOrLumiItr iter2 = indexIntoFile.beginRunOrLumi();
00794     SortedRunOrLumiItr iEnd2 = indexIntoFile.endRunOrLumi();
00795 
00796     // Quick decision if the lumi ranges in the two files do not overlap
00797     while(iter1 != iEnd1 && iter1.isRun()) ++iter1;
00798     if(iter1 == iEnd1) return;
00799     if(back2 < iter1.runOrLumiIndexes()) return;
00800 
00801     while(iter2 != iEnd2 && iter2.isRun()) ++iter2;
00802     if(iter2 == iEnd2) return;
00803     if(back1 < iter2.runOrLumiIndexes()) return;
00804 
00805     RunOrLumiIndexes const* previousIndexes = 0;
00806 
00807     // Loop through the both IndexIntoFile objects and look for matching lumis
00808     while(iter1 != iEnd1 && iter2 != iEnd2) {
00809 
00810       RunOrLumiIndexes const& indexes1 = iter1.runOrLumiIndexes();
00811       RunOrLumiIndexes const& indexes2 = iter2.runOrLumiIndexes();
00812       if(indexes1 < indexes2) {
00813         ++iter1;
00814       } else if(indexes2 < indexes1) {
00815         ++iter2;
00816       } else { // they are equal
00817 
00818         // Skip them if it is a run or the same lumi
00819         if(indexes1.isRun() ||
00820             (previousIndexes && !(*previousIndexes < indexes1))) {
00821           ++iter1;
00822           ++iter2;
00823         } else {
00824           previousIndexes = &indexes1;
00825 
00826           // Found a matching lumi, now look for matching events
00827 
00828           long long beginEventNumbers1 = indexes1.beginEventNumbers();
00829           long long endEventNumbers1 = indexes1.endEventNumbers();
00830 
00831           long long beginEventNumbers2 = indexes2.beginEventNumbers();
00832           long long endEventNumbers2 = indexes2.endEventNumbers();
00833 
00834           // there must be at least 1 event in each lumi for there to be any matches
00835           if((beginEventNumbers1 >= endEventNumbers1) ||
00836               (beginEventNumbers2 >= endEventNumbers2)) {
00837             ++iter1;
00838             ++iter2;
00839             continue;
00840           }
00841 
00842           if(!eventEntries().empty() && !indexIntoFile.eventEntries().empty()) {
00843             std::vector<EventEntry> matchingEvents;
00844             std::insert_iterator<std::vector<EventEntry> > insertIter(matchingEvents, matchingEvents.begin());
00845             std::set_intersection(eventEntries().begin() + beginEventNumbers1,
00846                                   eventEntries().begin() + endEventNumbers1,
00847                                   indexIntoFile.eventEntries().begin() + beginEventNumbers2,
00848                                   indexIntoFile.eventEntries().begin() + endEventNumbers2,
00849                                   insertIter);
00850             for(std::vector<EventEntry>::const_iterator iEvent = matchingEvents.begin(),
00851                                                            iEnd = matchingEvents.end();
00852                  iEvent != iEnd; ++iEvent) {
00853               intersection.insert(IndexRunLumiEventKey(indexes1.processHistoryIDIndex(),
00854                                                        indexes1.run(),
00855                                                        indexes1.lumi(),
00856                                                        iEvent->event()));
00857             }
00858           } else {
00859             fillEventNumbers();
00860             indexIntoFile.fillEventNumbers();
00861             std::vector<EventNumber_t> matchingEvents;
00862             std::insert_iterator<std::vector<EventNumber_t> > insertIter(matchingEvents, matchingEvents.begin());
00863             std::set_intersection(eventNumbers().begin() + beginEventNumbers1,
00864                                   eventNumbers().begin() + endEventNumbers1,
00865                                   indexIntoFile.eventNumbers().begin() + beginEventNumbers2,
00866                                   indexIntoFile.eventNumbers().begin() + endEventNumbers2,
00867                                   insertIter);
00868             for(std::vector<EventNumber_t>::const_iterator iEvent = matchingEvents.begin(),
00869                                                               iEnd = matchingEvents.end();
00870                  iEvent != iEnd; ++iEvent) {
00871               intersection.insert(IndexRunLumiEventKey(indexes1.processHistoryIDIndex(),
00872                                                        indexes1.run(),
00873                                                        indexes1.lumi(),
00874                                                        *iEvent));
00875             }
00876           }
00877         }
00878       }
00879     }
00880   }
00881 
00882   bool IndexIntoFile::containsDuplicateEvents() const {
00883 
00884     RunOrLumiIndexes const* previousIndexes = 0;
00885 
00886     for(SortedRunOrLumiItr iter = beginRunOrLumi(),
00887                             iEnd = endRunOrLumi();
00888          iter != iEnd; ++iter) {
00889 
00890       RunOrLumiIndexes const& indexes = iter.runOrLumiIndexes();
00891 
00892       // Skip it if it is a run or the same lumi
00893       if(indexes.isRun() ||
00894           (previousIndexes && !(*previousIndexes < indexes))) {
00895         continue;
00896       }
00897       previousIndexes = &indexes;
00898 
00899       long long beginEventNumbers = indexes.beginEventNumbers();
00900       long long endEventNumbers = indexes.endEventNumbers();
00901 
00902       // there must be more than 1 event in the lumi for there to be any duplicates
00903       if(beginEventNumbers + 1 >= endEventNumbers) continue;
00904 
00905       if(!eventEntries().empty()) {
00906         std::vector<EventEntry>::iterator last = eventEntries().begin() + endEventNumbers;
00907         if(std::adjacent_find(eventEntries().begin() + beginEventNumbers, last) != last) {
00908           return true;
00909         }
00910       } else {
00911         fillEventNumbers();
00912         std::vector<EventNumber_t>::iterator last = eventNumbers().begin() + endEventNumbers;
00913         if(std::adjacent_find(eventNumbers().begin() + beginEventNumbers, last) != last) {
00914            return true;
00915         }
00916       }
00917     }
00918     return false;
00919   }
00920 
00921   IndexIntoFile::RunOrLumiEntry::RunOrLumiEntry() :
00922     orderPHIDRun_(invalidEntry),
00923     orderPHIDRunLumi_(invalidEntry),
00924     entry_(invalidEntry),
00925     processHistoryIDIndex_(invalidIndex),
00926     run_(invalidRun),
00927     lumi_(invalidLumi),
00928     beginEvents_(invalidEntry),
00929     endEvents_(invalidEntry) {
00930   }
00931 
00932   IndexIntoFile::RunOrLumiEntry::RunOrLumiEntry(EntryNumber_t orderPHIDRun,
00933                                                 EntryNumber_t orderPHIDRunLumi,
00934                                                 EntryNumber_t entry,
00935                                                 int processHistoryIDIndex,
00936                                                 RunNumber_t run,
00937                                                 LuminosityBlockNumber_t lumi,
00938                                                 EntryNumber_t beginEvents,
00939                                                 EntryNumber_t endEvents) :
00940     orderPHIDRun_(orderPHIDRun),
00941     orderPHIDRunLumi_(orderPHIDRunLumi),
00942     entry_(entry),
00943     processHistoryIDIndex_(processHistoryIDIndex),
00944     run_(run),
00945     lumi_(lumi),
00946     beginEvents_(beginEvents),
00947     endEvents_(endEvents) {
00948   }
00949 
00950   IndexIntoFile::RunOrLumiIndexes::RunOrLumiIndexes(int processHistoryIDIndex,
00951                                                     RunNumber_t run,
00952                                                     LuminosityBlockNumber_t lumi,
00953                                                     int indexToGetEntry) :
00954     processHistoryIDIndex_(processHistoryIDIndex),
00955     run_(run),
00956     lumi_(lumi),
00957     indexToGetEntry_(indexToGetEntry),
00958     beginEventNumbers_(-1),
00959     endEventNumbers_(-1)
00960   {
00961   }
00962 
00963   IndexIntoFile::SortedRunOrLumiItr::SortedRunOrLumiItr(IndexIntoFile const* indexIntoFile, unsigned runOrLumi) :
00964     indexIntoFile_(indexIntoFile), runOrLumi_(runOrLumi) {
00965     assert(runOrLumi_ <= indexIntoFile_->runOrLumiEntries().size());
00966     indexIntoFile_->fillRunOrLumiIndexes();
00967   }
00968 
00969   bool IndexIntoFile::SortedRunOrLumiItr::operator==(SortedRunOrLumiItr const& right) const {
00970     return indexIntoFile_ == right.indexIntoFile() &&
00971            runOrLumi_ == right.runOrLumi();
00972   }
00973 
00974   bool IndexIntoFile::SortedRunOrLumiItr::operator!=(SortedRunOrLumiItr const& right) const {
00975     return indexIntoFile_ != right.indexIntoFile() ||
00976            runOrLumi_ != right.runOrLumi();
00977   }
00978 
00979   IndexIntoFile::SortedRunOrLumiItr & IndexIntoFile::SortedRunOrLumiItr::operator++() {
00980     if(runOrLumi_ != indexIntoFile_->runOrLumiEntries().size()) {
00981       ++runOrLumi_;
00982     }
00983     return *this;
00984   }
00985 
00986   bool IndexIntoFile::SortedRunOrLumiItr::isRun() {
00987     return indexIntoFile_->runOrLumiIndexes().at(runOrLumi_).lumi() == invalidLumi;
00988   }
00989 
00990   void IndexIntoFile::SortedRunOrLumiItr::getRange(long long & beginEventNumbers,
00991                 long long & endEventNumbers,
00992                 EntryNumber_t & beginEventEntry,
00993                 EntryNumber_t & endEventEntry) {
00994     beginEventNumbers = indexIntoFile_->runOrLumiIndexes().at(runOrLumi_).beginEventNumbers();
00995     endEventNumbers = indexIntoFile_->runOrLumiIndexes().at(runOrLumi_).endEventNumbers();
00996 
00997     int indexToGetEntry = indexIntoFile_->runOrLumiIndexes().at(runOrLumi_).indexToGetEntry();
00998     beginEventEntry = indexIntoFile_->runOrLumiEntries_.at(indexToGetEntry).beginEvents();
00999     endEventEntry = indexIntoFile_->runOrLumiEntries_.at(indexToGetEntry).endEvents();
01000   }
01001 
01002   IndexIntoFile::RunOrLumiIndexes const&
01003   IndexIntoFile::SortedRunOrLumiItr::runOrLumiIndexes() const {
01004     return indexIntoFile_->runOrLumiIndexes().at(runOrLumi_);
01005   }
01006 
01007   IndexIntoFile::IndexIntoFileItrImpl::IndexIntoFileItrImpl(IndexIntoFile const* indexIntoFile,
01008                        EntryType entryType,
01009                        int indexToRun,
01010                        int indexToLumi,
01011                        int indexToEventRange,
01012                        long long indexToEvent,
01013                        long long nEvents) :
01014     indexIntoFile_(indexIntoFile),
01015     size_(static_cast<int>(indexIntoFile_->runOrLumiEntries_.size())),
01016     type_(entryType),
01017     indexToRun_(indexToRun),
01018     indexToLumi_(indexToLumi),
01019     indexToEventRange_(indexToEventRange),
01020     indexToEvent_(indexToEvent),
01021     nEvents_(nEvents) {
01022   }
01023 
01024   IndexIntoFile::IndexIntoFileItrImpl::~IndexIntoFileItrImpl() {}
01025 
01026   void IndexIntoFile::IndexIntoFileItrImpl::next() {
01027 
01028     if(type_ == kEvent) {
01029       if((indexToEvent_ + 1)  < nEvents_) {
01030         ++indexToEvent_;
01031       } else {
01032         bool found = nextEventRange();
01033 
01034         if(!found) {
01035           type_ = getRunOrLumiEntryType(indexToLumi_ + 1);
01036 
01037           if(type_ == kLumi) {
01038             ++indexToLumi_;
01039             initializeLumi();
01040           } else if(type_ == kRun) {
01041             indexToRun_ = indexToLumi_ + 1;
01042             initializeRun();
01043           } else {
01044             setInvalid(); // type_ is kEnd
01045           }
01046         }
01047       }
01048     } else if(type_ == kLumi) {
01049 
01050       if(indexToLumi_ + 1 == size_) {
01051         if(indexToEvent_ < nEvents_) {
01052           type_ = kEvent;
01053         } else {
01054           setInvalid();
01055         }
01056       } else {
01057 
01058         EntryType nextType = getRunOrLumiEntryType(indexToLumi_ + 1);
01059 
01060         if(nextType == kLumi && isSameLumi(indexToLumi_, indexToLumi_ + 1)) {
01061           ++indexToLumi_;
01062         } else if(indexToEvent_ < nEvents_) {
01063           type_ = kEvent;
01064         } else if(nextType == kRun) {
01065           type_ = kRun;
01066           indexToRun_ = indexToLumi_ + 1;
01067           initializeRun();
01068         } else {
01069           ++indexToLumi_;
01070           initializeLumi();
01071         }
01072       }
01073     } else if(type_ == kRun) {
01074       EntryType nextType = getRunOrLumiEntryType(indexToRun_ + 1);
01075       bool sameRun = isSameRun(indexToRun_, indexToRun_ + 1);
01076       if(nextType == kRun && sameRun) {
01077         ++indexToRun_;
01078       } else if(nextType == kRun && !sameRun) {
01079         ++indexToRun_;
01080         initializeRun();
01081       } else if(nextType == kLumi) {
01082         type_ = kLumi;
01083       } else {
01084         setInvalid();
01085       }
01086     }
01087   }
01088 
01089   void IndexIntoFile::IndexIntoFileItrImpl::skipEventForward(int & phIndexOfSkippedEvent,
01090                                                              RunNumber_t & runOfSkippedEvent,
01091                                                              LuminosityBlockNumber_t & lumiOfSkippedEvent,
01092                                                              EntryNumber_t & skippedEventEntry) {
01093     if(indexToEvent_  < nEvents_) {
01094       phIndexOfSkippedEvent = processHistoryIDIndex();
01095       runOfSkippedEvent = run();
01096       lumiOfSkippedEvent = peekAheadAtLumi();
01097       skippedEventEntry = peekAheadAtEventEntry();
01098 
01099       if((indexToEvent_ + 1)  < nEvents_) {
01100         ++indexToEvent_;
01101         return;
01102       } else if(nextEventRange()) {
01103         return;
01104       } else if(type_ == kRun || type_ == kLumi) {
01105         if(skipLumiInRun()) {
01106           return;
01107         }
01108       } else if(type_ == kEvent) {
01109         next();
01110         return;
01111       }
01112       advanceToNextRun();
01113       return;
01114     }
01115 
01116     if(type_ == kRun) {
01117       while(skipLumiInRun()) {
01118         if(indexToEvent_  < nEvents_) {
01119           skipEventForward(phIndexOfSkippedEvent, runOfSkippedEvent, lumiOfSkippedEvent, skippedEventEntry);
01120           return;
01121         }
01122       }
01123     }
01124 
01125     while(indexToEvent_ >= nEvents_ && type_ != kEnd) {
01126       while(skipLumiInRun()) {
01127         if(indexToEvent_  < nEvents_) {
01128           skipEventForward(phIndexOfSkippedEvent, runOfSkippedEvent, lumiOfSkippedEvent, skippedEventEntry);
01129           return;
01130         }
01131       }
01132       advanceToNextRun();
01133     }
01134     if(type_ == kEnd) {
01135       phIndexOfSkippedEvent = invalidIndex;
01136       runOfSkippedEvent = invalidRun;
01137       lumiOfSkippedEvent = invalidLumi;
01138       skippedEventEntry = invalidEntry;
01139       return;
01140     }
01141     skipEventForward(phIndexOfSkippedEvent, runOfSkippedEvent, lumiOfSkippedEvent, skippedEventEntry);
01142     return;
01143   }
01144 
01145   void IndexIntoFile::IndexIntoFileItrImpl::skipEventBackward(int& phIndexOfEvent,
01146                                                               RunNumber_t& runOfEvent,
01147                                                               LuminosityBlockNumber_t& lumiOfEvent,
01148                                                               EntryNumber_t& eventEntry) {
01149     // Look for previous events in the current lumi
01150     if(indexToEvent_ > 0) {
01151       --indexToEvent_;
01152     } else if(!previousEventRange()) {
01153 
01154       // Look for previous events in previous lumis
01155       if(!previousLumiWithEvents()) {
01156 
01157         // If we get here there are no previous events in the file
01158 
01159         if(!indexIntoFile_->empty()) {
01160             // Set the iterator to the beginning of the file
01161             type_ = kRun;
01162             indexToRun_ = 0;
01163             initializeRun();
01164         }
01165         phIndexOfEvent = invalidIndex;
01166         runOfEvent = invalidRun;
01167         lumiOfEvent = invalidLumi;
01168         eventEntry = invalidEntry;
01169         return;
01170       }
01171     }
01172     // Found a previous event and we have set the iterator so that this event
01173     // will be the next event process. (There may or may not be a run and/or
01174     // a lumi processed first).
01175     // Return information about this event
01176     phIndexOfEvent = processHistoryIDIndex();
01177     runOfEvent = run();
01178     lumiOfEvent = peekAheadAtLumi();
01179     eventEntry = peekAheadAtEventEntry();
01180   }
01181 
01182   bool IndexIntoFile::IndexIntoFileItrImpl::previousLumiWithEvents() {
01183     // Find the correct place to start the search
01184     int newLumi = indexToLumi();
01185     if(newLumi == invalidIndex) {
01186       newLumi = indexToRun() == invalidIndex ? size() - 1 : indexToRun();
01187     } else {
01188       while(getRunOrLumiEntryType(newLumi - 1) == kLumi &&
01189              isSameLumi(newLumi, newLumi - 1)) {
01190         --newLumi;
01191       }
01192       --newLumi;
01193     }
01194     if(newLumi <= 0) return false;
01195 
01196     // Look backwards for a lumi with events
01197     for( ; newLumi > 0; --newLumi) {
01198       if(getRunOrLumiEntryType(newLumi) == kRun) {
01199         continue;
01200       }
01201       if(setToLastEventInRange(newLumi)) {
01202         break;  // found it
01203       }
01204     }
01205     if(newLumi == 0) return false;
01206 
01207     // Finish initializing the iterator
01208     while(getRunOrLumiEntryType(newLumi - 1) == kLumi &&
01209            isSameLumi(newLumi, newLumi - 1)) {
01210       --newLumi;
01211     }
01212     setIndexToLumi(newLumi);
01213 
01214     if(type() != kEnd &&
01215         isSameRun(newLumi, indexToRun())) {
01216       if(type() == kEvent) type_ = kLumi;
01217       return true;
01218     }
01219     int newRun = newLumi;
01220     while(newRun > 0 && getRunOrLumiEntryType(newRun - 1) == kLumi) {
01221       --newRun;
01222     }
01223     --newRun;
01224     assert(getRunOrLumiEntryType(newRun) == kRun);
01225     while(getRunOrLumiEntryType(newRun - 1) == kRun &&
01226            isSameRun(newRun - 1, newLumi)) {
01227       --newRun;
01228     }
01229     indexToRun_ = newRun;
01230     type_ = kRun;
01231     return true;
01232   }
01233 
01234   IndexIntoFile::EntryNumber_t IndexIntoFile::IndexIntoFileItrImpl::firstEventEntryThisRun() {
01235     if(indexToLumi() == invalidIndex) return invalidEntry;
01236 
01237     int saveIndexToLumi = indexToLumi();
01238     int saveIndexToEventRange = indexToEventRange();
01239     long long saveIndexToEvent = indexToEvent();
01240     long long saveNEvents = nEvents();
01241 
01242     initializeRun();
01243 
01244     IndexIntoFile::EntryNumber_t returnValue = invalidEntry;
01245 
01246     do {
01247       if(indexToEvent() < nEvents()) {
01248         returnValue = peekAheadAtEventEntry();
01249         break;
01250       }
01251     } while(skipLumiInRun());
01252 
01253     setIndexToLumi(saveIndexToLumi);
01254     setIndexToEventRange(saveIndexToEventRange);
01255     setIndexToEvent(saveIndexToEvent);
01256     setNEvents(saveNEvents);
01257 
01258     return returnValue;
01259   }
01260 
01261   IndexIntoFile::EntryNumber_t IndexIntoFile::IndexIntoFileItrImpl::firstEventEntryThisLumi() {
01262     if(indexToLumi() == invalidIndex) return invalidEntry;
01263 
01264     int saveIndexToLumi = indexToLumi();
01265     int saveIndexToEventRange = indexToEventRange();
01266     long long saveIndexToEvent = indexToEvent();
01267     long long saveNEvents = nEvents();
01268 
01269     for(int i = 1; indexToLumi() - i > 0; ++i) {
01270       if(getRunOrLumiEntryType(indexToLumi_ - i) == kRun) break;
01271       if(!isSameLumi(indexToLumi(), indexToLumi() - i)) break;
01272       indexToLumi_ = indexToLumi_ - i;
01273     }
01274     initializeLumi();
01275 
01276     IndexIntoFile::EntryNumber_t returnValue = invalidEntry;
01277 
01278     if(indexToEvent() < nEvents()) {
01279       returnValue = peekAheadAtEventEntry();
01280     }
01281 
01282     setIndexToLumi(saveIndexToLumi);
01283     setIndexToEventRange(saveIndexToEventRange);
01284     setIndexToEvent(saveIndexToEvent);
01285     setNEvents(saveNEvents);
01286 
01287     return returnValue;
01288   }
01289 
01290   void IndexIntoFile::IndexIntoFileItrImpl::advanceToNextRun() {
01291     if(type_ == kEnd) return;
01292     for(int i = 1; indexToRun_ + i < size_; ++i) {
01293       if(getRunOrLumiEntryType(indexToRun_ + i) == kRun) {
01294         if(!isSameRun(indexToRun_, indexToRun_ + i)) {
01295           type_ = kRun;
01296           indexToRun_ += i;
01297           initializeRun();
01298           return;
01299         }
01300       }
01301     }
01302     setInvalid();
01303   }
01304 
01305   void IndexIntoFile::IndexIntoFileItrImpl::advanceToNextLumiOrRun() {
01306     if(type_ == kEnd) return;
01307     assert(indexToRun_ != invalidIndex);
01308 
01309     // A preliminary step is to advance to the last run entry for
01310     // this run (actually this step is not needed in the
01311     // context I expect this to be called in, just being careful)
01312     int startSearch = indexToRun_;
01313     for(int i = 1; startSearch + i < size_; ++i) {
01314       if(getRunOrLumiEntryType(startSearch + i) == kRun &&
01315           isSameRun(indexToRun_, startSearch + i)) {
01316         indexToRun_ = startSearch + i;
01317       } else {
01318         break;
01319       }
01320     }
01321 
01322     if(type_ == kRun && indexToLumi_ != invalidIndex) {
01323       type_ = kLumi;
01324       return;
01325     }
01326 
01327     startSearch = indexToLumi_;
01328     if(startSearch == invalidIndex) startSearch = indexToRun_;
01329     for(int i = 1; startSearch + i < size_; ++i) {
01330       if(getRunOrLumiEntryType(startSearch + i) == kRun) {
01331         if(!isSameRun(indexToRun_, startSearch + i)) {
01332           type_ = kRun;
01333           indexToRun_ = startSearch + i;
01334           initializeRun();
01335           return;
01336         }
01337       } else if(indexToLumi_ != invalidIndex) {
01338         if(!isSameLumi(indexToLumi_, startSearch + i)) {
01339           type_ = kLumi;
01340           indexToLumi_ = startSearch + i;
01341           initializeLumi();
01342           return;
01343         }
01344       }
01345     }
01346     setInvalid();
01347   }
01348 
01349   bool IndexIntoFile::IndexIntoFileItrImpl::skipToNextEventInLumi() {
01350     if(indexToEvent_ >= nEvents_) return false;
01351     if((indexToEvent_ + 1)  < nEvents_) {
01352       ++indexToEvent_;
01353       return true;
01354     }
01355     return nextEventRange();
01356   }
01357 
01358   void IndexIntoFile::IndexIntoFileItrImpl::initializeRun() {
01359 
01360     indexToLumi_ = invalidIndex;
01361     indexToEventRange_ = invalidIndex;
01362     indexToEvent_ = 0;
01363     nEvents_ = 0;
01364 
01365     for(int i = 1; (i + indexToRun_) < size_; ++i) {
01366       EntryType entryType = getRunOrLumiEntryType(indexToRun_ + i);
01367       bool sameRun = isSameRun(indexToRun_, indexToRun_ + i);
01368 
01369       if(entryType == kRun) {
01370         if(sameRun) {
01371           continue;
01372         } else {
01373           break;
01374         }
01375       } else {
01376         indexToLumi_ = indexToRun_ + i;
01377         initializeLumi();
01378         return;
01379       }
01380     }
01381   }
01382 
01383   bool IndexIntoFile::IndexIntoFileItrImpl::operator==(IndexIntoFileItrImpl const& right) const {
01384     return (indexIntoFile_ == right.indexIntoFile_ &&
01385             size_ == right.size_ &&
01386             type_ == right.type_ &&
01387             indexToRun_ == right.indexToRun_ &&
01388             indexToLumi_ == right.indexToLumi_ &&
01389             indexToEventRange_ == right.indexToEventRange_ &&
01390             indexToEvent_ == right.indexToEvent_ &&
01391             nEvents_ == right.nEvents_);
01392   }
01393 
01394   void
01395   IndexIntoFile::IndexIntoFileItrImpl::copyPosition(IndexIntoFileItrImpl const& position) {
01396     type_ = position.type_;
01397     indexToRun_ = position.indexToRun_;
01398     indexToLumi_ = position.indexToLumi_;
01399     indexToEventRange_ = position.indexToEventRange_;
01400     indexToEvent_ = position.indexToEvent_;
01401     nEvents_ = position.nEvents_;
01402   }
01403 
01404   void IndexIntoFile::IndexIntoFileItrImpl::setInvalid() {
01405     type_ = kEnd;
01406     indexToRun_ = invalidIndex;
01407     indexToLumi_ = invalidIndex;
01408     indexToEventRange_ = invalidIndex;
01409     indexToEvent_ = 0;
01410     nEvents_ = 0;
01411   }
01412 
01413   IndexIntoFile::IndexIntoFileItrNoSort::IndexIntoFileItrNoSort(IndexIntoFile const* indexIntoFile,
01414                          EntryType entryType,
01415                          int indexToRun,
01416                          int indexToLumi,
01417                          int indexToEventRange,
01418                          long long indexToEvent,
01419                          long long nEvents) :
01420     IndexIntoFileItrImpl(indexIntoFile,
01421                          entryType,
01422                          indexToRun,
01423                          indexToLumi,
01424                          indexToEventRange,
01425                          indexToEvent,
01426                          nEvents)
01427   {
01428   }
01429 
01430   IndexIntoFile::IndexIntoFileItrImpl*
01431   IndexIntoFile::IndexIntoFileItrNoSort::clone() const {
01432     return new IndexIntoFileItrNoSort(*this);
01433   }
01434 
01435   int
01436   IndexIntoFile::IndexIntoFileItrNoSort::processHistoryIDIndex() const {
01437     if(type() == kEnd) return invalidIndex;
01438     return indexIntoFile()->runOrLumiEntries()[indexToRun()].processHistoryIDIndex();
01439   }
01440 
01441   RunNumber_t IndexIntoFile::IndexIntoFileItrNoSort::run() const {
01442     if(type() == kEnd) return invalidRun;
01443     return indexIntoFile()->runOrLumiEntries()[indexToRun()].run();
01444   }
01445 
01446   LuminosityBlockNumber_t IndexIntoFile::IndexIntoFileItrNoSort::lumi() const {
01447     if(type() == kEnd || type() == kRun) return invalidLumi;
01448     return indexIntoFile()->runOrLumiEntries()[indexToLumi()].lumi();
01449   }
01450 
01451   IndexIntoFile::EntryNumber_t IndexIntoFile::IndexIntoFileItrNoSort::entry() const {
01452     if(type() == kEnd) return invalidEntry;
01453     if(type() == kRun) return indexIntoFile()->runOrLumiEntries()[indexToRun()].entry();
01454     if(type() == kLumi) return indexIntoFile()->runOrLumiEntries()[indexToLumi()].entry();
01455     return
01456       indexIntoFile()->runOrLumiEntries()[indexToEventRange()].beginEvents() +
01457       indexToEvent();
01458   }
01459 
01460   LuminosityBlockNumber_t IndexIntoFile::IndexIntoFileItrNoSort::peekAheadAtLumi() const {
01461     if(indexToLumi() == invalidIndex) return invalidLumi;
01462     return indexIntoFile()->runOrLumiEntries()[indexToLumi()].lumi();
01463   }
01464 
01465   IndexIntoFile::EntryNumber_t IndexIntoFile::IndexIntoFileItrNoSort::peekAheadAtEventEntry() const {
01466     if(indexToLumi() == invalidIndex) return invalidEntry;
01467     if(indexToEvent() >= nEvents()) return invalidEntry;
01468     return
01469       indexIntoFile()->runOrLumiEntries()[indexToEventRange()].beginEvents() +
01470       indexToEvent();
01471   }
01472 
01473   void IndexIntoFile::IndexIntoFileItrNoSort::initializeLumi_() {
01474     assert(indexToLumi() != invalidIndex);
01475 
01476     setIndexToEventRange(invalidIndex);
01477     setIndexToEvent(0);
01478     setNEvents(0);
01479 
01480     for(int i = 0; indexToLumi() + i < size(); ++i) {
01481       if(indexIntoFile()->runOrLumiEntries()[indexToLumi() + i].isRun()) {
01482         break;
01483       } else if(indexIntoFile()->runOrLumiEntries()[indexToLumi() + i].lumi() ==
01484                 indexIntoFile()->runOrLumiEntries()[indexToLumi()].lumi()) {
01485         if(indexIntoFile()->runOrLumiEntries()[indexToLumi() + i].beginEvents() == invalidEntry) {
01486           continue;
01487         }
01488         setIndexToEventRange(indexToLumi() + i);
01489         setIndexToEvent(0);
01490         setNEvents(indexIntoFile()->runOrLumiEntries()[indexToEventRange()].endEvents() -
01491                    indexIntoFile()->runOrLumiEntries()[indexToEventRange()].beginEvents());
01492         break;
01493       } else {
01494         break;
01495       }
01496     }
01497   }
01498 
01499   bool IndexIntoFile::IndexIntoFileItrNoSort::nextEventRange() {
01500     if(indexToEventRange() == invalidIndex) return false;
01501 
01502     // Look for the next event range, same lumi but different entry
01503     for(int i = 1; indexToEventRange() + i < size(); ++i) {
01504       if(indexIntoFile()->runOrLumiEntries()[indexToEventRange() + i ].isRun()) {
01505         return false;  // hit next run
01506       } else if(indexIntoFile()->runOrLumiEntries()[indexToEventRange() + i].lumi() ==
01507                 indexIntoFile()->runOrLumiEntries()[indexToEventRange()].lumi()) {
01508         if(indexIntoFile()->runOrLumiEntries()[indexToEventRange() + i].beginEvents() == invalidEntry) {
01509           continue; // same lumi but has no events, keep looking
01510         }
01511         setIndexToEventRange(indexToEventRange() + i);
01512         setIndexToEvent(0);
01513         setNEvents(indexIntoFile()->runOrLumiEntries()[indexToEventRange()].endEvents() -
01514                    indexIntoFile()->runOrLumiEntries()[indexToEventRange()].beginEvents());
01515         return true; // found more events in this lumi
01516       }
01517       return false; // hit next lumi
01518     }
01519     return false; // hit the end of the IndexIntoFile
01520   }
01521 
01522   bool IndexIntoFile::IndexIntoFileItrNoSort::previousEventRange() {
01523     if(indexToEventRange() == invalidIndex) return false;
01524     assert(indexToEventRange() < size());
01525 
01526     // Look backward for a previous event range with events, same lumi but different entry
01527     for(int i = 1; indexToEventRange() - i > 0; ++i) {
01528       int newRange = indexToEventRange() - i;
01529       if(indexIntoFile()->runOrLumiEntries()[newRange].isRun()) {
01530         return false;  // hit run
01531       } else if(isSameLumi(newRange, indexToEventRange())) {
01532         if(indexIntoFile()->runOrLumiEntries()[newRange].beginEvents() == invalidEntry) {
01533           continue; // same lumi but has no events, keep looking
01534         }
01535         setIndexToEventRange(newRange);
01536         setNEvents(indexIntoFile()->runOrLumiEntries()[indexToEventRange()].endEvents() -
01537                    indexIntoFile()->runOrLumiEntries()[indexToEventRange()].beginEvents());
01538         setIndexToEvent(nEvents() - 1);
01539         return true; // found previous event in this lumi
01540       }
01541       return false; // hit previous lumi
01542     }
01543     return false; // hit the beginning of the IndexIntoFile, 0th entry has to be a run
01544   }
01545 
01546   bool IndexIntoFile::IndexIntoFileItrNoSort::setToLastEventInRange(int index) {
01547     if(indexIntoFile()->runOrLumiEntries()[index].beginEvents() == invalidEntry) {
01548       return false;
01549     }
01550     setIndexToEventRange(index);
01551     setNEvents(indexIntoFile()->runOrLumiEntries()[indexToEventRange()].endEvents() -
01552                indexIntoFile()->runOrLumiEntries()[indexToEventRange()].beginEvents());
01553     assert(nEvents() > 0);
01554     setIndexToEvent(nEvents() - 1);
01555     return true;
01556   }
01557 
01558   bool IndexIntoFile::IndexIntoFileItrNoSort::skipLumiInRun() {
01559     if(indexToLumi() == invalidIndex) return false;
01560     for(int i = 1; indexToLumi() + i < size(); ++i) {
01561       int newLumi = indexToLumi() + i;
01562       if(indexIntoFile()->runOrLumiEntries()[newLumi].isRun()) {
01563         return false;  // hit next run
01564       } else if(indexIntoFile()->runOrLumiEntries()[newLumi].lumi() ==
01565                indexIntoFile()->runOrLumiEntries()[indexToLumi()].lumi()) {
01566         continue;
01567       }
01568       setIndexToLumi(newLumi);
01569       initializeLumi();
01570       return true; // hit next lumi
01571     }
01572     return false; // hit the end of the IndexIntoFile
01573   }
01574 
01575   IndexIntoFile::EntryType IndexIntoFile::IndexIntoFileItrNoSort::getRunOrLumiEntryType(int index) const {
01576     if(index < 0 || index >= size()) {
01577       return kEnd;
01578     } else if(indexIntoFile()->runOrLumiEntries()[index].isRun()) {
01579       return kRun;
01580     }
01581     return kLumi;
01582   }
01583 
01584   bool IndexIntoFile::IndexIntoFileItrNoSort::isSameLumi(int index1, int index2) const {
01585     if(index1 < 0 || index1 >= size() || index2 < 0 || index2 >= size()) {
01586       return false;
01587     }
01588     return indexIntoFile()->runOrLumiEntries()[index1].lumi() ==
01589            indexIntoFile()->runOrLumiEntries()[index2].lumi();
01590   }
01591 
01592   bool IndexIntoFile::IndexIntoFileItrNoSort::isSameRun(int index1, int index2) const {
01593     if(index1 < 0 || index1 >= size() || index2 < 0 || index2 >= size()) {
01594       return false;
01595     }
01596     return indexIntoFile()->runOrLumiEntries()[index1].run() ==
01597            indexIntoFile()->runOrLumiEntries()[index2].run() &&
01598            indexIntoFile()->runOrLumiEntries()[index1].processHistoryIDIndex() ==
01599            indexIntoFile()->runOrLumiEntries()[index2].processHistoryIDIndex();
01600   }
01601 
01602   IndexIntoFile::IndexIntoFileItrSorted::IndexIntoFileItrSorted(IndexIntoFile const* indexIntoFile,
01603                          EntryType entryType,
01604                          int indexToRun,
01605                          int indexToLumi,
01606                          int indexToEventRange,
01607                          long long indexToEvent,
01608                          long long nEvents) :
01609     IndexIntoFileItrImpl(indexIntoFile,
01610                          entryType,
01611                          indexToRun,
01612                          indexToLumi,
01613                          indexToEventRange,
01614                          indexToEvent,
01615                          nEvents) {
01616     indexIntoFile->fillRunOrLumiIndexes();
01617   }
01618 
01619   IndexIntoFile::IndexIntoFileItrImpl* IndexIntoFile::IndexIntoFileItrSorted::clone() const {
01620     return new IndexIntoFileItrSorted(*this);
01621   }
01622 
01623   int IndexIntoFile::IndexIntoFileItrSorted::processHistoryIDIndex() const {
01624     if(type() == kEnd) return invalidIndex;
01625     return indexIntoFile()->runOrLumiIndexes()[indexToRun()].processHistoryIDIndex();
01626   }
01627 
01628   RunNumber_t IndexIntoFile::IndexIntoFileItrSorted::run() const {
01629     if(type() == kEnd) return invalidRun;
01630     return indexIntoFile()->runOrLumiIndexes()[indexToRun()].run();
01631   }
01632 
01633   LuminosityBlockNumber_t IndexIntoFile::IndexIntoFileItrSorted::lumi() const {
01634     if(type() == kEnd || type() == kRun) return invalidLumi;
01635     return indexIntoFile()->runOrLumiIndexes()[indexToLumi()].lumi();
01636   }
01637 
01638   IndexIntoFile::EntryNumber_t IndexIntoFile::IndexIntoFileItrSorted::entry() const {
01639     if(type() == kEnd) return invalidEntry;
01640     if(type() == kRun) {
01641       int i =  indexIntoFile()->runOrLumiIndexes()[indexToRun()].indexToGetEntry();
01642       return indexIntoFile()->runOrLumiEntries()[i].entry();
01643     }
01644     if(type() == kLumi) {
01645       int i =  indexIntoFile()->runOrLumiIndexes()[indexToLumi()].indexToGetEntry();
01646       return indexIntoFile()->runOrLumiEntries()[i].entry();
01647     }
01648     long long eventNumberIndex =
01649       indexIntoFile()->runOrLumiIndexes()[indexToEventRange()].beginEventNumbers() +
01650       indexToEvent();
01651     indexIntoFile()->fillEventEntries();
01652     return indexIntoFile()->eventEntries().at(eventNumberIndex).entry();
01653   }
01654 
01655   LuminosityBlockNumber_t IndexIntoFile::IndexIntoFileItrSorted::peekAheadAtLumi() const {
01656     if(indexToLumi() == invalidIndex) return invalidLumi;
01657     return indexIntoFile()->runOrLumiIndexes()[indexToLumi()].lumi();
01658   }
01659 
01660   IndexIntoFile::EntryNumber_t IndexIntoFile::IndexIntoFileItrSorted::peekAheadAtEventEntry() const {
01661     if(indexToLumi() == invalidIndex) return invalidEntry;
01662     if(indexToEvent() >= nEvents()) return invalidEntry;
01663     long long eventNumberIndex =
01664       indexIntoFile()->runOrLumiIndexes()[indexToEventRange()].beginEventNumbers() +
01665       indexToEvent();
01666     indexIntoFile()->fillEventEntries();
01667     return indexIntoFile()->eventEntries().at(eventNumberIndex).entry();
01668   }
01669 
01670   void IndexIntoFile::IndexIntoFileItrSorted::initializeLumi_() {
01671     assert(indexToLumi() != invalidIndex);
01672     setIndexToEventRange(indexToLumi());
01673     setIndexToEvent(0);
01674     setNEvents(
01675       indexIntoFile()->runOrLumiIndexes()[indexToLumi()].endEventNumbers() -
01676       indexIntoFile()->runOrLumiIndexes()[indexToLumi()].beginEventNumbers());
01677     if(nEvents() == 0){
01678       setIndexToEventRange(invalidIndex);
01679     }
01680   }
01681 
01682   bool IndexIntoFile::IndexIntoFileItrSorted::nextEventRange() {
01683     return false;
01684   }
01685 
01686   bool IndexIntoFile::IndexIntoFileItrSorted::previousEventRange() {
01687     return false;
01688   }
01689 
01690   bool IndexIntoFile::IndexIntoFileItrSorted::setToLastEventInRange(int index) {
01691     long long nEventsInRange =
01692       indexIntoFile()->runOrLumiIndexes()[index].endEventNumbers() -
01693       indexIntoFile()->runOrLumiIndexes()[index].beginEventNumbers();
01694     if(nEventsInRange == 0) {
01695       return false;
01696     }
01697     while(index > 0 &&
01698           !indexIntoFile()->runOrLumiIndexes()[index - 1].isRun() &&
01699           isSameLumi(index, index - 1)) {
01700       --index;
01701     }
01702     assert(nEventsInRange ==
01703       indexIntoFile()->runOrLumiIndexes()[index].endEventNumbers() -
01704       indexIntoFile()->runOrLumiIndexes()[index].beginEventNumbers());
01705 
01706     setIndexToEventRange(index);
01707     setNEvents(nEventsInRange);
01708     assert(nEvents() > 0);
01709     setIndexToEvent(nEventsInRange - 1);
01710     return true;
01711   }
01712 
01713   bool IndexIntoFile::IndexIntoFileItrSorted::skipLumiInRun() {
01714     if(indexToLumi() == invalidIndex) return false;
01715     for(int i = 1; indexToLumi() + i < size(); ++i) {
01716       int newLumi = indexToLumi() + i;
01717       if(indexIntoFile()->runOrLumiIndexes()[newLumi].isRun()) {
01718         return false;  // hit next run
01719       } else if(indexIntoFile()->runOrLumiIndexes()[newLumi].lumi() ==
01720                 indexIntoFile()->runOrLumiIndexes()[indexToLumi()].lumi()) {
01721         continue;
01722       }
01723       setIndexToLumi(newLumi);
01724       initializeLumi();
01725       return true; // hit next lumi
01726     }
01727     return false; // hit the end of the IndexIntoFile
01728   }
01729 
01730   IndexIntoFile::EntryType IndexIntoFile::IndexIntoFileItrSorted::getRunOrLumiEntryType(int index) const {
01731     if(index < 0 || index >= size()) {
01732       return kEnd;
01733     } else if(indexIntoFile()->runOrLumiIndexes()[index].isRun()) {
01734       return kRun;
01735     }
01736     return kLumi;
01737   }
01738 
01739   bool IndexIntoFile::IndexIntoFileItrSorted::isSameLumi(int index1, int index2) const {
01740     if(index1 < 0 || index1 >= size() || index2 < 0 || index2 >= size()) {
01741       return false;
01742     }
01743     return indexIntoFile()->runOrLumiIndexes()[index1].lumi() ==
01744            indexIntoFile()->runOrLumiIndexes()[index2].lumi();
01745   }
01746 
01747   bool IndexIntoFile::IndexIntoFileItrSorted::isSameRun(int index1, int index2) const {
01748     if(index1 < 0 || index1 >= size() || index2 < 0 || index2 >= size()) {
01749       return false;
01750     }
01751     return indexIntoFile()->runOrLumiIndexes()[index1].run() ==
01752            indexIntoFile()->runOrLumiIndexes()[index2].run() &&
01753            indexIntoFile()->runOrLumiIndexes()[index1].processHistoryIDIndex() ==
01754            indexIntoFile()->runOrLumiIndexes()[index2].processHistoryIDIndex();
01755   }
01756 
01757   IndexIntoFile::IndexIntoFileItr::IndexIntoFileItr(IndexIntoFile const* indexIntoFile,
01758                    SortOrder sortOrder,
01759                    EntryType entryType,
01760                    int indexToRun,
01761                    int indexToLumi,
01762                    int indexToEventRange,
01763                    long long indexToEvent,
01764                    long long nEvents) :
01765     impl_() {
01766     if(sortOrder == numericalOrder) {
01767       value_ptr<IndexIntoFileItrImpl> temp(new IndexIntoFileItrSorted(indexIntoFile,
01768                                                                       entryType,
01769                                                                       indexToRun,
01770                                                                       indexToLumi,
01771                                                                       indexToEventRange,
01772                                                                       indexToEvent,
01773                                                                       nEvents
01774                                                                      ));
01775       swap(temp, impl_);
01776     } else {
01777       value_ptr<IndexIntoFileItrImpl> temp(new IndexIntoFileItrNoSort(indexIntoFile,
01778                                                                       entryType,
01779                                                                       indexToRun,
01780                                                                       indexToLumi,
01781                                                                       indexToEventRange,
01782                                                                       indexToEvent,
01783                                                                       nEvents));
01784       swap(temp, impl_);
01785     }
01786   }
01787 
01788   void IndexIntoFile::IndexIntoFileItr::advanceToEvent() {
01789     for(EntryType entryType = getEntryType();
01790         entryType != kEnd && entryType != kEvent;
01791         entryType = getEntryType()) {
01792             impl_->next();
01793     }
01794   }
01795 
01796   void IndexIntoFile::IndexIntoFileItr::advanceToLumi() {
01797     for(EntryType entryType = getEntryType();
01798         entryType != kEnd && entryType != kLumi;
01799         entryType = getEntryType()) {
01800             impl_->next();
01801     }
01802   }
01803 
01804   void
01805   IndexIntoFile::IndexIntoFileItr::copyPosition(IndexIntoFileItr const& position) {
01806     impl_->copyPosition(*position.impl_);
01807   }
01808 
01809   bool Compare_Index_Run::operator()(IndexIntoFile::RunOrLumiIndexes const& lh, IndexIntoFile::RunOrLumiIndexes const& rh) {
01810     if(lh.processHistoryIDIndex() == rh.processHistoryIDIndex()) {
01811       return lh.run() < rh.run();
01812     }
01813     return lh.processHistoryIDIndex() < rh.processHistoryIDIndex();
01814   }
01815 
01816   bool Compare_Index::operator()(IndexIntoFile::RunOrLumiIndexes const& lh, IndexIntoFile::RunOrLumiIndexes const& rh) {
01817     return lh.processHistoryIDIndex() < rh.processHistoryIDIndex();
01818   }
01819 }