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