[tarantool-patches] [PATCH 1/5] swim: do not use ev_timer_start
Vladislav Shpilevoy
v.shpilevoy at tarantool.org
Wed May 1 01:31:23 MSK 2019
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)
More information about the Tarantool-patches
mailing list