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 2009/11/12 08:35:38 UTC

svn commit: r835281 - in /couchdb/branches/0.10.x: share/www/script/test/erlang_views.js src/couchdb/couch_native_process.erl test/query_server_spec.rb

Author: davisp
Date: Thu Nov 12 07:35:38 2009
New Revision: 835281

URL: http://svn.apache.org/viewvc?rev=835281&view=rev
Log:
Fixes COUCHDB-567 error with ErlView reduces.

Apparently we never tested ErlView reductions on 0.10.x? As far as I can tell   they never should have worked. It was exactly as Sean Geoghegan described in    that the interleaved calls to reduce where trouncing the mapper state.

Trunk uses the two process update scheme so wouldn't be affected by this        trouncing. This patch is a stop gap to make ErlViews work. I've tested with the Futon test patch and an updated query_server_spec.rb to revalidate things are working.

Fixing this bug has made it quite apparent that the query server specs need to be drastically rethought. I spent quite a bit of time tracking down that the specs were actually testing that the subprocess died. ErlViews causing the host process to die would be very bad. In the future I'd like to see script/response sets and file stuctures for function definitions.


Modified:
    couchdb/branches/0.10.x/share/www/script/test/erlang_views.js
    couchdb/branches/0.10.x/src/couchdb/couch_native_process.erl
    couchdb/branches/0.10.x/test/query_server_spec.rb

Modified: couchdb/branches/0.10.x/share/www/script/test/erlang_views.js
URL: http://svn.apache.org/viewvc/couchdb/branches/0.10.x/share/www/script/test/erlang_views.js?rev=835281&r1=835280&r2=835281&view=diff
==============================================================================
--- couchdb/branches/0.10.x/share/www/script/test/erlang_views.js (original)
+++ couchdb/branches/0.10.x/share/www/script/test/erlang_views.js Thu Nov 12 07:35:38 2009
@@ -93,5 +93,41 @@
       var xhr = CouchDB.request("GET", url);
       T(xhr.status == 200, "standard get should be 200");
       T(xhr.responseText == "head2tail");
+
+      // Larger dataset
+
+      db.deleteDb();
+      db.createDb();
+      var words = "foo bar abc def baz xxyz".split(/\s+/);
+      
+      var docs = [];
+      for(var i = 0; i < 10000; i++) {
+        var body = [];
+        for(var j = 0; j < 10; j++) {
+          body.push({
+            word: words[j%words.length],
+            count: j
+          });
+        }
+        docs.push({
+          "_id": "test-" + i,
+          "words": body
+        });
+      }
+      T(db.bulkSave(docs).length, 250, "Saved big doc set.");
+      
+      var mfun = 'fun({Doc}) -> ' +
+        'Words = proplists:get_value(<<"words">>, Doc), ' +
+        'lists:foreach(fun({Word}) -> ' +
+            'WordString = proplists:get_value(<<"word">>, Word), ' + 
+            'Count = proplists:get_value(<<"count">>, Word), ' + 
+            'Emit(WordString , Count) ' +
+          'end, Words) ' +
+        'end.';
+      
+      var rfun = 'fun(Keys, Values, RR) -> length(Values) end.';
+      var results = db.query(mfun, rfun, null, null, "erlang");
+      T(results.rows[0].key === null, "Returned a reduced value.");
+      T(results.rows[0].value > 0, "Reduce value exists.");
     });
 };

Modified: couchdb/branches/0.10.x/src/couchdb/couch_native_process.erl
URL: http://svn.apache.org/viewvc/couchdb/branches/0.10.x/src/couchdb/couch_native_process.erl?rev=835281&r1=835280&r2=835281&view=diff
==============================================================================
--- couchdb/branches/0.10.x/src/couchdb/couch_native_process.erl (original)
+++ couchdb/branches/0.10.x/src/couchdb/couch_native_process.erl Thu Nov 12 07:35:38 2009
@@ -41,6 +41,7 @@
 
 -export([start_link/0]).
 -export([set_timeout/2, prompt/2, stop/1]).
+-export([loop/0]).
 
 -define(STATE, native_proc_state).
 -record(evstate, {funs=[], query_config=[], list_pid=nil, timeout=5000}).
@@ -48,22 +49,56 @@
 -include("couch_db.hrl").
 
 start_link() ->
-    {ok, self()}.
+    {ok, spawn_link(?MODULE, loop, [])}.
 
-stop(_Pid) ->
-    ok.
+stop(Pid) ->
+    Pid ! {stop, self()},
+    receive
+        {ok, Pid} -> ok
+    after 1000 ->
+        throw({error, timeout})
+    end.
 
-set_timeout(_Pid, TimeOut) ->
-    NewState = case get(?STATE) of
-    undefined ->
-        #evstate{timeout=TimeOut};
-    State ->
-        State#evstate{timeout=TimeOut}
-    end,
-    put(?STATE, NewState),
-    ok.
+prompt(Pid, Data) ->
+    Pid ! {prompt, self(), Data},
+    receive
+        {ok, Pid, Resp} -> Resp
+    after 1000 ->
+        throw({error, timeout})
+    end.
 
-prompt(Pid, Data) when is_pid(Pid), is_list(Data) ->
+set_timeout(Pid, TimeOut) ->
+    Pid ! {set_timeout, self(), TimeOut},
+    receive
+        {ok, Pid} -> ok
+    after 1000 ->
+        throw({error, timeout})
+    end.
+
+loop() ->
+    receive
+        {prompt, From, Data} ->
+            case (catch prompt(Data)) of
+                {error, Reason} ->
+                    From ! {ok, self(), {[{error, Reason}]}};
+                {NewState, Resp} ->
+                    put(?STATE, NewState),
+                    From ! {ok, self(), Resp},
+                    loop()
+            end;
+        {set_timeout, From, TimeOut} ->
+            NewState = case get(?STATE) of
+                undefined -> #evstate{timeout=TimeOut};
+                State -> State#evstate{timeout=TimeOut}
+            end,
+            put(?STATE, NewState),
+            From ! {ok, self()},
+            loop();
+        {stop, From} ->
+            From ! {ok, self()}
+    end.
+
+prompt(Data) when is_list(Data) ->
     case get(?STATE) of
     undefined ->
         State = #evstate{},
@@ -81,15 +116,7 @@
         _ ->
             ok % Not listing
     end,
-    {NewState, Resp} = run(State, to_binary(Data)),
-    put(?STATE, NewState),
-    case Resp of
-        {error, Reason} ->
-            Msg = io_lib:format("couch native server error: ~p", [Reason]),
-            {[{<<"error">>, list_to_binary(Msg)}]};
-        _ ->
-            Resp
-    end.
+    run(State, to_binary(Data)).
 
 run(_, [<<"reset">>]) ->
     {#evstate{}, true};

Modified: couchdb/branches/0.10.x/test/query_server_spec.rb
URL: http://svn.apache.org/viewvc/couchdb/branches/0.10.x/test/query_server_spec.rb?rev=835281&r1=835280&r2=835281&view=diff
==============================================================================
--- couchdb/branches/0.10.x/test/query_server_spec.rb (original)
+++ couchdb/branches/0.10.x/test/query_server_spec.rb Thu Nov 12 07:35:38 2009
@@ -630,8 +630,12 @@
 
 def should_have_exited qs
   begin
-    qs.run(["reset"])
-    "raise before this".should == true
+    resp = qs.run(["reset"])
+    #"raise before this".should == true
+    # Erlang can't very well kill the process, test
+    # for an error condition. Also, we should seriously
+    # rethink this test setup.
+    resp["error"].should == "timeout"
   rescue RuntimeError => e
     e.message.should == "no response"
   rescue Errno::EPIPE