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 int event_daemon_reopen_logs(void *private_data
)
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
,
98 struct event_daemon_state
*e_state
= talloc_get_type_abort(
99 private_data
, struct event_daemon_state
);
102 ret
= eventd_client_add(e_state
->eventd
, client
);
104 D_ERR("Failed to register client, ret=%d\n", ret
);
111 static void event_client_disconnect(struct sock_client_context
*client
,
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
;
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
,
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
);
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
);
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
);
170 ok
= event_pkt_recv(subreq
, &ret
, state
, &state
->buf
, &state
->buflen
);
173 tevent_req_error(req
, ret
);
177 ok
= eventd_client_exists(state
->eventd
, state
->client
);
179 /* Client has already disconnected */
180 talloc_free(state
->buf
);
181 tevent_req_done(req
);
185 subreq
= sock_socket_write_send(state
,
190 if (tevent_req_nomem(subreq
, req
)) {
191 talloc_free(state
->buf
);
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
);
206 talloc_free(state
->buf
);
208 ok
= sock_socket_write_recv(subreq
, &ret
);
211 D_ERR("Sending reply failed\n");
212 tevent_req_error(req
, ret
);
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
)) {
236 struct poptOption cmdline_options
[] = {
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" },
245 int main(int argc
, const char **argv
)
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";
258 pc
= poptGetContext(argv
[0],
263 while ((opt
= poptGetNextOpt(pc
)) != -1) {
264 D_ERR("Invalid options %s: %s\n",
265 poptBadOption(pc
, 0),
270 t
= getenv("CTDB_INTERACTIVE");
275 e_state
= talloc_zero(NULL
, struct event_daemon_state
);
276 if (e_state
== NULL
) {
277 D_ERR("Memory allocation error\n");
282 e_state
->mem_ctx
= talloc_new(e_state
);
283 if (e_state
->mem_ctx
== NULL
) {
284 D_ERR("Memory allocation error\n");
289 e_state
->socket
= path_socket(e_state
, "eventd");
290 if (e_state
->socket
== NULL
) {
291 D_ERR("Memory allocation error\n");
296 e_state
->pidfile
= path_pidfile(e_state
, "eventd");
297 if (e_state
->pidfile
== NULL
) {
298 D_ERR("Memory allocation error\n");
303 ret
= event_config_init(e_state
, &e_state
->config
);
305 D_ERR("Failed to initialize event config\n");
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");
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
,
336 D_ERR("Failed to setup sock daemon\n");
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
,
352 D_ERR("Failed to setup socket %s\n", e_state
->socket
);
356 if (options
.startup_fd
!= -1) {
357 ok
= sock_daemon_set_startup_fd(e_state
->sockd
,
364 ret
= sock_daemon_run(e_state
->ev
,
375 talloc_report_full(e_state
->mem_ctx
, stderr
);
379 talloc_free(e_state
);
380 (void)poptFreeContext(pc
);