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 18:47:12 UTC

[12/34] couch commit: updated refs/heads/windsor-merge-209 to f2368da

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-209
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}