diff options
-rw-r--r-- | ctdb/common/sock_daemon.c | 47 | ||||
-rw-r--r-- | ctdb/common/sock_daemon.h | 14 | ||||
-rwxr-xr-x | ctdb/tests/cunit/sock_daemon_test_001.sh | 2 | ||||
-rw-r--r-- | ctdb/tests/src/sock_daemon_test.c | 175 |
4 files changed, 183 insertions, 55 deletions
diff --git a/ctdb/common/sock_daemon.c b/ctdb/common/sock_daemon.c index 3b679ab1332..b53b4d85333 100644 --- a/ctdb/common/sock_daemon.c +++ b/ctdb/common/sock_daemon.c @@ -70,7 +70,6 @@ struct sock_daemon_context { struct pidfile_context *pid_ctx; struct sock_socket *socket_list; - struct tevent_req *req; }; /* @@ -451,8 +450,6 @@ bool sock_socket_write_recv(struct tevent_req *req, int *perr) * Socket daemon */ -static int sock_daemon_context_destructor(struct sock_daemon_context *sockd); - int sock_daemon_setup(TALLOC_CTX *mem_ctx, const char *daemon_name, const char *logging, const char *debug_level, const char *pidfile, @@ -487,21 +484,10 @@ int sock_daemon_setup(TALLOC_CTX *mem_ctx, const char *daemon_name, } } - talloc_set_destructor(sockd, sock_daemon_context_destructor); - *out = sockd; return 0; } -static int sock_daemon_context_destructor(struct sock_daemon_context *sockd) -{ - if (sockd->req != NULL) { - tevent_req_done(sockd->req); - } - - return 0; -} - int sock_daemon_add_unix(struct sock_daemon_context *sockd, const char *sockpath, struct sock_socket_funcs *funcs, @@ -546,6 +532,7 @@ static void sock_daemon_run_reconfigure(struct tevent_req *req); static void sock_daemon_run_shutdown(struct tevent_req *req); static void sock_daemon_run_socket_fail(struct tevent_req *subreq); static void sock_daemon_run_watch_pid(struct tevent_req *subreq); +static void sock_daemon_run_wait_done(struct tevent_req *subreq); struct tevent_req *sock_daemon_run_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -620,7 +607,16 @@ struct tevent_req *sock_daemon_run_send(TALLOC_CTX *mem_ctx, req); } - sockd->req = req; + if (sockd->funcs != NULL && sockd->funcs->wait_send != NULL && + sockd->funcs->wait_recv != NULL) { + subreq = sockd->funcs->wait_send(state, ev, + sockd->private_data); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, sock_daemon_run_wait_done, + req); + } return req; } @@ -748,6 +744,26 @@ static void sock_daemon_run_watch_pid(struct tevent_req *subreq) tevent_req_set_callback(subreq, sock_daemon_run_watch_pid, req); } +static void sock_daemon_run_wait_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->wait_recv(subreq, &ret); + TALLOC_FREE(subreq); + sock_daemon_run_shutdown(req); + if (! status) { + tevent_req_error(req, ret); + } else { + tevent_req_done(req); + } +} + bool sock_daemon_run_recv(struct tevent_req *req, int *perr) { int ret; @@ -778,7 +794,6 @@ int sock_daemon_run(struct tevent_context *ev, tevent_req_poll(req, ev); status = sock_daemon_run_recv(req, &ret); - sockd->req = NULL; TALLOC_FREE(req); if (! status) { return ret; diff --git a/ctdb/common/sock_daemon.h b/ctdb/common/sock_daemon.h index 6c474acd021..81853f66446 100644 --- a/ctdb/common/sock_daemon.h +++ b/ctdb/common/sock_daemon.h @@ -50,12 +50,24 @@ struct sock_client_context; * startup() is called when the daemon starts running * either via sock_daemon_run() or via sock_daemon_run_send() * reconfigure() is called when process receives SIGUSR1 or SIGHUP - * shutdown() is called when process receives SIGINT or SIGTERM + * shutdown() is called when process receives SIGINT or SIGTERM or + * when wait computation has finished + * + * wait_send() starts the async computation to keep running the daemon + * wait_recv() ends the async computation to keep running the daemon + * + * If wait_send()/wait_recv() is NULL, then daemon will keep running forever. + * If wait_send() returns req, then when req is over, daemon will shutdown. */ struct sock_daemon_funcs { void (*startup)(void *private_data); void (*reconfigure)(void *private_data); void (*shutdown)(void *private_data); + + struct tevent_req * (*wait_send)(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + void *private_data); + bool (*wait_recv)(struct tevent_req *req, int *perr); }; /** diff --git a/ctdb/tests/cunit/sock_daemon_test_001.sh b/ctdb/tests/cunit/sock_daemon_test_001.sh index 036b6ac6f26..72e5532a332 100755 --- a/ctdb/tests/cunit/sock_daemon_test_001.sh +++ b/ctdb/tests/cunit/sock_daemon_test_001.sh @@ -47,6 +47,7 @@ unit_test sock_daemon_test "$pidfile" "$sockpath" 3 ok <<EOF test4[PID]: daemon started, pid=PID +test4[PID]: Shutting down EOF unit_test sock_daemon_test "$pidfile" "$sockpath" 4 @@ -61,5 +62,6 @@ unit_test sock_daemon_test "$pidfile" "$sockpath" 5 ok <<EOF test6[PID]: listening on $sockpath test6[PID]: daemon started, pid=PID +test6[PID]: Shutting down EOF unit_test sock_daemon_test "$pidfile" "$sockpath" 6 diff --git a/ctdb/tests/src/sock_daemon_test.c b/ctdb/tests/src/sock_daemon_test.c index 4a085c0a55a..278dcab8ec0 100644 --- a/ctdb/tests/src/sock_daemon_test.c +++ b/ctdb/tests/src/sock_daemon_test.c @@ -254,17 +254,68 @@ static void test3(TALLOC_CTX *mem_ctx, const char *pidfile, assert(ret == -1); } -static void test4_handler(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval curtime, - void *private_data) +struct test4_wait_state { +}; + +static void test4_wait_done(struct tevent_req *subreq); + +static struct tevent_req *test4_wait_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + void *private_data) { - struct sock_daemon_context *sockd = talloc_get_type_abort( - private_data, struct sock_daemon_context); + struct tevent_req *req, *subreq; + struct test4_wait_state *state; - talloc_free(sockd); + req = tevent_req_create(mem_ctx, &state, struct test4_wait_state); + if (req == NULL) { + return NULL; + } + + subreq = tevent_wakeup_send(state, ev, + tevent_timeval_current_ofs(10,0)); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, test4_wait_done, req); + + return req; } +static void test4_wait_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + bool status; + + status = tevent_wakeup_recv(subreq); + TALLOC_FREE(subreq); + + if (! status) { + tevent_req_error(req, EIO); + } else { + tevent_req_done(req); + } +} + +static bool test4_wait_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_daemon_funcs test4_funcs = { + .wait_send = test4_wait_send, + .wait_recv = test4_wait_recv, +}; + static void test4(TALLOC_CTX *mem_ctx, const char *pidfile, const char *sockpath) { @@ -278,19 +329,14 @@ static void test4(TALLOC_CTX *mem_ctx, const char *pidfile, if (pid == 0) { struct tevent_context *ev; struct sock_daemon_context *sockd; - struct tevent_timer *te; ev = tevent_context_init(mem_ctx); assert(ev != NULL); ret = sock_daemon_setup(mem_ctx, "test4", "file:", "NOTICE", - NULL, NULL, NULL, &sockd); + pidfile, &test4_funcs, NULL, &sockd); assert(ret == 0); - te = tevent_add_timer(ev, ev, tevent_timeval_current_ofs(10,0), - test4_handler, sockd); - assert(te != NULL); - ret = sock_daemon_run(ev, sockd, -1); assert(ret == 0); @@ -666,7 +712,7 @@ static void test6_client(const char *sockpath) struct test6_server_state { struct sock_daemon_context *sockd; - int done; + int fd, done; }; struct test6_read_state { @@ -752,35 +798,90 @@ static struct sock_socket_funcs test6_client_funcs = { static void test6_startup(void *private_data) { - int fd = *(int *)private_data; + struct test6_server_state *server_state = + (struct test6_server_state *)private_data; int ret = 1; ssize_t nwritten; - nwritten = write(fd, &ret, sizeof(ret)); + nwritten = write(server_state->fd, &ret, sizeof(ret)); assert(nwritten == sizeof(ret)); - close(fd); + close(server_state->fd); + server_state->fd = -1; } -static struct sock_daemon_funcs test6_funcs = { - .startup = test6_startup, +struct test6_wait_state { + struct test6_server_state *server_state; }; -static void test6_handler(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval curtime, - void *private_data) +static void test6_wait_done(struct tevent_req *subreq); + +static struct tevent_req *test6_wait_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + void *private_data) { - struct test6_server_state *state = - (struct test6_server_state *)private_data; + struct tevent_req *req, *subreq; + struct test6_wait_state *state; + + req = tevent_req_create(mem_ctx, &state, struct test6_wait_state); + if (req == NULL) { + return NULL; + } + + state->server_state = (struct test6_server_state *)private_data; - if (state->done == 0) { - kill(0, SIGTERM); + subreq = tevent_wakeup_send(state, ev, + tevent_timeval_current_ofs(10,0)); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, test6_wait_done, req); + + return req; +} + +static void test6_wait_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct test6_wait_state *state = tevent_req_data( + req, struct test6_wait_state); + bool status; + + status = tevent_wakeup_recv(subreq); + TALLOC_FREE(subreq); + if (! status) { + tevent_req_error(req, EIO); return; } - talloc_free(state->sockd); + if (state->server_state->done == 0) { + tevent_req_error(req, EIO); + return; + } + + tevent_req_done(req); } +static bool test6_wait_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_daemon_funcs test6_funcs = { + .startup = test6_startup, + .wait_send = test6_wait_send, + .wait_recv = test6_wait_recv, +}; + static void test6(TALLOC_CTX *mem_ctx, const char *pidfile, const char *sockpath) { @@ -799,29 +900,27 @@ static void test6(TALLOC_CTX *mem_ctx, const char *pidfile, if (pid_server == 0) { struct tevent_context *ev; struct sock_daemon_context *sockd; - struct test6_server_state state; - struct tevent_timer *te; + struct test6_server_state server_state = { 0 }; close(fd[0]); ev = tevent_context_init(mem_ctx); assert(ev != NULL); + server_state.fd = fd[1]; + ret = sock_daemon_setup(mem_ctx, "test6", "file:", "NOTICE", - pidfile, &test6_funcs, &fd[1], &sockd); + pidfile, &test6_funcs, &server_state, + &sockd); assert(ret == 0); - state.sockd = sockd; - state.done = 0; + server_state.sockd = sockd; + server_state.done = 0; ret = sock_daemon_add_unix(sockd, sockpath, - &test6_client_funcs, &state); + &test6_client_funcs, &server_state); assert(ret == 0); - te = tevent_add_timer(ev, ev, tevent_timeval_current_ofs(10,0), - test6_handler, &state); - assert(te != NULL); - ret = sock_daemon_run(ev, sockd, pid); assert(ret == 0); |