ListIterator<IndexEntry> listIterator(int idx) {
    NavigableMap<StoreKey, ConcurrentSkipListSet<IndexValue>> indexCopy = index;
    rwLock.readLock().lock();
    boolean isSealed = sealed.get();
    rwLock.readLock().unlock();
    if (!isSealed) {
      return new UnsealedIndexSegmentEntryListIterator(indexCopy, idx);
    }
    return new SealedIndexSegmentEntryListIterator(idx);
  }
Return an {@link ListIterator<IndexEntry>} from an IndexSegment that iterates over all the {@link IndexEntry}s in the same
order of {@link StoreKey}. And when the {@link StoreKey}s are the same, it iterates over the entry in the same order
as {@link Offset}.

When the {@link IndexSegment} is unsealed, newly added entries don't effect the iterator. Iterator takes a snapshot
of existing entries while creating this iterator. However, this snapshot can still be out of sync with what you intend
to do. For example
<pre>
  indexSegment.addEntry(entry, offset);
  int size = indexSegment.size();
  ListIterator &lt IndexEntry &gt listiter = indexSegment.listIterator(size);
</pre>
Unfortunately, the listiter returned by this method in the example might not contain the entry you just added before
invoking {@link #listIterator}. The reason is if there is an entry added between {@link #size()} and {@link #listIterator},
then the size is no up to date then.

@return an {@link Iterator<IndexEntry>}.
ambry-store/src/main/java/com/github/ambry/store/IndexSegment.java