Current section
Files
Jump to
Current section
Files
src/erc.erl
-module(erc).
-export([get_cluster_slots/2, parse_cluster_slots/1]).
-export([get_node_index/2, get_node_by_slot/2]).
-export([get_key_from_command/1, calc_slot_by_key/1, get_hash_tag/1]).
get_cluster_slots([], _CallbackMod) ->
[];
get_cluster_slots([{Host, Port}|T], CallbackMod) ->
case apply(CallbackMod, get_cluster_slots, [Host, Port]) of
{ok, ClusterInfo} -> parse_cluster_slots(ClusterInfo);
_ -> get_cluster_slots(T, CallbackMod)
end.
parse_cluster_slots(ClusterInfo) ->
parse_cluster_slots(ClusterInfo, []).
parse_cluster_slots([[StartSlot, EndSlot | [[PrimaryAddress, PrimaryPort | _] | _]] | T], Acc) ->
Node = {ensure_integer(StartSlot), ensure_integer(EndSlot),
PrimaryAddress, ensure_integer(PrimaryPort)},
parse_cluster_slots(T, [Node | Acc]);
parse_cluster_slots([], Acc) ->
lists:reverse(Acc).
get_node_index(Mapping, Command) ->
Key = get_key_from_command(Command),
Slot = calc_slot_by_key(Key),
Index = get_node_by_slot(Mapping, Slot),
Index.
get_node_by_slot([], _Slot) ->
undefined;
get_node_by_slot([{Start, End, Host, Port}|_], Slot) when Start =< Slot andalso Slot =< End ->
{Host, Port};
get_node_by_slot([_|T], Slot) ->
get_node_by_slot(T, Slot).
% Commands not suitable for cluster mode will NOT succeed
get_key_from_command([_Command, Key|_]) ->
Key.
calc_slot_by_key(Key) ->
case get_hash_tag(Key) of
undefined -> erc_hash:hash(Key);
HashTag -> erc_hash:hash(HashTag)
end.
get_hash_tag(Key) ->
case re:run(Key, <<"{(.*)}">>, [{capture, all_but_first, binary}]) of
{match, [HashTag]} when HashTag =/= <<>> -> HashTag;
_ -> undefined
end.
ensure_integer(Val) when is_binary(Val) ->
binary_to_integer(Val);
ensure_integer(Val) when is_list(Val) ->
list_to_integer(Val);
ensure_integer(Val) when is_integer(Val) ->
Val.