summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul J. Davis <paul.joseph.davis@gmail.com>2018-09-10 14:32:20 -0500
committerPaul J. Davis <paul.joseph.davis@gmail.com>2018-09-10 14:47:16 -0500
commit80076d4ab92f95dc555dcf88897ff458f4916eb3 (patch)
tree79ab2b35fc303e43070ec9b7aed717651b080be0
parent19a390c8ea41bf84d1a38096e622b10eb94daf7c (diff)
downloadcouchdb-couch-server-improvements-with-deadline.tar.gz
Add a deadline for open messages with a timeoutcouch-server-improvements-with-deadline
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.
-rw-r--r--src/couch/src/couch_server.erl25
1 files changed, 24 insertions, 1 deletions
diff --git a/src/couch/src/couch_server.erl b/src/couch/src/couch_server.erl
index c4b7bf199..782bba766 100644
--- a/src/couch/src/couch_server.erl
+++ b/src/couch/src/couch_server.erl
@@ -88,7 +88,14 @@ open(DbName, Options0) ->
Options = maybe_add_sys_db_callbacks(DbName, Options0),
Timeout = couch_util:get_value(timeout, Options, 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), Timeout >= 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
[] ->