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
407407err1 :
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
588595err1 :
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 );
685695err2 :
686696 mdb_txn_abort (txn );
687- return enif_raise_exception (env , err );
697+ err3 :
698+ return err ;
688699}
689700
690701static 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" );
0 commit comments