Skip to content

Commit 0cc7ef5

Browse files
author
wulei
committed
quickcheck elmdb
1 parent 725812a commit 0cc7ef5

File tree

6 files changed

+201
-48
lines changed

6 files changed

+201
-48
lines changed

Makefile

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,16 @@ PROJECT = elmdb
22
PROJECT_DESCRIPTION = New project
33
PROJECT_VERSION = 0.1.0
44

5-
#CFLAGS +=-DMYDEBUG
5+
TEST_DEPS = proper
6+
7+
CFLAGS += -DNODEBUG
68
CFLAGS += -pthread
7-
CFLAGS += -DMDB_DEBUG
9+
#CFLAGS += -DMDB_DEBUG
10+
11+
CONFIG ?= config/sys.config
12+
SHELL=/bin/bash
13+
SHELL_OPTS = -config ${CONFIG}
814

15+
EUNIT_ERL_OPTS = -config ${CONFIG}
16+
PROPER_ERL_OPTS = -config ${CONFIG}
917
include erlang.mk

c_src/common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
/* Atoms (initialized in on_load) */
1111
static ERL_NIF_TERM ATOM_ERROR;
1212
static ERL_NIF_TERM ATOM_OK;
13+
static ERL_NIF_TERM ATOM_NO_LAYER;
1314
static ERL_NIF_TERM ATOM_NOT_FOUND;
1415
static ERL_NIF_TERM ATOM_DBI_NOT_FOUND;
1516
static ERL_NIF_TERM ATOM_EXISTS;

c_src/elmdb_nif.c

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "liblmdb/lmdb.h"
1111
#include "mylog.h"
1212

13+
#define MAXSUBDB 512
1314
#define SUBDB_NAME_SZ 64
1415

1516
#define CHECK(expr, label) \
@@ -116,7 +117,7 @@ static ERL_NIF_TERM elmdb_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
116117

117118
MDB_env *ctx;
118119
CHECK(mdb_env_create(&ctx), err2);
119-
CHECK(mdb_env_set_maxdbs(ctx, 256 - 2), err2);
120+
CHECK(mdb_env_set_maxdbs(ctx, MAXSUBDB - 2), err2);
120121
CHECK(mdb_env_set_mapsize(ctx, 10485760), err2);
121122

122123
unsigned int envFlags = 0 | MDB_NOTLS;
@@ -207,7 +208,6 @@ static ERL_NIF_TERM elmdb_path(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
207208

208209
const char* path;
209210
mdb_env_get_path(handle->env, &path);
210-
DBG("path: %s",path);
211211
return enif_make_string(env, path, ERL_NIF_LATIN1);
212212
}
213213

@@ -227,7 +227,7 @@ static ERL_NIF_TERM elmdb_drop(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
227227
bool exist = (kh_get(layer,handle->layers, dbname) != kh_end(handle->layers));
228228
enif_rwlock_runlock(handle->layers_rwlock);
229229
if (!exist) {
230-
DBG("layer(sub-db: %s) NOT exist", dbname);
230+
DBG("layer(sub-db: %s) NoT exist", dbname);
231231
return enif_raise_exception(env,
232232
enif_make_tuple2(env, ATOM_DBI_NOT_FOUND, argv[1]));
233233
}
@@ -272,7 +272,7 @@ static ERL_NIF_TERM elmdb_count(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
272272
bool exist = (kh_get(layer,handle->layers, dbname) != kh_end(handle->layers));
273273
enif_rwlock_runlock(handle->layers_rwlock);
274274
if (!exist) {
275-
ERR_LOG("layer(sub-db: %s) NOT exist", dbname);
275+
WARN_LOG("layer(sub-db: %s) NOT exist", dbname);
276276
return enif_make_int(env, 0);
277277
}
278278

@@ -402,7 +402,7 @@ static ERL_NIF_TERM elmdb_put(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
402402
CHECK(mdb_txn_commit(txn), err3);
403403
// After a successful commit dbi will reside in the shared environment,
404404
// and may be used by other transactions.
405-
return argv[0];
405+
return ATOM_OK;
406406

407407
err1:
408408
enif_rwlock_rwunlock(handle->layers_rwlock);
@@ -440,8 +440,8 @@ static ERL_NIF_TERM elmdb_get(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
440440
bool exist = (kh_get(layer,handle->layers, dbname) != kh_end(handle->layers));
441441
enif_rwlock_runlock(handle->layers_rwlock);
442442
if (!exist) {
443-
ERR_LOG("no layer created for %s", dbname);
444-
return enif_raise_exception(env,
443+
WARN_LOG("no layer created for %s", dbname);
444+
return enif_make_tuple2(env, ATOM_ERROR,
445445
enif_make_tuple2(env, ATOM_DBI_NOT_FOUND, laykey[0]));
446446
}
447447

@@ -453,7 +453,10 @@ static ERL_NIF_TERM elmdb_get(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
453453
CHECK(mdb_dbi_open(txn, dbname, 0, &dbi), err1);
454454

455455
MDB_val val;
456-
CHECK( mdb_get(txn, dbi, &mykey.key, &val), err1);
456+
if (MDB_NOTFOUND == mdb_get(txn, dbi, &mykey.key, &val)) {
457+
err = enif_make_tuple2(env, ATOM_ERROR, ATOM_NOTFOUND);
458+
goto err1;
459+
}
457460
mdb_txn_abort(txn);
458461

459462
ERL_NIF_TERM res;
@@ -482,7 +485,7 @@ static ERL_NIF_TERM min_max(ErlNifEnv* env, const ERL_NIF_TERM argv[], MDB_curso
482485
bool exist = (kh_get(layer,handle->layers, dbname) != kh_end(handle->layers));
483486
enif_rwlock_runlock(handle->layers_rwlock);
484487
if (!exist) {
485-
ERR_LOG("no layer created for %s", dbname);
488+
WARN_LOG("no layer created for %s", dbname);
486489
return enif_raise_exception(env,
487490
enif_make_tuple2(env, ATOM_DBI_NOT_FOUND, argv[1]));
488491
}
@@ -569,8 +572,10 @@ static ERL_NIF_TERM elmdb_del(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
569572
bool exist = (kh_get(layer,handle->layers, dbname) != kh_end(handle->layers));
570573
enif_rwlock_runlock(handle->layers_rwlock);
571574
if (!exist) {
572-
ERR_LOG("no layer created for %s", dbname);
573-
return argv[0];
575+
WARN_LOG("no layer created for %s", dbname);
576+
return enif_make_tuple2(env, ATOM_ERROR,
577+
enif_make_tuple2(env, ATOM_NO_LAYER,
578+
enif_make_string(env, dbname, ERL_NIF_LATIN1)));
574579
}
575580

576581
int ret;
@@ -581,9 +586,11 @@ static ERL_NIF_TERM elmdb_del(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
581586
CHECK(mdb_dbi_open(txn, dbname, 0, &dbi), err1);
582587
DBG("open dbi: %d", dbi);
583588

584-
CHECK( mdb_del(txn, dbi, &mykey.key, NULL), err1);
585-
mdb_txn_commit(txn);
586-
return argv[0];
589+
if (MDB_NOTFOUND == mdb_del(txn, dbi, &mykey.key, NULL))
590+
mdb_txn_abort(txn);
591+
else
592+
mdb_txn_commit(txn);
593+
return ATOM_OK;
587594

588595
err1:
589596
mdb_txn_abort(txn);
@@ -623,7 +630,7 @@ static ERL_NIF_TERM elmdb_range(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
623630
bool exist = (kh_get(layer,handle->layers, dbname) != kh_end(handle->layers));
624631
enif_rwlock_runlock(handle->layers_rwlock);
625632
if (!exist) {
626-
ERR_LOG("no layer(sub-db) created for %s", dbname);
633+
WARN_LOG("no layer(sub-db) created for %s", dbname);
627634
return enif_raise_exception(env,
628635
enif_make_tuple2(env, ATOM_DBI_NOT_FOUND, argv[1]));
629636
}
@@ -645,17 +652,20 @@ static ERL_NIF_TERM elmdb_range(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
645652
MDB_val val;
646653

647654
my_key_t mykey = { };
648-
CHECKOUT_MYKEY(argv[2], mykey, err1);
655+
CHECKOUT_MYKEY(argv[2], mykey, err2);
649656
MDB_val iterkey;
650657
iterkey.mv_data = mykey.key.mv_data;
651658
iterkey.mv_size = mykey.key.mv_size;
652659

653660
my_key_t endkey = { };
654661
if (argc == 4) {
655-
CHECKOUT_MYKEY(argv[3], endkey, err1);
662+
CHECKOUT_MYKEY(argv[3], endkey, err2);
656663
}
657-
else {
658-
CHECK(mdb_cursor_get(cur, &endkey.key, NULL, MDB_LAST), err1);
664+
else if (mdb_cursor_get(cur, &endkey.key, NULL, MDB_LAST) == MDB_NOTFOUND) {
665+
// A cursor in a read-only transaction must be closed explicitly
666+
mdb_cursor_close(cur);
667+
mdb_txn_abort(txn);
668+
return map;
659669
}
660670
MDB_cursor_op op = MDB_SET_RANGE;
661671
while ((ret = mdb_cursor_get(cur, &iterkey, &val, op)) != MDB_NOTFOUND) {
@@ -684,7 +694,8 @@ static ERL_NIF_TERM elmdb_range(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
684694
mdb_dbi_close(handle->env, dbi);
685695
err2:
686696
mdb_txn_abort(txn);
687-
return enif_raise_exception(env, err);
697+
err3:
698+
return err;
688699
}
689700

690701
static ERL_NIF_TERM elmdb_to_map(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
@@ -706,7 +717,7 @@ static ERL_NIF_TERM elmdb_to_map(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
706717
bool exist = (kh_get(layer,handle->layers, dbname) != kh_end(handle->layers));
707718
enif_rwlock_runlock(handle->layers_rwlock);
708719
if (!exist) {
709-
ERR_LOG("no layer(sub-db) created for %s", dbname);
720+
WARN_LOG("no layer(sub-db) created for %s", dbname);
710721
return enif_raise_exception(env,
711722
enif_make_tuple2(env, ATOM_DBI_NOT_FOUND, argv[1]));
712723
}
@@ -816,7 +827,7 @@ static ERL_NIF_TERM elmdb_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
816827
bool exist = (kh_get(layer,handle->layers, dbname) != kh_end(handle->layers));
817828
enif_rwlock_runlock(handle->layers_rwlock);
818829
if (!exist) {
819-
ERR_LOG("no layer(sub-db) created for %s", dbname);
830+
WARN_LOG("no layer(sub-db) created for %s", dbname);
820831
return enif_raise_exception(env,
821832
enif_make_tuple2(env, ATOM_DBI_NOT_FOUND, argv[1]));
822833
}
@@ -871,6 +882,7 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
871882
loads++;
872883

873884
ATOM_ERROR = enif_make_atom(env, "error");
885+
ATOM_NO_LAYER = enif_make_atom(env, "notfound_layer");
874886
ATOM_OK = enif_make_atom(env, "ok");
875887
ATOM_NOT_FOUND = enif_make_atom(env, "not_found");
876888
ATOM_DBI_NOT_FOUND = enif_make_atom(env, "dbi_not_found");

c_src/mylog.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,18 +54,18 @@
5454
#endif
5555

5656

57-
#ifdef MYDEBUG
57+
#ifdef NODEBUG
5858

5959
#define DBG(fmt, ...)
60-
#define WARN(fmt, ...)
60+
#define WARN_LOG(fmt, ...)
6161

6262
#else
6363

6464
#define DBG(fmt, ...) enif_fprintf(stdout, GREY("%s-%llx [%34s#%-5d@(tid:%llx)]") " " fmt "\r\n",enif_thread_name(enif_thread_self()), enif_thread_self(),__FUNCTION__,__LINE__,thrd_id(), ##__VA_ARGS__)
6565
#define WARN(fmt, ...) enif_fprintf(stdout, B_MAGENTA("[%34s#%-5d@(tid:%llx)]") " " fmt "\r\n", __FUNCTION__,__LINE__,thrd_id(), ##__VA_ARGS__)
66+
#define WARN_LOG(fmt, ...) enif_fprintf(stderr, B_YELLOW("[@(tid:%llx)] " fmt) "\r\n", thrd_id(), ##__VA_ARGS__)
6667

6768
#endif
6869

6970
#define INFO_LOG(fmt, ...) enif_fprintf(stderr, "[@(tid:%llx)] " fmt "\r\n", thrd_id(), ##__VA_ARGS__)
70-
#define WARN_LOG(fmt, ...) enif_fprintf(stderr, B_YELLOW("[@(tid:%llx)] " fmt) "\r\n", thrd_id(), ##__VA_ARGS__)
7171
#define ERR_LOG(fmt, ...) enif_fprintf(stderr, B_RED("[@(tid:%llx)] " fmt) "\r\n", thrd_id(), ##__VA_ARGS__)

src/elmdb.erl

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
-export([ls/1]).
1919
-export([foldl/4]).
2020

21+
-export([db_path/1]).
22+
23+
-include_lib("kernel/include/logger.hrl").
24+
2125
-on_load(on_load/0).
2226

2327
on_load() ->
@@ -36,9 +40,11 @@ hello(_) ->
3640
to_map(_LmdbRes, _Layer) ->
3741
erlang:nif_error({not_loaded, ?MODULE}).
3842

43+
-spec range(reference(), string(), non_neg_integer()) -> map().
3944
range(_LmdbRes, _Layer, _Begin) ->
4045
erlang:nif_error({not_loaded, ?MODULE}).
4146

47+
-spec range(reference(), string(), non_neg_integer(), non_neg_integer()) -> map().
4248
range(_LmdbRes, _Layer, _Begin, _End) ->
4349
erlang:nif_error({not_loaded, ?MODULE}).
4450

@@ -63,6 +69,7 @@ db_path(_) ->
6369
dispose(LmdbRes) ->
6470
try db_path(LmdbRes) of
6571
Dir ->
72+
?LOG_NOTICE("dispose db: ~ts", [Dir]),
6673
ok = close(LmdbRes),
6774
[file:delete(F) || F <- filelib:wildcard(Dir ++ "/*")],
6875
file:del_dir(Dir)
@@ -77,15 +84,15 @@ drop(_LmdbRes, _Layer) ->
7784
count(_LmdbRes, _Layer) ->
7885
erlang:nif_error({not_loaded, ?MODULE}).
7986

80-
-spec put(reference(), {string(), binary()}, binary()) -> reference().
87+
-spec put(reference(), {string(), binary()}, binary()) -> ok.
8188
put(_LmdbRes, {_Layer,_Key}, _Value) ->
8289
erlang:nif_error({not_loaded, ?MODULE}).
8390

8491
-spec get(reference(), {string(), binary()|integer()}) -> binary().
8592
get(_LmdbRes, {_Layer,_Key}) ->
8693
erlang:nif_error({not_loaded, ?MODULE}).
8794

88-
-spec del(reference(), {string(), binary()|integer()}) -> reference().
95+
-spec del(reference(), {string(), binary()|integer()}) -> ok|{error,any()}.
8996
del(_LmdbRes, {_Layer,_Key}) ->
9097
erlang:nif_error({not_loaded, ?MODULE}).
9198

0 commit comments

Comments
 (0)