You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by rn...@apache.org on 2016/08/25 18:00:13 UTC

[3/3] couch-mrview commit: updated refs/heads/master to 9133f6d

Fix sorted=false for multi-query

I've reordered view_cb for readability, moving all response starting
logic to the front, in order to simplify how meta and row messages are
handled

COUCHDB-3060


Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/commit/9133f6d1
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/tree/9133f6d1
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/diff/9133f6d1

Branch: refs/heads/master
Commit: 9133f6d1612374e73f18f13244a32ce8678aab67
Parents: e936267
Author: Robert Newson <rn...@apache.org>
Authored: Thu Aug 25 17:58:34 2016 +0100
Committer: Robert Newson <rn...@apache.org>
Committed: Thu Aug 25 18:27:19 2016 +0100

----------------------------------------------------------------------
 include/couch_mrview.hrl  |  3 +-
 src/couch_mrview_http.erl | 94 +++++++++++++++++++++++-------------------
 2 files changed, 54 insertions(+), 43 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/blob/9133f6d1/include/couch_mrview.hrl
----------------------------------------------------------------------
diff --git a/include/couch_mrview.hrl b/include/couch_mrview.hrl
index 2dfd398..bfd20ad 100644
--- a/include/couch_mrview.hrl
+++ b/include/couch_mrview.hrl
@@ -99,7 +99,8 @@
     buffer = [],
     bufsize = 0,
     threshold = 1490,
-    row_sent = false
+    row_sent = false,
+    meta_sent = false
 }).
 
 -record(lacc, {

http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/blob/9133f6d1/src/couch_mrview_http.erl
----------------------------------------------------------------------
diff --git a/src/couch_mrview_http.erl b/src/couch_mrview_http.erl
index aa39912..b554e36 100644
--- a/src/couch_mrview_http.erl
+++ b/src/couch_mrview_http.erl
@@ -309,7 +309,7 @@ multi_query_view(Req, Db, DDoc, ViewName, Queries) ->
         VAcc1 = VAcc0#vacc{resp=Resp0},
         VAcc2 = lists:foldl(fun(Args, Acc0) ->
             {ok, Acc1} = couch_mrview:query_view(Db, DDoc, ViewName, Args, fun view_cb/2, Acc0),
-            reset_vacc(Acc1)
+            Acc1
         end, VAcc1, ArgQueries),
         {ok, Resp1} = chttpd:send_delayed_chunk(VAcc2#vacc.resp, "\r\n]}"),
         {ok, Resp2} = chttpd:end_delayed_json_response(Resp1),
@@ -320,11 +320,6 @@ multi_query_view(Req, Db, DDoc, ViewName, Queries) ->
         _ -> {ok, Resp2}
     end.
 
-%% reset between queries in multi-query
-reset_vacc(Vacc) ->
-    Vacc#vacc{row_sent=false}.
-
-
 filtered_view_cb({row, Row0}, Acc) ->
   Row1 = lists:map(fun({doc, null}) ->
         {doc, null};
@@ -339,16 +334,44 @@ filtered_view_cb(Obj, Acc) ->
     view_cb(Obj, Acc).
 
 
-view_cb({meta, Meta}, #vacc{resp=undefined}=Acc) ->
-    % Map function starting
+%% these clauses start (and possibly end) the response
+view_cb({error, Reason}, #vacc{resp=undefined}=Acc) ->
+    {ok, Resp} = chttpd:send_error(Acc#vacc.req, Reason),
+    {ok, Acc#vacc{resp=Resp}};
+
+view_cb(complete, #vacc{resp=undefined}=Acc) ->
+    % Nothing in view
+    {ok, Resp} = chttpd:send_json(Acc#vacc.req, 200, {[{rows, []}]}),
+    {ok, Acc#vacc{resp=Resp}};
+
+view_cb(Msg, #vacc{resp=undefined}=Acc) ->
+    %% Start response
     Headers = [],
     {ok, Resp} = chttpd:start_delayed_json_response(Acc#vacc.req, 200, Headers),
-    view_cb({meta, Meta}, Acc#vacc{resp=Resp, should_close=true});
-view_cb({meta, _Meta}, #vacc{row_sent=true}=Acc) ->
-    % sorted=false and meta arrived late, ignore it.
-    {ok, Acc};
-view_cb({meta, Meta}, #vacc{}=Acc) ->
-    % Sending metadata
+    view_cb(Msg, Acc#vacc{resp=Resp, should_close=true});
+
+%% ---------------------------------------------------
+
+%% From here on down, the response has been started.
+
+view_cb({error, Reason}, #vacc{resp=Resp}=Acc) ->
+    {ok, Resp1} = chttpd:send_delayed_error(Resp, Reason),
+    {ok, Acc#vacc{resp=Resp1}};
+
+view_cb(complete, #vacc{resp=Resp, buffer=Buf, threshold=Max}=Acc) ->
+    % Finish view output and possibly end the response
+    {ok, Resp1} = chttpd:close_delayed_json_object(Resp, Buf, "\r\n]}", Max),
+    case Acc#vacc.should_close of
+        true ->
+            {ok, Resp2} = chttpd:end_delayed_json_response(Resp1),
+            {ok, Acc#vacc{resp=Resp2}};
+        _ ->
+            {ok, Acc#vacc{resp=Resp1, meta_sent=false, row_sent=false,
+                prepend=",\r\n", buffer=[], bufsize=0}}
+    end;
+
+view_cb({meta, Meta}, #vacc{meta_sent=false, row_sent=false}=Acc) ->
+    % Sending metadata as we've not sent it or any row yet
     Parts = case couch_util:get_value(total, Meta) of
         undefined -> [];
         Total -> [io_lib:format("\"total_rows\":~p", [Total])]
@@ -364,36 +387,23 @@ view_cb({meta, Meta}, #vacc{}=Acc) ->
     end ++ ["\"rows\":["],
     Chunk = [prepend_val(Acc), "{", string:join(Parts, ","), "\r\n"],
     {ok, AccOut} = maybe_flush_response(Acc, Chunk, iolist_size(Chunk)),
-    {ok, AccOut#vacc{prepend=""}};
-view_cb({row, Row}, #vacc{resp=undefined}=Acc) ->
-    % sorted=false and a row arrived before meta, start response.
-    Pre = "{\"rows\":[\r\n",
-    {ok, Resp} = chttpd:start_delayed_json_response(Acc#vacc.req, 200, []),
-    view_cb({row, Row}, Acc#vacc{row_sent=true,resp=Resp, prepend=Pre, should_close=true});
-view_cb({row, Row}, Acc) ->
+    {ok, AccOut#vacc{prepend="", meta_sent=true}};
+
+view_cb({meta, _Meta}, #vacc{}=Acc) ->
+    %% ignore metadata
+    {ok, Acc};
+
+view_cb({row, Row}, #vacc{meta_sent=false}=Acc) ->
+    %% sorted=false and row arrived before meta
+    % Adding another row
+    Chunk = [prepend_val(Acc), "{\"rows\":[\r\n", row_to_json(Row)],
+    maybe_flush_response(Acc#vacc{meta_sent=true, row_sent=true}, Chunk, iolist_size(Chunk));
+
+view_cb({row, Row}, #vacc{meta_sent=true}=Acc) ->
     % Adding another row
     Chunk = [prepend_val(Acc), row_to_json(Row)],
-    maybe_flush_response(Acc#vacc{row_sent=true}, Chunk, iolist_size(Chunk));
-view_cb(complete, #vacc{resp=undefined}=Acc) ->
-    % Nothing in view
-    {ok, Resp} = chttpd:send_json(Acc#vacc.req, 200, {[{rows, []}]}),
-    {ok, Acc#vacc{resp=Resp}};
-view_cb(complete, #vacc{resp=Resp, buffer=Buf, threshold=Max}=Acc) ->
-    % Finish view output and possibly end the response
-    {ok, Resp1} = chttpd:close_delayed_json_object(Resp, Buf, "\r\n]}", Max),
-    case Acc#vacc.should_close of
-        true ->
-            {ok, Resp2} = chttpd:end_delayed_json_response(Resp1),
-            {ok, Acc#vacc{resp=Resp2}};
-        _ ->
-            {ok, Acc#vacc{resp=Resp1, prepend=",\r\n", buffer=[], bufsize=0}}
-    end;
-view_cb({error, Reason}, #vacc{resp=undefined}=Acc) ->
-    {ok, Resp} = chttpd:send_error(Acc#vacc.req, Reason),
-    {ok, Acc#vacc{resp=Resp}};
-view_cb({error, Reason}, #vacc{resp=Resp}=Acc) ->
-    {ok, Resp1} = chttpd:send_delayed_error(Resp, Reason),
-    {ok, Acc#vacc{resp=Resp1}}.
+    maybe_flush_response(Acc#vacc{row_sent=true}, Chunk, iolist_size(Chunk)).
+
 
 maybe_flush_response(#vacc{bufsize=Size, threshold=Max} = Acc, Data, Len)
         when Size > 0 andalso (Size + Len) > Max ->