You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by va...@apache.org on 2019/02/04 19:33:27 UTC
[couchdb] branch shard-split updated: Add a consistent reason to
state API queries.
This is an automated email from the ASF dual-hosted git repository.
vatamane pushed a commit to branch shard-split
in repository https://gitbox.apache.org/repos/asf/couchdb.git
The following commit(s) were added to refs/heads/shard-split by this push:
new 9ee3d08 Add a consistent reason to state API queries.
9ee3d08 is described below
commit 9ee3d08a02662c083f8e67aab56cde2d52db117b
Author: Nick Vatamaniuc <va...@apache.org>
AuthorDate: Mon Feb 4 14:27:05 2019 -0500
Add a consistent reason to state API queries.
This is both for _reshard/state and _reshard/ GET queries.
```
http $DB1/_reshard/state
{
"reason": null,
"state": "running"
}
```
```
http $DB1/_reshard/
{
"completed": 1,
"failed": 0,
"running": 0,
"state": "running",
"state_reason": null,
"stopped": 0,
"total": 1
}
```
Then when stopped:
```
http put $DB1/_reshard/state state=stopped reason="Rebalancing in progress"
```
```
http $DB1/_reshard/
{
"completed": 1,
"failed": 0,
"running": 0,
"state": "stopped",
"state_reason": "Rebalancing in progress",
"stopped": 0,
"total": 1
}
```
```
http $DB1/_reshard/state
{
"reason": "Rebalancing in progress",
"state": "stopped"
}
```
---
src/mem3/src/mem3_reshard.erl | 2 +-
src/mem3/src/mem3_reshard_httpd.erl | 7 ++--
src/mem3/src/mem3_reshard_httpd_util.erl | 62 +++++++++++++++++++++-----------
3 files changed, 48 insertions(+), 23 deletions(-)
diff --git a/src/mem3/src/mem3_reshard.erl b/src/mem3/src/mem3_reshard.erl
index 52c6f95..c9cd29b 100644
--- a/src/mem3/src/mem3_reshard.erl
+++ b/src/mem3/src/mem3_reshard.erl
@@ -187,7 +187,7 @@ handle_call(start, _From, #state{state = stopped} = State) ->
State1 = State#state{
state = running,
time_updated = now_sec(),
- state_info = info_update(reason, <<"Restarted">>, State#state.state_info)
+ state_info = info_delete(reason, State#state.state_info)
},
ok = mem3_reshard_store:store_state(State1),
State2 = reload_jobs(State1),
diff --git a/src/mem3/src/mem3_reshard_httpd.erl b/src/mem3/src/mem3_reshard_httpd.erl
index efa3a5c..8ed4755 100644
--- a/src/mem3/src/mem3_reshard_httpd.erl
+++ b/src/mem3/src/mem3_reshard_httpd.erl
@@ -45,8 +45,8 @@ handle_reshard_req(#httpd{path_parts=[_]} = Req) ->
%
handle_reshard_req(#httpd{method='GET',
path_parts=[_, ?STATE]} = Req) ->
- State = mem3_reshard_httpd_util:get_shard_splitting_state(),
- send_json(Req, {[{state, State}]});
+ {State, Reason} = mem3_reshard_httpd_util:get_shard_splitting_state(),
+ send_json(Req, {[{state, State}, {reason, Reason}]});
% PUT /_reshard/state
%
@@ -130,6 +130,9 @@ handle_reshard_req(#httpd{method = 'POST',
handle_reshard_req(#httpd{path_parts=[_, ?JOBS]} = Req) ->
send_method_not_allowed(Req, "GET,HEAD,POST");
+handle_reshard_req(#httpd{path_parts=[_, _]} = Req) ->
+ throw(not_found);
+
% GET /_reshard/jobs/$jobid
%
diff --git a/src/mem3/src/mem3_reshard_httpd_util.erl b/src/mem3/src/mem3_reshard_httpd_util.erl
index 4718bd5..8c99b19 100644
--- a/src/mem3/src/mem3_reshard_httpd_util.erl
+++ b/src/mem3/src/mem3_reshard_httpd_util.erl
@@ -205,33 +205,55 @@ get_summary() ->
{Replies, _Bad} = rpc:multicall(Nodes, mem3_reshard, get_state, []),
Stats0 = #{running => 0, total => 0, completed => 0, failed => 0,
stopped => 0},
- {Stats, States} = lists:foldl(fun({Res}, {Stats, States}) ->
- Stats1 = maps:map(fun(Stat, OldVal) ->
+ StatsF = lists:foldl(fun({Res}, Stats) ->
+ maps:map(fun(Stat, OldVal) ->
OldVal + couch_util:get_value(Stat, Res, 0)
- end, Stats),
- NewStates = [couch_util:get_value(state, Res) | States],
- {Stats1, NewStates}
- end, {Stats0, []}, Replies),
- State = case lists:member(<<"running">>, States) of
- true -> running;
- false -> stopped
- end,
- {[{state, State}] ++ lists:sort(maps:to_list(Stats))}.
+ end, Stats)
+ end, Stats0, Replies),
+ {State, Reason} = state_and_reason(Replies),
+ {[{state, State}, {state_reason, Reason}] ++ lists:sort(maps:to_list(StatsF))}.
get_shard_splitting_state() ->
Nodes = mem3_util:live_nodes(),
{Replies, _Bad} = rpc:multicall(Nodes, mem3_reshard, get_state, []),
- Running = lists:foldl(fun({Res}, R) ->
- case couch_util:get_value(state, Res) of
- <<"running">> -> R + 1;
- _ -> R
+ state_and_reason(Replies).
+
+
+state_and_reason(StateReplies) ->
+ AccF = lists:foldl(fun({ResProps}, Acc) ->
+ Reason = get_reason(ResProps),
+ case couch_util:get_value(state, ResProps) of
+ <<"running">> -> orddict:append(running, Reason, Acc);
+ <<"stopped">> -> orddict:append(stopped, Reason, Acc);
+ undefined -> Acc
end
- end, 0, Replies),
- % If at least one node is "running", then overall state is "running"
- case Running > 0 of
- true -> running;
- false -> stopped
+ end, orddict:from_list([{running, []}, {stopped, []}]), StateReplies),
+ Running = orddict:fetch(running, AccF),
+ case length(Running) > 0 of
+ true ->
+ Reason = pick_reason(Running),
+ {running, Reason};
+ false ->
+ Reason = pick_reason(orddict:fetch(stopped, AccF)),
+ {stopped, Reason}
+ end.
+
+
+pick_reason(Reasons) ->
+ Reasons1 = lists:usort(Reasons),
+ Reasons2 = [R || R <- Reasons1, R =/= undefined],
+ case Reasons2 of
+ [] -> null;
+ [R1 | _] -> R1
+ end.
+
+
+get_reason(StateProps) when is_list(StateProps) ->
+ case couch_util:get_value(state_info, StateProps) of
+ [] -> undefined;
+ undefined -> undefined;
+ {SInfoProps} -> couch_util:get_value(reason, SInfoProps)
end.