summaryrefslogtreecommitdiff
path: root/ctdb
diff options
context:
space:
mode:
authorAmitay Isaacs <amitay@gmail.com>2017-11-17 12:36:29 +1100
committerMartin Schwenke <martins@samba.org>2017-11-21 05:03:17 +0100
commit7558592d15fa4911fa8d2061aa56e2b151f516a2 (patch)
treecf5a10cfdd3c538a68fad70d577fe510f9fbbdd9 /ctdb
parentba3e9e6eae62af0ee991945206e0ef2b3dba8acf (diff)
downloadsamba-7558592d15fa4911fa8d2061aa56e2b151f516a2.tar.gz
ctdb-common: Add async version of startup in sock_daemon
Signed-off-by: Amitay Isaacs <amitay@gmail.com> Reviewed-by: Martin Schwenke <martin@meltin.net>
Diffstat (limited to 'ctdb')
-rw-r--r--ctdb/common/sock_daemon.c40
-rw-r--r--ctdb/common/sock_daemon.h8
-rwxr-xr-xctdb/tests/cunit/sock_daemon_test_001.sh2
-rw-r--r--ctdb/tests/src/sock_daemon_test.c45
4 files changed, 95 insertions, 0 deletions
diff --git a/ctdb/common/sock_daemon.c b/ctdb/common/sock_daemon.c
index 0ef01666883..6b05e2462f9 100644
--- a/ctdb/common/sock_daemon.c
+++ b/ctdb/common/sock_daemon.c
@@ -527,6 +527,7 @@ struct sock_daemon_run_state {
};
static void sock_daemon_run_started(struct tevent_req *subreq);
+static void sock_daemon_run_startup_done(struct tevent_req *subreq);
static void sock_daemon_run_signal_handler(struct tevent_context *ev,
struct tevent_signal *se,
int signum, int count, void *siginfo,
@@ -634,6 +635,18 @@ static void sock_daemon_run_started(struct tevent_req *subreq)
D_NOTICE("daemon started, pid=%u\n", getpid());
+ if (sockd->funcs != NULL && sockd->funcs->startup_send != NULL &&
+ sockd->funcs->startup_recv != NULL) {
+ subreq = sockd->funcs->startup_send(state, state->ev,
+ sockd->private_data);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, sock_daemon_run_startup_done,
+ req);
+ return;
+ }
+
if (sockd->funcs != NULL && sockd->funcs->startup != NULL) {
int ret;
@@ -654,6 +667,33 @@ static void sock_daemon_run_started(struct tevent_req *subreq)
sock_daemon_run_wait(req);
}
+static void sock_daemon_run_startup_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct sock_daemon_run_state *state = tevent_req_data(
+ req, struct sock_daemon_run_state);
+ struct sock_daemon_context *sockd = state->sockd;
+ int ret;
+ bool status;
+
+ status = sockd->funcs->startup_recv(subreq, &ret);
+ TALLOC_FREE(subreq);
+ if (! status) {
+ D_ERR("startup failed, ret=%d\n", ret);
+ tevent_req_error(req, EIO);
+ return;
+ }
+
+ D_NOTICE("startup completed succesfully\n");
+
+ status = sock_daemon_run_socket_listen(req);
+ if (! status) {
+ return;
+ }
+ sock_daemon_run_wait(req);
+}
+
static void sock_daemon_run_signal_handler(struct tevent_context *ev,
struct tevent_signal *se,
int signum, int count, void *siginfo,
diff --git a/ctdb/common/sock_daemon.h b/ctdb/common/sock_daemon.h
index 190a4ef172f..7f19b32dcd4 100644
--- a/ctdb/common/sock_daemon.h
+++ b/ctdb/common/sock_daemon.h
@@ -52,6 +52,8 @@ struct sock_client_context;
* startup() should return 0 for success, non-zero value on failure
* On failure, sock_daemon_run() will return error.
*
+ * startup_send()/startup_recv() is the async version of startup()
+ *
* reconfigure() is called when the daemon receives SIGUSR1 or SIGHUP
* reconfigure() should return 0 for success, non-zero value on failure
* On failure, sock_daemon_run() will continue to run.
@@ -67,6 +69,12 @@ struct sock_client_context;
*/
struct sock_daemon_funcs {
int (*startup)(void *private_data);
+
+ struct tevent_req * (*startup_send)(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ void *private_data);
+ bool (*startup_recv)(struct tevent_req *req, int *perr);
+
int (*reconfigure)(void *private_data);
void (*shutdown)(void *private_data);
diff --git a/ctdb/tests/cunit/sock_daemon_test_001.sh b/ctdb/tests/cunit/sock_daemon_test_001.sh
index bf925fbe2ab..aa1d6b471db 100755
--- a/ctdb/tests/cunit/sock_daemon_test_001.sh
+++ b/ctdb/tests/cunit/sock_daemon_test_001.sh
@@ -26,6 +26,8 @@ ok <<EOF
test1[PID]: daemon started, pid=PID
test1[PID]: startup failed, ret=1
test1[PID]: daemon started, pid=PID
+test1[PID]: startup failed, ret=2
+test1[PID]: daemon started, pid=PID
test1[PID]: startup completed successfully
test1[PID]: listening on $sockpath
test1[PID]: Shutting down
diff --git a/ctdb/tests/src/sock_daemon_test.c b/ctdb/tests/src/sock_daemon_test.c
index d224ce85dc3..72f265f0b78 100644
--- a/ctdb/tests/src/sock_daemon_test.c
+++ b/ctdb/tests/src/sock_daemon_test.c
@@ -80,6 +80,34 @@ static int test1_startup(void *private_data)
return 0;
}
+struct test1_startup_state {
+};
+
+static struct tevent_req *test1_startup_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ void *private_data)
+{
+ struct tevent_req *req;
+ struct test1_startup_state *state;
+
+ req = tevent_req_create(mem_ctx, &state, struct test1_startup_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ tevent_req_error(req, 2);
+ return tevent_req_post(req, ev);
+}
+
+static bool test1_startup_recv(struct tevent_req *req, int *perr)
+{
+ if (tevent_req_is_unix_error(req, perr)) {
+ return false;
+ }
+
+ return true;
+}
+
static struct tevent_req *dummy_read_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct sock_client_context *client,
@@ -137,6 +165,23 @@ static void test1(TALLOC_CTX *mem_ctx, const char *pidfile,
talloc_free(sockd);
test1_funcs = (struct sock_daemon_funcs){
+ .startup_send = test1_startup_send,
+ .startup_recv = test1_startup_recv,
+ };
+
+ ret = sock_daemon_setup(mem_ctx, "test1", "file:", "NOTICE",
+ &test1_funcs, NULL, &sockd);
+ assert(ret == 0);
+ assert(sockd != NULL);
+
+ ret = stat(pidfile, &st);
+ assert(ret == -1);
+
+ ret = sock_daemon_run(ev, sockd, NULL, false, false, -1);
+ assert(ret == EIO);
+ talloc_free(sockd);
+
+ test1_funcs = (struct sock_daemon_funcs){
.startup = test1_startup,
.wait_send = dummy_wait_send,
.wait_recv = dummy_wait_recv,