fusesource/leveldbjni — Issue #7: get() on a nonexistent key works through exception
Author: aluht
Created: 2012-03-02 12:52:24+00:00
State: open

I'm trying to work with leveldbjni-linux64-1.2-SNAPSHOT and found that get() on a nonexistent value works through

checkStatus(DBJNI.Get(self, options, keySlice, result.pointer()));

that throws exception if value was not found. Exceptions are usually not too good for performance and get() miss in my case is not an exceptional case.

The following test works 2700 ms with exceptions and 600ms after exceptions were removed in case of missed get():

import org.fusesource.leveldbjni.JniDBFactory;
import org.fusesource.leveldbjni.*;
import org.iq80.leveldb.*;

import java.io.File;
import java.io.IOException;
import java.util.*;

import static org.fusesource.leveldbjni.JniDBFactory.asString;
import static org.fusesource.leveldbjni.JniDBFactory.bytes;

public class Test {
static final DBFactory factory = JniDBFactory.factory;

public static void main(String[] args) throws Exception {
Options options = new Options().createIfMissing(true);

options.cacheSize(120 * 1024 * 1024);
options.writeBufferSize(8 * 1024 * 1024);
options.paranoidChecks(false);
options.verifyChecksums(false);
options.blockSize(4096);

DB db = factory.open(new File("gagaga"), options);

byte[] key = new byte[] {0, 0, 0, 0, -84, -19, 0, 5, 116, 0, 4, 107, 101, 121, 48};

long start = System.currentTimeMillis();

for(int i = 0; i < 1000000; i++) {
db.get(key);
}

long time = System.currentTimeMillis() - start;

System.out.println("test tool " + time + "ms");

db.close();

}
}

---

The "patch" is:

--- a/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeDB.java
+++ b/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/NativeDB.java
@@ -287,8 +287,22 @@ public class NativeDB extends NativeObject {
assertAllocated();
NativeStdString result = new NativeStdString();
try {
- checkStatus(DBJNI.Get(self, options, keySlice, result.pointer()));
- return result.toByteArray();
+ long s = DBJNI.Get(self, options, keySlice, result.pointer());
+
+ NativeStatus status = new NativeStatus(s);
+ try {
+ if(status.isOk()) {
+ return result.toByteArray();
+ }
+
+ if(status.isNotFound()) {
+ return null;
+ }
+
+ throw new DBException(status.toString(), status.isNotFound());
+ } finally {
+ status.delete();
+ }