@@ -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+
555644static 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
678769ERL_NIF_INIT (elmdb , nif_funcs , load , NULL , upgrade , unload )
0 commit comments