Skip to content

Commit c2f60c6

Browse files
author
Mikael Lixenstrand
committed
Use clique for sweeper cli.
1 parent 8ac37c2 commit c2f60c6

5 files changed

+209
-97
lines changed

rebar.config

+2-1
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,6 @@
3333
{riak_pipe, ".*", {git, "git://github.com/basho/riak_pipe.git", {branch, "2.1"}}},
3434
{riak_api, ".*", {git, "git://github.com/basho/riak_api.git", {branch, "2.1"}}},
3535
{riak_dt, ".*", {git, "git://github.com/basho/riak_dt.git", {branch, "2.1"}}},
36-
{eunit_formatters, ".*", {git, "git://github.com/seancribbs/eunit_formatters", {tag, "0.1.2"}}}
36+
{eunit_formatters, ".*", {git, "git://github.com/seancribbs/eunit_formatters", {tag, "0.1.2"}}},
37+
{clique, "0.3.2", {git, "git://github.com/basho/clique.git", {tag, "0.3.2"}}}
3738
]}.

src/riak_kv_app.erl

+2
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ start(_Type, _StartArgs) ->
124124
%% print out critical env limits for support/debugging purposes
125125
catch riak_kv_env:doc_env(),
126126

127+
riak_kv_cli_registry:register_cli(),
128+
127129
%% Spin up supervisor
128130
case riak_kv_sup:start_link() of
129131
{ok, Pid} ->

src/riak_kv_cli_registry.erl

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
%% -------------------------------------------------------------------
2+
%%
3+
%% Copyright (c) 2016 Basho Technologies, Inc. All Rights Reserved.
4+
%%
5+
%% This file is provided to you under the Apache License,
6+
%% Version 2.0 (the "License"); you may not use this file
7+
%% except in compliance with the License. You may obtain
8+
%% a copy of the License at
9+
%%
10+
%% http://www.apache.org/licenses/LICENSE-2.0
11+
%%
12+
%% Unless required by applicable law or agreed to in writing,
13+
%% software distributed under the License is distributed on an
14+
%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
%% KIND, either express or implied. See the License for the
16+
%% specific language governing permissions and limitations
17+
%% under the License.
18+
%%
19+
%% -------------------------------------------------------------------
20+
%% @doc This module tracks registrations for clique integrations.
21+
22+
-module(riak_kv_cli_registry).
23+
24+
-define(CLI_MODULES, [
25+
riak_kv_sweeper_cli
26+
]).
27+
28+
-export([
29+
register_cli/0
30+
]).
31+
32+
-spec register_cli() -> ok.
33+
register_cli() ->
34+
clique:register(?CLI_MODULES).

src/riak_kv_console.erl

+5-96
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
cluster_info/1,
3636
down/1,
3737
aae_status/1,
38-
sweep_status/1,
3938
repair_2i/1,
4039
reformat_indexes/1,
4140
reformat_objects/1,
@@ -54,8 +53,12 @@
5453
aae_repair_status/1,
5554
aae_tree_status/1]).
5655

57-
-include("riak_kv_sweeper.hrl").
56+
%% New CLI API
57+
-export([command/1]).
5858

59+
-spec command([string()]) -> ok.
60+
command(Cmd) ->
61+
clique:run(Cmd).
5962

6063
join([NodeStr]) ->
6164
join(NodeStr, fun riak_core:join/1,
@@ -362,100 +365,6 @@ format_timestamp(undefined, _) ->
362365
format_timestamp(Now, TS) ->
363366
riak_core_format:human_time_fmt("~.1f", timer:now_diff(Now, TS)).
364367

365-
sweep_status([]) ->
366-
{Participants, Sweeps} = riak_kv_sweeper:status(),
367-
format_participants(Participants),
368-
format_sweeps(Sweeps).
369-
370-
format_sweeps(Sweeps) ->
371-
io:format("~s~n~-49s ~-12s ~-12s~n",
372-
[string:centre(" Sweeps ", 79, $=),
373-
"Index",
374-
"Last (ago)",
375-
"Duration"]),
376-
Now = os:timestamp(),
377-
SortedSweeps = lists:keysort(#sweep.index, Sweeps),
378-
[begin
379-
StartTime = Sweep#sweep.start_time,
380-
EndTime = Sweep#sweep.end_time,
381-
LastSweep = format_timestamp(Now, StartTime),
382-
Duration = format_timestamp(EndTime, StartTime),
383-
ResultsString = format_results(Now, Sweep#sweep.results),
384-
Progress = format_progress(Sweep),
385-
io:format("~-49b ~-12s ~-12s ~s ~n~s", [Sweep#sweep.index, LastSweep, Duration, ResultsString, Progress])
386-
end
387-
|| Sweep <- SortedSweeps].
388-
389-
format_progress(#sweep{state = idle}) ->
390-
"";
391-
392-
format_progress(#sweep{active_participants = AcitvePart, estimated_keys = {EstimatedKeys, _TS} , swept_keys = SweptKeys}) ->
393-
format_active_participants(AcitvePart) ++
394-
case EstimatedKeys of
395-
EstimatedKeys when EstimatedKeys > 0 ->
396-
progress(SweptKeys/EstimatedKeys, 80) ++
397-
io_lib:format(" ~w of ~w keys swept ~n", [SweptKeys, EstimatedKeys]);
398-
_ ->
399-
format_progress_without_estimate(SweptKeys)
400-
end;
401-
format_progress(_) ->
402-
"".
403-
404-
format_active_participants(AcitvePart) ->
405-
io_lib:format("| Running: ", []) ++
406-
[io_lib:format("| ~s", [atom_to_list(Mod)])
407-
|| #sweep_participant{module = Mod} <- AcitvePart].
408-
409-
format_progress_without_estimate(undefined) ->
410-
"";
411-
format_progress_without_estimate(SweptKeys) ->
412-
io_lib:format("~nRunning: no estimate swept ~p keys~n", [SweptKeys]).
413-
414-
progress(PctDecimal, MaxSize) when PctDecimal > 1 ->
415-
progress(1, MaxSize);
416-
417-
progress(PctDecimal, MaxSize) ->
418-
ProgressTotalSize = progress_size(MaxSize),
419-
ProgressSize = trunc(PctDecimal * ProgressTotalSize),
420-
PadSize = ProgressTotalSize - ProgressSize,
421-
FormatStr = progress_fmt(ProgressSize, PadSize),
422-
riak_core_format:fmt(FormatStr, ["", "", integer_to_list(trunc(PctDecimal * 100))]).
423-
424-
progress_size(MaxSize) ->
425-
MaxSize - 3. %% 3 fixed characters in progress bar
426-
427-
progress_fmt(ArrowSize, PadSize) ->
428-
riak_core_format:fmt("~n|~~~p..=s~~~p.. s| ~~3.. s%", [ArrowSize, PadSize]).
429-
430-
format_results(Now, Results) ->
431-
ResultList = dict:to_list(Results),
432-
SortedResultList = lists:keysort(1, ResultList),
433-
[begin
434-
LastResult = format_timestamp(Now, TimeStamp),
435-
OutcomeString = string:to_upper(atom_to_list(Outcome)),
436-
io_lib:format("| ~s ~-4s ~-9s", [atom_to_list(Mod), OutcomeString, LastResult])
437-
end
438-
|| {Mod, {TimeStamp, Outcome}} <- SortedResultList, lists:member(Outcome, [succ, fail])].
439-
440-
format_participants(SweepParticipants) ->
441-
io:format("~s~n~-25s ~-20s ~-15s~n",
442-
[string:centre(" Sweep Participants ", 79, $=),
443-
"Module",
444-
"Desciption",
445-
"Run interval"]),
446-
SortedSweepParticipants = lists:keysort(1, SweepParticipants),
447-
[format_sweep_participant(SweepParticipant)
448-
|| SweepParticipant <- SortedSweepParticipants].
449-
450-
format_sweep_participant(#sweep_participant{module = Mod,
451-
description = Desciption,
452-
run_interval = Interval}) ->
453-
IntervalValue = riak_kv_sweeper:get_run_interval(Interval),
454-
IntervalString = format_interval(IntervalValue * 1000000),
455-
io:format("~-25s ~-20s ~-15s ~n", [atom_to_list(Mod), Desciption, IntervalString]).
456-
457-
format_interval(Interval) ->
458-
riak_core_format:human_time_fmt("~.1f", Interval).
459368

460369
parse_int(IntStr) ->
461370
try

src/riak_kv_sweeper_cli.erl

+166
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
%% -------------------------------------------------------------------
2+
%%
3+
%% Copyright (c) 2016 Basho Technologies, Inc. All Rights Reserved.
4+
%%
5+
%% This file is provided to you under the Apache License,
6+
%% Version 2.0 (the "License"); you may not use this file
7+
%% except in compliance with the License. You may obtain
8+
%% a copy of the License at
9+
%%
10+
%% http://www.apache.org/licenses/LICENSE-2.0
11+
%%
12+
%% Unless required by applicable law or agreed to in writing,
13+
%% software distributed under the License is distributed on an
14+
%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
%% KIND, either express or implied. See the License for the
16+
%% specific language governing permissions and limitations
17+
%% under the License.
18+
%%
19+
%% -------------------------------------------------------------------
20+
%% @doc This module encapsulates the command line interface for the
21+
%% sweeper commands:
22+
%%
23+
%% status
24+
%%
25+
-module(riak_kv_sweeper_cli).
26+
27+
-behaviour(clique_handler).
28+
29+
-include("riak_kv_sweeper.hrl").
30+
31+
-export([
32+
format_sweeps/1,
33+
register_cli/0,
34+
status/3
35+
]).
36+
37+
register_cli() ->
38+
register_all_usage(),
39+
register_all_commands().
40+
41+
register_all_usage() ->
42+
clique:register_usage(["riak-admin", "sweeper"], sweeper_usage()),
43+
clique:register_usage(["riak-admin", "sweeper", "status"], status_usage()).
44+
45+
register_all_commands() ->
46+
lists:foreach(fun(Args) -> apply(clique, register_command, Args) end,
47+
[status_register()]).
48+
49+
status_register() ->
50+
[["riak-admin", "sweeper", "status"], % Cmd
51+
[], % KeySpecs
52+
[], % FlagSpecs
53+
fun status/3]. % Implementation callback.
54+
55+
56+
sweeper_usage() ->
57+
[
58+
"riak-admin sweeper <sub-command>\n\n",
59+
" Sub-commands:\n",
60+
" status Display sweeper status\n",
61+
" Use --help after a sub-command for more details.\n"
62+
].
63+
64+
status_usage() ->
65+
["riak-admin sweeper status\n\n",
66+
" Display sweeper status\n"].
67+
68+
status(_CmdBase, [], []) ->
69+
{Participants, Sweeps} = riak_kv_sweeper:status(),
70+
ParticipantsTable = format_participants(Participants),
71+
SweepsTable = format_sweeps(Sweeps),
72+
ActiveSweeps = format_active_sweeps(Sweeps),
73+
[ParticipantsTable,
74+
SweepsTable]
75+
++ ActiveSweeps.
76+
77+
format_sweeps(Sweeps) ->
78+
Now = os:timestamp(),
79+
SortedSweeps = lists:keysort(#sweep.index, Sweeps),
80+
Rows =
81+
[begin
82+
StartTime = Sweep#sweep.start_time,
83+
EndTime = Sweep#sweep.end_time,
84+
LastSweep = format_timestamp(Now, StartTime),
85+
Duration = format_timestamp(EndTime, StartTime),
86+
ResultsString = format_results(Now, Sweep#sweep.results),
87+
[{"Index", Sweep#sweep.index},
88+
{"Last sweep", LastSweep},
89+
{"Duration", Duration},
90+
{"Results", ResultsString}
91+
]
92+
end
93+
|| Sweep <- SortedSweeps],
94+
clique_status:table(Rows).
95+
96+
format_active_sweeps(Sweeps) ->
97+
Header = io_lib:format("~n~s~n", [string:centre(" Active sweeps ", 79, $=)]),
98+
Rows = [begin
99+
format_progress(Sweep)
100+
end
101+
|| #sweep{state = State} = Sweep <- Sweeps, State == running],
102+
case Rows of
103+
[] ->
104+
[];
105+
Rows ->
106+
[clique_status:text(Header),
107+
clique_status:table(Rows)]
108+
end.
109+
110+
format_progress(#sweep{index = Index,
111+
active_participants = AcitvePart,
112+
estimated_keys = {EstimatedKeys, _TS},
113+
swept_keys = SweptKeys}) ->
114+
case EstimatedKeys of
115+
EstimatedKeys when is_integer(EstimatedKeys) andalso EstimatedKeys > 0 ->
116+
[{"Index", Index},
117+
{"Swept keys", SweptKeys},
118+
{"Estimated Keys", EstimatedKeys},
119+
{"Active", format_active_participants(AcitvePart)}];
120+
_ ->
121+
[{"Index", Index},
122+
{"Swept keys", SweptKeys},
123+
{"Active", format_active_participants(AcitvePart)}]
124+
end;
125+
126+
format_progress(_) ->
127+
"".
128+
129+
format_active_participants(AcitvePart) ->
130+
[io_lib:format("| ~s", [atom_to_list(Mod)])
131+
|| #sweep_participant{module = Mod} <- AcitvePart].
132+
133+
format_results(Now, Results) ->
134+
ResultList = dict:to_list(Results),
135+
SortedResultList = lists:keysort(1, ResultList),
136+
[begin
137+
LastResult = format_timestamp(Now, TimeStamp),
138+
OutcomeString = string:to_upper(atom_to_list(Outcome)),
139+
io_lib:format(" ~s ~-4s ~-8s", [atom_to_list(Mod), OutcomeString, LastResult])
140+
end
141+
|| {Mod, {TimeStamp, Outcome}} <- SortedResultList, lists:member(Outcome, [succ, fail])].
142+
143+
format_participants(SweepParticipants) ->
144+
SortedSweepParticipants = lists:keysort(1, SweepParticipants),
145+
Rows = [format_sweep_participant(SweepParticipant)
146+
|| SweepParticipant <- SortedSweepParticipants],
147+
clique_status:table(Rows).
148+
149+
format_sweep_participant(#sweep_participant{module = Mod,
150+
description = Desciption,
151+
run_interval = Interval}) ->
152+
IntervalValue = riak_kv_sweeper:get_run_interval(Interval),
153+
IntervalString = format_interval(IntervalValue * 1000000),
154+
[{"Module" ,atom_to_list(Mod)},
155+
{"Desciption" ,Desciption},
156+
{"Interval", IntervalString}].
157+
158+
format_interval(Interval) ->
159+
riak_core_format:human_time_fmt("~.1f", Interval).
160+
161+
format_timestamp(_Now, undefined) ->
162+
"--";
163+
format_timestamp(undefined, _) ->
164+
"--";
165+
format_timestamp(Now, TS) ->
166+
riak_core_format:human_time_fmt("~.1f", timer:now_diff(Now, TS)).

0 commit comments

Comments
 (0)