julius
julius

Reputation: 875

Leveldb for Java: deleting while iterating

I am running this test:

public class LeveldbTest {

@Test
public void test() throws IOException, InterruptedException {
    DBFactory factory = new Iq80DBFactory();

    Options opts = new Options();
    opts.cacheSize(4096);
    opts.compressionType(CompressionType.SNAPPY);
    opts.createIfMissing(true).writeBufferSize(4096);
    final DB db = factory.open(new File("target/leveldb"), opts);
    final AtomicLong counter = new AtomicLong();

    long start = System.currentTimeMillis();
    new Thread() {
        @Override
        public void run() {
            WriteOptions wo = new WriteOptions();
            wo.sync(true);
            while (true) {
                String key = UUID.randomUUID().toString();
                byte[] bytes = key.getBytes();
                System.out.println("putting: " + key);
                db.put(bytes, bytes, wo);
                counter.incrementAndGet();
            }
        }
    }.start();

    new Thread() {
        @Override
        public void run() {
            WriteOptions wo = new WriteOptions();
            ReadOptions ro = new ReadOptions();
            wo.sync(true);
            while (true) {
                DBIterator iterator = db.iterator(ro);
                if (iterator.hasNext()) {
                    Entry<byte[], byte[]> next = iterator.next();
                    byte[] key = next.getKey();
                    System.out.println("deleting: " + new String(key));
                    db.delete(key, wo);
                    counter.incrementAndGet();
                    try {
                        iterator.close();
                    } catch (IOException e) {
                    }
                }
            }
        }
    }.start();

    Thread.sleep(3000);
    System.out.println((double) counter.longValue() / (System.currentTimeMillis() - start));
}
}

I am expecting that keys will be delete from the queue but in the console only the one and the same key seems to be deleted:

putting: a1ad4662-18c3-4085-af9d-a451dc3279c0
deleting: 004ef0c2-b278-42c6-9c85-4769d93d5b30 <-
putting: 6c4ee31d-2910-4870-acc5-962f9c40a573
deleting: 004ef0c2-b278-42c6-9c85-4769d93d5b30 <-
deleting: 004ef0c2-b278-42c6-9c85-4769d93d5b30 <-
putting: 63e2e438-3849-46e3-9ea0-1165f9356efb
deleting: 004ef0c2-b278-42c6-9c85-4769d93d5b30 <-

Am I using the API wrongly?

Upvotes: 0

Views: 1644

Answers (2)

gub
gub

Reputation: 5249

As you have observed when using the Iterator you have to point the iterator to a valid row with seekToFirst or seekToLast before iterating.

I've discovered this before (the hard way), it doesn't throw ISE as you might expect, you just get inconsistent reads.

Upvotes: 1

julius
julius

Reputation: 875

It turns out that if I call iterator.seekToFirst() before calling next() in the deleter thread it behaves as I expect. The question then is where is the iterator pointing if I don't seek to a location.

Upvotes: 1

Related Questions