You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ch...@apache.org on 2014/02/27 21:02:25 UTC

chttpd commit: updated refs/heads/1993-bigcouch-couch-mrview to b78d2e7

Repository: couchdb-chttpd
Updated Branches:
  refs/heads/1993-bigcouch-couch-mrview 6dcd0f191 -> b78d2e78c


Update chttpd_view to use couch_mrview for multi query views

This switches to using the couch_mrview implementation for handling
multi query view requests, both for fetching the views through fabric
and also the http callbacks.

One concern I have with this implementation that needs to be tested,
is whether calling couch_mrview_util:get_view in multi_query_view is
appropriate. What happens when the database or the ddoc does not exist
on the node handling this request? I think the ddoc should be fine as
we load that from the ddoc_cache, but I'm less sure about the db. We
need to make this request so we can perform the validations on the
view, both for the url query params, and also for every set of
additional params provided in the list of queries.

COUCHDB-523
COUCHDB-1993


Project: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/commit/b78d2e78
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/tree/b78d2e78
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/diff/b78d2e78

Branch: refs/heads/1993-bigcouch-couch-mrview
Commit: b78d2e78cae88116bf89a3a16735e86ab5bea228
Parents: 6dcd0f1
Author: Russell Branca <ch...@apache.org>
Authored: Thu Feb 27 11:50:30 2014 -0800
Committer: Russell Branca <ch...@apache.org>
Committed: Thu Feb 27 11:50:30 2014 -0800

----------------------------------------------------------------------
 src/chttpd_db.erl   |  2 +-
 src/chttpd_view.erl | 98 ++++++++++++++++++++++++------------------------
 2 files changed, 51 insertions(+), 49 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/b78d2e78/src/chttpd_db.erl
----------------------------------------------------------------------
diff --git a/src/chttpd_db.erl b/src/chttpd_db.erl
index 17299d6..742c09b 100644
--- a/src/chttpd_db.erl
+++ b/src/chttpd_db.erl
@@ -478,7 +478,7 @@ db_req(#httpd{path_parts=[_, DocId | FileNameParts]}=Req, Db) ->
     db_attachment_req(Req, Db, DocId, FileNameParts).
 
 all_docs_view(Req, Db, Keys) ->
-    Args0 = couch_mrview_http:parse_qs(Req, Keys),
+    Args0 = couch_mrview_http:parse_params(Req, Keys),
     ETagFun = fun(Sig, Acc0) ->
         couch_mrview_http:check_view_etag(Sig, Acc0, Req)
     end,

http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/b78d2e78/src/chttpd_view.erl
----------------------------------------------------------------------
diff --git a/src/chttpd_view.erl b/src/chttpd_view.erl
index 057962a..eedf266 100644
--- a/src/chttpd_view.erl
+++ b/src/chttpd_view.erl
@@ -16,41 +16,41 @@
 
 -export([handle_view_req/3, handle_temp_view_req/2, get_reduce_type/1]).
 
-%% TODO: fix multi_query_view
-%% multi_query_view(Req, Db, DDoc, ViewName, Queries) ->
-%%     Group = couch_view_group:design_doc_to_view_group(DDoc),
-%%     IsReduce = get_reduce_type(Req),
-%%     ViewType = extract_view_type(ViewName, couch_view_group:get_views(Group),
-%%         IsReduce),
-%%     % TODO proper calculation of etag
-%%     % Etag = view_group_etag(ViewGroup, Db, Queries),
-%%     Etag = couch_uuids:new(),
-%%     DefaultParams = lists:flatmap(fun({K,V}) -> parse_view_param(K,V) end,
-%%         chttpd:qs(Req)),
-%%     [couch_stats_collector:increment({httpd, view_reads}) || _I <- Queries],
-%%     chttpd:etag_respond(Req, Etag, fun() ->
-%%         FirstChunk = "{\"results\":[",
-%%         {ok, Resp} = chttpd:start_delayed_json_response(Req, 200, [{"Etag",Etag}], FirstChunk),
-%%         {_, Resp1} = lists:foldl(fun({QueryProps}, {Chunk, RespAcc}) ->
-%%             if Chunk =/= nil -> chttpd:send_delayed_chunk(Resp, Chunk); true -> ok end,
-%%             ThisQuery = lists:flatmap(fun parse_json_view_param/1, QueryProps),
-%%             FullParams = lists:ukeymerge(1, ThisQuery, DefaultParams),
-%%             {ok, RespAcc1} = fabric:query_view(
-%%                 Db,
-%%                 DDoc,
-%%                 ViewName,
-%%                 fun couch_mrview_http:view_cb/2,
-%%                 {nil, RespAcc},
-%%                 parse_view_params(FullParams, nil, ViewType)
-%%             ),
-%%             {",\n", RespAcc1}
-%%         end, {nil,Resp}, Queries),
-%%         chttpd:send_delayed_chunk(Resp1, "]}"),
-%%         chttpd:end_delayed_json_response(Resp1)
-%%     end).
+multi_query_view(Req, Db, DDoc, ViewName, Queries) ->
+    Args0 = couch_mrview_http:parse_params(Req, undefined),
+    DbName = mem3:dbname(Db#db.name),
+    Args1 = couch_util:with_db(DbName, fun(WDb) ->
+        {ok, _, _, Args} = couch_mrview_util:get_view(WDb, DDoc, ViewName, Args0),
+        Args
+    end),
+    ArgQueries = lists:map(fun({Query}) ->
+        QueryArg = couch_mrview_http:parse_params(Query, undefined, Args1),
+        couch_mrview_util:validate_args(QueryArg)
+    end, Queries),
+    {ok, Resp2} = couch_httpd:etag_maybe(Req, fun() ->
+        VAcc0 = #vacc{db=Db, req=Req, prepend="\r\n"},
+        %% TODO: proper calculation of etag
+        Etag = couch_uuids:new(),
+        Headers = [{"ETag", Etag}],
+        FirstChunk = "{\"results\":[",
+        {ok, Resp0} = chttpd:start_delayed_json_response(VAcc0#vacc.req, 200, Headers, FirstChunk),
+        VAcc1 = VAcc0#vacc{resp=Resp0},
+        VAcc2 = lists:foldl(fun(Args, Acc0) ->
+            {ok, Acc1} = fabric:query_view(Db, DDoc, ViewName, fun couch_mrview_http:view_cb/2, Acc0, Args),
+            Acc1
+        end, VAcc1, ArgQueries),
+        {ok, Resp1} = chttpd:send_delayed_chunk(VAcc2#vacc.resp, "\r\n]}"),
+        {ok, Resp2} = chttpd:end_delayed_json_response(Resp1),
+        {ok, VAcc2#vacc{resp=Resp2}}
+    end),
+    case is_record(Resp2, vacc) of
+        true -> {ok, Resp2#vacc.resp};
+        _ -> {ok, Resp2}
+    end.
+
 
 design_doc_view(Req, Db, DDoc, ViewName, Keys) ->
-    Args0 = couch_mrview_http:parse_qs(Req, Keys),
+    Args0 = couch_mrview_http:parse_params(Req, Keys),
     ETagFun = fun(Sig, Acc0) ->
         couch_mrview_http:check_view_etag(Sig, Acc0, Req)
     end,
@@ -66,27 +66,29 @@ design_doc_view(Req, Db, DDoc, ViewName, Keys) ->
 
 handle_view_req(#httpd{method='GET',
         path_parts=[_, _, _, _, ViewName]}=Req, Db, DDoc) ->
+    couch_stats_collector:increment({httpd, view_reads}),
     Keys = chttpd:qs_json_value(Req, "keys", undefined),
     design_doc_view(Req, Db, DDoc, ViewName, Keys);
 
 handle_view_req(#httpd{method='POST',
         path_parts=[_, _, _, _, ViewName]}=Req, Db, DDoc) ->
-    {Fields} = chttpd:json_body_obj(Req),
-    Queries = couch_util:get_value(<<"queries">>, Fields),
-    Keys = couch_util:get_value(<<"keys">>, Fields),
+    Props = couch_httpd:json_body_obj(Req),
+    Keys = couch_mrview_util:get_view_keys(Props),
+    Queries = couch_mrview_util:get_view_queries(Props),
     case {Queries, Keys} of
-    %% {Queries, undefined} when is_list(Queries) ->
-    %%     multi_query_view(Req, Db, DDoc, ViewName, Queries);
-    {undefined, Keys} when is_list(Keys) ->
-        design_doc_view(Req, Db, DDoc, ViewName, Keys);
-    {undefined, undefined} ->
-        throw({bad_request, "POST body must contain `keys` or `queries` field"});
-    {undefined, _} ->
-        throw({bad_request, "`keys` body member must be an array"});
-    {_, undefined} ->
-        throw({bad_request, "`queries` body member must be an array"});
-    {_, _} ->
-        throw({bad_request, "`keys` and `queries` are mutually exclusive"})
+        {Queries, undefined} when is_list(Queries) ->
+            [couch_stats_collector:increment({httpd, view_reads}) || _I <- Queries],
+            multi_query_view(Req, Db, DDoc, ViewName, Queries);
+        {undefined, Keys} when is_list(Keys) ->
+            couch_stats_collector:increment({httpd, view_reads}),
+            design_doc_view(Req, Db, DDoc, ViewName, Keys);
+        {undefined, undefined} ->
+            throw({
+                bad_request,
+                "POST body must contain `keys` or `queries` field"
+            });
+        {_, _} ->
+            throw({bad_request, "`keys` and `queries` are mutually exclusive"})
     end;
 
 handle_view_req(Req, _Db, _DDoc) ->