dsdb: Use replmd_replPropertyMetaData1_new_should_be_taken in replmd_replicated_apply...
[Samba.git] / ctdb / client / client_message.c
blob03fcfc6690fde62d80281efd0fd5e2112e28442b
1 /*
2 CTDB client code
4 Copyright (C) Amitay Isaacs 2015
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/network.h"
22 #include "system/filesys.h"
24 #include <talloc.h>
25 #include <tevent.h>
26 #include <tdb.h>
28 #include "lib/util/tevent_unix.h"
30 #include "common/reqid.h"
31 #include "common/srvid.h"
32 #include "common/comm.h"
34 #include "protocol/protocol.h"
35 #include "protocol/protocol_api.h"
37 #include "client/client_private.h"
38 #include "client/client.h"
42 * Handle REQ_MESSAGE
45 struct ctdb_client_message_state {
46 struct ctdb_client_context *client;
47 uint32_t reqid;
50 static int ctdb_client_message_state_destructor(
51 struct ctdb_client_message_state *state);
52 static void ctdb_client_message_done(struct tevent_req *subreq);
54 struct tevent_req *ctdb_client_message_send(TALLOC_CTX *mem_ctx,
55 struct tevent_context *ev,
56 struct ctdb_client_context *client,
57 uint32_t destnode,
58 struct ctdb_req_message *message)
60 struct tevent_req *req, *subreq;
61 struct ctdb_client_message_state *state;
62 struct ctdb_req_header h;
63 uint32_t reqid;
64 uint8_t *buf;
65 size_t datalen, buflen;
66 int ret;
68 req = tevent_req_create(mem_ctx, &state,
69 struct ctdb_client_message_state);
70 if (req == NULL) {
71 return NULL;
74 reqid = reqid_new(client->idr, state);
75 if (reqid == REQID_INVALID) {
76 talloc_free(req);
77 return NULL;
80 state->client = client;
81 state->reqid = reqid;
83 talloc_set_destructor(state, ctdb_client_message_state_destructor);
85 ctdb_req_header_fill(&h, 0, CTDB_REQ_MESSAGE, destnode,
86 client->pnn, reqid);
88 datalen = ctdb_req_message_len(&h, message);
89 ret = ctdb_allocate_pkt(state, datalen, &buf, &buflen);
90 if (ret != 0) {
91 tevent_req_error(req, ret);
92 return tevent_req_post(req, ev);
95 ret = ctdb_req_message_push(&h, message, buf, &buflen);
96 if (ret != 0) {
97 tevent_req_error(req, ret);
98 return tevent_req_post(req, ev);
101 subreq = comm_write_send(state, ev, client->comm, buf, buflen);
102 if (tevent_req_nomem(subreq, req)) {
103 return tevent_req_post(req, ev);
105 tevent_req_set_callback(subreq, ctdb_client_message_done, req);
107 return req;
110 static int ctdb_client_message_state_destructor(
111 struct ctdb_client_message_state *state)
113 reqid_remove(state->client->idr, state->reqid);
114 return 0;
117 static void ctdb_client_message_done(struct tevent_req *subreq)
119 struct tevent_req *req = tevent_req_callback_data(
120 subreq, struct tevent_req);
121 int ret;
122 bool status;
124 status = comm_write_recv(subreq, &ret);
125 TALLOC_FREE(subreq);
126 if (! status) {
127 tevent_req_error(req, ret);
128 return;
131 tevent_req_done(req);
134 bool ctdb_client_message_recv(struct tevent_req *req, int *perr)
136 int err;
138 if (tevent_req_is_unix_error(req, &err)) {
139 if (perr != NULL) {
140 *perr = err;
142 return false;
145 return true;
148 void ctdb_client_req_message(struct ctdb_client_context *client,
149 uint8_t *buf, size_t buflen, uint32_t reqid)
151 struct ctdb_req_header h;
152 struct ctdb_req_message_data message;
153 TALLOC_CTX *tmp_ctx = talloc_new(client);
154 int ret;
156 ret = ctdb_req_message_data_pull(buf, buflen, &h, tmp_ctx, &message);
157 if (ret != 0) {
158 return;
161 srvid_dispatch(client->srv, message.srvid, CTDB_SRVID_ALL,
162 message.data);
163 talloc_free(tmp_ctx);
167 * Handle multiple nodes
170 struct ctdb_client_message_multi_state {
171 uint32_t *pnn_list;
172 int count;
173 int done;
174 int err;
175 int *err_list;
178 struct message_index_state {
179 struct tevent_req *req;
180 int index;
183 static void ctdb_client_message_multi_done(struct tevent_req *subreq);
185 struct tevent_req *ctdb_client_message_multi_send(
186 TALLOC_CTX *mem_ctx,
187 struct tevent_context *ev,
188 struct ctdb_client_context *client,
189 uint32_t *pnn_list, int count,
190 struct ctdb_req_message *message)
192 struct tevent_req *req, *subreq;
193 struct ctdb_client_message_multi_state *state;
194 int i;
196 if (pnn_list == NULL || count == 0) {
197 return NULL;
200 req = tevent_req_create(mem_ctx, &state,
201 struct ctdb_client_message_multi_state);
202 if (req == NULL) {
203 return NULL;
206 state->pnn_list = pnn_list;
207 state->count = count;
208 state->done = 0;
209 state->err = 0;
210 state->err_list = talloc_zero_array(state, int, count);
211 if (tevent_req_nomem(state->err_list, req)) {
212 return tevent_req_post(req, ev);
215 for (i=0; i<count; i++) {
216 struct message_index_state *substate;
218 subreq = ctdb_client_message_send(state, ev, client,
219 pnn_list[i], message);
220 if (tevent_req_nomem(subreq, req)) {
221 return tevent_req_post(req, ev);
224 substate = talloc(subreq, struct message_index_state);
225 if (tevent_req_nomem(substate, req)) {
226 return tevent_req_post(req, ev);
229 substate->req = req;
230 substate->index = i;
232 tevent_req_set_callback(subreq, ctdb_client_message_multi_done,
233 substate);
236 return req;
239 static void ctdb_client_message_multi_done(struct tevent_req *subreq)
241 struct message_index_state *substate = tevent_req_callback_data(
242 subreq, struct message_index_state);
243 struct tevent_req *req = substate->req;
244 int idx = substate->index;
245 struct ctdb_client_message_multi_state *state = tevent_req_data(
246 req, struct ctdb_client_message_multi_state);
247 bool status;
248 int ret;
250 status = ctdb_client_message_recv(subreq, &ret);
251 TALLOC_FREE(subreq);
252 if (! status) {
253 if (state->err == 0) {
254 state->err = ret;
255 state->err_list[idx] = state->err;
259 state->done += 1;
261 if (state->done == state->count) {
262 tevent_req_done(req);
266 bool ctdb_client_message_multi_recv(struct tevent_req *req, int *perr,
267 TALLOC_CTX *mem_ctx, int **perr_list)
269 struct ctdb_client_message_multi_state *state = tevent_req_data(
270 req, struct ctdb_client_message_multi_state);
271 int err;
273 if (tevent_req_is_unix_error(req, &err)) {
274 if (perr != NULL) {
275 *perr = err;
277 if (perr_list != NULL) {
278 *perr_list = talloc_steal(mem_ctx, state->err_list);
280 return false;
283 if (perr != NULL) {
284 *perr = state->err;
287 if (perr_list != NULL) {
288 *perr_list = talloc_steal(mem_ctx, state->err_list);
291 if (state->err != 0) {
292 return false;
295 return true;
299 * sync version of message send
302 int ctdb_client_message(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
303 struct ctdb_client_context *client,
304 uint32_t destnode, struct ctdb_req_message *message)
306 TALLOC_CTX *tmp_ctx;
307 struct tevent_req *req;
308 int ret;
309 bool status;
311 tmp_ctx = talloc_new(client);
312 if (tmp_ctx == NULL) {
313 return ENOMEM;
316 req = ctdb_client_message_send(tmp_ctx, ev, client, destnode, message);
317 if (req == NULL) {
318 talloc_free(tmp_ctx);
319 return ENOMEM;
322 tevent_req_poll(req, ev);
324 status = ctdb_client_message_recv(req, &ret);
325 if (! status) {
326 talloc_free(tmp_ctx);
327 return ret;
330 talloc_free(tmp_ctx);
331 return 0;
334 struct ctdb_client_set_message_handler_state {
335 struct ctdb_client_context *client;
336 uint64_t srvid;
337 srvid_handler_fn handler;
338 void *private_data;
341 static void ctdb_client_set_message_handler_done(struct tevent_req *subreq);
343 struct tevent_req *ctdb_client_set_message_handler_send(
344 TALLOC_CTX *mem_ctx,
345 struct tevent_context *ev,
346 struct ctdb_client_context *client,
347 uint64_t srvid,
348 srvid_handler_fn handler,
349 void *private_data)
351 struct tevent_req *req, *subreq;
352 struct ctdb_client_set_message_handler_state *state;
353 struct ctdb_req_control request;
355 req = tevent_req_create(mem_ctx, &state,
356 struct ctdb_client_set_message_handler_state);
357 if (req == NULL) {
358 return NULL;
361 state->client = client;
362 state->srvid = srvid;
363 state->handler = handler;
364 state->private_data = private_data;
366 ctdb_req_control_register_srvid(&request, srvid);
367 subreq = ctdb_client_control_send(state, ev, client, client->pnn,
368 tevent_timeval_zero(), &request);
369 if (tevent_req_nomem(subreq, req)) {
370 return tevent_req_post(req, ev);
372 tevent_req_set_callback(subreq, ctdb_client_set_message_handler_done,
373 req);
375 return req;
378 static void ctdb_client_set_message_handler_done(struct tevent_req *subreq)
380 struct tevent_req *req = tevent_req_callback_data(
381 subreq, struct tevent_req);
382 struct ctdb_client_set_message_handler_state *state = tevent_req_data(
383 req, struct ctdb_client_set_message_handler_state);
384 struct ctdb_reply_control *reply;
385 bool status;
386 int ret;
388 status = ctdb_client_control_recv(subreq, &ret, state, &reply);
389 TALLOC_FREE(subreq);
390 if (! status) {
391 tevent_req_error(req, ret);
392 return;
395 ret = ctdb_reply_control_register_srvid(reply);
396 talloc_free(reply);
397 if (ret != 0) {
398 tevent_req_error(req, ret);
399 return;
402 ret = srvid_register(state->client->srv, state->client, state->srvid,
403 state->handler, state->private_data);
404 if (ret != 0) {
405 tevent_req_error(req, ret);
406 return;
409 tevent_req_done(req);
412 bool ctdb_client_set_message_handler_recv(struct tevent_req *req, int *perr)
414 int err;
416 if (tevent_req_is_unix_error(req, &err)) {
417 if (perr != NULL) {
418 *perr = err;
420 return false;
422 return true;
425 struct ctdb_client_remove_message_handler_state {
426 struct ctdb_client_context *client;
427 uint64_t srvid;
428 void *private_data;
431 static void ctdb_client_remove_message_handler_done(struct tevent_req *subreq);
433 struct tevent_req *ctdb_client_remove_message_handler_send(
434 TALLOC_CTX *mem_ctx,
435 struct tevent_context *ev,
436 struct ctdb_client_context *client,
437 uint64_t srvid,
438 void *private_data)
440 struct tevent_req *req, *subreq;
441 struct ctdb_client_remove_message_handler_state *state;
442 struct ctdb_req_control request;
444 req = tevent_req_create(mem_ctx, &state,
445 struct ctdb_client_remove_message_handler_state);
446 if (req == NULL) {
447 return NULL;
450 state->client = client;
451 state->srvid = srvid;
452 state->private_data = private_data;
454 ctdb_req_control_deregister_srvid(&request, srvid);
455 subreq = ctdb_client_control_send(state, ev, client, client->pnn,
456 tevent_timeval_zero(), &request);
457 if (tevent_req_nomem(subreq, req)) {
458 return tevent_req_post(req, ev);
460 tevent_req_set_callback(subreq,
461 ctdb_client_remove_message_handler_done, req);
463 return req;
466 static void ctdb_client_remove_message_handler_done(struct tevent_req *subreq)
468 struct tevent_req *req = tevent_req_callback_data(
469 subreq, struct tevent_req);
470 struct ctdb_client_remove_message_handler_state *state = tevent_req_data(
471 req, struct ctdb_client_remove_message_handler_state);
472 struct ctdb_reply_control *reply;
473 bool status;
474 int ret;
476 status = ctdb_client_control_recv(subreq, &ret, state, &reply);
477 TALLOC_FREE(subreq);
478 if (! status) {
479 tevent_req_error(req, ret);
480 return;
483 ret = ctdb_reply_control_deregister_srvid(reply);
484 talloc_free(reply);
485 if (ret != 0) {
486 tevent_req_error(req, ret);
487 return;
490 ret = srvid_deregister(state->client->srv, state->srvid,
491 state->private_data);
492 if (ret != 0) {
493 tevent_req_error(req, ret);
494 return;
497 tevent_req_done(req);
500 bool ctdb_client_remove_message_handler_recv(struct tevent_req *req, int *perr)
502 int err;
504 if (tevent_req_is_unix_error(req, &err)) {
505 if (perr != NULL) {
506 *perr = err;
508 return false;
510 return true;
513 int ctdb_client_set_message_handler(struct tevent_context *ev,
514 struct ctdb_client_context *client,
515 uint64_t srvid, srvid_handler_fn handler,
516 void *private_data)
518 TALLOC_CTX *mem_ctx;
519 int ret;
521 mem_ctx = talloc_new(client);
522 if (mem_ctx == NULL) {
523 return ENOMEM;
526 ret = ctdb_ctrl_register_srvid(mem_ctx, ev, client, client->pnn,
527 tevent_timeval_zero(), srvid);
528 talloc_free(mem_ctx);
529 if (ret != 0) {
530 return ret;
533 return srvid_register(client->srv, client, srvid,
534 handler, private_data);
537 int ctdb_client_remove_message_handler(struct tevent_context *ev,
538 struct ctdb_client_context *client,
539 uint64_t srvid, void *private_data)
541 TALLOC_CTX *mem_ctx;
542 int ret;
544 mem_ctx = talloc_new(client);
545 if (mem_ctx == NULL) {
546 return ENOMEM;
549 ret = ctdb_ctrl_deregister_srvid(mem_ctx, ev, client, client->pnn,
550 tevent_timeval_zero(), srvid);
551 talloc_free(mem_ctx);
552 if (ret != 0) {
553 return ret;
556 return srvid_deregister(client->srv, srvid, private_data);