WHATSNEW.txt: document "veto files" and "hide files"
[Samba.git] / ctdb / event / event_daemon.c
blobd96ff6f172f32dac65bcb63a5cb1883d18f571c7
1 /*
2 CTDB event daemon
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/>.
20 #include "replace.h"
21 #include "system/filesys.h"
23 #include <popt.h>
24 #include <talloc.h>
25 #include <tevent.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 {
36 TALLOC_CTX *mem_ctx;
37 char *socket;
38 char *pidfile;
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);
49 int ret;
51 ret = event_context_init(e_state,
52 e_state->ev,
53 e_state->config,
54 &e_state->eventd);
55 if (ret != 0) {
56 D_ERR("Failed to initialize event context\n");
57 return ret;
60 return 0;
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);
67 int ret;
69 ret = event_config_reload(e_state->config);
70 if (ret != 0) {
71 D_WARNING("Configuration reload failed\n");
74 return 0;
77 static int event_daemon_reopen_logs(void *private_data)
79 bool status;
81 status = logging_reopen_logs();
83 return status ? 0 : 1;
86 static void event_daemon_shutdown(void *private_data)
88 struct event_daemon_state *e_state = talloc_get_type_abort(
89 private_data, struct event_daemon_state);
91 TALLOC_FREE(e_state->eventd);
94 static bool event_client_connect(struct sock_client_context *client,
95 pid_t pid,
96 void *private_data)
98 struct event_daemon_state *e_state = talloc_get_type_abort(
99 private_data, struct event_daemon_state);
100 int ret;
102 ret = eventd_client_add(e_state->eventd, client);
103 if (ret != 0) {
104 D_ERR("Failed to register client, ret=%d\n", ret);
105 return false;
108 return true;
111 static void event_client_disconnect(struct sock_client_context *client,
112 void *private_data)
114 struct event_daemon_state *e_state = talloc_get_type_abort(
115 private_data, struct event_daemon_state);
117 eventd_client_del(e_state->eventd, client);
120 struct event_client_state {
121 struct tevent_context *ev;
122 struct event_context *eventd;
123 struct sock_client_context *client;
124 uint8_t *buf;
125 size_t buflen;
128 static void event_client_request_done(struct tevent_req *subreq);
129 static void event_client_reply_done(struct tevent_req *subreq);
131 static struct tevent_req *event_client_send(TALLOC_CTX *mem_ctx,
132 struct tevent_context *ev,
133 struct sock_client_context *client,
134 uint8_t *buf,
135 size_t buflen,
136 void *private_data)
138 struct event_daemon_state *e_state = talloc_get_type_abort(
139 private_data, struct event_daemon_state);
140 struct tevent_req *req, *subreq;
141 struct event_client_state *state;
143 req = tevent_req_create(mem_ctx, &state, struct event_client_state);
144 if (req == NULL) {
145 return NULL;
148 state->ev = ev;
149 state->eventd = e_state->eventd;
150 state->client = client;
152 subreq = event_pkt_send(state, ev, e_state->eventd, buf, buflen);
153 if (tevent_req_nomem(subreq, req)) {
154 return tevent_req_post(req, ev);
156 tevent_req_set_callback(subreq, event_client_request_done, req);
158 return req;
161 static void event_client_request_done(struct tevent_req *subreq)
163 struct tevent_req *req = tevent_req_callback_data(
164 subreq, struct tevent_req);
165 struct event_client_state *state = tevent_req_data(
166 req, struct event_client_state);
167 int ret = 0;
168 bool ok;
170 ok = event_pkt_recv(subreq, &ret, state, &state->buf, &state->buflen);
171 TALLOC_FREE(subreq);
172 if (!ok) {
173 tevent_req_error(req, ret);
174 return;
177 ok = eventd_client_exists(state->eventd, state->client);
178 if (!ok) {
179 /* Client has already disconnected */
180 talloc_free(state->buf);
181 tevent_req_done(req);
182 return;
185 subreq = sock_socket_write_send(state,
186 state->ev,
187 state->client,
188 state->buf,
189 state->buflen);
190 if (tevent_req_nomem(subreq, req)) {
191 talloc_free(state->buf);
192 return;
194 tevent_req_set_callback(subreq, event_client_reply_done, req);
197 static void event_client_reply_done(struct tevent_req *subreq)
199 struct tevent_req *req = tevent_req_callback_data(
200 subreq, struct tevent_req);
201 struct event_client_state *state = tevent_req_data(
202 req, struct event_client_state);
203 int ret = 0;
204 bool ok;
206 talloc_free(state->buf);
208 ok = sock_socket_write_recv(subreq, &ret);
209 TALLOC_FREE(subreq);
210 if (!ok) {
211 D_ERR("Sending reply failed\n");
212 tevent_req_error(req, ret);
213 return;
216 tevent_req_done(req);
219 static bool event_client_recv(struct tevent_req *req, int *perr)
221 if (tevent_req_is_unix_error(req, perr)) {
222 return false;
225 return true;
228 static struct {
229 int pid;
230 int startup_fd;
231 } options = {
232 .pid = -1,
233 .startup_fd = -1,
236 struct poptOption cmdline_options[] = {
237 POPT_AUTOHELP
238 { "pid", 'P', POPT_ARG_INT, &options.pid, 0,
239 "pid to wait for", "PID" },
240 { "startup-fd", 'S', POPT_ARG_INT, &options.startup_fd, 0,
241 "file descriptor to notify of successful start", "FD" },
242 POPT_TABLEEND
245 int main(int argc, const char **argv)
247 poptContext pc;
248 struct event_daemon_state *e_state;
249 struct sock_daemon_funcs daemon_funcs;
250 struct sock_socket_funcs socket_funcs;
251 const char *log_location = "file:";
252 const char *log_level = "NOTICE";
253 const char *t;
254 int interactive = 0;
255 int opt, ret;
256 bool ok;
258 pc = poptGetContext(argv[0],
259 argc,
260 argv,
261 cmdline_options,
263 while ((opt = poptGetNextOpt(pc)) != -1) {
264 D_ERR("Invalid options %s: %s\n",
265 poptBadOption(pc, 0),
266 poptStrerror(opt));
267 exit(1);
270 t = getenv("CTDB_INTERACTIVE");
271 if (t != NULL) {
272 interactive = 1;
275 e_state = talloc_zero(NULL, struct event_daemon_state);
276 if (e_state == NULL) {
277 D_ERR("Memory allocation error\n");
278 ret = 1;
279 goto fail;
282 e_state->mem_ctx = talloc_new(e_state);
283 if (e_state->mem_ctx == NULL) {
284 D_ERR("Memory allocation error\n");
285 ret = 1;
286 goto fail;
289 e_state->socket = path_socket(e_state, "eventd");
290 if (e_state->socket == NULL) {
291 D_ERR("Memory allocation error\n");
292 ret = 1;
293 goto fail;
296 e_state->pidfile = path_pidfile(e_state, "eventd");
297 if (e_state->pidfile == NULL) {
298 D_ERR("Memory allocation error\n");
299 ret = 1;
300 goto fail;
303 ret = event_config_init(e_state, &e_state->config);
304 if (ret != 0) {
305 D_ERR("Failed to initialize event config\n");
306 goto fail;
309 e_state->ev = tevent_context_init(e_state->mem_ctx);
310 if (e_state->ev == NULL) {
311 D_ERR("Failed to initialize tevent\n");
312 ret = 1;
313 goto fail;
316 daemon_funcs = (struct sock_daemon_funcs) {
317 .startup = event_daemon_startup,
318 .reconfigure = event_daemon_reconfigure,
319 .reopen_logs = event_daemon_reopen_logs,
320 .shutdown = event_daemon_shutdown,
323 if (interactive == 0) {
324 log_location = event_config_log_location(e_state->config);
325 log_level = event_config_log_level(e_state->config);
328 ret = sock_daemon_setup(e_state->mem_ctx,
329 "ctdb-eventd",
330 log_location,
331 log_level,
332 &daemon_funcs,
333 e_state,
334 &e_state->sockd);
335 if (ret != 0) {
336 D_ERR("Failed to setup sock daemon\n");
337 goto fail;
340 socket_funcs = (struct sock_socket_funcs) {
341 .connect = event_client_connect,
342 .disconnect = event_client_disconnect,
343 .read_send = event_client_send,
344 .read_recv = event_client_recv,
347 ret = sock_daemon_add_unix(e_state->sockd,
348 e_state->socket,
349 &socket_funcs,
350 e_state);
351 if (ret != 0) {
352 D_ERR("Failed to setup socket %s\n", e_state->socket);
353 goto fail;
356 if (options.startup_fd != -1) {
357 ok = sock_daemon_set_startup_fd(e_state->sockd,
358 options.startup_fd);
359 if (!ok) {
360 goto fail;
364 ret = sock_daemon_run(e_state->ev,
365 e_state->sockd,
366 e_state->pidfile,
367 false,
368 false,
369 options.pid);
370 if (ret == EINTR) {
371 ret = 0;
374 if (t != NULL) {
375 talloc_report_full(e_state->mem_ctx, stderr);
378 fail:
379 talloc_free(e_state);
380 (void)poptFreeContext(pc);
381 exit(ret);