4 Copyright (C) Amitay Isaacs 2018
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "system/filesys.h"
27 #include "lib/util/tevent_unix.h"
29 #include "common/logging.h"
30 #include "common/path.h"
31 #include "common/sock_daemon.h"
33 #include "event/event_private.h"
35 struct event_daemon_state {
39 struct tevent_context *ev;
40 struct event_config *config;
41 struct sock_daemon_context *sockd;
42 struct event_context *eventd;
45 static int event_daemon_startup(void *private_data)
47 struct event_daemon_state *e_state = talloc_get_type_abort(
48 private_data, struct event_daemon_state);
51 ret = event_context_init(e_state,
56 D_ERR("Failed to initialize event context\n");
63 static int event_daemon_reconfigure(void *private_data)
65 struct event_daemon_state *e_state = talloc_get_type_abort(
66 private_data, struct event_daemon_state);
69 ret = event_config_reload(e_state->config);
71 D_WARNING("Configuration reload failed\n");
77 static void event_daemon_shutdown(void *private_data)
79 struct event_daemon_state *e_state = talloc_get_type_abort(
80 private_data, struct event_daemon_state);
82 TALLOC_FREE(e_state->eventd);
85 static bool event_client_connect(struct sock_client_context *client,
89 struct event_daemon_state *e_state = talloc_get_type_abort(
90 private_data, struct event_daemon_state);
93 ret = eventd_client_add(e_state->eventd, client);
95 D_ERR("Failed to register client, ret=%d\n", ret);
102 static void event_client_disconnect(struct sock_client_context *client,
105 struct event_daemon_state *e_state = talloc_get_type_abort(
106 private_data, struct event_daemon_state);
108 eventd_client_del(e_state->eventd, client);
111 struct event_client_state {
112 struct tevent_context *ev;
113 struct event_context *eventd;
114 struct sock_client_context *client;
119 static void event_client_request_done(struct tevent_req *subreq);
120 static void event_client_reply_done(struct tevent_req *subreq);
122 static struct tevent_req *event_client_send(TALLOC_CTX *mem_ctx,
123 struct tevent_context *ev,
124 struct sock_client_context *client,
129 struct event_daemon_state *e_state = talloc_get_type_abort(
130 private_data, struct event_daemon_state);
131 struct tevent_req *req, *subreq;
132 struct event_client_state *state;
134 req = tevent_req_create(mem_ctx, &state, struct event_client_state);
140 state->eventd = e_state->eventd;
141 state->client = client;
143 subreq = event_pkt_send(state, ev, e_state->eventd, buf, buflen);
144 if (tevent_req_nomem(subreq, req)) {
145 return tevent_req_post(req, ev);
147 tevent_req_set_callback(subreq, event_client_request_done, req);
152 static void event_client_request_done(struct tevent_req *subreq)
154 struct tevent_req *req = tevent_req_callback_data(
155 subreq, struct tevent_req);
156 struct event_client_state *state = tevent_req_data(
157 req, struct event_client_state);
161 ok = event_pkt_recv(subreq, &ret, state, &state->buf, &state->buflen);
164 tevent_req_error(req, ret);
168 ok = eventd_client_exists(state->eventd, state->client);
170 /* Client has already disconnected */
171 talloc_free(state->buf);
172 tevent_req_done(req);
176 subreq = sock_socket_write_send(state,
181 if (tevent_req_nomem(subreq, req)) {
182 talloc_free(state->buf);
185 tevent_req_set_callback(subreq, event_client_reply_done, req);
188 static void event_client_reply_done(struct tevent_req *subreq)
190 struct tevent_req *req = tevent_req_callback_data(
191 subreq, struct tevent_req);
192 struct event_client_state *state = tevent_req_data(
193 req, struct event_client_state);
197 talloc_free(state->buf);
199 ok = sock_socket_write_recv(subreq, &ret);
202 D_ERR("Sending reply failed\n");
203 tevent_req_error(req, ret);
207 tevent_req_done(req);
210 static bool event_client_recv(struct tevent_req *req, int *perr)
212 if (tevent_req_is_unix_error(req, perr)) {
227 struct poptOption cmdline_options[] = {
229 { "pid", 'P', POPT_ARG_INT, &options.pid, 0,
230 "pid to wait for", "PID" },
231 { "startup-fd", 'S', POPT_ARG_INT, &options.startup_fd, 0,
232 "file descriptor to notify of successful start", "FD" },
236 int main(int argc, const char **argv)
239 struct event_daemon_state *e_state;
240 struct sock_daemon_funcs daemon_funcs;
241 struct sock_socket_funcs socket_funcs;
242 const char *log_location = "file:";
243 const char *log_level = "NOTICE";
249 pc = poptGetContext(argv[0],
254 while ((opt = poptGetNextOpt(pc)) != -1) {
255 D_ERR("Invalid options %s: %s\n",
256 poptBadOption(pc, 0),
261 t = getenv("CTDB_INTERACTIVE");
266 e_state = talloc_zero(NULL, struct event_daemon_state);
267 if (e_state == NULL) {
268 D_ERR("Memory allocation error\n");
273 e_state->mem_ctx = talloc_new(e_state);
274 if (e_state->mem_ctx == NULL) {
275 D_ERR("Memory allocation error\n");
280 e_state->socket = path_socket(e_state, "eventd");
281 if (e_state->socket == NULL) {
282 D_ERR("Memory allocation error\n");
287 e_state->pidfile = path_pidfile(e_state, "eventd");
288 if (e_state->pidfile == NULL) {
289 D_ERR("Memory allocation error\n");
294 ret = event_config_init(e_state, &e_state->config);
296 D_ERR("Failed to initalize event config\n");
300 e_state->ev = tevent_context_init(e_state->mem_ctx);
301 if (e_state->ev == NULL) {
302 D_ERR("Failed to initalize tevent\n");
307 daemon_funcs = (struct sock_daemon_funcs) {
308 .startup = event_daemon_startup,
309 .reconfigure = event_daemon_reconfigure,
310 .shutdown = event_daemon_shutdown,
313 if (interactive == 0) {
314 log_location = event_config_log_location(e_state->config);
315 log_level = event_config_log_level(e_state->config);
318 ret = sock_daemon_setup(e_state->mem_ctx,
326 D_ERR("Failed to setup sock daemon\n");
330 socket_funcs = (struct sock_socket_funcs) {
331 .connect = event_client_connect,
332 .disconnect = event_client_disconnect,
333 .read_send = event_client_send,
334 .read_recv = event_client_recv,
337 ret = sock_daemon_add_unix(e_state->sockd,
342 D_ERR("Failed to setup socket %s\n", e_state->socket);
346 if (options.startup_fd != -1) {
347 ok = sock_daemon_set_startup_fd(e_state->sockd,
354 ret = sock_daemon_run(e_state->ev,
364 if (getenv("CTDB_TEST_MODE") != NULL) {
365 talloc_report_full(e_state->mem_ctx, stderr);
369 talloc_free(e_state);
370 (void)poptFreeContext(pc);