make wterl an app, cache the WT connection
Add app, supervisor, and worker to open and cache the database connection. Revert to using binaries for WT config in order to allow wterl callers to use proplists for configuration. Change {error, not_found} to not_found return values from wterl.
This commit is contained in:
parent
c89d6deaea
commit
7e6d947765
6 changed files with 239 additions and 36 deletions
|
@ -46,7 +46,6 @@ typedef struct
|
|||
WT_CURSOR* cursor;
|
||||
} wterl_cursor_handle;
|
||||
|
||||
typedef char Config[256]; // configuration strings
|
||||
typedef char Uri[128]; // object names
|
||||
|
||||
// Atoms (initialized in on_load)
|
||||
|
@ -115,7 +114,7 @@ static ErlNifFunc nif_funcs[] =
|
|||
static inline ERL_NIF_TERM wterl_strerror(ErlNifEnv* env, int rc)
|
||||
{
|
||||
if (rc == WT_NOTFOUND)
|
||||
return enif_make_tuple2(env, ATOM_ERROR, enif_make_atom(env, "not_found"));
|
||||
return enif_make_atom(env, "not_found");
|
||||
else
|
||||
return enif_make_tuple2(env, ATOM_ERROR,
|
||||
enif_make_string(env, wiredtiger_strerror(rc), ERL_NIF_LATIN1));
|
||||
|
@ -123,13 +122,13 @@ static inline ERL_NIF_TERM wterl_strerror(ErlNifEnv* env, int rc)
|
|||
|
||||
static ERL_NIF_TERM wterl_conn_open(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
Config config;
|
||||
ErlNifBinary config;
|
||||
char homedir[4096];
|
||||
if (enif_get_string(env, argv[0], homedir, sizeof homedir, ERL_NIF_LATIN1) &&
|
||||
enif_get_string(env, argv[1], config, sizeof config, ERL_NIF_LATIN1))
|
||||
enif_inspect_binary(env, argv[1], &config))
|
||||
{
|
||||
WT_CONNECTION* conn;
|
||||
int rc = wiredtiger_open(homedir, NULL, config, &conn);
|
||||
int rc = wiredtiger_open(homedir, NULL, (const char*)config.data, &conn);
|
||||
if (rc == 0)
|
||||
{
|
||||
wterl_conn_handle* conn_handle =
|
||||
|
@ -179,36 +178,36 @@ static inline ERL_NIF_TERM wterl_session_worker(ErlNifEnv* env, int argc, const
|
|||
if (enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&session_handle))
|
||||
{
|
||||
WT_SESSION* session = session_handle->session;
|
||||
Config config;
|
||||
ErlNifBinary config;
|
||||
Uri uri;
|
||||
if (enif_get_string(env, argv[1], uri, sizeof uri, ERL_NIF_LATIN1) &&
|
||||
enif_get_string(env, argv[2], config, sizeof config, ERL_NIF_LATIN1))
|
||||
enif_inspect_binary(env, argv[2], &config))
|
||||
{
|
||||
int rc;
|
||||
switch (op) {
|
||||
case WTERL_OP_CREATE:
|
||||
rc = session->create(session, uri, config);
|
||||
rc = session->create(session, uri, (const char*)config.data);
|
||||
break;
|
||||
case WTERL_OP_DROP:
|
||||
rc = session->drop(session, uri, config);
|
||||
rc = session->drop(session, uri, (const char*)config.data);
|
||||
break;
|
||||
case WTERL_OP_SALVAGE:
|
||||
rc = session->salvage(session, uri, config);
|
||||
rc = session->salvage(session, uri, (const char*)config.data);
|
||||
break;
|
||||
case WTERL_OP_SYNC:
|
||||
rc = session->sync(session, uri, config);
|
||||
rc = session->sync(session, uri, (const char*)config.data);
|
||||
break;
|
||||
case WTERL_OP_TRUNCATE:
|
||||
// Ignore the cursor start/stop form of truncation for now,
|
||||
// support only the full file truncation.
|
||||
rc = session->truncate(session, uri, NULL, NULL, config);
|
||||
rc = session->truncate(session, uri, NULL, NULL, (const char*)config.data);
|
||||
break;
|
||||
case WTERL_OP_UPGRADE:
|
||||
rc = session->upgrade(session, uri, config);
|
||||
rc = session->upgrade(session, uri, (const char*)config.data);
|
||||
break;
|
||||
default:
|
||||
case WTERL_OP_VERIFY:
|
||||
rc = session->verify(session, uri, config);
|
||||
rc = session->verify(session, uri, (const char*)config.data);
|
||||
break;
|
||||
}
|
||||
if (rc != 0)
|
||||
|
@ -285,13 +284,13 @@ static ERL_NIF_TERM wterl_session_rename(ErlNifEnv* env, int argc, const ERL_NIF
|
|||
if (enif_get_resource(env, argv[0], wterl_session_RESOURCE, (void**)&session_handle))
|
||||
{
|
||||
WT_SESSION* session = session_handle->session;
|
||||
Config config;
|
||||
ErlNifBinary config;
|
||||
Uri oldname, newname;
|
||||
if (enif_get_string(env, argv[1], oldname, sizeof oldname, ERL_NIF_LATIN1) &&
|
||||
enif_get_string(env, argv[2], newname, sizeof newname, ERL_NIF_LATIN1) &&
|
||||
enif_get_string(env, argv[3], config, sizeof config, ERL_NIF_LATIN1))
|
||||
enif_inspect_binary(env, argv[3], &config))
|
||||
{
|
||||
int rc = session->rename(session, oldname, newname, config);
|
||||
int rc = session->rename(session, oldname, newname, (const char*)config.data);
|
||||
if (rc != 0)
|
||||
{
|
||||
return wterl_strerror(env, rc);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
kernel,
|
||||
stdlib
|
||||
]},
|
||||
{mod, {wterl_app, []}},
|
||||
{env, [
|
||||
]}
|
||||
]}.
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
session_upgrade/3,
|
||||
session_verify/2,
|
||||
session_verify/3,
|
||||
config_to_bin/2]).
|
||||
config_to_bin/1]).
|
||||
|
||||
-on_load(init/0).
|
||||
|
||||
|
@ -63,6 +63,8 @@
|
|||
nif_stub_error(Line) ->
|
||||
erlang:nif_error({nif_not_loaded,module,?MODULE,line,Line}).
|
||||
|
||||
-define(EMPTY_CONFIG, <<"\0">>).
|
||||
|
||||
-ifdef(TEST).
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
-endif.
|
||||
|
@ -91,12 +93,12 @@ session_close(_Ref) ->
|
|||
?nif_stub.
|
||||
|
||||
session_create(Ref, Name) ->
|
||||
session_create(Ref, Name, "").
|
||||
session_create(Ref, Name, ?EMPTY_CONFIG).
|
||||
session_create(_Ref, _Name, _Config) ->
|
||||
?nif_stub.
|
||||
|
||||
session_drop(Ref, Name) ->
|
||||
session_drop(Ref, Name, "").
|
||||
session_drop(Ref, Name, ?EMPTY_CONFIG).
|
||||
session_drop(_Ref, _Name, _Config) ->
|
||||
?nif_stub.
|
||||
|
||||
|
@ -110,32 +112,32 @@ session_put(_Ref, _Table, _Key, _Value) ->
|
|||
?nif_stub.
|
||||
|
||||
session_rename(Ref, OldName, NewName) ->
|
||||
session_rename(Ref, OldName, NewName, "").
|
||||
session_rename(Ref, OldName, NewName, ?EMPTY_CONFIG).
|
||||
session_rename(_Ref, _OldName, _NewName, _Config) ->
|
||||
?nif_stub.
|
||||
|
||||
session_salvage(Ref, Name) ->
|
||||
session_salvage(Ref, Name, "").
|
||||
session_salvage(Ref, Name, ?EMPTY_CONFIG).
|
||||
session_salvage(_Ref, _Name, _Config) ->
|
||||
?nif_stub.
|
||||
|
||||
session_sync(Ref, Name) ->
|
||||
session_sync(Ref, Name, "").
|
||||
session_sync(Ref, Name, ?EMPTY_CONFIG).
|
||||
session_sync(_Ref, _Name, _Config) ->
|
||||
?nif_stub.
|
||||
|
||||
session_truncate(Ref, Name) ->
|
||||
session_truncate(Ref, Name, "").
|
||||
session_truncate(Ref, Name, ?EMPTY_CONFIG).
|
||||
session_truncate(_Ref, _Name, _Config) ->
|
||||
?nif_stub.
|
||||
|
||||
session_upgrade(Ref, Name) ->
|
||||
session_upgrade(Ref, Name, "").
|
||||
session_upgrade(Ref, Name, ?EMPTY_CONFIG).
|
||||
session_upgrade(_Ref, _Name, _Config) ->
|
||||
?nif_stub.
|
||||
|
||||
session_verify(Ref, Name) ->
|
||||
session_verify(Ref, Name, "").
|
||||
session_verify(Ref, Name, ?EMPTY_CONFIG).
|
||||
session_verify(_Ref, _Name, _Config) ->
|
||||
?nif_stub.
|
||||
|
||||
|
@ -179,6 +181,7 @@ config_types() ->
|
|||
{eviction_target, integer},
|
||||
{eviction_trigger, integer},
|
||||
{extensions, string},
|
||||
{force, bool},
|
||||
{hazard_max, integer},
|
||||
{home_environment, bool},
|
||||
{home_environment_priv, bool},
|
||||
|
@ -203,6 +206,8 @@ config_encode(bool, false) ->
|
|||
config_encode(_Type, _Value) ->
|
||||
invalid.
|
||||
|
||||
config_to_bin(Opts) ->
|
||||
config_to_bin(Opts, []).
|
||||
config_to_bin([], Acc) ->
|
||||
iolist_to_binary([Acc, <<"\0">>]);
|
||||
config_to_bin([{Key, Value} | Rest], Acc) ->
|
||||
|
@ -215,7 +220,7 @@ config_to_bin([{Key, Value} | Rest], Acc) ->
|
|||
Acc;
|
||||
EncodedValue ->
|
||||
EncodedKey = atom_to_binary(Key, utf8),
|
||||
[EncodedKey, <<" = ">>, EncodedValue, <<", ">> | Acc]
|
||||
[EncodedKey, <<"=">>, EncodedValue, <<",">> | Acc]
|
||||
end,
|
||||
config_to_bin(Rest, Acc2);
|
||||
false ->
|
||||
|
@ -235,13 +240,13 @@ basic_test() ->
|
|||
ok = filelib:ensure_dir(filename:join("/tmp/wterl.basic", "foo")),
|
||||
|
||||
io:put_chars(standard_error, "\topen connection\n"),
|
||||
{ok, ConnRef} =
|
||||
conn_open("/tmp/wterl.basic", "create=true,cache_size=100MB"),
|
||||
OpenConfig = config_to_bin([{create,true},{cache_size,"100MB"}]),
|
||||
{ok, ConnRef} = conn_open("/tmp/wterl.basic", OpenConfig),
|
||||
{ok, SRef} = session_open(ConnRef),
|
||||
|
||||
%% Remove the table from any earlier run and re-create it
|
||||
io:put_chars(standard_error, "\ttable drop/create\n"),
|
||||
ok = session_drop(SRef, "table:test", "force"),
|
||||
ok = session_drop(SRef, "table:test", config_to_bin([{force,true}])),
|
||||
ok = session_create(SRef, "table:test"),
|
||||
|
||||
%% Insert/delete a key using the session handle
|
||||
|
@ -249,7 +254,7 @@ basic_test() ->
|
|||
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">>),
|
||||
not_found = session_get(SRef, "table:test", <<"a">>),
|
||||
|
||||
%% Insert some items
|
||||
io:put_chars(standard_error, "\tsession insert\n"),
|
||||
|
@ -277,7 +282,7 @@ basic_test() ->
|
|||
|
||||
io:put_chars(standard_error, "\tsession truncate\n"),
|
||||
ok = session_truncate(SRef, "table:test"),
|
||||
{error, not_found} = session_get(SRef, "table:test", <<"a">>),
|
||||
not_found = session_get(SRef, "table:test", <<"a">>),
|
||||
|
||||
ok = session_put(SRef, "table:test", <<"a">>, <<"apple">>),
|
||||
ok = session_put(SRef, "table:test", <<"b">>, <<"banana">>),
|
||||
|
@ -314,7 +319,7 @@ basic_test() ->
|
|||
{ok, <<"cherry">>} = cursor_prev(Cursor),
|
||||
{ok, <<"date">>} = cursor_next(Cursor),
|
||||
{ok, <<"gooseberry">>} = cursor_next(Cursor),
|
||||
{error, not_found} = cursor_next(Cursor),
|
||||
not_found = cursor_next(Cursor),
|
||||
ok = cursor_close(Cursor),
|
||||
|
||||
%% Search for an item
|
||||
|
@ -352,7 +357,7 @@ basic_test() ->
|
|||
io:put_chars(standard_error, "\tcursor update\n"),
|
||||
{ok, Cursor} = cursor_open(SRef, "table:test"),
|
||||
ok = cursor_update(Cursor, <<"g">>, <<"goji berries">>),
|
||||
{error, not_found} = cursor_update(Cursor, <<"k">>, <<"kumquat">>),
|
||||
not_found = cursor_update(Cursor, <<"k">>, <<"kumquat">>),
|
||||
ok = cursor_close(Cursor),
|
||||
{ok, <<"goji berries">>} = session_get(SRef, "table:test", <<"g">>),
|
||||
|
||||
|
@ -360,9 +365,9 @@ basic_test() ->
|
|||
io:put_chars(standard_error, "\tcursor remove\n"),
|
||||
{ok, Cursor} = cursor_open(SRef, "table:test"),
|
||||
ok = cursor_remove(Cursor, <<"g">>, <<"goji berries">>),
|
||||
{error, not_found} = cursor_remove(Cursor, <<"l">>, <<"lemon">>),
|
||||
not_found = cursor_remove(Cursor, <<"l">>, <<"lemon">>),
|
||||
ok = cursor_close(Cursor),
|
||||
{error, not_found} = session_get(SRef, "table:test", <<"g">>),
|
||||
not_found = session_get(SRef, "table:test", <<"g">>),
|
||||
|
||||
%% Close the session/connection
|
||||
io:put_chars(standard_error, "\tsession/connection close\n"),
|
||||
|
|
39
src/wterl_app.erl
Normal file
39
src/wterl_app.erl
Normal file
|
@ -0,0 +1,39 @@
|
|||
%% -------------------------------------------------------------------
|
||||
%%
|
||||
%% wterl: access to WiredTiger database
|
||||
%%
|
||||
%% Copyright (c) 2012 Basho Technologies, Inc. All Rights Reserved.
|
||||
%%
|
||||
%% This file is provided to you under the Apache License,
|
||||
%% Version 2.0 (the "License"); you may not use this file
|
||||
%% except in compliance with the License. You may obtain
|
||||
%% a copy of the License at
|
||||
%%
|
||||
%% http://www.apache.org/licenses/LICENSE-2.0
|
||||
%%
|
||||
%% Unless required by applicable law or agreed to in writing,
|
||||
%% software distributed under the License is distributed on an
|
||||
%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
%% KIND, either express or implied. See the License for the
|
||||
%% specific language governing permissions and limitations
|
||||
%% under the License.
|
||||
%%
|
||||
%% -------------------------------------------------------------------
|
||||
-module(wterl_app).
|
||||
-author('Steve Vinoski <steve@basho.com>').
|
||||
|
||||
-behaviour(application).
|
||||
|
||||
%% Application callbacks
|
||||
-export([start/2, stop/1]).
|
||||
|
||||
|
||||
%% ===================================================================
|
||||
%% Application callbacks
|
||||
%% ===================================================================
|
||||
|
||||
start(_StartType, _StartArgs) ->
|
||||
wterl_sup:start_link().
|
||||
|
||||
stop(_State) ->
|
||||
ok.
|
111
src/wterl_conn.erl
Normal file
111
src/wterl_conn.erl
Normal file
|
@ -0,0 +1,111 @@
|
|||
%% -------------------------------------------------------------------
|
||||
%%
|
||||
%% wterl_conn: manage a connection to WiredTiger
|
||||
%%
|
||||
%% Copyright (c) 2012 Basho Technologies, Inc. All Rights Reserved.
|
||||
%%
|
||||
%% This file is provided to you under the Apache License,
|
||||
%% Version 2.0 (the "License"); you may not use this file
|
||||
%% except in compliance with the License. You may obtain
|
||||
%% a copy of the License at
|
||||
%%
|
||||
%% http://www.apache.org/licenses/LICENSE-2.0
|
||||
%%
|
||||
%% Unless required by applicable law or agreed to in writing,
|
||||
%% software distributed under the License is distributed on an
|
||||
%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
%% KIND, either express or implied. See the License for the
|
||||
%% specific language governing permissions and limitations
|
||||
%% under the License.
|
||||
%%
|
||||
%% -------------------------------------------------------------------
|
||||
-module(wterl_conn).
|
||||
-author('Steve Vinoski <steve@basho.com>').
|
||||
|
||||
-behaviour(gen_server).
|
||||
|
||||
-ifdef(TEST).
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
-endif.
|
||||
|
||||
%% API
|
||||
-export([start_link/0,
|
||||
open/1, get/0, close/0]).
|
||||
|
||||
%% gen_server callbacks
|
||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||
terminate/2, code_change/3]).
|
||||
|
||||
-record(state, { conn }).
|
||||
|
||||
%% ====================================================================
|
||||
%% API
|
||||
%% ====================================================================
|
||||
|
||||
start_link() ->
|
||||
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
|
||||
|
||||
open(Dir) ->
|
||||
gen_server:call(?MODULE, {open, Dir}, infinity).
|
||||
|
||||
get() ->
|
||||
gen_server:call(?MODULE, get, infinity).
|
||||
|
||||
close() ->
|
||||
gen_server:call(?MODULE, close, infinity).
|
||||
|
||||
%% ====================================================================
|
||||
%% gen_server callbacks
|
||||
%% ====================================================================
|
||||
|
||||
init([]) ->
|
||||
{ok, #state{}}.
|
||||
|
||||
handle_call({open, Dir}, _From, #state{conn = undefined}=State) ->
|
||||
Opts = [{create, true}, {cache_size, "100MB"}],
|
||||
{Reply, NState} = case wterl:conn_open(Dir, wterl:config_to_bin(Opts)) of
|
||||
{ok, ConnRef}=OK ->
|
||||
{OK, State#state{conn = ConnRef}};
|
||||
Error ->
|
||||
{Error, State}
|
||||
end,
|
||||
{reply, Reply, NState};
|
||||
handle_call({open, _Dir}, _From,#state{conn = ConnRef}=State) ->
|
||||
{reply, {ok, ConnRef}, State};
|
||||
|
||||
handle_call(get, _From, #state{conn = undefined}=State) ->
|
||||
{reply, {error, "no connection"}, State};
|
||||
handle_call(get, _From, #state{conn = ConnRef}=State) ->
|
||||
{reply, {ok, ConnRef}, State};
|
||||
|
||||
handle_call(close, _From, #state{conn = ConnRef}=State) ->
|
||||
close(ConnRef),
|
||||
{reply, ok, State}.
|
||||
|
||||
handle_cast(_Msg, State) ->
|
||||
{noreply, State}.
|
||||
|
||||
handle_info(_Info, State) ->
|
||||
{noreply, State}.
|
||||
|
||||
terminate(_Reason, #state{conn = ConnRef}) ->
|
||||
close(ConnRef),
|
||||
ok.
|
||||
|
||||
code_change(_OldVsn, State, _Extra) ->
|
||||
{ok, State}.
|
||||
|
||||
%% ====================================================================
|
||||
%% Internal functions
|
||||
%% ====================================================================
|
||||
|
||||
close(undefined) ->
|
||||
ok;
|
||||
close(ConnRef) ->
|
||||
wterl:conn_close(ConnRef).
|
||||
|
||||
|
||||
-ifdef(TEST).
|
||||
|
||||
|
||||
-endif.
|
48
src/wterl_sup.erl
Normal file
48
src/wterl_sup.erl
Normal file
|
@ -0,0 +1,48 @@
|
|||
%% -------------------------------------------------------------------
|
||||
%%
|
||||
%% wterl_sup: supervisor for WiredTiger database app
|
||||
%%
|
||||
%% Copyright (c) 2012 Basho Technologies, Inc. All Rights Reserved.
|
||||
%%
|
||||
%% This file is provided to you under the Apache License,
|
||||
%% Version 2.0 (the "License"); you may not use this file
|
||||
%% except in compliance with the License. You may obtain
|
||||
%% a copy of the License at
|
||||
%%
|
||||
%% http://www.apache.org/licenses/LICENSE-2.0
|
||||
%%
|
||||
%% Unless required by applicable law or agreed to in writing,
|
||||
%% software distributed under the License is distributed on an
|
||||
%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
%% KIND, either express or implied. See the License for the
|
||||
%% specific language governing permissions and limitations
|
||||
%% under the License.
|
||||
%%
|
||||
%% -------------------------------------------------------------------
|
||||
-module(wterl_sup).
|
||||
-author('Steve Vinoski <steve@basho.com>').
|
||||
|
||||
-behaviour(supervisor).
|
||||
|
||||
%% API
|
||||
-export([start_link/0]).
|
||||
|
||||
%% Supervisor callbacks
|
||||
-export([init/1]).
|
||||
|
||||
%% Helper macro for declaring children of supervisor
|
||||
-define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}).
|
||||
|
||||
%% ===================================================================
|
||||
%% API functions
|
||||
%% ===================================================================
|
||||
start_link() ->
|
||||
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
|
||||
|
||||
|
||||
%% ===================================================================
|
||||
%% Supervisor callbacks
|
||||
%% ===================================================================
|
||||
|
||||
init([]) ->
|
||||
{ok, {{one_for_one, 5, 10}, [?CHILD(wterl_conn, worker)]}}.
|
Loading…
Reference in a new issue