From 2df8cdfeb592a62a696be4487de48453b9bd5528 Mon Sep 17 00:00:00 2001 From: Bill Williams Date: Wed, 12 Feb 2020 09:42:15 -0800 Subject: [PATCH] change jitter calculation --- src/connection.c | 58 +++++++++++++++++++++------------------ tests/test_connection.c | 61 +++++++++++++++++++++++------------------ 2 files changed, 66 insertions(+), 53 deletions(-) diff --git a/src/connection.c b/src/connection.c index eed6ff1..9e25c5c 100644 --- a/src/connection.c +++ b/src/connection.c @@ -231,20 +231,19 @@ void init_backoff_timer (backoff_timer_t *timer, int max_count) { timer->count = 1; timer->max_count = max_count; - timer->delay = 0; + timer->delay = 1; clock_gettime (CLOCK_REALTIME, &timer->ts); timer->start_time = time(NULL); } unsigned update_backoff_delay (backoff_timer_t *timer) { - int next_delay = timer->delay; if (timer->count < timer->max_count) { timer->count += 1; - timer->delay = next_delay + next_delay + 1; - // 0,1,3,7,15,31 .. + timer->delay = timer->delay + timer->delay + 1; + // 3,7,15,31 .. } - return (unsigned) next_delay; + return (unsigned) timer->delay; } void add_timespec (struct timespec *t1, struct timespec *t2) @@ -257,31 +256,36 @@ void add_timespec (struct timespec *t1, struct timespec *t2) } } -void calc_random_expiration (int random_num, backoff_timer_t *timer, struct timespec *ts) +unsigned calc_random_secs (int random_num, unsigned max_secs) { + unsigned delay_secs = (unsigned) random_num & max_secs; + if (delay_secs < 3) + return delay_secs + 3; + else + return delay_secs; +} + +unsigned calc_random_nsecs (int random_num) +{ + /* random _num is in range 0..2147483648 */ + unsigned n = (unsigned) random_num >> 1; + /* n is in range 0..1073741824 */ + if (n < 1000000000) + return n; + return n - 1000000000; +} + +void calc_random_expiration (int random_num1, int random_num2, backoff_timer_t *timer, struct timespec *ts) +{ + unsigned max_secs = update_backoff_delay (timer); // 3,7,15,31 struct timespec ts_delay = {3, 0}; - unsigned delay_secs = update_backoff_delay (timer); // 0,1,3,7,15,31 - unsigned r262144 = 0; - unsigned r250000 = 0; - unsigned rdelay = 0; - if (0 != delay_secs) { - /* pick a random # in range 0..250000 - * 250000 chosen because it is easy to scale into the range we want */ - r262144 = (unsigned) (random_num >> 13); /* random (0..262144) */ - r250000 = (r262144*15625) >> 14; - - /* scale into range 4000000 usecs * delay_secs */ - rdelay = r250000 * delay_secs; - - /* secs = rdelay * (4000000 / 250000) / 1000000 */ - ts_delay.tv_sec = rdelay / 62500; /* (rdelay*4) / 250000 */ - ts_delay.tv_nsec = (rdelay % 62500) * 16000; - - ts_delay.tv_sec += 3; /* minimum 3 sec delay */ + if (max_secs > 3) { + ts_delay.tv_sec = calc_random_secs (random_num1, max_secs); + ts_delay.tv_nsec = calc_random_nsecs (random_num2); } - ParodusInfo("Waiting max delay %u r250000 %u backoffRetryTime %ld secs %ld usecs\n", - (4*delay_secs)+3, r250000, ts_delay.tv_sec, ts_delay.tv_nsec/1000); + ParodusInfo("Waiting max delay %u backoffRetryTime %ld secs %ld usecs\n", + max_secs, ts_delay.tv_sec, ts_delay.tv_nsec/1000); /* Add delay to expire time */ add_timespec (&ts_delay, ts); @@ -321,7 +325,7 @@ static int backoff_delay (backoff_timer_t *timer) timer->ts.tv_sec += UPDATE_HEALTH_FILE_INTERVAL_SECS; } - calc_random_expiration (random (), timer, &ts); + calc_random_expiration (random(), random(), timer, &ts); pthread_mutex_lock (&backoff_delay_mut); // The condition variable will only be set if we shut down. diff --git a/tests/test_connection.c b/tests/test_connection.c index bcec536..c52bcd1 100644 --- a/tests/test_connection.c +++ b/tests/test_connection.c @@ -37,8 +37,11 @@ extern void init_expire_timer (expire_timer_t *timer); extern int check_timer_expired (expire_timer_t *timer, long timeout_ms); extern void init_backoff_timer (backoff_timer_t *timer, int max_count); extern int update_backoff_delay (backoff_timer_t *timer); -void add_timespec (struct timespec *t1, struct timespec *t2); -void calc_random_expiration (int random_num, backoff_timer_t *timer, struct timespec *ts); +extern void add_timespec (struct timespec *t1, struct timespec *t2); +extern unsigned calc_random_secs (int random_num, unsigned max_secs); +extern unsigned calc_random_nsecs (int random_num); +void calc_random_expiration (int random_num1, int random_num2, + backoff_timer_t *timer, struct timespec *ts); extern int init_header_info (header_info_t *header_info); extern void free_header_info (header_info_t *header_info); extern char *build_extra_hdrs (header_info_t *header_info); @@ -340,13 +343,10 @@ void test_backoff_delay_timer() backoff_timer_t btimer; init_backoff_timer (&btimer, 5); - /* the actual max delay is 4*result + 3 secs */ - assert_int_equal (0, update_backoff_delay (&btimer)); - assert_int_equal (1, update_backoff_delay (&btimer)); assert_int_equal (3, update_backoff_delay (&btimer)); assert_int_equal (7, update_backoff_delay (&btimer)); assert_int_equal (15, update_backoff_delay (&btimer)); - assert_int_equal (15, update_backoff_delay (&btimer)); + assert_int_equal (31, update_backoff_delay (&btimer)); t1.tv_sec = 3; t1.tv_nsec = 0; t2.tv_sec = 3; t2.tv_nsec = 0; @@ -366,30 +366,39 @@ void test_backoff_delay_timer() assert_int_equal (7, t2.tv_sec); assert_int_equal (1000000, t2.tv_nsec); + assert_int_equal (3, calc_random_secs (0, 7)); + assert_int_equal (4, calc_random_secs (1, 7)); + assert_int_equal (7, calc_random_secs (15, 7)); + assert_int_equal (3, calc_random_secs (16, 15)); + assert_int_equal (14, calc_random_secs (30,15)); + + assert_int_equal (250000, calc_random_nsecs (500000)); + assert_int_equal (1, calc_random_nsecs (2000000002)); + init_backoff_timer (&btimer, 5); t1.tv_sec = 0; t1.tv_nsec = 0; - /* max delay is 3, random is 0 */ - calc_random_expiration (0, &btimer, &t1); + /* max delay is 3 */ + calc_random_expiration (0, 0, &btimer, &t1); + assert_int_equal (3, t1.tv_sec); + assert_int_equal (0, t1.tv_nsec); + + t1.tv_sec = 0; t1.tv_nsec = 0; + /* max delay is 7*/ + calc_random_expiration (15, 1073741824, &btimer, &t1); + assert_int_equal (7, t1.tv_sec); + assert_int_equal (536870912, t1.tv_nsec); + + t1.tv_sec = 0; t1.tv_nsec = 0; + /* max delay is 15 */ + calc_random_expiration (30, 2000000002, &btimer, &t1); + assert_int_equal (14, t1.tv_sec); + assert_int_equal (1, t1.tv_nsec); + + t1.tv_sec = 0; t1.tv_nsec = 0; + /* max delay is 31 */ + calc_random_expiration (32, 1, &btimer, &t1); assert_int_equal (3, t1.tv_sec); assert_int_equal (0, t1.tv_nsec); - - t1.tv_sec = 0; t1.tv_nsec = 0; - /* max delay is 7, random is INT_MAX/2 */ - calc_random_expiration (1073741824, &btimer, &t1); - assert_int_equal (5, t1.tv_sec); - assert_int_equal (0, t1.tv_nsec); - - t1.tv_sec = 0; t1.tv_nsec = 0; - /* max delay is 15, random is INT_MAX/4 */ - calc_random_expiration (536870912, &btimer, &t1); - assert_int_equal (6, t1.tv_sec); - assert_int_equal (0, t1.tv_nsec); - - t1.tv_sec = 0; t1.tv_nsec = 0; - /* max delay is 31, random is INT_MAX/8 */ - calc_random_expiration (268435456, &btimer, &t1); - assert_int_equal (6, t1.tv_sec); - assert_int_equal (500*1000000, t1.tv_nsec); }