more WiredTiger prototyping

A number of changes:

* Added exported functions to close connections and sessions.

* Added exported functions to create and drop tables. Currently not
  happy with the shape of these functions, though, as they treat
  tables in Erlang just as strings, and they force users of sessions
  to have to pass both sessions and tables into get/put/delete
  operations. It might be better to take a table identifier as part of
  the session creation function and store that identifier with the
  session resource.

* Added implementations for key-value get, put, and delete.

* Added very minimal unit tests for the changes above.
This commit is contained in:
Steve Vinoski 2012-02-08 17:31:16 -05:00
parent dcb4270f9d
commit b93946a5e0
2 changed files with 271 additions and 21 deletions

View file

@ -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;
}

View file

@ -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.