This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch couch-server-improvements-with-deadline
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit d2bf663482168036f408de39a74ed01ead472a9b
Author: Paul J. Davis <[email protected]>
AuthorDate: Mon Sep 10 14:32:20 2018 -0500

    Add a deadline for open messages with a timeout
    
    There's no point in performing the work for messages from workers that
    have abandoned listening for a request from couch_server. This change
    adds a deadline value to each timeout open message. If couch_server sees
    one of these after the deadline has passed it will return an error
    (although the process may not even be alive any longer) and then
    continue handling messages.
---
 src/couch/src/couch_server.erl | 29 ++++++++++++++++++++++++++---
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/src/couch/src/couch_server.erl b/src/couch/src/couch_server.erl
index c4b7bf1..330404d 100644
--- a/src/couch/src/couch_server.erl
+++ b/src/couch/src/couch_server.erl
@@ -85,10 +85,17 @@ open(DbName, Options0) ->
         {ok, Db1} = couch_db:incref(Db0),
         couch_db:set_user_ctx(Db1, Ctx);
     _ ->
-        Options = maybe_add_sys_db_callbacks(DbName, Options0),
-        Timeout = couch_util:get_value(timeout, Options, infinity),
+        Options1 = maybe_add_sys_db_callbacks(DbName, Options0),
+        Timeout = couch_util:get_value(timeout, Options1, infinity),
         Create = couch_util:get_value(create_if_missing, Options, false),
-        case gen_server:call(couch_server, {open, DbName, Options}, Timeout) of
+        Msg = case Timeout of
+            infinity ->
+                {open, DbName, Options};
+            _ when is_integer(Timeout), Timeout >= 0 ->
+                Deadline = make_deadline(Timeout),
+                {open, DbName, Options, Deadline}
+        end,
+        case gen_server:call(couch_server, Msg, Timeout) of
         {ok, Db0} ->
             {ok, Db1} = couch_db:incref(Db0),
             couch_db:set_user_ctx(Db1, Ctx);
@@ -100,6 +107,15 @@ open(DbName, Options0) ->
         end
     end.
 
+make_deadline(Timeout) when is_integer(Timeout), Timeoue >= 0 ->
+    {MegaNow, SecNow, MicroNow} = os:timestamp(),
+    Now = MegaNow * 1000000 * 1000000 + SecNow * 1000000 + MicroNow,
+    Deadline = Now + round(Timeout * 1.25),
+    MegaFuture = (Deadline div 1000000) div 1000000,
+    SecFuture = (Deadline div 1000000) rem 1000000,
+    MicroFuture = Deadline rem 1000000,
+    {MegaFuture, SecFuture, MicroFuture}.
+
 update_lru(DbName, Options) ->
     case config:get_boolean("couchdb", "update_lru_on_read", false) of
         true ->
@@ -468,6 +484,13 @@ handle_call({open_result, _T0, DbName, Error}, {Opener, 
_}, Server) ->
             % was in our mailbox and is now stale. Ignore it.
             {reply, ok, Server}
     end;
+handle_call({open, DbName, Options, Deadline}, From, Server) ->
+    case timer:now_diff(Deadline, os:timestamp()) of
+        N when N < 0 ->
+            {reply, {error, deadline_exceeded}, Server};
+        _ ->
+            handle_call({open, DbName, Options}, From, Server)
+    end;
 handle_call({open, DbName, Options}, From, Server) ->
     case ets:lookup(couch_dbs, DbName) of
     [] ->

Reply via email to