Wrapping and Extending the LevelDB Java API with Custom Features
This article demonstrates how to encapsulate the native LevelDB Java API into a reusable class, adds support for integer values and Redis‑like operations such as increment, decrement, append, and cut, and provides complete code examples for the extended functionality.
In the previous post I introduced a LevelDB Java & Go practice; this time I wrap the native LevelDB API into a custom class and extend it to behave more like Redis, supporting integer values and additional operations.
Encapsulation
The wrapper follows the previous base‑object approach: each LevelDB instance is represented by a custom class, providing methods that hide the conversion between String and byte[] . This reduces boilerplate and makes the code cleaner.
/**
* LevelDB database operation class
*/
class LevelBase extends SourceCode {
static Iq80DBFactory factory = Iq80DBFactory.factory;
static Options options = new Options();
DB db;
/**
* Create object
* @param path
*/
LevelBase(String path) {
db = factory.open(new File(getLongFile(path)), options);
}
/**
* Get value
* @param key
* @return
*/
def get(String key) {
new String(db.get(bytes(key)), DEFAULT_CHARSET);
}
/**
* Store data
* @param key
* @param value
* @return
*/
def put(String key, String value) {
db.put(bytes(key), bytes(value));
}
/**
* Delete a value
* @param key
* @return
*/
def del(String key) {
db.delete(bytes(key));
}
/**
* Get all keys
* @return
*/
def keys() {
def keys = [];
DBIterator iterator = db.iterator();
while (iterator.hasNext()) {
Map.Entry
next = iterator.next();
keys << next.key;
}
return keys;
}
/**
* Close
* @return
*/
def close() {
db.close();
}
}Feature Extension
To support integer values, the wrapper adds conversion between int and String . Inspired by com.funtester.db.redis.RedisBase , additional methods such as incr , decr , add , minus , append , and cut are implemented, all handling the necessary String / byte[] conversions. Increment/decrement methods are synchronized to avoid thread‑safety issues during performance testing.
/**
* Get int value
* @param key
* @return
*/
def getInt(String key) {
return changeStringToInt(get(key));
}
/**
* Append content to existing value
* @param key
* @param content
* @return
*/
def append(String key, String content) {
put(key, get(key) + content);
}
/**
* Remove a fragment from existing value
* @param key
* @param content
* @return
*/
def cut(String key, String content) {
put(key, get(key) - content);
}
/**
* Put int value
* @param key
* @param value
* @return
*/
def putInt(String key, int value) {
db.put(bytes(key), bytes(value + EMPTY));
}
/**
* Increment
* @param key
* @return
*/
def incr(String key) {
add(key, 1);
}
/**
* Decrement
* @param key
* @return
*/
def decr(String key) {
minus(key, 1);
}
/**
* Add i to value
* @param key
* @param i
* @return
*/
def add(String key, int i) {
synchronized (this) {
putInt(key, getInt(key) + i);
}
}
/**
* Subtract i from value
* @param key
* @param i
* @return
*/
def minus(String key, int i) {
add(key, -i);
}This post shares the Java implementation and extensions; the next post will cover the Go implementation and several testing scenarios for LevelDB. Stay tuned to FunTester for more.
FunTester
10k followers, 1k articles | completely useless
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.