Permalink
Browse files

add hook for custom transcoder

  • Loading branch information...
Ali Yakamercan
Ali Yakamercan committed Aug 15, 2012
1 parent 65973e4 commit 0049cfe58042966b804fa793d924a5d2b0770b76
Showing with 55 additions and 41 deletions.
  1. +6 −1 include/cberl.hrl
  2. +39 −37 src/cberl.erl
  3. +7 −0 src/cberl_transcoder.erl
  4. +3 −3 test/cberl_tests.erl
View
@@ -4,7 +4,12 @@
-define('CBE_APPEND', 4).
-define('CBE_PREPEND', 5).
+-opaque handle() :: binary().
+
+-record(instance, {handle :: handle(),
+ transcoder :: module()}).
+
-type key() :: string().
-type value() :: string() | list() | integer() | binary().
-type operation_type() :: add | replace | set | append | prepend.
--opaque instance() :: binary().
+-type instance() :: #instance{}.
View
@@ -40,53 +40,55 @@ new(Host, Username, Password) ->
%% bucket The bucket to connect to
-spec new(string(), string(), string(), string()) -> {ok, instance()} | {error, _}.
new(Host, Username, Password, BucketName) ->
- cberl_nif:new(Host, Username, Password, BucketName).
+ new(Host, Username, Password, BucketName, cberl_transcoder).
+new(Host, Username, Password, BucketName, Transcoder) ->
+ {ok, Handle} = cberl_nif:new(Host, Username, Password, BucketName),
+ {ok, #instance{handle = Handle, transcoder = Transcoder}}.
+
%%%%%%%%%%%%%%%%%%%%%%%%
%%% STORE OPERATIONS %%%
%%%%%%%%%%%%%%%%%%%%%%%%
-%% @equiv add(Instance, Key, Exp, Value, json)
+%% @equiv add(Instance, Key, Exp, Value, standard)
-spec add(instance(), key(), integer(), value()) -> ok | {error, _}.
add(Instance, Key, Exp, Value) ->
- add(Instance, Key, Exp, Value, json).
+ add(Instance, Key, Exp, Value, standard).
-%% @equiv store(Instance, add, Key, Value, Transcoder, Exp, 0)
+%% @equiv store(Instance, add, Key, Value, TranscoderOpts, Exp, 0)
-spec add(instance(), key(), integer(), value(), atom()) -> ok | {error, _}.
-add(Instance, Key, Exp, Value, Transcoder) ->
- store(Instance, add, Key, Value, Transcoder, Exp, 0).
+add(Instance, Key, Exp, Value, TranscoderOpts) ->
+ store(Instance, add, Key, Value, TranscoderOpts, Exp, 0).
-%% @equiv replace(Instance, Key, Exp, Value, json)
+%% @equiv replace(Instance, Key, Exp, Value, standard)
-spec replace(instance(), key(), integer(), value()) -> ok | {error, _}.
replace(Instance, Key, Exp, Value) ->
- replace(Instance, Key, Exp, Value, json).
+ replace(Instance, Key, Exp, Value, standard).
%% @equiv store(Instance, replace, "", Key, Value, Exp)
-spec replace(instance(), key(), integer(), value(), atom()) -> ok | {error, _}.
-replace(Instance, Key, Exp, Value, Transcoder) ->
- store(Instance, replace, Key, Value, Transcoder, Exp, 0).
+replace(Instance, Key, Exp, Value, TranscoderOpts) ->
+ store(Instance, replace, Key, Value, TranscoderOpts, Exp, 0).
-%% @equiv set(Instance, Key, Exp, Value, json)
+%% @equiv set(Instance, Key, Exp, Value, standard)
-spec set(instance(), key(), integer(), value()) -> ok | {error, _}.
set(Instance, Key, Exp, Value) ->
- set(Instance, Key, Exp, Value, json).
+ set(Instance, Key, Exp, Value, standard).
%% @equiv store(Instance, set, "", Key, Value, Exp)
-spec set(instance(), key(), integer(), value(), integer()) -> ok | {error, _}.
-set(Instance, Key, Exp, Value, Transcoder) ->
- store(Instance, set, Key, Value, Transcoder, Exp, 0).
+set(Instance, Key, Exp, Value, TranscoderOpts) ->
+ store(Instance, set, Key, Value, TranscoderOpts, Exp, 0).
%%%%%%%%%%%%%%%%%%%%%%%%%
%%% UPDATE OPERATIONS %%%
%%%%%%%%%%%%%%%%%%%%%%%%%
-%% @equiv append(Instance, Key, Value, 0)
-spec append(instance(), integer(), key(), value()) -> ok | {error, _}.
append(Instance, Cas, Key, Value) ->
store(Instance, append, Key, Value, str, 0, Cas).
-%% @equiv prepend(Instance, Cas, Key, Value, json)
-spec prepend(instance(), integer(), key(), value()) -> ok | {error, _}.
prepend(Instance, Cas, Key, Value) ->
store(Instance, prepend, Key, Value, str, 0, Cas).
@@ -96,8 +98,8 @@ prepend(Instance, Cas, Key, Value) ->
%% Key key to touch
%% ExpTime a new expiration time for the item
-spec mtouch(instance(), key(), integer()) -> ok | {error, _}.
-mtouch(Instance, Key, ExpTime) ->
- cberl_nif:mtouch(Instance, Key, ExpTime).
+mtouch(#instance{handle = Handle}, Key, ExpTime) ->
+ cberl_nif:mtouch(Handle, Key, ExpTime).
incr(Instance, Key, OffSet) ->
arithmetic(Instance, Key, OffSet, 0, 0, 0).
@@ -134,8 +136,8 @@ get_and_lock(Instance, Key, Exp) ->
getl(Instance, Key, Exp).
-spec unlock(instance(), key(), integer()) -> ok | {error, _}.
-unlock(Instance, Key, Cas) ->
- cberl_nif:unlock(Instance, Key, Cas).
+unlock(#instance{handle = Handle}, Key, Cas) ->
+ cberl_nif:unlock(Handle, Key, Cas).
%% @doc main store function takes care of all storing
%% Instance libcouchbase instance to use
%% Op add | replace | set | append | prepend
@@ -155,10 +157,10 @@ unlock(Instance, Key, Cas) ->
%% CAS
-spec store(instance(), operation_type(), key(), value(), atom(),
integer(), integer()) -> ok | {error, _}.
-store(Instance, Op, Key, Value, Transcoder, Exp, Cas) ->
- StoreValue = cberl_transcoder:encode_value(Transcoder, Value),
- cberl_nif:store(Instance, operation_value(Op), Key, StoreValue,
- cberl_transcoder:flag(Transcoder), Exp, Cas).
+store(#instance{handle = Handle, transcoder = Transcoder}, Op, Key, Value, TranscoderOpts, Exp, Cas) ->
+ StoreValue = Transcoder:encode_value(TranscoderOpts, Value),
+ cberl_nif:store(Handle, operation_value(Op), Key, StoreValue,
+ Transcoder:flag(TranscoderOpts), Exp, Cas).
%% @doc get the value for the given key
%% Instance libcouchbase instance to use
@@ -167,11 +169,11 @@ store(Instance, Op, Key, Value, Transcoder, Exp, Cas) ->
%% Exp When the object should expire
%% pass a negative number for infinity
-spec mget(instance(), key(), integer()) -> {ok, integer(), value()} | {error, _}.
-mget(Instance, Key, Exp) ->
- case cberl_nif:mget(Instance, Key, Exp) of
+mget(#instance{handle = Handle, transcoder = Transcoder}, Key, Exp) ->
+ case cberl_nif:mget(Handle, Key, Exp) of
{error, Error} -> {error, Error};
{ok, {Cas, Flag, Value}} ->
- DecodedValue = cberl_transcoder:decode_value(Flag, Value),
+ DecodedValue = Transcoder:decode_value(Flag, Value),
{ok, Cas, DecodedValue}
end.
@@ -181,11 +183,11 @@ mget(Instance, Key, Exp) ->
%% Key the key to get
%% Exp When the lock should expire
-spec getl(instance(), key(), integer()) -> {ok, integer(), value()} | {error, _}.
-getl(Instance, Key, Exp) ->
- case cberl_nif:getl(Instance, Key, Exp) of
+getl(#instance{handle = Handle, transcoder = Transcoder}, Key, Exp) ->
+ case cberl_nif:getl(Handle, Key, Exp) of
{error, Error} -> {error, Error};
{ok, {Cas, Flag, Value}} ->
- DecodedValue = cberl_transcoder:decode_value(Flag, Value),
+ DecodedValue = Transcoder:decode_value(Flag, Value),
{ok, Cas, DecodedValue}
end.
@@ -199,24 +201,24 @@ getl(Instance, Key, Exp) ->
%% Initial The initial value of the object if we create it
-spec arithmetic(instance(), key(), integer(), integer(), integer(), integer()) ->
ok | {error, _}.
-arithmetic(Instance, Key, OffSet, Exp, Create, Initial) ->
- case cberl_nif:arithmetic(Instance, Key, OffSet, Exp, Create, Initial) of
+arithmetic(#instance{handle = Handle, transcoder = Transcoder}, Key, OffSet, Exp, Create, Initial) ->
+ case cberl_nif:arithmetic(Handle, Key, OffSet, Exp, Create, Initial) of
{error, Error} -> {error, Error};
{ok, {Cas, Flag, Value}} ->
- DecodedValue = cberl_transcoder:decode_value(Flag, Value),
+ DecodedValue = Transcoder:decode_value(Flag, Value),
{ok, Cas, DecodedValue}
end.
%% @doc remove the value for given key
%% Instance libcouchbase instance to use
%% Key key to remove
-spec remove(instance(), key()) -> ok | {error, _}.
-remove(Instance, Key) ->
- cberl_nif:remove(Instance, Key, 0).
+remove(#instance{handle = Handle}, Key) ->
+ cberl_nif:remove(Handle, Key, 0).
%% @doc close the libcouchbase instance
-destroy(Instance) ->
- cberl_nif:destroy(Instance).
+destroy(#instance{handle = Handle}) ->
+ cberl_nif:destroy(Handle).
%%%%%%%%%%%%%%%%%%%%%%%%%%
View
@@ -8,12 +8,16 @@
-define('CBE_RAW', 16#0004).
-define('CBE_STR', 16#0008).
+-define(STANDARD_FLAG, json).
+
-type encoder() :: json | gzip | raw | str.
-type encoder_list() :: [encoder()].
+-spec encode_value(encoder() | encoder_list(), value()) -> value().
encode_value(Encoders, Value) ->
encode_value1(flag(Encoders), Value).
+-spec encode_value1(integer(), value()) -> value().
encode_value1(Flag, Value) when Flag band ?'CBE_STR' =/= 0 ->
encode_value1(Flag bxor ?'CBE_STR', list_to_binary(Value));
encode_value1(Flag, Value) when Flag band ?'CBE_JSON' =/= 0 ->
@@ -25,6 +29,7 @@ encode_value1(Flag, Value) when Flag band ?'CBE_RAW' =/= 0 ->
encode_value1(0, Value) ->
Value.
+-spec decode_value(integer(), value()) -> value().
decode_value(Flag, Value) when ?'CBE_RAW' band Flag =/= 0->
decode_value(Flag bxor ?'CBE_RAW', binary_to_term(Value));
decode_value(Flag, Value) when ?'CBE_GZIP' band Flag =/= 0->
@@ -36,6 +41,8 @@ decode_value(Flag, Value) when ?'CBE_STR' band Flag =/= 0->
decode_value(0, Value) ->
Value.
+-spec flag(encoder() | encoder_list()) -> integer().
+flag(standard) -> flag(?STANDARD_FLAG);
flag(json) -> ?'CBE_JSON';
flag(gzip) -> ?'CBE_GZIP';
flag(raw_binary) -> ?'CBE_RAW';
View
@@ -15,8 +15,8 @@ setup() ->
Instance.
clean_up(Instance) ->
- ok = cberl:remove(Instance, "testkey"),
- ok = cberl:remove(Instance, "testkey1"),
+ cberl:remove(Instance, "testkey"),
+ cberl:remove(Instance, "testkey1"),
ok = cberl:destroy(Instance).
%%%===================================================================
%%% Tests
@@ -51,7 +51,7 @@ test_replace_add(Instance) ->
].
test_append_prepend(Instance) ->
- ok = cberl:set(Instance, "testkey", 0, "base"),
+ ok = cberl:set(Instance, "testkey", 0, "base", str),
ok = cberl:append(Instance, 0, "testkey", "tail"),
Get1 = cberl:get(Instance, "testkey"),
ok = cberl:prepend(Instance, 0, "testkey", "head"),

0 comments on commit 0049cfe

Please sign in to comment.