Add cluster_info to deps and small callback module
For debuging from shell, some functions in machi_cinfo are exported: - public_projection/1 - private_projection/1 - fitness/1 - chain_manager/1 - flu1/1
This commit is contained in:
parent
f04e7f7132
commit
208c02853f
8 changed files with 206 additions and 10 deletions
|
@ -9,7 +9,8 @@
|
||||||
{protobuffs, "0.8.*", {git, "git://github.com/basho/erlang_protobuffs.git", {tag, "0.8.1p4"}}},
|
{protobuffs, "0.8.*", {git, "git://github.com/basho/erlang_protobuffs.git", {tag, "0.8.1p4"}}},
|
||||||
{riak_dt, ".*", {git, "git://github.com/basho/riak_dt.git", {branch, "develop"}}},
|
{riak_dt, ".*", {git, "git://github.com/basho/riak_dt.git", {branch, "develop"}}},
|
||||||
{node_package, ".*", {git, "git://github.com/basho/node_package.git", {branch, "develop"}}},
|
{node_package, ".*", {git, "git://github.com/basho/node_package.git", {branch, "develop"}}},
|
||||||
{eper, ".*", {git, "git://github.com/basho/eper.git", {tag, "0.78"}}}
|
{eper, ".*", {git, "git://github.com/basho/eper.git", {branch, "develop"}}},
|
||||||
|
{cluster_info, ".*", {git, "git://github.com/basho/cluster_info", {branch, "develop"}}}
|
||||||
]}.
|
]}.
|
||||||
|
|
||||||
{sub_dirs, ["rel", "apps/machi"]}.
|
{sub_dirs, ["rel", "apps/machi"]}.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{application, machi, [
|
{application, machi, [
|
||||||
{description, "A village of write-once files."},
|
{description, "A village of write-once files."},
|
||||||
{vsn, "0.0.0"},
|
{vsn, "0.0.0"},
|
||||||
{applications, [kernel, stdlib, crypto]},
|
{applications, [kernel, stdlib, crypto, cluster_info]},
|
||||||
{mod,{machi_app,[]}},
|
{mod,{machi_app,[]}},
|
||||||
{registered, []},
|
{registered, []},
|
||||||
{env, [
|
{env, [
|
||||||
|
|
|
@ -36,12 +36,8 @@
|
||||||
-export([start/2, stop/1]).
|
-export([start/2, stop/1]).
|
||||||
|
|
||||||
start(_StartType, _StartArgs) ->
|
start(_StartType, _StartArgs) ->
|
||||||
case machi_sup:start_link() of
|
machi_cinfo:register(),
|
||||||
{ok, Pid} ->
|
machi_sup:start_link().
|
||||||
{ok, Pid};
|
|
||||||
Error ->
|
|
||||||
Error
|
|
||||||
end.
|
|
||||||
|
|
||||||
stop(_State) ->
|
stop(_State) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
|
@ -111,7 +111,7 @@
|
||||||
set_chain_members/2, set_chain_members/3, set_active/2,
|
set_chain_members/2, set_chain_members/3, set_active/2,
|
||||||
trigger_react_to_env/1]).
|
trigger_react_to_env/1]).
|
||||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||||
terminate/2, code_change/3]).
|
terminate/2, format_status/2, code_change/3]).
|
||||||
|
|
||||||
-export([make_chmgr_regname/1, projection_transitions_are_sane/2,
|
-export([make_chmgr_regname/1, projection_transitions_are_sane/2,
|
||||||
simple_chain_state_transition_is_sane/3,
|
simple_chain_state_transition_is_sane/3,
|
||||||
|
@ -400,6 +400,11 @@ handle_info(Msg, #ch_mgr{name=MyName}=S) ->
|
||||||
terminate(_Reason, _S) ->
|
terminate(_Reason, _S) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
format_status(_Opt, [_PDict, Status]) ->
|
||||||
|
Fields = record_info(fields, ch_mgr),
|
||||||
|
[_Name | Values] = tuple_to_list(Status),
|
||||||
|
lists:zip(Fields, Values).
|
||||||
|
|
||||||
code_change(_OldVsn, S, _Extra) ->
|
code_change(_OldVsn, S, _Extra) ->
|
||||||
{ok, S}.
|
{ok, S}.
|
||||||
|
|
||||||
|
|
104
src/machi_cinfo.erl
Normal file
104
src/machi_cinfo.erl
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
%% -------------------------------------------------------------------
|
||||||
|
%%
|
||||||
|
%% Copyright (c) 2007-2015 Basho Technologies, Inc. All Rights Reserved.
|
||||||
|
%%
|
||||||
|
%% 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.
|
||||||
|
%%
|
||||||
|
%% -------------------------------------------------------------------
|
||||||
|
|
||||||
|
%% @doc cluster_info callback module for machi specific information
|
||||||
|
%% gathering.
|
||||||
|
|
||||||
|
-module(machi_cinfo).
|
||||||
|
|
||||||
|
%% cluster_info callbacks
|
||||||
|
-export([register/0, cluster_info_init/0, cluster_info_generator_funs/0]).
|
||||||
|
|
||||||
|
%% for debug in interactive shell
|
||||||
|
-export([dump/0,
|
||||||
|
public_projection/1, private_projection/1,
|
||||||
|
chain_manager/1, fitness/1, flu1/1]).
|
||||||
|
|
||||||
|
-include("machi_projection.hrl").
|
||||||
|
|
||||||
|
-spec register() -> ok.
|
||||||
|
register() ->
|
||||||
|
ok = cluster_info:register_app(?MODULE).
|
||||||
|
|
||||||
|
-spec cluster_info_init() -> ok.
|
||||||
|
cluster_info_init() ->
|
||||||
|
ok.
|
||||||
|
|
||||||
|
-spec cluster_info_generator_funs() -> [{string(), fun((pid()) -> ok)}].
|
||||||
|
cluster_info_generator_funs() ->
|
||||||
|
FluNames = [Name || {Name, _, _, _} <- supervisor:which_children(machi_flu_sup)],
|
||||||
|
lists:flatten([generator_funs_package(Name) || Name <- FluNames]).
|
||||||
|
|
||||||
|
generator_funs_package(FluName) ->
|
||||||
|
[{"Public projection of FLU " ++ atom_to_list(FluName),
|
||||||
|
cinfo_wrapper(fun public_projection/1, FluName)},
|
||||||
|
{"Private projection of FLU " ++ atom_to_list(FluName),
|
||||||
|
cinfo_wrapper(fun private_projection/1, FluName)},
|
||||||
|
{"Chain manager status of FLU " ++ atom_to_list(FluName),
|
||||||
|
cinfo_wrapper(fun chain_manager/1, FluName)},
|
||||||
|
{"Fitness server status of FLU " ++ atom_to_list(FluName),
|
||||||
|
cinfo_wrapper(fun fitness/1, FluName)},
|
||||||
|
{"FLU1 status of FLU " ++ atom_to_list(FluName),
|
||||||
|
cinfo_wrapper(fun flu1/1, FluName)}].
|
||||||
|
|
||||||
|
dump() ->
|
||||||
|
{{Y,M,D},{HH,MM,SS}} = calendar:local_time(),
|
||||||
|
Filename = lists:flatten(io_lib:format(
|
||||||
|
"machi-ci-~4..0B~2..0B~2..0B-~2..0B~2..0B~2..0B.html",
|
||||||
|
[Y,M,D,HH,MM,SS])),
|
||||||
|
cluster_info:dump_local_node(Filename).
|
||||||
|
|
||||||
|
-spec public_projection(atom()) -> ok.
|
||||||
|
public_projection(FluName) ->
|
||||||
|
projection(FluName, public).
|
||||||
|
|
||||||
|
-spec private_projection(atom()) -> ok.
|
||||||
|
private_projection(FluName) ->
|
||||||
|
projection(FluName, private).
|
||||||
|
|
||||||
|
-spec chain_manager(atom()) -> ok.
|
||||||
|
chain_manager(FluName) ->
|
||||||
|
Mgr = machi_flu_psup:make_mgr_supname(FluName),
|
||||||
|
sys:get_status(Mgr).
|
||||||
|
|
||||||
|
-spec fitness(atom()) -> ok.
|
||||||
|
fitness(FluName) ->
|
||||||
|
Fitness = machi_flu_psup:make_fitness_regname(FluName),
|
||||||
|
sys:get_status(Fitness).
|
||||||
|
|
||||||
|
-spec flu1(atom()) -> ok.
|
||||||
|
flu1(FluName) ->
|
||||||
|
State = machi_flu1:current_state(FluName),
|
||||||
|
machi_flu1:format_state(State).
|
||||||
|
|
||||||
|
%% Internal functions
|
||||||
|
|
||||||
|
projection(FluName, Kind) ->
|
||||||
|
ProjStore = machi_flu1:make_projection_server_regname(FluName),
|
||||||
|
{ok, Projection} = machi_projection_store:read_latest_projection(
|
||||||
|
whereis(ProjStore), Kind),
|
||||||
|
Fields = record_info(fields, projection_v1),
|
||||||
|
[_Name | Values] = tuple_to_list(Projection),
|
||||||
|
lists:zip(Fields, Values).
|
||||||
|
|
||||||
|
cinfo_wrapper(Fun, FluName) ->
|
||||||
|
fun(C) ->
|
||||||
|
cluster_info:format(C, "~p", [Fun(FluName)])
|
||||||
|
end.
|
|
@ -43,7 +43,7 @@
|
||||||
|
|
||||||
%% gen_server callbacks
|
%% gen_server callbacks
|
||||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||||
terminate/2, code_change/3]).
|
terminate/2, code_change/3, format_status/2]).
|
||||||
|
|
||||||
-record(state, {
|
-record(state, {
|
||||||
my_flu_name :: atom() | binary(),
|
my_flu_name :: atom() | binary(),
|
||||||
|
@ -193,6 +193,11 @@ handle_info(_Info, S) ->
|
||||||
terminate(_Reason, _S) ->
|
terminate(_Reason, _S) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
format_status(_Opt, [_PDict, Status]) ->
|
||||||
|
Fields = record_info(fields, state),
|
||||||
|
[_Name | Values] = tuple_to_list(Status),
|
||||||
|
lists:zip(Fields, Values).
|
||||||
|
|
||||||
code_change(_OldVsn, S, _Extra) ->
|
code_change(_OldVsn, S, _Extra) ->
|
||||||
{ok, S}.
|
{ok, S}.
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,8 @@
|
||||||
-export([start_link/1, stop/1,
|
-export([start_link/1, stop/1,
|
||||||
update_wedge_state/3, wedge_myself/2]).
|
update_wedge_state/3, wedge_myself/2]).
|
||||||
-export([make_listener_regname/1, make_projection_server_regname/1]).
|
-export([make_listener_regname/1, make_projection_server_regname/1]).
|
||||||
|
%% TODO: remove or replace in OTP way after gen_*'ified
|
||||||
|
-export([current_state/1, format_state/1]).
|
||||||
|
|
||||||
-record(state, {
|
-record(state, {
|
||||||
flu_name :: atom(),
|
flu_name :: atom(),
|
||||||
|
@ -98,6 +100,20 @@ wedge_myself(PidSpec, EpochId)
|
||||||
when is_tuple(EpochId) ->
|
when is_tuple(EpochId) ->
|
||||||
PidSpec ! {wedge_myself, EpochId}.
|
PidSpec ! {wedge_myself, EpochId}.
|
||||||
|
|
||||||
|
current_state(PidSpec) ->
|
||||||
|
PidSpec ! {current_state, self()},
|
||||||
|
%% TODO: Not so rubust f(^^;)
|
||||||
|
receive
|
||||||
|
Res -> Res
|
||||||
|
after
|
||||||
|
60*1000 -> {error, timeout}
|
||||||
|
end.
|
||||||
|
|
||||||
|
format_state(State) ->
|
||||||
|
Fields = record_info(fields, state),
|
||||||
|
[_Name | Values] = tuple_to_list(State),
|
||||||
|
lists:zip(Fields, Values).
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
ets_table_name(FluName) when is_atom(FluName) ->
|
ets_table_name(FluName) when is_atom(FluName) ->
|
||||||
|
@ -262,6 +278,8 @@ append_server_loop(FluPid, #state{wedged=Wedged_p,
|
||||||
#state{wedged=Wedged_p, epoch_id=EpochId} = S,
|
#state{wedged=Wedged_p, epoch_id=EpochId} = S,
|
||||||
FromPid ! {wedge_status_reply, Wedged_p, EpochId},
|
FromPid ! {wedge_status_reply, Wedged_p, EpochId},
|
||||||
append_server_loop(FluPid, S);
|
append_server_loop(FluPid, S);
|
||||||
|
{current_state, FromPid} ->
|
||||||
|
FromPid ! S;
|
||||||
Else ->
|
Else ->
|
||||||
io:format(user, "append_server_loop: WHA? ~p\n", [Else]),
|
io:format(user, "append_server_loop: WHA? ~p\n", [Else]),
|
||||||
append_server_loop(FluPid, S)
|
append_server_loop(FluPid, S)
|
||||||
|
|
67
test/machi_cinfo_test.erl
Normal file
67
test/machi_cinfo_test.erl
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
%% -------------------------------------------------------------------
|
||||||
|
%%
|
||||||
|
%% Copyright (c) 2007-2015 Basho Technologies, Inc. All Rights Reserved.
|
||||||
|
%%
|
||||||
|
%% 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(machi_cinfo_test).
|
||||||
|
|
||||||
|
-ifdef(TEST).
|
||||||
|
-ifndef(PULSE).
|
||||||
|
|
||||||
|
-include_lib("eunit/include/eunit.hrl").
|
||||||
|
|
||||||
|
-include("machi_projection.hrl").
|
||||||
|
|
||||||
|
%% smoke_test() will try just dump cluster_info and call each functions
|
||||||
|
|
||||||
|
smoke_test_() ->
|
||||||
|
{setup,
|
||||||
|
fun setup/0,
|
||||||
|
fun cleanup/1,
|
||||||
|
[
|
||||||
|
fun() -> machi_cinfo:public_projection(a) end,
|
||||||
|
fun() -> machi_cinfo:private_projection(a) end,
|
||||||
|
fun() -> machi_cinfo:fitness(a) end,
|
||||||
|
fun() -> machi_cinfo:chain_manager(a) end,
|
||||||
|
fun() -> machi_cinfo:dump() end
|
||||||
|
]}.
|
||||||
|
|
||||||
|
setup() ->
|
||||||
|
machi_cinfo:register(),
|
||||||
|
Ps = [{a,#p_srvr{name=a, address="localhost", port=5555, props="./data.a"}},
|
||||||
|
{b,#p_srvr{name=b, address="localhost", port=5556, props="./data.b"}},
|
||||||
|
{c,#p_srvr{name=c, address="localhost", port=5557, props="./data.c"}}
|
||||||
|
],
|
||||||
|
[os:cmd("rm -rf " ++ P#p_srvr.props) || {_,P} <- Ps],
|
||||||
|
{ok, SupPid} = machi_flu_sup:start_link(),
|
||||||
|
%% Only run a, don't run b & c so we have 100% failures talking to them
|
||||||
|
[begin
|
||||||
|
#p_srvr{name=Name, port=Port, props=Dir} = P,
|
||||||
|
{ok, _} = machi_flu_psup:start_flu_package(Name, Port, Dir, [])
|
||||||
|
end || {_,P} <- [hd(Ps)]],
|
||||||
|
machi_chain_manager1:set_chain_members(a_chmgr, orddict:from_list(Ps)),
|
||||||
|
{SupPid, Ps}.
|
||||||
|
|
||||||
|
cleanup({SupPid, Ps}) ->
|
||||||
|
exit(SupPid, normal),
|
||||||
|
[os:cmd("rm -rf " ++ P#p_srvr.props) || {_,P} <- Ps],
|
||||||
|
machi_util:wait_for_death(SupPid, 100),
|
||||||
|
ok.
|
||||||
|
|
||||||
|
-endif. % !PULSE
|
||||||
|
-endif. % TEST
|
Loading…
Reference in a new issue