[SCM] Samba Shared Repository - branch master updated

Martin Schwenke martins at samba.org
Fri Jan 6 11:28:03 UTC 2017


The branch, master has been updated
       via  4635c22 ctdb-tests: Do not attempt to unregister the join handler multiple times
       via  1dc1689 ctdb-tests: Add tests for generic socket I/O
       via  e3440d2 ctdb-common: Fix a bug in packet reading code for generic socket I/O
       via  ebc60b2 ctdb-tests: Add another test for sock_daemon
       via  d937055 ctdb-common: Simplify async computation for sock_socket_write_send/recv
      from  03373f6 VERSION: Bump version up to 4.7.0pre1...

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 4635c22411a7864dd70703f854ec9844816e0294
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Thu Jan 5 15:05:56 2017 +1100

    ctdb-tests: Do not attempt to unregister the join handler multiple times
    
    MSG_ID_SYNC is broadcast to each node when a MSG_ID_JOIN has been
    received from all nodes.  After MSG_ID_SYNC is successfully broadcast,
    the join handler is unregistered.  However, if another MSG_ID_JOIN is
    received before the join handler is unregistered then MSG_ID_SYNC is
    re-broadcast.  This results in multiple attempts to unregister the
    join handler.
    
    Once all MSG_ID_JOIN messages are received, unregister the join handler
    to ignore any extra MSG_ID_JOIN messages.  Also, make sure that while
    join handler is being unregistered, MSG_ID_JOIN messages are ignored.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12500
    
    Identified-by: Martin Schwenke <martin at meltin.net>
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    Reviewed-by: Martin Schwenke <martin at meltin.net>
    
    Autobuild-User(master): Martin Schwenke <martins at samba.org>
    Autobuild-Date(master): Fri Jan  6 12:27:23 CET 2017 on sn-devel-144

commit 1dc1689e7402f6f90af3ddd4c7d33d140892ff2a
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Thu Jan 5 00:48:32 2017 +1100

    ctdb-tests: Add tests for generic socket I/O
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12500
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    Reviewed-by: Martin Schwenke <martin at meltin.net>

commit e3440d2bbc0e8f2cb09c94a1d77a60524017cfa0
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Wed Jan 4 17:46:54 2017 +1100

    ctdb-common: Fix a bug in packet reading code for generic socket I/O
    
    queue->offset currently points to the end of available data.  However,
    after processing one packet the beginning of the next packet is not
    marked explicitly and caused the same packet to be processed again.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12500
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    Reviewed-by: Martin Schwenke <martin at meltin.net>

commit ebc60b2accbbb1586351d246d0bcc6a2dd528911
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Thu Jan 5 00:47:11 2017 +1100

    ctdb-tests: Add another test for sock_daemon
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12500
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    Reviewed-by: Martin Schwenke <martin at meltin.net>

commit d9370550a7f72ff02c296ef61bd7f86645167378
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Wed Jan 4 16:20:17 2017 +1100

    ctdb-common: Simplify async computation for sock_socket_write_send/recv
    
    This is now just a wrapper around comm_write_send/recv.  This avoids the
    extra tevent_req and fixes a bug in the termination of sock_socket_write
    computation.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12500
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    Reviewed-by: Martin Schwenke <martin at meltin.net>

-----------------------------------------------------------------------

Summary of changes:
 ctdb/common/sock_daemon.c                |  56 +-----
 ctdb/common/sock_io.c                    |  28 +--
 ctdb/tests/cunit/sock_daemon_test_001.sh |  23 ++-
 ctdb/tests/cunit/sock_io_test_001.sh     |   9 +
 ctdb/tests/src/cluster_wait.c            |  40 +++--
 ctdb/tests/src/sock_daemon_test.c        | 275 +++++++++++++++++++++++++++++-
 ctdb/tests/src/sock_io_test.c            | 283 +++++++++++++++++++++++++++++++
 ctdb/wscript                             |   1 +
 8 files changed, 628 insertions(+), 87 deletions(-)
 create mode 100755 ctdb/tests/cunit/sock_io_test_001.sh
 create mode 100644 ctdb/tests/src/sock_io_test.c


Changeset truncated at 500 lines:

diff --git a/ctdb/common/sock_daemon.c b/ctdb/common/sock_daemon.c
index dc5dba0..ca4086d 100644
--- a/ctdb/common/sock_daemon.c
+++ b/ctdb/common/sock_daemon.c
@@ -420,77 +420,33 @@ static bool sock_socket_start_recv(struct tevent_req *req, int *perr)
  * Send message to a client
  */
 
-struct sock_socket_write_state {
-	int status;
-};
-
-static void sock_socket_write_done(struct tevent_req *subreq);
-
 struct tevent_req *sock_socket_write_send(TALLOC_CTX *mem_ctx,
 					 struct tevent_context *ev,
 					 struct sock_client_context *client_ctx,
 					 uint8_t *buf, size_t buflen)
 {
-	struct tevent_req *req, *subreq;
-	struct sock_socket_write_state *state;
-
-	req = tevent_req_create(mem_ctx, &state,
-				struct sock_socket_write_state);
-	if (req == NULL) {
-		return NULL;
-	}
+	struct tevent_req *req;
 
-	subreq = comm_write_send(state, ev, client_ctx->comm, buf, buflen);
-	if (tevent_req_nomem(subreq, req)) {
-		return tevent_req_post(req, ev);
-	}
-	tevent_req_set_callback(subreq, sock_socket_write_done, req);
+	req = comm_write_send(mem_ctx, ev, client_ctx->comm, buf, buflen);
 
 	return req;
 }
 
-static void sock_socket_write_done(struct tevent_req *subreq)
+bool sock_socket_write_recv(struct tevent_req *req, int *perr)
 {
-	struct tevent_req *req = tevent_req_callback_data(
-		subreq, struct tevent_req);
-	struct sock_socket_write_state *state = tevent_req_data(
-		req, struct sock_socket_write_state);
 	int ret;
 	bool status;
 
-	status = comm_write_recv(subreq, &ret);
-	TALLOC_FREE(subreq);
+	status = comm_write_recv(req, &ret);
 	if (! status) {
-		state->status = ret;
-		return;
-	}
-}
-
-bool sock_socket_write_recv(struct tevent_req *req, int *perr)
-{
-	struct sock_socket_write_state *state = tevent_req_data(
-		req, struct sock_socket_write_state);
-	int ret;
-
-	if (tevent_req_is_unix_error(req, &ret)) {
 		if (perr != NULL) {
 			*perr = ret;
 		}
-		return false;
 	}
 
-	if (state->status != 0) {
-		if (perr != NULL) {
-			*perr = state->status;
-		}
-		return false;
-	}
-
-	if (perr != NULL) {
-		*perr = 0;
-	}
-	return true;
+	return status;
 }
+
 /*
  * Socket daemon
  */
diff --git a/ctdb/common/sock_io.c b/ctdb/common/sock_io.c
index b3581fc..7431eec 100644
--- a/ctdb/common/sock_io.c
+++ b/ctdb/common/sock_io.c
@@ -76,7 +76,7 @@ struct sock_queue {
 	struct tevent_queue *queue;
 	struct tevent_fd *fde;
 	uint8_t *buf;
-	size_t buflen, offset;
+	size_t buflen, begin, end;
 };
 
 static bool sock_queue_set_fd(struct sock_queue *queue, int fd);
@@ -181,20 +181,20 @@ static void sock_queue_handler(struct tevent_context *ev,
 		goto fail;
 	}
 
-	if (num_ready > queue->buflen - queue->offset) {
+	if (num_ready > queue->buflen - queue->end) {
 		queue->buf = talloc_realloc_size(queue, queue->buf,
-						 queue->offset + num_ready);
+						 queue->end + num_ready);
 		if (queue->buf == NULL) {
 			goto fail;
 		}
-		queue->buflen = queue->offset + num_ready;
+		queue->buflen = queue->end + num_ready;
 	}
 
-	nread = sys_read(queue->fd, queue->buf + queue->offset, num_ready);
+	nread = sys_read(queue->fd, queue->buf + queue->end, num_ready);
 	if (nread < 0) {
 		goto fail;
 	}
-	queue->offset += nread;
+	queue->end += nread;
 
 	sock_queue_process(queue);
 	return;
@@ -207,33 +207,35 @@ static void sock_queue_process(struct sock_queue *queue)
 {
 	uint32_t pkt_size;
 
-	if (queue->offset < sizeof(uint32_t)) {
+	if ((queue->end - queue->begin) < sizeof(uint32_t)) {
 		/* not enough data */
 		return;
 	}
 
-	pkt_size = *(uint32_t *)queue->buf;
+	pkt_size = *(uint32_t *)(queue->buf + queue->begin);
 	if (pkt_size == 0) {
 		D_ERR("Invalid packet of length 0\n");
 		queue->callback(NULL, 0, queue->private_data);
 	}
 
-	if (queue->offset < pkt_size) {
+	if ((queue->end - queue->begin) < pkt_size) {
 		/* not enough data */
 		return;
 	}
 
-	queue->callback(queue->buf, pkt_size, queue->private_data);
-	queue->offset += pkt_size;
+	queue->callback(queue->buf + queue->begin, pkt_size,
+			queue->private_data);
+	queue->begin += pkt_size;
 
-	if (queue->offset < queue->buflen) {
+	if (queue->begin < queue->end) {
 		/* more data to be processed */
 		tevent_schedule_immediate(queue->im, queue->ev,
 					  sock_queue_process_event, queue);
 	} else {
 		TALLOC_FREE(queue->buf);
 		queue->buflen = 0;
-		queue->offset = 0;
+		queue->begin = 0;
+		queue->end = 0;
 	}
 }
 
diff --git a/ctdb/tests/cunit/sock_daemon_test_001.sh b/ctdb/tests/cunit/sock_daemon_test_001.sh
index 9555cdd..036b6ac 100755
--- a/ctdb/tests/cunit/sock_daemon_test_001.sh
+++ b/ctdb/tests/cunit/sock_daemon_test_001.sh
@@ -24,21 +24,42 @@ result_filter ()
 
 ok <<EOF
 test1[PID]: listening on $sockpath
+EOF
+unit_test sock_daemon_test "$pidfile" "$sockpath" 1
+
+ok <<EOF
 test2[PID]: listening on $sockpath
 test2[PID]: daemon started, pid=PID
 test2[PID]: Received signal 1
 test2[PID]: Received signal 10
 test2[PID]: Received signal 15
 test2[PID]: Shutting down
+EOF
+unit_test sock_daemon_test "$pidfile" "$sockpath" 2
+
+ok <<EOF
 test3[PID]: listening on $sockpath
 test3[PID]: daemon started, pid=PID
 test3[PID]: PID PID gone away, exiting
 test3[PID]: Shutting down
+EOF
+unit_test sock_daemon_test "$pidfile" "$sockpath" 3
+
+ok <<EOF
 test4[PID]: daemon started, pid=PID
+EOF
+unit_test sock_daemon_test "$pidfile" "$sockpath" 4
+
+ok <<EOF
 test5[PID]: listening on $sockpath
 test5[PID]: daemon started, pid=PID
 test5[PID]: Received signal 15
 test5[PID]: Shutting down
 EOF
+unit_test sock_daemon_test "$pidfile" "$sockpath" 5
 
-unit_test sock_daemon_test "$pidfile" "$sockpath"
+ok <<EOF
+test6[PID]: listening on $sockpath
+test6[PID]: daemon started, pid=PID
+EOF
+unit_test sock_daemon_test "$pidfile" "$sockpath" 6
diff --git a/ctdb/tests/cunit/sock_io_test_001.sh b/ctdb/tests/cunit/sock_io_test_001.sh
new file mode 100755
index 0000000..1ead2f3
--- /dev/null
+++ b/ctdb/tests/cunit/sock_io_test_001.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+. "${TEST_SCRIPTS_DIR}/unit.sh"
+
+sockpath="${TEST_VAR_DIR}/sock_daemon_test.sock.$$"
+
+ok_null
+
+unit_test sock_io_test "$sockpath"
diff --git a/ctdb/tests/src/cluster_wait.c b/ctdb/tests/src/cluster_wait.c
index ddc3e02..1405738 100644
--- a/ctdb/tests/src/cluster_wait.c
+++ b/ctdb/tests/src/cluster_wait.c
@@ -36,6 +36,7 @@ struct cluster_wait_state {
 	struct ctdb_client_context *client;
 	int num_nodes;
 	bool *ready;
+	bool join_done;
 };
 
 static void cluster_wait_join_registered(struct tevent_req *subreq);
@@ -44,8 +45,8 @@ static void cluster_wait_join(struct tevent_req *subreq);
 static void cluster_wait_join_sent(struct tevent_req *subreq);
 static void cluster_wait_join_handler(uint64_t srvid, TDB_DATA data,
 				      void *private_data);
-static void cluster_wait_sync_sent(struct tevent_req *subreq);
 static void cluster_wait_join_unregistered(struct tevent_req *subreq);
+static void cluster_wait_sync_sent(struct tevent_req *subreq);
 static void cluster_wait_sync_handler(uint64_t srvid, TDB_DATA data,
 				      void *private_data);
 static void cluster_wait_sync_unregistered(struct tevent_req *subreq);
@@ -67,6 +68,8 @@ struct tevent_req *cluster_wait_send(TALLOC_CTX *mem_ctx,
 	state->client = client;
 	state->num_nodes = num_nodes;
 
+	state->join_done = false;
+
 	if (ctdb_client_pnn(client) == 0) {
 		state->ready = talloc_zero_array(state, bool, num_nodes);
 		if (tevent_req_nomem(state->ready, req)) {
@@ -201,7 +204,6 @@ static void cluster_wait_join_handler(uint64_t srvid, TDB_DATA data,
 		private_data, struct tevent_req);
 	struct cluster_wait_state *state = tevent_req_data(
 		req, struct cluster_wait_state);
-	struct ctdb_req_message msg;
 	struct tevent_req *subreq;
 	uint32_t pnn;
 	int i;
@@ -228,50 +230,56 @@ static void cluster_wait_join_handler(uint64_t srvid, TDB_DATA data,
 		}
 	}
 
-	msg.srvid = MSG_ID_SYNC;
-	msg.data.data = tdb_null;
+	if (state->join_done) {
+		return;
+	}
 
-	subreq = ctdb_client_message_send(state, state->ev, state->client,
-					  CTDB_BROADCAST_ALL, &msg);
+	state->join_done = true;
+	subreq = ctdb_client_remove_message_handler_send(
+					state, state->ev, state->client,
+					MSG_ID_JOIN, req);
 	if (tevent_req_nomem(subreq, req)) {
 		return;
 	}
-	tevent_req_set_callback(subreq, cluster_wait_sync_sent, req);
+	tevent_req_set_callback(subreq, cluster_wait_join_unregistered, req);
 }
 
-static void cluster_wait_sync_sent(struct tevent_req *subreq)
+static void cluster_wait_join_unregistered(struct tevent_req *subreq)
 {
 	struct tevent_req *req = tevent_req_callback_data(
 		subreq, struct tevent_req);
 	struct cluster_wait_state *state = tevent_req_data(
 		req, struct cluster_wait_state);
+	struct ctdb_req_message msg;
 	bool status;
 	int ret;
 
-	status = ctdb_client_message_recv(subreq, &ret);
-	TALLOC_FREE(subreq);
+	status = ctdb_client_remove_message_handler_recv(subreq, &ret);
 	if (! status) {
 		tevent_req_error(req, ret);
 		return;
 	}
 
-	subreq = ctdb_client_remove_message_handler_send(
-					state, state->ev, state->client,
-					MSG_ID_JOIN, req);
+	msg.srvid = MSG_ID_SYNC;
+	msg.data.data = tdb_null;
+
+	subreq = ctdb_client_message_send(state, state->ev, state->client,
+					  CTDB_BROADCAST_ALL, &msg);
 	if (tevent_req_nomem(subreq, req)) {
 		return;
 	}
-	tevent_req_set_callback(subreq, cluster_wait_join_unregistered, req);
+	tevent_req_set_callback(subreq, cluster_wait_sync_sent, req);
 }
 
-static void cluster_wait_join_unregistered(struct tevent_req *subreq)
+static void cluster_wait_sync_sent(struct tevent_req *subreq)
 {
 	struct tevent_req *req = tevent_req_callback_data(
 		subreq, struct tevent_req);
 	bool status;
 	int ret;
 
-	status = ctdb_client_remove_message_handler_recv(subreq, &ret);
+	status = ctdb_client_message_recv(subreq, &ret);
+	TALLOC_FREE(subreq);
 	if (! status) {
 		tevent_req_error(req, ret);
 		return;
diff --git a/ctdb/tests/src/sock_daemon_test.c b/ctdb/tests/src/sock_daemon_test.c
index 14ddefd..4a085c0 100644
--- a/ctdb/tests/src/sock_daemon_test.c
+++ b/ctdb/tests/src/sock_daemon_test.c
@@ -606,27 +606,288 @@ static void test5(TALLOC_CTX *mem_ctx, const char *pidfile,
 	assert(ret == 0);
 }
 
+struct test6_pkt {
+	uint32_t len;
+	uint32_t data;
+};
+
+struct test6_client_state {
+	bool done;
+};
+
+static void test6_client_callback(uint8_t *buf, size_t buflen,
+				  void *private_data)
+{
+	struct test6_client_state *state =
+		(struct test6_client_state *)private_data;
+	struct test6_pkt *pkt;
+
+	assert(buflen == sizeof(struct test6_pkt));
+	pkt = (struct test6_pkt *)buf;
+	assert(pkt->len == sizeof(struct test6_pkt));
+	assert(pkt->data == 0xffeeddcc);
+
+	state->done = true;
+}
+
+static void test6_client(const char *sockpath)
+{
+	struct tevent_context *ev;
+	struct test6_client_state state;
+	struct sock_queue *queue;
+	struct test6_pkt pkt;
+	int conn, ret;
+
+	ev = tevent_context_init(NULL);
+	assert(ev != NULL);
+
+	conn = sock_connect(sockpath);
+	assert(conn != -1);
+
+	state.done = false;
+
+	queue = sock_queue_setup(ev, ev, conn,
+				 test6_client_callback, &state);
+	assert(queue != NULL);
+
+	pkt.len = 8;
+	pkt.data = 0xaabbccdd;
+
+	ret = sock_queue_write(queue, (uint8_t *)&pkt,
+			       sizeof(struct test6_pkt));
+	assert(ret == 0);
+
+	while (! state.done) {
+		tevent_loop_once(ev);
+	}
+
+	talloc_free(ev);
+}
+
+struct test6_server_state {
+	struct sock_daemon_context *sockd;
+	int done;
+};
+
+struct test6_read_state {
+	struct test6_server_state *server_state;
+	struct test6_pkt reply;
+};
+
+static void test6_read_done(struct tevent_req *subreq);
+
+static struct tevent_req *test6_read_send(TALLOC_CTX *mem_ctx,
+					  struct tevent_context *ev,
+					  struct sock_client_context *client,
+					  uint8_t *buf, size_t buflen,
+					  void *private_data)
+{
+	struct test6_server_state *server_state =
+		(struct test6_server_state *)private_data;
+	struct tevent_req *req, *subreq;
+	struct test6_read_state *state;
+	struct test6_pkt *pkt;
+
+	req = tevent_req_create(mem_ctx, &state, struct test6_read_state);
+	assert(req != NULL);
+
+	state->server_state = server_state;
+
+	assert(buflen == sizeof(struct test6_pkt));
+
+	pkt = (struct test6_pkt *)buf;
+	assert(pkt->data == 0xaabbccdd);
+
+	state->reply.len = sizeof(struct test6_pkt);
+	state->reply.data = 0xffeeddcc;
+
+	subreq = sock_socket_write_send(state, ev, client,
+					(uint8_t *)&state->reply,
+					state->reply.len);
+	assert(subreq != NULL);
+
+	tevent_req_set_callback(subreq, test6_read_done, req);
+
+	return req;
+}
+
+static void test6_read_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct test6_read_state *state = tevent_req_data(
+		req, struct test6_read_state);
+	int ret;
+	bool status;
+
+	status = sock_socket_write_recv(subreq, &ret);
+	TALLOC_FREE(subreq);
+	if (! status) {
+		tevent_req_error(req, ret);
+		return;
+	}
+
+	state->server_state->done = 1;
+	tevent_req_done(req);
+}
+
+static bool test6_read_recv(struct tevent_req *req, int *perr)
+{
+	int ret;
+
+	if (tevent_req_is_unix_error(req, &ret)) {
+		if (perr != NULL) {
+			*perr = ret;
+		}
+		return false;
+	}
+
+	return true;
+}
+
+static struct sock_socket_funcs test6_client_funcs = {
+	.read_send = test6_read_send,
+	.read_recv = test6_read_recv,
+};
+
+static void test6_startup(void *private_data)
+{
+	int fd = *(int *)private_data;
+	int ret = 1;
+	ssize_t nwritten;


-- 
Samba Shared Repository



More information about the samba-cvs mailing list