2012-04-19 22:09:01 +00:00
|
|
|
%% ----------------------------------------------------------------------------
|
|
|
|
%%
|
2012-05-07 15:22:55 +00:00
|
|
|
%% hanoidb: LSM-trees (Log-Structured Merge Trees) Indexed Storage
|
2012-04-19 22:09:01 +00:00
|
|
|
%%
|
|
|
|
%% Copyright 2011-2012 (c) Trifork A/S. All Rights Reserved.
|
|
|
|
%% http://trifork.com/ info@trifork.com
|
|
|
|
%%
|
|
|
|
%% Copyright 2012 (c) Basho Technologies, Inc. All Rights Reserved.
|
|
|
|
%% http://basho.com/ info@basho.com
|
|
|
|
%%
|
|
|
|
%% 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.
|
|
|
|
%%
|
|
|
|
%% ----------------------------------------------------------------------------
|
|
|
|
|
2012-05-07 20:53:05 +00:00
|
|
|
%% @doc Drive a set of LSM BTrees
|
2012-05-07 15:22:55 +00:00
|
|
|
-module(hanoidb_drv).
|
2012-01-06 21:56:23 +00:00
|
|
|
|
|
|
|
-behaviour(gen_server).
|
|
|
|
|
|
|
|
%% API
|
|
|
|
-export([start_link/0]).
|
|
|
|
|
2012-01-07 00:00:31 +00:00
|
|
|
-export([
|
2012-01-07 11:43:11 +00:00
|
|
|
delete_exist/2,
|
2012-04-15 14:35:39 +00:00
|
|
|
get_exist/2,
|
|
|
|
get_fail/2,
|
2012-01-07 14:16:57 +00:00
|
|
|
open/1, close/1,
|
2012-01-06 21:56:23 +00:00
|
|
|
put/3,
|
2012-04-27 07:59:09 +00:00
|
|
|
fold_range/4,
|
2012-01-06 21:56:23 +00:00
|
|
|
stop/0]).
|
|
|
|
|
|
|
|
%% gen_server callbacks
|
|
|
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
|
|
|
terminate/2, code_change/3]).
|
|
|
|
|
2012-04-15 14:35:39 +00:00
|
|
|
-define(SERVER, ?MODULE).
|
2012-01-06 21:56:23 +00:00
|
|
|
|
|
|
|
-record(state, { btrees = dict:new() % Map from a name to its tree
|
|
|
|
}).
|
|
|
|
|
|
|
|
%%%===================================================================
|
|
|
|
|
|
|
|
start_link() ->
|
|
|
|
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
|
|
|
|
|
|
|
|
call(X) ->
|
|
|
|
gen_server:call(?SERVER, X, infinity).
|
|
|
|
|
2012-04-15 14:35:39 +00:00
|
|
|
get_exist(N, K) ->
|
|
|
|
call({get, N, K}).
|
2012-01-07 21:57:01 +00:00
|
|
|
|
2012-04-15 14:35:39 +00:00
|
|
|
get_fail(N, K) ->
|
|
|
|
call({get, N, K}).
|
2012-01-07 00:00:31 +00:00
|
|
|
|
2012-01-07 11:43:11 +00:00
|
|
|
delete_exist(N, K) ->
|
|
|
|
call({delete_exist, N, K}).
|
|
|
|
|
2012-01-06 21:56:23 +00:00
|
|
|
open(N) ->
|
|
|
|
call({open, N}).
|
|
|
|
|
2012-01-07 14:16:57 +00:00
|
|
|
close(N) ->
|
|
|
|
call({close, N}).
|
|
|
|
|
2012-01-06 21:56:23 +00:00
|
|
|
put(N, K, V) ->
|
|
|
|
call({put, N, K, V}).
|
|
|
|
|
2012-04-27 07:59:09 +00:00
|
|
|
fold_range(T, Fun, Acc0, Range) ->
|
|
|
|
call({fold_range, T, Fun, Acc0, Range}).
|
2012-01-22 11:34:22 +00:00
|
|
|
|
2012-01-06 21:56:23 +00:00
|
|
|
stop() ->
|
|
|
|
call(stop).
|
|
|
|
|
|
|
|
%%%===================================================================
|
|
|
|
|
|
|
|
init([]) ->
|
|
|
|
{ok, #state{}}.
|
|
|
|
|
|
|
|
handle_call({open, N}, _, #state { btrees = D} = State) ->
|
2012-05-07 15:22:55 +00:00
|
|
|
case hanoidb:open(N) of
|
2012-01-06 21:56:23 +00:00
|
|
|
{ok, Tree} ->
|
|
|
|
{reply, ok, State#state { btrees = dict:store(N, Tree, D)}};
|
|
|
|
Otherwise ->
|
|
|
|
{reply, {error, Otherwise}, State}
|
|
|
|
end;
|
2012-01-07 14:16:57 +00:00
|
|
|
handle_call({close, N}, _, #state { btrees = D} = State) ->
|
|
|
|
Tree = dict:fetch(N, D),
|
2012-05-07 15:22:55 +00:00
|
|
|
case hanoidb:close(Tree) of
|
2012-01-07 14:16:57 +00:00
|
|
|
ok ->
|
|
|
|
{reply, ok, State#state { btrees = dict:erase(N, D)}};
|
|
|
|
Otherwise ->
|
|
|
|
{reply, {error, Otherwise}, State}
|
|
|
|
end;
|
2012-04-27 07:59:09 +00:00
|
|
|
handle_call({fold_range, Name, Fun, Acc0, Range},
|
2012-01-22 11:34:22 +00:00
|
|
|
_From,
|
|
|
|
#state { btrees = D } = State) ->
|
|
|
|
Tree = dict:fetch(Name, D),
|
2012-05-07 15:22:55 +00:00
|
|
|
Result = hanoidb:fold_range(Tree, Fun, Acc0, Range),
|
2012-01-22 11:34:22 +00:00
|
|
|
{reply, Result, State};
|
2012-01-06 21:56:23 +00:00
|
|
|
handle_call({put, N, K, V}, _, #state { btrees = D} = State) ->
|
|
|
|
Tree = dict:fetch(N, D),
|
2012-05-07 15:22:55 +00:00
|
|
|
case hanoidb:put(Tree, K, V) of
|
2012-01-06 21:56:23 +00:00
|
|
|
ok ->
|
|
|
|
{reply, ok, State};
|
|
|
|
Other ->
|
|
|
|
{reply, {error, Other}, State}
|
|
|
|
end;
|
2012-01-07 11:43:11 +00:00
|
|
|
handle_call({delete_exist, N, K}, _, #state { btrees = D} = State) ->
|
|
|
|
Tree = dict:fetch(N, D),
|
2012-05-07 15:22:55 +00:00
|
|
|
Reply = hanoidb:delete(Tree, K),
|
2012-01-07 11:43:11 +00:00
|
|
|
{reply, Reply, State};
|
2012-04-15 14:35:39 +00:00
|
|
|
handle_call({get, N, K}, _, #state { btrees = D} = State) ->
|
2012-01-07 00:00:31 +00:00
|
|
|
Tree = dict:fetch(N, D),
|
2012-05-07 15:22:55 +00:00
|
|
|
Reply = hanoidb:get(Tree, K),
|
2012-01-07 00:00:31 +00:00
|
|
|
{reply, Reply, State};
|
2012-01-19 13:15:46 +00:00
|
|
|
handle_call(stop, _, #state{ btrees = D } = State ) ->
|
2012-05-07 15:22:55 +00:00
|
|
|
[ hanoidb:close(Tree) || {_,Tree} <- dict:to_list(D) ],
|
2012-01-06 21:56:23 +00:00
|
|
|
{stop, normal, ok, State};
|
|
|
|
handle_call(_Request, _From, State) ->
|
|
|
|
Reply = ok,
|
|
|
|
{reply, Reply, State}.
|
|
|
|
|
|
|
|
handle_cast(_Msg, State) ->
|
|
|
|
{noreply, State}.
|
|
|
|
|
|
|
|
handle_info(_Info, State) ->
|
|
|
|
{noreply, State}.
|
|
|
|
|
2012-01-07 00:00:31 +00:00
|
|
|
terminate(_Reason, _State) ->
|
2012-01-06 21:56:23 +00:00
|
|
|
ok.
|
|
|
|
|
|
|
|
code_change(_OldVsn, State, _Extra) ->
|
|
|
|
{ok, State}.
|
|
|
|
|