smbd: add handle lease breaking when deleting files in tree disconnect
[samba4-gss.git] / ctdb / event / event_cmd.c
blobdb39e4d881cbe420300dcdf163573571a7438556
1 /*
2 CTDB event daemon - command handling
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"
22 #include <talloc.h>
23 #include <tevent.h>
25 #include "lib/util/debug.h"
26 #include "lib/util/tevent_unix.h"
28 #include "common/logging.h"
30 #include "event/event_private.h"
32 struct event_cmd_state {
33 struct event_context *eventd;
34 struct ctdb_event_request *request;
35 struct ctdb_event_reply *reply;
39 * CTDB_EVENT_CMD_RUN
42 static void event_cmd_run_done(struct tevent_req *subreq);
44 static struct tevent_req *event_cmd_run_send(
45 TALLOC_CTX *mem_ctx,
46 struct tevent_context *ev,
47 struct event_context *eventd,
48 struct ctdb_event_request *request,
49 struct ctdb_event_reply *reply)
51 struct tevent_req *req, *subreq;
52 struct event_cmd_state *state;
53 struct run_event_context *run_ctx;
54 struct ctdb_event_request_run *rdata;
55 int ret;
56 bool continue_on_failure = false;
58 req = tevent_req_create(mem_ctx, &state, struct event_cmd_state);
59 if (req == NULL) {
60 return NULL;
63 state->eventd = eventd;
64 state->request = request;
65 state->reply = reply;
67 rdata = request->data.run;
69 ret = eventd_run_ctx(eventd, rdata->component, &run_ctx);
70 if (ret != 0) {
71 state->reply->result = ret;
72 tevent_req_done(req);
73 return tevent_req_post(req, ev);
76 if (rdata->flags & CTDB_EVENT_RUN_ALL) {
77 continue_on_failure = true;
80 subreq = run_event_send(state,
81 ev,
82 run_ctx,
83 rdata->event,
84 rdata->args,
85 tevent_timeval_current_ofs(rdata->timeout,0),
86 continue_on_failure);
87 if (tevent_req_nomem(subreq, req)) {
88 return tevent_req_post(req, ev);
90 tevent_req_set_callback(subreq, event_cmd_run_done, req);
92 return req;
95 static void event_cmd_run_done(struct tevent_req *subreq)
97 struct tevent_req *req = tevent_req_callback_data(
98 subreq, struct tevent_req);
99 struct event_cmd_state *state = tevent_req_data(
100 req, struct event_cmd_state);
101 struct run_event_script_list *script_list = NULL;
102 struct ctdb_event_request_run *rdata;
103 int ret;
104 bool ok;
106 ok = run_event_recv(subreq, &ret, state, &script_list);
107 TALLOC_FREE(subreq);
108 if (!ok) {
109 state->reply->result = ret;
110 goto done;
113 if (script_list == NULL) {
114 state->reply->result = EIO;
115 goto done;
118 if (script_list->summary == -ECANCELED) {
119 state->reply->result = ECANCELED;
120 goto done;
123 rdata = state->request->data.run;
124 ret = eventd_set_event_result(state->eventd,
125 rdata->component,
126 rdata->event,
127 script_list);
128 if (ret != 0) {
129 state->reply->result = ret;
130 goto done;
133 if (script_list->summary == -ETIMEDOUT) {
134 state->reply->result = ETIMEDOUT;
135 } else if (script_list->summary != 0) {
136 state->reply->result = ENOEXEC;
139 done:
140 tevent_req_done(req);
144 * CTDB_EVENT_CMD_STATUS
147 static struct tevent_req *event_cmd_status_send(
148 TALLOC_CTX *mem_ctx,
149 struct tevent_context *ev,
150 struct event_context *eventd,
151 struct ctdb_event_request *request,
152 struct ctdb_event_reply *reply)
154 struct tevent_req *req;
155 struct event_cmd_state *state;
156 struct ctdb_event_request_run *rdata;
157 struct run_event_script_list *script_list;
158 int ret;
160 req = tevent_req_create(mem_ctx, &state, struct event_cmd_state);
161 if (req == NULL) {
162 return NULL;
165 reply->data.status = talloc_zero(reply,
166 struct ctdb_event_reply_status);
167 if (tevent_req_nomem(reply->data.status, req)) {
168 reply->result = ENOMEM;
169 goto done;
172 rdata = request->data.run;
174 ret = eventd_get_event_result(eventd,
175 rdata->component,
176 rdata->event,
177 &script_list);
178 if (ret != 0) {
179 reply->result = ret;
180 goto done;
183 reply->data.status->script_list = eventd_script_list(reply,
184 script_list);
185 if (reply->data.status->script_list == NULL) {
186 reply->result = ENOMEM;
187 goto done;
189 reply->data.status->summary = script_list->summary;
191 reply->result = 0;
193 done:
194 tevent_req_done(req);
195 return tevent_req_post(req, ev);
199 * CTDB_EVENT_CMD_SCRIPT
202 static struct tevent_req *event_cmd_script_send(
203 TALLOC_CTX *mem_ctx,
204 struct tevent_context *ev,
205 struct event_context *eventd,
206 struct ctdb_event_request *request,
207 struct ctdb_event_reply *reply)
209 struct tevent_req *req;
210 struct event_cmd_state *state;
211 struct run_event_context *run_ctx;
212 struct ctdb_event_request_script *rdata;
213 int ret;
215 req = tevent_req_create(mem_ctx, &state, struct event_cmd_state);
216 if (req == NULL) {
217 return NULL;
220 rdata = request->data.script;
222 ret = eventd_run_ctx(eventd, rdata->component, &run_ctx);
223 if (ret != 0) {
224 reply->result = ret;
225 goto done;
228 if (rdata->action == CTDB_EVENT_SCRIPT_DISABLE) {
229 ret = run_event_script_disable(run_ctx, rdata->script);
230 } else if (rdata->action == CTDB_EVENT_SCRIPT_ENABLE) {
231 ret = run_event_script_enable(run_ctx, rdata->script);
232 } else {
233 D_ERR("Invalid action specified\n");
234 reply->result = EPROTO;
235 goto done;
238 if (ret != 0) {
239 reply->result = ret;
240 goto done;
243 reply->result = 0;
245 done:
246 tevent_req_done(req);
247 return tevent_req_post(req, ev);
250 static bool event_cmd_recv(struct tevent_req *req, int *perr)
252 if (tevent_req_is_unix_error(req, perr)) {
253 return false;
256 return true;
260 struct event_cmd_dispatch_state {
261 struct ctdb_event_reply *reply;
264 static void event_cmd_dispatch_done(struct tevent_req *subreq);
266 struct tevent_req *event_cmd_dispatch_send(TALLOC_CTX *mem_ctx,
267 struct tevent_context *ev,
268 struct event_context *eventd,
269 struct ctdb_event_request *request)
271 struct tevent_req *req, *subreq;
272 struct event_cmd_dispatch_state *state;
274 req = tevent_req_create(mem_ctx,
275 &state,
276 struct event_cmd_dispatch_state);
277 if (req == NULL) {
278 return NULL;
281 state->reply = talloc_zero(state, struct ctdb_event_reply);
282 if (tevent_req_nomem(state->reply, req)) {
283 return tevent_req_post(req, ev);
286 state->reply->cmd = request->cmd;
288 switch (request->cmd) {
289 case CTDB_EVENT_CMD_RUN:
290 subreq = event_cmd_run_send(state,
292 eventd,
293 request,
294 state->reply);
295 break;
297 case CTDB_EVENT_CMD_STATUS:
298 subreq = event_cmd_status_send(state,
300 eventd,
301 request,
302 state->reply);
303 break;
305 case CTDB_EVENT_CMD_SCRIPT:
306 subreq = event_cmd_script_send(state,
308 eventd,
309 request,
310 state->reply);
311 break;
313 default:
314 state->reply->result = EPROTO;
315 tevent_req_done(req);
316 return tevent_req_post(req, ev);
319 if (tevent_req_nomem(subreq, req)) {
320 return tevent_req_post(req, ev);
322 tevent_req_set_callback(subreq, event_cmd_dispatch_done, req);
324 return req;
327 static void event_cmd_dispatch_done(struct tevent_req *subreq)
329 struct tevent_req *req = tevent_req_callback_data(
330 subreq, struct tevent_req);
331 int ret;
332 bool ok;
334 ok = event_cmd_recv(subreq, &ret);
335 TALLOC_FREE(subreq);
336 if (!ok) {
337 tevent_req_error(req, ret);
338 return;
341 tevent_req_done(req);
344 bool event_cmd_dispatch_recv(struct tevent_req *req,
345 int *perr,
346 TALLOC_CTX *mem_ctx,
347 struct ctdb_event_reply **reply)
349 struct event_cmd_dispatch_state *state = tevent_req_data(
350 req, struct event_cmd_dispatch_state);
352 if (tevent_req_is_unix_error(req, perr)) {
353 return false;
356 *reply = talloc_steal(mem_ctx, state->reply);
357 return true;