Skip to content

Commit

Permalink
Prefix search implementation
Browse files Browse the repository at this point in the history
Implemente a solution to the issue described by google/leveldb#610
  • Loading branch information
pcmind committed Nov 26, 2018
1 parent a302df6 commit da3771e
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 2 deletions.
5 changes: 5 additions & 0 deletions leveldb-api/src/main/java/org/iq80/leveldb/DB.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ byte[] get(byte[] key, ReadOptions options)
@Override
DBIterator iterator();

default DBIterator prefixIterator(ReadOptions options, byte[] prefix)
{
throw new UnsupportedOperationException();
}

DBIterator iterator(ReadOptions options);

void put(byte[] key, byte[] value)
Expand Down
8 changes: 7 additions & 1 deletion leveldb/src/main/java/org/iq80/leveldb/impl/DbImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -971,14 +971,20 @@ public SeekingIteratorAdapter iterator()

@Override
public SeekingIteratorAdapter iterator(ReadOptions options)
{
return prefixIterator(options, null);
}

@Override
public SeekingIteratorAdapter prefixIterator(ReadOptions options, byte[] prefix)
{
mutex.lock();
try {
DbIterator rawIterator = internalIterator(options);

// filter out any entries not visible in our snapshot
long snapshot = getSnapshot(options);
SnapshotSeekingIterator snapshotIterator = new SnapshotSeekingIterator(rawIterator, snapshot, internalKeyComparator.getUserComparator(), new Random(), this);
SnapshotSeekingIterator snapshotIterator = new SnapshotSeekingIterator(rawIterator, snapshot, internalKeyComparator.getUserComparator(), prefix == null || prefix.length == 0 ? null : Slices.wrappedBuffer(prefix), new Random(), this);
return new SeekingIteratorAdapter(snapshotIterator);
}
finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,14 @@ public final class SnapshotSeekingIterator
private final Random r;
private final DbImpl db;
private int bytesCounter;
private final Slice prefix;

public SnapshotSeekingIterator(DbIterator iterator, long sequence, Comparator<Slice> userComparator, Random r, DbImpl db)
public SnapshotSeekingIterator(DbIterator iterator, long sequence, Comparator<Slice> userComparator, Slice prefix, Random r, DbImpl db)
{
this.iterator = iterator;
this.sequence = sequence;
this.userComparator = userComparator;
this.prefix = prefix;
this.r = r;
this.db = db;
this.bytesCounter = getRandomPeriod(); //use this.r
Expand Down Expand Up @@ -105,6 +107,9 @@ private void findNextUserEntry()
if (key.getSequenceNumber() > sequence) {
continue;
}
if (prefix != null && !prefix.isPrefixOf(key.getUserKey())) {
break;
}
if (key.getValueType() == ValueType.DELETION) {
while (iterator.hasNext()) {
Entry<InternalKey, Slice> peek = iterator.peek();
Expand Down
23 changes: 23 additions & 0 deletions leveldb/src/main/java/org/iq80/leveldb/util/Slice.java
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,29 @@ public int compareTo(Slice that)
return this.length - that.length;
}

public boolean isPrefixOf(Slice that)
{
if (this == that) {
return true;
}
if (this.data == that.data && length == that.length && offset == that.offset) {
return true;
}
if (this.length > that.length) {
return false;
}

int minLength = this.length;
for (int i = 0; i < minLength; i++) {
int thisByte = 0xFF & this.data[this.offset + i];
int thatByte = 0xFF & that.data[that.offset + i];
if (thisByte != thatByte) {
return false;
}
}
return true;
}

/**
* Decodes this buffer's readable bytes into a string with the specified
* character set name.
Expand Down

0 comments on commit da3771e

Please sign in to comment.