Skip to content

Commit 571823b

Browse files
author
wulei
committed
retrive key-value pairs in the range
1 parent 29f6e9e commit 571823b

File tree

3 files changed

+102
-1
lines changed

3 files changed

+102
-1
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ every key-value must be in a named sub-db
1010
* `ls/1`: list all sub-db
1111
* `put/3`: inserts/update Key with value Val into the sub-db
1212
* `get/2`: retrieves the value stored with Key in the sub-db
13+
* `range/3`: retrives the key-value pairs in the range [From...) in the sub-db
14+
* `range/4`: retrives the key-value pairs between the range [From,To] in the sub-db
1315
* `del/2`: Removes the key-value pair with key from the sub-db
1416
* `count/2`: Count the key-value number for the sub-db
1517
* `drop/2`: deletes all key-value pairs in the sub-db.

c_src/elmdb_nif.c

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,95 @@ static ERL_NIF_TERM elmdb_ls(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
552552
return list;
553553
}
554554

555+
static ERL_NIF_TERM elmdb_range(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
556+
__UNUSED(argc);
557+
lmdb_env_t *handle = NULL;
558+
if (!enif_get_resource(env, argv[0], lmdbEnvResType, (void**)&handle)) {
559+
return enif_make_badarg(env);
560+
}
561+
if (handle->env == NULL) return enif_raise_exception(env, enif_make_string(env, "closed lmdb", ERL_NIF_LATIN1));
562+
563+
ErlNifBinary layBin;
564+
if (!enif_inspect_iolist_as_binary(env, argv[1], &layBin)) {
565+
return enif_make_badarg(env);
566+
}
567+
char dbname[SUBDB_NAME_SZ] = {0};
568+
memcpy(dbname, layBin.data, layBin.size);
569+
570+
enif_rwlock_rlock(handle->layers_rwlock);
571+
bool exist = (kh_get(layer,handle->layers, dbname) != kh_end(handle->layers));
572+
enif_rwlock_runlock(handle->layers_rwlock);
573+
if (!exist) {
574+
ERR_LOG("no layer(sub-db) created for %s", dbname);
575+
return enif_raise_exception(env,
576+
enif_make_tuple2(env, ATOM_DBI_NOT_FOUND, argv[1]));
577+
}
578+
579+
int ret;
580+
ERL_NIF_TERM err;
581+
582+
MDB_txn *txn = NULL;
583+
CHECK(mdb_txn_begin(handle->env, NULL, MDB_RDONLY, &txn), err2);
584+
MDB_dbi dbi;
585+
CHECK(mdb_dbi_open(txn, dbname, 0, &dbi), err2);
586+
DBG("open sub-db: %d for %s", dbi, dbname);
587+
unsigned int dbflag = 0;
588+
CHECK(mdb_dbi_flags(txn, dbi, &dbflag), err1);
589+
MDB_cursor *cur;
590+
CHECK(mdb_cursor_open(txn, dbi, &cur), err1);
591+
592+
ERL_NIF_TERM map = enif_make_new_map(env);
593+
MDB_val val;
594+
595+
my_key_t mykey = { };
596+
if (!get_mykey_from(env, argv[2], &mykey)) {
597+
err = enif_raise_exception(env, enif_make_string(env, "cannot extract key", ERL_NIF_LATIN1));
598+
goto err1;
599+
}
600+
MDB_val iterkey;
601+
iterkey.mv_data = mykey.key.mv_data;
602+
iterkey.mv_size = mykey.key.mv_size;
603+
604+
my_key_t endkey = { };
605+
if (argc == 4) {
606+
if (!get_mykey_from(env, argv[3], &endkey)) {
607+
err = enif_raise_exception(env, enif_make_string(env, "cannot extract key", ERL_NIF_LATIN1));
608+
goto err1;
609+
}
610+
}
611+
else {
612+
CHECK(mdb_cursor_get(cur, &endkey.key, NULL, MDB_LAST), err1);
613+
}
614+
MDB_cursor_op op = MDB_SET_RANGE;
615+
while ((ret = mdb_cursor_get(cur, &iterkey, &val, op)) != MDB_NOTFOUND) {
616+
if (mdb_cmp(txn, dbi, &iterkey, &endkey.key) > 0)
617+
break;
618+
ERL_NIF_TERM keyTerm;
619+
if (dbflag & MDB_INTEGERKEY) {
620+
keyTerm = enif_make_int64(env, *((ErlNifSInt64*)iterkey.mv_data));
621+
}
622+
else {
623+
unsigned char* ptr = enif_make_new_binary(env, iterkey.mv_size, &keyTerm);
624+
memcpy(ptr, iterkey.mv_data, iterkey.mv_size);
625+
}
626+
ERL_NIF_TERM valTerm;
627+
unsigned char* ptr = enif_make_new_binary(env, val.mv_size, &valTerm);
628+
memcpy(ptr, val.mv_data, val.mv_size);
629+
enif_make_map_put(env, map, keyTerm, valTerm, &map);
630+
op = MDB_NEXT;
631+
}
632+
mdb_cursor_close(cur);
633+
mdb_dbi_close(handle->env, dbi);
634+
mdb_txn_abort(txn);
635+
return map;
636+
637+
err1:
638+
mdb_dbi_close(handle->env, dbi);
639+
err2:
640+
mdb_txn_abort(txn);
641+
return enif_raise_exception(env, err);
642+
}
643+
555644
static ERL_NIF_TERM elmdb_to_map(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
556645
lmdb_env_t *handle = NULL;
557646
if (!enif_get_resource(env, argv[0], lmdbEnvResType, (void**)&handle)) {
@@ -671,8 +760,10 @@ static ErlNifFunc nif_funcs[] = {
671760
{"get", 2, elmdb_get, 0},
672761
{"del", 2, elmdb_del, 0},
673762
{"ls", 1, elmdb_ls, 0},
763+
{"range", 3, elmdb_range, ERL_NIF_DIRTY_JOB_IO_BOUND},
764+
{"range", 4, elmdb_range, ERL_NIF_DIRTY_JOB_IO_BOUND},
674765
{"to_map", 2, elmdb_to_map, ERL_NIF_DIRTY_JOB_IO_BOUND},
675-
{"hello", 1, hello}
766+
{"hello", 1, hello, 0}
676767
};
677768

678769
ERL_NIF_INIT(elmdb, nif_funcs, load, NULL, upgrade, unload)

src/elmdb.erl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
-export([put/3]).
1111
-export([get/2]).
1212
-export([del/2]).
13+
-export([range/3]).
14+
-export([range/4]).
1315
-export([ls/1]).
1416

1517
-on_load(on_load/0).
@@ -29,6 +31,12 @@ hello(_) ->
2931
to_map(_LmdbRes, _Layer) ->
3032
erlang:nif_error({not_loaded, ?MODULE}).
3133

34+
range(_LmdbRes, _Layer, _Begin) ->
35+
erlang:nif_error({not_loaded, ?MODULE}).
36+
37+
range(_LmdbRes, _Layer, _Begin, _End) ->
38+
erlang:nif_error({not_loaded, ?MODULE}).
39+
3240
-spec open(filelib:dirname()) -> reference().
3341
open(DirName) ->
3442
filelib:ensure_dir(DirName ++ "/"),

0 commit comments

Comments
 (0)