diff options
author | Filipe David Borba Manana <fdmanana@apache.org> | 2011-08-27 07:30:35 +0000 |
---|---|---|
committer | Filipe David Borba Manana <fdmanana@apache.org> | 2011-08-27 07:30:35 +0000 |
commit | 745dc431376f115e645fadf82526f4e9ac24d4c5 (patch) | |
tree | 9ce241f977e15e11f1ab34d254011479df6825ec /src | |
parent | 595ceeb8be4b5fea4bf40264cf294cf10f63eb3e (diff) |
Fix replication crash on database compaction
There were race conditions that made replications crash
when a local endpoint database is compacted.
Patch tested by Joan Touzet.
git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1162306 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src')
-rw-r--r-- | src/couchdb/couch_rep_reader.erl | 11 | ||||
-rw-r--r-- | src/couchdb/couch_rep_writer.erl | 16 |
2 files changed, 18 insertions, 9 deletions
diff --git a/src/couchdb/couch_rep_reader.erl b/src/couchdb/couch_rep_reader.erl index 0d344e5c..856699e1 100644 --- a/src/couchdb/couch_rep_reader.erl +++ b/src/couchdb/couch_rep_reader.erl @@ -244,7 +244,7 @@ reader_loop(ReaderServer, Parent, Source, MissingRevsServer) -> case couch_rep_missing_revs:next(MissingRevsServer) of complete -> exit(complete); - {HighSeq, IdsRevs} -> + {_HighSeq, IdsRevs} -> % to be safe, make sure Results are sorted by source_seq SortedIdsRevs = lists:keysort(2, IdsRevs), RequestSeqs = [S || {_,S,_} <- SortedIdsRevs], @@ -256,7 +256,8 @@ reader_loop(ReaderServer, Parent, Source, MissingRevsServer) -> reader_loop(ReaderServer, Parent, Source, MissingRevsServer); _Local -> {ok, Source1} = gen_server:call(Parent, get_source_db, infinity), - Source2 = maybe_reopen_db(Source1, HighSeq), + {ok, Source2} = couch_db:open( + Source1#db.name, [{user_ctx, Source1#db.user_ctx}]), lists:foreach(fun({Id,Seq,Revs}) -> {ok, Docs} = couch_db:open_doc_revs(Source2, Id, Revs, [latest]), JustTheDocs = [Doc || {ok, Doc} <- Docs], @@ -268,12 +269,6 @@ reader_loop(ReaderServer, Parent, Source, MissingRevsServer) -> end end. -maybe_reopen_db(#db{update_seq=OldSeq} = Db, HighSeq) when HighSeq > OldSeq -> - {ok, NewDb} = couch_db:open(Db#db.name, [{user_ctx, Db#db.user_ctx}]), - NewDb; -maybe_reopen_db(Db, _HighSeq) -> - Db. - spawn_document_request(Source, Id, Seq, Revs) -> Server = self(), SpawnFun = fun() -> diff --git a/src/couchdb/couch_rep_writer.erl b/src/couchdb/couch_rep_writer.erl index 2b722e8e..40323925 100644 --- a/src/couchdb/couch_rep_writer.erl +++ b/src/couchdb/couch_rep_writer.erl @@ -26,7 +26,8 @@ writer_loop(Parent, Reader) -> ok; {HighSeq, Docs} -> DocCount = length(Docs), - {ok, Target} = gen_server:call(Parent, get_target_db, infinity), + {ok, Target0} = gen_server:call(Parent, get_target_db, infinity), + Target = open_db(Target0), try write_docs(Target, Docs) of {ok, []} -> Parent ! {update_stats, docs_written, DocCount}; @@ -38,6 +39,8 @@ writer_loop(Parent, Reader) -> {attachment_request_failed, Err} -> ?LOG_DEBUG("writer failed to write an attachment ~p", [Err]), exit({attachment_request_failed, Err, Docs}) + after + close_db(Target) end, Parent ! {writer_checkpoint, HighSeq}, couch_rep_att:cleanup(), @@ -163,3 +166,14 @@ write_docs_1({Props}) -> ErrId = couch_util:to_existing_atom(couch_util:get_value(<<"error">>, Props)), Reason = couch_util:get_value(<<"reason">>, Props), {{Id, Rev}, {ErrId, Reason}}. + +open_db(#db{name = Name, user_ctx = UserCtx}) -> + {ok, Db} = couch_db:open(Name, [{user_ctx, UserCtx}]), + Db; +open_db(HttpDb) -> + HttpDb. + +close_db(#db{} = Db) -> + couch_db:close(Db); +close_db(_HttpDb) -> + ok. |