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 3/5] test: process IO swim test events before protocol's ones
Date: Tue,  9 Apr 2019 21:12:10 +0300	[thread overview]
Message-ID: <79b08bc60bcebefba3333dc2874359769e6586c2.1554833062.git.v.shpilevoy@tarantool.org> (raw)
In-Reply-To: <cover.1554833062.git.v.shpilevoy@tarantool.org>
In-Reply-To: <cover.1554833062.git.v.shpilevoy@tarantool.org>

Before that patch the swim test event loop worked like this: pop
a new event, set the global watch to its deadline, process the
event, repeat until the deadlines are the same. These events
usually generate IO events, which are processed next. But after
swim_quit() will be introduced, it is possible to insert new IO
events before protocol's events like round steps and ack checks.

Because of that it would be impossible to process new IO events
only, with timeout = 0, or with timeout > 0, but without changing
the global clock.

For example, a typical test would try to call swim_quit() on a
swim instance, and expect that it has sent all the quit messages
without delays immediately. But before this patch it would be
necessary to run at least one swim round to get to the IO
processing.

The patch splits protocol's events and IO events processing logic
into two functions and calls them explicitly in
swim_wait_timeout() - the main function to check something in the
swim tests.

Part of #3234
---
 test/unit/swim_test_ev.c        | 27 +--------------------------
 test/unit/swim_test_ev.h        |  2 +-
 test/unit/swim_test_transport.c | 32 ++++++++++++++++++++++++++++++--
 test/unit/swim_test_transport.h |  9 +++++----
 test/unit/swim_test_utils.c     | 16 +++++++++++++++-
 5 files changed, 52 insertions(+), 34 deletions(-)

diff --git a/test/unit/swim_test_ev.c b/test/unit/swim_test_ev.c
index 1c4ba8612..135f20107 100644
--- a/test/unit/swim_test_ev.c
+++ b/test/unit/swim_test_ev.c
@@ -281,7 +281,7 @@ swim_ev_timer_stop(struct ev_loop *loop, struct ev_timer *base)
 
 /** Process all the events with the next nearest deadline. */
 void
-swim_do_loop_step(struct ev_loop *loop)
+swim_test_ev_do_loop_step(struct ev_loop *loop)
 {
 	struct swim_event *next_e, *e = event_heap_top(&event_heap);
 	if (e != NULL) {
@@ -296,31 +296,6 @@ swim_do_loop_step(struct ev_loop *loop)
 			e = next_e;
 		} while (e != NULL && e->deadline == watch);
 	}
-	/*
-	 * After events are processed, it is possible that some of
-	 * them generated IO events. Process them too.
-	 */
-	do {
-		swim_transport_do_loop_step(loop);
-		/*
-		 * Just a single loop + invoke is not enough. At
-		 * least two are necessary.
-		 *
-		 * First loop does nothing since send queues are
-		 * empty. First invoke fills send queues.
-		 *
-		 * Second loop moves messages from send to recv
-		 * queues. Second invoke processes messages in
-		 * recv queues.
-		 *
-		 * With indirect messages even 2 cycles is not
-		 * enough - processing of one received message can
-		 * add a new message into another send queue.
-		 */
-		if (ev_pending_count(loop) == 0)
-			break;
-		ev_invoke_pending(loop);
-	} while (true);
 }
 
 void
diff --git a/test/unit/swim_test_ev.h b/test/unit/swim_test_ev.h
index 6a0002c2f..bc925a859 100644
--- a/test/unit/swim_test_ev.h
+++ b/test/unit/swim_test_ev.h
@@ -98,7 +98,7 @@ swim_ev_set_brk(double delay);
 
 /** Play one step of event loop, process generated events. */
 void
-swim_do_loop_step(struct ev_loop *loop);
+swim_test_ev_do_loop_step(struct ev_loop *loop);
 
 /** Destroy pending events, reset global watch. */
 void
diff --git a/test/unit/swim_test_transport.c b/test/unit/swim_test_transport.c
index f30000135..78fda587a 100644
--- a/test/unit/swim_test_transport.c
+++ b/test/unit/swim_test_transport.c
@@ -304,8 +304,12 @@ swim_fd_send_packet(struct swim_fd *fd)
 		swim_test_packet_delete(p);
 }
 
-void
-swim_transport_do_loop_step(struct ev_loop *loop)
+/**
+ * Feed EV_WRITE/READ events to the descriptors having something
+ * to send/recv.
+ */
+static inline void
+swim_test_transport_feed_events(struct ev_loop *loop)
 {
 	struct swim_fd *fd;
 	/*
@@ -322,3 +326,27 @@ swim_transport_do_loop_step(struct ev_loop *loop)
 			ev_feed_fd_event(loop, fd->evfd, EV_READ);
 	}
 }
+
+void
+swim_test_transport_do_loop_step(struct ev_loop *loop)
+{
+	do {
+		ev_invoke_pending(loop);
+		swim_test_transport_feed_events(loop);
+		/*
+		 * Just a single loop + invoke is not enough. At
+		 * least two are necessary.
+		 *
+		 * First loop does nothing since send queues are
+		 * empty. First invoke fills send queues.
+		 *
+		 * Second loop moves messages from send to recv
+		 * queues. Second invoke processes messages in
+		 * recv queues.
+		 *
+		 * With indirect messages even 2 cycles is not
+		 * enough - processing of one received message can
+		 * add a new message into another send queue.
+		 */
+	} while (ev_pending_count(loop) > 0);
+}
diff --git a/test/unit/swim_test_transport.h b/test/unit/swim_test_transport.h
index d291abe91..9248f0e98 100644
--- a/test/unit/swim_test_transport.h
+++ b/test/unit/swim_test_transport.h
@@ -41,12 +41,13 @@ struct ev_loop;
  */
 
 /**
- * Feed EV_WRITE event to all opened descriptors, and EV_READ to
- * ones, who have not empty recv queue. Move packets from send to
- * recv queues. No callbacks is invoked. Only events are fed.
+ * Until there are no new IO events, feed EV_WRITE event to all
+ * opened descriptors; EV_READ to ones, who have not empty recv
+ * queue; invoke callbacks to process the events. Move packets
+ * from send to recv queues.
  */
 void
-swim_transport_do_loop_step(struct ev_loop *loop);
+swim_test_transport_do_loop_step(struct ev_loop *loop);
 
 /**
  * Block a file descriptor so as it can not receive nor send any
diff --git a/test/unit/swim_test_utils.c b/test/unit/swim_test_utils.c
index a42e50cae..8964e345c 100644
--- a/test/unit/swim_test_utils.c
+++ b/test/unit/swim_test_utils.c
@@ -293,10 +293,24 @@ swim_wait_timeout(double timeout, struct swim_cluster *cluster,
 {
 	swim_ev_set_brk(timeout);
 	double deadline = swim_time() + timeout;
+	struct ev_loop *loop = loop();
+	/*
+	 * There can be pending out of bound IO events, affecting
+	 * the result. For example, 'quit' messages, which are
+	 * send immediately without preliminary timeouts or
+	 * whatsoever.
+	 */
+	swim_test_transport_do_loop_step(loop);
 	while (! check(cluster, data)) {
 		if (swim_time() >= deadline)
 			return -1;
-		swim_do_loop_step(loop());
+		swim_test_ev_do_loop_step(loop);
+		/*
+		 * After events are processed, it is possible that
+		 * some of them generated IO events. Process them
+		 * too.
+		 */
+		swim_test_transport_do_loop_step(loop);
 	}
 	return 0;
 }
-- 
2.17.2 (Apple Git-113)

  parent reply	other threads:[~2019-04-09 18:12 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-04-09 18:12 [tarantool-patches] [PATCH 0/5] swim member 'left' status Vladislav Shpilevoy
2019-04-09 18:12 ` [tarantool-patches] [PATCH 1/5] test: allow to remove swim nodes from the cluster Vladislav Shpilevoy
2019-04-10  7:15   ` [tarantool-patches] " Konstantin Osipov
2019-04-09 18:12 ` [tarantool-patches] [PATCH 2/5] test: on close of swim fake fd send its packets, not drop Vladislav Shpilevoy
2019-04-10  7:16   ` [tarantool-patches] " Konstantin Osipov
2019-04-09 18:12 ` Vladislav Shpilevoy [this message]
2019-04-10  7:17   ` [tarantool-patches] Re: [PATCH 3/5] test: process IO swim test events before protocol's ones Konstantin Osipov
2019-04-09 18:12 ` [tarantool-patches] [PATCH 4/5] swim: introduce quit message Vladislav Shpilevoy
2019-04-10  7:21   ` [tarantool-patches] " Konstantin Osipov
2019-04-09 18:12 ` [tarantool-patches] [PATCH 5/5] swim: make UUID update smoother and faster Vladislav Shpilevoy
2019-04-10  7:22   ` [tarantool-patches] " Konstantin Osipov
2019-04-10 10:29 ` [tarantool-patches] Re: [PATCH 0/5] swim member 'left' status 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=79b08bc60bcebefba3333dc2874359769e6586c2.1554833062.git.v.shpilevoy@tarantool.org \
    --to=v.shpilevoy@tarantool.org \
    --cc=kostja@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --subject='Re: [tarantool-patches] [PATCH 3/5] test: process IO swim test events before protocol'\''s ones' \
    /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