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/03/28 19:45:25 UTC

[1/4] couch-mrview commit: updated refs/heads/1993-bigcouch-couch-mrview to 6cb1bd8

Repository: couchdb-couch-mrview
Updated Branches:
  refs/heads/1993-bigcouch-couch-mrview 83d362f5a -> 6cb1bd8ed (forced update)


Move vacc and lacc records into couch_mrview.hrl for use in chttpd


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/b6582614
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/tree/b6582614
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/diff/b6582614

Branch: refs/heads/1993-bigcouch-couch-mrview
Commit: b6582614ba1da218e47f241eba8d0cdcbbd2edd1
Parents: 3a093fa
Author: Russell Branca <ch...@gmail.com>
Authored: Thu Mar 27 13:57:23 2014 -0700
Committer: Russell Branca <ch...@gmail.com>
Committed: Thu Mar 27 13:57:23 2014 -0700

----------------------------------------------------------------------
 include/couch_mrview.hrl  | 20 ++++++++++++++++++++
 src/couch_mrview_http.erl |  9 ---------
 src/couch_mrview_show.erl | 11 -----------
 3 files changed, 20 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/blob/b6582614/include/couch_mrview.hrl
----------------------------------------------------------------------
diff --git a/include/couch_mrview.hrl b/include/couch_mrview.hrl
index 6a0dfd0..40bb257 100644
--- a/include/couch_mrview.hrl
+++ b/include/couch_mrview.hrl
@@ -80,3 +80,23 @@
     sorted = true,
     extra = []
 }).
+
+-record(vacc, {
+    db,
+    req,
+    resp,
+    prepend,
+    etag,
+    should_close = false
+}).
+
+-record(lacc, {
+    db,
+    req,
+    resp,
+    qserver,
+    lname,
+    etag,
+    code,
+    headers
+}).

http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/blob/b6582614/src/couch_mrview_http.erl
----------------------------------------------------------------------
diff --git a/src/couch_mrview_http.erl b/src/couch_mrview_http.erl
index cf81b33..940bfa0 100644
--- a/src/couch_mrview_http.erl
+++ b/src/couch_mrview_http.erl
@@ -27,15 +27,6 @@
 -include_lib("couch_mrview/include/couch_mrview.hrl").
 
 
--record(vacc, {
-    db,
-    req,
-    resp,
-    prepend,
-    etag
-}).
-
-
 handle_all_docs_req(#httpd{method='GET'}=Req, Db) ->
     all_docs_req(Req, Db, undefined);
 handle_all_docs_req(#httpd{method='POST'}=Req, Db) ->

http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/blob/b6582614/src/couch_mrview_show.erl
----------------------------------------------------------------------
diff --git a/src/couch_mrview_show.erl b/src/couch_mrview_show.erl
index 1be96d5..e08a688 100644
--- a/src/couch_mrview_show.erl
+++ b/src/couch_mrview_show.erl
@@ -21,17 +21,6 @@
 -include_lib("couch/include/couch_db.hrl").
 -include_lib("couch_mrview/include/couch_mrview.hrl").
 
--record(lacc, {
-    db,
-    req,
-    resp,
-    qserver,
-    lname,
-    etag,
-    code,
-    headers
-}).
-
 % /db/_design/foo/_show/bar/docid
 % show converts a json doc to a response of any content-type.
 % it looks up the doc an then passes it to the query server.


[3/4] couch-mrview commit: updated refs/heads/1993-bigcouch-couch-mrview to 6cb1bd8

Posted by ch...@apache.org.
Add mutli view query support

COUCHDB-523


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/3688736b
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/tree/3688736b
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/diff/3688736b

Branch: refs/heads/1993-bigcouch-couch-mrview
Commit: 3688736b81c8b8b6485cb136eea836bd729d152f
Parents: 23c16c0
Author: Russell Branca <ch...@gmail.com>
Authored: Thu Mar 27 14:44:11 2014 -0700
Committer: Russell Branca <ch...@gmail.com>
Committed: Thu Mar 27 14:44:11 2014 -0700

----------------------------------------------------------------------
 src/couch_mrview_http.erl | 50 +++++++++++++++++++++++++++++++++++++++---
 1 file changed, 47 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/blob/3688736b/src/couch_mrview_http.erl
----------------------------------------------------------------------
diff --git a/src/couch_mrview_http.erl b/src/couch_mrview_http.erl
index 5c7133b..94099f5 100644
--- a/src/couch_mrview_http.erl
+++ b/src/couch_mrview_http.erl
@@ -53,9 +53,24 @@ handle_view_req(#httpd{method='GET'}=Req, Db, DDoc) ->
     design_doc_view(Req, Db, DDoc, ViewName, undefined);
 handle_view_req(#httpd{method='POST'}=Req, Db, DDoc) ->
     [_, _, _, _, ViewName] = Req#httpd.path_parts,
-    Keys = get_view_keys(couch_httpd:json_body_obj(Req)),
-    couch_stats_collector:increment({httpd, view_reads}),
-    design_doc_view(Req, Db, DDoc, ViewName, Keys);
+    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) ->
+            [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) ->
     couch_httpd:send_method_not_allowed(Req, "GET,POST,HEAD").
 
@@ -148,6 +163,35 @@ design_doc_view(Req, Db, DDoc, ViewName, Keys) ->
     end.
 
 
+multi_query_view(Req, Db, DDoc, ViewName, Queries) ->
+    Args0 = parse_params(Req, undefined),
+    {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, 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} = couch_mrview:query_view(Db, DDoc, ViewName, Args, fun view_cb/2, Acc0),
+            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.
+
+
 view_cb({meta, Meta}, #vacc{resp=undefined}=Acc) ->
     % Map function starting
     Headers = [{"ETag", Acc#vacc.etag}],


[2/4] couch-mrview commit: updated refs/heads/1993-bigcouch-couch-mrview to 6cb1bd8

Posted by ch...@apache.org.
Allow couch_mrview_http to be more usable in chttpd

This makes a number of updates to useful utility functions in
couch_mrview, especially around parsing of requests, handling view
rows, and interacting with view source code. The `parse_qs` function
was updated to allow for parsing params from json bodies in addition
to just query strings.

The view_cb function is also updated to allow for reuse in chttpd, and
also for better flow control of when to start and complete chunked
responses, which is critical for multi view queries in COUCHDB-523.


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/23c16c0f
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/tree/23c16c0f
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/diff/23c16c0f

Branch: refs/heads/1993-bigcouch-couch-mrview
Commit: 23c16c0ffbcb8a79fb4cf3969b3b698929642597
Parents: b658261
Author: Russell Branca <ch...@gmail.com>
Authored: Thu Mar 27 14:43:14 2014 -0700
Committer: Russell Branca <ch...@gmail.com>
Committed: Thu Mar 27 14:43:31 2014 -0700

----------------------------------------------------------------------
 src/couch_mrview.erl      |   4 +
 src/couch_mrview_http.erl | 168 +++++++++++++++++++++++++----------------
 src/couch_mrview_util.erl |  31 ++++++++
 3 files changed, 137 insertions(+), 66 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/blob/23c16c0f/src/couch_mrview.erl
----------------------------------------------------------------------
diff --git a/src/couch_mrview.erl b/src/couch_mrview.erl
index 29b86d7..d5faca3 100644
--- a/src/couch_mrview.erl
+++ b/src/couch_mrview.erl
@@ -127,6 +127,10 @@ query_view(Db, {Type, View, Ref}, Args, Callback, Acc) ->
     end.
 
 
+get_info(Db, DDocId) when is_binary(DDocId) ->
+    DbName = mem3:dbname(Db#db.name),
+    {ok, DDoc} = ddoc_cache:open(DbName, DDocId),
+    get_info(Db, DDoc);
 get_info(Db, DDoc) ->
     {ok, Pid} = couch_index_server:get_index(couch_mrview_index, Db, DDoc),
     couch_index:get_info(Pid).

http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/blob/23c16c0f/src/couch_mrview_http.erl
----------------------------------------------------------------------
diff --git a/src/couch_mrview_http.erl b/src/couch_mrview_http.erl
index 940bfa0..5c7133b 100644
--- a/src/couch_mrview_http.erl
+++ b/src/couch_mrview_http.erl
@@ -18,10 +18,21 @@
     handle_temp_view_req/2,
     handle_info_req/3,
     handle_compact_req/3,
-    handle_cleanup_req/2,
-    parse_qs/2
+    handle_cleanup_req/2
 ]).
 
+-export([
+    parse_boolean/1,
+    parse_int/1,
+    parse_pos_int/1,
+    prepend_val/1,
+    parse_params/2,
+    parse_params/3,
+    view_cb/2,
+    row_to_json/1,
+    row_to_json/2,
+    check_view_etag/3
+]).
 
 -include_lib("couch/include/couch_db.hrl").
 -include_lib("couch_mrview/include/couch_mrview.hrl").
@@ -30,7 +41,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").
@@ -54,7 +65,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) ->
@@ -106,13 +117,9 @@ all_docs_req(Req, Db, Keys) ->
 
 
 do_all_docs_req(Req, Db, Keys) ->
-    Args0 = parse_qs(Req, Keys),
+    Args0 = parse_params(Req, Keys),
     ETagFun = fun(Sig, Acc0) ->
-        ETag = couch_httpd:make_etag(Sig),
-        case couch_httpd:etag_match(Req, ETag) of
-            true -> throw({etag_match, ETag});
-            false -> {ok, Acc0#vacc{etag=ETag}}
-        end
+        check_view_etag(Sig, Acc0, Req)
     end,
     Args = Args0#mrargs{preflight_fun=ETagFun},
     {ok, Resp} = couch_httpd:etag_maybe(Req, fun() ->
@@ -126,13 +133,9 @@ do_all_docs_req(Req, Db, Keys) ->
 
 
 design_doc_view(Req, Db, DDoc, ViewName, Keys) ->
-    Args0 = parse_qs(Req, Keys),
+    Args0 = parse_params(Req, Keys),
     ETagFun = fun(Sig, Acc0) ->
-        ETag = couch_httpd:make_etag(Sig),
-        case couch_httpd:etag_match(Req, ETag) of
-            true -> throw({etag_match, ETag});
-            false -> {ok, Acc0#vacc{etag=ETag}}
-        end
+        check_view_etag(Sig, Acc0, Req)
     end,
     Args = Args0#mrargs{preflight_fun=ETagFun},
     {ok, Resp} = couch_httpd:etag_maybe(Req, fun() ->
@@ -146,9 +149,12 @@ design_doc_view(Req, Db, DDoc, ViewName, Keys) ->
 
 
 view_cb({meta, Meta}, #vacc{resp=undefined}=Acc) ->
-    Headers = [{"ETag", Acc#vacc.etag}],
-    {ok, Resp} = couch_httpd:start_json_response(Acc#vacc.req, 200, Headers),
     % 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, should_close=true});
+view_cb({meta, Meta}, #vacc{resp=Resp}=Acc) ->
+    % Sending metadata
     Parts = case couch_util:get_value(total, Meta) of
         undefined -> [];
         Total -> [io_lib:format("\"total_rows\":~p", [Total])]
@@ -159,28 +165,41 @@ view_cb({meta, Meta}, #vacc{resp=undefined}=Acc) ->
         undefined -> [];
         UpdateSeq -> [io_lib:format("\"update_seq\":~p", [UpdateSeq])]
     end ++ ["\"rows\":["],
-    Chunk = lists:flatten("{" ++ string:join(Parts, ",") ++ "\r\n"),
-    couch_httpd:send_chunk(Resp, Chunk),
-    {ok, Acc#vacc{resp=Resp, prepend=""}};
-view_cb({row, Row}, #vacc{resp=undefined}=Acc) ->
-    % Reduce function starting
-    Headers = [{"ETag", Acc#vacc.etag}],
-    {ok, Resp} = couch_httpd:start_json_response(Acc#vacc.req, 200, Headers),
-    couch_httpd:send_chunk(Resp, ["{\"rows\":[\r\n", row_to_json(Row)]),
-    {ok, #vacc{resp=Resp, prepend=",\r\n"}};
+    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}, Acc) ->
     % Adding another row
-    couch_httpd:send_chunk(Acc#vacc.resp, [Acc#vacc.prepend, row_to_json(Row)]),
-    {ok, Acc#vacc{prepend=",\r\n"}};
+    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} = couch_httpd:send_json(Acc#vacc.req, 200, {[{rows, []}]}),
+    {ok, Resp} = chttpd:send_json(Acc#vacc.req, 200, {[{rows, []}]}),
     {ok, Acc#vacc{resp=Resp}};
-view_cb(complete, Acc) ->
-    % Finish view output
-    couch_httpd:send_chunk(Acc#vacc.resp, "\r\n]}"),
-    couch_httpd:end_json_response(Acc#vacc.resp),
-    {ok, Acc}.
+view_cb(complete, #vacc{resp=Resp}=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;
+view_cb({error, Reason}, #vacc{resp=Resp}=Acc) ->
+    {ok, Resp1} = chttpd:send_delayed_error(Resp, Reason),
+    {ok, Acc#vacc{resp=Resp1}}.
+
+
+prepend_val(#vacc{prepend=Prepend}) ->
+    case Prepend of
+        undefined ->
+            "";
+        _ ->
+            Prepend
+    end.
 
 
 row_to_json(Row) ->
@@ -210,59 +229,56 @@ 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.
+parse_params(#httpd{}=Req, Keys) ->
+    parse_params(couch_httpd:qs(Req), Keys);
+parse_params(Props, Keys) ->
+    Args = #mrargs{},
+    parse_params(Props, Keys, Args).
 
 
-parse_qs(Req, Keys) ->
-    Args = #mrargs{keys=Keys},
+parse_params(Props, Keys, #mrargs{}=Args0) ->
+    Args = Args0#mrargs{keys=Keys},
     lists:foldl(fun({K, V}, Acc) ->
-        parse_qs(K, V, Acc)
-    end, Args, couch_httpd:qs(Req)).
+        parse_param(K, V, Acc)
+    end, Args, Props).
 
 
-parse_qs(Key, Val, Args) ->
+parse_param(Key, Val, Args) when is_binary(Key) ->
+    parse_param(binary_to_list(Key), Val, Args);
+parse_param(Key, Val, Args) ->
     case Key of
         "" ->
             Args;
         "reduce" ->
             Args#mrargs{reduce=parse_boolean(Val)};
         "key" ->
-            JsonKey = ?JSON_DECODE(Val),
+            JsonKey = parse_json(Val),
             Args#mrargs{start_key=JsonKey, end_key=JsonKey};
         "keys" ->
-            Args#mrargs{keys=?JSON_DECODE(Val)};
+            Args#mrargs{keys=parse_json(Val)};
         "startkey" ->
-            Args#mrargs{start_key=?JSON_DECODE(Val)};
+            Args#mrargs{start_key=parse_json(Val)};
         "start_key" ->
-            Args#mrargs{start_key=?JSON_DECODE(Val)};
+            Args#mrargs{start_key=parse_json(Val)};
         "startkey_docid" ->
-            Args#mrargs{start_key_docid=list_to_binary(Val)};
+            Args#mrargs{start_key_docid=couch_util:to_binary(Val)};
         "start_key_doc_id" ->
-            Args#mrargs{start_key_docid=list_to_binary(Val)};
+            Args#mrargs{start_key_docid=couch_util:to_binary(Val)};
         "endkey" ->
-            Args#mrargs{end_key=?JSON_DECODE(Val)};
+            Args#mrargs{end_key=parse_json(Val)};
         "end_key" ->
-            Args#mrargs{end_key=?JSON_DECODE(Val)};
+            Args#mrargs{end_key=parse_json(Val)};
         "endkey_docid" ->
-            Args#mrargs{end_key_docid=list_to_binary(Val)};
+            Args#mrargs{end_key_docid=couch_util:to_binary(Val)};
         "end_key_doc_id" ->
-            Args#mrargs{end_key_docid=list_to_binary(Val)};
+            Args#mrargs{end_key_docid=couch_util:to_binary(Val)};
         "limit" ->
             Args#mrargs{limit=parse_pos_int(Val)};
         "count" ->
             throw({query_parse_error, <<"QS param `count` is not `limit`">>});
-        "stale" when Val == "ok" ->
+        "stale" when Val == "ok" orelse Val == <<"ok">> ->
             Args#mrargs{stale=ok};
-        "stale" when Val == "update_after" ->
+        "stale" when Val == "update_after" orelse Val == "update_after" ->
             Args#mrargs{stale=update_after};
         "stale" ->
             throw({query_parse_error, <<"Invalid value for `stale`.">>});
@@ -289,16 +305,20 @@ parse_qs(Key, Val, Args) ->
         "conflicts" ->
             Args#mrargs{conflicts=parse_boolean(Val)};
         "list" ->
-            Args#mrargs{list=list_to_binary(Val)};
+            Args#mrargs{list=couch_util:to_binary(Val)};
         "callback" ->
-            Args#mrargs{callback=list_to_binary(Val)};
+            Args#mrargs{callback=couch_util:to_binary(Val)};
         _ ->
-            BKey = list_to_binary(Key),
-            BVal = list_to_binary(Val),
+            BKey = couch_util:to_binary(Key),
+            BVal = couch_util:to_binary(Val),
             Args#mrargs{extra=[{BKey, BVal} | Args#mrargs.extra]}
     end.
 
 
+parse_boolean(true) ->
+    true;
+parse_boolean(false) ->
+    false;
 parse_boolean(Val) ->
     case string:to_lower(Val) of
     "true" -> true;
@@ -309,6 +329,8 @@ parse_boolean(Val) ->
     end.
 
 
+parse_int(Val) when is_integer(Val) ->
+    Val;
 parse_int(Val) ->
     case (catch list_to_integer(Val)) of
     IntVal when is_integer(IntVal) ->
@@ -328,3 +350,17 @@ parse_pos_int(Val) ->
         Msg = io_lib:format(Fmt, [Val]),
         throw({query_parse_error, ?l2b(Msg)})
     end.
+
+
+check_view_etag(Sig, Acc0, Req) ->
+    ETag = couch_httpd:make_etag(Sig),
+    case couch_httpd:etag_match(Req, ETag) of
+        true -> throw({etag_match, ETag});
+        false -> {ok, Acc0#vacc{etag=ETag}}
+    end.
+
+
+parse_json(V) when is_list(V) ->
+    ?JSON_DECODE(V);
+parse_json(V) ->
+    V.

http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/blob/23c16c0f/src/couch_mrview_util.erl
----------------------------------------------------------------------
diff --git a/src/couch_mrview_util.erl b/src/couch_mrview_util.erl
index 27baa4a..815bf08 100644
--- a/src/couch_mrview_util.erl
+++ b/src/couch_mrview_util.erl
@@ -24,6 +24,9 @@
 -export([calculate_data_size/2]).
 -export([validate_args/1]).
 -export([maybe_load_doc/3, maybe_load_doc/4]).
+-export([extract_view/4, extract_view_reduce/1]).
+-export([get_view_keys/1, get_view_queries/1]).
+-export([set_view_type/3]).
 
 -define(MOD, couch_mrview_index).
 
@@ -708,3 +711,31 @@ index_of(Key, [_ | Rest], Idx) ->
 
 mrverror(Mesg) ->
     throw({query_parse_error, 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.


[4/4] couch-mrview commit: updated refs/heads/1993-bigcouch-couch-mrview to 6cb1bd8

Posted by ch...@apache.org.
Allow couch_mrview_show to be more fully utilized by chttpd_show


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/6cb1bd8e
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/tree/6cb1bd8e
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/diff/6cb1bd8e

Branch: refs/heads/1993-bigcouch-couch-mrview
Commit: 6cb1bd8eda740b322f0128ef8638e704c945c2b8
Parents: 3688736
Author: Russell Branca <ch...@gmail.com>
Authored: Thu Mar 27 14:45:10 2014 -0700
Committer: Russell Branca <ch...@gmail.com>
Committed: Thu Mar 27 14:45:10 2014 -0700

----------------------------------------------------------------------
 src/couch_mrview_show.erl | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/blob/6cb1bd8e/src/couch_mrview_show.erl
----------------------------------------------------------------------
diff --git a/src/couch_mrview_show.erl b/src/couch_mrview_show.erl
index e08a688..4591c5d 100644
--- a/src/couch_mrview_show.erl
+++ b/src/couch_mrview_show.erl
@@ -15,7 +15,8 @@
 -export([
     handle_doc_show_req/3,
     handle_doc_update_req/3,
-    handle_view_list_req/3
+    handle_view_list_req/3,
+    list_cb/2
 ]).
 
 -include_lib("couch/include/couch_db.hrl").
@@ -182,7 +183,7 @@ handle_view_list_req(Req, _Db, _DDoc) ->
 
 
 handle_view_list(Req, Db, DDoc, LName, VDDoc, VName, Keys) ->
-    Args0 = couch_mrview_http:parse_qs(Req, Keys),
+    Args0 = couch_mrview_http:parse_params(Req, Keys),
     ETagFun = fun(BaseSig, Acc0) ->
         UserCtx = Req#httpd.user_ctx,
         Name = UserCtx#user_ctx.name,
@@ -240,7 +241,7 @@ list_cb(complete, Acc) ->
 
 start_list_resp(Head, Acc) ->
     #lacc{db=Db, req=Req, qserver=QServer, lname=LName} = Acc,
-    JsonReq = couch_httpd_external:json_req_obj(Req, Db),
+    JsonReq = json_req_obj(Req, Db),
 
     [<<"start">>,Chunk,JsonResp] = couch_query_servers:ddoc_proc_prompt(QServer,
         [<<"lists">>, LName], [Head, JsonReq]),
@@ -350,3 +351,13 @@ json_apply_field({Key, NewValue}, [], Acc) ->
     % end of list, add ours
     {[{Key, NewValue}|Acc]}.
 
+
+% This loads the db info if we have a fully loaded db record, but we might not
+% have the db locally on this node, so then load the info through fabric.
+json_req_obj(Req, #db{main_pid=Pid}=Db) when is_pid(Pid) ->
+    couch_httpd_external:json_req_obj(Req, Db);
+json_req_obj(Req, Db) ->
+    % use a separate process because we're already in a receive loop, and
+    % json_req_obj calls fabric:get_db_info()
+    spawn_monitor(fun() -> exit(chttpd_external:json_req_obj(Req, Db)) end),
+    receive {'DOWN', _, _, _, JsonReq} -> JsonReq end.