Permalink
Browse files

Add HanoiDB backend support

  • Loading branch information...
1 parent c531e3f commit 38bea8305b2abd3a67b43d6478289dfb3bb99c5f Gregory Burd committed May 21, 2012
Showing with 116 additions and 17 deletions.
  1. +1 −0 .gitignore
  2. +6 −6 Makefile
  3. +9 −3 README.md
  4. +4 −3 rebar.config
  5. +91 −0 src/backends/edis_hanoidb_backend.erl
  6. +2 −2 src/edis.app.src
  7. +1 −1 src/edis.erl
  8. +2 −2 src/edis_config.erl
View
@@ -6,3 +6,4 @@ ebin
deps
erl_crash.dump
logs/
+*~
View
@@ -13,7 +13,7 @@ all: erl
erl:
rebar get-deps && rebar compile
-
+
clean:
rm -rf bin
rebar clean
@@ -27,12 +27,12 @@ analyze: erl
xref: erl
rebar skip_deps=true xref
-
-run: erl
+
+run:
${ERL} -s edis
test: erl
- ${ERL} -config test.config -noshell -sname edis_test_server -s edis -run elog debug &
+ ${ERL} -config test.config -noshell -sname edis_test_server -s edis -run elog debug &
mkdir -p ./test/ebin
erlc -o ./test/ebin +debug_info ./test/*_SUITE.erl
rebar skip_deps=true ct ; \
@@ -42,7 +42,7 @@ shell: erl
${ERL}
doc: erl
- cd deps/erldocs
+ cd deps/erldocs
make
cd ../..
./deps/erldocs/erldocs doc
@@ -57,4 +57,4 @@ service: install
mkdir -p /etc/edis/db/
if [ ! -f /etc/edis/edis.config ] ; then cp priv/edis.config /etc/edis/ ; fi
cp priv/edis.init.d /etc/init.d/edis
-
+
View
@@ -22,9 +22,15 @@ Just run `$ make run` and open connections with your favourite redis client.
### Unsupported Commands
_SYNC_, _SLOWLOG_, _SLAVEOF_, _DEBUG *_
-
-
-
### License
edis is licensed by Electronic Inaka, LLC under the Apache 2.0 license; see the LICENSE file in this repository.
+### TODO
+
+* Backends
+ * HanoiDB
+ * Make use of the efficient range searchs with start/end for searching ranges
+ * Make use of time-based key expiry
+ * Finish the TODO items
+* Logging
+ * Swap out elog for lager
View
@@ -1,7 +1,8 @@
{deps, [{elog, "\.*", {git, "git://github.com/inaka/elog.git", "master"}},
{erldis, "\.*", {git, "git://github.com/inaka/erldis.git", "master"}},
- {eleveldb, "\.*", {git, "git@github.com:inaka/eleveldb.git", "master"}},
- {erldocs, "\.*", {git, "git://github.com/daleharvey/erldocs.git", "master"}}]}.
+ {eleveldb, "\.*", {git, "git@github.com:basho/eleveldb.git", "master"}},
+ {hanoidb, "\.*", {git, "git://github.com/basho/hanoidb.git", "master"}},
+ {erldocs, "\.*", {git, "git://github.com/daleharvey/erldocs.git", "master"}}]}.
{require_otp_vsn, "R1[45]"}.
{erl_first_files, ["src/edis_backend.erl", "test/edis_bench.erl"]}.
{erl_opts, [{src_dirs, ["src", "src/backends", "tests", "test/benchmarks"]},
@@ -21,4 +22,4 @@
warn_missing_spec,
warn_untyped_record, debug_info]}.
{xref_checks, [undefined_function_calls]}.
-{ct_extra_params,"-no_auto_compile -dir ./test/ebin -logdir logs/ct"}.
+{ct_extra_params,"-no_auto_compile -dir ./test/ebin -logdir logs/ct"}.
@@ -0,0 +1,91 @@
+%%%-------------------------------------------------------------------
+%%% @author Fernando Benavides <fernando.benavides@inakanetworks.com>
+%%% @author Chad DePue <chad@inakanetworks.com>
+%%% @copyright (C) 2011 InakaLabs SRL
+%%% @doc leveldb based backend
+%%% @end
+%%%-------------------------------------------------------------------
+-module(edis_hanoidb_backend).
+-author('Greg Burd <greg@burd.me>').
+
+-behaviour(edis_backend).
+
+-include("edis.hrl").
+-include_lib("hanoidb/include/hanoidb.hrl").
+
+-record(ref, {db :: hanoidb:db_ref(),
+ file :: string()}).
+-opaque ref() :: #ref{}.
+-export_type([ref/0]).
+
+-export([init/3, write/2, put/3, delete/2, fold/3, is_empty/1, destroy/1, status/1, get/2]).
+
+%% ====================================================================
+%% Behaviour functions
+%% ====================================================================
+-spec init(string(), non_neg_integer(), hanoidb:open_options()) -> {ok, ref()} | {error, term()}.
+init(Dir, Index, Options) ->
+ File = Dir ++ "/edis-" ++ integer_to_list(Index),
+ case hanoidb:open(File, Options) of
+ {ok, Db} -> {ok, #ref{db = Db, file = File}};
+ Error -> Error
+ end.
+
+-spec write(ref(), edis_backend:write_actions()) -> ok | {error, term()}.
+write(#ref{db = Db}, Actions) ->
+ ParseAction = fun({put, Key, Item}) ->
+ {put, sext:encode(Key), erlang:term_to_binary(Item)};
+ (Action) -> Action
+ end,
+ hanoidb:transact(Db, lists:map(ParseAction, Actions)).
+
+-spec put(ref(), binary(), #edis_item{}) -> ok | {error, term()}.
+put(#ref{db = Db}, Key, Item) ->
+ hanoidb:put(Db, sext:encode(Key), erlang:term_to_binary(Item)).
+
+-spec delete(ref(), binary()) -> ok | {error, term()}.
+delete(#ref{db = Db}, Key) ->
+ hanoidb:delete(Db, sext:encode(Key)).
+
+-spec fold(ref(), edis_backend:fold_fun(), term()) -> term().
+fold(#ref{db = Db}, Fun, InitValue) ->
+ hanoidb:range(
+ Db,
+ fun({_Key, Bin}, Acc) ->
+ Fun(erlang:binary_to_term(Bin), Acc)
+ end,
+ InitValue).
+
+-define(MAX_OBJECT_KEY, <<16,0,0,0,4>>). %% TODO: really?
+
+-spec is_empty(ref()) -> boolean().
+is_empty(#ref{db = Db}) ->
+ FoldFun = fun(_K, _V, _Acc) -> throw(ok) end,
+ try
+ Range = #key_range{ from_key = sext:decode(<<>>),
+ from_inclusive = true,
+ to_key = ?MAX_OBJECT_KEY,
+ to_inclusive = false
+ },
+ [] =:= hanoi:fold_range(Db, FoldFun, [], Range)
+ catch
+ _:ok ->
+ false
+ end.
+
+-spec destroy(ref()) -> ok | {error, term()}.
+destroy(#ref{file = _File}) ->
+ ok. %% TODO: not yet implemented
+
+-spec status(ref()) -> {ok, binary()} | error.
+status(#ref{db = _Db}) ->
+ []. %% TODO: not yet implemented
+
+-spec get(ref(), binary()) -> #edis_item{} | not_found | {error, term()}.
+get(#ref{db = Db}, Key) ->
+ case hanoidb:get(Db, sext:encode(Key)) of
+ {ok, Bin} ->
+ erlang:binary_to_term(Bin);
+ NotFoundOrError ->
+ NotFoundOrError
+ end.
View
@@ -1,7 +1,7 @@
{application, edis,
[
- {description, "Redis KV Store - The Erlang Way :)"},
- {vsn, "0.1"},
+ {description, "An Erlang implementation of the Redis KV Store"},
+ {vsn, "0.2.0"},
{registered, []},
{applications, [
kernel,
View
@@ -64,4 +64,4 @@ start(_StartType, _StartArgs) ->
%% @private
-spec stop(any()) -> ok.
-stop(_State) -> ok.
+stop(_State) -> ok.
View
@@ -59,7 +59,7 @@ get(requirepass) ->
get(dir) ->
get(dir, "./db/");
get(backend) ->
- get(backend, {edis_eleveldb_backend, [{create_if_missing, true}]});
+ get(backend, {edis_hanoidb_backend, []});
get(Pattern) ->
[{K, V} ||
{K, V} <- application:get_all_env(edis),
@@ -73,4 +73,4 @@ get(Field, Default) ->
_ ->
?DEBUG("~p := ~p~n", [Field, Default]),
Default
- end.
+ end.

0 comments on commit 38bea83

Please sign in to comment.