Fix cursor.{open,close}, it now works.

Add support for cursor.{next,prev,search,search_near,reset}.

Change table_create to no longer pass back the table name, WiredTiger's
model is that you pass in the object name each time (and the current
model means we can't drop the table before we run the tests).

Upgrade to the WiredTiger 1.0 release, there's a bug where static
libraries aren't created correctly, for now create shared libraries
for wterl.
This commit is contained in:
Keith Bostic 2012-02-16 14:54:05 -05:00
parent 642da3a44c
commit 6f0357b4c5
5 changed files with 187 additions and 33 deletions

View file

@ -2,7 +2,7 @@
set -e set -e
WT_VSN=20111212 WT_VSN=1.0.0
if [ `basename $PWD` != "c_src" ]; then if [ `basename $PWD` != "c_src" ]; then
pushd c_src pushd c_src
@ -21,7 +21,7 @@ case "$1" in
tar -xjf wiredtiger-$WT_VSN.tar.bz2 tar -xjf wiredtiger-$WT_VSN.tar.bz2
(cd wiredtiger-$WT_VSN/build_posix && \ (cd wiredtiger-$WT_VSN/build_posix && \
../configure --disable-shared --enable-static --with-pic \ ../configure --with-pic \
--prefix=$BASEDIR/system && \ --prefix=$BASEDIR/system && \
make && make install) make && make install)

Binary file not shown.

Binary file not shown.

View file

@ -62,9 +62,15 @@ static ERL_NIF_TERM wterl_session_delete(ErlNifEnv* env, int argc, const ERL_NIF
static ERL_NIF_TERM wterl_session_close(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_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 ERL_NIF_TERM wterl_table_drop(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_cursor_open(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_cursor_next(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_close(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM wterl_cursor_next(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[], 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_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_reset(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ErlNifFunc nif_funcs[] = static ErlNifFunc nif_funcs[] =
{ {
@ -77,9 +83,13 @@ static ErlNifFunc nif_funcs[] =
{"session_close", 1, wterl_session_close}, {"session_close", 1, wterl_session_close},
{"table_create", 3, wterl_table_create}, {"table_create", 3, wterl_table_create},
{"table_drop", 3, wterl_table_drop}, {"table_drop", 3, wterl_table_drop},
{"cursor_open", 2, wterl_cursor_open},
{"cursor_next", 1, wterl_cursor_next},
{"cursor_close", 1, wterl_cursor_close}, {"cursor_close", 1, wterl_cursor_close},
{"cursor_next", 1, wterl_cursor_next},
{"cursor_open", 2, wterl_cursor_open},
{"cursor_prev", 1, wterl_cursor_prev},
{"cursor_reset", 1, wterl_cursor_reset},
{"cursor_search", 2, wterl_cursor_search},
{"cursor_search_near", 2, wterl_cursor_search_near},
}; };
@ -188,7 +198,7 @@ static ERL_NIF_TERM wterl_session_get(ErlNifEnv* env, int argc, const ERL_NIF_TE
{ {
WT_ITEM raw_value; WT_ITEM raw_value;
rc = cursor->get_value(cursor, &raw_value); rc = cursor->get_value(cursor, &raw_value);
cursor->close(cursor, NULL); cursor->close(cursor);
if (rc != 0) if (rc != 0)
{ {
return enif_make_tuple2(env, ATOM_ERROR, return enif_make_tuple2(env, ATOM_ERROR,
@ -202,7 +212,7 @@ static ERL_NIF_TERM wterl_session_get(ErlNifEnv* env, int argc, const ERL_NIF_TE
} }
else else
{ {
cursor->close(cursor, NULL); cursor->close(cursor);
if (rc == WT_NOTFOUND) if (rc == WT_NOTFOUND)
{ {
return enif_make_tuple2(env, ATOM_ERROR, enif_make_atom(env, "not_found")); return enif_make_tuple2(env, ATOM_ERROR, enif_make_atom(env, "not_found"));
@ -246,7 +256,7 @@ static ERL_NIF_TERM wterl_session_put(ErlNifEnv* env, int argc, const ERL_NIF_TE
raw_value.size = value.size; raw_value.size = value.size;
cursor->set_value(cursor, &raw_value); cursor->set_value(cursor, &raw_value);
rc = cursor->insert(cursor); rc = cursor->insert(cursor);
cursor->close(cursor, NULL); cursor->close(cursor);
if (rc != 0) if (rc != 0)
{ {
return enif_make_tuple2(env, ATOM_ERROR, return enif_make_tuple2(env, ATOM_ERROR,
@ -283,7 +293,7 @@ static ERL_NIF_TERM wterl_session_delete(ErlNifEnv* env, int argc, const ERL_NIF
raw_key.size = key.size; raw_key.size = key.size;
cursor->set_key(cursor, &raw_key); cursor->set_key(cursor, &raw_key);
rc = cursor->remove(cursor); rc = cursor->remove(cursor);
cursor->close(cursor, NULL); cursor->close(cursor);
if (rc != 0) if (rc != 0)
{ {
return enif_make_tuple2(env, ATOM_ERROR, return enif_make_tuple2(env, ATOM_ERROR,
@ -326,16 +336,13 @@ static ERL_NIF_TERM wterl_table_create(ErlNifEnv* env, int argc, const ERL_NIF_T
enif_get_string(env, argv[2], config, sizeof config, ERL_NIF_LATIN1)) enif_get_string(env, argv[2], config, sizeof config, ERL_NIF_LATIN1))
{ {
int rc = session->create(session, table, config); int rc = session->create(session, table, config);
if (rc == 0) 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, return enif_make_tuple2(env, ATOM_ERROR,
enif_make_string(env, wiredtiger_strerror(rc), enif_make_string(env, wiredtiger_strerror(rc),
ERL_NIF_LATIN1)); ERL_NIF_LATIN1));
} }
return ATOM_OK;
} }
} }
return enif_make_badarg(env); return enif_make_badarg(env);
@ -353,17 +360,13 @@ static ERL_NIF_TERM wterl_table_drop(ErlNifEnv* env, int argc, const ERL_NIF_TER
enif_get_string(env, argv[2], config, sizeof config, ERL_NIF_LATIN1)) enif_get_string(env, argv[2], config, sizeof config, ERL_NIF_LATIN1))
{ {
int rc = session->drop(session, table, config); int rc = session->drop(session, table, config);
if (rc == 0) if (rc != 0)
{
return ATOM_OK;
}
else
{ {
return enif_make_tuple2(env, ATOM_ERROR, return enif_make_tuple2(env, ATOM_ERROR,
enif_make_string(env, wiredtiger_strerror(rc), enif_make_string(env, wiredtiger_strerror(rc),
ERL_NIF_LATIN1)); ERL_NIF_LATIN1));
} }
return ATOM_OK;
} }
} }
return enif_make_badarg(env); return enif_make_badarg(env);
@ -402,12 +405,22 @@ static ERL_NIF_TERM wterl_cursor_open(ErlNifEnv* env, int argc, const ERL_NIF_TE
} }
static ERL_NIF_TERM wterl_cursor_next(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) static ERL_NIF_TERM wterl_cursor_next(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
return (wterl_cursor_np_worker(env, argc, argv, 1));
}
static ERL_NIF_TERM wterl_cursor_prev(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
return (wterl_cursor_np_worker(env, argc, argv, 0));
}
static ERL_NIF_TERM wterl_cursor_np_worker(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[], int next)
{ {
wterl_cursor_handle *cursor_handle; wterl_cursor_handle *cursor_handle;
if (enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&cursor_handle)) if (enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&cursor_handle))
{ {
WT_CURSOR* cursor = cursor_handle->cursor; WT_CURSOR* cursor = cursor_handle->cursor;
int rc = cursor->next(cursor); int rc = next == 1 ? cursor->next(cursor) : cursor->prev(cursor);
if (rc == 0) if (rc == 0)
{ {
WT_ITEM raw_value; WT_ITEM raw_value;
@ -440,13 +453,90 @@ static ERL_NIF_TERM wterl_cursor_next(ErlNifEnv* env, int argc, const ERL_NIF_TE
return enif_make_badarg(env); return enif_make_badarg(env);
} }
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));
}
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));
}
static ERL_NIF_TERM wterl_cursor_search_worker(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[], int near)
{
wterl_cursor_handle *cursor_handle;
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);
int rc = near == 1 ? cursor->search_near(cursor, &exact) : cursor->search(cursor);
if (rc == 0)
{
WT_ITEM raw_value;
rc = cursor->get_value(cursor, &raw_value);
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
{
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_cursor_reset(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
wterl_cursor_handle *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);
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 ERL_NIF_TERM wterl_cursor_close(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[])
{ {
wterl_cursor_handle *cursor_handle; wterl_cursor_handle *cursor_handle;
if (enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&cursor_handle)) if (enif_get_resource(env, argv[0], wterl_cursor_RESOURCE, (void**)&cursor_handle))
{ {
WT_CURSOR* cursor = cursor_handle->cursor; WT_CURSOR* cursor = cursor_handle->cursor;
int rc = cursor->close(cursor, NULL); int rc = cursor->close(cursor);
if (rc == 0) if (rc == 0)
{ {
return ATOM_OK; return ATOM_OK;
@ -473,6 +563,11 @@ static void wterl_session_resource_cleanup(ErlNifEnv* env, void* arg)
/* wterl_handle* handle = (wterl_handle*)arg; */ /* wterl_handle* handle = (wterl_handle*)arg; */
} }
static void wterl_cursor_resource_cleanup(ErlNifEnv* env, void* arg)
{
/* Delete any dynamically allocated memory stored in wterl_handle */
/* wterl_handle* handle = (wterl_handle*)arg; */
}
static int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) static int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
{ {
@ -485,6 +580,10 @@ static int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
"wterl_session_resource", "wterl_session_resource",
&wterl_session_resource_cleanup, &wterl_session_resource_cleanup,
flags, NULL); flags, NULL);
wterl_cursor_RESOURCE = enif_open_resource_type(env, NULL,
"wterl_cursor_resource",
&wterl_cursor_resource_cleanup,
flags, NULL);
ATOM_ERROR = enif_make_atom(env, "error"); ATOM_ERROR = enif_make_atom(env, "error");
ATOM_OK = enif_make_atom(env, "ok"); ATOM_OK = enif_make_atom(env, "ok");
return 0; return 0;

View file

@ -33,9 +33,13 @@
table_create/3, table_create/3,
table_drop/2, table_drop/2,
table_drop/3, table_drop/3,
cursor_open/2,
cursor_next/1,
cursor_close/1, cursor_close/1,
cursor_next/1,
cursor_open/2,
cursor_prev/1,
cursor_reset/1,
cursor_search/2,
cursor_search_near/2,
config_to_bin/2]). config_to_bin/2]).
-on_load(init/0). -on_load(init/0).
@ -98,6 +102,18 @@ cursor_open(_Ref, _Table) ->
cursor_next(_Cursor) -> cursor_next(_Cursor) ->
?nif_stub. ?nif_stub.
cursor_prev(_Cursor) ->
?nif_stub.
cursor_search(_Cursor, _Key) ->
?nif_stub.
cursor_search_near(_Cursor, _Key) ->
?nif_stub.
cursor_reset(_Cursor) ->
?nif_stub.
cursor_close(_Cursor) -> cursor_close(_Cursor) ->
?nif_stub. ?nif_stub.
@ -163,26 +179,65 @@ config_to_bin([{Key, Value} | Rest], Acc) ->
-ifdef(TEST). -ifdef(TEST).
basic_test() -> basic_test() ->
%% Open a connection and a session, create the test table.
Opts = [{create, true}, {cache_size, "100MB"}], Opts = [{create, true}, {cache_size, "100MB"}],
ok = filelib:ensure_dir(filename:join("/tmp/wterl.basic", "foo")), ok = filelib:ensure_dir(filename:join("/tmp/wterl.basic", "foo")),
{ok, ConnRef} = conn_open("/tmp/wterl.basic", config_to_bin(Opts, [])), {ok, ConnRef} = conn_open("/tmp/wterl.basic", config_to_bin(Opts, [])),
{ok, SRef} = session_open(ConnRef), {ok, SRef} = session_open(ConnRef),
{ok, Table} = table_create(SRef, "table:test"),
ok = session_put(SRef, Table, <<"a">>, <<"apple">>), %% Remove the table from any earlier run.
{ok, <<"apple">>} = session_get(SRef, Table, <<"a">>), ok = table_drop(SRef, "table:test", "force"),
ok = session_delete(SRef, Table, <<"a">>),
{error, not_found} = session_get(SRef, Table, <<"a">>),
{ok, Cursor} = cursor_open(SRef, Table), %% Create the table
ok = table_create(SRef, "table:test"),
%% Insert/delete a key using the session handle
ok = session_put(SRef, "table:test", <<"a">>, <<"apple">>),
{ok, <<"apple">>} = session_get(SRef, "table:test", <<"a">>),
ok = session_delete(SRef, "table:test", <<"a">>),
{error, not_found} = session_get(SRef, "table:test", <<"a">>),
%% Open/close a cursor
{ok, Cursor} = cursor_open(SRef, "table:test"),
ok = cursor_close(Cursor), ok = cursor_close(Cursor),
ok = session_put(SRef, Table, <<"a">>, <<"apple">>), %% Insert some items
{ok, Cursor} = cursor_open(SRef, Table), ok = session_put(SRef, "table:test", <<"a">>, <<"apple">>),
ok = session_put(SRef, "table:test", <<"b">>, <<"banana">>),
ok = session_put(SRef, "table:test", <<"c">>, <<"cherry">>),
ok = session_put(SRef, "table:test", <<"d">>, <<"date">>),
ok = session_put(SRef, "table:test", <<"g">>, <<"gooseberry">>),
%% Move a cursor back and forth
{ok, Cursor} = cursor_open(SRef, "table:test"),
{ok, <<"apple">>} = cursor_next(Cursor), {ok, <<"apple">>} = cursor_next(Cursor),
{ok, <<"banana">>} = cursor_next(Cursor),
{ok, <<"cherry">>} = cursor_next(Cursor),
{ok, <<"date">>} = cursor_next(Cursor),
{ok, <<"cherry">>} = cursor_prev(Cursor),
{ok, <<"date">>} = cursor_next(Cursor),
{ok, <<"gooseberry">>} = cursor_next(Cursor),
{error, not_found} = cursor_next(Cursor), {error, not_found} = cursor_next(Cursor),
ok = cursor_close(Cursor), ok = cursor_close(Cursor),
%% Search for an item
{ok, Cursor} = cursor_open(SRef, "table:test"),
{ok, <<"banana">>} = cursor_search(Cursor, <<"b">>),
ok = cursor_close(Cursor),
%% Range search for an item
{ok, Cursor} = cursor_open(SRef, "table:test"),
{ok, <<"gooseberry">>} = cursor_search_near(Cursor, <<"f">>),
ok = cursor_close(Cursor),
%% Check that cursor reset works
{ok, Cursor} = cursor_open(SRef, "table:test"),
{ok, <<"apple">>} = cursor_next(Cursor),
ok = cursor_reset(Cursor),
{ok, <<"apple">>} = cursor_next(Cursor),
ok = cursor_close(Cursor),
%% Close the session/connection
ok = session_close(SRef), ok = session_close(SRef),
ok = conn_close(ConnRef). ok = conn_close(ConnRef).