/levelkt

LevelDB client for Kotlin and/or Java 8+

Primary LanguageKotlin

levelkt

Build Status Maven Central ktlint

LevelDB client for Kotlin and/or Java 8+.

Initially project aimed to provide an alternative API for fusesource/leveldbjni's JNI layer fixing some of the issues around thread-safety, inefficient backward traversal, absent key-only iteration, Java 8 support. Later on, leveldbjni was replaced with protonail/leveldb-jna.

Compared to pure leveldb-jna, levelkt

  • hides the complexity associated with managing LevelDB Read/Write options
    (while optimizing number of JNA calls),
  • provides convenient API for range/prefix queries, existence checks and
  • makes it easier not to leak resources (you only need to close LevelDB, LevelDBSnapshot and LevelDBCursor instances (it will also warn you if you don't)).

Usage

<dependency>
    <groupId>com.github.shyiko.levelkt</groupId>
    <artifactId>levelkt</artifactId>
    <version>0.1.0</version>
    <!-- omit classifier below if you plan to use this library in koltin -->
    <classifier>kalvanized</classifier>
</dependency>

(example) Kotlin

import com.github.shyiko.levelkt.jna.JNALevelDB

JNALevelDB("/tmp/0.leveldb").use { levelDB ->

    levelDB.put("key1".toByteArray(), "value1".toByteArray())
    levelDB.put("key2.1".toByteArray(), "value2.1".toByteArray())
    levelDB.put("key2.2".toByteArray(), "value2.2".toByteArray())
    levelDB.put("key3".toByteArray(), "value3".toByteArray())

    assert(levelDB.get("key1".toByteArray())?.let { String(it) } == "value1")

    assert(levelDB.keySlice("key".toByteArray(), offset = 1, limit = 2).map { String(it) } == 
        listOf("key2.1", "key2.2"))
    assert(levelDB.keySlice("key2".toByteArray(), "key3".toByteArray()).map { String(it) } == 
        listOf("key2.1", "key2.2"))
    assert(levelDB.keySliceByPrefix("key2".toByteArray()).map { String(it) } == 
        listOf("key2.1", "key2.2"))

    levelDB.keyCursor().use { cursor ->
        assert(cursor.seek("key2".toByteArray())?.let { String(it) } == "key2.1")
        assert(cursor.next()?.let { String(it) } == "key2.2")
    }

    // slice/sliceByPrefix/cursor look exactly the same as keySlice/keySliceByPrefix/keyCursor
    // the only difference - they operate with LevelDBRecord instead of ByteArray

    levelDB.batch {
        put("key1".toByteArray(), "value1.updated".toByteArray())
        del("key3".toByteArray())
    }

    levelDB.del("key1".toByteArray())
    
}

(example) Java 8+

import com.github.shyiko.levelkt.LevelDB;
import com.github.shyiko.levelkt.jna.JNALevelDB;

try (LevelDB levelDB = new JNALevelDB("/tmp/0.levedb")) {

    levelDB.batch(batch -> batch
        .put("key1".getBytes(), "value1".getBytes())
        .put("key2.1".getBytes(), "value2.1".getBytes())
        .put("key2.2".getBytes(), "value2.2".getBytes())
        .put("key3".getBytes(), "value3".getBytes())
    );

    assert levelDB
        .sliceByPrefix("key2".getBytes())
        .stream()
        .map(record -> new String(record.getKey()) + "=" + new String(record.getValue()))
        .collect(Collectors.toList())
        .equals(Arrays.asList("key2.1=value2.1", "key2.2=value2.2"));

}

Development

git clone https://github.com/shyiko/levelkt && cd levelkt
./mvnw # shows how to build, test, etc. project

Legal

All code, unless specified otherwise, is licensed under the MIT license.
Copyright (c) 2017 Stanley Shyiko.