Author: fdmanana
Date: Sun Mar 27 19:20:59 2011
New Revision: 1086009

URL: http://svn.apache.org/viewvc?rev=1086009&view=rev
Log:
Backport fix for COUCHDB-1093 (revision 1086007)

    Fix for crashes in continuous and filtered changes feeds

    Fixes COUCHDB-1093.


Modified:
    couchdb/branches/1.1.x/share/www/script/test/replication.js
    couchdb/branches/1.1.x/src/couchdb/couch_changes.erl

Modified: couchdb/branches/1.1.x/share/www/script/test/replication.js
URL: 
http://svn.apache.org/viewvc/couchdb/branches/1.1.x/share/www/script/test/replication.js?rev=1086009&r1=1086008&r2=1086009&view=diff
==============================================================================
--- couchdb/branches/1.1.x/share/www/script/test/replication.js (original)
+++ couchdb/branches/1.1.x/share/www/script/test/replication.js Sun Mar 27 
19:20:59 2011
@@ -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();

Modified: couchdb/branches/1.1.x/src/couchdb/couch_changes.erl
URL: 
http://svn.apache.org/viewvc/couchdb/branches/1.1.x/src/couchdb/couch_changes.erl?rev=1086009&r1=1086008&r2=1086009&view=diff
==============================================================================
--- couchdb/branches/1.1.x/src/couchdb/couch_changes.erl (original)
+++ couchdb/branches/1.1.x/src/couchdb/couch_changes.erl Sun Mar 27 19:20:59 
2011
@@ -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, 
     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, _, _, F
     "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, _, Prep
     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


Reply via email to