ctdb-common: Add async version of startup in sock_daemon
authorAmitay Isaacs <amitay@gmail.com>
Fri, 17 Nov 2017 01:36:29 +0000 (12:36 +1100)
committerMartin Schwenke <martins@samba.org>
Tue, 21 Nov 2017 04:03:17 +0000 (05:03 +0100)
Signed-off-by: Amitay Isaacs <amitay@gmail.com>
Reviewed-by: Martin Schwenke <martin@meltin.net>
ctdb/common/sock_daemon.c
ctdb/common/sock_daemon.h
ctdb/tests/cunit/sock_daemon_test_001.sh
ctdb/tests/src/sock_daemon_test.c

index 0ef016668831ce877af6763cd3198b5a69777dea..6b05e2462f90e19e2e77099128fdd98ce3d77e1a 100644 (file)
@@ -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,
index 190a4ef172f93955fed59137ea352e7f2df84ab2..7f19b32dcd4d2885f08accfa54870dabcdc6efbd 100644 (file)
@@ -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);
 
index bf925fbe2ab8aa9574eeac751fe99378772f890d..aa1d6b471db49e6dc81fdae297568fc2b690105f 100755 (executable)
@@ -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
index d224ce85dc30fbbafabc00c7c7b8d82bd02b66d5..72f265f0b784fd9eea31fcd7507ce05813f6c2df 100644 (file)
@@ -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,
@@ -136,6 +164,23 @@ static void test1(TALLOC_CTX *mem_ctx, const char *pidfile,
        assert(ret == EIO);
        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,