You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by va...@apache.org on 2021/10/15 15:18:58 UTC

[couchdb] 01/01: Fix badarith error in get_db_timeout when request timeout = infinity

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

vatamane pushed a commit to branch fix-fabric-get-db-timeout-badarith
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 533627ae5db24f6bb942828596d880b5feccf5ee
Author: Nick Vatamaniuc <va...@gmail.com>
AuthorDate: Fri Oct 15 11:00:03 2021 -0400

    Fix badarith error in get_db_timeout when request timeout = infinity
    
    `infinity` it turns out is a valid configuration value for fabric
    request_timeout. We can pass that to Erlang `receive` statement, any arithmetic
    with it would fail.
    
    To guard against the crash use the max small int value (60 bits). With enough
    shards, due to the exponential nature of the algorithm, we still get a nice
    progression from the minimum 100 msec all the way up to the large int value.
    This case is illustrated in the test.
    
    Issue: https://github.com/apache/couchdb/issues/3789
---
 src/fabric/src/fabric_util.erl | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/src/fabric/src/fabric_util.erl b/src/fabric/src/fabric_util.erl
index e07ab7b..4c40316 100644
--- a/src/fabric/src/fabric_util.erl
+++ b/src/fabric/src/fabric_util.erl
@@ -138,6 +138,10 @@ get_shard([#shard{node = Node, name = Name} | Rest], Opts, Timeout, Factor) ->
         rexi_monitor:stop(Mon)
     end.
 
+get_db_timeout(N, Factor, MinTimeout, infinity) ->
+    % MaxTimeout may be infinity so we just use the largest Erlang small int to
+    % avoid blowing up the arithmetic
+    get_db_timeout(N, Factor, MinTimeout, 1 bsl 59);
 get_db_timeout(N, Factor, MinTimeout, MaxTimeout) ->
     %
     % The progression of timeouts forms a geometric series:
@@ -460,4 +464,8 @@ get_db_timeout_test() ->
     ?assertEqual(28346, get_db_timeout(2 * 3, 2, 100, 3600000)),
 
     % No shards at all
-    ?assertEqual(60000, get_db_timeout(0, 2, 100, 60000)).
+    ?assertEqual(60000, get_db_timeout(0, 2, 100, 60000)),
+
+    % request_timeout was set to infinity, with enough shards it still gets to
+    % 100 min timeout at the start from the exponential logic
+    ?assertEqual(100, get_db_timeout(64, 2, 100, infinity)).