diff options
author | Filipe David Borba Manana <fdmanana@apache.org> | 2011-03-27 19:20:59 +0000 |
---|---|---|
committer | Filipe David Borba Manana <fdmanana@apache.org> | 2011-03-27 19:20:59 +0000 |
commit | e5acebced31345e47bca2571a7de9432d4f9855b (patch) | |
tree | 55419658119dc66a538887e476e431488f9e0c1d | |
parent | 579eadac058a82bcc609fea0473047ba6d90ea7c (diff) |
Backport fix for COUCHDB-1093 (revision 1086007)
Fix for crashes in continuous and filtered changes feeds
Fixes COUCHDB-1093.
git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1086009 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | share/www/script/test/replication.js | 61 | ||||
-rw-r--r-- | src/couchdb/couch_changes.erl | 16 |
2 files changed, 69 insertions, 8 deletions
diff --git a/share/www/script/test/replication.js b/share/www/script/test/replication.js index 5acff4ab..7f92891e 100644 --- a/share/www/script/test/replication.js +++ b/share/www/script/test/replication.js @@ -724,6 +724,67 @@ couchTests.replication = function(debug) { run_on_modified_server(server_config, test_fun); + // COUCHDB-1093 - filtered and continuous _changes feed dies when the + // database is compacted + dbA = new CouchDB("test_suite_db_a"); + dbB = new CouchDB("test_suite_db_b"); + + dbA.deleteDb(); + dbA.createDb(); + dbB.deleteDb(); + dbB.createDb(); + + var docs = makeDocs(1, 10); + docs.push({ + _id: "_design/foo", + language: "javascript", + filters: { + myfilter: (function(doc, req) { return true; }).toString() + } + }); + dbA.bulkSave(docs).ok; + + var repResult = CouchDB.replicate( + CouchDB.protocol + host + "/" + dbA.name, + dbB.name, + { + body: { + continuous: true, + filter: "foo/myfilter" + } + } + ); + TEquals(true, repResult.ok); + TEquals('string', typeof repResult._local_id); + + var xhr = CouchDB.request("GET", "/_active_tasks"); + var tasks = JSON.parse(xhr.responseText); + + TEquals(true, dbA.compact().ok); + while (dbA.info().compact_running) {}; + + TEquals(true, dbA.save(makeDocs(30, 31)[0]).ok); + xhr = CouchDB.request("GET", "/_active_tasks"); + + var tasksAfter = JSON.parse(xhr.responseText); + TEquals(tasks.length, tasksAfter.length); + T(dbB.open("30") !== null); + + repResult = CouchDB.replicate( + CouchDB.protocol + host + "/" + dbA.name, + dbB.name, + { + body: { + continuous: true, + filter: "foo/myfilter", + cancel: true + } + } + ); + TEquals(true, repResult.ok); + TEquals('string', typeof repResult._local_id); + + // cleanup dbA.deleteDb(); dbB.deleteDb(); diff --git a/src/couchdb/couch_changes.erl b/src/couchdb/couch_changes.erl index 2241e554..6eb6f7e1 100644 --- a/src/couchdb/couch_changes.erl +++ b/src/couchdb/couch_changes.erl @@ -87,7 +87,7 @@ os_filter_fun(FilterName, Style, Req, Db) -> case [list_to_binary(couch_httpd:unquote(Part)) || Part <- string:tokens(FilterName, "/")] of [] -> - fun(#doc_info{revs=Revs}) -> + fun(_Db2, #doc_info{revs=Revs}) -> builtin_results(Style, Revs) end; [DName, FName] -> @@ -96,7 +96,7 @@ os_filter_fun(FilterName, Style, Req, Db) -> % validate that the ddoc has the filter fun #doc{body={Props}} = DDoc, couch_util:get_nested_json_value({Props}, [<<"filters">>, FName]), - fun(DocInfo) -> + fun(Db2, DocInfo) -> DocInfos = case Style of main_only -> @@ -105,10 +105,10 @@ os_filter_fun(FilterName, Style, Req, Db) -> [DocInfo#doc_info{revs=[Rev]}|| Rev <- DocInfo#doc_info.revs] end, Docs = [Doc || {ok, Doc} <- [ - couch_db:open_doc(Db, DocInfo2, [deleted, conflicts]) + couch_db:open_doc(Db2, DocInfo2, [deleted, conflicts]) || DocInfo2 <- DocInfos]], {ok, Passes} = couch_query_servers:filter_docs( - Req, Db, DDoc, FName, Docs + Req, Db2, DDoc, FName, Docs ), [{[{<<"rev">>, couch_doc:rev_to_str({RevPos,RevId})}]} || {Pass, #doc{revs={RevPos,[RevId|_]}}} @@ -134,7 +134,7 @@ builtin_filter_fun(_FilterName, _Style, _Req, _Db) -> throw({bad_request, "unknown builtin filter name"}). filter_docids(DocIds, Style) when is_list(DocIds)-> - fun(#doc_info{id=DocId, revs=Revs}) -> + fun(_Db, #doc_info{id=DocId, revs=Revs}) -> case lists:member(DocId, DocIds) of true -> builtin_results(Style, Revs); @@ -145,7 +145,7 @@ filter_docids(_, _) -> throw({bad_request, "`doc_ids` filter parameter is not a list."}). filter_designdoc(Style) -> - fun(#doc_info{id=DocId, revs=Revs}) -> + fun(_Db, #doc_info{id=DocId, revs=Revs}) -> case DocId of <<"_design", _/binary>> -> builtin_results(Style, Revs); @@ -263,7 +263,7 @@ changes_enumerator(DocInfo, {Db, _, _, FilterFun, Callback, UserAcc, "continuous", Limit, IncludeDocs, Conflicts}) -> #doc_info{high_seq = Seq} = DocInfo, - Results0 = FilterFun(DocInfo), + Results0 = FilterFun(Db, DocInfo), Results = [Result || Result <- Results0, Result /= null], Go = if Limit =< 1 -> stop; true -> ok end, case Results of @@ -282,7 +282,7 @@ changes_enumerator(DocInfo, {Db, _, Prepend, FilterFun, Callback, UserAcc, ResponseType, Limit, IncludeDocs, Conflicts}) -> #doc_info{high_seq = Seq} = DocInfo, - Results0 = FilterFun(DocInfo), + Results0 = FilterFun(Db, DocInfo), Results = [Result || Result <- Results0, Result /= null], Go = if (Limit =< 1) andalso Results =/= [] -> stop; true -> ok end, case Results of |