You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ei...@apache.org on 2017/06/05 18:04:58 UTC
[couchdb] branch master updated: Add retry to get_view_state
This is an automated email from the ASF dual-hosted git repository.
eiri pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/couchdb.git
The following commit(s) were added to refs/heads/master by this push:
new 05d2e1e Add retry to get_view_state
05d2e1e is described below
commit 05d2e1e6a7db3e2526530cdbb446034557b94e57
Author: Eric Avdey <ei...@eiri.ca>
AuthorDate: Mon Jun 5 13:21:28 2017 -0300
Add retry to get_view_state
There are a race condition in `get_view/4`,
between aquiring index's Pid and getting
its state, that surface when the same
signature DDoc got rapidly deleted
and re-created.
This patch addresses this by adding
retry logic to get_view_index_state.
---
src/couch_mrview/src/couch_mrview_util.erl | 51 +++++++++++++++++++++---------
1 file changed, 36 insertions(+), 15 deletions(-)
diff --git a/src/couch_mrview/src/couch_mrview_util.erl b/src/couch_mrview/src/couch_mrview_util.erl
index 27f8737..3e6a86b 100644
--- a/src/couch_mrview/src/couch_mrview_util.erl
+++ b/src/couch_mrview/src/couch_mrview_util.erl
@@ -34,28 +34,16 @@
-export([to_key_seq/1]).
-define(MOD, couch_mrview_index).
+-define(GET_VIEW_RETRY_COUNT, 1).
+-define(GET_VIEW_RETRY_DELAY, 50).
-include_lib("couch/include/couch_db.hrl").
-include_lib("couch_mrview/include/couch_mrview.hrl").
get_view(Db, DDoc, ViewName, Args0) ->
- {ok, Pid, Args2} = get_view_index_pid(Db, DDoc, ViewName, Args0),
- DbUpdateSeq = couch_util:with_db(Db, fun(WDb) ->
- couch_db:get_update_seq(WDb)
- end),
- MinSeq = case Args2#mrargs.update of
- false -> 0; lazy -> 0; _ -> DbUpdateSeq
- end,
- {ok, State} = case couch_index:get_state(Pid, MinSeq) of
- {ok, _} = Resp -> Resp;
- Error -> throw(Error)
- end,
+ {ok, State, Args2} = get_view_index_state(Db, DDoc, ViewName, Args0),
Ref = erlang:monitor(process, State#mrst.fd),
- if Args2#mrargs.update == lazy ->
- spawn(fun() -> catch couch_index:get_state(Pid, DbUpdateSeq) end);
- true -> ok
- end,
#mrst{language=Lang, views=Views} = State,
{Type, View, Args3} = extract_view(Lang, Args2, ViewName, Views),
check_range(Args3, view_cmp(View)),
@@ -71,6 +59,39 @@ get_view_index_pid(Db, DDoc, ViewName, Args0) ->
couch_index_server:get_index(?MOD, Db, DDoc, ArgCheck).
+get_view_index_state(Db, DDoc, ViewName, Args0) ->
+ get_view_index_state(Db, DDoc, ViewName, Args0, ?GET_VIEW_RETRY_COUNT).
+
+get_view_index_state(_, DDoc, _, _, RetryCount) when RetryCount < 0 ->
+ couch_log:warning("DDoc '~s' recreated too frequently", [DDoc#doc.id]),
+ throw({get_view_state, exceeded_retry_count});
+get_view_index_state(Db, DDoc, ViewName, Args0, RetryCount) ->
+ try
+ {ok, Pid, Args} = get_view_index_pid(Db, DDoc, ViewName, Args0),
+ UpdateSeq = couch_util:with_db(Db, fun(WDb) ->
+ couch_db:get_update_seq(WDb)
+ end),
+ {ok, State} = case Args#mrargs.update of
+ lazy ->
+ spawn(fun() ->
+ catch couch_index:get_state(Pid, UpdateSeq)
+ end),
+ couch_index:get_state(Pid, 0);
+ false ->
+ couch_index:get_state(Pid, 0);
+ _ ->
+ couch_index:get_state(Pid, UpdateSeq)
+ end,
+ {ok, State, Args}
+ catch
+ exit:{Reason, _} when Reason == noproc; Reason == normal ->
+ timer:sleep(?GET_VIEW_RETRY_DELAY),
+ get_view_index_state(Db, DDoc, ViewName, Args0, RetryCount - 1);
+ Error ->
+ throw(Error)
+ end.
+
+
ddoc_to_mrst(DbName, #doc{id=Id, body={Fields}}) ->
MakeDict = fun({Name, {MRFuns}}, DictBySrcAcc) ->
case couch_util:get_value(<<"map">>, MRFuns) of
--
To stop receiving notification emails like this one, please contact
['"commits@couchdb.apache.org" <co...@couchdb.apache.org>'].