You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by da...@apache.org on 2017/07/12 21:44:07 UTC
[couchdb] 01/02: Prevent a terrible race condition
This is an automated email from the ASF dual-hosted git repository.
davisp pushed a commit to branch 649-fix-mrview-changes-since-test
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit d3e06625015cac765620ec11eb3fea518fb14016
Author: Paul J. Davis <pa...@gmail.com>
AuthorDate: Wed Jul 12 15:50:17 2017 -0500
Prevent a terrible race condition
Looking into #649 I realized there's a pretty terrible race condition if
an index is compacted quickly followed by an index update. Since we
don't check the index updater message it would be possible for us to
swap out a compaction change, followed by immediately resetting to the
new state from the index updater. This would be bad as we'd possibly end
up with a situation where our long lived index would be operating on a
file that no longer existed on disk.
---
src/couch_index/src/couch_index.erl | 49 +++++++++++++++++++++++--------------
1 file changed, 31 insertions(+), 18 deletions(-)
diff --git a/src/couch_index/src/couch_index.erl b/src/couch_index/src/couch_index.erl
index 9da928d..604d503 100644
--- a/src/couch_index/src/couch_index.erl
+++ b/src/couch_index/src/couch_index.erl
@@ -230,24 +230,37 @@ handle_cast({new_state, NewIdxState}, State) ->
mod=Mod,
idx_state=OldIdxState
} = State,
- assert_signature_match(Mod, OldIdxState, NewIdxState),
- CurrSeq = Mod:get(update_seq, NewIdxState),
- Args = [
- Mod:get(db_name, NewIdxState),
- Mod:get(idx_name, NewIdxState),
- CurrSeq
- ],
- couch_log:debug("Updated index for db: ~s idx: ~s seq: ~B", Args),
- Rest = send_replies(State#st.waiters, CurrSeq, NewIdxState),
- case State#st.committed of
- true -> erlang:send_after(commit_delay(), self(), commit);
- false -> ok
- end,
- {noreply, State#st{
- idx_state=NewIdxState,
- waiters=Rest,
- committed=false
- }};
+ OldFd = Mod:get(fd, OldIdxState),
+ NewFd = Mod:get(fd, NewIdxState),
+ case NewFd == OldFd of
+ true ->
+ assert_signature_match(Mod, OldIdxState, NewIdxState),
+ CurrSeq = Mod:get(update_seq, NewIdxState),
+ Args = [
+ Mod:get(db_name, NewIdxState),
+ Mod:get(idx_name, NewIdxState),
+ CurrSeq
+ ],
+ couch_log:debug("Updated index for db: ~s idx: ~s seq: ~B", Args),
+ Rest = send_replies(State#st.waiters, CurrSeq, NewIdxState),
+ case State#st.committed of
+ true -> erlang:send_after(commit_delay(), self(), commit);
+ false -> ok
+ end,
+ {noreply, State#st{
+ idx_state=NewIdxState,
+ waiters=Rest,
+ committed=false
+ }};
+ false ->
+ Fmt = "Ignoring update from old indexer for db: ~s idx: ~s",
+ Args = [
+ Mod:get(db_name, NewIdxState),
+ Mod:get(idx_name, NewIdxState)
+ ],
+ couch_log:warning(Fmt, Args),
+ {noreply, State}
+ end;
handle_cast({update_error, Error}, State) ->
send_all(State#st.waiters, Error),
{noreply, State#st{waiters=[]}};
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.