Commits

Jacob Perkins  committed 705ef63

vsn 0.2.0 with sorted sets commands

  • Participants
  • Parent commits c89921f

Comments (0)

Files changed (6)

File ebin/erldis.app

 {application, erldis, [
 	{description, "Erlang Redis application"},
-	{vsn, "0.1.6"},
+	{vsn, "0.2.0"},
 	{registered, [erldis_sup]},
 	{mod, {erldis_app, []}},
 	{applications, [kernel, stdlib]},
 	{modules, [
 		erldis_client, erldis, erldis_proto, erldis_app, erldis_sup,
-		erldis_sets, erldis_dict, erldis_list, gen_server2, erldis_sync_client
+		erldis_sets, erldis_dict, erldis_list, gen_server2, erldis_sync_client,
+		erldis_binaries
 	]},
 	{env, [{host, "localhost"}, {port, 6379}, {timeout, 500}]}
 ]}.

File ebin/erldis.appup

-{"0.1.6", [
+{"0.2.0", [
+	{"0.1.6", [
+		{add_module, erldis_binaries},
+		{load_module, erldis_client},
+		{load_module, erldis}
+	]},
 	{"0.1.5", [{load_module, erldis}]},
 	{"0.1.4", [{load_module, erldis_client}]},
 	{"0.1.3", [{load_module, erldis_client}]},
 		{add_module, erldis_sets}
 	]}
 ], [
+	{"0.1.6", [
+		{load_module, erldis_client},
+		{load_module, erldis},
+		{delete_module, erldis_binaries}
+	]},
 	{"0.1.5", [{load_module, erldis}]},
 	{"0.1.4", [{load_module, erldis_client}]},
 	{"0.1.3", [{load_module, erldis_client}]},

File src/erldis.erl

 	Reply = erldis_client:call(Client, Command, [[Key, size(Value)], [Value]]),
 	internal_set_like_reply(Reply);
 internal_set_like(Client, Command, Key, Value) when not is_binary(Key) ->
-	internal_set_like(Client, Command, erldis_client:bin(Key), Value);
+	internal_set_like(Client, Command, erldis_binaries:to_binary(Key), Value);
 internal_set_like(Client, Command, Key, Value) when not is_binary(Value) ->
-	internal_set_like(Client, Command, Key, erldis_client:bin(Value));
+	internal_set_like(Client, Command, Key, erldis_binaries:to_binary(Value));
 internal_set_like(_, _, _, _) ->
 	{error, badarg}.
 
 
 numeric(false) -> 0;
 numeric(true) -> 1;
+numeric(nil) -> 0;
 numeric(I) when is_binary(I) -> numeric(binary_to_list(I));
 numeric(I) when is_list(I) ->
 	try list_to_integer(I)
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 exists(Client, Key) when not is_binary(Key) ->
-	exists(Client, erldis_client:bin(Key));
+	exists(Client, erldis_binaries:to_binary(Key));
 exists(Client, Key) ->
 	erldis_client:sr_scall(Client, <<"exists ", Key/binary>>).
 
 del(Client, Key) when not is_binary(Key) ->
-	del(Client, erldis_client:bin(Key));
+	del(Client, erldis_binaries:to_binary(Key));
 del(Client, Key) ->
 	erldis_client:sr_scall(Client, <<"del ", Key/binary>>).
 
 type(Client, Key) when not is_binary(Key) ->
-	type(Client, erldis_client:bin(Key));
+	type(Client, erldis_binaries:to_binary(Key));
 type(Client, Key) ->
 	erldis_client:sr_scall(Client, <<"type ", Key/binary>>).
 
 keys(Client, Pattern) when not is_binary(Pattern) ->
-	keys(Client, erldis_client:bin(Pattern));
+	keys(Client, erldis_binaries:to_binary(Pattern));
 keys(Client, Pattern) ->
 	% TODO: tokenize the binary directly (if is faster)
 	% NOTE: with binary-list conversion, timer:tc says 26000-30000 microseconds
 	end.
 
 randomkey(Client, Key) when not is_binary(Key) ->
-	randomkey(Client, erldis_client:bin(Key));
+	randomkey(Client, erldis_binaries:to_binary(Key));
 randomkey(Client, Key) ->
 	erldis_client:sr_scall(Client, <<"randomkey ", Key/binary>>).
 
 rename(Client, OldKey, NewKey) when not is_binary(OldKey) ->
-	rename(Client, erldis_client:bin(OldKey), NewKey);
+	rename(Client, erldis_binaries:to_binary(OldKey), NewKey);
 rename(Client, OldKey, NewKey) when not is_binary(NewKey) ->
-	rename(Client, OldKey, erldis_client:bin(NewKey));
+	rename(Client, OldKey, erldis_binaries:to_binary(NewKey));
 rename(Client, OldKey, NewKey) ->
 	erldis_client:sr_scall(Client, <<"rename ", OldKey/binary, " ", NewKey/binary>>).
 
 renamenx(Client, OldKey, NewKey) when not is_binary(OldKey) ->
-	renamenx(Client, erldis_client:bin(OldKey), NewKey);
+	renamenx(Client, erldis_binaries:to_binary(OldKey), NewKey);
 renamenx(Client, OldKey, NewKey) when not is_binary(NewKey) ->
-	renamenx(Client, OldKey, erldis_client:bin(NewKey));
+	renamenx(Client, OldKey, erldis_binaries:to_binary(NewKey));
 renamenx(Client, OldKey, NewKey) ->
 	erldis_client:sr_scall(Client, <<"renamenx ", OldKey/binary, " ", NewKey/binary>>).
 
 dbsize(Client) -> numeric(erldis_client:sr_scall(Client, <<"dbsize ">>)).
 
 expire(Client, Key, Seconds) when not is_binary(Key) ->
-	expire(Client, erldis_client:bin(Key), Seconds);
+	expire(Client, erldis_binaries:to_binary(Key), Seconds);
 expire(Client, Key, Seconds) ->
 	erldis_client:sr_scall(Client, <<"expire ", Key/binary, " ", Seconds/binary>>).
 
 set(Client, Key, Value) -> internal_set_like(Client, <<"set ">>, Key, Value).
 
 get(Client, Key) when not is_binary(Key) ->
-	get(Client, erldis_client:bin(Key));
+	get(Client, erldis_binaries:to_binary(Key));
 get(Client, Key) ->
 	erldis_client:sr_scall(Client, <<"get ", Key/binary>>).
 
 setnx(Client, Key, Value) -> internal_set_like(Client, <<"setnx ">>, Key, Value).
 
 incr(Client, Key) when not is_binary(Key) ->
-	incr(Client, erldis_client:bin(Key));
+	incr(Client, erldis_binaries:to_binary(Key));
 incr(Client, Key) ->
 	numeric(erldis_client:sr_scall(Client, <<"incr ", Key/binary>>)).
 
 	numeric(erldis_client:sr_scall(Client, <<"incrby ">>, [Key, By])).
 
 decr(Client, Key) when not is_binary(Key) ->
-	decr(Client, erldis_client:bin(Key));
+	decr(Client, erldis_binaries:to_binary(Key));
 decr(Client, Key) ->
 	numeric(erldis_client:sr_scall(Client, <<"decr ", Key/binary>>)).
 
 	erldis_client:sr_scall(Client, <<"lindex ">>, [Key, Index]).
 
 lset(Client, Key, Index, Value) when not is_binary(Value) ->
-	lset(Client, Key, Index, erldis_client:bin(Value));
+	lset(Client, Key, Index, erldis_binaries:to_binary(Value));
 lset(Client, Key, Index, Value) ->
 	erldis_client:call(Client, <<"lset ">>, [[Key, Index, size(Value)], [Value]]).
 
 lrem(Client, Key, Number, Value) when not is_binary(Value) ->
-	lrem(Client, Key, Number, erldis_client:bin(Value));
+	lrem(Client, Key, Number, erldis_binaries:to_binary(Value));
 lrem(Client, Key, Number, Value) ->
 	% TODO: needs sr_scall like single results
 	numeric(hd(erldis_client:call(Client, <<"lrem ">>, [[Key, Number, size(Value)], [Value]]))).
 srem(Client, Key, Member) -> internal_set_like(Client, <<"srem ">>, Key, Member).
 
 smove(Client, SrcKey, DstKey, Member) when not is_binary(Member) ->
-	smove(Client, SrcKey, DstKey, erldis_client:bin(Member));
+	smove(Client, SrcKey, DstKey, erldis_binaries:to_binary(Member));
 smove(Client, SrcKey, DstKey, Member) ->
 	erldis_client:call(Client, <<"smove ">>, [[SrcKey, DstKey, size(Member)], [Member]]).
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 zadd(Client, Key, Score, Member) ->
-	internal_zset_like(Client, <<"zadd ">>, Key, erldis_client:bin(Score), Member).
+	erldis_client:sr_scall(Client, bulk_cmd([<<"zadd">>, Key, Score], Member)).
 
-zrem(Client, Key, Member) -> internal_set_like(Client, <<"zrem ">>, Key, Member).
+zrem(Client, Key, Member) ->
+	erldis_client:sr_scall(Client, bulk_cmd([<<"zrem">>, Key], Member)).
 
 zincrby(Client, Key, By, Member) ->
-	% TODO: this & zscore need sr_scall like results instead of hd()
-	numeric(hd(internal_zset_like(Client, <<"zincrby ">>, Key, erldis_client:bin(By), Member))).
+	numeric(erldis_client:sr_scall(Client, bulk_cmd([<<"zincrby">>, Key, By], Member))).
 
 zrange(Client, Key, Start, End) ->
-	erldis_client:scall(Client, <<"zrange ">>, [Key, Start, End]).
+	erldis_client:scall(Client, inline_cmd([<<"zrange">>, Key, Start, End])).
 
 % TODO: return [{member, score}] for withscores functions
 %zrange_withscores(Client, Key, Start, End) ->
 %	erldis_client:scall(Client, <<"zrange ">>, [Key, Start, End, <<"withscores">>]).
 
 zrevrange(Client, Key, Start, End) ->
-	erldis_client:scall(Client, <<"zrevrange ">>, [Key, Start, End]).
+	erldis_client:scall(Client, inline_cmd([<<"zrevrange">>, Key, Start, End])).
 
 %zrevrange_withscores(Client, Key, Start, End) ->
 %	erldis_client:scall(Client, <<"zrevrange ">>, [Key, Start, End, <<"withscores">>]).
 
-%zrangebyscore(Client, Key, Min, Max) ->
-%	erldis_client:scall(Client, <<"zrangebyscore ">>, [Key, Min, Max]).
+zrangebyscore(Client, Key, Min, Max) ->
+	erldis_client:scall(Client, inline_cmd([<<"zrangebyscore ">>, Key, Min, Max])).
 
-%zrangebyscore(Client, Key, Min, Max, Offset, Count) ->
-%	Args = [Key, Min, Max, <<"limit">>, Offset, Count],
-%	erldis_client:scall(Client, <<"zrangebyscore ">>, Args).
+zrangebyscore(Client, Key, Min, Max, Offset, Count) ->
+	Cmd = inline_cmd([<<"zrangebyscore ">>, Key, Min, Max, <<"limit">>, Offset, Count]),
+	erldis_client:scall(Client, Cmd).
 
-zcard(Client, Key) -> numeric(erldis_client:sr_scall(Client, <<"zcard ">>, [Key])).
+zcard(Client, Key) ->
+	numeric(erldis_client:sr_scall(Client, inline_cmd(<<"zcard">>, Key))).
 
 zscore(Client, Key, Member) ->
-	numeric(hd(internal_set_like(Client, <<"zscore ">>, Key, Member))).
+	numeric(erldis_client:sr_scall(Client, bulk_cmd([<<"zscore">>, Key], Member))).
 
-%zremrangebyscore(Client, Key, Min, Max) ->
-%	numeric(erldis_client:sr_call(Client, <<"zremrangebyscore ">>, [Key, Min, Max])).
+zremrangebyscore(Client, Key, Min, Max) ->
+	Cmd = inline_cmd([<<"zremrangebyscore ">>, Key, Min, Max]),
+	numeric(erldis_client:sr_scall(Client, Cmd)).
+
+% TODO: use these for other commands, especially to replace internal_set_like
+% and reduce number of erldis_client:*call functions
+inline_cmd(Args) -> make_cmd([Args]).
+
+inline_cmd(Cmd, Key) -> inline_cmd([Cmd, Key]).
+
+bulk_cmd(Line1, Bulk) ->
+	Bin = erldis_binaries:to_binary(Bulk),
+	make_cmd([Line1 ++ [size(Bin)], [Bin]]).
+
+make_cmd(Lines) ->
+	BLines = [erldis_binaries:join(Line, <<" ">>) || Line <- Lines],
+	erldis_binaries:join(BLines, <<"\r\n">>).
 
 %%%%%%%%%%%%%
 %% Sorting %%

File src/erldis_binaries.erl

+-module(erldis_binaries).
+
+-export([to_binary/1, join/2]).
+
+to_binary(X) when is_list(X) -> list_to_binary(X);
+to_binary(X) when is_atom(X) -> list_to_binary(atom_to_list(X));
+to_binary(X) when is_binary(X) -> X;
+to_binary(X) when is_integer(X) -> list_to_binary(integer_to_list(X));
+to_binary(X) when is_float(X) -> list_to_binary(float_to_list(X));
+to_binary(X) -> term_to_binary(X).
+
+join([], _)->
+	<<>>;
+join(Array, Sep)->
+	F = fun(Elem, Acc) ->
+			E2 = to_binary(Elem),
+			<<Acc/binary, Sep/binary, E2/binary>>
+		end,
+	
+	Sz = size(Sep),
+	<<_:Sz/bytes, Result/binary>> = lists:foldl(F, <<>>, Array),
+	Result.

File src/erldis_client.erl

 -export([start_link/0, start_link/1, start_link/2, start_link/3, start_link/4]).
 -export([init/1, handle_call/3, handle_cast/2, handle_info/2,
 		 terminate/2, code_change/3]).
--export([bin/1, format/2, format/1, sformat/1]).
+-export([format/2, format/1, sformat/1]).
 -define(EOL, "\r\n").
 
 -define(default_timeout, 5000). %% same as in gen.erl in stdlib
 %% helpers %%
 %%%%%%%%%%%%%
 
-bin(X) when is_list(X) ->
-	list_to_binary(X);
-bin(X) when is_atom(X) ->
-	list_to_binary(atom_to_list(X));
-bin(X) when is_binary(X) ->
-	X;
-bin(X) when is_integer(X) ->
-	list_to_binary(integer_to_list(X));
-bin(X) when is_float(X) ->
-	list_to_binary(float_to_list(X));
-bin(X) ->
-	term_to_binary(X).
-
-format(Lines) ->
-	format(Lines, <<>>).
+format(Lines) -> format(Lines, <<>>).
 
 format([], Result) ->
 	Result;
 format([Line|Rest], <<>>) ->
-	JoinedLine = binary_join(Line, <<" ">>),
-	format(Rest, JoinedLine);
+	format(Rest, erldis_binaries:join(Line, <<" ">>));
 format([Line|Rest], Result) ->
-	Sep = <<?EOL>>,
-	JoinedLine = binary_join(Line, <<" ">>),
-	format(Rest, <<Result/binary, Sep/binary, JoinedLine/binary>>).
+	JoinedLine = erldis_binaries:join(Line, <<" ">>),
+	format(Rest, <<Result/binary, "\r\n", JoinedLine/binary>>).
 
-sformat(<<>>)->
-	<<>>;
-sformat(Line) ->
-	format([Line], <<>>).
-
-binary_join([], _)->
-	<<>>;
-binary_join(Array, Sep)->
-	F = fun(Elem, Acc) ->
-			E2 = bin(Elem),
-			<<Acc/binary, Sep/binary, E2/binary>>
-		end,
-	
-	Sz = size(Sep),
-	<<_:Sz/bytes, Result/binary>> = lists:foldl(F, <<>>, Array),
-	Result.
+sformat(<<>>)-> <<>>;
+sformat(Line) -> format([Line], <<>>).
 
 trim2({ok, S}) ->
 	Read = size(S)-2,
 %%%%%%%%%%%%%%%%%%%
 
 select(Client, DB) ->
-	DBB = list_to_binary(integer_to_list(DB)),
+	DBB = erldis_binaries:to_binary(DB),
 	[ok] = scall(Client, <<"select ", DBB/binary>>),
 	Client.
 
 set_call(Client, Cmd, Key, Val) when is_binary(Val) ->
 	call(Client, Cmd, [[Key, erlang:size(Val)], [Val]]);
 set_call(Client, Cmd, Key, Val) ->
-	set_call(Client, Cmd, Key, bin(Val)).
+	set_call(Client, Cmd, Key, erldis_binaries:to_binary(Val)).
 
 % Erlang uses milliseconds, with symbol "infinity" for "wait forever";
 % redis uses seconds, with 0 for "wait forever".

File test/erldis_tests.erl

 	false = is_process_alive(Client).
 
 utils_test() ->
-	?assertEqual(<<"1">>, erldis_client:bin(1)),
-	?assertEqual(<<"atom">>, erldis_client:bin(atom)),
+	?assertEqual(<<"1">>, erldis_binaries:to_binary(1)),
+	?assertEqual(<<"atom">>, erldis_binaries:to_binary(atom)),
 	?assertEqual(<<"1 2 3">>, erldis_client:format([[1, 2, 3]])),
 	?assertEqual(<<"1 2 3\r\n4 5 6">>, erldis_client:format([[1,2,3], [4,5,6]])).
 
 	
 	?assertEqual(0, erldis:zcard(Client, <<"foo">>)),
 	?assertEqual([], erldis:zrange(Client, <<"foo">>, 0, 1)),
+	?assertEqual(0, erldis:zscore(Client, <<"foo">>, <<"elem1">>)),
+	
 	?assertEqual(true, erldis:zadd(Client, <<"foo">>, 5, <<"elem1">>)),
 	?assertEqual([<<"elem1">>], erldis:zrange(Client, <<"foo">>, 0, 1)),
+	?assertEqual([<<"elem1">>], erldis:zrevrange(Client, <<"foo">>, 0, 1)),
 	?assertEqual(false, erldis:zadd(Client, <<"foo">>, 6, <<"elem1">>)),
 	?assertEqual(1, erldis:zcard(Client, <<"foo">>)),
 	?assertEqual(6, erldis:zscore(Client, <<"foo">>, <<"elem1">>)),
 	?assertEqual(8, erldis:zincrby(Client, <<"foo">>, 2, <<"elem1">>)),
+	% can use list keys & values too
+	?assertEqual(true, erldis:zadd(Client, "foo", 1.5, "a-elem")),
+	?assertEqual(2, erldis:zcard(Client, "foo")),
+	?assertEqual(1.5, erldis:zscore(Client, "foo", "a-elem")),
+	?assertEqual([<<"a-elem">>, <<"elem1">>], erldis:zrange(Client, "foo", 0, 2)),
+	?assertEqual([<<"elem1">>, <<"a-elem">>], erldis:zrevrange(Client, "foo", 0, 2)),
+	?assertEqual([<<"a-elem">>], erldis:zrangebyscore(Client, "foo", 1.0, 2.0)),
+	?assertEqual([<<"a-elem">>], erldis:zrangebyscore(Client, "foo", 1, 10, 0, 1)),
+	?assertEqual([<<"a-elem">>, <<"elem1">>], erldis:zrangebyscore(Client, "foo", 1, 10, 0, 2)),
+	?assertEqual([<<"elem1">>], erldis:zrangebyscore(Client, "foo", 1, 10, 1, 2)),
+	?assertEqual([], erldis:zrangebyscore(Client, "foo", 1, 10, 2, 2)),
+	?assertEqual(1, erldis:zremrangebyscore(Client, "foo", 1, 2)),
+	?assertEqual(false, erldis:zrem(Client, "foo", "a-elem")),
+	?assertEqual(1, erldis:zcard(Client, "foo")),
+	?assertEqual([<<"elem1">>], erldis:zrevrange(Client, "foo", 0, 1)),
+	
 	?assertEqual(true, erldis:zrem(Client, <<"foo">>, <<"elem1">>)),
 	?assertEqual(false, erldis:zrem(Client, <<"foo">>, <<"elem1">>)),
 	?assertEqual(0, erldis:zcard(Client, <<"foo">>)),