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>'].