tow open db with different name
ayalma opened this issue · 4 comments
why i can't create tow instance of Snappy db with different name at same time.
I believe there is a bug that prevents multiple databases from being opened in the same process. I'm surprised this issue hasn't been addressed: #26
It looks like the bug was root caused, but the fix hasn't been released, unfortunately. We'll be moving away from this library given the poor support in light of such a critical issue.
thank you so much .
i aggregate my dbs to one single db.
👍
would like to address the same issue, hopefully it can be fixed in future release?
do you have any plan to fix this?
@nhachicha
The change snappydb implementation to support more databases isn't so hard.
I implemented similar key value DB with leveldb but only for bytes[]
(we don't need to store other types of data to db).
please look on implementation: LevelDB.java
and leveldb_jni.cc
In my case LevelDB
isn't singleton, and it has private long nativeDB;
field that is used only by jni to store pointer to structure:
struct DatabaseNative {
leveldb::DB* db;
};
when you call java nativeOpen()
, jni jni_database_open
method will be invoked:
void jni_database_open(JNIEnv *env, jobject thiz, jstring dbpath) {
struct DatabaseNative *native = (struct DatabaseNative *)malloc(sizeof(struct DatabaseNative)); // allocate structure
leveldb::DB::Open(options, path, &native->db); // open database and save it to structure
jclass database_clazz = env->FindClass("com/appunite/leveldb/LevelDB"); // get class
database_clazz_field_native = env->GetFieldID(database_clazz, "nativeDB", "J"); //get java field
env->SetLongField(thiz, database_clazz_field_native, (jlong) native_db); // store structure to that field
}
and now in each operation you can get this structure:
void jni_database_put_bytes(JNIEnv *env, jobject thiz, jbyteArray jkey, jbyteArray jvalue) {
jclass database_clazz = env->FindClass("com/appunite/leveldb/LevelDB"); // get class
database_clazz_field_native = env->GetFieldID(database_clazz, "nativeDB", "J"); //get java field
struct DatabaseNative *native = (struct DatabaseNative * )env->GetLongField(thiz, database_clazz_field_native); // get struct from java field
native->db->Put(leveldb::WriteOptions(), key, value); // write to DB
}
The implementation is pretty straightforward. Simillar solution I wrote quite while ago in https://github.com/appunite/AndroidFFmpeg
btw: usually you don't have to use multiple databases opened because it's necessary. You can always use prefix for index:
database.put("post:" + postId, "your post");
database.put("comment:" + commentId, "your comment");
String post1 = database.get("post:" + "1");
and query for all:
KeysIterator posts = database.findKeysIterator("post:");
while (key.startWith("post:")) {
// read your post
}
look on KeyValueSnappy.getKeys()