From 6c1c27a51aaebabd269fb59ea8eb2654791643e0 Mon Sep 17 00:00:00 2001 From: Gregory Burd Date: Mon, 5 Aug 2013 12:45:43 -0400 Subject: [PATCH] WIP: adding more of the API. --- c_src/lmdb.c | 158 +++++++++++++++++++++-------------- c_src/lmdb_nif.c | 207 +++++++++++++++++++++++++++++----------------- rebar.config | 1 + tools/lmdb.config | 11 ++- 4 files changed, 237 insertions(+), 140 deletions(-) diff --git a/c_src/lmdb.c b/c_src/lmdb.c index 4d68600..e6056c3 100644 --- a/c_src/lmdb.c +++ b/c_src/lmdb.c @@ -2949,6 +2949,19 @@ mdb_env_init_meta(MDB_env *env, MDB_meta *meta) MDB_page *p, *q; int rc; unsigned int psize; +#ifdef _WIN32 + DWORD len; + OVERLAPPED ov; + memset(&ov, 0, sizeof(ov)); +#define DO_PWRITE(rc, fd, ptr, size, len, pos) do { \ + ov.Offset = pos; \ + rc = WriteFile(fd, ptr, size, &len, &ov); } while(0) +#else + unsigned int len; +#define DO_PWRITE(rc, fd, ptr, size, len, pos) do { \ + len = pwrite(fd, ptr, size, pos); \ + rc = (len >= 0); } while(0) +#endif DPUTS("writing new meta page"); @@ -2974,18 +2987,13 @@ mdb_env_init_meta(MDB_env *env, MDB_meta *meta) q->mp_flags = P_META; *(MDB_meta *)METADATA(q) = *meta; -#ifdef _WIN32 - { - DWORD len; - OVERLAPPED ov; - memset(&ov, 0, sizeof(ov)); - rc = WriteFile(env->me_fd, p, psize * 2, &len, &ov); - rc = rc ? (len == psize * 2 ? MDB_SUCCESS : EIO) : ErrCode(); - } -#else - rc = pwrite(env->me_fd, p, psize * 2, 0); - rc = (rc == (int)psize * 2) ? MDB_SUCCESS : rc < 0 ? ErrCode() : EIO; -#endif + DO_PWRITE(rc, env->me_fd, p, psize * 2, len, 0); + if (!rc) + rc = ErrCode(); + else if (len == psize * 2) + rc = MDB_SUCCESS; + else + rc = ENOSPC; free(p); return rc; } @@ -3535,20 +3543,35 @@ mdb_hash_val(MDB_val *val, mdb_hash_t hval) return hval; } -/** Hash the string and output the hash in hex. +/** Hash the string and output the encoded hash. + * This uses modified RFC1924 Ascii85 encoding to accommodate systems with + * very short name limits. We don't care about the encoding being reversible, + * we just want to preserve as many bits of the input as possible in a + * small printable string. * @param[in] str string to hash - * @param[out] hexbuf an array of 17 chars to hold the hash + * @param[out] encbuf an array of 11 chars to hold the hash */ +const static char mdb_a85[]= "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~"; static void -mdb_hash_hex(MDB_val *val, char *hexbuf) +mdb_pack85(unsigned long l, char *out) { int i; - mdb_hash_t h = mdb_hash_val(val, MDB_HASH_INIT); - for (i=0; i<8; i++) { - hexbuf += sprintf(hexbuf, "%02x", (unsigned int)h & 0xff); - h >>= 8; + for (i=0; i<5; i++) { + *out++ = mdb_a85[l % 85]; + l /= 85; } } + +static void +mdb_hash_enc(MDB_val *val, char *encbuf) +{ + mdb_hash_t h = mdb_hash_val(val, MDB_HASH_INIT); + unsigned long *l = (unsigned long *)&h; + + mdb_pack85(l[0], encbuf); + mdb_pack85(l[1], encbuf+5); + encbuf[10] = '\0'; +} #endif /** Open and/or initialize the lock region for the environment. @@ -3661,7 +3684,7 @@ mdb_env_setup_locks(MDB_env *env, char *lpath, int mode, int *excl) DWORD nlow; } idbuf; MDB_val val; - char hexbuf[17]; + char encbuf[11]; if (!mdb_sec_inited) { InitializeSecurityDescriptor(&mdb_null_sd, @@ -3678,9 +3701,9 @@ mdb_env_setup_locks(MDB_env *env, char *lpath, int mode, int *excl) idbuf.nlow = stbuf.nFileIndexLow; val.mv_data = &idbuf; val.mv_size = sizeof(idbuf); - mdb_hash_hex(&val, hexbuf); - sprintf(env->me_txns->mti_rmname, "Global\\MDBr%s", hexbuf); - sprintf(env->me_txns->mti_wmname, "Global\\MDBw%s", hexbuf); + mdb_hash_enc(&val, encbuf); + sprintf(env->me_txns->mti_rmname, "Global\\MDBr%s", encbuf); + sprintf(env->me_txns->mti_wmname, "Global\\MDBw%s", encbuf); env->me_rmutex = CreateMutex(&mdb_all_sa, FALSE, env->me_txns->mti_rmname); if (!env->me_rmutex) goto fail_errno; env->me_wmutex = CreateMutex(&mdb_all_sa, FALSE, env->me_txns->mti_wmname); @@ -3692,16 +3715,22 @@ mdb_env_setup_locks(MDB_env *env, char *lpath, int mode, int *excl) ino_t ino; } idbuf; MDB_val val; - char hexbuf[17]; + char encbuf[11]; +#if defined(__NetBSD__) +#define MDB_SHORT_SEMNAMES 1 /* limited to 14 chars */ +#endif if (fstat(env->me_lfd, &stbuf)) goto fail_errno; idbuf.dev = stbuf.st_dev; idbuf.ino = stbuf.st_ino; val.mv_data = &idbuf; val.mv_size = sizeof(idbuf); - mdb_hash_hex(&val, hexbuf); - sprintf(env->me_txns->mti_rmname, "/MDBr%s", hexbuf); - sprintf(env->me_txns->mti_wmname, "/MDBw%s", hexbuf); + mdb_hash_enc(&val, encbuf); +#ifdef MDB_SHORT_SEMNAMES + encbuf[9] = '\0'; /* drop name from 15 chars to 14 chars */ +#endif + sprintf(env->me_txns->mti_rmname, "/MDBr%s", encbuf); + sprintf(env->me_txns->mti_wmname, "/MDBw%s", encbuf); /* Clean up after a previous run, if needed: Try to * remove both semaphores before doing anything else. */ @@ -3984,6 +4013,14 @@ mdb_env_copyfd(MDB_env *env, HANDLE fd) int rc; size_t wsize; char *ptr; +#ifdef _WIN32 + DWORD len, w2; +#define DO_WRITE(rc, fd, ptr, w2, len) rc = WriteFile(fd, ptr, w2, &len, NULL) +#else + ssize_t len; + size_t w2; +#define DO_WRITE(rc, fd, ptr, w2, len) len = write(fd, ptr, w2); rc = (len >= 0) +#endif /* Do the lock/unlock of the reader mutex before starting the * write txn. Otherwise other read txns could block writers. @@ -4007,52 +4044,50 @@ mdb_env_copyfd(MDB_env *env, HANDLE fd) } wsize = env->me_psize * 2; -#ifdef _WIN32 - { - DWORD len; - rc = WriteFile(fd, env->me_map, wsize, &len, NULL); - rc = rc ? (len == wsize ? MDB_SUCCESS : EIO) : ErrCode(); + ptr = env->me_map; + w2 = wsize; + while (w2 > 0) { + DO_WRITE(rc, fd, ptr, w2, len); + if (!rc) { + rc = ErrCode(); + break; + } else if (len > 0) { + rc = MDB_SUCCESS; + ptr += len; + w2 -= len; + continue; + } else { + /* Non-blocking or async handles are not supported */ + rc = EIO; + break; + } } -#else - rc = write(fd, env->me_map, wsize); - rc = rc == (int)wsize ? MDB_SUCCESS : rc < 0 ? ErrCode() : EIO; -#endif if (env->me_txns) UNLOCK_MUTEX_W(env); if (rc) goto leave; - ptr = env->me_map + wsize; wsize = txn->mt_next_pgno * env->me_psize - wsize; -#ifdef _WIN32 while (wsize > 0) { - DWORD len, w2; if (wsize > MAX_WRITE) w2 = MAX_WRITE; else w2 = wsize; - rc = WriteFile(fd, ptr, w2, &len, NULL); - rc = rc ? (len == w2 ? MDB_SUCCESS : EIO) : ErrCode(); - if (rc) break; - wsize -= w2; - ptr += w2; + DO_WRITE(rc, fd, ptr, w2, len); + if (!rc) { + rc = ErrCode(); + break; + } else if (len > 0) { + rc = MDB_SUCCESS; + ptr += len; + wsize -= len; + continue; + } else { + rc = EIO; + break; } -#else - while (wsize > 0) { - size_t w2; - ssize_t wres; - if (wsize > MAX_WRITE) - w2 = MAX_WRITE; - else - w2 = wsize; - wres = write(fd, ptr, w2); - rc = wres == (ssize_t)w2 ? MDB_SUCCESS : wres < 0 ? ErrCode() : EIO; - if (rc) break; - wsize -= wres; - ptr += wres; } -#endif leave: mdb_txn_abort(txn); @@ -7659,7 +7694,10 @@ mdb_env_info(MDB_env *env, MDB_envinfo *arg) arg->me_mapaddr = (env->me_flags & MDB_FIXEDMAP) ? env->me_map : 0; arg->me_mapsize = env->me_mapsize; arg->me_maxreaders = env->me_maxreaders; - arg->me_numreaders = env->me_numreaders; + /* me_numreaders may be zero if this process never used any readers. Use + * the shared numreader count if it exists. + */ + arg->me_numreaders = env->me_txns ? env->me_txns->mti_numreaders : env->me_numreaders; arg->me_last_pgno = env->me_metas[toggle]->mm_last_pg; arg->me_last_txnid = env->me_metas[toggle]->mm_txnid; return MDB_SUCCESS; @@ -8055,7 +8093,7 @@ static int mdb_pid_insert(pid_t *ids, pid_t pid) return -1; } } - + if( val > 0 ) { ++cursor; } diff --git a/c_src/lmdb_nif.c b/c_src/lmdb_nif.c index 7fab239..f276040 100644 --- a/c_src/lmdb_nif.c +++ b/c_src/lmdb_nif.c @@ -36,6 +36,7 @@ #include "common.h" #include "async_nif.h" +#include "queue.h" #include "lmdb.h" @@ -43,6 +44,7 @@ static ErlNifResourceType *lmdb_RESOURCE; struct lmdb { MDB_env *env; MDB_dbi dbi; + STAILQ_ENTRY(lmdb) entries; }; static ErlNifResourceType *lmdb_txn_RESOURCE; @@ -55,10 +57,9 @@ struct lmdb_cursor { MDB_cursor *cursor; }; -KHASH_MAP_INIT_PTR(envs, struct lmdb_env*); struct lmdb_priv_data { void *async_nif_priv; // Note: must be first element in struct - khash_t(envs) *envs; // TODO: could just be a list + STAILQ_HEAD(envs, lmdb) envs; ErlNifMutex *envs_mutex; }; @@ -66,27 +67,34 @@ struct lmdb_priv_data { ASYNC_NIF_INIT(lmdb); /* Atoms (initialized in on_load) */ -static ERL_NIF_TERM ATOM_ERROR; -static ERL_NIF_TERM ATOM_OK; -static ERL_NIF_TERM ATOM_NOT_FOUND; -static ERL_NIF_TERM ATOM_EXISTS; -static ERL_NIF_TERM ATOM_KEYEXIST; -static ERL_NIF_TERM ATOM_NOTFOUND; -static ERL_NIF_TERM ATOM_PAGE_NOTFOUND; +static ERL_NIF_TERM ATOM_BAD_RSLOT; +static ERL_NIF_TERM ATOM_BRANCH_PAGES; static ERL_NIF_TERM ATOM_CORRUPTED; -static ERL_NIF_TERM ATOM_PANIC; -static ERL_NIF_TERM ATOM_VERSION_MISMATCH; -static ERL_NIF_TERM ATOM_KEYEXIST; -static ERL_NIF_TERM ATOM_MAP_FULL; +static ERL_NIF_TERM ATOM_CURSOR_FULL; static ERL_NIF_TERM ATOM_DBS_FULL; +static ERL_NIF_TERM ATOM_DEPTH; +static ERL_NIF_TERM ATOM_ENTRIES; +static ERL_NIF_TERM ATOM_ERROR; +static ERL_NIF_TERM ATOM_EXISTS; +static ERL_NIF_TERM ATOM_INCOMPATIBLE; +static ERL_NIF_TERM ATOM_KEYEXIST; +static ERL_NIF_TERM ATOM_KEYEXIST; +static ERL_NIF_TERM ATOM_LEAF_PAGES; +static ERL_NIF_TERM ATOM_MAP_FULL; +static ERL_NIF_TERM ATOM_MAP_RESIZED; +static ERL_NIF_TERM ATOM_NOTFOUND; +static ERL_NIF_TERM ATOM_NOT_FOUND; +static ERL_NIF_TERM ATOM_OK; +static ERL_NIF_TERM ATOM_OVERFLOW_PAGES; +static ERL_NIF_TERM ATOM_PAGE_FULL; +static ERL_NIF_TERM ATOM_PAGE_NOTFOUND; +static ERL_NIF_TERM ATOM_PANIC; +static ERL_NIF_TERM ATOM_PSIZE; static ERL_NIF_TERM ATOM_READERS_FULL; static ERL_NIF_TERM ATOM_TLS_FULL; +static ERL_NIF_TERM ATOM_TRUE; static ERL_NIF_TERM ATOM_TXN_FULL; -static ERL_NIF_TERM ATOM_CURSOR_FULL; -static ERL_NIF_TERM ATOM_PAGE_FULL; -static ERL_NIF_TERM ATOM_MAP_RESIZED; -static ERL_NIF_TERM ATOM_INCOMPATIBLE; -static ERL_NIF_TERM ATOM_BAD_RSLOT; +static ERL_NIF_TERM ATOM_VERSION_MISMATCH; #define CHECK(expr, label) \ if (MDB_SUCCESS != (ret = (expr))) { \ @@ -191,16 +199,16 @@ __strerror_term(ErlNifEnv* env, int err) * argv[5] maxdbs */ ASYNC_NIF_DECL( - lmdb_env_open_nif, + lmdb_env_open, { // struct char dirname[MAXPATHLEN]; unsigned int flags; - mdb_mod_t mode; + mdb_mode_t mode; size_t mapsize; unsigned int maxreaders; MDB_dbi maxdbs; - struct wterl_priv_data *priv; + struct lmdb_priv_data *priv; }, { // pre @@ -215,54 +223,46 @@ ASYNC_NIF_DECL( } if (enif_get_string(env, argv[0], args->dirname, MAXPATHLEN, ERL_NIF_LATIN1) <= 0) ASYNC_NIF_RETURN_BADARG(); - enif_get_uint32(env, argv[1], &(args->flags)); - enif_get_int32(env, argv[2], &(args->mode)); + enif_get_uint(env, argv[1], &(args->flags)); + enif_get_uint(env, argv[2], &(args->mode)); #if (__SIZEOF_SIZE_T__ == 8) - enif_get_int64(env, argv[3], &(args->mapsize)); -#else if (__SIZEOF_SIZE_T__ == 4) - enif_get_int32(env, argv[3], &(args->mapsize)); + enif_get_uint64(env, argv[3], &(args->mapsize)); +#elif (__SIZEOF_SIZE_T__ == 4) + enif_get_int(env, argv[3], &(args->mapsize)); #endif - enif_get_int32(env, argv[4], &(args->maxreaders)); - enif_get_int32(env, argv[5], &(args->maxdbs)); + enif_get_uint(env, argv[4], &(args->maxreaders)); + enif_get_uint(env, argv[5], &(args->maxdbs)); args->priv = (struct lmdb_priv_data *)enif_priv_data(env); }, { // work int ret; ERL_NIF_TERM err; - struct lmdb_env *handle; - khash_t(envs) *h; - khiter_t itr; - int itr_status; + struct lmdb *handle; if ((handle = enif_alloc_resource(lmdb_RESOURCE, sizeof(struct lmdb))) == NULL) FAIL_ERR(ENOMEM, err2); - STAT_INIT(handle, lmdb_env_get); - STAT_INIT(handle, lmdb_env_put); - STAT_INIT(handle, lmdb_env_upd); - STAT_INIT(handle, lmdb_env_del); - CHECK(mdb_env_create(&(handle->env)), err1); if (mdb_env_set_mapsize(handle->env, args->mapsize)) { - err = enif_make_badarg(handle->env); + err = enif_make_badarg(env); goto err1; } if (mdb_env_set_maxreaders(handle->env, args->maxreaders)) { - err = enif_make_badarg(handle->env); + err = enif_make_badarg(env); goto err1; } if (mdb_env_set_maxdbs(handle->env, args->maxdbs)) { - err = enif_make_badarg(handle->env); + err = enif_make_badarg(env); goto err1; } - h = args->priv->envs; - itr = kh_put(envs, h, handle, &itr_status); - kh_value(h, itr) = handle; + enif_mutex_lock(args->priv->envs_mutex); + STAILQ_INSERT_TAIL(&args->priv->envs, handle, entries); + enif_mutex_unlock(args->priv->envs_mutex); ERL_NIF_TERM term = enif_make_resource(env, handle); ASYNC_NIF_REPLY(enif_make_tuple(env, 2, ATOM_OK, term)); @@ -287,17 +287,17 @@ ASYNC_NIF_DECL( * argv[1] destination path */ ASYNC_NIF_DECL( - lmdb_copy_nif, + lmdb_copy, { // struct - struct lmdb_env *handle; + struct lmdb *handle; char dirname[MAXPATHLEN]; }, { // pre if (!(argc == 2 && enif_get_resource(env, argv[0], lmdb_RESOURCE, (void**)&args->handle) && - enif_is_list(env, arg[1])) { + enif_is_list(env, argv[1]))) { ASYNC_NIF_RETURN_BADARG(); } if (enif_get_string(env, argv[1], args->dirname, MAXPATHLEN, @@ -312,7 +312,7 @@ ASYNC_NIF_DECL( ERL_NIF_TERM err; int ret; - CHECK(mdb_env_copy(args->handle->env, args->dirname, err)); + CHECK(mdb_env_copy(args->handle->env, args->dirname), err); ASYNC_NIF_REPLY(ATOM_OK); return; @@ -323,15 +323,15 @@ ASYNC_NIF_DECL( { // post enif_release_resource((void*)args->handle); - }). + }); /** - * ?? + * Return statistics about the MDB environment. * - * argv[0] ?? + * argv[0] an environment handle */ ASYNC_NIF_DECL( - lmdb_??_nif, + lmdb_stat, { // struct struct lmdb *handle; @@ -349,20 +349,77 @@ ASYNC_NIF_DECL( { // work ERL_NIF_TERM err; + ERL_NIF_TERM term; + MDB_stat stats; int ret; - CHECK(??, err); + CHECK(mdb_env_stat(args->handle->env, &stats), err1); + + term = enif_make_tuple(env, 6, + enif_make_tuple(env, 2, ATOM_PSIZE, enif_make_uint(env, stats.ms_psize)), + enif_make_tuple(env, 2, ATOM_DEPTH, enif_make_uint(env, stats.ms_depth)), + enif_make_tuple(env, 2, ATOM_BRANCH_PAGES, enif_make_uint(env, stats.ms_branch_pages)), + enif_make_tuple(env, 2, ATOM_LEAF_PAGES, enif_make_uint(env, stats.ms_leaf_pages)), + enif_make_tuple(env, 2, ATOM_OVERFLOW_PAGES, enif_make_uint(env, stats.ms_overflow_pages)), + enif_make_tuple(env, 2, ATOM_ENTRIES, enif_make_uint(env, stats.ms_entries))); + ASYNC_NIF_REPLY(enif_make_tuple(env, 2, ATOM_OK, term)); return; - err: + err1: ASYNC_NIF_REPLY(err); return; }, { // post enif_release_resource((void*)args->handle); - }). + }); + +/** + * Flush the data buffers to disk. + * + * argv[0] an environment handle + * argv[1] if true, force a synchronous flush. Otherwise if the environment + * has the ?MDB_NOSYNC flag set the flushes will be omitted, and + * with ?MDB_MAPASYNC they will be asynchronous. + */ +ASYNC_NIF_DECL( + lmdb_sync, + { // struct + + struct lmdb *handle; + int force; + }, + { // pre + + if (!(argc == 2 && + enif_get_resource(env, argv[0], lmdb_RESOURCE, (void**)&args->handle) && + enif_is_atom(env, argv[1]))) { + ASYNC_NIF_RETURN_BADARG(); + } + + args->force = enif_is_identical(ATOM_TRUE, argv[1]) ? 1 : 0; + if (!args->handle->env) + ASYNC_NIF_RETURN_BADARG(); + enif_keep_resource((void*)args->handle); + }, + { // work + + ERL_NIF_TERM err; + int ret; + + CHECK(mdb_env_sync(args->handle->env, args->force), err1); + ASYNC_NIF_REPLY(enif_make_tuple(env, 1, ATOM_OK)); + return; + + err1: + ASYNC_NIF_REPLY(err); + return; + }, + { // post + + enif_release_resource((void*)args->handle); + }); /** * Opens a MDB database. @@ -825,7 +882,6 @@ lmdb_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) { UNUSED(load_info); int err; - char msg[1024]; ErlNifResourceFlags flags; struct lmdb_priv_data *priv; @@ -835,21 +891,20 @@ lmdb_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) FAIL_ERR(ENOMEM, err1); memset(priv, 0, sizeof(struct lmdb_priv_data)); priv->envs_mutex = enif_mutex_create(NULL); - priv->envs = kh_init(envs); - if (!priv->envs) - FAIL_ERR(ENOMEM, err2); + STAILQ_INIT(&priv->envs); /* Note: !!! the first element of our priv_data struct *must* be the pointer to the async_nif's private data which we set here. */ ASYNC_NIF_LOAD(lmdb, priv->async_nif_priv); if (!priv) - FAIL_ERR(ENOMEM, err3); + FAIL_ERR(ENOMEM, err2); *priv_data = priv; ATOM_ERROR = enif_make_atom(env, "error"); ATOM_OK = enif_make_atom(env, "ok"); ATOM_NOT_FOUND = enif_make_atom(env, "not_found"); ATOM_EXISTS = enif_make_atom(env, "exists"); + ATOM_TRUE = enif_make_atom(env, "true"); ATOM_KEYEXIST = enif_make_atom(env, "key_exist"); ATOM_NOTFOUND = enif_make_atom(env, "notfound"); @@ -867,18 +922,25 @@ lmdb_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) ATOM_INCOMPATIBLE = enif_make_atom(env, "incompatible"); ATOM_BAD_RSLOT = enif_make_atom(env, "bad_rslot"); + ATOM_PSIZE = enif_make_atom(env, "psize"); + ATOM_DEPTH = enif_make_atom(env, "depth"); + ATOM_BRANCH_PAGES = enif_make_atom(env, "branch_pages"); + ATOM_LEAF_PAGES = enif_make_atom(env, "leaf_pages"); + ATOM_OVERFLOW_PAGES = enif_make_atom(env, "overflow_pages"); + ATOM_ENTRIES = enif_make_atom(env, "entries"); + + lmdb_RESOURCE = enif_open_resource_type(env, NULL, "lmdb_resource", NULL, flags, NULL); fprintf(stderr, "NIF on_load complete (lmdb version: %s)", MDB_VERSION_STRING); fflush(stderr); return (0); -err3: - kh_destroy(envs, priv->envs); + err2: - enif_mutex_destroy(priv->conns_mutex); + enif_mutex_destroy(priv->envs_mutex); enif_free(priv); err1: - return (ENOMEM); + return (err); } /** @@ -916,24 +978,13 @@ static void lmdb_unload(ErlNifEnv* env, void* priv_data) { struct lmdb_priv_data *priv = (struct lmdb_priv_data *)priv_data; - khash_t(envs) *h; - khiter_t itr_envs; - struct lmdb_env *env; + struct lmdb *handle; enif_mutex_lock(priv->envs_mutex); - h = priv->envs; - for (itr_envs = kh_begin(h); itr_envs != kh_end(h); ++itr_envs) { - if (kh_exist(h, itr_envs)) { - env = kh_val(h, itr_envs); - if (env) { - mdb_env_close(env); - kh_del(envs, h, itr_envs); - enif_free(env); - kh_value(h, itr_envs) = NULL; - } - } + STAILQ_FOREACH(handle, &priv->envs, entries) { + mdb_env_close(handle->env); + enif_free(handle); } - kh_destroy(envs, h); ASYNC_NIF_UNLOAD(lmdb, env, priv->async_nif_priv); enif_mutex_unlock(priv->envs_mutex); enif_mutex_destroy(priv->envs_mutex); diff --git a/rebar.config b/rebar.config index 5b96b0a..fcda477 100644 --- a/rebar.config +++ b/rebar.config @@ -6,6 +6,7 @@ {cover_enabled, true}. {erl_opts, [%{d,'DEBUG',true}, + %native, {hipe, [o3,verbose]}, inline, {inline_size, 1024}, debug_info, warn_unused_vars, warn_export_all, diff --git a/tools/lmdb.config b/tools/lmdb.config index ef63aa7..2ee5d1e 100644 --- a/tools/lmdb.config +++ b/tools/lmdb.config @@ -27,11 +27,18 @@ {duration, 480}. {concurrent, 32}. {driver, basho_bench_driver_lmdb}. +{report_interval, 1}. % sec, default was 10 +{pb_timeout_general, 1000}. % ms, default was 60 sec +%{pb_timeout_read, ?}. +%{pb_timeout_write, ?}. +%{pb_timeout_listkeys, ?}. +%{pb_timeout_mapreduce, ?}. {key_generator, {int_to_bin_littleendian,{uniform_int, 5000000000}}}. +{key_generator, {int_to_bin_littleendian,{pareto_int, 5000000000}}}. {value_generator, {highly_compressible_bin, 2048}}. %{value_generator, {fixed_bin, 1024}}. -{operations, [{get, 25}, {put, 70}, {delete, 5}]}. -%{operations, [{put, 1}]}. +%{operations, [{get, 25}, {put, 70}, {delete, 5}]}. +{operations, [{put, 1}]}. {code_paths, ["../lmdb"]}. {lmdb_dir, "/home/gburd/ws/basho_bench/data"}.