Tarantool development patches archive
 help / color / mirror / Atom feed
From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
To: tarantool-patches@freelists.org
Cc: kostja@tarantool.org
Subject: [tarantool-patches] [PATCH 1/5] swim: do not use ev_timer_start
Date: Wed,  1 May 2019 01:31:23 +0300	[thread overview]
Message-ID: <55eb3963102ddf0f83e0358d7041d6e2fabd729c.1556663421.git.v.shpilevoy@tarantool.org> (raw)
In-Reply-To: <cover.1556663421.git.v.shpilevoy@tarantool.org>

Appeared that libev changes 'ev_timer.at' field to a remaining
time value, and it can't be used as a storage for a timeout. By
the same reason ev_timer_start() can't be used to reuse a timer.

On the contrary, 'ev_timer.repeat' is not touched by libev, and
ev_timer_again() allows to reuse a timer.

This patch replaces 'at' with 'repeat' and ev_timer_start() with
ev_timer_again().

The bug was not detected by unit tests, because they implement
their own event loop and do not change ev_timer.at. Now they do
to prevent a regression.

Part of #3234
---
 src/lib/swim/swim.c      | 28 +++++++++++-----------------
 src/lib/swim/swim.h      |  4 ----
 src/lib/swim/swim_ev.c   |  6 ++++++
 src/lib/swim/swim_ev.h   |  3 +++
 test/unit/swim_test_ev.c | 11 +++++++++++
 5 files changed, 31 insertions(+), 21 deletions(-)

diff --git a/src/lib/swim/swim.c b/src/lib/swim/swim.c
index 68b87b120..dfee16493 100644
--- a/src/lib/swim/swim.c
+++ b/src/lib/swim/swim.c
@@ -496,7 +496,7 @@ swim_wait_ack(struct swim *swim, struct swim_member *member,
 	      bool was_ping_indirect)
 {
 	if (heap_node_is_stray(&member->in_wait_ack_heap)) {
-		double timeout = swim->wait_ack_tick.at;
+		double timeout = swim->wait_ack_tick.repeat;
 		/*
 		 * Direct ping is two trips: PING + ACK.
 		 * Indirect ping is four trips: PING,
@@ -507,7 +507,7 @@ swim_wait_ack(struct swim *swim, struct swim_member *member,
 			timeout *= 2;
 		member->ping_deadline = swim_time() + timeout;
 		wait_ack_heap_insert(&swim->wait_ack_heap, member);
-		swim_ev_timer_start(loop(), &swim->wait_ack_tick);
+		swim_ev_timer_again(loop(), &swim->wait_ack_tick);
 	}
 }
 
@@ -767,7 +767,7 @@ swim_new_member(struct swim *swim, const struct sockaddr_in *addr,
 		return NULL;
 	}
 	if (mh_size(swim->members) > 1)
-		swim_ev_timer_start(loop(), &swim->round_tick);
+		swim_ev_timer_again(loop(), &swim->round_tick);
 
 	/* Dissemination component. */
 	swim_on_member_update(swim, member);
@@ -1072,7 +1072,7 @@ swim_complete_step(struct swim_task *task,
 	(void) rc;
 	(void) task;
 	struct swim *swim = swim_by_scheduler(scheduler);
-	swim_ev_timer_start(loop(), &swim->round_tick);
+	swim_ev_timer_again(loop(), &swim->round_tick);
 	/*
 	 * It is possible that the original member was deleted
 	 * manually during the task execution.
@@ -1239,7 +1239,7 @@ swim_check_acks(struct ev_loop *loop, struct ev_timer *t, int events)
 	struct swim_member *m;
 	while ((m = wait_ack_heap_top(&swim->wait_ack_heap)) != NULL) {
 		if (current_time < m->ping_deadline) {
-			swim_ev_timer_start(loop, t);
+			swim_ev_timer_again(loop, t);
 			return;
 		}
 		wait_ack_heap_pop(&swim->wait_ack_heap);
@@ -1635,7 +1635,7 @@ swim_new(void)
 	}
 	rlist_create(&swim->round_queue);
 	swim_ev_timer_init(&swim->round_tick, swim_begin_step,
-			   HEARTBEAT_RATE_DEFAULT, 0);
+			   0, HEARTBEAT_RATE_DEFAULT);
 	swim->round_tick.data = (void *) swim;
 	swim_task_create(&swim->round_step_task, swim_complete_step, NULL,
 			 "round packet");
@@ -1644,7 +1644,7 @@ swim_new(void)
 	/* Failure detection component. */
 	wait_ack_heap_create(&swim->wait_ack_heap);
 	swim_ev_timer_init(&swim->wait_ack_tick, swim_check_acks,
-			   ACK_TIMEOUT_DEFAULT, 0);
+			   0, ACK_TIMEOUT_DEFAULT);
 	swim->wait_ack_tick.data = (void *) swim;
 	swim->gc_mode = SWIM_GC_ON;
 
@@ -1737,11 +1737,11 @@ swim_cfg(struct swim *swim, const char *uri, double heartbeat_rate,
 	} else {
 		addr = swim->self->addr;
 	}
-	if (swim->round_tick.at != heartbeat_rate && heartbeat_rate > 0)
-		swim_ev_timer_set(&swim->round_tick, heartbeat_rate, 0);
+	if (swim->round_tick.repeat != heartbeat_rate && heartbeat_rate > 0)
+		swim_ev_timer_set(&swim->round_tick, 0, heartbeat_rate);
 
-	if (swim->wait_ack_tick.at != ack_timeout && ack_timeout > 0)
-		swim_ev_timer_set(&swim->wait_ack_tick, ack_timeout, 0);
+	if (swim->wait_ack_tick.repeat != ack_timeout && ack_timeout > 0)
+		swim_ev_timer_set(&swim->wait_ack_tick, 0, ack_timeout);
 
 	if (new_self != NULL) {
 		swim->self->status = MEMBER_LEFT;
@@ -1763,12 +1763,6 @@ swim_set_codec(struct swim *swim, enum crypto_algo algo, const char *key)
 	return swim_scheduler_set_codec(&swim->scheduler, algo, key);
 }
 
-double
-swim_ack_timeout(const struct swim *swim)
-{
-	return swim->wait_ack_tick.at;
-}
-
 bool
 swim_is_configured(const struct swim *swim)
 {
diff --git a/src/lib/swim/swim.h b/src/lib/swim/swim.h
index 5abbe8c33..653e45be7 100644
--- a/src/lib/swim/swim.h
+++ b/src/lib/swim/swim.h
@@ -101,10 +101,6 @@ swim_cfg(struct swim *swim, const char *uri, double heartbeat_rate,
 	 double ack_timeout, enum swim_gc_mode gc_mode,
 	 const struct tt_uuid *uuid);
 
-/** SWIM's ACK timeout, previously set via @sa swim_cfg. */
-double
-swim_ack_timeout(const struct swim *swim);
-
 /** Set payload to disseminate over the cluster. */
 int
 swim_set_payload(struct swim *swim, const char *payload, uint16_t payload_size);
diff --git a/src/lib/swim/swim_ev.c b/src/lib/swim/swim_ev.c
index f7c464426..49c8c273b 100644
--- a/src/lib/swim/swim_ev.c
+++ b/src/lib/swim/swim_ev.c
@@ -44,6 +44,12 @@ swim_ev_timer_start(struct ev_loop *loop, struct ev_timer *watcher)
 	ev_timer_start(loop, watcher);
 }
 
+void
+swim_ev_timer_again(struct ev_loop *loop, struct ev_timer *watcher)
+{
+	ev_timer_again(loop, watcher);
+}
+
 void
 swim_ev_timer_stop(struct ev_loop *loop, struct ev_timer *watcher)
 {
diff --git a/src/lib/swim/swim_ev.h b/src/lib/swim/swim_ev.h
index 34394ef47..0fe550523 100644
--- a/src/lib/swim/swim_ev.h
+++ b/src/lib/swim/swim_ev.h
@@ -46,6 +46,9 @@ swim_time(void);
 void
 swim_ev_timer_start(struct ev_loop *loop, struct ev_timer *watcher);
 
+void
+swim_ev_timer_again(struct ev_loop *loop, struct ev_timer *watcher);
+
 void
 swim_ev_timer_stop(struct ev_loop *loop, struct ev_timer *watcher);
 
diff --git a/test/unit/swim_test_ev.c b/test/unit/swim_test_ev.c
index 135f20107..16fd87c78 100644
--- a/test/unit/swim_test_ev.c
+++ b/test/unit/swim_test_ev.c
@@ -184,6 +184,7 @@ swim_timer_event_process(struct swim_event *e, struct ev_loop *loop)
 	assert(e->type == SWIM_EVENT_TIMER);
 	struct ev_watcher *w = ((struct swim_timer_event *) e)->watcher;
 	swim_timer_event_delete(e);
+	((struct ev_timer *) w)->at = 0;
 	ev_invoke(loop, w, EV_TIMER);
 }
 
@@ -265,6 +266,16 @@ swim_ev_timer_start(struct ev_loop *loop, struct ev_timer *base)
 	swim_timer_event_new((struct ev_watcher *) base, base->at);
 }
 
+void
+swim_ev_timer_again(struct ev_loop *loop, struct ev_timer *base)
+{
+	(void) loop;
+	if (swim_event_by_ev((struct ev_watcher *) base) != NULL)
+		return;
+	/* Create the periodic watcher and one event. */
+	swim_timer_event_new((struct ev_watcher *) base, base->repeat);
+}
+
 /** Time stop cancels the event if the timer is active. */
 void
 swim_ev_timer_stop(struct ev_loop *loop, struct ev_timer *base)
-- 
2.20.1 (Apple Git-117)

  reply	other threads:[~2019-04-30 22:31 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-04-30 22:31 [tarantool-patches] [PATCH 0/5] swim lua preparation Vladislav Shpilevoy
2019-04-30 22:31 ` Vladislav Shpilevoy [this message]
2019-05-01  5:09   ` [tarantool-patches] Re: [PATCH 1/5] swim: do not use ev_timer_start Konstantin Osipov
2019-04-30 22:31 ` [tarantool-patches] [PATCH 2/5] swim: introduce member reference API Vladislav Shpilevoy
2019-05-01  5:15   ` [tarantool-patches] " Konstantin Osipov
2019-05-02 15:10     ` Vladislav Shpilevoy
2019-05-02 15:46       ` Konstantin Osipov
2019-05-02 17:32         ` Vladislav Shpilevoy
2019-04-30 22:31 ` [tarantool-patches] [PATCH 3/5] sio: return 'no host' flag from sio_uri_to_addr() Vladislav Shpilevoy
2019-05-01  5:18   ` [tarantool-patches] " Konstantin Osipov
2019-04-30 22:31 ` [tarantool-patches] [PATCH 4/5] swim: allow to omit host in URI Vladislav Shpilevoy
2019-05-01  5:20   ` [tarantool-patches] " Konstantin Osipov
2019-05-02 15:10     ` Vladislav Shpilevoy
2019-04-30 22:31 ` [tarantool-patches] [PATCH 5/5] swim: explicitly stop old ev_io input/output on rebind Vladislav Shpilevoy
2019-05-01  5:21   ` [tarantool-patches] " Konstantin Osipov
2019-05-02 17:32 ` [tarantool-patches] Re: [PATCH 0/5] swim lua preparation Vladislav Shpilevoy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=55eb3963102ddf0f83e0358d7041d6e2fabd729c.1556663421.git.v.shpilevoy@tarantool.org \
    --to=v.shpilevoy@tarantool.org \
    --cc=kostja@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --subject='Re: [tarantool-patches] [PATCH 1/5] swim: do not use ev_timer_start' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox