You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by da...@apache.org on 2014/02/13 04:09:57 UTC

[01/14] couch-httpd commit: updated refs/heads/1994-merge-rcouch to d936233

Updated Branches:
  refs/heads/1994-merge-rcouch 5b12577ee -> d936233c8 (forced update)


unbreak js test and display a report


Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/commit/2c783019
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/tree/2c783019
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/diff/2c783019

Branch: refs/heads/1994-merge-rcouch
Commit: 2c783019993c1c5f0ddb5802a2e6763bb05dbe10
Parents: 819ebcc
Author: benoitc <be...@apache.org>
Authored: Sun Jan 12 13:38:25 2014 +0100
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Feb 12 21:05:51 2014 -0600

----------------------------------------------------------------------
 src/couch_httpd_misc_handlers.erl | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/blob/2c783019/src/couch_httpd_misc_handlers.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_misc_handlers.erl b/src/couch_httpd_misc_handlers.erl
index 1999e5e..57cc5ec 100644
--- a/src/couch_httpd_misc_handlers.erl
+++ b/src/couch_httpd_misc_handlers.erl
@@ -99,6 +99,7 @@ handle_restart_req(#httpd{method='POST'}=Req) ->
     ok = couch_httpd:verify_is_server_admin(Req),
     Result = send_json(Req, 202, {[{ok, true}]}),
     couch_server_sup:restart_core_server(),
+    couch_httpd_sup:reload_listeners(),
     Result;
 handle_restart_req(Req) ->
     send_method_not_allowed(Req, "POST").


[05/14] couch-httpd commit: updated refs/heads/1994-merge-rcouch to d936233

Posted by da...@apache.org.
only display sasl reports on error. be less verbose in tests


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

Branch: refs/heads/1994-merge-rcouch
Commit: b97fac73c37056e4cbb2a8d584875e4c99da4504
Parents: 2c78301
Author: benoitc <be...@apache.org>
Authored: Sun Jan 12 20:58:30 2014 +0100
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Feb 12 21:05:52 2014 -0600

----------------------------------------------------------------------
 src/couch_httpd_misc_handlers.erl | 1 -
 1 file changed, 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/blob/b97fac73/src/couch_httpd_misc_handlers.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_misc_handlers.erl b/src/couch_httpd_misc_handlers.erl
index 57cc5ec..1999e5e 100644
--- a/src/couch_httpd_misc_handlers.erl
+++ b/src/couch_httpd_misc_handlers.erl
@@ -99,7 +99,6 @@ handle_restart_req(#httpd{method='POST'}=Req) ->
     ok = couch_httpd:verify_is_server_admin(Req),
     Result = send_json(Req, 202, {[{ok, true}]}),
     couch_server_sup:restart_core_server(),
-    couch_httpd_sup:reload_listeners(),
     Result;
 handle_restart_req(Req) ->
     send_method_not_allowed(Req, "POST").


[09/14] couch-httpd commit: updated refs/heads/1994-merge-rcouch to d936233

Posted by da...@apache.org.
fix rebarclean


Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/commit/1f1f4602
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/tree/1f1f4602
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/diff/1f1f4602

Branch: refs/heads/1994-merge-rcouch
Commit: 1f1f46026f5f47bd88501a3083c8c566dd09e264
Parents: 898bb1e
Author: benoitc <be...@apache.org>
Authored: Wed Jan 15 21:10:45 2014 +0100
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Feb 12 21:05:52 2014 -0600

----------------------------------------------------------------------
 ebin/couch_httpd.app | 14 --------------
 1 file changed, 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/blob/1f1f4602/ebin/couch_httpd.app
----------------------------------------------------------------------
diff --git a/ebin/couch_httpd.app b/ebin/couch_httpd.app
deleted file mode 100644
index 4338b4e..0000000
--- a/ebin/couch_httpd.app
+++ /dev/null
@@ -1,14 +0,0 @@
-{application,couch_httpd,
-             [{description,"CouchDB HTTP API"},
-              {vsn,"1.6.0"},
-              {modules,[couch_httpd,couch_httpd_app,couch_httpd_auth,
-                        couch_httpd_cors,couch_httpd_db,couch_httpd_external,
-                        couch_httpd_misc_handlers,couch_httpd_oauth,
-                        couch_httpd_proxy,couch_httpd_rewrite,
-                        couch_httpd_stats_handlers,couch_httpd_sup,
-                        couch_httpd_util,couch_httpd_vhost]},
-              {registered,[couch_httpd_sup]},
-              {applications,[kernel,stdlib,crypto,asn1,public_key,ssl,inets]},
-              {included_applications,[mochiweb]},
-              {mod,{couch_httpd_app,[]}},
-              {env,[]}]}.


[06/14] couch-httpd commit: updated refs/heads/1994-merge-rcouch to d936233

Posted by da...@apache.org.
export couch_httpd:set_auth_handlers/0

This function wasn't exported so any changes to the
`httpf/authentication_handlers` setting wasn't effective.


Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/commit/886f562c
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/tree/886f562c
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/diff/886f562c

Branch: refs/heads/1994-merge-rcouch
Commit: 886f562cfb6f98e7aea080f19a049d1894e1414b
Parents: b97fac7
Author: benoitc <be...@apache.org>
Authored: Mon Jan 13 09:01:59 2014 +0100
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Feb 12 21:05:52 2014 -0600

----------------------------------------------------------------------
 src/couch_httpd.erl | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/blob/886f562c/src/couch_httpd.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd.erl b/src/couch_httpd.erl
index ae28817..8cef53f 100644
--- a/src/couch_httpd.erl
+++ b/src/couch_httpd.erl
@@ -30,7 +30,7 @@
 -export([send_json/2,send_json/3,send_json/4,last_chunk/1,parse_multipart_request/3]).
 -export([accepted_encodings/1,handle_request_int/5,validate_referer/1,validate_ctype/2]).
 -export([http_1_0_keep_alive/2]).
-
+-export([set_auth_handlers/0]).
 
 start_link(couch_http) ->
     Port = couch_config:get("httpd", "port", "5984"),
@@ -157,7 +157,7 @@ set_auth_handlers() ->
         couch_config:get("httpd", "authentication_handlers", "")),
     AuthHandlers = lists:map(
         fun(A) -> {make_arity_1_fun(A), ?l2b(A)} end, AuthenticationSrcs),
-    ok = application:set_env(couch, auth_handlers, AuthHandlers).
+    ok = application:set_env(couch_httpd, auth_handlers, AuthHandlers).
 
 % SpecStr is a string like "{my_module, my_fun}"
 %  or "{my_module, my_fun, <<"my_arg">>}"
@@ -286,7 +286,7 @@ handle_request_int(MochiReq, DefaultFun,
     },
 
     HandlerFun = couch_util:dict_find(HandlerKey, UrlHandlers, DefaultFun),
-    {ok, AuthHandlers} = application:get_env(couch, auth_handlers),
+    {ok, AuthHandlers} = application:get_env(couch_httpd, auth_handlers),
 
     {ok, Resp} =
     try


[02/14] couch-httpd commit: updated refs/heads/1994-merge-rcouch to d936233

Posted by da...@apache.org.
couch_replicator: add replication using changes in a view

Instead of a database, the replicator can now filter the documents using
a view index. All documents having a key emitted in the view can be
replicated.

View parameters can be used. Which means that you can replicate results
corresponding to a key in a view or a range.


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

Branch: refs/heads/1994-merge-rcouch
Commit: d936233c8e8c63681cf17c8f76b12f6540827eae
Parents: 792797f
Author: benoitc <be...@apache.org>
Authored: Sun Feb 9 00:43:23 2014 +0100
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Feb 12 21:05:52 2014 -0600

----------------------------------------------------------------------
 src/couch_httpd_changes.erl | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/blob/d936233c/src/couch_httpd_changes.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_changes.erl b/src/couch_httpd_changes.erl
index 1c4a147..6cb0b16 100644
--- a/src/couch_httpd_changes.erl
+++ b/src/couch_httpd_changes.erl
@@ -137,12 +137,15 @@ handle_view_changes(ChangesArgs, Req, Db) ->
     {DDocId, VName} = parse_view_param(Req),
 
     %% get view options
-    Query = case Req of
+    {Query, NoIndex} = case Req of
         {json_req, {Props}} ->
             {Q} = couch_util:get_value(<<"query">>, Props, {[]}),
-            Q;
+            NoIndex1 = (couch_util:get_value(<<"use_index">>, Q,
+                                            <<"yes">>) =:= <<"no">>),
+            {Q, NoIndex1};
         _ ->
-            couch_httpd:qs(Req)
+            NoIndex1 = couch_httpd:qs_value(Req, "use_index", "yes") =:= "no",
+            {couch_httpd:qs(Req), NoIndex1}
     end,
     ViewOptions = parse_view_options(Query, []),
 
@@ -151,8 +154,6 @@ handle_view_changes(ChangesArgs, Req, Db) ->
                              proplists:get_value(update_options, Infos,
                                                  [])),
 
-    NoIndex = couch_httpd:qs_value(Req, "use_index", "yes") =:= "no",
-
     case {IsIndexed, NoIndex} of
         {true, false} ->
             handle_view_changes(Db, DDocId, VName, ViewOptions, ChangesArgs,


[14/14] couch-httpd commit: updated refs/heads/1994-merge-rcouch to d936233

Posted by da...@apache.org.
add the option use_index={no,yes} (yes by default)

If use_index=no even if the view is indexed by sequence, the index won't
be use. Instead it will fold the btree and return the changes each time
the view map function can emit a value. (default behaviour).


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

Branch: refs/heads/1994-merge-rcouch
Commit: f870b4babdc3081bc63d5ce15878ca2e0dd49cc3
Parents: 70409b2
Author: benoitc <bc...@gmail.com>
Authored: Fri Feb 7 15:57:25 2014 +0100
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Feb 12 21:05:52 2014 -0600

----------------------------------------------------------------------
 src/couch_httpd_changes.erl | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/blob/f870b4ba/src/couch_httpd_changes.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_changes.erl b/src/couch_httpd_changes.erl
index 56ce559..82d9fe0 100644
--- a/src/couch_httpd_changes.erl
+++ b/src/couch_httpd_changes.erl
@@ -118,6 +118,7 @@ handle_changes_req1(Req, #db{name=DbName}=Db) ->
 
 
 handle_changes(ChangesArgs, Req, Db) ->
+
     case ChangesArgs#changes_args.filter of
         "_view" ->
             handle_view_changes(ChangesArgs, Req, Db);
@@ -146,18 +147,26 @@ handle_view_changes(ChangesArgs, Req, Db) ->
     ViewOptions = parse_view_options(Query, []),
 
     {ok, Infos} = couch_mrview:get_info(Db, DDocId),
-    case lists:member(<<"seq_indexed">>,
-                      proplists:get_value(update_options, Infos, [])) of
-        true ->
+    IsIndexed = lists:member(<<"seq_indexed">>,
+                             proplists:get_value(update_options, Infos,
+                                                 [])),
+
+    NoIndex = couch_httpd:qs_value(Req, "use_index", "yes") =:= "no",
+
+    case {IsIndexed, NoIndex} of
+        {true, false} ->
             handle_view_changes(Db, DDocId, VName, ViewOptions, ChangesArgs,
                                 Req);
-        false when ViewOptions /= [] ->
+        {true, true} when ViewOptions /= [] ->
             ?LOG_ERROR("Tried to filter a non sequence indexed view~n",[]),
             throw({bad_request, seqs_not_indexed});
-        false ->
+        {false, _} when ViewOptions /= [] ->
+            ?LOG_ERROR("Tried to filter a non sequence indexed view~n",[]),
+            throw({bad_request, seqs_not_indexed});
+        {_, _} ->
             %% old method we are getting changes using the btree instead
             %% which is not efficient, log it
-            ?LOG_WARN("Get view changes with seq_indexed=false.~n", []),
+            ?LOG_WARN("Filter without using a seq_indexed view.~n", []),
             couch_changes:handle_changes(ChangesArgs, Req, Db)
     end.
 


[10/14] couch-httpd commit: updated refs/heads/1994-merge-rcouch to d936233

Posted by da...@apache.org.
extract couch_httpd changes API in its own module


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

Branch: refs/heads/1994-merge-rcouch
Commit: c629342a16925d0f9b9094016f4e91fecb39a774
Parents: dc841e0
Author: benoitc <bc...@gmail.com>
Authored: Sun Feb 2 19:54:01 2014 +0100
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Feb 12 21:05:52 2014 -0600

----------------------------------------------------------------------
 src/couch_httpd_changes.erl | 174 +++++++++++++++++++++++++++++++++++++++
 src/couch_httpd_db.erl      |   8 +-
 2 files changed, 178 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/blob/c629342a/src/couch_httpd_changes.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_changes.erl b/src/couch_httpd_changes.erl
new file mode 100644
index 0000000..1e431e9
--- /dev/null
+++ b/src/couch_httpd_changes.erl
@@ -0,0 +1,174 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(couch_httpd_changes).
+
+-export([handle_changes_req/2]).
+
+-include_lib("couch/include/couch_db.hrl").
+
+handle_changes_req(#httpd{method='POST'}=Req, Db) ->
+    couch_httpd:validate_ctype(Req, "application/json"),
+    handle_changes_req1(Req, Db);
+handle_changes_req(#httpd{method='GET'}=Req, Db) ->
+    handle_changes_req1(Req, Db);
+handle_changes_req(#httpd{path_parts=[_,<<"_changes">>]}=Req, _Db) ->
+    couch_httpd:send_method_not_allowed(Req, "GET,HEAD,POST").
+
+handle_changes_req1(Req, #db{name=DbName}=Db) ->
+    AuthDbName = ?l2b(couch_config:get("couch_httpd_auth", "authentication_db")),
+    case AuthDbName of
+    DbName ->
+        % in the authentication database, _changes is admin-only.
+        ok = couch_db:check_is_admin(Db);
+    _Else ->
+        % on other databases, _changes is free for all.
+        ok
+    end,
+    handle_changes_req2(Req, Db).
+
+handle_changes_req2(Req, Db) ->
+    MakeCallback = fun(Resp) ->
+        fun({change, {ChangeProp}=Change, _}, "eventsource") ->
+            Seq = proplists:get_value(<<"seq">>, ChangeProp),
+            couch_httpd:send_chunk(Resp, ["data: ", ?JSON_ENCODE(Change),
+                              "\n", "id: ", ?JSON_ENCODE(Seq),
+                              "\n\n"]);
+        ({change, Change, _}, "continuous") ->
+            couch_httpd:send_chunk(Resp, [?JSON_ENCODE(Change) | "\n"]);
+        ({change, Change, Prepend}, _) ->
+            couch_httpd:send_chunk(Resp, [Prepend, ?JSON_ENCODE(Change)]);
+        (start, "eventsource") ->
+            ok;
+        (start, "continuous") ->
+            ok;
+        (start, _) ->
+            couch_httpd:send_chunk(Resp, "{\"results\":[\n");
+        ({stop, _EndSeq}, "eventsource") ->
+            couch_httpd:end_json_response(Resp);
+        ({stop, EndSeq}, "continuous") ->
+            couch_httpd:send_chunk(
+                Resp,
+                [?JSON_ENCODE({[{<<"last_seq">>, EndSeq}]}) | "\n"]
+            ),
+            couch_httpd:end_json_response(Resp);
+        ({stop, EndSeq}, _) ->
+            couch_httpd:send_chunk(
+                Resp,
+                io_lib:format("\n],\n\"last_seq\":~w}\n", [EndSeq])
+            ),
+            couch_httpd:end_json_response(Resp);
+        (timeout, _) ->
+            couch_httpd:send_chunk(Resp, "\n")
+        end
+    end,
+    ChangesArgs = parse_changes_query(Req, Db),
+    ChangesFun = couch_changes:handle_changes(ChangesArgs, Req, Db),
+    WrapperFun = case ChangesArgs#changes_args.feed of
+    "normal" ->
+        {ok, Info} = couch_db:get_db_info(Db),
+        CurrentEtag = couch_httpd:make_etag(Info),
+        fun(FeedChangesFun) ->
+            couch_httpd:etag_respond(
+                Req,
+                CurrentEtag,
+                fun() ->
+                    {ok, Resp} = couch_httpd:start_json_response(
+                         Req, 200, [{"ETag", CurrentEtag}]
+                    ),
+                    FeedChangesFun(MakeCallback(Resp))
+                end
+            )
+        end;
+    "eventsource" ->
+        Headers = [
+            {"Content-Type", "text/event-stream"},
+            {"Cache-Control", "no-cache"}
+        ],
+        {ok, Resp} = couch_httpd:start_chunked_response(Req, 200, Headers),
+        fun(FeedChangesFun) ->
+            FeedChangesFun(MakeCallback(Resp))
+        end;
+    _ ->
+        % "longpoll" or "continuous"
+        {ok, Resp} = couch_httpd:start_json_response(Req, 200),
+        fun(FeedChangesFun) ->
+            FeedChangesFun(MakeCallback(Resp))
+        end
+    end,
+    couch_stats_collector:increment(
+        {httpd, clients_requesting_changes}
+    ),
+    try
+        WrapperFun(ChangesFun)
+    after
+    couch_stats_collector:decrement(
+        {httpd, clients_requesting_changes}
+    )
+    end.
+
+parse_changes_query(Req, Db) ->
+    ChangesArgs = lists:foldl(fun({Key, Value}, Args) ->
+        case {string:to_lower(Key), Value} of
+        {"feed", _} ->
+            Args#changes_args{feed=Value};
+        {"descending", "true"} ->
+            Args#changes_args{dir=rev};
+        {"since", "now"} ->
+            UpdateSeq = couch_util:with_db(Db#db.name, fun(WDb) ->
+                                        couch_db:get_update_seq(WDb)
+                                end),
+            Args#changes_args{since=UpdateSeq};
+        {"since", _} ->
+            Args#changes_args{since=list_to_integer(Value)};
+        {"last-event-id", _} ->
+            Args#changes_args{since=list_to_integer(Value)};
+        {"limit", _} ->
+            Args#changes_args{limit=list_to_integer(Value)};
+        {"style", _} ->
+            Args#changes_args{style=list_to_existing_atom(Value)};
+        {"heartbeat", "true"} ->
+            Args#changes_args{heartbeat=true};
+        {"heartbeat", _} ->
+            Args#changes_args{heartbeat=list_to_integer(Value)};
+        {"timeout", _} ->
+            Args#changes_args{timeout=list_to_integer(Value)};
+        {"include_docs", "true"} ->
+            Args#changes_args{include_docs=true};
+        {"attachments", "true"} ->
+            Opts = Args#changes_args.doc_options,
+            Args#changes_args{doc_options=[attachments|Opts]};
+        {"att_encoding_info", "true"} ->
+            Opts = Args#changes_args.doc_options,
+            Args#changes_args{doc_options=[att_encoding_info|Opts]};
+        {"conflicts", "true"} ->
+            Args#changes_args{conflicts=true};
+        {"filter", _} ->
+            Args#changes_args{filter=Value};
+        _Else -> % unknown key value pair, ignore.
+            Args
+        end
+    end, #changes_args{}, couch_httpd:qs(Req)),
+    %% if it's an EventSource request with a Last-event-ID header
+    %% that should override the `since` query string, since it's
+    %% probably the browser reconnecting.
+    case ChangesArgs#changes_args.feed of
+        "eventsource" ->
+            case couch_httpd:header_value(Req, "last-event-id") of
+                undefined ->
+                    ChangesArgs;
+                Value ->
+                    ChangesArgs#changes_args{since=list_to_integer(Value)}
+            end;
+        _ ->
+            ChangesArgs
+    end.

http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/blob/c629342a/src/couch_httpd_db.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_db.erl b/src/couch_httpd_db.erl
index 45a6dd5..0d1e0f8 100644
--- a/src/couch_httpd_db.erl
+++ b/src/couch_httpd_db.erl
@@ -19,10 +19,10 @@
     handle_design_info_req/3]).
 
 -import(couch_httpd,
-    [send_json/2,send_json/3,send_json/4,send_method_not_allowed/2,
-    start_json_response/2,send_chunk/2,last_chunk/1,end_json_response/1,
-    start_chunked_response/3, absolute_uri/2, send/2,
-    start_response_length/4, send_error/4]).
+        [send_json/2,send_json/3,send_json/4,send_method_not_allowed/2,
+         start_json_response/2,send_chunk/2,last_chunk/1,end_json_response/1,
+         start_chunked_response/3, absolute_uri/2, send/2,
+         start_response_length/4, send_error/4]).
 
 -record(doc_query_args, {
     options = [],


[07/14] couch-httpd commit: updated refs/heads/1994-merge-rcouch to d936233

Posted by da...@apache.org.
a more descriptive comment of the listener reloading flow


Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/commit/9f994a55
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/tree/9f994a55
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/diff/9f994a55

Branch: refs/heads/1994-merge-rcouch
Commit: 9f994a55497ae308183a007a42819ecb604c9c13
Parents: 886f562
Author: benoitc <be...@apache.org>
Authored: Mon Jan 13 09:36:44 2014 +0100
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Feb 12 21:05:52 2014 -0600

----------------------------------------------------------------------
 src/couch_httpd_sup.erl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/blob/9f994a55/src/couch_httpd_sup.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_sup.erl b/src/couch_httpd_sup.erl
index b430e45..1ce53f1 100644
--- a/src/couch_httpd_sup.erl
+++ b/src/couch_httpd_sup.erl
@@ -62,7 +62,7 @@ upgrade() ->
 %% @doc upgrade  a listener
 -spec reload_listener(atom()) -> {ok, pid()} | {error, term()}.
 reload_listener(Id) ->
-    %% stop the listener
+    %% stop the listener and remove it from the supervision temporarely
     supervisor:terminate_child(?MODULE, Id),
     supervisor:delete_child(?MODULE, Id),
 


[03/14] couch-httpd commit: updated refs/heads/1994-merge-rcouch to d936233

Posted by da...@apache.org.
couch_index: add background indexing facility

This change add the possibility to trigger a view indexation in
background. The indexation can only work in background if at least one
process acquired it using the `couch_index_server:acquire_index/3`
function. If all the process that acquired it are down or released it
using `couch_index_server:release_indexer/3` then the background task is
stopped.

By default the background indexation will happen every 1s or when 200
docs has been saved in the database. These parameters can be changed
using the options `threshold` and `refresh_interval` in the couch_index
section.

To use it with couch_mrview a new option {refresh, true} has been added
to couch_mrview_changes:handle_changes Also the query parameter
refresh=true is passsed in t the HTTP changes API.


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

Branch: refs/heads/1994-merge-rcouch
Commit: c1d2f8f0fe1af2159a8872629c965fcef4d7234e
Parents: f870b4b
Author: benoitc <be...@apache.org>
Authored: Sat Feb 8 19:55:40 2014 +0100
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Feb 12 21:05:52 2014 -0600

----------------------------------------------------------------------
 src/couch_httpd_changes.erl | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/blob/c1d2f8f0/src/couch_httpd_changes.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_changes.erl b/src/couch_httpd_changes.erl
index 82d9fe0..510e20a 100644
--- a/src/couch_httpd_changes.erl
+++ b/src/couch_httpd_changes.erl
@@ -177,8 +177,11 @@ handle_view_changes(#db{name=DbName}=Db0, DDocId, VName, ViewOptions,
         since = Since,
         db_open_options = DbOptions} = ChangesArgs,
 
+    Refresh = refresh_option(Req),
+
     Options0 = [{since, Since},
-                {view_options, ViewOptions}],
+                {view_options, ViewOptions},
+                {refresh, Refresh}],
     Options = case ResponseType of
         "continuous" -> [stream | Options0];
         "eventsource" -> [stream | Options0];
@@ -236,9 +239,9 @@ view_changes_cb({{Seq, _Key, DocId}, _VAl},
             %% if we achieved the limit, stop here, else continue.
             NewLimit = OldLimit + 1,
             if Limit > NewLimit ->
-                    {ok, {<<",\n">>, Db, NewLimit, Callback, Args}};
+                    {ok, {<<",\n">>, NewLimit, Db, Callback, Args}};
                 true ->
-                    {stop, {<<"">>, Db, NewLimit, Callback, Args}}
+                    {stop, {<<"">>, NewLimit, Db, Callback, Args}}
             end;
         {error, not_found} ->
             %% doc not found, continue
@@ -416,6 +419,15 @@ parse_view_options([{K, V} | Rest], Acc) ->
     end,
     parse_view_options(Rest, Acc1).
 
+refresh_option({json_req, {Props}}) ->
+    {Query} = couch_util:get_value(<<"query">>, Props),
+    couch_util:get_value(<<"refresh">>, Query, true);
+refresh_option(Req) ->
+    case couch_httpd:qs_value(Req, "refresh", "true") of
+        "false" -> false;
+        _ -> true
+    end.
+
 parse_json(V) when is_list(V) ->
     ?JSON_DECODE(V);
 parse_json(V) ->


[11/14] couch-httpd commit: updated refs/heads/1994-merge-rcouch to d936233

Posted by da...@apache.org.
Move addition of qs params after normalization

This refactor executes normalize_path/1 before appending the bound query
string parameters.

COUCHDB-2031


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

Branch: refs/heads/1994-merge-rcouch
Commit: e41dc6ce105f8daf663104c36135157c6a26aacf
Parents: 1f1f460
Author: Adam Kocoloski <ad...@cloudant.com>
Authored: Sat Jan 18 00:31:49 2014 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Feb 12 21:05:52 2014 -0600

----------------------------------------------------------------------
 src/couch_httpd_rewrite.erl | 58 +++++++++++++++++++---------------------
 1 file changed, 27 insertions(+), 31 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/blob/e41dc6ce/src/couch_httpd_rewrite.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_rewrite.erl b/src/couch_httpd_rewrite.erl
index 997992f..011c3c8 100644
--- a/src/couch_httpd_rewrite.erl
+++ b/src/couch_httpd_rewrite.erl
@@ -143,36 +143,32 @@ handle_rewrite_req(#httpd{
             DispatchList =  [make_rule(Rule) || {Rule} <- Rules],
             Method1 = couch_util:to_binary(Method),
 
-            %% get raw path by matching url to a rule.
-            RawPath = case try_bind_path(DispatchList, Method1,
-                    PathParts, QueryList) of
-                no_dispatch_path ->
-                    throw(not_found);
-                {NewPathParts, Bindings} ->
-                    Parts = [quote_plus(X) || X <- NewPathParts],
-
-                    % build new path, reencode query args, eventually convert
-                    % them to json
-                    Bindings1 = maybe_encode_bindings(Bindings),
-                    Path = binary_to_list(
-                        iolist_to_binary([
-                                string:join(Parts, [?SEPARATOR]),
-                                [["?", mochiweb_util:urlencode(Bindings1)]
-                                    || Bindings1 =/= [] ]
-                            ])),
-
-                    % if path is relative detect it and rewrite path
-                    case mochiweb_util:safe_relative_path(Path) of
-                        undefined ->
-                            ?b2l(Prefix) ++ "/" ++ Path;
-                        P1 ->
-                            ?b2l(Prefix) ++ "/" ++ P1
-                    end
-
-                end,
-
-            % normalize final path (fix levels "." and "..")
-            RawPath1 = ?b2l(iolist_to_binary(normalize_path(RawPath))),
+            % get raw path by matching url to a rule. Throws not_found.
+            {NewPathParts0, Bindings0} =
+                try_bind_path(DispatchList, Method1, PathParts, QueryList),
+            NewPathParts = [quote_plus(X) || X <- NewPathParts0],
+            Bindings = maybe_encode_bindings(Bindings0),
+
+            Path0 = string:join(NewPathParts, [?SEPARATOR]),
+
+            % if path is relative detect it and rewrite path
+            Path1 = case mochiweb_util:safe_relative_path(Path0) of
+                undefined ->
+                    ?b2l(Prefix) ++ "/" ++ Path0;
+                P1 ->
+                    ?b2l(Prefix) ++ "/" ++ P1
+            end,
+
+            Path2 = normalize_path(Path1),
+
+            Path3 = case Bindings of
+                [] ->
+                    Path2;
+                _ ->
+                    [Path2, "?", mochiweb_util:urlencode(Bindings)]
+            end,
+
+            RawPath1 = ?b2l(iolist_to_binary(Path3)),
 
             % In order to do OAuth correctly, we have to save the
             % requested path. We use default so chained rewriting
@@ -216,7 +212,7 @@ quote_plus(X) ->
 %% @doc Try to find a rule matching current url. If none is found
 %% 404 error not_found is raised
 try_bind_path([], _Method, _PathParts, _QueryList) ->
-    no_dispatch_path;
+    throw(not_found);
 try_bind_path([Dispatch|Rest], Method, PathParts, QueryList) ->
     [{PathParts1, Method1}, RedirectPath, QueryArgs, Formats] = Dispatch,
     case bind_method(Method1, Method) of


[08/14] couch-httpd commit: updated refs/heads/1994-merge-rcouch to d936233

Posted by da...@apache.org.
couch_server_sup -> couch_sup


Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/commit/898bb1e5
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/tree/898bb1e5
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/diff/898bb1e5

Branch: refs/heads/1994-merge-rcouch
Commit: 898bb1e51e5ceff64ff1734d881360dcbe4e6b4e
Parents: 9f994a5
Author: benoitc <be...@apache.org>
Authored: Mon Jan 13 23:06:26 2014 +0100
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Feb 12 21:05:52 2014 -0600

----------------------------------------------------------------------
 src/couch_httpd.erl               | 2 +-
 src/couch_httpd_misc_handlers.erl | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/blob/898bb1e5/src/couch_httpd.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd.erl b/src/couch_httpd.erl
index 8cef53f..7be8a2a 100644
--- a/src/couch_httpd.erl
+++ b/src/couch_httpd.erl
@@ -92,7 +92,7 @@ start_link(couch_https) ->
 start_link(Name, Options) ->
     % read config and register for configuration changes
 
-    % just stop if one of the config settings change. couch_server_sup
+    % just stop if one of the config settings change. couch_sup
     % will restart us and then we will pick up the new settings.
 
     BindAddress = couch_config:get("httpd", "bind_address", any),

http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/blob/898bb1e5/src/couch_httpd_misc_handlers.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_misc_handlers.erl b/src/couch_httpd_misc_handlers.erl
index 1999e5e..293ef00 100644
--- a/src/couch_httpd_misc_handlers.erl
+++ b/src/couch_httpd_misc_handlers.erl
@@ -98,7 +98,7 @@ handle_restart_req(#httpd{method='POST'}=Req) ->
     couch_httpd:validate_ctype(Req, "application/json"),
     ok = couch_httpd:verify_is_server_admin(Req),
     Result = send_json(Req, 202, {[{ok, true}]}),
-    couch_server_sup:restart_core_server(),
+    couch_sup:restart_core_server(),
     Result;
 handle_restart_req(Req) ->
     send_method_not_allowed(Req, "POST").


[12/14] couch-httpd commit: updated refs/heads/1994-merge-rcouch to d936233

Posted by da...@apache.org.
add supports of view changes in the _changes API

Now when the option `seq_indexed=true` is set in the design doc, the
view filter in _changes will use it to retrieve the results. Compared to
the current way, using a view index will be faster to retrieve changes.
It also gives the possibility to filter changes by key or get changes in
a key range. All the view options can be used.

Note 1: if someone is trying to filter a changes with view options when
the views are not indexed by sequence, a 400 error will be returned.
Note 2: The changes will only be returned when the view is updated if
seq_indexed=true


Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/commit/70409b20
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/tree/70409b20
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/diff/70409b20

Branch: refs/heads/1994-merge-rcouch
Commit: 70409b20e5be8f0fa5d125cd1e9ec2697c82d909
Parents: c629342
Author: benoitc <bc...@gmail.com>
Authored: Fri Feb 7 15:38:34 2014 +0100
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Feb 12 21:05:52 2014 -0600

----------------------------------------------------------------------
 src/couch_httpd_changes.erl | 250 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 246 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/blob/70409b20/src/couch_httpd_changes.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_changes.erl b/src/couch_httpd_changes.erl
index 1e431e9..56ce559 100644
--- a/src/couch_httpd_changes.erl
+++ b/src/couch_httpd_changes.erl
@@ -12,7 +12,9 @@
 
 -module(couch_httpd_changes).
 
--export([handle_changes_req/2]).
+-export([handle_changes_req/2,
+         handle_changes/3,
+         handle_view_changes/3]).
 
 -include_lib("couch/include/couch_db.hrl").
 
@@ -34,9 +36,7 @@ handle_changes_req1(Req, #db{name=DbName}=Db) ->
         % on other databases, _changes is free for all.
         ok
     end,
-    handle_changes_req2(Req, Db).
 
-handle_changes_req2(Req, Db) ->
     MakeCallback = fun(Resp) ->
         fun({change, {ChangeProp}=Change, _}, "eventsource") ->
             Seq = proplists:get_value(<<"seq">>, ChangeProp),
@@ -72,7 +72,7 @@ handle_changes_req2(Req, Db) ->
         end
     end,
     ChangesArgs = parse_changes_query(Req, Db),
-    ChangesFun = couch_changes:handle_changes(ChangesArgs, Req, Db),
+    ChangesFun = handle_changes(ChangesArgs, Req, Db),
     WrapperFun = case ChangesArgs#changes_args.feed of
     "normal" ->
         {ok, Info} = couch_db:get_db_info(Db),
@@ -116,6 +116,164 @@ handle_changes_req2(Req, Db) ->
     )
     end.
 
+
+handle_changes(ChangesArgs, Req, Db) ->
+    case ChangesArgs#changes_args.filter of
+        "_view" ->
+            handle_view_changes(ChangesArgs, Req, Db);
+        _ ->
+            couch_changes:handle_changes(ChangesArgs, Req, Db)
+    end.
+
+%% wrapper around couch_mrview_changes.
+%% This wrapper mimic couch_changes:handle_changes/3 and return a
+%% Changefun that can be used by the handle_changes_req function. Also
+%% while couch_mrview_changes:handle_changes/6 is returning tha view
+%% changes this function return docs corresponding to the changes
+%% instead so it can be used to replace the _view filter.
+handle_view_changes(ChangesArgs, Req, Db) ->
+    %% parse view parameter
+    {DDocId, VName} = parse_view_param(Req),
+
+    %% get view options
+    Query = case Req of
+        {json_req, {Props}} ->
+            {Q} = couch_util:get_value(<<"query">>, Props, {[]}),
+            Q;
+        _ ->
+            couch_httpd:qs(Req)
+    end,
+    ViewOptions = parse_view_options(Query, []),
+
+    {ok, Infos} = couch_mrview:get_info(Db, DDocId),
+    case lists:member(<<"seq_indexed">>,
+                      proplists:get_value(update_options, Infos, [])) of
+        true ->
+            handle_view_changes(Db, DDocId, VName, ViewOptions, ChangesArgs,
+                                Req);
+        false when ViewOptions /= [] ->
+            ?LOG_ERROR("Tried to filter a non sequence indexed view~n",[]),
+            throw({bad_request, seqs_not_indexed});
+        false ->
+            %% old method we are getting changes using the btree instead
+            %% which is not efficient, log it
+            ?LOG_WARN("Get view changes with seq_indexed=false.~n", []),
+            couch_changes:handle_changes(ChangesArgs, Req, Db)
+    end.
+
+handle_view_changes(#db{name=DbName}=Db0, DDocId, VName, ViewOptions,
+                    ChangesArgs, Req) ->
+    #changes_args{
+        feed = ResponseType,
+        since = Since,
+        db_open_options = DbOptions} = ChangesArgs,
+
+    Options0 = [{since, Since},
+                {view_options, ViewOptions}],
+    Options = case ResponseType of
+        "continuous" -> [stream | Options0];
+        "eventsource" -> [stream | Options0];
+        "longpoll" -> [{stream, once} | Options0];
+        _ -> Options0
+    end,
+
+    %% reopen the db with the db options given to the changes args
+    couch_db:close(Db0),
+    DbOptions1 = [{user_ctx, Db0#db.user_ctx} | DbOptions],
+    {ok, Db} = couch_db:open(DbName, DbOptions1),
+
+
+    %% initialise the changes fun
+    ChangesFun = fun(Callback) ->
+            Callback(start, ResponseType),
+
+            Acc0 = {"", 0, Db, Callback, ChangesArgs},
+            couch_mrview_changes:handle_changes(DbName, DDocId, VName,
+                                               fun view_changes_cb/2,
+                                               Acc0, Options)
+    end,
+    ChangesFun.
+
+
+view_changes_cb(stop, {LastSeq, {_, _, _, Callback, Args}}) ->
+    Callback({stop, LastSeq}, Args#changes_args.feed);
+
+view_changes_cb(heartbeat, {_, _, _, Callback, Args}=Acc) ->
+    Callback(timeout, Args#changes_args.feed),
+    {ok, Acc};
+view_changes_cb({{Seq, _Key, DocId}, _VAl},
+                {Prepend, OldLimit, Db0, Callback, Args}=Acc) ->
+
+    #changes_args{
+        feed = ResponseType,
+        limit = Limit} = Args,
+
+    %% if the doc sequence is > to the one in the db record, reopen the
+    %% database since it means we don't have the latest db value.
+    Db = case Db0#db.update_seq >= Seq of
+        true -> Db0;
+        false ->
+            {ok, Db1} = couch_db:reopen_db(Db0),
+            Db1
+    end,
+
+    case couch_db:get_doc_info(Db, DocId) of
+        {ok, DocInfo} ->
+            %% get change row
+            ChangeRow = view_change_row(Db, DocInfo, Args),
+            %% emit change row
+            Callback({change, ChangeRow, Prepend}, ResponseType),
+
+            %% if we achieved the limit, stop here, else continue.
+            NewLimit = OldLimit + 1,
+            if Limit > NewLimit ->
+                    {ok, {<<",\n">>, Db, NewLimit, Callback, Args}};
+                true ->
+                    {stop, {<<"">>, Db, NewLimit, Callback, Args}}
+            end;
+        {error, not_found} ->
+            %% doc not found, continue
+            {ok, Acc};
+        Error ->
+            throw(Error)
+    end.
+
+
+view_change_row(Db, DocInfo, Args) ->
+    #doc_info{id = Id, high_seq = Seq, revs = Revs} = DocInfo,
+    [#rev_info{rev=Rev, deleted=Del} | _] = Revs,
+
+    #changes_args{style=Style,
+                  include_docs=InDoc,
+                  doc_options = DocOpts,
+                  conflicts=Conflicts}=Args,
+
+    Changes = case Style of
+        main_only ->
+            [{[{<<"rev">>, couch_doc:rev_to_str(Rev)}]}];
+        all_docs ->
+            [{[{<<"rev">>, couch_doc:rev_to_str(R)}]}
+                || #rev_info{rev=R} <- Revs]
+    end,
+
+    {[{<<"seq">>, Seq}, {<<"id">>, Id}, {<<"changes">>, Changes}] ++
+     deleted_item(Del) ++ case InDoc of
+            true ->
+                Opts = case Conflicts of
+                    true -> [deleted, conflicts];
+                    false -> [deleted]
+                end,
+                Doc = couch_index_util:load_doc(Db, DocInfo, Opts),
+                case Doc of
+                    null ->
+                        [{doc, null}];
+                    _ ->
+                        [{doc, couch_doc:to_json_obj(Doc, DocOpts)}]
+                end;
+            false ->
+                []
+        end}.
+
 parse_changes_query(Req, Db) ->
     ChangesArgs = lists:foldl(fun({Key, Value}, Args) ->
         case {string:to_lower(Key), Value} of
@@ -172,3 +330,87 @@ parse_changes_query(Req, Db) ->
         _ ->
             ChangesArgs
     end.
+
+parse_view_param({json_req, {Props}}) ->
+    {Query} = couch_util:get_value(<<"query">>, Props),
+    parse_view_param1(couch_util:get_value(<<"view">>, Query, <<"">>));
+parse_view_param(Req) ->
+    parse_view_param1(list_to_binary(couch_httpd:qs_value(Req, "view", ""))).
+
+parse_view_param1(ViewParam) ->
+    case re:split(ViewParam, <<"/">>) of
+        [DName, ViewName] ->
+            {<< "_design/", DName/binary >>, ViewName};
+        _ ->
+            throw({bad_request, "Invalid `view` parameter."})
+    end.
+
+parse_view_options([], Acc) ->
+    Acc;
+parse_view_options([{K, V} | Rest], Acc) ->
+    Acc1 = case couch_util:to_binary(K) of
+        <<"reduce">> ->
+            [{reduce, couch_mrview_http:parse_boolean(V)}];
+        <<"key">> ->
+            V1 = parse_json(V),
+            [{start_key, V1}, {end_key, V1} | Acc];
+        <<"keys">> ->
+            [{keys, parse_json(V)} | Acc];
+        <<"startkey">> ->
+            [{start_key, parse_json(V)} | Acc];
+        <<"start_key">> ->
+            [{start_key, parse_json(V)} | Acc];
+        <<"startkey_docid">> ->
+            [{start_key_docid, couch_util:to_binary(V)} | Acc];
+        <<"start_key_docid">> ->
+            [{start_key_docid, couch_util:to_binary(V)} | Acc];
+        <<"endkey">> ->
+            [{end_key, parse_json(V)} | Acc];
+        <<"end_key">> ->
+            [{end_key, parse_json(V)} | Acc];
+        <<"endkey_docid">> ->
+            [{start_key_docid, couch_util:to_binary(V)} | Acc];
+        <<"end_key_docid">> ->
+            [{start_key_docid, couch_util:to_binary(V)} | Acc];
+        <<"limit">> ->
+            [{limit, couch_mrview_http:parse_pos_int(V)} | Acc];
+        <<"count">> ->
+            throw({query_parse_error, <<"QS param `count` is not `limit`">>});
+        <<"stale">> when V =:= <<"ok">> orelse V =:= "ok" ->
+            [{stale, ok} | Acc];
+        <<"stale">> when V =:= <<"update_after">> orelse V =:= "update_after" ->
+            [{stale, update_after} | Acc];
+        <<"stale">> ->
+            throw({query_parse_error, <<"Invalid value for `stale`.">>});
+        <<"descending">> ->
+            case couch_mrview_http:parse_boolean(V) of
+                true ->
+                    [{direction, rev} | Acc];
+                _ ->
+                    [{direction, fwd} | Acc]
+            end;
+        <<"skip">> ->
+            [{skip, couch_mrview_http:parse_pos_int(V)} | Acc];
+        <<"group">> ->
+            case couch_mrview_http:parse_booolean(V) of
+                true ->
+                    [{group_level, exact} | Acc];
+                _ ->
+                    [{group_level, 0} | Acc]
+            end;
+        <<"group_level">> ->
+            [{group_level, couch_mrview_http:parse_pos_int(V)} | Acc];
+        <<"inclusive_end">> ->
+            [{inclusive_end, couch_mrview_http:parse_boolean(V)}];
+        _ ->
+            Acc
+    end,
+    parse_view_options(Rest, Acc1).
+
+parse_json(V) when is_list(V) ->
+    ?JSON_DECODE(V);
+parse_json(V) ->
+    V.
+
+deleted_item(true) -> [{<<"deleted">>, true}];
+deleted_item(_) -> [].


[04/14] couch-httpd commit: updated refs/heads/1994-merge-rcouch to d936233

Posted by da...@apache.org.
Speed up and move couch_httpd:find_in_binary.

See https://issues.apache.org/jira/browse/COUCHDB-1953


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

Branch: refs/heads/1994-merge-rcouch
Commit: dc841e0492d960e1a19f6564a34076b9bbbd7d16
Parents: e41dc6c
Author: NickNorth <No...@gmail.com>
Authored: Tue Dec 3 20:58:53 2013 +0000
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Feb 12 21:05:52 2014 -0600

----------------------------------------------------------------------
 src/couch_httpd.erl | 30 +-----------------------------
 1 file changed, 1 insertion(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/blob/dc841e04/src/couch_httpd.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd.erl b/src/couch_httpd.erl
index 7be8a2a..29f9db0 100644
--- a/src/couch_httpd.erl
+++ b/src/couch_httpd.erl
@@ -968,7 +968,7 @@ split_header(Line) ->
      mochiweb_util:parse_header(Value)}].
 
 read_until(#mp{data_fun=DataFun, buffer=Buffer}=Mp, Pattern, Callback) ->
-    case find_in_binary(Pattern, Buffer) of
+    case couch_util:find_in_binary(Pattern, Buffer) of
     not_found ->
         Callback2 = Callback(Buffer),
         {Buffer2, DataFun2} = DataFun(),
@@ -1044,34 +1044,6 @@ check_for_last(#mp{buffer=Buffer, data_fun=DataFun}=Mp) ->
                 data_fun = DataFun2})
     end.
 
-find_in_binary(_B, <<>>) ->
-    not_found;
-
-find_in_binary(B, Data) ->
-    case binary:match(Data, [B], []) of
-    nomatch ->
-        partial_find(binary:part(B, {0, byte_size(B) - 1}),
-                     binary:part(Data, {byte_size(Data), -byte_size(Data) + 1}), 1);
-    {Pos, _Len} ->
-        {exact, Pos}
-    end.
-
-partial_find(<<>>, _Data, _Pos) ->
-    not_found;
-
-partial_find(B, Data, N) when byte_size(Data) > 0 ->
-    case binary:match(Data, [B], []) of
-    nomatch ->
-        partial_find(binary:part(B, {0, byte_size(B) - 1}),
-                     binary:part(Data, {byte_size(Data), -byte_size(Data) + 1}), N + 1);
-    {Pos, _Len} ->
-        {partial, N + Pos}
-    end;
-
-partial_find(_B, _Data, _N) ->
-    not_found.
-
-
 validate_bind_address(Address) ->
     case inet_parse:address(Address) of
         {ok, _} -> ok;


[13/14] couch-httpd commit: updated refs/heads/1994-merge-rcouch to d936233

Posted by da...@apache.org.
couch_httpd_changes: check removed keys from the view filter

Make sure to only emit deleted document when a deleted key is passed to
the view filter.


Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/commit/792797f3
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/tree/792797f3
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/diff/792797f3

Branch: refs/heads/1994-merge-rcouch
Commit: 792797f394dfe95eb1195b2da37de57dc7dc0d56
Parents: c1d2f8f
Author: benoitc <be...@apache.org>
Authored: Sat Feb 8 21:27:58 2014 +0100
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Feb 12 21:05:52 2014 -0600

----------------------------------------------------------------------
 src/couch_httpd_changes.erl | 40 +++++++++++++++++++++++++++-------------
 1 file changed, 27 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch-httpd/blob/792797f3/src/couch_httpd_changes.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_changes.erl b/src/couch_httpd_changes.erl
index 510e20a..1c4a147 100644
--- a/src/couch_httpd_changes.erl
+++ b/src/couch_httpd_changes.erl
@@ -213,9 +213,15 @@ view_changes_cb(stop, {LastSeq, {_, _, _, Callback, Args}}) ->
 view_changes_cb(heartbeat, {_, _, _, Callback, Args}=Acc) ->
     Callback(timeout, Args#changes_args.feed),
     {ok, Acc};
-view_changes_cb({{Seq, _Key, DocId}, _VAl},
+view_changes_cb({{Seq, _Key, DocId}, Val},
                 {Prepend, OldLimit, Db0, Callback, Args}=Acc) ->
 
+    %% is the key removed from the index?
+    Removed = case Val of
+        {[{<<"_removed">>, true}]} -> true;
+        _ -> false
+    end,
+
     #changes_args{
         feed = ResponseType,
         limit = Limit} = Args,
@@ -232,16 +238,24 @@ view_changes_cb({{Seq, _Key, DocId}, _VAl},
     case couch_db:get_doc_info(Db, DocId) of
         {ok, DocInfo} ->
             %% get change row
-            ChangeRow = view_change_row(Db, DocInfo, Args),
-            %% emit change row
-            Callback({change, ChangeRow, Prepend}, ResponseType),
-
-            %% if we achieved the limit, stop here, else continue.
-            NewLimit = OldLimit + 1,
-            if Limit > NewLimit ->
-                    {ok, {<<",\n">>, NewLimit, Db, Callback, Args}};
-                true ->
-                    {stop, {<<"">>, NewLimit, Db, Callback, Args}}
+            {Deleted, ChangeRow} = view_change_row(Db, DocInfo, Args),
+
+            case Removed of
+                true when Deleted /= true ->
+                    %% the key has been removed from the view but the
+                    %% document hasn't been deleted so ignore it.
+                    {ok, Acc};
+                _ ->
+                    %% emit change row
+                    Callback({change, ChangeRow, Prepend}, ResponseType),
+
+                    %% if we achieved the limit, stop here, else continue.
+                    NewLimit = OldLimit + 1,
+                    if Limit > NewLimit ->
+                            {ok, {<<",\n">>, NewLimit, Db, Callback, Args}};
+                        true ->
+                            {stop, {<<"">>, NewLimit, Db, Callback, Args}}
+                    end
             end;
         {error, not_found} ->
             %% doc not found, continue
@@ -268,7 +282,7 @@ view_change_row(Db, DocInfo, Args) ->
                 || #rev_info{rev=R} <- Revs]
     end,
 
-    {[{<<"seq">>, Seq}, {<<"id">>, Id}, {<<"changes">>, Changes}] ++
+    {Del, {[{<<"seq">>, Seq}, {<<"id">>, Id}, {<<"changes">>, Changes}] ++
      deleted_item(Del) ++ case InDoc of
             true ->
                 Opts = case Conflicts of
@@ -284,7 +298,7 @@ view_change_row(Db, DocInfo, Args) ->
                 end;
             false ->
                 []
-        end}.
+    end}}.
 
 parse_changes_query(Req, Db) ->
     ChangesArgs = lists:foldl(fun({Key, Value}, Args) ->