Skip to content
This repository has been archived by the owner on Sep 19, 2019. It is now read-only.

Commit

Permalink
Explicit zone placement
Browse files Browse the repository at this point in the history
  • Loading branch information
Robert Newson committed Sep 27, 2012
1 parent e108c74 commit d5f5ff2
Showing 1 changed file with 45 additions and 19 deletions.
64 changes: 45 additions & 19 deletions src/mem3.erl
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -137,27 +137,53 @@ choose_shards(DbName, Options) ->
try shards(DbName) try shards(DbName)
catch error:E when E==database_does_not_exist; E==badarg -> catch error:E when E==database_does_not_exist; E==badarg ->
Nodes = mem3:nodes(), Nodes = mem3:nodes(),
NodeCount = length(Nodes), case get_placement(Options) of
Zones = zones(Nodes), undefined ->
ZoneCount = length(Zones), choose_shards(DbName, Nodes, Options);
if ZoneCount =:= 0 -> erlang:error(no_available_zones); true -> ok end, Placement ->
N = mem3_util:n_val(couch_util:get_value(n, Options), NodeCount), lists:flatmap(fun({Zone, N}) ->
Q = mem3_util:to_integer(couch_util:get_value(q, Options, NodesInZone = nodes_in_zone(Nodes, Zone),
couch_config:get("cluster", "q", "8"))), Options1 = lists:keymerge(1, [{n,N}], Options),
Z = mem3_util:z_val(couch_util:get_value(z, Options), NodeCount, ZoneCount), choose_shards(DbName, NodesInZone, Options1)
Suffix = couch_util:get_value(shard_suffix, Options, ""), end, Placement)
ChosenZones = lists:sublist(shuffle(Zones), Z), end
lists:flatmap(
fun({Zone, N1}) ->
Nodes1 = nodes_in_zone(Nodes, Zone),
{A, B} = lists:split(crypto:rand_uniform(1,length(Nodes1)+1), Nodes1),
RotatedNodes = B ++ A,
mem3_util:create_partition_map(DbName, erlang:min(N1,length(Nodes1)),
Q, RotatedNodes, Suffix)
end,
lists:zip(ChosenZones, apportion(N, Z)))
end. end.


choose_shards(DbName, Nodes, Options) ->
NodeCount = length(Nodes),
Suffix = couch_util:get_value(shard_suffix, Options, ""),
N = mem3_util:n_val(couch_util:get_value(n, Options), NodeCount),
if N =:= 0 -> erlang:error(no_nodes_in_zone);
true -> ok
end,
Q = mem3_util:to_integer(couch_util:get_value(q, Options,
couch_config:get("cluster", "q", "8"))),
%% rotate to a random entry in the nodelist for even distribution
{A, B} = lists:split(crypto:rand_uniform(1,length(Nodes)+1), Nodes),
RotatedNodes = B ++ A,
mem3_util:create_partition_map(DbName, N, Q, RotatedNodes, Suffix).

%% either directly as [{term(), non_neg_integer()}] or
%% a config setting as "a:2,b:1"
get_placement(Options) ->
case couch_util:get_value(placement, Options) of
undefined ->
case couch_config:get("cluster", "placement") of
undefined ->
undefined;
PlacementStr ->
decode_placement_string(PlacementStr)
end;
Placement ->
Placement
end.

decode_placement_string(PlacementStr) ->
[begin
[Zone, N] = string:tokens(Rule, ":"),
{list_to_binary(Zone), list_to_integer(N)}
end || Rule <- string:tokens(PlacementStr, ",")].

-spec dbname(#shard{} | iodata()) -> binary(). -spec dbname(#shard{} | iodata()) -> binary().
dbname(#shard{dbname = DbName}) -> dbname(#shard{dbname = DbName}) ->
DbName; DbName;
Expand Down

0 comments on commit d5f5ff2

Please sign in to comment.