diff --git a/c_src/wterl.c b/c_src/wterl.c index 076aa03..90ee13d 100644 --- a/c_src/wterl.c +++ b/c_src/wterl.c @@ -44,84 +44,12 @@ typedef struct { WT_CURSOR* cursor; } WterlCursorHandle; -typedef char Uri[128]; // object names +typedef char Uri[128]; // object names // Atoms (initialized in on_load) static ERL_NIF_TERM ATOM_ERROR; static ERL_NIF_TERM ATOM_OK; -typedef ERL_NIF_TERM (*CursorRetFun)(ErlNifEnv* env, WT_CURSOR* cursor, int rc); - -// Prototypes -static ERL_NIF_TERM wterl_conn_close(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_conn_open(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_cursor_close(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_cursor_insert(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_cursor_key_ret(ErlNifEnv* env, WT_CURSOR *cursor, int rc); -static ERL_NIF_TERM wterl_cursor_kv_ret(ErlNifEnv* env, WT_CURSOR *cursor, int rc); -static ERL_NIF_TERM wterl_cursor_next(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_cursor_next_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_cursor_next_value(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_cursor_np_worker(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[], - CursorRetFun cursor_ret_fun, int next); -static ERL_NIF_TERM wterl_cursor_open(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_cursor_prev(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_cursor_prev_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_cursor_prev_value(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_cursor_remove(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_cursor_reset(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_cursor_search(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_cursor_search_near(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_cursor_search_worker(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[], int near); -static ERL_NIF_TERM wterl_cursor_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_cursor_value_ret(ErlNifEnv* env, WT_CURSOR *cursor, int rc); -static ERL_NIF_TERM wterl_session_checkpoint(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_session_close(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_session_create(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_session_delete(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_session_drop(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_session_get(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_session_open(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_session_put(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_session_rename(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_session_salvage(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_session_truncate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_session_upgrade(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM wterl_session_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); - -static ErlNifFunc nif_funcs[] = -{ - {"conn_close", 1, wterl_conn_close}, - {"conn_open", 2, wterl_conn_open}, - {"cursor_close", 1, wterl_cursor_close}, - {"cursor_insert", 3, wterl_cursor_insert}, - {"cursor_next", 1, wterl_cursor_next}, - {"cursor_next_key", 1, wterl_cursor_next_key}, - {"cursor_next_value", 1, wterl_cursor_next_value}, - {"cursor_open", 2, wterl_cursor_open}, - {"cursor_prev", 1, wterl_cursor_prev}, - {"cursor_prev_key", 1, wterl_cursor_prev_key}, - {"cursor_prev_value", 1, wterl_cursor_prev_value}, - {"cursor_remove", 2, wterl_cursor_remove}, - {"cursor_reset", 1, wterl_cursor_reset}, - {"cursor_search", 2, wterl_cursor_search}, - {"cursor_search_near", 2, wterl_cursor_search_near}, - {"cursor_update", 3, wterl_cursor_update}, - {"session_checkpoint", 2, wterl_session_checkpoint}, - {"session_close", 1, wterl_session_close}, - {"session_create", 3, wterl_session_create}, - {"session_delete", 3, wterl_session_delete}, - {"session_drop", 3, wterl_session_drop}, - {"session_get", 3, wterl_session_get}, - {"session_open", 2, wterl_session_open}, - {"session_put", 4, wterl_session_put}, - {"session_rename", 4, wterl_session_rename}, - {"session_salvage", 3, wterl_session_salvage}, - {"session_truncate", 3, wterl_session_truncate}, - {"session_upgrade", 3, wterl_session_upgrade}, - {"session_verify", 3, wterl_session_verify}, -}; - static inline ERL_NIF_TERM wterl_strerror(ErlNifEnv* env, int rc) { return rc == WT_NOTFOUND ? @@ -148,7 +76,7 @@ ASYNC_NIF_DECL( }, { // work - WT_CONNECTION* conn; + WT_CONNECTION* conn; ErlNifBinary config; if (!enif_inspect_binary(env, args->config, &config)) { ASYNC_NIF_REPLY(enif_make_badarg(env)); @@ -156,18 +84,18 @@ ASYNC_NIF_DECL( } int rc = wiredtiger_open(args->homedir, NULL, (const char*)config.data, &conn); - if (rc == 0) - { - WterlConnHandle* conn_handle = enif_alloc_resource(wterl_conn_RESOURCE, sizeof(WterlConnHandle)); - conn_handle->conn = conn; - ERL_NIF_TERM result = enif_make_resource(env, conn_handle); - enif_release_resource(conn_handle); + if (rc == 0) + { + WterlConnHandle* conn_handle = enif_alloc_resource(wterl_conn_RESOURCE, sizeof(WterlConnHandle)); + conn_handle->conn = conn; + ERL_NIF_TERM result = enif_make_resource(env, conn_handle); + enif_release_resource(conn_handle); ASYNC_NIF_REPLY(enif_make_tuple2(env, ATOM_OK, result)); - } - else - { + } + else + { ASYNC_NIF_REPLY(wterl_strerror(env, rc)); - } + } }, { // post @@ -211,7 +139,7 @@ ASYNC_NIF_DECL( enif_get_resource(env, argv[0], wterl_conn_RESOURCE, (void**)&args->conn_handle) && enif_is_binary(env, argv[1]))) { ASYNC_NIF_RETURN_BADARG(); - } + } args->config = enif_make_copy(ASYNC_NIF_WORK_ENV, argv[1]); enif_keep_resource((void*)args->conn_handle); }, @@ -224,21 +152,21 @@ ASYNC_NIF_DECL( ASYNC_NIF_REPLY(enif_make_badarg(env)); return; } - int rc = conn->open_session(conn, NULL, (const char *)config.data, &session); - if (rc == 0) - { - WterlSessionHandle* session_handle = - enif_alloc_resource(wterl_session_RESOURCE, sizeof(WterlSessionHandle)); - session_handle->session = session; - ERL_NIF_TERM result = enif_make_resource(env, session_handle); + int rc = conn->open_session(conn, NULL, (const char*)config.data, &session); + if (rc == 0) + { + WterlSessionHandle* session_handle = + enif_alloc_resource(wterl_session_RESOURCE, sizeof(WterlSessionHandle)); + session_handle->session = session; + ERL_NIF_TERM result = enif_make_resource(env, session_handle); enif_keep_resource(args->conn_handle); - enif_release_resource(session_handle); + enif_release_resource(session_handle); ASYNC_NIF_REPLY(enif_make_tuple2(env, ATOM_OK, result)); - } - else - { + } + else + { ASYNC_NIF_REPLY(wterl_strerror(env, rc)); - } + } }, { // post @@ -296,7 +224,7 @@ ASYNC_NIF_DECL( if (!enif_inspect_binary(env, args->config, &config)) { ASYNC_NIF_REPLY(enif_make_badarg(env)); return; -} + } int rc = session->create(session, args->uri, (const char*)config.data); ASYNC_NIF_REPLY(rc == 0 ? ATOM_OK : wterl_strerror(env, rc)); }, @@ -320,7 +248,7 @@ ASYNC_NIF_DECL( enif_get_string(env, argv[1], args->uri, sizeof args->uri, ERL_NIF_LATIN1) && enif_is_binary(env, argv[2]))) { ASYNC_NIF_RETURN_BADARG(); -} + } args->config = enif_make_copy(ASYNC_NIF_WORK_ENV, argv[2]); enif_keep_resource((void*)args->session_handle); }, @@ -331,14 +259,19 @@ ASYNC_NIF_DECL( if (!enif_inspect_binary(env, args->config, &config)) { ASYNC_NIF_REPLY(enif_make_badarg(env)); return; -} + } int rc = session->drop(session, args->uri, (const char*)config.data); ASYNC_NIF_REPLY(rc == 0 ? ATOM_OK : wterl_strerror(env, rc)); }, { // post -static ERL_NIF_TERM wterl_session_rename(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ + enif_release_resource((void*)args->session_handle); + }); + +ASYNC_NIF_DECL( + wterl_session_rename, + { // struct + WterlSessionHandle* session_handle; ERL_NIF_TERM config; Uri oldname; @@ -359,11 +292,11 @@ static ERL_NIF_TERM wterl_session_rename(ErlNifEnv* env, int argc, const ERL_NIF { // work WT_SESSION* session = args->session_handle->session; - ErlNifBinary config; + ErlNifBinary config; if (!enif_inspect_binary(env, args->config, &config)) { ASYNC_NIF_REPLY(enif_make_badarg(env)); return; - } + } int rc = session->rename(session, args->oldname, args->newname, (const char*)config.data); ASYNC_NIF_REPLY(rc == 0 ? ATOM_OK : wterl_strerror(env, rc)); }, @@ -398,199 +331,400 @@ ASYNC_NIF_DECL( if (!enif_inspect_binary(env, args->config, &config)) { ASYNC_NIF_REPLY(enif_make_badarg(env)); return; -} + } + int rc = session->salvage(session, args->uri, (const char*)config.data); + ASYNC_NIF_REPLY(rc == 0 ? ATOM_OK : wterl_strerror(env, rc)); + }, + { // post -static ERL_NIF_TERM wterl_session_salvage(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ - return wterl_session_worker(env, argc, argv, WTERL_OP_SALVAGE); -} + enif_release_resource((void*)args->session_handle); + }); + +ASYNC_NIF_DECL( + wterl_session_checkpoint, + { // struct -static ERL_NIF_TERM wterl_session_checkpoint(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ WterlSessionHandle* session_handle; + ERL_NIF_TERM config; + }, + { // pre + + if (!(argc == 2 && + enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&args->session_handle) && + enif_is_binary(env, argv[1]))) { + ASYNC_NIF_RETURN_BADARG(); + } + args->config = enif_make_copy(ASYNC_NIF_WORK_ENV, argv[1]); + enif_keep_resource((void*)args->session_handle); + }, + { // work + + WT_SESSION* session = args->session_handle->session; ErlNifBinary config; - if (enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&session_handle) && - enif_inspect_binary(env, argv[1], &config)) - { - WT_SESSION* session = session_handle->session; - int rc = session->checkpoint(session, (const char*)config.data); - return rc == 0 ? ATOM_OK : wterl_strerror(env, rc); + if (!enif_inspect_binary(env, args->config, &config)) { + ASYNC_NIF_REPLY(enif_make_badarg(env)); + return; } - return enif_make_badarg(env); -} + int rc = session->checkpoint(session, (const char*)config.data); + ASYNC_NIF_REPLY(rc == 0 ? ATOM_OK : wterl_strerror(env, rc)); + }, + { // post -static ERL_NIF_TERM wterl_session_truncate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ - return wterl_session_worker(env, argc, argv, WTERL_OP_TRUNCATE); -} + enif_release_resource((void*)args->session_handle); + }); -static ERL_NIF_TERM wterl_session_upgrade(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ - return wterl_session_worker(env, argc, argv, WTERL_OP_UPGRADE); -} +ASYNC_NIF_DECL( + wterl_session_truncate, + { // struct -static ERL_NIF_TERM wterl_session_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ - return wterl_session_worker(env, argc, argv, WTERL_OP_VERIFY); -} - -static ERL_NIF_TERM wterl_session_delete(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ WterlSessionHandle* session_handle; - if (enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&session_handle)) - { - Uri uri; - ErlNifBinary key; - if (enif_get_string(env, argv[1], uri, sizeof uri, ERL_NIF_LATIN1) && - enif_inspect_binary(env, argv[2], &key)) - { - WT_SESSION* session = session_handle->session; - WT_CURSOR* cursor; - int rc = session->open_cursor(session, uri, NULL, "raw", &cursor); - if (rc != 0) - { - return wterl_strerror(env, rc); - } - WT_ITEM raw_key; - raw_key.data = key.data; - raw_key.size = key.size; - cursor->set_key(cursor, &raw_key); - rc = cursor->remove(cursor); - cursor->close(cursor); - return rc == 0 ? ATOM_OK : wterl_strerror(env, rc); - } - } - return enif_make_badarg(env); -} + Uri uri; + ERL_NIF_TERM config; + }, + { // pre + + if (!(argc == 3 && + enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&args->session_handle) && + enif_get_string(env, argv[1], args->uri, sizeof args->uri, ERL_NIF_LATIN1) && + enif_is_binary(env, argv[2]))) { + ASYNC_NIF_RETURN_BADARG(); + } + args->config = enif_make_copy(ASYNC_NIF_WORK_ENV, argv[2]); + enif_keep_resource((void*)args->session_handle); + }, + { // work + + // Ignore the cursor start/stop form of truncation for now, + // support only the full file truncation. + WT_SESSION* session = args->session_handle->session; + ErlNifBinary config; + if (!enif_inspect_binary(env, args->config, &config)) { + ASYNC_NIF_REPLY(enif_make_badarg(env)); + return; + } + int rc = session->truncate(session, args->uri, NULL, NULL, (const char*)config.data); + ASYNC_NIF_REPLY(rc == 0 ? ATOM_OK : wterl_strerror(env, rc)); + }, + { // post + + enif_release_resource((void*)args->session_handle); + }); + +ASYNC_NIF_DECL( + wterl_session_upgrade, + { // struct -static ERL_NIF_TERM wterl_session_get(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ WterlSessionHandle* session_handle; - if (enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&session_handle)) - { - Uri uri; - ErlNifBinary key; - if (enif_get_string(env, argv[1], uri, sizeof uri, ERL_NIF_LATIN1) && - enif_inspect_binary(env, argv[2], &key)) - { - WT_SESSION* session = session_handle->session; - WT_CURSOR* cursor; - int rc = session->open_cursor(session, uri, NULL, "overwrite,raw", &cursor); - if (rc != 0) - { - return wterl_strerror(env, rc); - } - WT_ITEM raw_key, raw_value; - raw_key.data = key.data; - raw_key.size = key.size; - cursor->set_key(cursor, &raw_key); - rc = cursor->search(cursor); - if (rc == 0) - { - rc = cursor->get_value(cursor, &raw_value); - if (rc == 0) - { - ERL_NIF_TERM value; - unsigned char* bin = enif_make_new_binary(env, raw_value.size, &value); - memcpy(bin, raw_value.data, raw_value.size); - cursor->close(cursor); - return enif_make_tuple2(env, ATOM_OK, value); - } - } - cursor->close(cursor); - return wterl_strerror(env, rc); - } - } - return enif_make_badarg(env); -} + Uri uri; + ERL_NIF_TERM config; + }, + { // pre + + if (!(argc == 3 && + enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&args->session_handle) && + enif_get_string(env, argv[1], args->uri, sizeof args->uri, ERL_NIF_LATIN1) && + enif_is_binary(env, argv[2]))) { + ASYNC_NIF_RETURN_BADARG(); + } + args->config = enif_make_copy(ASYNC_NIF_WORK_ENV, argv[2]); + enif_keep_resource((void*)args->session_handle); + }, + { // work + + WT_SESSION* session = args->session_handle->session; + ErlNifBinary config; + if (!enif_inspect_binary(env, args->config, &config)) { + ASYNC_NIF_REPLY(enif_make_badarg(env)); + return; + } + int rc = session->upgrade(session, args->uri, (const char*)config.data); + ASYNC_NIF_REPLY(rc == 0 ? ATOM_OK : wterl_strerror(env, rc)); + }, + { // post + + enif_release_resource((void*)args->session_handle); + }); + +ASYNC_NIF_DECL( + wterl_session_verify, + { // struct -static ERL_NIF_TERM wterl_session_put(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ WterlSessionHandle* session_handle; - if (enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&session_handle)) - { - Uri uri; - ErlNifBinary key, value; - if (enif_get_string(env, argv[1], uri, sizeof uri, ERL_NIF_LATIN1) && - enif_inspect_binary(env, argv[2], &key) && - enif_inspect_binary(env, argv[3], &value)) - { - WT_SESSION* session = session_handle->session; - WT_CURSOR* cursor; - int rc = session->open_cursor(session, uri, NULL, "overwrite,raw", &cursor); - if (rc != 0) - { - return wterl_strerror(env, rc); - } - WT_ITEM raw_key, raw_value; - raw_key.data = key.data; - raw_key.size = key.size; - cursor->set_key(cursor, &raw_key); - raw_value.data = value.data; - raw_value.size = value.size; - cursor->set_value(cursor, &raw_value); - rc = cursor->insert(cursor); - cursor->close(cursor); - return rc == 0 ? ATOM_OK : wterl_strerror(env, rc); - } - } - return enif_make_badarg(env); -} + Uri uri; + ERL_NIF_TERM config; + }, + { // pre + + if (!(argc == 3 && + enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&args->session_handle) && + enif_get_string(env, argv[1], args->uri, sizeof args->uri, ERL_NIF_LATIN1) && + enif_is_binary(env, argv[2]))) { + ASYNC_NIF_RETURN_BADARG(); + } + args->config = enif_make_copy(ASYNC_NIF_WORK_ENV, argv[2]); + enif_keep_resource((void*)args->session_handle); + }, + { // work + + WT_SESSION* session = args->session_handle->session; + ErlNifBinary config; + if (!enif_inspect_binary(env, args->config, &config)) { + ASYNC_NIF_REPLY(enif_make_badarg(env)); + return; + } + int rc = session->verify(session, args->uri, (const char*)config.data); + ASYNC_NIF_REPLY(rc == 0 ? ATOM_OK : wterl_strerror(env, rc)); + }, + { // post + + enif_release_resource((void*)args->session_handle); + }); + +ASYNC_NIF_DECL( + wterl_session_delete, + { // struct -static ERL_NIF_TERM wterl_cursor_open(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ WterlSessionHandle* session_handle; - if (enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&session_handle)) - { - WT_CURSOR* cursor; - Uri uri; - if (enif_get_string(env, argv[1], uri, sizeof uri, ERL_NIF_LATIN1)) - { - WT_SESSION* session = session_handle->session; - int rc = session->open_cursor(session, uri, NULL, "overwrite,raw", &cursor); - if (rc == 0) - { - WterlCursorHandle* cursor_handle = - enif_alloc_resource(wterl_cursor_RESOURCE, sizeof(WterlCursorHandle)); - cursor_handle->cursor = cursor; - ERL_NIF_TERM result = enif_make_resource(env, cursor_handle); - enif_keep_resource(session_handle); - enif_release_resource(cursor_handle); - return enif_make_tuple2(env, ATOM_OK, result); - } - else - { - return wterl_strerror(env, rc); - } - } - } - return enif_make_badarg(env); -} + Uri uri; + ERL_NIF_TERM key; + }, + { // pre + + if (!(argc == 3 && + enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&args->session_handle) && + enif_get_string(env, argv[1], args->uri, sizeof args->uri, ERL_NIF_LATIN1) && + enif_is_binary(env, argv[2]))) { + ASYNC_NIF_RETURN_BADARG(); + } + args->key = enif_make_copy(ASYNC_NIF_WORK_ENV, argv[2]); + enif_keep_resource((void*)args->session_handle); + }, + { // work + + WT_SESSION* session = args->session_handle->session; + ErlNifBinary key; + if (!enif_inspect_binary(env, args->key, &key)) { + ASYNC_NIF_REPLY(enif_make_badarg(env)); + return; + } + WT_CURSOR* cursor; + int rc = session->open_cursor(session, args->uri, NULL, "raw", &cursor); + if (rc != 0) + { + ASYNC_NIF_REPLY(wterl_strerror(env, rc)); + return; + } + WT_ITEM raw_key; + raw_key.data = key.data; + raw_key.size = key.size; + cursor->set_key(cursor, &raw_key); + rc = cursor->remove(cursor); + cursor->close(cursor); + ASYNC_NIF_REPLY(rc == 0 ? ATOM_OK : wterl_strerror(env, rc)); + }, + { // post + + enif_release_resource((void*)args->session_handle); + }); + +ASYNC_NIF_DECL( + wterl_session_get, + { // struct + + WterlSessionHandle* session_handle; + Uri uri; + ERL_NIF_TERM key; + }, + { // pre + + if (!(argc == 3 && + enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&args->session_handle) && + enif_get_string(env, argv[1], args->uri, sizeof args->uri, ERL_NIF_LATIN1) && + enif_is_binary(env, argv[2]))) { + ASYNC_NIF_RETURN_BADARG(); + } + args->key = enif_make_copy(ASYNC_NIF_WORK_ENV, argv[2]); + enif_keep_resource((void*)args->session_handle); + }, + { // work + + WT_SESSION* session = args->session_handle->session; + ErlNifBinary key; + if (!enif_inspect_binary(env, args->key, &key)) { + ASYNC_NIF_REPLY(enif_make_badarg(env)); + return; + } + WT_CURSOR* cursor; + int rc = session->open_cursor(session, args->uri, NULL, "overwrite,raw", &cursor); + if (rc != 0) + { + ASYNC_NIF_REPLY(wterl_strerror(env, rc)); + return; + } + WT_ITEM raw_key; + WT_ITEM raw_value; + raw_key.data = key.data; + raw_key.size = key.size; + cursor->set_key(cursor, &raw_key); + rc = cursor->search(cursor); + if (rc == 0) + { + rc = cursor->get_value(cursor, &raw_value); + if (rc == 0) + { + ERL_NIF_TERM value; + unsigned char* bin = enif_make_new_binary(env, raw_value.size, &value); + memcpy(bin, raw_value.data, raw_value.size); + cursor->close(cursor); + ASYNC_NIF_REPLY(enif_make_tuple2(env, ATOM_OK, value)); + return; + } + } + cursor->close(cursor); + ASYNC_NIF_REPLY(wterl_strerror(env, rc)); + }, + { // post + + enif_release_resource((void*)args->session_handle); + }); + +ASYNC_NIF_DECL( + wterl_session_put, + { // struct + + WterlSessionHandle* session_handle; + Uri uri; + ERL_NIF_TERM key; + ERL_NIF_TERM value; + }, + { // pre + + if (!(argc == 4 && + enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&args->session_handle) && + enif_get_string(env, argv[1], args->uri, sizeof args->uri, ERL_NIF_LATIN1) && + enif_is_binary(env, argv[2]) && + enif_is_binary(env, argv[3]))) { + ASYNC_NIF_RETURN_BADARG(); + } + args->key = enif_make_copy(ASYNC_NIF_WORK_ENV, argv[2]); + args->value = enif_make_copy(ASYNC_NIF_WORK_ENV, argv[3]); + enif_keep_resource((void*)args->session_handle); + }, + { // work + + WT_SESSION* session = args->session_handle->session; + ErlNifBinary key; + ErlNifBinary value; + if (!enif_inspect_binary(env, args->key, &key)) { + ASYNC_NIF_REPLY(enif_make_badarg(env)); + return; + } + if (!enif_inspect_binary(env, args->value, &value)) { + ASYNC_NIF_REPLY(enif_make_badarg(env)); + return; + } + WT_CURSOR* cursor; + int rc = session->open_cursor(session, args->uri, NULL, "overwrite,raw", &cursor); + if (rc != 0) + { + ASYNC_NIF_REPLY(wterl_strerror(env, rc)); + return; + } + WT_ITEM raw_key; + WT_ITEM raw_value; + raw_key.data = key.data; + raw_key.size = key.size; + cursor->set_key(cursor, &raw_key); + raw_value.data = value.data; + raw_value.size = value.size; + cursor->set_value(cursor, &raw_value); + rc = cursor->insert(cursor); + cursor->close(cursor); + ASYNC_NIF_REPLY(rc == 0 ? ATOM_OK : wterl_strerror(env, rc)); + }, + { // post + + enif_release_resource((void*)args->session_handle); + }); + +ASYNC_NIF_DECL( + wterl_cursor_open, + { // struct + + WterlSessionHandle* session_handle; + Uri uri; + }, + { // pre + + if (!(argc == 2 && + enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&args->session_handle) && + enif_get_string(env, argv[1], args->uri, sizeof args->uri, ERL_NIF_LATIN1))) { + ASYNC_NIF_RETURN_BADARG(); + } + enif_keep_resource((void*)args->session_handle); + }, + { // work + + WT_SESSION* session = args->session_handle->session; + WT_CURSOR* cursor; + int rc = session->open_cursor(session, args->uri, NULL, "overwrite,raw", &cursor); + if (rc == 0) + { + WterlCursorHandle* cursor_handle = + enif_alloc_resource(wterl_cursor_RESOURCE, sizeof(WterlCursorHandle)); + cursor_handle->cursor = cursor; + ERL_NIF_TERM result = enif_make_resource(env, cursor_handle); + enif_keep_resource(args->session_handle); + enif_release_resource(cursor_handle); + ASYNC_NIF_REPLY(enif_make_tuple2(env, ATOM_OK, result)); + } + else + { + ASYNC_NIF_REPLY(wterl_strerror(env, rc)); + } + }, + { // post + + enif_release_resource((void*)args->session_handle); + }); + +ASYNC_NIF_DECL( + wterl_cursor_close, + { // struct -static ERL_NIF_TERM wterl_cursor_close(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ WterlCursorHandle *cursor_handle; - if (enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&cursor_handle)) - { - WT_CURSOR* cursor = cursor_handle->cursor; - int rc = cursor->close(cursor); - return rc == 0 ? ATOM_OK : wterl_strerror(env, rc); + }, + { // pre + + if (!(argc == 1 && + enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&args->cursor_handle))) { + ASYNC_NIF_RETURN_BADARG(); } - return enif_make_badarg(env); -} + enif_keep_resource((void*)args->cursor_handle); + }, + { // work + + WT_CURSOR* cursor = args->cursor_handle->cursor; + int rc = cursor->close(cursor); + ASYNC_NIF_REPLY(rc == 0 ? ATOM_OK : wterl_strerror(env, rc)); + }, + { // post + + enif_release_resource((void*)args->cursor_handle); + }); static ERL_NIF_TERM wterl_cursor_key_ret(ErlNifEnv* env, WT_CURSOR *cursor, int rc) { if (rc == 0) { - WT_ITEM raw_key; - rc = cursor->get_key(cursor, &raw_key); - if (rc == 0) + WT_ITEM raw_key; + rc = cursor->get_key(cursor, &raw_key); + if (rc == 0) { - ERL_NIF_TERM key; - memcpy(enif_make_new_binary(env, raw_key.size, &key), raw_key.data, raw_key.size); - return enif_make_tuple2(env, ATOM_OK, key); - } + ERL_NIF_TERM key; + memcpy(enif_make_new_binary(env, raw_key.size, &key), raw_key.data, raw_key.size); + return enif_make_tuple2(env, ATOM_OK, key); + } } return wterl_strerror(env, rc); } @@ -600,16 +734,16 @@ static ERL_NIF_TERM wterl_cursor_kv_ret(ErlNifEnv* env, WT_CURSOR *cursor, int r if (rc == 0) { WT_ITEM raw_key, raw_value; - rc = cursor->get_key(cursor, &raw_key); - if (rc == 0) + rc = cursor->get_key(cursor, &raw_key); + if (rc == 0) { rc = cursor->get_value(cursor, &raw_value); if (rc == 0) { - ERL_NIF_TERM key, value; - memcpy(enif_make_new_binary(env, raw_key.size, &key), raw_key.data, raw_key.size); - memcpy(enif_make_new_binary(env, raw_value.size, &value), raw_value.data, raw_value.size); - return enif_make_tuple3(env, ATOM_OK, key, value); + ERL_NIF_TERM key, value; + memcpy(enif_make_new_binary(env, raw_key.size, &key), raw_key.data, raw_key.size); + memcpy(enif_make_new_binary(env, raw_value.size, &value), raw_value.data, raw_value.size); + return enif_make_tuple3(env, ATOM_OK, key, value); } } } @@ -620,164 +754,407 @@ static ERL_NIF_TERM wterl_cursor_value_ret(ErlNifEnv* env, WT_CURSOR *cursor, in { if (rc == 0) { - WT_ITEM raw_value; - rc = cursor->get_value(cursor, &raw_value); - if (rc == 0) + WT_ITEM raw_value; + rc = cursor->get_value(cursor, &raw_value); + if (rc == 0) { - ERL_NIF_TERM value; - memcpy(enif_make_new_binary(env, raw_value.size, &value), raw_value.data, raw_value.size); - return enif_make_tuple2(env, ATOM_OK, value); - } + ERL_NIF_TERM value; + memcpy(enif_make_new_binary(env, raw_value.size, &value), raw_value.data, raw_value.size); + return enif_make_tuple2(env, ATOM_OK, value); + } } return wterl_strerror(env, rc); } -static ERL_NIF_TERM wterl_cursor_np_worker(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[], - CursorRetFun cursor_ret, int prev) -{ +ASYNC_NIF_DECL( + wterl_cursor_next, + { // struct + WterlCursorHandle *cursor_handle; - if (enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&cursor_handle)) - { - WT_CURSOR* cursor = cursor_handle->cursor; - return cursor_ret(env, cursor, prev == 0 ? cursor->next(cursor) : cursor->prev(cursor)); + }, + { // pre + + if (!(argc == 1 && + enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&args->cursor_handle))) { + ASYNC_NIF_RETURN_BADARG(); } - return enif_make_badarg(env); -} + enif_keep_resource((void*)args->cursor_handle); + }, + { // work -static ERL_NIF_TERM wterl_cursor_next(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ - return wterl_cursor_np_worker(env, argc, argv, wterl_cursor_kv_ret, 0); -} + WT_CURSOR* cursor = args->cursor_handle->cursor; + ASYNC_NIF_REPLY(wterl_cursor_kv_ret(env, cursor, cursor->next(cursor))); + }, + { // post -static ERL_NIF_TERM wterl_cursor_next_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ - return wterl_cursor_np_worker(env, argc, argv, wterl_cursor_key_ret, 0); -} + enif_release_resource((void*)args->cursor_handle); + }); -static ERL_NIF_TERM wterl_cursor_next_value(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ - return wterl_cursor_np_worker(env, argc, argv, wterl_cursor_value_ret, 0); -} +ASYNC_NIF_DECL( + wterl_cursor_next_key, + { // struct -static ERL_NIF_TERM wterl_cursor_prev(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ - return wterl_cursor_np_worker(env, argc, argv, wterl_cursor_kv_ret, 1); -} - -static ERL_NIF_TERM wterl_cursor_prev_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ - return wterl_cursor_np_worker(env, argc, argv, wterl_cursor_key_ret, 1); -} - -static ERL_NIF_TERM wterl_cursor_prev_value(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ - return wterl_cursor_np_worker(env, argc, argv, wterl_cursor_value_ret, 1); -} - -static ERL_NIF_TERM wterl_cursor_search_worker(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[], int near) -{ WterlCursorHandle *cursor_handle; + }, + { // pre + + if (!(enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&args->cursor_handle))) { + ASYNC_NIF_RETURN_BADARG(); + } + enif_keep_resource((void*)args->cursor_handle); + }, + { // work + + WT_CURSOR* cursor = args->cursor_handle->cursor; + ASYNC_NIF_REPLY(wterl_cursor_key_ret(env, cursor, cursor->next(cursor))); + }, + { // post + + enif_release_resource((void*)args->cursor_handle); + }); + +ASYNC_NIF_DECL( + wterl_cursor_next_value, + { // struct + + WterlCursorHandle *cursor_handle; + }, + { // pre + + if (!(argc == 1 && + enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&args->cursor_handle))) { + ASYNC_NIF_RETURN_BADARG(); + } + enif_keep_resource((void*)args->cursor_handle); + }, + { // work + + WT_CURSOR* cursor = args->cursor_handle->cursor; + ASYNC_NIF_REPLY(wterl_cursor_value_ret(env, cursor, cursor->next(cursor))); + }, + { // post + + enif_release_resource((void*)args->cursor_handle); + }); + +ASYNC_NIF_DECL( + wterl_cursor_prev, + { // struct + + WterlCursorHandle *cursor_handle; + }, + { // pre + + if (!(argc == 1 && + enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&args->cursor_handle))) { + ASYNC_NIF_RETURN_BADARG(); + } + enif_keep_resource((void*)args->cursor_handle); + }, + { // work + + WT_CURSOR* cursor = args->cursor_handle->cursor; + ASYNC_NIF_REPLY(wterl_cursor_kv_ret(env, cursor, cursor->prev(cursor))); + }, + { // post + + enif_release_resource((void*)args->cursor_handle); + }); + +ASYNC_NIF_DECL( + wterl_cursor_prev_key, + { // struct + + WterlCursorHandle *cursor_handle; + }, + { // pre + + if (!(argc == 1 && + enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&args->cursor_handle))) { + ASYNC_NIF_RETURN_BADARG(); + } + enif_keep_resource((void*)args->cursor_handle); + }, + { // work + + WT_CURSOR* cursor = args->cursor_handle->cursor; + ASYNC_NIF_REPLY(wterl_cursor_key_ret(env, cursor, cursor->prev(cursor))); + }, + { // post + + enif_release_resource((void*)args->cursor_handle); + }); + +ASYNC_NIF_DECL( + wterl_cursor_prev_value, + { // struct + + WterlCursorHandle *cursor_handle; + }, + { // pre + + if (!(argc == 1 && + enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&args->cursor_handle))) { + ASYNC_NIF_RETURN_BADARG(); + } + enif_keep_resource((void*)args->cursor_handle); + }, + { // work + + WT_CURSOR* cursor = args->cursor_handle->cursor; + ASYNC_NIF_REPLY(wterl_cursor_value_ret(env, cursor, cursor->prev(cursor))); + }, + { // post + + enif_release_resource((void*)args->cursor_handle); + }); + +ASYNC_NIF_DECL( + wterl_cursor_search, + { // struct + + WterlCursorHandle *cursor_handle; + ERL_NIF_TERM key; + }, + { // pre + + if (!(argc == 2 && + enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&args->cursor_handle) && + enif_is_binary(env, argv[1]))) { + ASYNC_NIF_RETURN_BADARG(); + } + args->key = enif_make_copy(ASYNC_NIF_WORK_ENV, argv[1]); + enif_keep_resource((void*)args->cursor_handle); + }, + { // work + + WT_CURSOR* cursor = args->cursor_handle->cursor; ErlNifBinary key; - if (enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&cursor_handle) && - enif_inspect_binary(env, argv[1], &key)) - { - WT_CURSOR* cursor = cursor_handle->cursor; - WT_ITEM raw_key; - int exact; - raw_key.data = key.data; - raw_key.size = key.size; - cursor->set_key(cursor, &raw_key); - - // We currently ignore the less-than, greater-than or equals-to return information - // from the cursor.search_near method. - return wterl_cursor_value_ret(env, cursor, - near == 1 ? - cursor->search_near(cursor, &exact) : cursor->search(cursor)); + if (!enif_inspect_binary(env, args->key, &key)) { + ASYNC_NIF_REPLY(enif_make_badarg(env)); + return; } - return enif_make_badarg(env); -} + WT_ITEM raw_key; -static ERL_NIF_TERM wterl_cursor_search(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ - return wterl_cursor_search_worker(env, argc, argv, 0); -} + raw_key.data = key.data; + raw_key.size = key.size; + cursor->set_key(cursor, &raw_key); -static ERL_NIF_TERM wterl_cursor_search_near(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ - return wterl_cursor_search_worker(env, argc, argv, 1); -} + // We currently ignore the less-than, greater-than or equals-to return information + // from the cursor.search_near method. + ASYNC_NIF_REPLY(wterl_cursor_value_ret(env, cursor, cursor->search(cursor))); + }, + { // post + + enif_release_resource((void*)args->cursor_handle); + }); + +ASYNC_NIF_DECL( + wterl_cursor_search_near, + { // struct -static ERL_NIF_TERM wterl_cursor_reset(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ WterlCursorHandle *cursor_handle; - if (enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&cursor_handle)) - { - WT_CURSOR* cursor = cursor_handle->cursor; - int rc = cursor->reset(cursor); - return rc == 0 ? ATOM_OK : wterl_strerror(env, rc); + ERL_NIF_TERM key; + }, + { // pre + + if (!(argc == 2 && + enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&args->cursor_handle) && + enif_is_binary(env, argv[1]))) { + ASYNC_NIF_RETURN_BADARG(); } - return enif_make_badarg(env); -} + args->key = enif_make_copy(ASYNC_NIF_WORK_ENV, argv[1]); + enif_keep_resource((void*)args->cursor_handle); + }, + { // work -#define WTERL_OP_CURSOR_INSERT 1 -#define WTERL_OP_CURSOR_UPDATE 2 -#define WTERL_OP_CURSOR_REMOVE 3 + WT_CURSOR* cursor = args->cursor_handle->cursor; + ErlNifBinary key; + if (!enif_inspect_binary(env, args->key, &key)) { + ASYNC_NIF_REPLY(enif_make_badarg(env)); + return; + } + WT_ITEM raw_key; + int exact; + + raw_key.data = key.data; + raw_key.size = key.size; + cursor->set_key(cursor, &raw_key); + + // We currently ignore the less-than, greater-than or equals-to return information + // from the cursor.search_near method. + ASYNC_NIF_REPLY(wterl_cursor_value_ret(env, cursor, cursor->search_near(cursor, &exact))); + }, + { // post + + enif_release_resource((void*)args->cursor_handle); + }); + +ASYNC_NIF_DECL( + wterl_cursor_reset, + { // struct -static inline ERL_NIF_TERM wterl_cursor_data_op(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[], int op) -{ WterlCursorHandle *cursor_handle; - if (enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&cursor_handle)) - { - ErlNifBinary key, value; - int rc; + }, + { // pre - if (enif_inspect_binary(env, argv[1], &key) && - (op == WTERL_OP_CURSOR_REMOVE ? 1 : enif_inspect_binary(env, argv[2], &value))) - { - WT_CURSOR* cursor = cursor_handle->cursor; - WT_ITEM raw_key, raw_value; - raw_key.data = key.data; - raw_key.size = key.size; - cursor->set_key(cursor, &raw_key); - if (op != WTERL_OP_CURSOR_REMOVE) - { - raw_value.data = value.data; - raw_value.size = value.size; - cursor->set_value(cursor, &raw_value); - } - switch (op) - { - case WTERL_OP_CURSOR_INSERT: - rc = cursor->insert(cursor); - break; - case WTERL_OP_CURSOR_UPDATE: - rc = cursor->update(cursor); - break; - case WTERL_OP_CURSOR_REMOVE: - default: - rc = cursor->remove(cursor); - break; - } - return rc == 0 ? ATOM_OK : wterl_strerror(env, rc); - } + if (!(argc == 1 && + enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&args->cursor_handle))) { + ASYNC_NIF_RETURN_BADARG(); } - return enif_make_badarg(env); -} + enif_keep_resource((void*)args->cursor_handle); + }, + { // work -static ERL_NIF_TERM wterl_cursor_insert(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ - return wterl_cursor_data_op(env, argc, argv, WTERL_OP_CURSOR_INSERT); -} + WT_CURSOR* cursor = args->cursor_handle->cursor; + int rc = cursor->reset(cursor); + ASYNC_NIF_REPLY(rc == 0 ? ATOM_OK : wterl_strerror(env, rc)); + }, + { // post -static ERL_NIF_TERM wterl_cursor_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ - return wterl_cursor_data_op(env, argc, argv, WTERL_OP_CURSOR_UPDATE); -} + enif_release_resource((void*)args->cursor_handle); + }); -static ERL_NIF_TERM wterl_cursor_remove(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ - return wterl_cursor_data_op(env, argc, argv, WTERL_OP_CURSOR_REMOVE); -} +ASYNC_NIF_DECL( + wterl_cursor_insert, + { // struct + + WterlCursorHandle *cursor_handle; + ERL_NIF_TERM key; + ERL_NIF_TERM value; + int rc; + }, + { // pre + + if (!(argc == 3 && + enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&args->cursor_handle) && + enif_is_binary(env, argv[1]) && + enif_is_binary(env, argv[2]))) { + ASYNC_NIF_RETURN_BADARG(); + } + args->key = enif_make_copy(ASYNC_NIF_WORK_ENV, argv[1]); + args->value = enif_make_copy(ASYNC_NIF_WORK_ENV, argv[2]); + enif_keep_resource((void*)args->cursor_handle); + }, + { // work + + WT_CURSOR* cursor = args->cursor_handle->cursor; + ErlNifBinary key; + ErlNifBinary value; + if (!enif_inspect_binary(env, args->key, &key)) { + ASYNC_NIF_REPLY(enif_make_badarg(env)); + return; + } + if (!enif_inspect_binary(env, args->value, &value)) { + ASYNC_NIF_REPLY(enif_make_badarg(env)); + return; + } + WT_ITEM raw_key; + WT_ITEM raw_value; + + raw_key.data = key.data; + raw_key.size = key.size; + cursor->set_key(cursor, &raw_key); + raw_value.data = value.data; + raw_value.size = value.size; + cursor->set_value(cursor, &raw_value); + int rc = cursor->insert(cursor); + ASYNC_NIF_REPLY(rc == 0 ? ATOM_OK : wterl_strerror(env, rc)); + }, + { // post + + enif_release_resource((void*)args->cursor_handle); + }); + +ASYNC_NIF_DECL( + wterl_cursor_update, + { // struct + + WterlCursorHandle *cursor_handle; + ERL_NIF_TERM key; + ERL_NIF_TERM value; + int rc; + }, + { // pre + + if (!(argc == 3 && + enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&args->cursor_handle) && + enif_is_binary(env, argv[1]) && + enif_is_binary(env, argv[2]))) { + ASYNC_NIF_RETURN_BADARG(); + } + args->key = enif_make_copy(ASYNC_NIF_WORK_ENV, argv[1]); + args->value = enif_make_copy(ASYNC_NIF_WORK_ENV, argv[2]); + enif_keep_resource((void*)args->cursor_handle); + }, + { // work + + WT_CURSOR* cursor = args->cursor_handle->cursor; + ErlNifBinary key; + ErlNifBinary value; + if (!enif_inspect_binary(env, args->key, &key)) { + ASYNC_NIF_REPLY(enif_make_badarg(env)); + return; + } + if (!enif_inspect_binary(env, args->value, &value)) { + ASYNC_NIF_REPLY(enif_make_badarg(env)); + return; + } + WT_ITEM raw_key; + WT_ITEM raw_value; + + raw_key.data = key.data; + raw_key.size = key.size; + cursor->set_key(cursor, &raw_key); + raw_value.data = value.data; + raw_value.size = value.size; + cursor->set_value(cursor, &raw_value); + int rc = cursor->update(cursor); + ASYNC_NIF_REPLY(rc == 0 ? ATOM_OK : wterl_strerror(env, rc)); + }, + { // post + + enif_release_resource((void*)args->cursor_handle); + }); + +ASYNC_NIF_DECL( + wterl_cursor_remove, + { // struct + + WterlCursorHandle *cursor_handle; + ERL_NIF_TERM key; + int rc; + }, + { // pre + + if (!(argc == 2 && + enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&args->cursor_handle) && + enif_is_binary(env, argv[1]))) { + ASYNC_NIF_RETURN_BADARG(); + } + args->key = enif_make_copy(ASYNC_NIF_WORK_ENV, argv[1]); + enif_keep_resource((void*)args->cursor_handle); + }, + { // work + + WT_CURSOR* cursor = args->cursor_handle->cursor; + ErlNifBinary key; + if (!enif_inspect_binary(env, args->key, &key)) { + ASYNC_NIF_REPLY(enif_make_badarg(env)); + return; + } + WT_ITEM raw_key; + + raw_key.data = key.data; + raw_key.size = key.size; + cursor->set_key(cursor, &raw_key); + int rc = cursor->remove(cursor); + ASYNC_NIF_REPLY(rc == 0 ? ATOM_OK : wterl_strerror(env, rc)); + }, + { // post + + enif_release_resource((void*)args->cursor_handle); + }); static int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) { @@ -787,7 +1164,54 @@ static int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) wterl_cursor_RESOURCE = enif_open_resource_type(env, NULL, "wterl_cursor_resource", NULL, flags, NULL); ATOM_ERROR = enif_make_atom(env, "error"); ATOM_OK = enif_make_atom(env, "ok"); + + ASYNC_NIF_LOAD(); + return 0; } -ERL_NIF_INIT(wterl, nif_funcs, &on_load, NULL, NULL, NULL); +static void on_unload(ErlNifEnv* env, void* priv_data) +{ + ASYNC_NIF_UNLOAD(); +} + +static int on_upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info) +{ + ASYNC_NIF_UPGRADE(); + return 0; +} + +static ErlNifFunc nif_funcs[] = +{ + {"conn_open_nif", 3, wterl_conn_open}, + {"conn_close_nif", 2, wterl_conn_close}, + {"session_open_nif", 3, wterl_session_open}, + {"session_close_nif", 2, wterl_session_close}, + {"session_create_nif", 4, wterl_session_create}, + {"session_drop_nif", 4, wterl_session_drop}, + {"session_rename_nif", 5, wterl_session_rename}, + {"session_salvage_nif", 4, wterl_session_salvage}, + {"session_checkpoint_nif", 3, wterl_session_checkpoint}, + {"session_truncate_nif", 4, wterl_session_truncate}, + {"session_upgrade_nif", 4, wterl_session_upgrade}, + {"session_verify_nif", 4, wterl_session_verify}, + {"session_delete_nif", 4, wterl_session_delete}, + {"session_get_nif", 4, wterl_session_get}, + {"session_put_nif", 5, wterl_session_put}, + {"cursor_open_nif", 3, wterl_cursor_open}, + {"cursor_close_nif", 2, wterl_cursor_close}, + {"cursor_next_nif", 2, wterl_cursor_next}, + {"cursor_next_key_nif", 2, wterl_cursor_next_key}, + {"cursor_next_value_nif", 2, wterl_cursor_next_value}, + {"cursor_prev_nif", 2, wterl_cursor_prev}, + {"cursor_prev_key_nif", 2, wterl_cursor_prev_key}, + {"cursor_prev_value_nif", 2, wterl_cursor_prev_value}, + {"cursor_search_nif", 3, wterl_cursor_search}, + {"cursor_search_near_nif", 3, wterl_cursor_search_near}, + {"cursor_reset_nif", 2, wterl_cursor_reset}, + {"cursor_insert_nif", 4, wterl_cursor_insert}, + {"cursor_update_nif", 4, wterl_cursor_update}, + {"cursor_remove_nif", 3, wterl_cursor_remove}, +}; + +ERL_NIF_INIT(wterl, nif_funcs, &on_load, NULL, &on_upgrade, &on_unload);