2013-02-07 16:45:55 +00:00
|
|
|
%% -------------------------------------------------------------------
|
|
|
|
%%
|
|
|
|
%% Copyright (c) 2012 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.
|
|
|
|
%%
|
|
|
|
%% -------------------------------------------------------------------
|
2012-07-25 17:21:44 +00:00
|
|
|
-module(loaded_upgrade).
|
2013-02-05 19:29:25 +00:00
|
|
|
|
2012-07-25 17:21:44 +00:00
|
|
|
-include_lib("eunit/include/eunit.hrl").
|
2012-08-28 13:54:56 +00:00
|
|
|
|
2013-02-05 19:29:25 +00:00
|
|
|
-export([confirm/0]).
|
|
|
|
|
|
|
|
-export([kv_valgen/1, bucket/1, erlang_mr/0, int_to_key/1]).
|
2012-07-25 17:21:44 +00:00
|
|
|
|
2014-01-07 22:56:20 +00:00
|
|
|
-define(TIME_BETWEEN_UPGRADES, 120). %% Seconds!
|
2012-11-07 14:58:41 +00:00
|
|
|
|
2013-02-05 19:29:25 +00:00
|
|
|
confirm() ->
|
|
|
|
|
|
|
|
case whereis(loaded_upgrade) of
|
|
|
|
undefined -> meh;
|
|
|
|
_ -> unregister(loaded_upgrade)
|
2014-01-07 22:56:20 +00:00
|
|
|
end,
|
2013-02-05 19:29:25 +00:00
|
|
|
register(loaded_upgrade, self()),
|
|
|
|
%% Build Cluster
|
2012-11-13 15:28:12 +00:00
|
|
|
TestMetaData = riak_test_runner:metadata(),
|
2012-11-15 19:46:18 +00:00
|
|
|
%% Only run 2i for level
|
2012-11-07 14:58:41 +00:00
|
|
|
Backend = proplists:get_value(backend, TestMetaData),
|
2012-11-15 19:46:18 +00:00
|
|
|
OldVsn = proplists:get_value(upgrade_version, TestMetaData, previous),
|
2012-11-07 14:58:41 +00:00
|
|
|
|
2013-02-05 19:29:25 +00:00
|
|
|
Config = [{riak_search, [{enabled, true}]}, {riak_pipe, [{worker_limit, 200}]}],
|
2012-07-25 17:21:44 +00:00
|
|
|
NumNodes = 4,
|
2013-02-05 19:29:25 +00:00
|
|
|
Vsns = [{OldVsn, Config} || _ <- lists:seq(1,NumNodes)],
|
|
|
|
Nodes = rt:build_cluster(Vsns),
|
|
|
|
|
|
|
|
seed_cluster(Nodes),
|
2014-01-07 22:56:20 +00:00
|
|
|
|
2013-02-05 19:29:25 +00:00
|
|
|
%% Now we have a cluster!
|
|
|
|
%% Let's spawn workers against it.
|
2013-04-26 15:02:23 +00:00
|
|
|
Concurrent = rt_config:get(load_workers, 10),
|
2013-02-08 04:20:43 +00:00
|
|
|
|
2014-01-07 22:56:20 +00:00
|
|
|
Sups = [{rt_worker_sup:start_link([{concurrent, Concurrent},
|
|
|
|
{node, Node},
|
|
|
|
{backend, Backend},
|
|
|
|
{version, OldVsn},
|
|
|
|
{report_pid, self()}]), Node} || Node <- Nodes],
|
2013-02-05 19:29:25 +00:00
|
|
|
|
|
|
|
upgrade_recv_loop(),
|
2012-07-25 17:21:44 +00:00
|
|
|
|
|
|
|
[begin
|
2014-01-07 22:56:20 +00:00
|
|
|
exit(Sup, normal),
|
|
|
|
lager:info("Upgrading ~p", [Node]),
|
|
|
|
rt:upgrade(Node, current),
|
|
|
|
rt:wait_for_service(Node, [riak_search,riak_kv,riak_pipe]),
|
|
|
|
{ok, NewSup} = rt_worker_sup:start_link([{concurrent, Concurrent},
|
|
|
|
{node, Node},
|
|
|
|
{backend, Backend},
|
|
|
|
{version, current},
|
|
|
|
{report_pid, self()}]),
|
|
|
|
_NodeMon = init_node_monitor(Node, NewSup, self()),
|
|
|
|
upgrade_recv_loop()
|
|
|
|
end || {{ok, Sup}, Node} <- Sups],
|
2013-02-05 19:29:25 +00:00
|
|
|
pass.
|
2013-01-21 22:57:38 +00:00
|
|
|
|
2013-02-05 19:29:25 +00:00
|
|
|
upgrade_recv_loop() ->
|
|
|
|
{SMega, SSec, SMicro} = os:timestamp(),
|
|
|
|
EndSecs = SSec + ?TIME_BETWEEN_UPGRADES,
|
|
|
|
EndTime = case EndSecs > 1000000 of
|
2014-01-07 22:56:20 +00:00
|
|
|
true ->
|
|
|
|
{SMega + 1, EndSecs - 1000000, SMicro};
|
|
|
|
_ ->
|
|
|
|
{SMega, EndSecs, SMicro}
|
|
|
|
end,
|
2013-02-05 19:29:25 +00:00
|
|
|
upgrade_recv_loop(EndTime).
|
|
|
|
|
2013-02-07 16:38:06 +00:00
|
|
|
%% TODO: Collect error message counts in ets table
|
2013-02-05 19:29:25 +00:00
|
|
|
upgrade_recv_loop(EndTime) ->
|
|
|
|
Now = os:timestamp(),
|
|
|
|
case Now > EndTime of
|
|
|
|
true ->
|
|
|
|
lager:info("Done waiting 'cause ~p > ~p", [Now, EndTime]);
|
2012-07-25 17:21:44 +00:00
|
|
|
_ ->
|
2014-01-07 22:56:20 +00:00
|
|
|
receive
|
|
|
|
{mapred, Node, bad_result} ->
|
|
|
|
?assertEqual(true, {mapred, Node, bad_result});
|
|
|
|
{kv, Node, not_equal} ->
|
|
|
|
?assertEqual(true, {kv, Node, bad_result});
|
|
|
|
{kv, Node, {notfound, Key}} ->
|
|
|
|
?assertEqual(true, {kv, Node, {notfound, Key}});
|
|
|
|
{listkeys, Node, not_equal} ->
|
|
|
|
?assertEqual(true, {listkeys, Node, not_equal});
|
|
|
|
{search, Node, bad_result} ->
|
|
|
|
?assertEqual(true, {search, Node, bad_result});
|
|
|
|
Msg ->
|
|
|
|
lager:debug("Received Mesg ~p", [Msg]),
|
|
|
|
upgrade_recv_loop(EndTime)
|
|
|
|
after timer:now_diff(EndTime, Now) div 1000 ->
|
|
|
|
lager:info("Done waiting 'cause ~p is up", [?TIME_BETWEEN_UPGRADES])
|
|
|
|
end
|
2012-07-25 17:21:44 +00:00
|
|
|
end.
|
|
|
|
|
2013-02-07 16:38:06 +00:00
|
|
|
seed_cluster(Nodes=[Node1|_]) ->
|
2013-02-05 19:29:25 +00:00
|
|
|
lager:info("Seeding Cluster"),
|
2012-08-08 19:54:53 +00:00
|
|
|
|
2013-02-05 19:29:25 +00:00
|
|
|
%% For List Keys
|
|
|
|
lager:info("Writing 100 keys to ~p", [Node1]),
|
|
|
|
rt:systest_write(Node1, 100, 3),
|
|
|
|
?assertEqual([], rt:systest_read(Node1, 100, 1)),
|
2012-07-27 20:17:57 +00:00
|
|
|
|
2013-02-07 16:38:06 +00:00
|
|
|
seed(Node1, 0, 100, fun(Key) ->
|
2014-01-07 22:56:20 +00:00
|
|
|
Bin = iolist_to_binary(io_lib:format("~p", [Key])),
|
|
|
|
riakc_obj:new(<<"objects">>, Bin, Bin)
|
|
|
|
end),
|
2012-07-27 20:17:57 +00:00
|
|
|
|
2013-02-05 19:29:25 +00:00
|
|
|
%% For KV
|
2013-02-07 16:38:06 +00:00
|
|
|
kv_seed(Node1),
|
2012-11-03 16:32:42 +00:00
|
|
|
|
2013-02-05 19:29:25 +00:00
|
|
|
%% for 2i
|
2013-02-07 16:38:06 +00:00
|
|
|
twoi_seed(Node1),
|
2012-11-03 16:32:42 +00:00
|
|
|
|
2013-02-05 19:29:25 +00:00
|
|
|
%% for mapred
|
2013-02-07 16:38:06 +00:00
|
|
|
mr_seed(Node1),
|
2012-11-03 16:32:42 +00:00
|
|
|
|
2013-02-05 19:29:25 +00:00
|
|
|
%% For MC Serch
|
|
|
|
rt:enable_search_hook(Node1, bucket(search)),
|
2013-02-07 16:38:06 +00:00
|
|
|
rt:wait_until_ring_converged(Nodes),
|
|
|
|
seed_search(Node1).
|
2012-11-03 16:32:42 +00:00
|
|
|
|
2013-02-05 19:29:25 +00:00
|
|
|
%% Buckets
|
|
|
|
bucket(kv) -> <<"utest">>;
|
|
|
|
bucket(twoi) -> <<"2ibuquot">>;
|
|
|
|
bucket(mapred) -> <<"bryanitbs">>;
|
|
|
|
bucket(search) -> <<"scotts_spam">>.
|
|
|
|
|
2013-02-07 16:38:06 +00:00
|
|
|
seed_search(Node) ->
|
|
|
|
Pid = rt:pbc(Node),
|
2013-04-26 15:02:23 +00:00
|
|
|
SpamDir = rt_config:get(spam_dir),
|
2013-02-05 19:29:25 +00:00
|
|
|
Files = case SpamDir of
|
2014-01-07 22:56:20 +00:00
|
|
|
undefined -> undefined;
|
|
|
|
_ -> filelib:wildcard(SpamDir ++ "/*")
|
|
|
|
end,
|
2013-02-07 16:38:06 +00:00
|
|
|
seed_search(Pid, Files),
|
|
|
|
riakc_pb_socket:stop(Pid).
|
2013-02-05 19:29:25 +00:00
|
|
|
|
|
|
|
seed_search(_Pid, []) -> ok;
|
|
|
|
seed_search(Pid, [File|Files]) ->
|
|
|
|
Key = list_to_binary(filename:basename(File)),
|
|
|
|
rt:pbc_put_file(Pid, bucket(search), Key, File),
|
|
|
|
seed_search(Pid, Files).
|
|
|
|
|
2013-02-07 16:38:06 +00:00
|
|
|
kv_seed(Node) ->
|
|
|
|
ValFun = fun(Key) ->
|
2014-01-07 22:56:20 +00:00
|
|
|
riakc_obj:new(bucket(kv), iolist_to_binary(io_lib:format("~p", [Key])), kv_valgen(Key))
|
|
|
|
end,
|
2013-02-07 16:38:06 +00:00
|
|
|
seed(Node, 0, 7999, ValFun).
|
2013-02-05 19:29:25 +00:00
|
|
|
|
|
|
|
kv_valgen(Key) ->
|
|
|
|
term_to_binary(lists:seq(0, Key)).
|
|
|
|
|
|
|
|
int_to_key(KInt) ->
|
|
|
|
list_to_binary(["", integer_to_list(KInt)]).
|
|
|
|
|
|
|
|
%% Every 2i seeded object will have indexes
|
|
|
|
%% int_plusone -> [Key + 1, Key + 10000]
|
|
|
|
%% bin_plustwo -> [<<"Key + 2">>]
|
2013-02-07 16:38:06 +00:00
|
|
|
twoi_seed(Node) ->
|
|
|
|
ValFun = fun(Key) ->
|
2014-01-07 22:56:20 +00:00
|
|
|
Obj = riakc_obj:new(bucket(twoi), iolist_to_binary(io_lib:format("~p", [Key])), kv_valgen(Key)),
|
|
|
|
MD1 = riakc_obj:get_update_metadata(Obj),
|
|
|
|
MD2 = riakc_obj:set_secondary_index(MD1, [
|
|
|
|
{{integer_index, "plusone"}, [Key + 1, Key + 10000]},
|
|
|
|
{{binary_index, "plustwo"}, [int_to_key(Key + 2)]}
|
|
|
|
]),
|
|
|
|
riakc_obj:update_metadata(Obj, MD2)
|
|
|
|
end,
|
2013-02-07 16:38:06 +00:00
|
|
|
seed(Node, 0, 7999, ValFun).
|
2013-02-05 19:29:25 +00:00
|
|
|
|
|
|
|
erlang_mr() ->
|
|
|
|
[{map, {modfun, riak_kv_mapreduce, map_object_value}, none, false},
|
2014-01-07 22:56:20 +00:00
|
|
|
{reduce, {modfun, riak_kv_mapreduce, reduce_count_inputs}, none, true}].
|
2013-02-05 19:29:25 +00:00
|
|
|
|
2013-02-07 16:38:06 +00:00
|
|
|
mr_seed(Node) ->
|
2014-01-07 22:56:20 +00:00
|
|
|
%% to be used along with sequential_int keygen to populate known
|
|
|
|
%% mapreduce set
|
2013-02-07 16:38:06 +00:00
|
|
|
ValFun = fun(Key) ->
|
2014-01-07 22:56:20 +00:00
|
|
|
Value = iolist_to_binary(io_lib:format("~p", [Key])),
|
|
|
|
riakc_obj:new(bucket(mapred), Value, Value)
|
|
|
|
end,
|
2013-02-07 16:38:06 +00:00
|
|
|
seed(Node, 0, 9999, ValFun).
|
|
|
|
|
|
|
|
seed(Node, Start, End, ValFun) ->
|
|
|
|
PBC = rt:pbc(Node),
|
|
|
|
|
2013-02-05 19:29:25 +00:00
|
|
|
[ begin
|
2014-01-07 22:56:20 +00:00
|
|
|
Obj = ValFun(Key),
|
|
|
|
riakc_pb_socket:put(PBC, Obj, [{w,3}])
|
|
|
|
end || Key <- lists:seq(Start, End)],
|
2012-07-25 17:21:44 +00:00
|
|
|
|
2013-02-07 16:38:06 +00:00
|
|
|
riakc_pb_socket:stop(PBC).
|
2013-02-06 19:44:15 +00:00
|
|
|
|
|
|
|
%% ===================================================================
|
|
|
|
%% Monitor nodes after they upgrade
|
|
|
|
%% ===================================================================
|
2013-02-07 19:15:18 +00:00
|
|
|
init_node_monitor(Node, Sup, TestProc) ->
|
|
|
|
spawn_link(fun() -> node_monitor(Node, Sup, TestProc) end).
|
2013-02-06 19:44:15 +00:00
|
|
|
|
2013-02-07 19:15:18 +00:00
|
|
|
node_monitor(Node, Sup, TestProc) ->
|
2013-02-06 19:44:15 +00:00
|
|
|
lager:info("Monitoring node ~p to make sure it stays up.", [Node]),
|
|
|
|
erlang:process_flag(trap_exit, true),
|
|
|
|
erlang:monitor_node(Node, true),
|
2013-02-07 19:15:18 +00:00
|
|
|
node_monitor_loop(Node, Sup, TestProc).
|
2013-02-06 19:44:15 +00:00
|
|
|
|
2013-02-07 19:15:18 +00:00
|
|
|
node_monitor_loop(Node, Sup, TestProc) ->
|
2013-02-06 19:44:15 +00:00
|
|
|
receive
|
|
|
|
{nodedown, Node} ->
|
|
|
|
lager:error("Node ~p exited after upgrade!", [Node]),
|
2013-02-07 19:15:18 +00:00
|
|
|
exit(Sup, normal),
|
2013-02-06 19:44:15 +00:00
|
|
|
?assertEqual(nodeup, {nodedown, Node});
|
|
|
|
{'EXIT', TestProc, _} ->
|
|
|
|
erlang:monitor_node(Node, false),
|
|
|
|
ok;
|
|
|
|
Other ->
|
|
|
|
lager:warn("Node monitor for ~p got unknown message ~p", [Node, Other]),
|
2013-02-07 19:15:18 +00:00
|
|
|
node_monitor_loop(Node, Sup, TestProc)
|
2013-02-06 19:44:15 +00:00
|
|
|
end.
|