You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If MergingIterator#seekToFirst() or MergingIterator#seek(key) are called after starting using the iterator (after calling first #next()), MergingIterator start returning wrong values.
Root cause: resetPriorityQueue() should clear queue before reusing it, other wise duplicate iterators will be inserted and used in next iterations
Following unit test reproduce the problem:
@Test
public void testName() throws Exception {
InternalKeyComparator comparator = new InternalKeyComparator(new BytewiseComparator());
InternalKey key1 = new InternalKey(Slices.wrappedBuffer(new byte[]{'1'}), 1, ValueType.VALUE);
InternalKey key2 = new InternalKey(Slices.wrappedBuffer(new byte[]{'3'}), 2, ValueType.VALUE);
InternalKey key3 = new InternalKey(Slices.wrappedBuffer(new byte[]{'2'}), 3, ValueType.VALUE);
InternalKey key4 = new InternalKey(Slices.wrappedBuffer(new byte[]{'4'}), 4, ValueType.VALUE);
ImmutableList<Map.Entry<InternalKey, Slice>> of1 = ImmutableList
.of(
Maps.immutableEntry(key1, Slices.EMPTY_SLICE),
Maps.immutableEntry(key2, Slices.EMPTY_SLICE)
);
ImmutableList<Map.Entry<InternalKey, Slice>> of2 = ImmutableList
.of(
Maps.immutableEntry(key3, Slices.EMPTY_SLICE),
Maps.immutableEntry(key4, Slices.EMPTY_SLICE)
);
ImmutableList<InternalIterator> of = ImmutableList.of(new InternalKeySliceAbstractSeekingIterator(of1, comparator), new InternalKeySliceAbstractSeekingIterator(of2, comparator));
MergingIterator mergingIterator = new MergingIterator(of, comparator);
assertEquals(mergingIterator.next().getKey(), key1);
assertEquals(mergingIterator.next().getKey(), key3);
mergingIterator.seekToFirst();
assertEquals(mergingIterator.next().getKey(), key1);
assertEquals(mergingIterator.next().getKey(), key3);
assertEquals(mergingIterator.next().getKey(), key2);
assertEquals(mergingIterator.next().getKey(), key4); //fail here! key2 is return a second time!
assertFalse(mergingIterator.hasNext());
}
private static class InternalKeySliceAbstractSeekingIterator extends AbstractSeekingIterator<InternalKey, Slice> implements InternalIterator {
int index = 0;
private final List<Map.Entry<InternalKey, Slice>> entries;
private final InternalKeyComparator comparator;
public InternalKeySliceAbstractSeekingIterator(List<Map.Entry<InternalKey, Slice>> entries, InternalKeyComparator comparator) {
this.entries = entries;
this.comparator = comparator;
}
@Override
protected void seekToFirstInternal() {
index = 0;
}
@Override
protected void seekInternal(InternalKey targetKey) {
index = entries.size();
for (int i = 0; i < entries.size(); i++) {
Map.Entry<InternalKey, Slice> entry = entries.get(i);
if (comparator.compare(entry.getKey(), targetKey) >= 0) {
index = i;
}
}
}
@Override
protected Map.Entry<InternalKey, Slice> getNextElement() {
return index < entries.size() ? entries.get(index++) : null;
}
}
The text was updated successfully, but these errors were encountered:
pcmind
added a commit
to pcmind/leveldb
that referenced
this issue
Jan 13, 2018
If
MergingIterator#seekToFirst()
orMergingIterator#seek(key)
are called after starting using the iterator (after calling first#next()
), MergingIterator start returning wrong values.Root cause:
resetPriorityQueue()
should clear queue before reusing it, other wise duplicate iterators will be inserted and used in next iterationsFollowing unit test reproduce the problem:
The text was updated successfully, but these errors were encountered: