CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/DataFormats/Provenance/src/IndexIntoFile.cc

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