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 initialize 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 initialize 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
,
365 talloc_report_full(e_state
->mem_ctx
, stderr
);
369 talloc_free(e_state
);
370 (void)poptFreeContext(pc
);