diff --git a/c_src/wterl.c b/c_src/wterl.c index 7875ae6..17242e7 100644 --- a/c_src/wterl.c +++ b/c_src/wterl.c @@ -39,23 +39,34 @@ typedef struct WT_SESSION* session; } wterl_session_handle; +typedef char TableName[128]; + // Atoms (initialized in on_load) static ERL_NIF_TERM ATOM_ERROR; +static ERL_NIF_TERM ATOM_OK; // Prototypes static ERL_NIF_TERM wterl_conn_open(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM wterl_conn_close(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM wterl_session_new(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_put(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_close(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM wterl_table_create(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM wterl_table_drop(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ErlNifFunc nif_funcs[] = { {"conn_open", 2, wterl_conn_open}, + {"conn_close", 1, wterl_conn_close}, {"session_new", 1, wterl_session_new}, - {"session_get", 2, wterl_session_get}, - {"session_put", 3, wterl_session_put}, - {"session_delete", 2, wterl_session_delete} + {"session_get", 3, wterl_session_get}, + {"session_put", 4, wterl_session_put}, + {"session_delete", 3, wterl_session_delete}, + {"session_close", 1, wterl_session_close}, + {"table_create", 3, wterl_table_create}, + {"table_drop", 3, wterl_table_drop}, }; @@ -63,7 +74,7 @@ static ERL_NIF_TERM wterl_conn_open(ErlNifEnv* env, int argc, const ERL_NIF_TERM { char homedir[4096]; ErlNifBinary configBin; - if (enif_get_string(env, argv[0], homedir, sizeof(homedir), ERL_NIF_LATIN1) && + if (enif_get_string(env, argv[0], homedir, sizeof homedir, ERL_NIF_LATIN1) && enif_inspect_binary(env, argv[1], &configBin)) { WT_CONNECTION* conn; @@ -71,11 +82,11 @@ static ERL_NIF_TERM wterl_conn_open(ErlNifEnv* env, int argc, const ERL_NIF_TERM if (rc == 0) { wterl_conn_handle* handle = enif_alloc_resource(wterl_conn_RESOURCE, - sizeof(wterl_conn_handle)); + sizeof(wterl_conn_handle)); handle->conn = conn; ERL_NIF_TERM result = enif_make_resource(env, handle); enif_release_resource(handle); - return enif_make_tuple2(env, enif_make_atom(env, "ok"), result); + return enif_make_tuple2(env, ATOM_OK, result); } else { @@ -88,7 +99,24 @@ static ERL_NIF_TERM wterl_conn_open(ErlNifEnv* env, int argc, const ERL_NIF_TERM { return enif_make_badarg(env); } +} +static ERL_NIF_TERM wterl_conn_close(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + wterl_conn_handle* conn_handle; + if (enif_get_resource(env, argv[0], wterl_conn_RESOURCE, (void**)&conn_handle)) + { + WT_CONNECTION* conn = conn_handle->conn; + int rc = conn->close(conn, NULL); + if (rc != 0) + { + return enif_make_tuple2(env, ATOM_ERROR, + enif_make_string(env, wiredtiger_strerror(rc), + ERL_NIF_LATIN1)); + } + return ATOM_OK; + } + return enif_make_badarg(env); } static ERL_NIF_TERM wterl_session_new(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) @@ -107,7 +135,7 @@ static ERL_NIF_TERM wterl_session_new(ErlNifEnv* env, int argc, const ERL_NIF_TE ERL_NIF_TERM result = enif_make_resource(env, shandle); enif_keep_resource(conn_handle); enif_release_resource(shandle); - return enif_make_tuple2(env, enif_make_atom(env, "ok"), result); + return enif_make_tuple2(env, ATOM_OK, result); } else { @@ -116,25 +144,216 @@ static ERL_NIF_TERM wterl_session_new(ErlNifEnv* env, int argc, const ERL_NIF_TE ERL_NIF_LATIN1)); } } - else - { - return enif_make_badarg(env); - } + return enif_make_badarg(env); } static ERL_NIF_TERM wterl_session_get(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { - return enif_make_atom(env, "ok"); + wterl_session_handle* session_handle; + if (enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&session_handle)) + { + WT_SESSION* session = session_handle->session; + TableName table; + ErlNifBinary key; + if (enif_get_string(env, argv[1], table, sizeof table, ERL_NIF_LATIN1) && + enif_inspect_binary(env, argv[2], &key)) + { + WT_CURSOR* cursor; + int rc = session->open_cursor(session, table, NULL, "overwrite,raw", &cursor); + if (rc != 0) + { + return enif_make_tuple2(env, ATOM_ERROR, + enif_make_string(env, wiredtiger_strerror(rc), + ERL_NIF_LATIN1)); + } + WT_ITEM raw_key; + raw_key.data = key.data; + raw_key.size = key.size; + cursor->set_key(cursor, &raw_key); + rc = cursor->search(cursor); + if (rc == 0) + { + WT_ITEM raw_value; + rc = cursor->get_value(cursor, &raw_value); + cursor->close(cursor, NULL); + if (rc != 0) + { + return enif_make_tuple2(env, ATOM_ERROR, + enif_make_string(env, wiredtiger_strerror(rc), + ERL_NIF_LATIN1)); + } + ErlNifBinary value; + enif_alloc_binary(raw_value.size, &value); + memcpy(value.data, raw_value.data, raw_value.size); + return enif_make_tuple2(env, ATOM_OK, enif_make_binary(env, &value)); + } + else + { + cursor->close(cursor, NULL); + if (rc == WT_NOTFOUND) + { + return enif_make_tuple2(env, ATOM_ERROR, enif_make_atom(env, "not_found")); + } + else + { + return enif_make_tuple2(env, ATOM_ERROR, + enif_make_string(env, wiredtiger_strerror(rc), + ERL_NIF_LATIN1)); + } + } + } + } + return enif_make_badarg(env); } static ERL_NIF_TERM wterl_session_put(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { - return enif_make_atom(env, "ok"); + wterl_session_handle* session_handle; + if (enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&session_handle)) + { + WT_SESSION* session = session_handle->session; + TableName table; + ErlNifBinary key, value; + if (enif_get_string(env, argv[1], table, sizeof table, ERL_NIF_LATIN1) && + enif_inspect_binary(env, argv[2], &key) && enif_inspect_binary(env, argv[3], &value)) + { + WT_CURSOR* cursor; + int rc = session->open_cursor(session, table, NULL, "overwrite,raw", &cursor); + if (rc != 0) + { + return enif_make_tuple2(env, ATOM_ERROR, + enif_make_string(env, wiredtiger_strerror(rc), + ERL_NIF_LATIN1)); + } + 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, NULL); + if (rc != 0) + { + return enif_make_tuple2(env, ATOM_ERROR, + enif_make_string(env, wiredtiger_strerror(rc), + ERL_NIF_LATIN1)); + } + return ATOM_OK; + } + } + return enif_make_badarg(env); } static ERL_NIF_TERM wterl_session_delete(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { - return enif_make_atom(env, "ok"); + wterl_session_handle* session_handle; + if (enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&session_handle)) + { + WT_SESSION* session = session_handle->session; + TableName table; + ErlNifBinary key; + if (enif_get_string(env, argv[1], table, sizeof table, ERL_NIF_LATIN1) && + enif_inspect_binary(env, argv[2], &key)) + { + WT_CURSOR* cursor; + int rc = session->open_cursor(session, table, NULL, "raw", &cursor); + if (rc != 0) + { + return enif_make_tuple2(env, ATOM_ERROR, + enif_make_string(env, wiredtiger_strerror(rc), + ERL_NIF_LATIN1)); + } + 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, NULL); + if (rc != 0) + { + return enif_make_tuple2(env, ATOM_ERROR, + enif_make_string(env, wiredtiger_strerror(rc), + ERL_NIF_LATIN1)); + } + return ATOM_OK; + } + } + return enif_make_badarg(env); +} + +static ERL_NIF_TERM wterl_session_close(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + wterl_session_handle* session_handle; + if (enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&session_handle)) + { + WT_SESSION* session = session_handle->session; + int rc = session->close(session, NULL); + if (rc != 0) + { + return enif_make_tuple2(env, ATOM_ERROR, + enif_make_string(env, wiredtiger_strerror(rc), + ERL_NIF_LATIN1)); + } + return ATOM_OK; + } + return enif_make_badarg(env); +} + +static ERL_NIF_TERM wterl_table_create(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + wterl_session_handle* session_handle; + if (enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&session_handle)) + { + WT_SESSION* session = session_handle->session; + TableName table; + char config[256]; + if (enif_get_string(env, argv[1], table, sizeof table, ERL_NIF_LATIN1) && + enif_get_string(env, argv[2], config, sizeof config, ERL_NIF_LATIN1)) + { + int rc = session->create(session, table, config); + if (rc == 0) + { + return enif_make_tuple2(env, ATOM_OK, enif_make_string(env, table, ERL_NIF_LATIN1)); + } + else + { + return enif_make_tuple2(env, ATOM_ERROR, + enif_make_string(env, wiredtiger_strerror(rc), + ERL_NIF_LATIN1)); + } + } + } + return enif_make_badarg(env); +} + +static ERL_NIF_TERM wterl_table_drop(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + wterl_session_handle* session_handle; + if (enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&session_handle)) + { + WT_SESSION* session = session_handle->session; + TableName table; + char config[256]; + if (enif_get_string(env, argv[1], table, sizeof table, ERL_NIF_LATIN1) && + enif_get_string(env, argv[2], config, sizeof config, ERL_NIF_LATIN1)) + { + int rc = session->drop(session, table, config); + if (rc == 0) + { + return ATOM_OK; + + } + else + { + return enif_make_tuple2(env, ATOM_ERROR, + enif_make_string(env, wiredtiger_strerror(rc), + ERL_NIF_LATIN1)); + } + } + } + return enif_make_badarg(env); } static void wterl_conn_resource_cleanup(ErlNifEnv* env, void* arg) @@ -162,6 +381,7 @@ static int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) &wterl_session_resource_cleanup, flags, NULL); ATOM_ERROR = enif_make_atom(env, "error"); + ATOM_OK = enif_make_atom(env, "ok"); return 0; } diff --git a/src/wterl.erl b/src/wterl.erl index 1cce013..7f01683 100644 --- a/src/wterl.erl +++ b/src/wterl.erl @@ -23,10 +23,16 @@ -export([conn_open/2, + conn_close/1, session_new/1, - session_get/2, - session_put/3, - session_delete/2, + session_get/3, + session_put/4, + session_delete/3, + session_close/1, + table_create/2, + table_create/3, + table_drop/2, + table_drop/3, config_to_bin/2]). -on_load(init/0). @@ -53,18 +59,35 @@ init() -> conn_open(_HomeDir, _Config) -> ?nif_stub. +conn_close(_ConnRef) -> + ?nif_stub. + session_new(_ConnRef) -> ?nif_stub. -session_get(_Ref, _Key) -> +session_get(_Ref, _Table, _Key) -> ?nif_stub. -session_put(_Ref, _Key, _Value) -> +session_put(_Ref, _Table, _Key, _Value) -> ?nif_stub. -session_delete(_Ref, _Key) -> +session_delete(_Ref, _Table, _Key) -> ?nif_stub. +session_close(_Ref) -> + ?nif_stub. + +table_create(Ref, Name) -> + table_create(Ref, Name, ""). + +table_create(_Ref, _Name, _Config) -> + ?nif_stub. + +table_drop(Ref, Name) -> + table_drop(Ref, Name, ""). + +table_drop(_Ref, _Name, _Config) -> + ?nif_stub. %% %% Configuration type information. @@ -132,6 +155,13 @@ basic_test() -> Opts = [{create, true}], ok = filelib:ensure_dir(filename:join("/tmp/wterl.basic", "foo")), {ok, ConnRef} = conn_open("/tmp/wterl.basic", config_to_bin(Opts, [])), - {ok, SRef} = session_new(ConnRef). + {ok, SRef} = session_new(ConnRef), + {ok, Table} = table_create(SRef, "table:test"), + ok = session_put(SRef, Table, <<"a">>, <<"apple">>), + {ok, <<"apple">>} = session_get(SRef, Table, <<"a">>), + ok = session_delete(SRef, Table, <<"a">>), + {error, not_found} = session_get(SRef, Table, <<"a">>), + ok = session_close(SRef), + ok = conn_close(ConnRef). -endif.