You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by rn...@apache.org on 2014/08/05 00:18:03 UTC

[01/20] couch commit: updated refs/heads/windsor-merge-102 to 944c542

Repository: couchdb-couch
Updated Branches:
  refs/heads/windsor-merge-102 [created] 944c5426b


Reset to default if max_dbs_open is deleted

max_dbs_opens is present in the stock default.ini so it appears we've
never deleted the value so far, just changed it up or down (mostly up
;))

When this property is deleted, reset to the default value.


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

Branch: refs/heads/windsor-merge-102
Commit: 1caf4b68bd3457a8593b294cf7dd24111a916c43
Parents: c68dc65
Author: Robert Newson <ro...@cloudant.com>
Authored: Mon Apr 15 21:46:22 2013 +0100
Committer: Robert Newson <rn...@apache.org>
Committed: Mon Aug 4 14:16:54 2014 +0100

----------------------------------------------------------------------
 src/couch_server.erl | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/1caf4b68/src/couch_server.erl
----------------------------------------------------------------------
diff --git a/src/couch_server.erl b/src/couch_server.erl
index ef7a6b6..e54efcc 100644
--- a/src/couch_server.erl
+++ b/src/couch_server.erl
@@ -26,10 +26,12 @@
 
 -include_lib("couch/include/couch_db.hrl").
 
+-define(MAX_DBS_OPEN, 100).
+
 -record(server,{
     root_dir = [],
     dbname_regexp,
-    max_dbs_open=100,
+    max_dbs_open=?MAX_DBS_OPEN,
     dbs_open=0,
     start_time="",
     lru = couch_lru:new()
@@ -187,7 +189,7 @@ init([]) ->
 
     RootDir = config:get("couchdb", "database_dir", "."),
     MaxDbsOpen = list_to_integer(
-            config:get("couchdb", "max_dbs_open")),
+            config:get("couchdb", "max_dbs_open", integer_to_list(?MAX_DBS_OPEN))),
     ok = config:listen_for_changes(?MODULE, nil),
     ok = couch_file:init_delete_dir(RootDir),
     hash_admin_passwords(),
@@ -210,8 +212,10 @@ terminate(_Reason, _Srv) ->
 handle_config_change("couchdb", "database_dir", _, _, _) ->
     exit(whereis(couch_server), config_change),
     remove_handler;
-handle_config_change("couchdb", "max_dbs_open", Max, _, _) ->
+handle_config_change("couchdb", "max_dbs_open", Max, _, _) when is_list(Max) ->
     {ok, gen_server:call(couch_server,{set_max_dbs_open,list_to_integer(Max)})};
+handle_config_change("couchdb", "max_dbs_open", _, _, _) ->
+    {ok, gen_server:call(couch_server,{set_max_dbs_open,?MAX_DBS_OPEN})};
 handle_config_change("admins", _, _, Persist, _) ->
     % spawn here so couch event manager doesn't deadlock
     {ok, spawn(fun() -> hash_admin_passwords(Persist) end)};


[17/20] couch commit: updated refs/heads/windsor-merge-102 to 944c542

Posted by rn...@apache.org.
Allow graceful reloading of OS processes

This patch adds a reload/0 command to couch_proc_manager that will cause
all OS processes to be reclaimed at the next earliest convenience (i.e.,
when the current client is done with the process).  It also adds a
get_stale_proc_count/0 function to report the number of processes that
have yet to be reclaimied.

BugzID: 19529


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

Branch: refs/heads/windsor-merge-102
Commit: 814eadc09594cff6f1815ade06c4fbb38e65da8d
Parents: 286df6e
Author: Adam Kocoloski <ad...@cloudant.com>
Authored: Mon Jun 3 12:26:35 2013 -0400
Committer: Robert Newson <rn...@apache.org>
Committed: Mon Aug 4 18:39:44 2014 +0100

----------------------------------------------------------------------
 src/couch_proc_manager.erl | 53 ++++++++++++++++++++++++++++++++++-------
 1 file changed, 45 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/814eadc0/src/couch_proc_manager.erl
----------------------------------------------------------------------
diff --git a/src/couch_proc_manager.erl b/src/couch_proc_manager.erl
index 8dd7da4..e0f03e5 100644
--- a/src/couch_proc_manager.erl
+++ b/src/couch_proc_manager.erl
@@ -17,7 +17,13 @@
 -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, 
     code_change/3]).
 
--export([start_link/0, get_proc_count/0, new_proc/1]).
+-export([
+    start_link/0,
+    get_proc_count/0,
+    get_stale_proc_count/0,
+    new_proc/1,
+    reload/0
+]).
 
 % config_listener api
 -export([handle_config_change/5]).
@@ -28,7 +34,8 @@
     tab,
     config,
     proc_counts,
-    waiting
+    waiting,
+    threshold_ts
 }).
 
 -record(proc_int, {
@@ -38,7 +45,8 @@
     ddoc_keys = [],
     prompt_fun,
     set_timeout_fun,
-    stop_fun
+    stop_fun,
+    t0
 }).
 
 -record(client, {
@@ -55,6 +63,12 @@ start_link() ->
 get_proc_count() ->
     gen_server:call(?MODULE, get_proc_count).
 
+get_stale_proc_count() ->
+    gen_server:call(?MODULE, get_stale_proc_count).
+
+reload() ->
+    gen_server:call(?MODULE, bump_threshold_ts).
+
 init([]) ->
     process_flag(trap_exit, true),
     ok = config:listen_for_changes(?MODULE, nil),
@@ -63,7 +77,8 @@ init([]) ->
         config = get_proc_config(),
         proc_counts = dict:new(),
         waiting = ets:new(couch_proc_manage_waiting,
-                [ordered_set, {keypos, #client.timestamp}])
+                [ordered_set, {keypos, #client.timestamp}]),
+        threshold_ts = os:timestamp()
     }}.
 
 handle_call(get_table, _From, State) ->
@@ -72,6 +87,11 @@ handle_call(get_table, _From, State) ->
 handle_call(get_proc_count, _From, State) ->
     {reply, ets:info(State#state.tab, size), State};
 
+handle_call(get_stale_proc_count, _From, State) ->
+    #state{tab = Tab, threshold_ts = T0} = State,
+    MatchSpec = [{#proc_int{t0='$1', _='_'}, [{'<', '$1', T0}], [true]}],
+    {reply, ets:select_count(Tab, MatchSpec), State};
+
 handle_call({get_proc, #doc{body={Props}}=DDoc, DDocKey}, From, State) ->
     {ClientPid, _} = From,
     Lang = couch_util:to_binary(
@@ -112,6 +132,16 @@ handle_call({ret_proc, #proc{client=Ref, lang=Lang0} = Proc}, _From, State) ->
     % table before the insert.  Don't know which approach is cheaper.
     {reply, true, return_proc(State, Proc#proc{lang=Lang})};
 
+handle_call(bump_threshold_ts, _From, #state{tab = Tab} = State) ->
+    FoldFun = fun(#proc_int{client = nil, pid = Pid}, _) ->
+        gen_server:cast(Pid, stop),
+        ets:delete(Tab, Pid);
+    (_, _) ->
+        ok
+    end,
+    ets:foldl(FoldFun, nil, Tab),
+    {reply, ok, State#state{threshold_ts = os:timestamp()}};
+
 handle_call(_Call, _From, State) ->
     {reply, ignored, State}.
 
@@ -331,7 +361,8 @@ make_proc(Pid, Lang, Mod) ->
         pid = Pid,
         prompt_fun = {Mod, prompt},
         set_timeout_fun = {Mod, set_timeout},
-        stop_fun = {Mod, stop}
+        stop_fun = {Mod, stop},
+        t0 = os:timestamp()
     },
     unlink(Pid),
     {ok, Proc}.
@@ -345,12 +376,18 @@ assign_proc(Tab, #client{}=Client, #proc{client=nil}=Proc) ->
     assign_proc(Tab, Pid, Proc).
 
 return_proc(State, #proc{pid=Pid, lang=Lang} = Proc) ->
-    #state{tab=Tab, waiting=Waiting} = State,
+    #state{tab=Tab, waiting=Waiting, threshold_ts = T0} = State,
     case is_process_alive(Pid) of true ->
         case get_waiting_client(Waiting, Lang) of
             nil ->
-                gen_server:cast(Pid, garbage_collect),
-                ets:insert(Tab, Proc#proc{client=nil}),
+                [ProcInt] = ets:lookup(Tab, Pid),
+                if ProcInt#proc_int.t0 < T0 ->
+                    gen_server:cast(Pid, stop),
+                    ets:delete(Tab, Pid);
+                true ->
+                    gen_server:cast(Pid, garbage_collect),
+                    ets:insert(Tab, Proc#proc{client=nil})
+                end,
                 State;
             #client{}=Client ->
                 From = Client#client.from,


[10/20] couch commit: updated refs/heads/windsor-merge-102 to 944c542

Posted by rn...@apache.org.
Remove old couch_db_update_notifier code


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

Branch: refs/heads/windsor-merge-102
Commit: a2addb5fc8eabbe29ca5fad22e1fa8d7c1e70ecf
Parents: c24e6d6
Author: Paul J. Davis <pa...@gmail.com>
Authored: Wed Apr 24 12:59:59 2013 -0500
Committer: Robert Newson <rn...@apache.org>
Committed: Mon Aug 4 15:24:37 2014 +0100

----------------------------------------------------------------------
 src/couch_db_update_notifier.erl     | 82 -------------------------------
 src/couch_db_update_notifier_sup.erl | 68 -------------------------
 src/couch_os_process.erl             |  2 +-
 src/couch_primary_sup.erl            |  6 ---
 src/couch_secondary_sup.erl          |  7 ---
 5 files changed, 1 insertion(+), 164 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/a2addb5f/src/couch_db_update_notifier.erl
----------------------------------------------------------------------
diff --git a/src/couch_db_update_notifier.erl b/src/couch_db_update_notifier.erl
deleted file mode 100644
index 3958917..0000000
--- a/src/couch_db_update_notifier.erl
+++ /dev/null
@@ -1,82 +0,0 @@
-% 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.
-
-%
-% This causes an OS process to spawned and it is notified every time a database
-% is updated.
-%
-% The notifications are in the form of a the database name sent as a line of
-% text to the OS processes stdout.
-%
-
--module(couch_db_update_notifier).
-
--behaviour(gen_event).
-
--export([start_link/1, notify/1]).
--export([init/1, terminate/2, handle_event/2, handle_call/2, handle_info/2, code_change/3,stop/1]).
-
--include_lib("couch/include/couch_db.hrl").
-
-start_link(Exec) ->
-    couch_event_sup:start_link(couch_db_update, {couch_db_update_notifier, make_ref()}, Exec).
-
-notify(Event) ->
-    gen_event:notify(couch_db_update, Event).
-
-stop(Pid) ->
-    couch_event_sup:stop(Pid).
-
-init(Exec) when is_list(Exec) -> % an exe
-    couch_os_process:start_link(Exec, []);
-init(Else) ->
-    {ok, Else}.
-
-terminate(_Reason, Pid) when is_pid(Pid) ->
-    couch_os_process:stop(Pid),
-    ok;
-terminate(_Reason, _State) ->
-    ok.
-
-handle_event(Event, Fun) when is_function(Fun, 1) ->
-    Fun(Event),
-    {ok, Fun};
-handle_event(Event, {Fun, FunAcc}) ->
-    FunAcc2 = Fun(Event, FunAcc),
-    {ok, {Fun, FunAcc2}};
-handle_event({EventType, EventDesc}, Pid) ->
-    Obj = encode_event(EventType, EventDesc),
-    ok = couch_os_process:send(Pid, Obj),
-    {ok, Pid}.
-
-handle_call(_Request, State) ->
-    {reply, ok, State}.
-
-handle_info({'EXIT', Pid, Reason}, Pid) ->
-    ?LOG_ERROR("Update notification process ~p died: ~p", [Pid, Reason]),
-    remove_handler;
-handle_info({'EXIT', _, _}, Pid) ->
-    %% the db_update event manager traps exits and forwards this message to all
-    %% its handlers. Just ignore as it wasn't our os_process that exited.
-    {ok, Pid}.
-
-code_change(_OldVsn, State, _Extra) ->
-    {ok, State}.
-
-encode_event(EventType, EventDesc) when is_atom(EventType) ->
-    encode_event(atom_to_list(EventType), EventDesc);
-encode_event(EventType, EventDesc) when is_list(EventType) ->
-    encode_event(?l2b(EventType), EventDesc);
-encode_event(EventType, {DbName, DocId}) ->
-    {[{type, EventType}, {db, DbName}, {id, DocId}]};
-encode_event(EventType, DbName) ->
-    {[{type, EventType}, {db, DbName}]}.

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/a2addb5f/src/couch_db_update_notifier_sup.erl
----------------------------------------------------------------------
diff --git a/src/couch_db_update_notifier_sup.erl b/src/couch_db_update_notifier_sup.erl
deleted file mode 100644
index 9eb943a..0000000
--- a/src/couch_db_update_notifier_sup.erl
+++ /dev/null
@@ -1,68 +0,0 @@
-% 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.
-
-%
-% This causes an OS process to spawned and it is notified every time a database
-% is updated.
-%
-% The notifications are in the form of a the database name sent as a line of
-% text to the OS processes stdout.
-%
-
--module(couch_db_update_notifier_sup).
-
--behaviour(supervisor).
--behaviour(config_listener).
-
--export([start_link/0, init/1]).
-
-% config_listener api
--export([handle_config_change/5]).
-
-
-start_link() ->
-    supervisor:start_link({local, couch_db_update_notifier_sup},
-        couch_db_update_notifier_sup, []).
-
-init([]) ->
-    ok = config:listen_for_changes(?MODULE, nil),
-
-    UpdateNotifierExes = config:get("update_notification"),
-
-    {ok,
-        {{one_for_one, 10, 3600},
-            lists:map(fun({Name, UpdateNotifierExe}) ->
-                {Name,
-                {couch_db_update_notifier, start_link, [UpdateNotifierExe]},
-                    permanent,
-                    1000,
-                    supervisor,
-                    [couch_db_update_notifier]}
-                end, UpdateNotifierExes)}}.
-
-%% @doc when update_notification configuration changes, terminate the process
-%%      for that notifier and start a new one with the updated config
-handle_config_change("update_notification", Id, Exe, _, _) ->
-    ChildSpec = {
-        Id,
-        {couch_db_update_notifier, start_link, [Exe]},
-        permanent,
-        1000,
-        supervisor,
-        [couch_db_update_notifier]
-    },
-    supervisor:terminate_child(couch_db_update_notifier_sup, Id),
-    supervisor:delete_child(couch_db_update_notifier_sup, Id),
-    supervisor:start_child(couch_db_update_notifier_sup, ChildSpec),
-    {ok, nil};
-handle_config_change(_, _, _, _, _) ->
-    {ok, nil}.

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/a2addb5f/src/couch_os_process.erl
----------------------------------------------------------------------
diff --git a/src/couch_os_process.erl b/src/couch_os_process.erl
index 6756dd3..f4d65e9 100644
--- a/src/couch_os_process.erl
+++ b/src/couch_os_process.erl
@@ -45,7 +45,7 @@ stop(Pid) ->
 set_timeout(Pid, TimeOut) when is_integer(TimeOut) ->
     ok = gen_server:call(Pid, {set_timeout, TimeOut}, infinity).
 
-% Used by couch_db_update_notifier.erl
+% Used by couch_event_os_process.erl
 send(Pid, Data) ->
     gen_server:cast(Pid, {send, Data}).
 

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/a2addb5f/src/couch_primary_sup.erl
----------------------------------------------------------------------
diff --git a/src/couch_primary_sup.erl b/src/couch_primary_sup.erl
index 3ce8827..cbd576d 100644
--- a/src/couch_primary_sup.erl
+++ b/src/couch_primary_sup.erl
@@ -37,12 +37,6 @@ init([]) ->
             brutal_kill,
             worker,
             [couch_server]},
-        {couch_db_update_event,
-            {gen_event, start_link, [{local, couch_db_update}]},
-            permanent,
-            brutal_kill,
-            worker,
-            dynamic},
         {couch_replication_event,
             {gen_event, start_link, [{local, couch_replication}]},
             permanent,

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/a2addb5f/src/couch_secondary_sup.erl
----------------------------------------------------------------------
diff --git a/src/couch_secondary_sup.erl b/src/couch_secondary_sup.erl
index 91e87cb..09e77b7 100644
--- a/src/couch_secondary_sup.erl
+++ b/src/couch_secondary_sup.erl
@@ -19,13 +19,6 @@ start_link() ->
 
 init([]) ->
     SecondarySupervisors = [
-        {couch_db_update_notifier_sup,
-            {couch_db_update_notifier_sup, start_link, []},
-            permanent,
-            infinity,
-            supervisor,
-            [couch_db_update_notifier_sup]},
-
         {couch_plugin_event,
             {gen_event, start_link, [{local, couch_plugin}]},
             permanent,


[06/20] couch commit: updated refs/heads/windsor-merge-102 to 944c542

Posted by rn...@apache.org.
Ignore all casts, not just foo


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

Branch: refs/heads/windsor-merge-102
Commit: ff3b88bc0c26fa92e67ae4ce9735ea45c006145c
Parents: 1caf4b6
Author: Robert Newson <ro...@cloudant.com>
Authored: Tue Apr 30 18:17:44 2013 +0100
Committer: Robert Newson <rn...@apache.org>
Committed: Mon Aug 4 14:16:55 2014 +0100

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/ff3b88bc/src/couch_native_process.erl
----------------------------------------------------------------------
diff --git a/src/couch_native_process.erl b/src/couch_native_process.erl
index d4b2deb..e59a223 100644
--- a/src/couch_native_process.erl
+++ b/src/couch_native_process.erl
@@ -97,7 +97,7 @@ handle_call({prompt, Data}, _From, State) ->
 handle_cast(garbage_collect, State) ->
     erlang:garbage_collect(),
     {noreply, State};
-handle_cast(foo, State) -> {noreply, State}.
+handle_cast(_, State) -> {noreply, State}.
 
 handle_info({'EXIT',_,normal}, State) -> {noreply, State};
 handle_info({'EXIT',_,Reason}, State) ->


[02/20] couch commit: updated refs/heads/windsor-merge-102 to 944c542

Posted by rn...@apache.org.
Update all view/search index shards on ddoc update

This update is part of the fix to trigger view/search index updates for
all shards when a ddoc is updated. In the past, we only triggered
indexing jobs for shards which contained the ddoc. Other parts of the
fix are in ken and fabric. This particular commit contains the
following:

- A new couch_db_update event, which will be used in ken to spawn
  indexing jobs.

- A new function clause for the local _changes feed couch_db_update
  handler. This function clause will cause the _changes feed handler to
  ignore the aforementioned new couch_db_update event.

BugzID: 10979


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

Branch: refs/heads/windsor-merge-102
Commit: 088ded691a04faa1c679ce5df1038df79ff8f89a
Parents: a74e7a0
Author: Benjamin Bastian <be...@gmail.com>
Authored: Wed Mar 13 17:10:05 2013 -0700
Committer: Robert Newson <rn...@apache.org>
Committed: Mon Aug 4 14:16:55 2014 +0100

----------------------------------------------------------------------
 src/couch_changes.erl    | 2 +-
 src/couch_db_updater.erl | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/088ded69/src/couch_changes.erl
----------------------------------------------------------------------
diff --git a/src/couch_changes.erl b/src/couch_changes.erl
index d8b5320..fd14f3d 100644
--- a/src/couch_changes.erl
+++ b/src/couch_changes.erl
@@ -79,7 +79,7 @@ handle_changes(Args1, Req, Db0) ->
             {Callback, UserAcc} = get_callback_acc(CallbackAcc),
             Self = self(),
             {ok, Notify} = couch_db_update_notifier:start_link(
-                fun({_, DbName}) when  Db0#db.name == DbName ->
+                fun({updated, DbName}) when Db0#db.name == DbName ->
                     Self ! db_updated;
                 (_) ->
                     ok

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/088ded69/src/couch_db_updater.erl
----------------------------------------------------------------------
diff --git a/src/couch_db_updater.erl b/src/couch_db_updater.erl
index 330f8cb..1b20544 100644
--- a/src/couch_db_updater.erl
+++ b/src/couch_db_updater.erl
@@ -738,6 +738,8 @@ update_docs_int(Db, DocsList, NonRepDocs, MergeConflicts, FullCommit) ->
     % funs if we did.
     Db4 = case length(UpdatedDDocIds) > 0 of
         true ->
+            couch_db_update_notifier:notify(
+                {ddoc_updated, Db3#db.name}),
             ddoc_cache:evict(Db3#db.name, UpdatedDDocIds),
             refresh_validate_doc_funs(Db3);
         false ->


[19/20] couch commit: updated refs/heads/windsor-merge-102 to 944c542

Posted by rn...@apache.org.
Improve code_change and #proc{} imports

Going forward we should define default values for all fields of a
proc_int that are not shared by a proc.  This allows us to implement the
general import_proc/1 function that I've added (and used in code_change)
here.

BugzID: 19529


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

Branch: refs/heads/windsor-merge-102
Commit: f69d7ef75d4af1389da53a54dcd7f61256791360
Parents: 0e78ae2
Author: Adam Kocoloski <ad...@cloudant.com>
Authored: Tue Jun 4 16:36:22 2013 -0400
Committer: Robert Newson <rn...@apache.org>
Committed: Mon Aug 4 18:41:14 2014 +0100

----------------------------------------------------------------------
 src/couch_proc_manager.erl | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/f69d7ef7/src/couch_proc_manager.erl
----------------------------------------------------------------------
diff --git a/src/couch_proc_manager.erl b/src/couch_proc_manager.erl
index 93c53cb..3cbb744 100644
--- a/src/couch_proc_manager.erl
+++ b/src/couch_proc_manager.erl
@@ -47,7 +47,7 @@
     prompt_fun,
     set_timeout_fun,
     stop_fun,
-    t0
+    t0 = os:timestamp()
 }).
 
 -record(client, {
@@ -232,7 +232,11 @@ terminate(_Reason, #state{tab=Tab}) ->
     ets:foldl(fun(#proc_int{pid=P}, _) -> couch_util:shutdown_sync(P) end, 0, Tab),
     ok.
 
-code_change(_, State, _) ->
+code_change(_OldVsn, {state, Tab}, _Extra) ->
+    State = #state{tab = Tab, threshold_ts = {0,0,0}},
+    ProcInts = lists:map(fun import_proc/1, ets:tab2list(Tab)),
+    ets:delete_all_objects(Tab),
+    ets:insert(Tab, ProcInts),
     {ok, State}.
 
 handle_config_change("query_server_config", _, _, _, _) ->
@@ -326,6 +330,11 @@ export_proc(#proc_int{} = ProcInt) ->
     [_ | Data] = lists:sublist(record_info(size, proc), tuple_to_list(ProcInt)),
     list_to_tuple([proc | Data]).
 
+import_proc(#proc{} = P) ->
+    lists:foldl(fun(Idx, ProcInt) ->
+        setelement(Idx, ProcInt, element(Idx, P))
+    end, #proc_int{}, lists:seq(2, tuple_size(P))).
+
 remove_proc(Tab, Pid) ->
     ets:delete(Tab, Pid),
     case is_process_alive(Pid) of true ->
@@ -373,8 +382,7 @@ make_proc(Pid, Lang, Mod) ->
         pid = Pid,
         prompt_fun = {Mod, prompt},
         set_timeout_fun = {Mod, set_timeout},
-        stop_fun = {Mod, stop},
-        t0 = os:timestamp()
+        stop_fun = {Mod, stop}
     },
     unlink(Pid),
     {ok, Proc}.


[14/20] couch commit: updated refs/heads/windsor-merge-102 to 944c542

Posted by rn...@apache.org.
Add config for couch_server LRU updates on read

This commit adds the ability for couch_server to ignore update_lru
messages. This should reduce load on couch_server when few entries are
being expired.


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

Branch: refs/heads/windsor-merge-102
Commit: f2b3162cd99a17d4d57fce035c3d326140124ae1
Parents: 1d6c18e
Author: Benjamin Bastian <be...@gmail.com>
Authored: Fri May 31 13:18:32 2013 -0700
Committer: Robert Newson <rn...@apache.org>
Committed: Mon Aug 4 16:41:04 2014 +0100

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/f2b3162c/src/couch_server.erl
----------------------------------------------------------------------
diff --git a/src/couch_server.erl b/src/couch_server.erl
index a10fcd0..441290f 100644
--- a/src/couch_server.erl
+++ b/src/couch_server.erl
@@ -34,6 +34,7 @@
     max_dbs_open=?MAX_DBS_OPEN,
     dbs_open=0,
     start_time="",
+    update_lru_on_read=true,
     lru = couch_lru:new()
     }).
 
@@ -213,6 +214,10 @@ terminate(_Reason, _Srv) ->
 handle_config_change("couchdb", "database_dir", _, _, _) ->
     exit(whereis(couch_server), config_change),
     remove_handler;
+handle_config_change("couchdb", "update_lru_on_read", "true", _, _) ->
+    {ok, gen_server:call(couch_server,{set_update_lru_on_read,true})};
+handle_config_change("couchdb", "update_lru_on_read", _, _, _) ->
+    {ok, gen_server:call(couch_server,{set_update_lru_on_read,false})};
 handle_config_change("couchdb", "max_dbs_open", Max, _, _) when is_list(Max) ->
     {ok, gen_server:call(couch_server,{set_max_dbs_open,list_to_integer(Max)})};
 handle_config_change("couchdb", "max_dbs_open", _, _, _) ->
@@ -324,6 +329,8 @@ handle_call(close_lru, _From, #server{lru=Lru} = Server) ->
     end;
 handle_call(open_dbs_count, _From, Server) ->
     {reply, Server#server.dbs_open, Server};
+handle_call({set_update_lru_on_read, UpdateOnRead}, _From, Server) ->
+    {reply, ok, Server#server{update_lru_on_read=UpdateOnRead}};
 handle_call({set_max_dbs_open, Max}, _From, Server) ->
     {reply, ok, Server#server{max_dbs_open=Max}};
 handle_call(get_server, _From, Server) ->
@@ -481,8 +488,10 @@ handle_call({db_updated, #db{name = DbName} = Db}, _From, Server) ->
     end,
     {reply, ok, Server#server{lru = Lru}}.
 
-handle_cast({update_lru, DbName}, #server{lru = Lru} = Server) ->
+handle_cast({update_lru, DbName}, #server{lru = Lru, update_lru_on_read=true} = Server) ->
     {noreply, Server#server{lru = couch_lru:update(DbName, Lru)}};
+handle_cast({update_lru, _DbName}, Server) ->
+    {noreply, Server};
 handle_cast(Msg, Server) ->
     {stop, {unknown_cast_message, Msg}, Server}.
 
@@ -494,8 +503,7 @@ handle_info({'EXIT', _Pid, config_change}, Server) ->
 handle_info({'EXIT', Pid, Reason}, Server) ->
     case ets:lookup(couch_dbs_pid_to_name, Pid) of
     [DbName] ->
-        [#db{compactor_pid=Froms}=Db] =
-            ets:match_object(couch_dbs, #db{name=DbName, _='_'}),
+        [#db{compactor_pid=Froms}=Db] = ets:lookup(couch_dbs, DbName),
         if Reason /= snappy_nif_not_loaded -> ok; true ->
             Msg = io_lib:format("To open the database `~s`, Apache CouchDB "
                 "must be built with Erlang OTP R13B04 or higher.", [DbName]),


[04/20] couch commit: updated refs/heads/windsor-merge-102 to 944c542

Posted by rn...@apache.org.
Send 400 bad request rather than 500 for invalid base64 in auth header

Along with a useful error message.


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

Branch: refs/heads/windsor-merge-102
Commit: 7e8dca72bf156a6f207904f943751ac039144c9f
Parents: c4ce490
Author: Michael Rhodes <mi...@gmail.com>
Authored: Tue May 14 12:40:25 2013 +0100
Committer: Robert Newson <rn...@apache.org>
Committed: Mon Aug 4 14:16:55 2014 +0100

----------------------------------------------------------------------
 src/couch_httpd_auth.erl | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/7e8dca72/src/couch_httpd_auth.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_auth.erl b/src/couch_httpd_auth.erl
index 6c1d037..483e4cd 100644
--- a/src/couch_httpd_auth.erl
+++ b/src/couch_httpd_auth.erl
@@ -48,7 +48,7 @@ basic_name_pw(Req) ->
     AuthorizationHeader = header_value(Req, "Authorization"),
     case AuthorizationHeader of
     "Basic " ++ Base64Value ->
-        case re:split(base64:decode(Base64Value), ":",
+        try re:split(base64:decode(Base64Value), ":",
                       [{return, list}, {parts, 2}]) of
         ["_", "_"] ->
             % special name and pass to be logged out
@@ -57,6 +57,9 @@ basic_name_pw(Req) ->
             {User, Pass};
         _ ->
             nil
+        catch
+        error:function_clause ->
+            throw({bad_request, "Authorization header has invalid base64 value"})
         end;
     _ ->
         nil


[08/20] couch commit: updated refs/heads/windsor-merge-102 to 944c542

Posted by rn...@apache.org.
Update couch_changes to use new couch_event app


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

Branch: refs/heads/windsor-merge-102
Commit: c24e6d6805d638879832fcf338bb42f2f201d104
Parents: be7b1a4
Author: Paul J. Davis <pa...@gmail.com>
Authored: Tue Apr 23 16:00:01 2013 -0500
Committer: Robert Newson <rn...@apache.org>
Committed: Mon Aug 4 15:19:30 2014 +0100

----------------------------------------------------------------------
 src/couch_changes.erl | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/c24e6d68/src/couch_changes.erl
----------------------------------------------------------------------
diff --git a/src/couch_changes.erl b/src/couch_changes.erl
index fd14f3d..637a6ba 100644
--- a/src/couch_changes.erl
+++ b/src/couch_changes.erl
@@ -19,7 +19,8 @@
     wait_db_updated/3,
     get_rest_db_updated/1,
     configure_filter/4,
-    filter/3
+    filter/3,
+    handle_db_event/3
 ]).
 
 -export([changes_enumerator/2]).
@@ -77,13 +78,8 @@ handle_changes(Args1, Req, Db0) ->
     true ->
         fun(CallbackAcc) ->
             {Callback, UserAcc} = get_callback_acc(CallbackAcc),
-            Self = self(),
-            {ok, Notify} = couch_db_update_notifier:start_link(
-                fun({updated, DbName}) when Db0#db.name == DbName ->
-                    Self ! db_updated;
-                (_) ->
-                    ok
-                end
+            {ok, Listener} = couch_event:link_listener(
+                 ?MODULE, handle_db_event, self(), [{dbname, Db0#db.name}]
             ),
             {Db, StartSeq} = Start(),
             UserAcc2 = start_sending_changes(Callback, UserAcc, Feed),
@@ -96,7 +92,7 @@ handle_changes(Args1, Req, Db0) ->
                     Acc0,
                     true)
             after
-                couch_db_update_notifier:stop(Notify),
+                couch_event:stop_listener(Listener),
                 get_rest_db_updated(ok) % clean out any remaining update messages
             end
         end;
@@ -117,6 +113,15 @@ handle_changes(Args1, Req, Db0) ->
         end
     end.
 
+
+handle_db_event(_DbName, updated, Parent) ->
+    Parent ! db_updated,
+    {ok, Parent};
+
+handle_db_event(_DbName, _Event, Parent) ->
+    {ok, Parent}.
+
+
 get_callback_acc({Callback, _UserAcc} = Pair) when is_function(Callback, 3) ->
     Pair;
 get_callback_acc(Callback) when is_function(Callback, 2) ->


[11/20] couch commit: updated refs/heads/windsor-merge-102 to 944c542

Posted by rn...@apache.org.
Add uuid and epochs to couchdb database header

All .couch files now have a uuid value that is preserved during
compaction. This value can be used to distinguish one .couch file from
another. In addition, a list of {node(), non_neg_integer()} tuples is
recorded showing the highest update sequence used since the last time
that the value of node() changed. This allows us to know if the
database file has moved and received writes since the last time we saw it.

BugzID: 19133

Conflicts:
	include/couch_db.hrl
	src/couch_db.erl
	src/couch_db_updater.erl


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

Branch: refs/heads/windsor-merge-102
Commit: b7b20c906e6041816ad1caf66e747c5be4882d0c
Parents: a2addb5
Author: Robert Newson <ro...@cloudant.com>
Authored: Mon Apr 29 22:39:52 2013 +0100
Committer: Robert Newson <rn...@apache.org>
Committed: Mon Aug 4 15:32:10 2014 +0100

----------------------------------------------------------------------
 include/couch_db.hrl     |  8 ++++--
 src/couch_db.erl         |  6 +++--
 src/couch_db_updater.erl | 57 ++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 64 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/b7b20c90/include/couch_db.hrl
----------------------------------------------------------------------
diff --git a/include/couch_db.hrl b/include/couch_db.hrl
index 90cc263..5c549ec 100644
--- a/include/couch_db.hrl
+++ b/include/couch_db.hrl
@@ -151,7 +151,9 @@
      purge_seq = 0,
      purged_docs = nil,
      security_ptr = nil,
-     revs_limit = 1000
+     revs_limit = 1000,
+     uuid = nil,
+     epochs = nil
     }).
 
 -record(db,
@@ -178,7 +180,9 @@
     options = [],
     compression,
     before_doc_update = nil, % nil | fun(Doc, Db) -> NewDoc
-    after_doc_read = nil     % nil | fun(Doc, Db) -> NewDoc
+    after_doc_read = nil,    % nil | fun(Doc, Db) -> NewDoc
+    uuid = nil,
+    epochs = nil
     }).
 
 -record(view_fold_helper_funs, {

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/b7b20c90/src/couch_db.erl
----------------------------------------------------------------------
diff --git a/src/couch_db.erl b/src/couch_db.erl
index 9d480a9..aaab19b 100644
--- a/src/couch_db.erl
+++ b/src/couch_db.erl
@@ -304,7 +304,8 @@ get_db_info(Db) ->
         committed_update_seq=CommittedUpdateSeq,
         id_tree = IdBtree,
         seq_tree = SeqBtree,
-        local_tree = LocalBtree
+        local_tree = LocalBtree,
+        uuid = Uuid
     } = Db,
     {ok, Size} = couch_file:bytes(Fd),
     {ok, DbReduction} = couch_btree:full_reduce(IdBtree),
@@ -319,7 +320,8 @@ get_db_info(Db) ->
         {data_size, db_data_size(DbReduction, [SeqBtree, IdBtree, LocalBtree])},
         {instance_start_time, StartTime},
         {disk_format_version, DiskVersion},
-        {committed_update_seq, CommittedUpdateSeq}
+        {committed_update_seq, CommittedUpdateSeq},
+        {uuid, Uuid}
         ],
     {ok, InfoList}.
 

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/b7b20c90/src/couch_db_updater.erl
----------------------------------------------------------------------
diff --git a/src/couch_db_updater.erl b/src/couch_db_updater.erl
index 4e72dac..f6276c5 100644
--- a/src/couch_db_updater.erl
+++ b/src/couch_db_updater.erl
@@ -227,7 +227,9 @@ handle_cast({compact_done, CompactFilepath}, #db{filepath=Filepath}=Db) ->
             main_pid = self(),
             filepath = Filepath,
             instance_start_time = Db#db.instance_start_time,
-            revs_limit = Db#db.revs_limit
+            revs_limit = Db#db.revs_limit,
+            uuid = Db#db.uuid,
+            epochs = Db#db.epochs
         }),
 
         ?LOG_DEBUG("CouchDB swapping files ~s and ~s.",
@@ -522,7 +524,9 @@ init_db(DbName, Filepath, Fd, Header0, Options) ->
         options = Options,
         compression = Compression,
         before_doc_update = couch_util:get_value(before_doc_update, Options, nil),
-        after_doc_read = couch_util:get_value(after_doc_read, Options, nil)
+        after_doc_read = couch_util:get_value(after_doc_read, Options, nil),
+        uuid = initialize_uuid(Header),
+        epochs = initialize_epochs(Header)
         }.
 
 
@@ -804,7 +808,9 @@ db_to_header(Db, Header) ->
         id_tree_state = couch_btree:get_state(Db#db.id_tree),
         local_tree_state = couch_btree:get_state(Db#db.local_tree),
         security_ptr = Db#db.security_ptr,
-        revs_limit = Db#db.revs_limit}.
+        revs_limit = Db#db.revs_limit,
+        uuid = Db#db.uuid,
+        epochs = update_epochs(Db)}.
 
 commit_data(Db) ->
     commit_data(Db, false).
@@ -1273,3 +1279,48 @@ make_doc_summary(#db{compression = Comp}, {Body0, Atts0}) ->
     end,
     SummaryBin = ?term_to_bin({Body, Atts}),
     couch_file:assemble_file_chunk(SummaryBin, couch_util:md5(SummaryBin)).
+
+initialize_uuid(#db_header{uuid=nil}) ->
+    couch_uuids:random();
+initialize_uuid(#db_header{uuid=Uuid}) ->
+    Uuid.
+
+initialize_epochs(#db_header{epochs=nil}=Db) ->
+    [{node(), Db#db_header.update_seq}];
+initialize_epochs(#db_header{epochs=Epochs}) ->
+    Epochs.
+
+update_epochs(Db) ->
+    case Db#db.epochs of
+        [{Node, _} | _] when Node =:= node() ->
+            Db#db.epochs;
+        Epochs when is_list(Epochs) ->
+            %% Mark the sequence where this node took over.
+            [{node(), Db#db.update_seq} | Epochs]
+    end.
+
+-ifdef(TEST).
+-include_lib("eunit/include/eunit.hrl").
+
+initialize_uuid_is_stable_test() ->
+    %% UUID was initialized.
+    ?assertMatch(<<_:32/binary>>, initialize_uuid(#db_header{})),
+    %% UUID was preserved.
+    ?assertEqual(foo, initialize_uuid(#db_header{uuid=foo})).
+
+initialize_epochs_is_stable_test() ->
+    %% Epochs were initialized.
+    ?assertMatch([{'nonode@nohost', 0}], initialize_epochs(#db_header{})),
+    %% Epochs are preserved.
+    ?assertMatch(foo, initialize_epochs(#db_header{epochs=foo})).
+
+update_epochs_test() ->
+    %% Epochs are not extended if node stays the same.
+    ?assertMatch([{'nonode@nohost', 0}],
+                 update_epochs(#db{epochs=[{'nonode@nohost', 0}]})),
+
+    %% Epochs are extended if node changes.
+    ?assertMatch([{'nonode@nohost', 1}, {foo, 0}],
+                 update_epochs(#db{update_seq=1, epochs=[{foo, 0}]})).
+
+-endif.


[03/20] couch commit: updated refs/heads/windsor-merge-102 to 944c542

Posted by rn...@apache.org.
Export parse_copy_destination_header/1


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

Branch: refs/heads/windsor-merge-102
Commit: a74e7a0fdc8c20af06033573665bdc99780e27c5
Parents: 7e8dca7
Author: Robert Newson <rn...@apache.org>
Authored: Mon Aug 4 13:44:52 2014 +0100
Committer: Robert Newson <rn...@apache.org>
Committed: Mon Aug 4 14:16:55 2014 +0100

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/a74e7a0f/src/couch_httpd_db.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_db.erl b/src/couch_httpd_db.erl
index 4c113e5..7360dc0 100644
--- a/src/couch_httpd_db.erl
+++ b/src/couch_httpd_db.erl
@@ -16,7 +16,7 @@
 -export([handle_request/1, handle_compact_req/2, handle_design_req/2,
     db_req/2, couch_doc_open/4,handle_changes_req/2,
     update_doc_result_to_json/1, update_doc_result_to_json/2,
-    handle_design_info_req/3]).
+    handle_design_info_req/3, parse_copy_destination_header/1]).
 
 -import(couch_httpd,
     [send_json/2,send_json/3,send_json/4,send_method_not_allowed/2,


[07/20] couch commit: updated refs/heads/windsor-merge-102 to 944c542

Posted by rn...@apache.org.
Switch notifications to the new couch_event app


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

Branch: refs/heads/windsor-merge-102
Commit: 2b45f92ba0f5c5de6eef1c65ee6252abb9f0ffb9
Parents: 088ded6
Author: Paul J. Davis <pa...@gmail.com>
Authored: Wed Apr 24 12:42:14 2013 -0500
Committer: Robert Newson <rn...@apache.org>
Committed: Mon Aug 4 15:19:26 2014 +0100

----------------------------------------------------------------------
 src/couch_db_updater.erl | 24 ++++++++++++++----------
 src/couch_server.erl     |  4 ++--
 2 files changed, 16 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/2b45f92b/src/couch_db_updater.erl
----------------------------------------------------------------------
diff --git a/src/couch_db_updater.erl b/src/couch_db_updater.erl
index 1b20544..4e72dac 100644
--- a/src/couch_db_updater.erl
+++ b/src/couch_db_updater.erl
@@ -107,7 +107,7 @@ handle_call(cancel_compact, _From, #db{compactor_pid = Pid} = Db) ->
 handle_call(increment_update_seq, _From, Db) ->
     Db2 = commit_data(Db#db{update_seq=Db#db.update_seq+1}),
     ok = gen_server:call(couch_server, {db_updated, Db2}, infinity),
-    couch_db_update_notifier:notify({updated, Db#db.name}),
+    couch_event:notify(Db#db.name, updated),
     {reply, {ok, Db2#db.update_seq}, Db2};
 
 handle_call({set_security, NewSec}, _From, #db{compression = Comp} = Db) ->
@@ -189,7 +189,7 @@ handle_call({purge_docs, IdRevs}, _From, Db) ->
             header=Header#db_header{purge_seq=PurgeSeq+1, purged_docs=Pointer}}),
 
     ok = gen_server:call(couch_server, {db_updated, Db2}, infinity),
-    couch_db_update_notifier:notify({updated, Db#db.name}),
+    couch_event:notify(Db#db.name, updated),
     {reply, {ok, (Db2#db.header)#db_header.purge_seq, IdRevsPurged}, Db2}.
 
 
@@ -242,7 +242,7 @@ handle_cast({compact_done, CompactFilepath}, #db{filepath=Filepath}=Db) ->
         close_db(Db),
         NewDb3 = refresh_validate_doc_funs(NewDb2),
         ok = gen_server:call(couch_server, {db_updated, NewDb3}, infinity),
-        couch_db_update_notifier:notify({compacted, NewDb3#db.name}),
+        couch_event:notify(NewDb3#db.name, compacted),
         ?LOG_INFO("Compaction for db \"~s\" completed.", [Db#db.name]),
         {noreply, NewDb3#db{compactor_pid=nil}};
     false ->
@@ -278,14 +278,19 @@ handle_info({update_docs, Client, GroupedDocs, NonRepDocs, MergeConflicts,
     {ok, Db2, UpdatedDDocIds} ->
         ok = gen_server:call(couch_server, {db_updated, Db2}, infinity),
         if Db2#db.update_seq /= Db#db.update_seq ->
-            couch_db_update_notifier:notify({updated, Db2#db.name});
+            couch_event:notify(Db2#db.name, updated);
         true -> ok
         end,
         [catch(ClientPid ! {done, self()}) || ClientPid <- Clients],
-        lists:foreach(fun(DDocId) ->
-            couch_db_update_notifier:notify({ddoc_updated, {Db#db.name, DDocId}})
-        end, UpdatedDDocIds),
-        {noreply, Db2, hibernate}
+        Db3 = case length(UpdatedDDocIds) > 0 of
+            true ->
+                couch_event:notify(Db2#db.name, ddoc_updated),
+                ddoc_cache:evict(Db2#db.name, UpdatedDDocIds),
+                refresh_validate_doc_funs(Db2);
+            false ->
+                Db2
+        end,
+        {noreply, Db3, hibernate}
     catch
         throw: retry ->
             [catch(ClientPid ! {retry, self()}) || ClientPid <- Clients],
@@ -738,8 +743,7 @@ update_docs_int(Db, DocsList, NonRepDocs, MergeConflicts, FullCommit) ->
     % funs if we did.
     Db4 = case length(UpdatedDDocIds) > 0 of
         true ->
-            couch_db_update_notifier:notify(
-                {ddoc_updated, Db3#db.name}),
+            couch_event:notify(Db3#db.name, ddoc_updated),
             ddoc_cache:evict(Db3#db.name, UpdatedDDocIds),
             refresh_validate_doc_funs(Db3);
         false ->

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/2b45f92b/src/couch_server.erl
----------------------------------------------------------------------
diff --git a/src/couch_server.erl b/src/couch_server.erl
index e54efcc..5a73877 100644
--- a/src/couch_server.erl
+++ b/src/couch_server.erl
@@ -291,7 +291,7 @@ open_async(Server, From, DbName, Filepath, Options) ->
         Res = couch_db:start_link(DbName, Filepath, Options),
         case {Res, lists:member(create, Options)} of
             {{ok, _Db}, true} ->
-                couch_db_update_notifier:notify({created, DbName});
+                couch_event:notify(DbName, created);
             _ ->
                 ok
         end,
@@ -456,7 +456,7 @@ handle_call({delete, DbName, Options}, _From, Server) ->
 
         case couch_file:delete(Server#server.root_dir, FullFilepath, Async) of
         ok ->
-            couch_db_update_notifier:notify({deleted, DbName}),
+            couch_event:notify(DbName, deleted),
             {reply, ok, Server2};
         {error, enoent} ->
             {reply, not_found, Server2};


[15/20] couch commit: updated refs/heads/windsor-merge-102 to 944c542

Posted by rn...@apache.org.
Use a #proc_int record internally instead of #proc

This allows us to add more information to an OS process without
disturbing the proc manager API.

BugzID: 19529


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

Branch: refs/heads/windsor-merge-102
Commit: 1e8e996cb8efddc260b1abb0ba6a79a9d2c98c27
Parents: f2b3162
Author: Adam Kocoloski <ad...@cloudant.com>
Authored: Mon Jun 3 11:04:59 2013 -0400
Committer: Robert Newson <rn...@apache.org>
Committed: Mon Aug 4 18:27:06 2014 +0100

----------------------------------------------------------------------
 src/couch_proc_manager.erl | 55 +++++++++++++++++++++++++----------------
 1 file changed, 34 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/1e8e996c/src/couch_proc_manager.erl
----------------------------------------------------------------------
diff --git a/src/couch_proc_manager.erl b/src/couch_proc_manager.erl
index 9aca645..24c3b47 100644
--- a/src/couch_proc_manager.erl
+++ b/src/couch_proc_manager.erl
@@ -31,6 +31,16 @@
     waiting
 }).
 
+-record(proc_int, {
+    pid,
+    lang,
+    client = nil,
+    ddoc_keys = [],
+    prompt_fun,
+    set_timeout_fun,
+    stop_fun
+}).
+
 -record(client, {
     timestamp,
     from,
@@ -49,7 +59,7 @@ init([]) ->
     process_flag(trap_exit, true),
     ok = config:listen_for_changes(?MODULE, nil),
     {ok, #state{
-        tab = ets:new(procs, [ordered_set, {keypos, #proc.pid}]),
+        tab = ets:new(procs, [ordered_set, {keypos, #proc_int.pid}]),
         config = get_proc_config(),
         proc_counts = dict:new(),
         waiting = ets:new(couch_proc_manage_waiting,
@@ -67,7 +77,7 @@ handle_call({get_proc, #doc{body={Props}}=DDoc, DDocKey}, From, State) ->
     Lang = couch_util:to_binary(
             couch_util:get_value(<<"language">>, Props, <<"javascript">>)),
     IterFun = fun(Proc, Acc) ->
-        case lists:member(DDocKey, Proc#proc.ddoc_keys) of
+        case lists:member(DDocKey, Proc#proc_int.ddoc_keys) of
             true ->
                 {stop, assign_proc(State#state.tab, ClientPid, Proc)};
             false ->
@@ -98,7 +108,7 @@ handle_call({ret_proc, #proc{client=Ref, lang=Lang0} = Proc}, _From, State) ->
     Lang = couch_util:to_binary(Lang0),
     % We need to check if the process is alive here, as the client could be
     % handing us a #proc{} with a dead one.  We would have already removed the
-    % #proc{} from our own table, so the alternative is to do a lookup in the
+    % #proc_int{} from our own table, so the alternative is to do a lookup in the
     % table before the insert.  Don't know which approach is cheaper.
     {reply, true, return_proc(State, Proc#proc{lang=Lang})};
 
@@ -109,7 +119,7 @@ handle_cast({os_proc_idle, Pid}, #state{tab=Tab, proc_counts=Counts}=State0) ->
     Limit = list_to_integer(
             config:get("query_server_config", "os_process_soft_limit", "100")),
     State = case ets:lookup(Tab, Pid) of
-        [#proc{client=nil, lang=Lang}] ->
+        [#proc_int{client=nil, lang=Lang}] ->
             case dict:find(Lang, Counts) of
                 {ok, Count} when Count > Limit ->
                     ?LOG_INFO("Closing idle OS Process: ~p", [Pid]),
@@ -141,7 +151,7 @@ handle_info(shutdown, State) ->
     {stop, shutdown, State};
 
 handle_info({'EXIT', _, {ok, Proc0, {ClientPid,_} = From}}, State) ->
-    link(Proc0#proc.pid),
+    link(Proc0#proc_int.pid),
     Proc = assign_proc(State#state.tab, ClientPid, Proc0),
     gen_server:reply(From, {ok, Proc, State#state.config}),
     {noreply, State};
@@ -152,7 +162,7 @@ handle_info({'EXIT', Pid, Reason}, State) ->
     MaybeProc = ets:lookup(State#state.tab, Pid),
     ets:delete(State#state.tab, Pid),
     case MaybeProc of
-        [#proc{lang=Lang}] ->
+        [#proc_int{lang=Lang}] ->
             case get_waiting_client(Waiting, Lang) of
                 nil ->
                     {noreply, State#state{
@@ -167,10 +177,10 @@ handle_info({'EXIT', Pid, Reason}, State) ->
     end;
 
 handle_info({'DOWN', Ref, _, _, _Reason}, State0) ->
-    case ets:match_object(State0#state.tab, #proc{client=Ref, _='_'}) of
+    case ets:match_object(State0#state.tab, #proc_int{client=Ref, _='_'}) of
     [] ->
         {noreply, State0};
-    [#proc{} = Proc] ->
+    [#proc_int{} = Proc] ->
         {noreply, return_proc(State0, Proc)}
     end;
 
@@ -186,14 +196,11 @@ handle_info(_Msg, State) ->
     {noreply, State}.
 
 terminate(_Reason, #state{tab=Tab}) ->
-    ets:foldl(fun(#proc{pid=P}, _) -> couch_util:shutdown_sync(P) end, 0, Tab),
+    ets:foldl(fun(#proc_int{pid=P}, _) -> couch_util:shutdown_sync(P) end, 0, Tab),
     ok.
 
-code_change(_OldVsn, #state{tab = Tab} = State, _Extra) ->
-    NewTab = ets:new(procs, [ordered_set, {keypos, #proc.pid}]),
-    true = ets:insert(NewTab, ets:tab2list(Tab)),
-    true = ets:delete(Tab),
-    {ok, State#state{tab = NewTab}}.
+code_change(_, State, _) ->
+    {ok, State}.
 
 handle_config_change("query_server_config", _, _, _, _) ->
     gen_server:cast(?MODULE, reload_config),
@@ -217,7 +224,7 @@ find_proc(State, Client, []) ->
 iter_procs(Tab, Lang, Fun, Acc) when is_list(Lang) ->
     iter_procs(Tab, list_to_binary(Lang), Fun, Acc);
 iter_procs(Tab, Lang, Fun, Acc) ->
-    Pattern = #proc{lang=Lang, client=nil, _='_'},
+    Pattern = #proc_int{lang=Lang, client=nil, _='_'},
     MSpec = [{Pattern, [], ['$_']}],
     case ets:select_reverse(Tab, MSpec, 25) of
         '$end_of_table' ->
@@ -282,8 +289,12 @@ new_proc_int(From, Lang) when is_list(Lang) ->
         make_proc(Pid, Lang, couch_os_process)
     end.
 
+export_proc(#proc_int{} = ProcInt) ->
+    [_ | Data] = lists:sublist(record_info(size, proc), tuple_to_list(ProcInt)),
+    list_to_tuple([proc | Data]).
+
 proc_with_ddoc(DDoc, DDocKey, Procs) ->
-    Filter = fun(#proc{ddoc_keys=Keys}) -> not lists:member(DDocKey, Keys) end,
+    Filter = fun(#proc_int{ddoc_keys=Keys}) -> not lists:member(DDocKey, Keys) end,
     case lists:dropwhile(Filter, Procs) of
     [DDocProc|_] ->
         {ok, DDocProc};
@@ -300,20 +311,22 @@ teach_any_proc(DDoc, DDocKey, [Proc|Rest]) ->
 teach_any_proc(_, _, []) ->
     {error, noproc}.
 
-teach_ddoc(DDoc, {DDocId, _Rev}=DDocKey, #proc{ddoc_keys=Keys}=Proc) ->
+teach_ddoc(DDoc, {DDocId, _Rev}=DDocKey, #proc_int{ddoc_keys=Keys}=Proc) ->
     % send ddoc over the wire
     % we only share the rev with the client we know to update code
     % but it only keeps the latest copy, per each ddoc, around.
-    true = couch_query_servers:proc_prompt(Proc, [<<"ddoc">>, <<"new">>,
-        DDocId, couch_doc:to_json_obj(DDoc, [])]),
+    true = couch_query_servers:proc_prompt(
+        export_proc(Proc),
+        [<<"ddoc">>, <<"new">>, DDocId, couch_doc:to_json_obj(DDoc, [])]
+    ),
     % we should remove any other ddocs keys for this docid
     % because the query server overwrites without the rev
     Keys2 = [{D,R} || {D,R} <- Keys, D /= DDocId],
     % add ddoc to the proc
-    {ok, Proc#proc{ddoc_keys=[DDocKey|Keys2]}}.
+    {ok, Proc#proc_int{ddoc_keys=[DDocKey|Keys2]}}.
 
 make_proc(Pid, Lang, Mod) ->
-    Proc = #proc{
+    Proc = #proc_int{
         lang = Lang,
         pid = Pid,
         prompt_fun = {Mod, prompt},


[13/20] couch commit: updated refs/heads/windsor-merge-102 to 944c542

Posted by rn...@apache.org.
Add backwards compatible key_group_level option

This adds a new btree reduce fold option called `key_group_level` that
can have the value `exact`, `0`, or `N` where `N` is any positive
integer. The reason for adding this is so that calling code can pass a
group level option instead of a function for key grouping. The important
point is that the new option uses the btree's defined `less` operator to
test equality which means that ICU collation is used for key grouping on
most views.

BugzId: 19776


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

Branch: refs/heads/windsor-merge-102
Commit: 1d6c18e54478765ba4cda4379f0504a441bf5c9e
Parents: caffc58
Author: Paul J. Davis <pa...@gmail.com>
Authored: Wed May 29 13:19:32 2013 -0500
Committer: Robert Newson <rn...@apache.org>
Committed: Mon Aug 4 16:40:39 2014 +0100

----------------------------------------------------------------------
 src/couch_btree.erl | 58 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 57 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/1d6c18e5/src/couch_btree.erl
----------------------------------------------------------------------
diff --git a/src/couch_btree.erl b/src/couch_btree.erl
index 9caceb8..e9d1ea8 100644
--- a/src/couch_btree.erl
+++ b/src/couch_btree.erl
@@ -73,7 +73,7 @@ fold_reduce(#btree{root=Root}=Bt, Fun, Acc, Options) ->
     Dir = couch_util:get_value(dir, Options, fwd),
     StartKey = couch_util:get_value(start_key, Options),
     InEndRangeFun = make_key_in_end_range_function(Bt, Dir, Options),
-    KeyGroupFun = couch_util:get_value(key_group_fun, Options, fun(_,_) -> true end),
+    KeyGroupFun = get_group_fun(Bt, Options),
     try
         {ok, Acc2, GroupedRedsAcc2, GroupedKVsAcc2, GroupedKey2} =
             reduce_stream_node(Bt, Dir, Root, StartKey, InEndRangeFun, undefined, [], [],
@@ -103,6 +103,62 @@ size(#btree{root = {_P, _Red}}) ->
 size(#btree{root = {_P, _Red, Size}}) ->
     Size.
 
+get_group_fun(Bt, Options) ->
+    case couch_util:get_value(key_group_level, Options) of
+        exact ->
+            make_group_fun(Bt, exact);
+        0 ->
+            fun(_, _) -> true end;
+        N when is_integer(N), N > 0 ->
+            make_group_fun(Bt, N);
+        undefined ->
+            couch_util:get_value(key_group_fun, Options, fun(_,_) -> true end)
+    end.
+
+make_group_fun(Bt, exact) ->
+    fun({Key1, _}, {Key2, _}) ->
+        case less(Bt, {Key1, nil}, {Key2, nil}) of
+            false ->
+                case less(Bt, {Key2, nil}, {Key1, nil}) of
+                    false ->
+                        true;
+                    _ ->
+                        false
+                end;
+            _ ->
+                false
+        end
+    end;
+make_group_fun(Bt, GroupLevel) when is_integer(GroupLevel), GroupLevel > 0 ->
+    fun
+        ({[_|_] = Key1, _}, {[_|_] = Key2, _}) ->
+            SL1 = lists:sublist(Key1, GroupLevel),
+            SL2 = lists:sublist(Key2, GroupLevel),
+            case less(Bt, {SL1, nil}, {SL2, nil}) of
+                false ->
+                    case less(Bt, {SL2, nil}, {SL1, nil}) of
+                        false ->
+                            true;
+                        _ ->
+                            false
+                    end;
+                _ ->
+                    false
+            end;
+        ({Key1, _}, {Key2, _}) ->
+            case less(Bt, {Key1, nil}, {Key2, nil}) of
+                false ->
+                    case less(Bt, {Key2, nil}, {Key1, nil}) of
+                        false ->
+                            true;
+                        _ ->
+                            false
+                    end;
+                _ ->
+                    false
+            end
+    end.
+
 % wraps a 2 arity function with the proper 3 arity function
 convert_fun_arity(Fun) when is_function(Fun, 2) ->
     fun


[09/20] couch commit: updated refs/heads/windsor-merge-102 to 944c542

Posted by rn...@apache.org.
Update couch_auth_cache to use new couch_event app


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

Branch: refs/heads/windsor-merge-102
Commit: be7b1a48fd7a9ba135915be7a76a5996b702bec7
Parents: 2b45f92
Author: Paul J. Davis <pa...@gmail.com>
Authored: Tue Apr 23 15:53:49 2013 -0500
Committer: Robert Newson <rn...@apache.org>
Committed: Mon Aug 4 15:19:30 2014 +0100

----------------------------------------------------------------------
 src/couch_auth_cache.erl | 44 ++++++++++++++++++++++++++-----------------
 1 file changed, 27 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/be7b1a48/src/couch_auth_cache.erl
----------------------------------------------------------------------
diff --git a/src/couch_auth_cache.erl b/src/couch_auth_cache.erl
index 4f6c308..72e9278 100644
--- a/src/couch_auth_cache.erl
+++ b/src/couch_auth_cache.erl
@@ -22,6 +22,7 @@
 -export([code_change/3, terminate/2]).
 
 -export([handle_config_change/5]).
+-export([handle_db_event/3]).
 
 -include_lib("couch/include/couch_db.hrl").
 -include("couch_js_functions.hrl").
@@ -34,7 +35,8 @@
     max_cache_size = 0,
     cache_size = 0,
     db_notifier = nil,
-    db_mon_ref = nil
+    db_mon_ref = nil,
+    event_listener = nil
 }).
 
 
@@ -131,11 +133,14 @@ init(_) ->
     ?STATE = ets:new(?STATE, [set, protected, named_table]),
     ?BY_USER = ets:new(?BY_USER, [set, protected, named_table]),
     ?BY_ATIME = ets:new(?BY_ATIME, [ordered_set, private, named_table]),
+    AuthDbName = config:get("couch_httpd_auth", "authentication_db"),
     process_flag(trap_exit, true),
     ok = config:listen_for_changes(?MODULE, nil),
-    {ok, Notifier} = couch_db_update_notifier:start_link(fun handle_db_event/1),
+    {ok, Listener} = couch_event:link_listener(
+            ?MODULE, handle_db_event, nil, [{dbname, AuthDbName}]
+        ),
     State = #state{
-        db_notifier = Notifier,
+        event_listener = Listener,
         max_cache_size = list_to_integer(
             config:get("couch_httpd_auth", "auth_cache_size", "50")
         )
@@ -143,18 +148,14 @@ init(_) ->
     {ok, reinit_cache(State)}.
 
 
-handle_db_event({Event, DbName}) ->
-    [{auth_db_name, AuthDbName}] = ets:lookup(?STATE, auth_db_name),
-    case DbName =:= AuthDbName of
-    true ->
-        case Event of
-        created -> gen_server:call(?MODULE, reinit_cache, infinity);
-        compacted -> gen_server:call(?MODULE, auth_db_compacted, infinity);
-        _Else   -> ok
-        end;
-    false ->
-        ok
-    end.
+handle_db_event(_DbName, created, St) ->
+    gen_server:call(?MODULE, reinit_cache, infinity),
+    {ok, St};
+handle_db_event(_DbName, compacted, St) ->
+    gen_server:call(?MODULE, auth_db_compacted, infinity),
+    {ok, St};
+handle_db_event(_, _, St) ->
+    {ok, St}.
 
 
 handle_call(reinit_cache, _From, State) ->
@@ -206,6 +207,15 @@ handle_cast({cache_hit, UserName}, State) ->
     {noreply, State}.
 
 
+handle_info({'EXIT', LPid, _Reason}, #state{event_listener=LPid}=State) ->
+    erlang:send_after(5000, self(), restart_event_listener),
+    {noreply, State#state{event_listener=undefined}};
+handle_info(restart_event_listener, State) ->
+    [{auth_db_name, AuthDbName}] = ets:lookup(?STATE, auth_db_name),
+    {ok, NewListener} = couch_event:link_listener(
+            ?MODULE, handle_db_event, nil, [{dbanme, AuthDbName}]
+        ),
+    {noreply, State#state{event_listener=NewListener}};
 handle_info({gen_event_EXIT, {config_listener, ?MODULE}, _Reason}, State) ->
     erlang:send_after(5000, self(), restart_config_listener),
     {noreply, State};
@@ -216,8 +226,8 @@ handle_info({'DOWN', Ref, _, _, _Reason}, #state{db_mon_ref = Ref} = State) ->
     {noreply, reinit_cache(State)}.
 
 
-terminate(_Reason, #state{db_notifier = Notifier}) ->
-    couch_db_update_notifier:stop(Notifier),
+terminate(_Reason, #state{event_listener = Listener}) ->
+    couch_event:stop_listener(Listener),
     exec_if_auth_db(fun(AuthDb) -> catch couch_db:close(AuthDb) end),
     true = ets:delete(?BY_USER),
     true = ets:delete(?BY_ATIME),


[16/20] couch commit: updated refs/heads/windsor-merge-102 to 944c542

Posted by rn...@apache.org.
Fix typo in pattern match


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

Branch: refs/heads/windsor-merge-102
Commit: 286df6eac01c8d26be33bb0fb0e4a78959de3963
Parents: 1e8e996
Author: Robert Newson <rn...@apache.org>
Authored: Mon Aug 4 18:12:32 2014 +0100
Committer: Robert Newson <rn...@apache.org>
Committed: Mon Aug 4 18:27:10 2014 +0100

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/286df6ea/src/couch_proc_manager.erl
----------------------------------------------------------------------
diff --git a/src/couch_proc_manager.erl b/src/couch_proc_manager.erl
index 24c3b47..8dd7da4 100644
--- a/src/couch_proc_manager.erl
+++ b/src/couch_proc_manager.erl
@@ -188,7 +188,7 @@ handle_info({gen_event_EXIT, {config_listener, ?MODULE}, _Reason}, State) ->
     erlang:send_after(5000, self(), restart_config_listener),
     {noreply, State};
 
-handle_info(restart_config_lister, State) ->
+handle_info(restart_config_listener, State) ->
     ok = config:listen_for_changes(?MODULE, nil),
     {noreply, State};
 


[20/20] couch commit: updated refs/heads/windsor-merge-102 to 944c542

Posted by rn...@apache.org.
Fix use of lists:sublist/2

The lists module has pretty terrible consistency on which argument is
the list. This one happens to take the list first.


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

Branch: refs/heads/windsor-merge-102
Commit: 944c5426b700bfe1817c49925d83d644200945b9
Parents: f69d7ef
Author: Paul J. Davis <pa...@gmail.com>
Authored: Fri Jun 7 14:42:11 2013 -0500
Committer: Robert Newson <rn...@apache.org>
Committed: Mon Aug 4 18:41:43 2014 +0100

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


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/944c5426/src/couch_proc_manager.erl
----------------------------------------------------------------------
diff --git a/src/couch_proc_manager.erl b/src/couch_proc_manager.erl
index 3cbb744..fbe0104 100644
--- a/src/couch_proc_manager.erl
+++ b/src/couch_proc_manager.erl
@@ -327,7 +327,7 @@ new_proc_int(From, Lang) when is_list(Lang) ->
     end.
 
 export_proc(#proc_int{} = ProcInt) ->
-    [_ | Data] = lists:sublist(record_info(size, proc), tuple_to_list(ProcInt)),
+    [_ | Data] = lists:sublist(tuple_to_list(ProcInt), record_info(size, proc)),
     list_to_tuple([proc | Data]).
 
 import_proc(#proc{} = P) ->


[18/20] couch commit: updated refs/heads/windsor-merge-102 to 944c542

Posted by rn...@apache.org.
Allow operator to forcibly terminate stale procs

This patch adds a new terminate_stale_procs/0 command which kills off
any OS processes with spawn times older than the current threshold time,
regardless of whether the process has a client.  It also refactors the
internals to use the same logic to terminate a process in every case.

BugzID: 19529


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

Branch: refs/heads/windsor-merge-102
Commit: 0e78ae2ff7a28cea5353dae05dc1432f1dfbe4fa
Parents: 814eadc
Author: Adam Kocoloski <ad...@cloudant.com>
Authored: Mon Jun 3 13:24:02 2013 -0400
Committer: Robert Newson <rn...@apache.org>
Committed: Mon Aug 4 18:39:47 2014 +0100

----------------------------------------------------------------------
 src/couch_proc_manager.erl | 37 ++++++++++++++++++++++++-------------
 1 file changed, 24 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/0e78ae2f/src/couch_proc_manager.erl
----------------------------------------------------------------------
diff --git a/src/couch_proc_manager.erl b/src/couch_proc_manager.erl
index e0f03e5..93c53cb 100644
--- a/src/couch_proc_manager.erl
+++ b/src/couch_proc_manager.erl
@@ -22,7 +22,8 @@
     get_proc_count/0,
     get_stale_proc_count/0,
     new_proc/1,
-    reload/0
+    reload/0,
+    terminate_stale_procs/0
 ]).
 
 % config_listener api
@@ -69,6 +70,9 @@ get_stale_proc_count() ->
 reload() ->
     gen_server:call(?MODULE, bump_threshold_ts).
 
+terminate_stale_procs() ->
+    gen_server:call(?MODULE, terminate_stale_procs).
+
 init([]) ->
     process_flag(trap_exit, true),
     ok = config:listen_for_changes(?MODULE, nil),
@@ -134,14 +138,20 @@ handle_call({ret_proc, #proc{client=Ref, lang=Lang0} = Proc}, _From, State) ->
 
 handle_call(bump_threshold_ts, _From, #state{tab = Tab} = State) ->
     FoldFun = fun(#proc_int{client = nil, pid = Pid}, _) ->
-        gen_server:cast(Pid, stop),
-        ets:delete(Tab, Pid);
+        remove_proc(Tab, Pid);
     (_, _) ->
         ok
     end,
     ets:foldl(FoldFun, nil, Tab),
     {reply, ok, State#state{threshold_ts = os:timestamp()}};
 
+handle_call(terminate_stale_procs, _From, State) ->
+    #state{tab = Tab, threshold_ts = T0} = State,
+    MatchHead = #proc_int{pid = '$1', t0 = '$2', _ = '_'},
+    MatchSpec = [{MatchHead, [{'<', '$2', T0}], ['$1']}],
+    lists:foreach(fun(P) -> remove_proc(Tab,P) end, ets:select(Tab, MatchSpec)),
+    {reply, ok, State};
+
 handle_call(_Call, _From, State) ->
     {reply, ignored, State}.
 
@@ -153,14 +163,7 @@ handle_cast({os_proc_idle, Pid}, #state{tab=Tab, proc_counts=Counts}=State0) ->
             case dict:find(Lang, Counts) of
                 {ok, Count} when Count > Limit ->
                     ?LOG_INFO("Closing idle OS Process: ~p", [Pid]),
-                    ets:delete(Tab, Pid),
-                    case is_process_alive(Pid) of
-                        true ->
-                            unlink(Pid),
-                            gen_server:cast(Pid, stop);
-                        _ ->
-                            ok
-                    end,
+                    remove_proc(Tab, Pid),
                     State0#state{
                         proc_counts=dict:update_counter(Lang, -1, Counts)
                     };
@@ -323,6 +326,15 @@ export_proc(#proc_int{} = ProcInt) ->
     [_ | Data] = lists:sublist(record_info(size, proc), tuple_to_list(ProcInt)),
     list_to_tuple([proc | Data]).
 
+remove_proc(Tab, Pid) ->
+    ets:delete(Tab, Pid),
+    case is_process_alive(Pid) of true ->
+        unlink(Pid),
+        gen_server:cast(Pid, stop);
+    false ->
+        ok
+    end.
+
 proc_with_ddoc(DDoc, DDocKey, Procs) ->
     Filter = fun(#proc_int{ddoc_keys=Keys}) -> not lists:member(DDocKey, Keys) end,
     case lists:dropwhile(Filter, Procs) of
@@ -382,8 +394,7 @@ return_proc(State, #proc{pid=Pid, lang=Lang} = Proc) ->
             nil ->
                 [ProcInt] = ets:lookup(Tab, Pid),
                 if ProcInt#proc_int.t0 < T0 ->
-                    gen_server:cast(Pid, stop),
-                    ets:delete(Tab, Pid);
+                    remove_proc(Tab, Pid);
                 true ->
                     gen_server:cast(Pid, garbage_collect),
                     ets:insert(Tab, Proc#proc{client=nil})


[05/20] couch commit: updated refs/heads/windsor-merge-102 to 944c542

Posted by rn...@apache.org.
Add couch_event dependency


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

Branch: refs/heads/windsor-merge-102
Commit: c4ce4906797006337a691af956d358a05c38d5a2
Parents: ff3b88b
Author: Robert Newson <rn...@apache.org>
Authored: Tue Jul 22 17:12:58 2014 +0100
Committer: Robert Newson <rn...@apache.org>
Committed: Mon Aug 4 14:16:55 2014 +0100

----------------------------------------------------------------------
 src/couch.app.src | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/c4ce4906/src/couch.app.src
----------------------------------------------------------------------
diff --git a/src/couch.app.src b/src/couch.app.src
index 48b089b..8007278 100644
--- a/src/couch.app.src
+++ b/src/couch.app.src
@@ -29,5 +29,5 @@
     ]},
     {mod, {couch_app, []}},
     {applications, [kernel, stdlib, crypto, sasl, inets, oauth, ibrowse,
-        mochiweb, ssl, couch_log]}
+        mochiweb, ssl, couch_log, couch_event]}
 ]}.


[12/20] couch commit: updated refs/heads/windsor-merge-102 to 944c542

Posted by rn...@apache.org.
Remove ets table scan on process exit

This commit adds a new ets table for doing O(1) pid-to-db-name lookup.
This is to remove the necessity for doing an ets table scan on the exit
of a monitored process.

BugzID: 19132


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

Branch: refs/heads/windsor-merge-102
Commit: caffc58f3cc62211294b39eda0e32b2ff230bde2
Parents: b7b20c9
Author: Benjamin Bastian <be...@gmail.com>
Authored: Tue May 28 15:03:03 2013 -0700
Committer: Robert Newson <rn...@apache.org>
Committed: Mon Aug 4 16:40:35 2014 +0100

----------------------------------------------------------------------
 src/couch_lru.erl    |  1 +
 src/couch_server.erl | 18 ++++++++++++++----
 2 files changed, 15 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/caffc58f/src/couch_lru.erl
----------------------------------------------------------------------
diff --git a/src/couch_lru.erl b/src/couch_lru.erl
index 97f27f8..ad432ec 100644
--- a/src/couch_lru.erl
+++ b/src/couch_lru.erl
@@ -47,6 +47,7 @@ close_int({Lru, DbName, Iter}, {Tree, Dict} = Cache) ->
         [#db{main_pid = Pid} = Db] = ets:lookup(couch_dbs, DbName),
         case couch_db:is_idle(Db) of true ->
             true = ets:delete(couch_dbs, DbName),
+            true = ets:delete(couch_dbs_pid_to_name, Pid),
             exit(Pid, kill),
             {gb_trees:delete(Lru, Tree), dict:erase(DbName, Dict)};
         false ->

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/caffc58f/src/couch_server.erl
----------------------------------------------------------------------
diff --git a/src/couch_server.erl b/src/couch_server.erl
index 5a73877..a10fcd0 100644
--- a/src/couch_server.erl
+++ b/src/couch_server.erl
@@ -198,6 +198,7 @@ init([]) ->
         "(\\.[0-9]{10,})?$" % but allow an optional shard timestamp at the end
     ),
     ets:new(couch_dbs, [set, protected, named_table, {keypos, #db.name}]),
+    ets:new(couch_dbs_pid_to_name, [set, protected, named_table]),
     process_flag(trap_exit, true),
     {ok, #server{root_dir=RootDir,
                 dbname_regexp=RegExp,
@@ -312,6 +313,7 @@ open_async(Server, From, DbName, Filepath, Options) ->
         fd_monitor = locked,
         options = Options
     }),
+    true = ets:insert(couch_dbs_pid_to_name, {Opener, DbName}),
     db_opened(Server, Options).
 
 handle_call(close_lru, _From, #server{lru=Lru} = Server) ->
@@ -326,8 +328,9 @@ handle_call({set_max_dbs_open, Max}, _From, Server) ->
     {reply, ok, Server#server{max_dbs_open=Max}};
 handle_call(get_server, _From, Server) ->
     {reply, {ok, Server}, Server};
-handle_call({open_result, DbName, {ok, Db}}, _From, Server) ->
+handle_call({open_result, DbName, {ok, Db}}, {FromPid, _Tag}, Server) ->
     link(Db#db.main_pid),
+    true = ets:delete(couch_dbs_pid_to_name, FromPid),
     case erase({async_open, DbName}) of undefined -> ok; T0 ->
         ?LOG_INFO("needed ~p ms to open new ~s", [timer:now_diff(os:timestamp(),T0)/1000,
             DbName])
@@ -344,6 +347,7 @@ handle_call({open_result, DbName, {ok, Db}}, _From, Server) ->
             ok
     end,
     true = ets:insert(couch_dbs, Db),
+    true = ets:insert(couch_dbs_pid_to_name, {Db#db.main_pid, DbName}),
     Lru = case couch_db:is_system_db(Db) of
         false ->
             Stat = {couchdb, open_databases},
@@ -355,12 +359,13 @@ handle_call({open_result, DbName, {ok, Db}}, _From, Server) ->
     {reply, ok, Server#server{lru = Lru}};
 handle_call({open_result, DbName, {error, eexist}}, From, Server) ->
     handle_call({open_result, DbName, file_exists}, From, Server);
-handle_call({open_result, DbName, Error}, _From, Server) ->
+handle_call({open_result, DbName, Error}, {FromPid, _Tag}, Server) ->
     % icky hack of field values - compactor_pid used to store clients
     [#db{fd=ReqType, compactor_pid=Froms}=Db] = ets:lookup(couch_dbs, DbName),
     [gen_server:reply(From, Error) || From <- Froms],
     ?LOG_INFO("open_result error ~p for ~s", [Error, DbName]),
     true = ets:delete(couch_dbs, DbName),
+    true = ets:delete(couch_dbs_pid_to_name, FromPid),
     NewServer = case ReqType of
         {create, DbName, Filepath, Options, CrFrom} ->
             open_async(Server, CrFrom, DbName, Filepath, Options);
@@ -435,11 +440,13 @@ handle_call({delete, DbName, Options}, _From, Server) ->
         [#db{main_pid=Pid, compactor_pid=Froms} = Db] when is_list(Froms) ->
             % icky hack of field values - compactor_pid used to store clients
             true = ets:delete(couch_dbs, DbName),
+            true = ets:delete(couch_dbs_pid_to_name, Pid),
             exit(Pid, kill),
             [gen_server:reply(F, not_found) || F <- Froms],
             db_closed(Server, Db#db.options);
         [#db{main_pid=Pid} = Db] ->
             true = ets:delete(couch_dbs, DbName),
+            true = ets:delete(couch_dbs_pid_to_name, Pid),
             exit(Pid, kill),
             db_closed(Server, Db#db.options)
         end,
@@ -485,8 +492,10 @@ code_change(_, State, _) ->
 handle_info({'EXIT', _Pid, config_change}, Server) ->
     {stop, config_change, Server};
 handle_info({'EXIT', Pid, Reason}, Server) ->
-    case ets:match_object(couch_dbs, #db{main_pid=Pid, _='_'}) of
-    [#db{name = DbName, compactor_pid=Froms} = Db] ->
+    case ets:lookup(couch_dbs_pid_to_name, Pid) of
+    [DbName] ->
+        [#db{compactor_pid=Froms}=Db] =
+            ets:match_object(couch_dbs, #db{name=DbName, _='_'}),
         if Reason /= snappy_nif_not_loaded -> ok; true ->
             Msg = io_lib:format("To open the database `~s`, Apache CouchDB "
                 "must be built with Erlang OTP R13B04 or higher.", [DbName]),
@@ -500,6 +509,7 @@ handle_info({'EXIT', Pid, Reason}, Server) ->
             ok
         end,
         true = ets:delete(couch_dbs, DbName),
+        true = ets:delete(couch_dbs_pid_to_name, Pid),
         {noreply, db_closed(Server, Db#db.options)};
     [] ->
         {noreply, Server}