2014-04-09 00:41:11 +00:00
|
|
|
%% -------------------------------------------------------------------
|
|
|
|
%%
|
|
|
|
%% Copyright (c) 2013-2014 Basho Technologies, Inc.
|
|
|
|
%%
|
|
|
|
%% This file is provided to you under the Apache License,
|
|
|
|
%% Version 2.0 (the "License"); you may not use this file
|
|
|
|
%% except in compliance with the License. You may obtain
|
|
|
|
%% a copy of the License at
|
|
|
|
%%
|
|
|
|
%% http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
%%
|
|
|
|
%% Unless required by applicable law or agreed to in writing,
|
|
|
|
%% software distributed under the License is distributed on an
|
|
|
|
%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
|
|
%% KIND, either express or implied. See the License for the
|
|
|
|
%% specific language governing permissions and limitations
|
|
|
|
%% under the License.
|
|
|
|
%%
|
|
|
|
%% -------------------------------------------------------------------
|
|
|
|
|
|
|
|
-module(ensemble_util).
|
|
|
|
-compile(export_all).
|
|
|
|
|
2014-06-09 14:58:34 +00:00
|
|
|
-define(DEFAULT_RING_SIZE, 16).
|
|
|
|
|
2014-04-09 00:41:11 +00:00
|
|
|
-include_lib("eunit/include/eunit.hrl").
|
|
|
|
|
|
|
|
build_cluster(Num, Config, NVal) ->
|
|
|
|
Nodes = rt:deploy_nodes(Num, Config),
|
|
|
|
Node = hd(Nodes),
|
|
|
|
rt:join_cluster(Nodes),
|
|
|
|
ensemble_util:wait_until_cluster(Nodes),
|
|
|
|
ensemble_util:wait_for_membership(Node),
|
|
|
|
ensemble_util:wait_until_stable(Node, NVal),
|
|
|
|
Nodes.
|
|
|
|
|
2014-06-09 14:58:34 +00:00
|
|
|
build_cluster_without_quorum(Num, Config) ->
|
|
|
|
Nodes = rt:deploy_nodes(Num, Config),
|
|
|
|
SetupLogCaptureFun = fun(Node) ->
|
|
|
|
rt:setup_log_capture(Node)
|
|
|
|
end,
|
|
|
|
lists:map(SetupLogCaptureFun, Nodes),
|
|
|
|
Node = hd(Nodes),
|
|
|
|
ok = rpc:call(Node, riak_ensemble_manager, enable, []),
|
|
|
|
_ = rpc:call(Node, riak_core_ring_manager, force_update, []),
|
|
|
|
rt:join_cluster(Nodes),
|
|
|
|
ensemble_util:wait_until_cluster(Nodes),
|
|
|
|
ensemble_util:wait_for_membership(Node),
|
|
|
|
Nodes.
|
|
|
|
|
2014-04-09 00:41:11 +00:00
|
|
|
fast_config(NVal) ->
|
2014-06-09 14:58:34 +00:00
|
|
|
fast_config(NVal, ?DEFAULT_RING_SIZE).
|
2014-04-09 00:41:11 +00:00
|
|
|
|
2014-06-09 14:58:34 +00:00
|
|
|
fast_config(Nval, RingSize) when is_integer(RingSize) ->
|
|
|
|
fast_config(Nval, RingSize, true);
|
|
|
|
fast_config(Nval, EnableAAE) when is_boolean(EnableAAE) ->
|
|
|
|
fast_config(Nval, ?DEFAULT_RING_SIZE, EnableAAE).
|
|
|
|
|
|
|
|
fast_config(NVal, RingSize, EnableAAE) ->
|
|
|
|
[config_aae(EnableAAE),
|
2014-04-09 00:41:11 +00:00
|
|
|
{riak_core, [{default_bucket_props, [{n_val, NVal}]},
|
|
|
|
{vnode_management_timer, 1000},
|
|
|
|
{ring_creation_size, RingSize},
|
|
|
|
{enable_consensus, true}]}].
|
|
|
|
|
2014-06-09 14:58:34 +00:00
|
|
|
config_aae(true) ->
|
|
|
|
{riak_kv, [{anti_entropy_build_limit, {100, 1000}},
|
|
|
|
{anti_entropy_concurrency, 100},
|
|
|
|
{anti_entropy_tick, 100},
|
|
|
|
{anti_entropy, {on, []}},
|
|
|
|
{anti_entropy_timeout, 5000},
|
|
|
|
{storage_backend, riak_kv_memory_backend}]};
|
|
|
|
config_aae(false) ->
|
|
|
|
{riak_kv, [{anti_entropy, {off, []}}]}.
|
|
|
|
|
2014-04-09 00:41:11 +00:00
|
|
|
ensembles(Node) ->
|
|
|
|
rpc:call(Node, riak_kv_ensembles, ensembles, []).
|
|
|
|
|
|
|
|
get_leader_pid(Node, Ensemble) ->
|
|
|
|
rpc:call(Node, riak_ensemble_manager, get_leader_pid, [Ensemble]).
|
|
|
|
|
2014-06-20 03:26:30 +00:00
|
|
|
peers(Node) ->
|
|
|
|
rpc:call(Node, riak_ensemble_peer_sup, peers, []).
|
|
|
|
|
2014-04-09 00:41:11 +00:00
|
|
|
kill_leader(Node, Ensemble) ->
|
|
|
|
case get_leader_pid(Node, Ensemble) of
|
|
|
|
undefined ->
|
|
|
|
ok;
|
|
|
|
Pid ->
|
|
|
|
exit(Pid, kill),
|
|
|
|
ok
|
|
|
|
end.
|
|
|
|
|
|
|
|
kill_leaders(Node, Ensembles) ->
|
|
|
|
_ = [kill_leader(Node, Ensemble) || Ensemble <- Ensembles],
|
|
|
|
ok.
|
|
|
|
|
|
|
|
wait_until_cluster(Nodes) ->
|
|
|
|
lager:info("Waiting until riak_ensemble cluster includes all nodes"),
|
|
|
|
Node = hd(Nodes),
|
|
|
|
F = fun() ->
|
|
|
|
case rpc:call(Node, riak_ensemble_manager, cluster, []) of
|
|
|
|
Nodes ->
|
|
|
|
true;
|
|
|
|
_ ->
|
|
|
|
false
|
|
|
|
end
|
|
|
|
end,
|
|
|
|
?assertEqual(ok, rt:wait_until(F)),
|
|
|
|
lager:info("....cluster ready"),
|
|
|
|
ok.
|
|
|
|
|
|
|
|
wait_until_stable(Node, Count) ->
|
|
|
|
lager:info("Waiting until all ensembles are stable"),
|
|
|
|
Ensembles = rpc:call(Node, riak_kv_ensembles, ensembles, []),
|
|
|
|
wait_until_quorum(Node, root),
|
|
|
|
[wait_until_quorum(Node, Ensemble) || Ensemble <- Ensembles],
|
|
|
|
[wait_until_quorum_count(Node, Ensemble, Count) || Ensemble <- Ensembles],
|
|
|
|
lager:info("....all stable"),
|
|
|
|
ok.
|
|
|
|
|
|
|
|
wait_until_quorum(Node, Ensemble) ->
|
|
|
|
F = fun() ->
|
2014-06-02 20:40:19 +00:00
|
|
|
case rpc:call(Node, riak_ensemble_manager, check_quorum,
|
|
|
|
[Ensemble, 10000]) of
|
2014-04-09 00:41:11 +00:00
|
|
|
true ->
|
|
|
|
true;
|
|
|
|
false ->
|
|
|
|
lager:info("Not ready: ~p", [Ensemble]),
|
|
|
|
false
|
|
|
|
end
|
|
|
|
end,
|
|
|
|
?assertEqual(ok, rt:wait_until(F)).
|
|
|
|
|
|
|
|
wait_until_quorum_count(Node, Ensemble, Want) ->
|
|
|
|
F = fun() ->
|
2014-06-02 20:40:19 +00:00
|
|
|
case rpc:call(Node, riak_ensemble_manager, count_quorum,
|
|
|
|
[Ensemble, 10000]) of
|
2014-04-09 00:41:11 +00:00
|
|
|
Count when Count >= Want ->
|
|
|
|
true;
|
|
|
|
Count ->
|
|
|
|
lager:info("Count: ~p :: ~p < ~p", [Ensemble, Count, Want]),
|
|
|
|
false
|
|
|
|
end
|
|
|
|
end,
|
|
|
|
?assertEqual(ok, rt:wait_until(F)).
|
|
|
|
|
|
|
|
wait_for_membership(Node) ->
|
|
|
|
lager:info("Waiting until ensemble membership matches ring ownership"),
|
|
|
|
F = fun() ->
|
|
|
|
case rpc:call(Node, riak_kv_ensembles, check_membership, []) of
|
|
|
|
Results when is_list(Results) ->
|
|
|
|
[] =:= [x || false <- Results];
|
|
|
|
_ ->
|
|
|
|
false
|
|
|
|
end
|
|
|
|
end,
|
|
|
|
?assertEqual(ok, rt:wait_until(F)),
|
|
|
|
lager:info("....ownership matches"),
|
|
|
|
ok.
|