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:32 UTC
couch-mrview commit: updated refs/heads/1993-bigcouch-couch-mrview to
3015c85
Repository: couchdb-couch-mrview
Updated Branches:
refs/heads/1993-bigcouch-couch-mrview 22ec9d906 -> 3015c8554
Add support for multi query views
This adds support for making multiple view queries in one request by
supplying a "queries" list in a POST request body. The primary
implementation was ported over from chttpd_view:multi_query_view/5.
The support added here is two fold. First, we add multi_query_view
support to the single node interface in couch_mrview_http. Second we
add support in couch_mrview_http:view_cb/2 to allow chttpd to utilize
this callback as well.
This also switches updates the #vacc record from setting a multi_query
flag, to instead setting a should_close flag. Now
couch_mrview_http:view_cb/2 will only start a new delayed response if
#vacc.resp is undefined, and similarly, it will only close a delayed
response if #vacc.should_close is true.
COUCHDB-523
COUCHDB-1993
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/3015c855
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/tree/3015c855
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/diff/3015c855
Branch: refs/heads/1993-bigcouch-couch-mrview
Commit: 3015c8554ae38fc3fa7890209c5e394e5995e1c8
Parents: 22ec9d9
Author: Russell Branca <ch...@apache.org>
Authored: Thu Feb 27 11:43:12 2014 -0800
Committer: Russell Branca <ch...@apache.org>
Committed: Thu Feb 27 11:43:12 2014 -0800
----------------------------------------------------------------------
include/couch_mrview.hrl | 2 +-
src/couch_mrview_http.erl | 98 ++++++++++++++----------------------------
src/couch_mrview_util.erl | 24 +++++++++++
3 files changed, 57 insertions(+), 67 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/blob/3015c855/include/couch_mrview.hrl
----------------------------------------------------------------------
diff --git a/include/couch_mrview.hrl b/include/couch_mrview.hrl
index 8791249..b279d8c 100644
--- a/include/couch_mrview.hrl
+++ b/include/couch_mrview.hrl
@@ -87,5 +87,5 @@
resp,
prepend,
etag,
- multi_query
+ should_close = false
}).
http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/blob/3015c855/src/couch_mrview_http.erl
----------------------------------------------------------------------
diff --git a/src/couch_mrview_http.erl b/src/couch_mrview_http.erl
index 87a56b0..f29a089 100644
--- a/src/couch_mrview_http.erl
+++ b/src/couch_mrview_http.erl
@@ -20,6 +20,7 @@
handle_compact_req/3,
handle_cleanup_req/2,
parse_params/2,
+ parse_params/3,
view_cb/2,
row_to_json/1,
row_to_json/2,
@@ -37,7 +38,7 @@
handle_all_docs_req(#httpd{method='GET'}=Req, Db) ->
all_docs_req(Req, Db, undefined);
handle_all_docs_req(#httpd{method='POST'}=Req, Db) ->
- Keys = get_view_keys(couch_httpd:json_body_obj(Req)),
+ Keys = couch_mrview_util:get_view_keys(couch_httpd:json_body_obj(Req)),
all_docs_req(Req, Db, Keys);
handle_all_docs_req(Req, _Db) ->
couch_httpd:send_method_not_allowed(Req, "GET,POST,HEAD").
@@ -50,8 +51,8 @@ handle_view_req(#httpd{method='GET'}=Req, Db, DDoc) ->
handle_view_req(#httpd{method='POST'}=Req, Db, DDoc) ->
[_, _, _, _, ViewName] = Req#httpd.path_parts,
Props = couch_httpd:json_body_obj(Req),
- Keys = get_view_keys(Props),
- Queries = get_view_queries(Props),
+ 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) ->
[couch_stats_collector:increment({httpd, view_reads}) || _I <- Queries],
@@ -76,7 +77,7 @@ handle_temp_view_req(#httpd{method='POST'}=Req, Db) ->
ok = couch_db:check_is_admin(Db),
{Body} = couch_httpd:json_body_obj(Req),
DDoc = couch_mrview_util:temp_view_to_ddoc({Body}),
- Keys = get_view_keys({Body}),
+ Keys = couch_mrview_util:get_view_keys({Body}),
couch_stats_collector:increment({httpd, temporary_view_reads}),
design_doc_view(Req, Db, DDoc, <<"temp">>, Keys);
handle_temp_view_req(Req, _Db) ->
@@ -161,26 +162,16 @@ design_doc_view(Req, Db, DDoc, ViewName, Keys) ->
multi_query_view(Req, Db, DDoc, ViewName, Queries) ->
Args0 = parse_params(Req, undefined),
- %% ETagFun = fun(Sig, Acc0) ->
- %% check_view_etag(Sig, Acc0, Req)
- %% end,
- %% Args = Args0#mrargs{preflight_fun=ETagFun},
- %% Args2 = couch_util:with_db(
- %% DbName,
- %% fun(WDb) ->
- %% {ok, _VInfo, _Sig, Args1} =
- %% couch_mrview_util:get_view(WDb, DDoc, ViewName, Args0),
- %% Args1
- %% end
- %% ),
{ok, _, _, Args1} = couch_mrview_util:get_view(Db, DDoc, ViewName, Args0),
ArgQueries = lists:map(fun({Query}) ->
QueryArg = 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, multi_query=true},
- Headers = [{"ETag", VAcc0#vacc.etag}],
+ 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},
@@ -198,19 +189,13 @@ multi_query_view(Req, Db, DDoc, ViewName, Queries) ->
end.
-view_cb({meta, Meta}, #vacc{resp=undefined, multi_query=undefined}=Acc) ->
+view_cb({meta, Meta}, #vacc{resp=undefined}=Acc) ->
% Map function starting
Headers = [{"ETag", Acc#vacc.etag}],
{ok, Resp} = chttpd:start_delayed_json_response(Acc#vacc.req, 200, Headers),
- view_cb({meta, Meta}, Acc#vacc{resp=Resp});
-view_cb({meta, Meta}, #vacc{resp=Resp, prepend=Prepend0}=Acc) ->
+ view_cb({meta, Meta}, Acc#vacc{resp=Resp, should_close=true});
+view_cb({meta, Meta}, #vacc{resp=Resp}=Acc) ->
% Sending metadata
- Prepend = case Prepend0 of
- undefined ->
- "";
- _ ->
- Prepend0
- end,
Parts = case couch_util:get_value(total, Meta) of
undefined -> [];
Total -> [io_lib:format("\"total_rows\":~p", [Total])]
@@ -221,34 +206,38 @@ view_cb({meta, Meta}, #vacc{resp=Resp, prepend=Prepend0}=Acc) ->
undefined -> [];
UpdateSeq -> [io_lib:format("\"update_seq\":~p", [UpdateSeq])]
end ++ ["\"rows\":["],
+ Prepend = prepend_val(Acc),
Chunk = lists:flatten(Prepend ++ "{" ++ string:join(Parts, ",") ++ "\r\n"),
{ok, Resp1} = chttpd:send_delayed_chunk(Resp, Chunk),
{ok, Acc#vacc{resp=Resp1, prepend=""}};
-view_cb({row, Row}, #vacc{resp=undefined}=Acc) ->
- % Reduce function starting
- Headers = [{"ETag", Acc#vacc.etag}],
- {ok, Resp} = chttpd:start_delayed_json_response(Acc#vacc.req, 200, Headers),
- Chunk = ["{\"rows\":[\r\n", row_to_json(Row)],
- {ok, Resp1} = chttpd:send_delayed_chunk(Resp, Chunk),
- {ok, Acc#vacc{resp=Resp1, prepend=",\r\n"}};
view_cb({row, Row}, Acc) ->
% Adding another row
- Chunk = [Acc#vacc.prepend, row_to_json(Row)],
+ Chunk = [prepend_val(Acc), row_to_json(Row)],
{ok, Resp1} = chttpd:send_delayed_chunk(Acc#vacc.resp, Chunk),
{ok, Acc#vacc{prepend=",\r\n", resp=Resp1}};
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=Resp0, multi_query=true}=Acc) ->
- % Finish current query of a multiquery view output
- {ok, Resp1} = chttpd:send_delayed_chunk(Resp0, "\r\n]}"),
- {ok, Acc#vacc{resp=Resp1, prepend=",\r\n"}};
view_cb(complete, #vacc{resp=Resp}=Acc) ->
- % Finish view output
- chttpd:send_delayed_chunk(Resp, "\r\n]}"),
- chttpd:end_delayed_json_response(Resp),
- {ok, Acc}.
+ % Finish view output and possibly end the response
+ {ok, Resp1} = chttpd:send_delayed_chunk(Resp, "\r\n]}"),
+ 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"}}
+ end.
+
+
+prepend_val(#vacc{prepend=Prepend}) ->
+ case Prepend of
+ undefined ->
+ "";
+ _ ->
+ Prepend
+ end.
row_to_json(Row) ->
@@ -278,29 +267,6 @@ row_to_json(Id0, Row) ->
?JSON_ENCODE(Obj).
-get_view_keys({Props}) ->
- case couch_util:get_value(<<"keys">>, Props) of
- undefined ->
- ?LOG_DEBUG("POST with no keys member.", []),
- undefined;
- Keys when is_list(Keys) ->
- Keys;
- _ ->
- throw({bad_request, "`keys` member must be a array."})
- end.
-
-
-get_view_queries({Props}) ->
- case couch_util:get_value(<<"queries">>, Props) of
- undefined ->
- undefined;
- Queries when is_list(Queries) ->
- Queries;
- _ ->
- throw({bad_request, "`queries` member must be a array."})
- end.
-
-
parse_params(#httpd{}=Req, Keys) ->
parse_params(couch_httpd:qs(Req), Keys);
parse_params(Props, Keys) ->
http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/blob/3015c855/src/couch_mrview_util.erl
----------------------------------------------------------------------
diff --git a/src/couch_mrview_util.erl b/src/couch_mrview_util.erl
index ae8079d..8a36c0b 100644
--- a/src/couch_mrview_util.erl
+++ b/src/couch_mrview_util.erl
@@ -25,6 +25,7 @@
-export([validate_args/1]).
-export([maybe_load_doc/3, maybe_load_doc/4]).
-export([extract_view_reduce/1]).
+-export([get_view_keys/1, get_view_queries/1]).
-define(MOD, couch_mrview_index).
@@ -713,3 +714,26 @@ mrverror(Mesg) ->
extract_view_reduce({red, {N, _Lang, #mrview{reduce_funs=Reds}}, _Ref}) ->
{_Name, FunSrc} = lists:nth(N, Reds),
FunSrc.
+
+
+get_view_keys({Props}) ->
+ case couch_util:get_value(<<"keys">>, Props) of
+ undefined ->
+ ?LOG_DEBUG("POST with no keys member.", []),
+ undefined;
+ Keys when is_list(Keys) ->
+ Keys;
+ _ ->
+ throw({bad_request, "`keys` member must be a array."})
+ end.
+
+
+get_view_queries({Props}) ->
+ case couch_util:get_value(<<"queries">>, Props) of
+ undefined ->
+ undefined;
+ Queries when is_list(Queries) ->
+ Queries;
+ _ ->
+ throw({bad_request, "`queries` member must be a array."})
+ end.