couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rnew...@apache.org
Subject [2/4] couch-mrview commit: updated refs/heads/master to 01cff34
Date Tue, 06 May 2014 16:33:22 GMT
Merge remote-tracking branch 'origin/1993-bigcouch-couch-mrview'

Conflicts:
	src/couch_mrview_http.erl
	src/couch_mrview_util.erl


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

Branch: refs/heads/master
Commit: a81627207e4f1e84a96164536dfe85292c88603a
Parents: 86de6cc c186e47
Author: Robert Newson <rnewson@apache.org>
Authored: Tue May 6 16:57:46 2014 +0100
Committer: Robert Newson <rnewson@apache.org>
Committed: Tue May 6 16:57:46 2014 +0100

----------------------------------------------------------------------
 include/couch_mrview.hrl  |  20 ++++
 src/couch_mrview.erl      |   4 +
 src/couch_mrview_http.erl | 228 +++++++++++++++++++++++++++--------------
 src/couch_mrview_show.erl |  28 ++---
 src/couch_mrview_util.erl |  30 ++++++
 5 files changed, 218 insertions(+), 92 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/blob/a8162720/include/couch_mrview.hrl
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/blob/a8162720/src/couch_mrview_http.erl
----------------------------------------------------------------------
diff --cc src/couch_mrview_http.erl
index 302efde,8735187..fc0a143
--- a/src/couch_mrview_http.erl
+++ b/src/couch_mrview_http.erl
@@@ -129,14 -130,11 +146,10 @@@ all_docs_req(Req, Db, Keys) -
          do_all_docs_req(Req, Db, Keys)
      end.
  
 -
  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() ->
@@@ -154,35 -146,11 +167,31 @@@
          _ -> {ok, Resp}
      end.
  
 +is_admin(Db) ->
 +    case catch couch_db:check_is_admin(Db) of
 +    {unauthorized, _} ->
 +        false;
 +    ok ->
 +        true
 +    end.
 +
 +
 +% admin users always get all fields
 +get_view_callback(_, _, true) ->
 +    fun view_cb/2;
 +% if we are operating on the users db and we aren't
 +% admin, filter the view
 +get_view_callback(_DbName, _DbName, false) ->
 +    fun filtered_view_cb/2;
 +% non _users databases get all fields
 +get_view_callback(_, _, _) ->
 +    fun view_cb/2.
 +
  
  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() ->
@@@ -195,24 -163,42 +204,55 @@@
      end.
  
  
 +filtered_view_cb({row, Row0}, Acc) ->
 +  Row1 = lists:map(fun({doc, null}) ->
 +        {doc, null};
 +    ({doc, Body}) ->
 +        Doc = couch_users_db:strip_non_public_fields(#doc{body=Body}),
 +        {doc, Doc#doc.body};
 +    (KV) ->
 +        KV
 +    end, Row0),
 +    view_cb({row, Row1}, Acc);
 +filtered_view_cb(Obj, Acc) ->
 +    view_cb(Obj, Acc).
 +
+ 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) ->
-     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])]

http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/blob/a8162720/src/couch_mrview_show.erl
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/blob/a8162720/src/couch_mrview_util.erl
----------------------------------------------------------------------
diff --cc src/couch_mrview_util.erl
index fc3ebfe,815bf08..cbba5ac
--- a/src/couch_mrview_util.erl
+++ b/src/couch_mrview_util.erl
@@@ -24,7 -24,9 +24,10 @@@
  -export([calculate_data_size/2]).
  -export([validate_args/1]).
  -export([maybe_load_doc/3, maybe_load_doc/4]).
 +-export([maybe_update_index_file/1]).
+ -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).
  
@@@ -714,88 -713,29 +717,115 @@@ mrverror(Mesg) -
      throw({query_parse_error, Mesg}).
  
  
 +%% Updates 1.2.x or earlier view files to 1.3.x or later view files
 +%% transparently, the first time the 1.2.x view file is opened by
 +%% 1.3.x or later.
 +%%
 +%% Here's how it works:
 +%%
 +%% Before opening a view index,
 +%% If no matching index file is found in the new location:
 +%%  calculate the <= 1.2.x view signature
 +%%  if a file with that signature lives in the old location
 +%%    rename it to the new location with the new signature in the name.
 +%% Then proceed to open the view index as usual.
 +%% After opening, read its header.
 +%%
 +%% If the header matches the <= 1.2.x style #index_header record:
 +%%   upgrade the header to the new #mrheader record
 +%% The next time the view is used, the new header is used.
 +%%
 +%% If we crash after the rename, but before the header upgrade,
 +%%   the header upgrade is done on the next view opening.
 +%%
 +%% If we crash between upgrading to the new header and writing
 +%%   that header to disk, we start with the old header again,
 +%%   do the upgrade and write to disk.
 +
 +maybe_update_index_file(State) ->
 +    DbName = State#mrst.db_name,
 +    NewIndexFile = index_file(DbName, State#mrst.sig),
 +    % open in read-only mode so we don't create
 +    % the file if it doesn't exist.
 +    case file:open(NewIndexFile, [read, raw]) of
 +    {ok, Fd_Read} ->
 +        % the new index file exists, there is nothing to do here.
 +        file:close(Fd_Read);
 +    _Error ->
 +        update_index_file(State)
 +    end.
 +
 +update_index_file(State) ->
 +    Sig = sig_vsn_12x(State),
 +    DbName = State#mrst.db_name,
 +    FileName = couch_index_util:hexsig(Sig) ++ ".view",
 +    IndexFile = couch_index_util:index_file("", DbName, FileName),
 +
 +    % If we have an old index, rename it to the new position.
 +    case file:read_file_info(IndexFile) of
 +    {ok, _FileInfo} ->
 +        % Crash if the rename fails for any reason.
 +        % If the target exists, e.g. the next request will find the
 +        % new file and we are good. We might need to catch this
 +        % further up to avoid a full server crash.
 +        ?LOG_INFO("Attempting to update legacy view index file.", []),
 +        NewIndexFile = index_file(DbName, State#mrst.sig),
 +        ok = filelib:ensure_dir(NewIndexFile),
 +        ok = file:rename(IndexFile, NewIndexFile),
 +        ?LOG_INFO("Successfully updated legacy view index file.", []),
 +        Sig;
 +    _ ->
 +        % Ignore missing index file
 +        ok
 +    end.
 +
 +sig_vsn_12x(State) ->
 +    ViewInfo = [old_view_format(V) || V <- State#mrst.views],
 +    SigData = case State#mrst.lib of
 +    {[]} ->
 +        {ViewInfo, State#mrst.language, State#mrst.design_opts};
 +    _ ->
 +        {ViewInfo, State#mrst.language, State#mrst.design_opts,
 +            couch_index_util:sort_lib(State#mrst.lib)}
 +    end,
 +    couch_util:md5(term_to_binary(SigData)).
 +
 +old_view_format(View) ->
 +{
 +    view,
 +    View#mrview.id_num,
 +    View#mrview.map_names,
 +    View#mrview.def,
 +    View#mrview.btree,
 +    View#mrview.reduce_funs,
 +    View#mrview.options
 +}.
 +
 +%% End of <= 1.2.x upgrade code.
++
+ 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.


Mime
View raw message