diff options
author | Paul J. Davis <paul.joseph.davis@gmail.com> | 2018-09-10 14:32:20 -0500 |
---|---|---|
committer | Paul J. Davis <paul.joseph.davis@gmail.com> | 2018-09-10 14:47:16 -0500 |
commit | 80076d4ab92f95dc555dcf88897ff458f4916eb3 (patch) | |
tree | 79ab2b35fc303e43070ec9b7aed717651b080be0 | |
parent | 19a390c8ea41bf84d1a38096e622b10eb94daf7c (diff) | |
download | couchdb-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.erl | 25 |
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 [] -> |