ctdb-daemon: Schedule running of callback if there are no event scripts
[Samba.git] / ctdb / client / ctdb_client.c
blob1661d2ae178ac5c801d219190c1d9db4e3b2b990
1 /*
2 ctdb daemon code
4 Copyright (C) Andrew Tridgell 2007
5 Copyright (C) Ronnie Sahlberg 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "replace.h"
22 #include "system/network.h"
23 #include "system/filesys.h"
24 #include "system/locale.h"
26 #include <talloc.h>
27 #include <tevent.h>
28 #include <tdb.h>
30 #include "lib/tdb_wrap/tdb_wrap.h"
31 #include "lib/util/dlinklist.h"
32 #include "lib/util/time.h"
33 #include "lib/util/debug.h"
34 #include "lib/util/samba_util.h"
36 #include "ctdb_private.h"
37 #include "ctdb_client.h"
39 #include "common/reqid.h"
40 #include "common/system.h"
41 #include "common/common.h"
42 #include "common/logging.h"
45 allocate a packet for use in client<->daemon communication
47 struct ctdb_req_header *_ctdbd_allocate_pkt(struct ctdb_context *ctdb,
48 TALLOC_CTX *mem_ctx,
49 enum ctdb_operation operation,
50 size_t length, size_t slength,
51 const char *type)
53 int size;
54 struct ctdb_req_header *hdr;
56 length = MAX(length, slength);
57 size = (length+(CTDB_DS_ALIGNMENT-1)) & ~(CTDB_DS_ALIGNMENT-1);
59 hdr = (struct ctdb_req_header *)talloc_zero_size(mem_ctx, size);
60 if (hdr == NULL) {
61 DEBUG(DEBUG_ERR,("Unable to allocate packet for operation %u of length %u\n",
62 operation, (unsigned)length));
63 return NULL;
65 talloc_set_name_const(hdr, type);
66 hdr->length = length;
67 hdr->operation = operation;
68 hdr->ctdb_magic = CTDB_MAGIC;
69 hdr->ctdb_version = CTDB_PROTOCOL;
70 hdr->srcnode = ctdb->pnn;
71 if (ctdb->vnn_map) {
72 hdr->generation = ctdb->vnn_map->generation;
75 return hdr;
79 local version of ctdb_call
81 int ctdb_call_local(struct ctdb_db_context *ctdb_db, struct ctdb_call *call,
82 struct ctdb_ltdb_header *header, TALLOC_CTX *mem_ctx,
83 TDB_DATA *data, bool updatetdb)
85 struct ctdb_call_info *c;
86 struct ctdb_registered_call *fn;
87 struct ctdb_context *ctdb = ctdb_db->ctdb;
89 c = talloc(ctdb, struct ctdb_call_info);
90 CTDB_NO_MEMORY(ctdb, c);
92 c->key = call->key;
93 c->call_data = &call->call_data;
94 c->record_data.dptr = talloc_memdup(c, data->dptr, data->dsize);
95 c->record_data.dsize = data->dsize;
96 CTDB_NO_MEMORY(ctdb, c->record_data.dptr);
97 c->new_data = NULL;
98 c->reply_data = NULL;
99 c->status = 0;
100 c->header = header;
102 for (fn=ctdb_db->calls;fn;fn=fn->next) {
103 if (fn->id == call->call_id) break;
105 if (fn == NULL) {
106 ctdb_set_error(ctdb, "Unknown call id %u\n", call->call_id);
107 talloc_free(c);
108 return -1;
111 if (fn->fn(c) != 0) {
112 ctdb_set_error(ctdb, "ctdb_call %u failed\n", call->call_id);
113 talloc_free(c);
114 return -1;
117 /* we need to force the record to be written out if this was a remote access */
118 if (c->new_data == NULL) {
119 c->new_data = &c->record_data;
122 if (c->new_data && updatetdb) {
123 /* XXX check that we always have the lock here? */
124 if (ctdb_ltdb_store(ctdb_db, call->key, header, *c->new_data) != 0) {
125 ctdb_set_error(ctdb, "ctdb_call tdb_store failed\n");
126 talloc_free(c);
127 return -1;
131 if (c->reply_data) {
132 call->reply_data = *c->reply_data;
134 talloc_steal(call, call->reply_data.dptr);
135 talloc_set_name_const(call->reply_data.dptr, __location__);
136 } else {
137 call->reply_data.dptr = NULL;
138 call->reply_data.dsize = 0;
140 call->status = c->status;
142 talloc_free(c);
144 return 0;
149 queue a packet for sending from client to daemon
151 static int ctdb_client_queue_pkt(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
153 return ctdb_queue_send(ctdb->daemon.queue, (uint8_t *)hdr, hdr->length);
158 called when a CTDB_REPLY_CALL packet comes in in the client
160 This packet comes in response to a CTDB_REQ_CALL request packet. It
161 contains any reply data from the call
163 static void ctdb_client_reply_call(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
165 struct ctdb_reply_call_old *c = (struct ctdb_reply_call_old *)hdr;
166 struct ctdb_client_call_state *state;
168 state = reqid_find(ctdb->idr, hdr->reqid, struct ctdb_client_call_state);
169 if (state == NULL) {
170 DEBUG(DEBUG_ERR,(__location__ " reqid %u not found\n", hdr->reqid));
171 return;
174 if (hdr->reqid != state->reqid) {
175 /* we found a record but it was the wrong one */
176 DEBUG(DEBUG_ERR, ("Dropped client call reply with reqid:%u\n",hdr->reqid));
177 return;
180 state->call->reply_data.dptr = c->data;
181 state->call->reply_data.dsize = c->datalen;
182 state->call->status = c->status;
184 talloc_steal(state, c);
186 state->state = CTDB_CALL_DONE;
188 if (state->async.fn) {
189 state->async.fn(state);
193 void ctdb_request_message(struct ctdb_context *ctdb,
194 struct ctdb_req_header *hdr)
196 struct ctdb_req_message_old *c = (struct ctdb_req_message_old *)hdr;
197 TDB_DATA data;
199 data.dsize = c->datalen;
200 data.dptr = talloc_memdup(c, &c->data[0], c->datalen);
201 if (data.dptr == NULL) {
202 DEBUG(DEBUG_ERR, (__location__ " Memory allocation failure\n"));
203 return;
206 srvid_dispatch(ctdb->srv, c->srvid, CTDB_SRVID_ALL, data);
209 static void ctdb_client_reply_control(struct ctdb_context *ctdb, struct ctdb_req_header *hdr);
212 this is called in the client, when data comes in from the daemon
214 void ctdb_client_read_cb(uint8_t *data, size_t cnt, void *args)
216 struct ctdb_context *ctdb = talloc_get_type(args, struct ctdb_context);
217 struct ctdb_req_header *hdr = (struct ctdb_req_header *)data;
218 TALLOC_CTX *tmp_ctx;
220 /* place the packet as a child of a tmp_ctx. We then use
221 talloc_free() below to free it. If any of the calls want
222 to keep it, then they will steal it somewhere else, and the
223 talloc_free() will be a no-op */
224 tmp_ctx = talloc_new(ctdb);
225 talloc_steal(tmp_ctx, hdr);
227 if (cnt == 0) {
228 DEBUG(DEBUG_CRIT,("Daemon has exited - shutting down client\n"));
229 exit(1);
232 if (cnt < sizeof(*hdr)) {
233 DEBUG(DEBUG_CRIT,("Bad packet length %u in client\n", (unsigned)cnt));
234 goto done;
236 if (cnt != hdr->length) {
237 ctdb_set_error(ctdb, "Bad header length %u expected %u in client\n",
238 (unsigned)hdr->length, (unsigned)cnt);
239 goto done;
242 if (hdr->ctdb_magic != CTDB_MAGIC) {
243 ctdb_set_error(ctdb, "Non CTDB packet rejected in client\n");
244 goto done;
247 if (hdr->ctdb_version != CTDB_PROTOCOL) {
248 ctdb_set_error(ctdb, "Bad CTDB version 0x%x rejected in client\n", hdr->ctdb_version);
249 goto done;
252 switch (hdr->operation) {
253 case CTDB_REPLY_CALL:
254 ctdb_client_reply_call(ctdb, hdr);
255 break;
257 case CTDB_REQ_MESSAGE:
258 ctdb_request_message(ctdb, hdr);
259 break;
261 case CTDB_REPLY_CONTROL:
262 ctdb_client_reply_control(ctdb, hdr);
263 break;
265 default:
266 DEBUG(DEBUG_CRIT,("bogus operation code:%u\n",hdr->operation));
269 done:
270 talloc_free(tmp_ctx);
274 connect to a unix domain socket
276 int ctdb_socket_connect(struct ctdb_context *ctdb)
278 struct sockaddr_un addr;
279 int ret;
281 memset(&addr, 0, sizeof(addr));
282 addr.sun_family = AF_UNIX;
283 strncpy(addr.sun_path, ctdb->daemon.name, sizeof(addr.sun_path)-1);
285 ctdb->daemon.sd = socket(AF_UNIX, SOCK_STREAM, 0);
286 if (ctdb->daemon.sd == -1) {
287 DEBUG(DEBUG_ERR,(__location__ " Failed to open client socket. Errno:%s(%d)\n", strerror(errno), errno));
288 return -1;
291 if (connect(ctdb->daemon.sd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
292 DEBUG(DEBUG_ERR,
293 (__location__
294 "Failed to connect client socket to daemon (%s)\n",
295 strerror(errno)));
296 close(ctdb->daemon.sd);
297 ctdb->daemon.sd = -1;
298 return -1;
301 ret = set_blocking(ctdb->daemon.sd, false);
302 if (ret != 0) {
303 DEBUG(DEBUG_ERR,
304 (__location__
305 " failed to set socket non-blocking (%s)\n",
306 strerror(errno)));
307 close(ctdb->daemon.sd);
308 ctdb->daemon.sd = -1;
309 return -1;
312 set_close_on_exec(ctdb->daemon.sd);
314 ctdb->daemon.queue = ctdb_queue_setup(ctdb, ctdb, ctdb->daemon.sd,
315 CTDB_DS_ALIGNMENT,
316 ctdb_client_read_cb, ctdb, "to-ctdbd");
317 return 0;
321 struct ctdb_record_handle {
322 struct ctdb_db_context *ctdb_db;
323 TDB_DATA key;
324 TDB_DATA *data;
325 struct ctdb_ltdb_header header;
330 make a recv call to the local ctdb daemon - called from client context
332 This is called when the program wants to wait for a ctdb_call to complete and get the
333 results. This call will block unless the call has already completed.
335 int ctdb_call_recv(struct ctdb_client_call_state *state, struct ctdb_call *call)
337 if (state == NULL) {
338 return -1;
341 while (state->state < CTDB_CALL_DONE) {
342 tevent_loop_once(state->ctdb_db->ctdb->ev);
344 if (state->state != CTDB_CALL_DONE) {
345 DEBUG(DEBUG_ERR,(__location__ " ctdb_call_recv failed\n"));
346 talloc_free(state);
347 return -1;
350 if (state->call->reply_data.dsize) {
351 call->reply_data.dptr = talloc_memdup(state->ctdb_db,
352 state->call->reply_data.dptr,
353 state->call->reply_data.dsize);
354 call->reply_data.dsize = state->call->reply_data.dsize;
355 } else {
356 call->reply_data.dptr = NULL;
357 call->reply_data.dsize = 0;
359 call->status = state->call->status;
360 talloc_free(state);
362 return call->status;
369 destroy a ctdb_call in client
371 static int ctdb_client_call_destructor(struct ctdb_client_call_state *state)
373 reqid_remove(state->ctdb_db->ctdb->idr, state->reqid);
374 return 0;
378 construct an event driven local ctdb_call
380 this is used so that locally processed ctdb_call requests are processed
381 in an event driven manner
383 static struct ctdb_client_call_state *ctdb_client_call_local_send(struct ctdb_db_context *ctdb_db,
384 struct ctdb_call *call,
385 struct ctdb_ltdb_header *header,
386 TDB_DATA *data)
388 struct ctdb_client_call_state *state;
389 struct ctdb_context *ctdb = ctdb_db->ctdb;
390 int ret;
392 state = talloc_zero(ctdb_db, struct ctdb_client_call_state);
393 CTDB_NO_MEMORY_NULL(ctdb, state);
394 state->call = talloc_zero(state, struct ctdb_call);
395 CTDB_NO_MEMORY_NULL(ctdb, state->call);
397 talloc_steal(state, data->dptr);
399 state->state = CTDB_CALL_DONE;
400 *(state->call) = *call;
401 state->ctdb_db = ctdb_db;
403 ret = ctdb_call_local(ctdb_db, state->call, header, state, data, true);
404 if (ret != 0) {
405 DEBUG(DEBUG_DEBUG,("ctdb_call_local() failed, ignoring return code %d\n", ret));
408 return state;
412 make a ctdb call to the local daemon - async send. Called from client context.
414 This constructs a ctdb_call request and queues it for processing.
415 This call never blocks.
417 struct ctdb_client_call_state *ctdb_call_send(struct ctdb_db_context *ctdb_db,
418 struct ctdb_call *call)
420 struct ctdb_client_call_state *state;
421 struct ctdb_context *ctdb = ctdb_db->ctdb;
422 struct ctdb_ltdb_header header;
423 TDB_DATA data;
424 int ret;
425 size_t len;
426 struct ctdb_req_call_old *c;
428 /* if the domain socket is not yet open, open it */
429 if (ctdb->daemon.sd==-1) {
430 ctdb_socket_connect(ctdb);
433 ret = ctdb_ltdb_lock(ctdb_db, call->key);
434 if (ret != 0) {
435 DEBUG(DEBUG_ERR,(__location__ " Failed to get chainlock\n"));
436 return NULL;
439 ret = ctdb_ltdb_fetch(ctdb_db, call->key, &header, ctdb_db, &data);
441 if ((call->flags & CTDB_IMMEDIATE_MIGRATION) && (header.flags & CTDB_REC_RO_HAVE_DELEGATIONS)) {
442 ret = -1;
445 if (ret == 0 && header.dmaster == ctdb->pnn) {
446 state = ctdb_client_call_local_send(ctdb_db, call, &header, &data);
447 talloc_free(data.dptr);
448 ctdb_ltdb_unlock(ctdb_db, call->key);
449 return state;
452 ctdb_ltdb_unlock(ctdb_db, call->key);
453 talloc_free(data.dptr);
455 state = talloc_zero(ctdb_db, struct ctdb_client_call_state);
456 if (state == NULL) {
457 DEBUG(DEBUG_ERR, (__location__ " failed to allocate state\n"));
458 return NULL;
460 state->call = talloc_zero(state, struct ctdb_call);
461 if (state->call == NULL) {
462 DEBUG(DEBUG_ERR, (__location__ " failed to allocate state->call\n"));
463 return NULL;
466 len = offsetof(struct ctdb_req_call_old, data) + call->key.dsize + call->call_data.dsize;
467 c = ctdbd_allocate_pkt(ctdb, state, CTDB_REQ_CALL, len, struct ctdb_req_call_old);
468 if (c == NULL) {
469 DEBUG(DEBUG_ERR, (__location__ " failed to allocate packet\n"));
470 return NULL;
473 state->reqid = reqid_new(ctdb->idr, state);
474 state->ctdb_db = ctdb_db;
475 talloc_set_destructor(state, ctdb_client_call_destructor);
477 c->hdr.reqid = state->reqid;
478 c->flags = call->flags;
479 c->db_id = ctdb_db->db_id;
480 c->callid = call->call_id;
481 c->hopcount = 0;
482 c->keylen = call->key.dsize;
483 c->calldatalen = call->call_data.dsize;
484 memcpy(&c->data[0], call->key.dptr, call->key.dsize);
485 memcpy(&c->data[call->key.dsize],
486 call->call_data.dptr, call->call_data.dsize);
487 *(state->call) = *call;
488 state->call->call_data.dptr = &c->data[call->key.dsize];
489 state->call->key.dptr = &c->data[0];
491 state->state = CTDB_CALL_WAIT;
494 ctdb_client_queue_pkt(ctdb, &c->hdr);
496 return state;
501 full ctdb_call. Equivalent to a ctdb_call_send() followed by a ctdb_call_recv()
503 int ctdb_call(struct ctdb_db_context *ctdb_db, struct ctdb_call *call)
505 struct ctdb_client_call_state *state;
507 state = ctdb_call_send(ctdb_db, call);
508 return ctdb_call_recv(state, call);
513 tell the daemon what messaging srvid we will use, and register the message
514 handler function in the client
516 int ctdb_client_set_message_handler(struct ctdb_context *ctdb, uint64_t srvid,
517 srvid_handler_fn handler,
518 void *private_data)
520 int res;
521 int32_t status;
523 res = ctdb_control(ctdb, CTDB_CURRENT_NODE, srvid,
524 CTDB_CONTROL_REGISTER_SRVID, 0,
525 tdb_null, NULL, NULL, &status, NULL, NULL);
526 if (res != 0 || status != 0) {
527 DEBUG(DEBUG_ERR,
528 ("Failed to register srvid %llu\n",
529 (unsigned long long)srvid));
530 return -1;
533 /* also need to register the handler with our own ctdb structure */
534 return srvid_register(ctdb->srv, ctdb, srvid, handler, private_data);
538 tell the daemon we no longer want a srvid
540 int ctdb_client_remove_message_handler(struct ctdb_context *ctdb,
541 uint64_t srvid, void *private_data)
543 int res;
544 int32_t status;
546 res = ctdb_control(ctdb, CTDB_CURRENT_NODE, srvid,
547 CTDB_CONTROL_DEREGISTER_SRVID, 0,
548 tdb_null, NULL, NULL, &status, NULL, NULL);
549 if (res != 0 || status != 0) {
550 DEBUG(DEBUG_ERR,
551 ("Failed to deregister srvid %llu\n",
552 (unsigned long long)srvid));
553 return -1;
556 /* also need to register the handler with our own ctdb structure */
557 srvid_deregister(ctdb->srv, srvid, private_data);
558 return 0;
562 * check server ids
564 int ctdb_client_check_message_handlers(struct ctdb_context *ctdb, uint64_t *ids, uint32_t num,
565 uint8_t *result)
567 TDB_DATA indata, outdata;
568 int res;
569 int32_t status;
570 int i;
572 indata.dptr = (uint8_t *)ids;
573 indata.dsize = num * sizeof(*ids);
575 res = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_CHECK_SRVIDS, 0,
576 indata, ctdb, &outdata, &status, NULL, NULL);
577 if (res != 0 || status != 0) {
578 DEBUG(DEBUG_ERR, (__location__ " failed to check srvids\n"));
579 return -1;
582 if (outdata.dsize != num*sizeof(uint8_t)) {
583 DEBUG(DEBUG_ERR, (__location__ " expected %lu bytes, received %zi bytes\n",
584 (long unsigned int)num*sizeof(uint8_t),
585 outdata.dsize));
586 talloc_free(outdata.dptr);
587 return -1;
590 for (i=0; i<num; i++) {
591 result[i] = outdata.dptr[i];
594 talloc_free(outdata.dptr);
595 return 0;
599 send a message - from client context
601 int ctdb_client_send_message(struct ctdb_context *ctdb, uint32_t pnn,
602 uint64_t srvid, TDB_DATA data)
604 struct ctdb_req_message_old *r;
605 int len, res;
607 len = offsetof(struct ctdb_req_message_old, data) + data.dsize;
608 r = ctdbd_allocate_pkt(ctdb, ctdb, CTDB_REQ_MESSAGE,
609 len, struct ctdb_req_message_old);
610 CTDB_NO_MEMORY(ctdb, r);
612 r->hdr.destnode = pnn;
613 r->srvid = srvid;
614 r->datalen = data.dsize;
615 memcpy(&r->data[0], data.dptr, data.dsize);
617 res = ctdb_client_queue_pkt(ctdb, &r->hdr);
618 talloc_free(r);
619 return res;
624 cancel a ctdb_fetch_lock operation, releasing the lock
626 static int fetch_lock_destructor(struct ctdb_record_handle *h)
628 ctdb_ltdb_unlock(h->ctdb_db, h->key);
629 return 0;
633 force the migration of a record to this node
635 static int ctdb_client_force_migration(struct ctdb_db_context *ctdb_db, TDB_DATA key)
637 struct ctdb_call call;
638 ZERO_STRUCT(call);
639 call.call_id = CTDB_NULL_FUNC;
640 call.key = key;
641 call.flags = CTDB_IMMEDIATE_MIGRATION;
642 return ctdb_call(ctdb_db, &call);
646 try to fetch a readonly copy of a record
648 static int
649 ctdb_client_fetch_readonly(struct ctdb_db_context *ctdb_db, TDB_DATA key, TALLOC_CTX *mem_ctx, struct ctdb_ltdb_header **hdr, TDB_DATA *data)
651 int ret;
653 struct ctdb_call call;
654 ZERO_STRUCT(call);
656 call.call_id = CTDB_FETCH_WITH_HEADER_FUNC;
657 call.call_data.dptr = NULL;
658 call.call_data.dsize = 0;
659 call.key = key;
660 call.flags = CTDB_WANT_READONLY;
661 ret = ctdb_call(ctdb_db, &call);
663 if (ret != 0) {
664 return -1;
666 if (call.reply_data.dsize < sizeof(struct ctdb_ltdb_header)) {
667 return -1;
670 *hdr = talloc_memdup(mem_ctx, &call.reply_data.dptr[0], sizeof(struct ctdb_ltdb_header));
671 if (*hdr == NULL) {
672 talloc_free(call.reply_data.dptr);
673 return -1;
676 data->dsize = call.reply_data.dsize - sizeof(struct ctdb_ltdb_header);
677 data->dptr = talloc_memdup(mem_ctx, &call.reply_data.dptr[sizeof(struct ctdb_ltdb_header)], data->dsize);
678 if (data->dptr == NULL) {
679 talloc_free(call.reply_data.dptr);
680 talloc_free(hdr);
681 return -1;
684 return 0;
688 get a lock on a record, and return the records data. Blocks until it gets the lock
690 struct ctdb_record_handle *ctdb_fetch_lock(struct ctdb_db_context *ctdb_db, TALLOC_CTX *mem_ctx,
691 TDB_DATA key, TDB_DATA *data)
693 int ret;
694 struct ctdb_record_handle *h;
697 procedure is as follows:
699 1) get the chain lock.
700 2) check if we are dmaster
701 3) if we are the dmaster then return handle
702 4) if not dmaster then ask ctdb daemon to make us dmaster, and wait for
703 reply from ctdbd
704 5) when we get the reply, goto (1)
707 h = talloc_zero(mem_ctx, struct ctdb_record_handle);
708 if (h == NULL) {
709 return NULL;
712 h->ctdb_db = ctdb_db;
713 h->key = key;
714 h->key.dptr = talloc_memdup(h, key.dptr, key.dsize);
715 if (h->key.dptr == NULL) {
716 talloc_free(h);
717 return NULL;
719 h->data = data;
721 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: key=%*.*s\n", (int)key.dsize, (int)key.dsize,
722 (const char *)key.dptr));
724 again:
725 /* step 1 - get the chain lock */
726 ret = ctdb_ltdb_lock(ctdb_db, key);
727 if (ret != 0) {
728 DEBUG(DEBUG_ERR, (__location__ " failed to lock ltdb record\n"));
729 talloc_free(h);
730 return NULL;
733 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: got chain lock\n"));
735 talloc_set_destructor(h, fetch_lock_destructor);
737 ret = ctdb_ltdb_fetch(ctdb_db, key, &h->header, h, data);
739 /* when torturing, ensure we test the remote path */
740 if ((ctdb_db->ctdb->flags & CTDB_FLAG_TORTURE) &&
741 random() % 5 == 0) {
742 h->header.dmaster = (uint32_t)-1;
746 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: done local fetch\n"));
748 if (ret != 0 || h->header.dmaster != ctdb_db->ctdb->pnn) {
749 ctdb_ltdb_unlock(ctdb_db, key);
750 ret = ctdb_client_force_migration(ctdb_db, key);
751 if (ret != 0) {
752 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: force_migration failed\n"));
753 talloc_free(h);
754 return NULL;
756 goto again;
759 /* if this is a request for read/write and we have delegations
760 we have to revoke all delegations first
762 if ((h->header.dmaster == ctdb_db->ctdb->pnn) &&
763 (h->header.flags & CTDB_REC_RO_HAVE_DELEGATIONS)) {
764 ctdb_ltdb_unlock(ctdb_db, key);
765 ret = ctdb_client_force_migration(ctdb_db, key);
766 if (ret != 0) {
767 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
768 talloc_free(h);
769 return NULL;
771 goto again;
774 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: we are dmaster - done\n"));
775 return h;
779 get a readonly lock on a record, and return the records data. Blocks until it gets the lock
781 struct ctdb_record_handle *
782 ctdb_fetch_readonly_lock(
783 struct ctdb_db_context *ctdb_db, TALLOC_CTX *mem_ctx,
784 TDB_DATA key, TDB_DATA *data,
785 int read_only)
787 int ret;
788 struct ctdb_record_handle *h;
789 struct ctdb_ltdb_header *roheader = NULL;
791 h = talloc_zero(mem_ctx, struct ctdb_record_handle);
792 if (h == NULL) {
793 return NULL;
796 h->ctdb_db = ctdb_db;
797 h->key = key;
798 h->key.dptr = talloc_memdup(h, key.dptr, key.dsize);
799 if (h->key.dptr == NULL) {
800 talloc_free(h);
801 return NULL;
803 h->data = data;
805 data->dptr = NULL;
806 data->dsize = 0;
809 again:
810 talloc_free(roheader);
811 roheader = NULL;
813 talloc_free(data->dptr);
814 data->dptr = NULL;
815 data->dsize = 0;
817 /* Lock the record/chain */
818 ret = ctdb_ltdb_lock(ctdb_db, key);
819 if (ret != 0) {
820 DEBUG(DEBUG_ERR, (__location__ " failed to lock ltdb record\n"));
821 talloc_free(h);
822 return NULL;
825 talloc_set_destructor(h, fetch_lock_destructor);
827 /* Check if record exists yet in the TDB */
828 ret = ctdb_ltdb_fetch_with_header(ctdb_db, key, &h->header, h, data);
829 if (ret != 0) {
830 ctdb_ltdb_unlock(ctdb_db, key);
831 ret = ctdb_client_force_migration(ctdb_db, key);
832 if (ret != 0) {
833 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
834 talloc_free(h);
835 return NULL;
837 goto again;
840 /* if this is a request for read/write and we have delegations
841 we have to revoke all delegations first
843 if ((read_only == 0)
844 && (h->header.dmaster == ctdb_db->ctdb->pnn)
845 && (h->header.flags & CTDB_REC_RO_HAVE_DELEGATIONS)) {
846 ctdb_ltdb_unlock(ctdb_db, key);
847 ret = ctdb_client_force_migration(ctdb_db, key);
848 if (ret != 0) {
849 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
850 talloc_free(h);
851 return NULL;
853 goto again;
856 /* if we are dmaster, just return the handle */
857 if (h->header.dmaster == ctdb_db->ctdb->pnn) {
858 return h;
861 if (read_only != 0) {
862 TDB_DATA rodata = {NULL, 0};
864 if ((h->header.flags & CTDB_REC_RO_HAVE_READONLY)
865 || (h->header.flags & CTDB_REC_RO_HAVE_DELEGATIONS)) {
866 return h;
869 ctdb_ltdb_unlock(ctdb_db, key);
870 ret = ctdb_client_fetch_readonly(ctdb_db, key, h, &roheader, &rodata);
871 if (ret != 0) {
872 DEBUG(DEBUG_ERR,("ctdb_fetch_readonly_lock: failed. force migration and try again\n"));
873 ret = ctdb_client_force_migration(ctdb_db, key);
874 if (ret != 0) {
875 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
876 talloc_free(h);
877 return NULL;
880 goto again;
883 if (!(roheader->flags&CTDB_REC_RO_HAVE_READONLY)) {
884 ret = ctdb_client_force_migration(ctdb_db, key);
885 if (ret != 0) {
886 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
887 talloc_free(h);
888 return NULL;
891 goto again;
894 ret = ctdb_ltdb_lock(ctdb_db, key);
895 if (ret != 0) {
896 DEBUG(DEBUG_ERR, (__location__ " failed to lock ltdb record\n"));
897 talloc_free(h);
898 return NULL;
901 ret = ctdb_ltdb_fetch_with_header(ctdb_db, key, &h->header, h, data);
902 if (ret != 0) {
903 ctdb_ltdb_unlock(ctdb_db, key);
905 ret = ctdb_client_force_migration(ctdb_db, key);
906 if (ret != 0) {
907 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
908 talloc_free(h);
909 return NULL;
912 goto again;
915 return h;
918 /* we are not dmaster and this was not a request for a readonly lock
919 * so unlock the record, migrate it and try again
921 ctdb_ltdb_unlock(ctdb_db, key);
922 ret = ctdb_client_force_migration(ctdb_db, key);
923 if (ret != 0) {
924 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: force_migration failed\n"));
925 talloc_free(h);
926 return NULL;
928 goto again;
932 store some data to the record that was locked with ctdb_fetch_lock()
934 int ctdb_record_store(struct ctdb_record_handle *h, TDB_DATA data)
936 if (h->ctdb_db->persistent) {
937 DEBUG(DEBUG_ERR, (__location__ " ctdb_record_store prohibited for persistent dbs\n"));
938 return -1;
941 return ctdb_ltdb_store(h->ctdb_db, h->key, &h->header, data);
945 non-locking fetch of a record
947 int ctdb_fetch(struct ctdb_db_context *ctdb_db, TALLOC_CTX *mem_ctx,
948 TDB_DATA key, TDB_DATA *data)
950 struct ctdb_call call;
951 int ret;
953 call.call_id = CTDB_FETCH_FUNC;
954 call.call_data.dptr = NULL;
955 call.call_data.dsize = 0;
956 call.key = key;
958 ret = ctdb_call(ctdb_db, &call);
960 if (ret == 0) {
961 *data = call.reply_data;
962 talloc_steal(mem_ctx, data->dptr);
965 return ret;
971 called when a control completes or timesout to invoke the callback
972 function the user provided
974 static void invoke_control_callback(struct tevent_context *ev,
975 struct tevent_timer *te,
976 struct timeval t, void *private_data)
978 struct ctdb_client_control_state *state;
979 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
980 int ret;
982 state = talloc_get_type(private_data, struct ctdb_client_control_state);
983 talloc_steal(tmp_ctx, state);
985 ret = ctdb_control_recv(state->ctdb, state, state,
986 NULL,
987 NULL,
988 NULL);
989 if (ret != 0) {
990 DEBUG(DEBUG_DEBUG,("ctdb_control_recv() failed, ignoring return code %d\n", ret));
993 talloc_free(tmp_ctx);
997 called when a CTDB_REPLY_CONTROL packet comes in in the client
999 This packet comes in response to a CTDB_REQ_CONTROL request packet. It
1000 contains any reply data from the control
1002 static void ctdb_client_reply_control(struct ctdb_context *ctdb,
1003 struct ctdb_req_header *hdr)
1005 struct ctdb_reply_control_old *c = (struct ctdb_reply_control_old *)hdr;
1006 struct ctdb_client_control_state *state;
1008 state = reqid_find(ctdb->idr, hdr->reqid, struct ctdb_client_control_state);
1009 if (state == NULL) {
1010 DEBUG(DEBUG_ERR,(__location__ " reqid %u not found\n", hdr->reqid));
1011 return;
1014 if (hdr->reqid != state->reqid) {
1015 /* we found a record but it was the wrong one */
1016 DEBUG(DEBUG_ERR, ("Dropped orphaned reply control with reqid:%u\n",hdr->reqid));
1017 return;
1020 state->outdata.dptr = c->data;
1021 state->outdata.dsize = c->datalen;
1022 state->status = c->status;
1023 if (c->errorlen) {
1024 state->errormsg = talloc_strndup(state,
1025 (char *)&c->data[c->datalen],
1026 c->errorlen);
1029 /* state->outdata now uses resources from c so we don't want c
1030 to just dissappear from under us while state is still alive
1032 talloc_steal(state, c);
1034 state->state = CTDB_CONTROL_DONE;
1036 /* if we had a callback registered for this control, pull the response
1037 and call the callback.
1039 if (state->async.fn) {
1040 tevent_add_timer(ctdb->ev, state, timeval_zero(),
1041 invoke_control_callback, state);
1047 destroy a ctdb_control in client
1049 static int ctdb_client_control_destructor(struct ctdb_client_control_state *state)
1051 reqid_remove(state->ctdb->idr, state->reqid);
1052 return 0;
1056 /* time out handler for ctdb_control */
1057 static void control_timeout_func(struct tevent_context *ev,
1058 struct tevent_timer *te,
1059 struct timeval t, void *private_data)
1061 struct ctdb_client_control_state *state = talloc_get_type(private_data, struct ctdb_client_control_state);
1063 DEBUG(DEBUG_ERR,(__location__ " control timed out. reqid:%u opcode:%u "
1064 "dstnode:%u\n", state->reqid, state->c->opcode,
1065 state->c->hdr.destnode));
1067 state->state = CTDB_CONTROL_TIMEOUT;
1069 /* if we had a callback registered for this control, pull the response
1070 and call the callback.
1072 if (state->async.fn) {
1073 tevent_add_timer(state->ctdb->ev, state, timeval_zero(),
1074 invoke_control_callback, state);
1078 /* async version of send control request */
1079 struct ctdb_client_control_state *ctdb_control_send(struct ctdb_context *ctdb,
1080 uint32_t destnode, uint64_t srvid,
1081 uint32_t opcode, uint32_t flags, TDB_DATA data,
1082 TALLOC_CTX *mem_ctx,
1083 struct timeval *timeout,
1084 char **errormsg)
1086 struct ctdb_client_control_state *state;
1087 size_t len;
1088 struct ctdb_req_control_old *c;
1089 int ret;
1091 if (errormsg) {
1092 *errormsg = NULL;
1095 /* if the domain socket is not yet open, open it */
1096 if (ctdb->daemon.sd==-1) {
1097 ctdb_socket_connect(ctdb);
1100 state = talloc_zero(mem_ctx, struct ctdb_client_control_state);
1101 CTDB_NO_MEMORY_NULL(ctdb, state);
1103 state->ctdb = ctdb;
1104 state->reqid = reqid_new(ctdb->idr, state);
1105 state->state = CTDB_CONTROL_WAIT;
1106 state->errormsg = NULL;
1108 talloc_set_destructor(state, ctdb_client_control_destructor);
1110 len = offsetof(struct ctdb_req_control_old, data) + data.dsize;
1111 c = ctdbd_allocate_pkt(ctdb, state, CTDB_REQ_CONTROL,
1112 len, struct ctdb_req_control_old);
1113 state->c = c;
1114 CTDB_NO_MEMORY_NULL(ctdb, c);
1115 c->hdr.reqid = state->reqid;
1116 c->hdr.destnode = destnode;
1117 c->opcode = opcode;
1118 c->client_id = 0;
1119 c->flags = flags;
1120 c->srvid = srvid;
1121 c->datalen = data.dsize;
1122 if (data.dsize) {
1123 memcpy(&c->data[0], data.dptr, data.dsize);
1126 /* timeout */
1127 if (timeout && !timeval_is_zero(timeout)) {
1128 tevent_add_timer(ctdb->ev, state, *timeout,
1129 control_timeout_func, state);
1132 ret = ctdb_client_queue_pkt(ctdb, &(c->hdr));
1133 if (ret != 0) {
1134 talloc_free(state);
1135 return NULL;
1138 if (flags & CTDB_CTRL_FLAG_NOREPLY) {
1139 talloc_free(state);
1140 return NULL;
1143 return state;
1147 /* async version of receive control reply */
1148 int ctdb_control_recv(struct ctdb_context *ctdb,
1149 struct ctdb_client_control_state *state,
1150 TALLOC_CTX *mem_ctx,
1151 TDB_DATA *outdata, int32_t *status, char **errormsg)
1153 TALLOC_CTX *tmp_ctx;
1155 if (status != NULL) {
1156 *status = -1;
1158 if (errormsg != NULL) {
1159 *errormsg = NULL;
1162 if (state == NULL) {
1163 return -1;
1166 /* prevent double free of state */
1167 tmp_ctx = talloc_new(ctdb);
1168 talloc_steal(tmp_ctx, state);
1170 /* loop one event at a time until we either timeout or the control
1171 completes.
1173 while (state->state == CTDB_CONTROL_WAIT) {
1174 tevent_loop_once(ctdb->ev);
1177 if (state->state != CTDB_CONTROL_DONE) {
1178 DEBUG(DEBUG_ERR,(__location__ " ctdb_control_recv failed\n"));
1179 if (state->async.fn) {
1180 state->async.fn(state);
1182 talloc_free(tmp_ctx);
1183 return -1;
1186 if (state->errormsg) {
1187 int s = (state->status == 0 ? -1 : state->status);
1188 DEBUG(DEBUG_ERR,("ctdb_control error: '%s'\n", state->errormsg));
1189 if (errormsg) {
1190 (*errormsg) = talloc_move(mem_ctx, &state->errormsg);
1192 if (state->async.fn) {
1193 state->async.fn(state);
1195 talloc_free(tmp_ctx);
1196 return s;
1199 if (outdata) {
1200 *outdata = state->outdata;
1201 outdata->dptr = talloc_memdup(mem_ctx, outdata->dptr, outdata->dsize);
1204 if (status) {
1205 *status = state->status;
1208 if (state->async.fn) {
1209 state->async.fn(state);
1212 talloc_free(tmp_ctx);
1213 return 0;
1219 send a ctdb control message
1220 timeout specifies how long we should wait for a reply.
1221 if timeout is NULL we wait indefinitely
1223 int ctdb_control(struct ctdb_context *ctdb, uint32_t destnode, uint64_t srvid,
1224 uint32_t opcode, uint32_t flags, TDB_DATA data,
1225 TALLOC_CTX *mem_ctx, TDB_DATA *outdata, int32_t *status,
1226 struct timeval *timeout,
1227 char **errormsg)
1229 struct ctdb_client_control_state *state;
1231 state = ctdb_control_send(ctdb, destnode, srvid, opcode,
1232 flags, data, mem_ctx,
1233 timeout, errormsg);
1235 /* FIXME: Error conditions in ctdb_control_send return NULL without
1236 * setting errormsg. So, there is no way to distinguish between sucess
1237 * and failure when CTDB_CTRL_FLAG_NOREPLY is set */
1238 if (flags & CTDB_CTRL_FLAG_NOREPLY) {
1239 if (status != NULL) {
1240 *status = 0;
1242 return 0;
1245 return ctdb_control_recv(ctdb, state, mem_ctx, outdata, status,
1246 errormsg);
1253 a process exists call. Returns 0 if process exists, -1 otherwise
1255 int ctdb_ctrl_process_exists(struct ctdb_context *ctdb, uint32_t destnode, pid_t pid)
1257 int ret;
1258 TDB_DATA data;
1259 int32_t status;
1261 data.dptr = (uint8_t*)&pid;
1262 data.dsize = sizeof(pid);
1264 ret = ctdb_control(ctdb, destnode, 0,
1265 CTDB_CONTROL_PROCESS_EXISTS, 0, data,
1266 NULL, NULL, &status, NULL, NULL);
1267 if (ret != 0) {
1268 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for process_exists failed\n"));
1269 return -1;
1272 return status;
1276 get remote statistics
1278 int ctdb_ctrl_statistics(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_statistics *status)
1280 int ret;
1281 TDB_DATA data;
1282 int32_t res;
1284 ret = ctdb_control(ctdb, destnode, 0,
1285 CTDB_CONTROL_STATISTICS, 0, tdb_null,
1286 ctdb, &data, &res, NULL, NULL);
1287 if (ret != 0 || res != 0) {
1288 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for statistics failed\n"));
1289 return -1;
1292 if (data.dsize != sizeof(struct ctdb_statistics)) {
1293 DEBUG(DEBUG_ERR,(__location__ " Wrong statistics size %u - expected %u\n",
1294 (unsigned)data.dsize, (unsigned)sizeof(struct ctdb_statistics)));
1295 return -1;
1298 *status = *(struct ctdb_statistics *)data.dptr;
1299 talloc_free(data.dptr);
1301 return 0;
1305 * get db statistics
1307 int ctdb_ctrl_dbstatistics(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid,
1308 TALLOC_CTX *mem_ctx, struct ctdb_db_statistics_old **dbstat)
1310 int ret;
1311 TDB_DATA indata, outdata;
1312 int32_t res;
1313 struct ctdb_db_statistics_old *wire, *s;
1314 char *ptr;
1315 int i;
1317 indata.dptr = (uint8_t *)&dbid;
1318 indata.dsize = sizeof(dbid);
1320 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_DB_STATISTICS,
1321 0, indata, ctdb, &outdata, &res, NULL, NULL);
1322 if (ret != 0 || res != 0) {
1323 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for dbstatistics failed\n"));
1324 return -1;
1327 if (outdata.dsize < offsetof(struct ctdb_db_statistics_old, hot_keys_wire)) {
1328 DEBUG(DEBUG_ERR,(__location__ " Wrong dbstatistics size %zi - expected >= %lu\n",
1329 outdata.dsize,
1330 (long unsigned int)sizeof(struct ctdb_statistics)));
1331 return -1;
1334 s = talloc_zero(mem_ctx, struct ctdb_db_statistics_old);
1335 if (s == NULL) {
1336 talloc_free(outdata.dptr);
1337 CTDB_NO_MEMORY(ctdb, s);
1340 wire = (struct ctdb_db_statistics_old *)outdata.dptr;
1341 memcpy(s, wire, offsetof(struct ctdb_db_statistics_old, hot_keys_wire));
1342 ptr = &wire->hot_keys_wire[0];
1343 for (i=0; i<wire->num_hot_keys; i++) {
1344 s->hot_keys[i].key.dptr = talloc_size(mem_ctx, s->hot_keys[i].key.dsize);
1345 if (s->hot_keys[i].key.dptr == NULL) {
1346 talloc_free(outdata.dptr);
1347 CTDB_NO_MEMORY(ctdb, s->hot_keys[i].key.dptr);
1350 memcpy(s->hot_keys[i].key.dptr, ptr, s->hot_keys[i].key.dsize);
1351 ptr += wire->hot_keys[i].key.dsize;
1354 talloc_free(outdata.dptr);
1355 *dbstat = s;
1356 return 0;
1360 shutdown a remote ctdb node
1362 int ctdb_ctrl_shutdown(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
1364 struct ctdb_client_control_state *state;
1366 state = ctdb_control_send(ctdb, destnode, 0,
1367 CTDB_CONTROL_SHUTDOWN, 0, tdb_null,
1368 NULL, &timeout, NULL);
1369 if (state == NULL) {
1370 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for shutdown failed\n"));
1371 return -1;
1374 return 0;
1378 get vnn map from a remote node
1380 int ctdb_ctrl_getvnnmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_vnn_map **vnnmap)
1382 int ret;
1383 TDB_DATA outdata;
1384 int32_t res;
1385 struct ctdb_vnn_map_wire *map;
1387 ret = ctdb_control(ctdb, destnode, 0,
1388 CTDB_CONTROL_GETVNNMAP, 0, tdb_null,
1389 mem_ctx, &outdata, &res, &timeout, NULL);
1390 if (ret != 0 || res != 0) {
1391 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getvnnmap failed\n"));
1392 return -1;
1395 map = (struct ctdb_vnn_map_wire *)outdata.dptr;
1396 if (outdata.dsize < offsetof(struct ctdb_vnn_map_wire, map) ||
1397 outdata.dsize != map->size*sizeof(uint32_t) + offsetof(struct ctdb_vnn_map_wire, map)) {
1398 DEBUG(DEBUG_ERR,("Bad vnn map size received in ctdb_ctrl_getvnnmap\n"));
1399 return -1;
1402 (*vnnmap) = talloc(mem_ctx, struct ctdb_vnn_map);
1403 CTDB_NO_MEMORY(ctdb, *vnnmap);
1404 (*vnnmap)->generation = map->generation;
1405 (*vnnmap)->size = map->size;
1406 (*vnnmap)->map = talloc_array(*vnnmap, uint32_t, map->size);
1408 CTDB_NO_MEMORY(ctdb, (*vnnmap)->map);
1409 memcpy((*vnnmap)->map, map->map, sizeof(uint32_t)*map->size);
1410 talloc_free(outdata.dptr);
1412 return 0;
1417 get the recovery mode of a remote node
1419 struct ctdb_client_control_state *
1420 ctdb_ctrl_getrecmode_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode)
1422 return ctdb_control_send(ctdb, destnode, 0,
1423 CTDB_CONTROL_GET_RECMODE, 0, tdb_null,
1424 mem_ctx, &timeout, NULL);
1427 int ctdb_ctrl_getrecmode_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *recmode)
1429 int ret;
1430 int32_t res;
1432 ret = ctdb_control_recv(ctdb, state, mem_ctx, NULL, &res, NULL);
1433 if (ret != 0) {
1434 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_getrecmode_recv failed\n"));
1435 return -1;
1438 if (recmode) {
1439 *recmode = (uint32_t)res;
1442 return 0;
1445 int ctdb_ctrl_getrecmode(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, uint32_t *recmode)
1447 struct ctdb_client_control_state *state;
1449 state = ctdb_ctrl_getrecmode_send(ctdb, mem_ctx, timeout, destnode);
1450 return ctdb_ctrl_getrecmode_recv(ctdb, mem_ctx, state, recmode);
1457 set the recovery mode of a remote node
1459 int ctdb_ctrl_setrecmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmode)
1461 int ret;
1462 TDB_DATA data;
1463 int32_t res;
1465 data.dsize = sizeof(uint32_t);
1466 data.dptr = (unsigned char *)&recmode;
1468 ret = ctdb_control(ctdb, destnode, 0,
1469 CTDB_CONTROL_SET_RECMODE, 0, data,
1470 NULL, NULL, &res, &timeout, NULL);
1471 if (ret != 0 || res != 0) {
1472 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setrecmode failed\n"));
1473 return -1;
1476 return 0;
1482 get the recovery master of a remote node
1484 struct ctdb_client_control_state *
1485 ctdb_ctrl_getrecmaster_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx,
1486 struct timeval timeout, uint32_t destnode)
1488 return ctdb_control_send(ctdb, destnode, 0,
1489 CTDB_CONTROL_GET_RECMASTER, 0, tdb_null,
1490 mem_ctx, &timeout, NULL);
1493 int ctdb_ctrl_getrecmaster_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *recmaster)
1495 int ret;
1496 int32_t res;
1498 ret = ctdb_control_recv(ctdb, state, mem_ctx, NULL, &res, NULL);
1499 if (ret != 0) {
1500 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_getrecmaster_recv failed\n"));
1501 return -1;
1504 if (recmaster) {
1505 *recmaster = (uint32_t)res;
1508 return 0;
1511 int ctdb_ctrl_getrecmaster(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, uint32_t *recmaster)
1513 struct ctdb_client_control_state *state;
1515 state = ctdb_ctrl_getrecmaster_send(ctdb, mem_ctx, timeout, destnode);
1516 return ctdb_ctrl_getrecmaster_recv(ctdb, mem_ctx, state, recmaster);
1521 set the recovery master of a remote node
1523 int ctdb_ctrl_setrecmaster(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmaster)
1525 int ret;
1526 TDB_DATA data;
1527 int32_t res;
1529 ZERO_STRUCT(data);
1530 data.dsize = sizeof(uint32_t);
1531 data.dptr = (unsigned char *)&recmaster;
1533 ret = ctdb_control(ctdb, destnode, 0,
1534 CTDB_CONTROL_SET_RECMASTER, 0, data,
1535 NULL, NULL, &res, &timeout, NULL);
1536 if (ret != 0 || res != 0) {
1537 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setrecmaster failed\n"));
1538 return -1;
1541 return 0;
1546 get a list of databases off a remote node
1548 int ctdb_ctrl_getdbmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
1549 TALLOC_CTX *mem_ctx, struct ctdb_dbid_map_old **dbmap)
1551 int ret;
1552 TDB_DATA outdata;
1553 int32_t res;
1555 ret = ctdb_control(ctdb, destnode, 0,
1556 CTDB_CONTROL_GET_DBMAP, 0, tdb_null,
1557 mem_ctx, &outdata, &res, &timeout, NULL);
1558 if (ret != 0 || res != 0) {
1559 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getdbmap failed ret:%d res:%d\n", ret, res));
1560 return -1;
1563 *dbmap = (struct ctdb_dbid_map_old *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
1564 talloc_free(outdata.dptr);
1566 return 0;
1570 get a list of nodes (vnn and flags ) from a remote node
1572 int ctdb_ctrl_getnodemap(struct ctdb_context *ctdb,
1573 struct timeval timeout, uint32_t destnode,
1574 TALLOC_CTX *mem_ctx, struct ctdb_node_map_old **nodemap)
1576 int ret;
1577 TDB_DATA outdata;
1578 int32_t res;
1580 ret = ctdb_control(ctdb, destnode, 0,
1581 CTDB_CONTROL_GET_NODEMAP, 0, tdb_null,
1582 mem_ctx, &outdata, &res, &timeout, NULL);
1583 if (ret != 0 || res != 0 || outdata.dsize == 0) {
1584 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getnodes failed ret:%d res:%d\n", ret, res));
1585 return -1;
1588 *nodemap = (struct ctdb_node_map_old *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
1589 talloc_free(outdata.dptr);
1590 return 0;
1594 load nodes file on a remote node and return as a node map
1596 int ctdb_ctrl_getnodesfile(struct ctdb_context *ctdb,
1597 struct timeval timeout, uint32_t destnode,
1598 TALLOC_CTX *mem_ctx, struct ctdb_node_map_old **nodemap)
1600 int ret;
1601 TDB_DATA outdata;
1602 int32_t res;
1604 ret = ctdb_control(ctdb, destnode, 0,
1605 CTDB_CONTROL_GET_NODES_FILE, 0, tdb_null,
1606 mem_ctx, &outdata, &res, &timeout, NULL);
1607 if (ret != 0 || res != 0 || outdata.dsize == 0) {
1608 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getnodes failed ret:%d res:%d\n", ret, res));
1609 return -1;
1612 *nodemap = (struct ctdb_node_map_old *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
1613 talloc_free(outdata.dptr);
1615 return 0;
1619 drop the transport, reload the nodes file and restart the transport
1621 int ctdb_ctrl_reload_nodes_file(struct ctdb_context *ctdb,
1622 struct timeval timeout, uint32_t destnode)
1624 int ret;
1625 int32_t res;
1627 ret = ctdb_control(ctdb, destnode, 0,
1628 CTDB_CONTROL_RELOAD_NODES_FILE, 0, tdb_null,
1629 NULL, NULL, &res, &timeout, NULL);
1630 if (ret != 0 || res != 0) {
1631 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for reloadnodesfile failed\n"));
1632 return -1;
1635 return 0;
1640 set vnn map on a node
1642 int ctdb_ctrl_setvnnmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
1643 TALLOC_CTX *mem_ctx, struct ctdb_vnn_map *vnnmap)
1645 int ret;
1646 TDB_DATA data;
1647 int32_t res;
1648 struct ctdb_vnn_map_wire *map;
1649 size_t len;
1651 len = offsetof(struct ctdb_vnn_map_wire, map) + sizeof(uint32_t)*vnnmap->size;
1652 map = talloc_size(mem_ctx, len);
1653 CTDB_NO_MEMORY(ctdb, map);
1655 map->generation = vnnmap->generation;
1656 map->size = vnnmap->size;
1657 memcpy(map->map, vnnmap->map, sizeof(uint32_t)*map->size);
1659 data.dsize = len;
1660 data.dptr = (uint8_t *)map;
1662 ret = ctdb_control(ctdb, destnode, 0,
1663 CTDB_CONTROL_SETVNNMAP, 0, data,
1664 NULL, NULL, &res, &timeout, NULL);
1665 if (ret != 0 || res != 0) {
1666 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setvnnmap failed\n"));
1667 return -1;
1670 talloc_free(map);
1672 return 0;
1677 async send for pull database
1679 struct ctdb_client_control_state *ctdb_ctrl_pulldb_send(
1680 struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid,
1681 uint32_t lmaster, TALLOC_CTX *mem_ctx, struct timeval timeout)
1683 TDB_DATA indata;
1684 struct ctdb_pulldb *pull;
1685 struct ctdb_client_control_state *state;
1687 pull = talloc(mem_ctx, struct ctdb_pulldb);
1688 CTDB_NO_MEMORY_NULL(ctdb, pull);
1690 pull->db_id = dbid;
1691 pull->lmaster = lmaster;
1693 indata.dsize = sizeof(struct ctdb_pulldb);
1694 indata.dptr = (unsigned char *)pull;
1696 state = ctdb_control_send(ctdb, destnode, 0,
1697 CTDB_CONTROL_PULL_DB, 0, indata,
1698 mem_ctx, &timeout, NULL);
1699 talloc_free(pull);
1701 return state;
1705 async recv for pull database
1707 int ctdb_ctrl_pulldb_recv(
1708 struct ctdb_context *ctdb,
1709 TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state,
1710 TDB_DATA *outdata)
1712 int ret;
1713 int32_t res;
1715 ret = ctdb_control_recv(ctdb, state, mem_ctx, outdata, &res, NULL);
1716 if ( (ret != 0) || (res != 0) ){
1717 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_pulldb_recv failed\n"));
1718 return -1;
1721 return 0;
1725 pull all keys and records for a specific database on a node
1727 int ctdb_ctrl_pulldb(struct ctdb_context *ctdb, uint32_t destnode,
1728 uint32_t dbid, uint32_t lmaster,
1729 TALLOC_CTX *mem_ctx, struct timeval timeout,
1730 TDB_DATA *outdata)
1732 struct ctdb_client_control_state *state;
1734 state = ctdb_ctrl_pulldb_send(ctdb, destnode, dbid, lmaster, mem_ctx,
1735 timeout);
1737 return ctdb_ctrl_pulldb_recv(ctdb, mem_ctx, state, outdata);
1742 change dmaster for all keys in the database to the new value
1744 int ctdb_ctrl_setdmaster(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
1745 TALLOC_CTX *mem_ctx, uint32_t dbid, uint32_t dmaster)
1747 int ret;
1748 TDB_DATA indata;
1749 int32_t res;
1751 indata.dsize = 2*sizeof(uint32_t);
1752 indata.dptr = (unsigned char *)talloc_array(mem_ctx, uint32_t, 2);
1754 ((uint32_t *)(&indata.dptr[0]))[0] = dbid;
1755 ((uint32_t *)(&indata.dptr[0]))[1] = dmaster;
1757 ret = ctdb_control(ctdb, destnode, 0,
1758 CTDB_CONTROL_SET_DMASTER, 0, indata,
1759 NULL, NULL, &res, &timeout, NULL);
1760 if (ret != 0 || res != 0) {
1761 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setdmaster failed\n"));
1762 return -1;
1765 return 0;
1769 ping a node, return number of clients connected
1771 int ctdb_ctrl_ping(struct ctdb_context *ctdb, uint32_t destnode)
1773 int ret;
1774 int32_t res;
1776 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_PING, 0,
1777 tdb_null, NULL, NULL, &res, NULL, NULL);
1778 if (ret != 0) {
1779 return -1;
1781 return res;
1784 int ctdb_ctrl_get_runstate(struct ctdb_context *ctdb,
1785 struct timeval timeout,
1786 uint32_t destnode,
1787 uint32_t *runstate)
1789 TDB_DATA outdata;
1790 int32_t res;
1791 int ret;
1793 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_RUNSTATE, 0,
1794 tdb_null, ctdb, &outdata, &res, &timeout, NULL);
1795 if (ret != 0 || res != 0) {
1796 DEBUG(DEBUG_ERR,("ctdb_control for get_runstate failed\n"));
1797 return ret != 0 ? ret : res;
1800 if (outdata.dsize != sizeof(uint32_t)) {
1801 DEBUG(DEBUG_ERR,("Invalid return data in get_runstate\n"));
1802 talloc_free(outdata.dptr);
1803 return -1;
1806 if (runstate != NULL) {
1807 *runstate = *(uint32_t *)outdata.dptr;
1809 talloc_free(outdata.dptr);
1811 return 0;
1815 find the real path to a ltdb
1817 int ctdb_ctrl_getdbpath(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t dbid, TALLOC_CTX *mem_ctx,
1818 const char **path)
1820 int ret;
1821 int32_t res;
1822 TDB_DATA data;
1824 data.dptr = (uint8_t *)&dbid;
1825 data.dsize = sizeof(dbid);
1827 ret = ctdb_control(ctdb, destnode, 0,
1828 CTDB_CONTROL_GETDBPATH, 0, data,
1829 mem_ctx, &data, &res, &timeout, NULL);
1830 if (ret != 0 || res != 0) {
1831 return -1;
1834 (*path) = talloc_strndup(mem_ctx, (const char *)data.dptr, data.dsize);
1835 if ((*path) == NULL) {
1836 return -1;
1839 talloc_free(data.dptr);
1841 return 0;
1845 find the name of a db
1847 int ctdb_ctrl_getdbname(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t dbid, TALLOC_CTX *mem_ctx,
1848 const char **name)
1850 int ret;
1851 int32_t res;
1852 TDB_DATA data;
1854 data.dptr = (uint8_t *)&dbid;
1855 data.dsize = sizeof(dbid);
1857 ret = ctdb_control(ctdb, destnode, 0,
1858 CTDB_CONTROL_GET_DBNAME, 0, data,
1859 mem_ctx, &data, &res, &timeout, NULL);
1860 if (ret != 0 || res != 0) {
1861 return -1;
1864 (*name) = talloc_strndup(mem_ctx, (const char *)data.dptr, data.dsize);
1865 if ((*name) == NULL) {
1866 return -1;
1869 talloc_free(data.dptr);
1871 return 0;
1875 get the health status of a db
1877 int ctdb_ctrl_getdbhealth(struct ctdb_context *ctdb,
1878 struct timeval timeout,
1879 uint32_t destnode,
1880 uint32_t dbid, TALLOC_CTX *mem_ctx,
1881 const char **reason)
1883 int ret;
1884 int32_t res;
1885 TDB_DATA data;
1887 data.dptr = (uint8_t *)&dbid;
1888 data.dsize = sizeof(dbid);
1890 ret = ctdb_control(ctdb, destnode, 0,
1891 CTDB_CONTROL_DB_GET_HEALTH, 0, data,
1892 mem_ctx, &data, &res, &timeout, NULL);
1893 if (ret != 0 || res != 0) {
1894 return -1;
1897 if (data.dsize == 0) {
1898 (*reason) = NULL;
1899 return 0;
1902 (*reason) = talloc_strndup(mem_ctx, (const char *)data.dptr, data.dsize);
1903 if ((*reason) == NULL) {
1904 return -1;
1907 talloc_free(data.dptr);
1909 return 0;
1913 * get db sequence number
1915 int ctdb_ctrl_getdbseqnum(struct ctdb_context *ctdb, struct timeval timeout,
1916 uint32_t destnode, uint32_t dbid, uint64_t *seqnum)
1918 int ret;
1919 int32_t res;
1920 TDB_DATA data, outdata;
1922 data.dptr = (uint8_t *)&dbid;
1923 data.dsize = sizeof(uint64_t); /* This is just wrong */
1925 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_DB_SEQNUM,
1926 0, data, ctdb, &outdata, &res, &timeout, NULL);
1927 if (ret != 0 || res != 0) {
1928 DEBUG(DEBUG_ERR,("ctdb_control for getdbesqnum failed\n"));
1929 return -1;
1932 if (outdata.dsize != sizeof(uint64_t)) {
1933 DEBUG(DEBUG_ERR,("Invalid return data in get_dbseqnum\n"));
1934 talloc_free(outdata.dptr);
1935 return -1;
1938 if (seqnum != NULL) {
1939 *seqnum = *(uint64_t *)outdata.dptr;
1941 talloc_free(outdata.dptr);
1943 return 0;
1947 create a database
1949 int ctdb_ctrl_createdb(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
1950 TALLOC_CTX *mem_ctx, const char *name, bool persistent)
1952 int ret;
1953 int32_t res;
1954 TDB_DATA data;
1955 uint64_t tdb_flags = 0;
1957 data.dptr = discard_const(name);
1958 data.dsize = strlen(name)+1;
1960 /* Make sure that volatile databases use jenkins hash */
1961 if (!persistent) {
1962 tdb_flags = TDB_INCOMPATIBLE_HASH;
1965 #ifdef TDB_MUTEX_LOCKING
1966 if (!persistent && ctdb->tunable.mutex_enabled == 1) {
1967 tdb_flags |= (TDB_MUTEX_LOCKING | TDB_CLEAR_IF_FIRST);
1969 #endif
1971 ret = ctdb_control(ctdb, destnode, tdb_flags,
1972 persistent?CTDB_CONTROL_DB_ATTACH_PERSISTENT:CTDB_CONTROL_DB_ATTACH,
1973 0, data,
1974 mem_ctx, &data, &res, &timeout, NULL);
1976 if (ret != 0 || res != 0) {
1977 return -1;
1980 return 0;
1984 get debug level on a node
1986 int ctdb_ctrl_get_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, int32_t *level)
1988 int ret;
1989 int32_t res;
1990 TDB_DATA data;
1992 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_DEBUG, 0, tdb_null,
1993 ctdb, &data, &res, NULL, NULL);
1994 if (ret != 0 || res != 0) {
1995 return -1;
1997 if (data.dsize != sizeof(int32_t)) {
1998 DEBUG(DEBUG_ERR,("Bad control reply size in ctdb_get_debuglevel (got %u)\n",
1999 (unsigned)data.dsize));
2000 return -1;
2002 *level = *(int32_t *)data.dptr;
2003 talloc_free(data.dptr);
2004 return 0;
2008 set debug level on a node
2010 int ctdb_ctrl_set_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, int32_t level)
2012 int ret;
2013 int32_t res;
2014 TDB_DATA data;
2016 data.dptr = (uint8_t *)&level;
2017 data.dsize = sizeof(level);
2019 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SET_DEBUG, 0, data,
2020 NULL, NULL, &res, NULL, NULL);
2021 if (ret != 0 || res != 0) {
2022 return -1;
2024 return 0;
2029 get a list of connected nodes
2031 uint32_t *ctdb_get_connected_nodes(struct ctdb_context *ctdb,
2032 struct timeval timeout,
2033 TALLOC_CTX *mem_ctx,
2034 uint32_t *num_nodes)
2036 struct ctdb_node_map_old *map=NULL;
2037 int ret, i;
2038 uint32_t *nodes;
2040 *num_nodes = 0;
2042 ret = ctdb_ctrl_getnodemap(ctdb, timeout, CTDB_CURRENT_NODE, mem_ctx, &map);
2043 if (ret != 0) {
2044 return NULL;
2047 nodes = talloc_array(mem_ctx, uint32_t, map->num);
2048 if (nodes == NULL) {
2049 return NULL;
2052 for (i=0;i<map->num;i++) {
2053 if (!(map->nodes[i].flags & NODE_FLAGS_DISCONNECTED)) {
2054 nodes[*num_nodes] = map->nodes[i].pnn;
2055 (*num_nodes)++;
2059 return nodes;
2064 reset remote status
2066 int ctdb_statistics_reset(struct ctdb_context *ctdb, uint32_t destnode)
2068 int ret;
2069 int32_t res;
2071 ret = ctdb_control(ctdb, destnode, 0,
2072 CTDB_CONTROL_STATISTICS_RESET, 0, tdb_null,
2073 NULL, NULL, &res, NULL, NULL);
2074 if (ret != 0 || res != 0) {
2075 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for reset statistics failed\n"));
2076 return -1;
2078 return 0;
2082 attach to a specific database - client call
2084 struct ctdb_db_context *ctdb_attach(struct ctdb_context *ctdb,
2085 struct timeval timeout,
2086 const char *name,
2087 bool persistent,
2088 uint32_t tdb_flags)
2090 struct ctdb_db_context *ctdb_db;
2091 TDB_DATA data;
2092 int ret;
2093 int32_t res;
2094 #ifdef TDB_MUTEX_LOCKING
2095 uint32_t mutex_enabled = 0;
2096 #endif
2098 ctdb_db = ctdb_db_handle(ctdb, name);
2099 if (ctdb_db) {
2100 return ctdb_db;
2103 ctdb_db = talloc_zero(ctdb, struct ctdb_db_context);
2104 CTDB_NO_MEMORY_NULL(ctdb, ctdb_db);
2106 ctdb_db->ctdb = ctdb;
2107 ctdb_db->db_name = talloc_strdup(ctdb_db, name);
2108 CTDB_NO_MEMORY_NULL(ctdb, ctdb_db->db_name);
2110 data.dptr = discard_const(name);
2111 data.dsize = strlen(name)+1;
2113 /* CTDB has switched to using jenkins hash for volatile databases.
2114 * Even if tdb_flags do not explicitly mention TDB_INCOMPATIBLE_HASH,
2115 * always set it.
2117 if (!persistent) {
2118 tdb_flags |= TDB_INCOMPATIBLE_HASH;
2121 #ifdef TDB_MUTEX_LOCKING
2122 if (!persistent) {
2123 ret = ctdb_ctrl_get_tunable(ctdb, timeval_current_ofs(3,0),
2124 CTDB_CURRENT_NODE,
2125 "TDBMutexEnabled",
2126 &mutex_enabled);
2127 if (ret != 0) {
2128 DEBUG(DEBUG_WARNING, ("Assuming no mutex support.\n"));
2131 if (mutex_enabled == 1) {
2132 tdb_flags |= (TDB_MUTEX_LOCKING | TDB_CLEAR_IF_FIRST);
2135 #endif
2137 /* tell ctdb daemon to attach */
2138 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, tdb_flags,
2139 persistent?CTDB_CONTROL_DB_ATTACH_PERSISTENT:CTDB_CONTROL_DB_ATTACH,
2140 0, data, ctdb_db, &data, &res, NULL, NULL);
2141 if (ret != 0 || res != 0 || data.dsize != sizeof(uint32_t)) {
2142 DEBUG(DEBUG_ERR,("Failed to attach to database '%s'\n", name));
2143 talloc_free(ctdb_db);
2144 return NULL;
2147 ctdb_db->db_id = *(uint32_t *)data.dptr;
2148 talloc_free(data.dptr);
2150 ret = ctdb_ctrl_getdbpath(ctdb, timeout, CTDB_CURRENT_NODE, ctdb_db->db_id, ctdb_db, &ctdb_db->db_path);
2151 if (ret != 0) {
2152 DEBUG(DEBUG_ERR,("Failed to get dbpath for database '%s'\n", name));
2153 talloc_free(ctdb_db);
2154 return NULL;
2157 if (persistent) {
2158 tdb_flags = TDB_DEFAULT;
2159 } else {
2160 tdb_flags = TDB_NOSYNC;
2161 #ifdef TDB_MUTEX_LOCKING
2162 if (mutex_enabled) {
2163 tdb_flags |= (TDB_MUTEX_LOCKING | TDB_CLEAR_IF_FIRST);
2165 #endif
2167 if (ctdb->valgrinding) {
2168 tdb_flags |= TDB_NOMMAP;
2170 tdb_flags |= TDB_DISALLOW_NESTING;
2172 ctdb_db->ltdb = tdb_wrap_open(ctdb_db, ctdb_db->db_path, 0, tdb_flags,
2173 O_RDWR, 0);
2174 if (ctdb_db->ltdb == NULL) {
2175 ctdb_set_error(ctdb, "Failed to open tdb '%s'\n", ctdb_db->db_path);
2176 talloc_free(ctdb_db);
2177 return NULL;
2180 ctdb_db->persistent = persistent;
2182 DLIST_ADD(ctdb->db_list, ctdb_db);
2184 /* add well known functions */
2185 ctdb_set_call(ctdb_db, ctdb_null_func, CTDB_NULL_FUNC);
2186 ctdb_set_call(ctdb_db, ctdb_fetch_func, CTDB_FETCH_FUNC);
2187 ctdb_set_call(ctdb_db, ctdb_fetch_with_header_func, CTDB_FETCH_WITH_HEADER_FUNC);
2189 return ctdb_db;
2193 * detach from a specific database - client call
2195 int ctdb_detach(struct ctdb_context *ctdb, uint32_t db_id)
2197 int ret;
2198 int32_t status;
2199 TDB_DATA data;
2201 data.dsize = sizeof(db_id);
2202 data.dptr = (uint8_t *)&db_id;
2204 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_DB_DETACH,
2205 0, data, NULL, NULL, &status, NULL, NULL);
2206 if (ret != 0 || status != 0) {
2207 return -1;
2209 return 0;
2213 setup a call for a database
2215 int ctdb_set_call(struct ctdb_db_context *ctdb_db, ctdb_fn_t fn, uint32_t id)
2217 struct ctdb_registered_call *call;
2219 /* register locally */
2220 call = talloc(ctdb_db, struct ctdb_registered_call);
2221 call->fn = fn;
2222 call->id = id;
2224 DLIST_ADD(ctdb_db->calls, call);
2225 return 0;
2229 struct traverse_state {
2230 bool done;
2231 uint32_t count;
2232 ctdb_traverse_func fn;
2233 void *private_data;
2234 bool listemptyrecords;
2238 called on each key during a ctdb_traverse
2240 static void traverse_handler(uint64_t srvid, TDB_DATA data, void *p)
2242 struct traverse_state *state = (struct traverse_state *)p;
2243 struct ctdb_rec_data_old *d = (struct ctdb_rec_data_old *)data.dptr;
2244 TDB_DATA key;
2246 if (data.dsize < sizeof(uint32_t) || d->length != data.dsize) {
2247 DEBUG(DEBUG_ERR, ("Bad data size %u in traverse_handler\n",
2248 (unsigned)data.dsize));
2249 state->done = true;
2250 return;
2253 key.dsize = d->keylen;
2254 key.dptr = &d->data[0];
2255 data.dsize = d->datalen;
2256 data.dptr = &d->data[d->keylen];
2258 if (key.dsize == 0 && data.dsize == 0) {
2259 /* end of traverse */
2260 state->done = true;
2261 return;
2264 if (!state->listemptyrecords &&
2265 data.dsize == sizeof(struct ctdb_ltdb_header))
2267 /* empty records are deleted records in ctdb */
2268 return;
2271 if (state->fn(key, data, state->private_data) != 0) {
2272 state->done = true;
2275 state->count++;
2279 * start a cluster wide traverse, calling the supplied fn on each record
2280 * return the number of records traversed, or -1 on error
2282 * Extendet variant with a flag to signal whether empty records should
2283 * be listed.
2285 static int ctdb_traverse_ext(struct ctdb_db_context *ctdb_db,
2286 ctdb_traverse_func fn,
2287 bool withemptyrecords,
2288 void *private_data)
2290 TDB_DATA data;
2291 struct ctdb_traverse_start_ext t;
2292 int32_t status;
2293 int ret;
2294 uint64_t srvid = (getpid() | 0xFLL<<60);
2295 struct traverse_state state;
2297 state.done = false;
2298 state.count = 0;
2299 state.private_data = private_data;
2300 state.fn = fn;
2301 state.listemptyrecords = withemptyrecords;
2303 ret = ctdb_client_set_message_handler(ctdb_db->ctdb, srvid, traverse_handler, &state);
2304 if (ret != 0) {
2305 DEBUG(DEBUG_ERR,("Failed to setup traverse handler\n"));
2306 return -1;
2309 t.db_id = ctdb_db->db_id;
2310 t.srvid = srvid;
2311 t.reqid = 0;
2312 t.withemptyrecords = withemptyrecords;
2314 data.dptr = (uint8_t *)&t;
2315 data.dsize = sizeof(t);
2317 ret = ctdb_control(ctdb_db->ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_TRAVERSE_START_EXT, 0,
2318 data, NULL, NULL, &status, NULL, NULL);
2319 if (ret != 0 || status != 0) {
2320 DEBUG(DEBUG_ERR,("ctdb_traverse_all failed\n"));
2321 ctdb_client_remove_message_handler(ctdb_db->ctdb, srvid, &state);
2322 return -1;
2325 while (!state.done) {
2326 tevent_loop_once(ctdb_db->ctdb->ev);
2329 ret = ctdb_client_remove_message_handler(ctdb_db->ctdb, srvid, &state);
2330 if (ret != 0) {
2331 DEBUG(DEBUG_ERR,("Failed to remove ctdb_traverse handler\n"));
2332 return -1;
2335 return state.count;
2339 * start a cluster wide traverse, calling the supplied fn on each record
2340 * return the number of records traversed, or -1 on error
2342 * Standard version which does not list the empty records:
2343 * These are considered deleted.
2345 int ctdb_traverse(struct ctdb_db_context *ctdb_db, ctdb_traverse_func fn, void *private_data)
2347 return ctdb_traverse_ext(ctdb_db, fn, false, private_data);
2350 #define ISASCII(x) (isprint(x) && !strchr("\"\\", (x)))
2352 called on each key during a catdb
2354 int ctdb_dumpdb_record(TDB_DATA key, TDB_DATA data, void *p)
2356 int i;
2357 struct ctdb_dump_db_context *c = (struct ctdb_dump_db_context *)p;
2358 FILE *f = c->f;
2359 struct ctdb_ltdb_header *h = (struct ctdb_ltdb_header *)data.dptr;
2361 fprintf(f, "key(%u) = \"", (unsigned)key.dsize);
2362 for (i=0;i<key.dsize;i++) {
2363 if (ISASCII(key.dptr[i])) {
2364 fprintf(f, "%c", key.dptr[i]);
2365 } else {
2366 fprintf(f, "\\%02X", key.dptr[i]);
2369 fprintf(f, "\"\n");
2371 fprintf(f, "dmaster: %u\n", h->dmaster);
2372 fprintf(f, "rsn: %llu\n", (unsigned long long)h->rsn);
2374 if (c->printlmaster && c->ctdb->vnn_map != NULL) {
2375 fprintf(f, "lmaster: %u\n", ctdb_lmaster(c->ctdb, &key));
2378 if (c->printhash) {
2379 fprintf(f, "hash: 0x%08x\n", ctdb_hash(&key));
2382 if (c->printrecordflags) {
2383 fprintf(f, "flags: 0x%08x", h->flags);
2384 if (h->flags & CTDB_REC_FLAG_MIGRATED_WITH_DATA) printf(" MIGRATED_WITH_DATA");
2385 if (h->flags & CTDB_REC_FLAG_VACUUM_MIGRATED) printf(" VACUUM_MIGRATED");
2386 if (h->flags & CTDB_REC_FLAG_AUTOMATIC) printf(" AUTOMATIC");
2387 if (h->flags & CTDB_REC_RO_HAVE_DELEGATIONS) printf(" RO_HAVE_DELEGATIONS");
2388 if (h->flags & CTDB_REC_RO_HAVE_READONLY) printf(" RO_HAVE_READONLY");
2389 if (h->flags & CTDB_REC_RO_REVOKING_READONLY) printf(" RO_REVOKING_READONLY");
2390 if (h->flags & CTDB_REC_RO_REVOKE_COMPLETE) printf(" RO_REVOKE_COMPLETE");
2391 fprintf(f, "\n");
2394 if (c->printdatasize) {
2395 fprintf(f, "data size: %u\n", (unsigned)data.dsize);
2396 } else {
2397 fprintf(f, "data(%u) = \"", (unsigned)(data.dsize - sizeof(*h)));
2398 for (i=sizeof(*h);i<data.dsize;i++) {
2399 if (ISASCII(data.dptr[i])) {
2400 fprintf(f, "%c", data.dptr[i]);
2401 } else {
2402 fprintf(f, "\\%02X", data.dptr[i]);
2405 fprintf(f, "\"\n");
2408 fprintf(f, "\n");
2410 return 0;
2414 convenience function to list all keys to stdout
2416 int ctdb_dump_db(struct ctdb_db_context *ctdb_db,
2417 struct ctdb_dump_db_context *ctx)
2419 return ctdb_traverse_ext(ctdb_db, ctdb_dumpdb_record,
2420 ctx->printemptyrecords, ctx);
2424 get the pid of a ctdb daemon
2426 int ctdb_ctrl_getpid(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *pid)
2428 int ret;
2429 int32_t res;
2431 ret = ctdb_control(ctdb, destnode, 0,
2432 CTDB_CONTROL_GET_PID, 0, tdb_null,
2433 NULL, NULL, &res, &timeout, NULL);
2434 if (ret != 0) {
2435 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getpid failed\n"));
2436 return -1;
2439 *pid = res;
2441 return 0;
2444 /* Freeze all databases */
2445 int ctdb_ctrl_freeze(struct ctdb_context *ctdb, struct timeval timeout,
2446 uint32_t destnode)
2448 int ret;
2449 int32_t res;
2451 ret = ctdb_control(ctdb, destnode, 0,
2452 CTDB_CONTROL_FREEZE, 0, tdb_null,
2453 NULL, NULL, &res, &timeout, NULL);
2454 if (ret != 0 || res != 0) {
2455 DEBUG(DEBUG_ERR, ("ctdb_ctrl_freeze_priority failed\n"));
2456 return -1;
2459 return 0;
2463 get pnn of a node, or -1
2465 int ctdb_ctrl_getpnn(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2467 int ret;
2468 int32_t res;
2470 ret = ctdb_control(ctdb, destnode, 0,
2471 CTDB_CONTROL_GET_PNN, 0, tdb_null,
2472 NULL, NULL, &res, &timeout, NULL);
2473 if (ret != 0) {
2474 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getpnn failed\n"));
2475 return -1;
2478 return res;
2482 get the monitoring mode of a remote node
2484 int ctdb_ctrl_getmonmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *monmode)
2486 int ret;
2487 int32_t res;
2489 ret = ctdb_control(ctdb, destnode, 0,
2490 CTDB_CONTROL_GET_MONMODE, 0, tdb_null,
2491 NULL, NULL, &res, &timeout, NULL);
2492 if (ret != 0) {
2493 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getmonmode failed\n"));
2494 return -1;
2497 *monmode = res;
2499 return 0;
2504 set the monitoring mode of a remote node to active
2506 int ctdb_ctrl_enable_monmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2508 int ret;
2511 ret = ctdb_control(ctdb, destnode, 0,
2512 CTDB_CONTROL_ENABLE_MONITOR, 0, tdb_null,
2513 NULL, NULL,NULL, &timeout, NULL);
2514 if (ret != 0) {
2515 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for enable_monitor failed\n"));
2516 return -1;
2521 return 0;
2525 set the monitoring mode of a remote node to disable
2527 int ctdb_ctrl_disable_monmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2529 int ret;
2532 ret = ctdb_control(ctdb, destnode, 0,
2533 CTDB_CONTROL_DISABLE_MONITOR, 0, tdb_null,
2534 NULL, NULL, NULL, &timeout, NULL);
2535 if (ret != 0) {
2536 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for disable_monitor failed\n"));
2537 return -1;
2542 return 0;
2548 sent to a node to make it take over an ip address
2550 int ctdb_ctrl_takeover_ip(struct ctdb_context *ctdb, struct timeval timeout,
2551 uint32_t destnode, struct ctdb_public_ip *ip)
2553 TDB_DATA data;
2554 int ret;
2555 int32_t res;
2557 data.dsize = sizeof(*ip);
2558 data.dptr = (uint8_t *)ip;
2560 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_TAKEOVER_IP, 0,
2561 data, NULL, NULL, &res, &timeout, NULL);
2562 if (ret != 0 || res != 0) {
2563 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for takeover_ip failed\n"));
2564 return -1;
2567 return 0;
2572 sent to a node to make it release an ip address
2574 int ctdb_ctrl_release_ip(struct ctdb_context *ctdb, struct timeval timeout,
2575 uint32_t destnode, struct ctdb_public_ip *ip)
2577 TDB_DATA data;
2578 int ret;
2579 int32_t res;
2581 data.dsize = sizeof(*ip);
2582 data.dptr = (uint8_t *)ip;
2584 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_RELEASE_IP, 0,
2585 data, NULL, NULL, &res, &timeout, NULL);
2586 if (ret != 0 || res != 0) {
2587 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for release_ip failed\n"));
2588 return -1;
2591 return 0;
2596 get a tunable
2598 int ctdb_ctrl_get_tunable(struct ctdb_context *ctdb,
2599 struct timeval timeout,
2600 uint32_t destnode,
2601 const char *name, uint32_t *value)
2603 struct ctdb_control_get_tunable *t;
2604 TDB_DATA data, outdata;
2605 int32_t res;
2606 int ret;
2608 data.dsize = offsetof(struct ctdb_control_get_tunable, name) + strlen(name) + 1;
2609 data.dptr = talloc_size(ctdb, data.dsize);
2610 CTDB_NO_MEMORY(ctdb, data.dptr);
2612 t = (struct ctdb_control_get_tunable *)data.dptr;
2613 t->length = strlen(name)+1;
2614 memcpy(t->name, name, t->length);
2616 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_TUNABLE, 0, data, ctdb,
2617 &outdata, &res, &timeout, NULL);
2618 talloc_free(data.dptr);
2619 if (ret != 0 || res != 0) {
2620 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get_tunable failed\n"));
2621 return ret != 0 ? ret : res;
2624 if (outdata.dsize != sizeof(uint32_t)) {
2625 DEBUG(DEBUG_ERR,("Invalid return data in get_tunable\n"));
2626 talloc_free(outdata.dptr);
2627 return -1;
2630 *value = *(uint32_t *)outdata.dptr;
2631 talloc_free(outdata.dptr);
2633 return 0;
2637 set a tunable
2639 int ctdb_ctrl_set_tunable(struct ctdb_context *ctdb,
2640 struct timeval timeout,
2641 uint32_t destnode,
2642 const char *name, uint32_t value)
2644 struct ctdb_tunable_old *t;
2645 TDB_DATA data;
2646 int32_t res;
2647 int ret;
2649 data.dsize = offsetof(struct ctdb_tunable_old, name) + strlen(name) + 1;
2650 data.dptr = talloc_size(ctdb, data.dsize);
2651 CTDB_NO_MEMORY(ctdb, data.dptr);
2653 t = (struct ctdb_tunable_old *)data.dptr;
2654 t->length = strlen(name)+1;
2655 memcpy(t->name, name, t->length);
2656 t->value = value;
2658 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SET_TUNABLE, 0, data, NULL,
2659 NULL, &res, &timeout, NULL);
2660 talloc_free(data.dptr);
2661 if ((ret != 0) || (res == -1)) {
2662 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set_tunable failed\n"));
2663 return -1;
2666 return res;
2670 list tunables
2672 int ctdb_ctrl_list_tunables(struct ctdb_context *ctdb,
2673 struct timeval timeout,
2674 uint32_t destnode,
2675 TALLOC_CTX *mem_ctx,
2676 const char ***list, uint32_t *count)
2678 TDB_DATA outdata;
2679 int32_t res;
2680 int ret;
2681 struct ctdb_control_list_tunable *t;
2682 char *p, *s, *ptr;
2684 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_LIST_TUNABLES, 0, tdb_null,
2685 mem_ctx, &outdata, &res, &timeout, NULL);
2686 if (ret != 0 || res != 0) {
2687 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for list_tunables failed\n"));
2688 return -1;
2691 t = (struct ctdb_control_list_tunable *)outdata.dptr;
2692 if (outdata.dsize < offsetof(struct ctdb_control_list_tunable, data) ||
2693 t->length > outdata.dsize-offsetof(struct ctdb_control_list_tunable, data)) {
2694 DEBUG(DEBUG_ERR,("Invalid data in list_tunables reply\n"));
2695 talloc_free(outdata.dptr);
2696 return -1;
2699 p = talloc_strndup(mem_ctx, (char *)t->data, t->length);
2700 CTDB_NO_MEMORY(ctdb, p);
2702 talloc_free(outdata.dptr);
2704 (*list) = NULL;
2705 (*count) = 0;
2707 for (s=strtok_r(p, ":", &ptr); s; s=strtok_r(NULL, ":", &ptr)) {
2708 (*list) = talloc_realloc(mem_ctx, *list, const char *, 1+(*count));
2709 CTDB_NO_MEMORY(ctdb, *list);
2710 (*list)[*count] = talloc_strdup(*list, s);
2711 CTDB_NO_MEMORY(ctdb, (*list)[*count]);
2712 (*count)++;
2715 talloc_free(p);
2717 return 0;
2721 int ctdb_ctrl_get_public_ips_flags(struct ctdb_context *ctdb,
2722 struct timeval timeout, uint32_t destnode,
2723 TALLOC_CTX *mem_ctx,
2724 uint32_t flags,
2725 struct ctdb_public_ip_list_old **ips)
2727 int ret;
2728 TDB_DATA outdata;
2729 int32_t res;
2731 ret = ctdb_control(ctdb, destnode, 0,
2732 CTDB_CONTROL_GET_PUBLIC_IPS, flags, tdb_null,
2733 mem_ctx, &outdata, &res, &timeout, NULL);
2734 if (ret != 0 || res != 0) {
2735 DEBUG(DEBUG_ERR,(__location__
2736 " ctdb_control for getpublicips failed ret:%d res:%d\n",
2737 ret, res));
2738 return -1;
2741 *ips = (struct ctdb_public_ip_list_old *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
2742 talloc_free(outdata.dptr);
2744 return 0;
2747 int ctdb_ctrl_get_public_ips(struct ctdb_context *ctdb,
2748 struct timeval timeout, uint32_t destnode,
2749 TALLOC_CTX *mem_ctx,
2750 struct ctdb_public_ip_list_old **ips)
2752 return ctdb_ctrl_get_public_ips_flags(ctdb, timeout,
2753 destnode, mem_ctx,
2754 0, ips);
2757 int ctdb_ctrl_get_public_ip_info(struct ctdb_context *ctdb,
2758 struct timeval timeout, uint32_t destnode,
2759 TALLOC_CTX *mem_ctx,
2760 const ctdb_sock_addr *addr,
2761 struct ctdb_public_ip_info_old **_info)
2763 int ret;
2764 TDB_DATA indata;
2765 TDB_DATA outdata;
2766 int32_t res;
2767 struct ctdb_public_ip_info_old *info;
2768 uint32_t len;
2769 uint32_t i;
2771 indata.dptr = discard_const_p(uint8_t, addr);
2772 indata.dsize = sizeof(*addr);
2774 ret = ctdb_control(ctdb, destnode, 0,
2775 CTDB_CONTROL_GET_PUBLIC_IP_INFO, 0, indata,
2776 mem_ctx, &outdata, &res, &timeout, NULL);
2777 if (ret != 0 || res != 0) {
2778 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
2779 "failed ret:%d res:%d\n",
2780 ret, res));
2781 return -1;
2784 len = offsetof(struct ctdb_public_ip_info_old, ifaces);
2785 if (len > outdata.dsize) {
2786 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
2787 "returned invalid data with size %u > %u\n",
2788 (unsigned int)outdata.dsize,
2789 (unsigned int)len));
2790 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
2791 return -1;
2794 info = (struct ctdb_public_ip_info_old *)outdata.dptr;
2795 len += info->num*sizeof(struct ctdb_iface);
2797 if (len > outdata.dsize) {
2798 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
2799 "returned invalid data with size %u > %u\n",
2800 (unsigned int)outdata.dsize,
2801 (unsigned int)len));
2802 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
2803 return -1;
2806 /* make sure we null terminate the returned strings */
2807 for (i=0; i < info->num; i++) {
2808 info->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
2811 *_info = (struct ctdb_public_ip_info_old *)talloc_memdup(mem_ctx,
2812 outdata.dptr,
2813 outdata.dsize);
2814 talloc_free(outdata.dptr);
2815 if (*_info == NULL) {
2816 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
2817 "talloc_memdup size %u failed\n",
2818 (unsigned int)outdata.dsize));
2819 return -1;
2822 return 0;
2825 int ctdb_ctrl_get_ifaces(struct ctdb_context *ctdb,
2826 struct timeval timeout, uint32_t destnode,
2827 TALLOC_CTX *mem_ctx,
2828 struct ctdb_iface_list_old **_ifaces)
2830 int ret;
2831 TDB_DATA outdata;
2832 int32_t res;
2833 struct ctdb_iface_list_old *ifaces;
2834 uint32_t len;
2835 uint32_t i;
2837 ret = ctdb_control(ctdb, destnode, 0,
2838 CTDB_CONTROL_GET_IFACES, 0, tdb_null,
2839 mem_ctx, &outdata, &res, &timeout, NULL);
2840 if (ret != 0 || res != 0) {
2841 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
2842 "failed ret:%d res:%d\n",
2843 ret, res));
2844 return -1;
2847 len = offsetof(struct ctdb_iface_list_old, ifaces);
2848 if (len > outdata.dsize) {
2849 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
2850 "returned invalid data with size %u > %u\n",
2851 (unsigned int)outdata.dsize,
2852 (unsigned int)len));
2853 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
2854 return -1;
2857 ifaces = (struct ctdb_iface_list_old *)outdata.dptr;
2858 len += ifaces->num*sizeof(struct ctdb_iface);
2860 if (len > outdata.dsize) {
2861 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
2862 "returned invalid data with size %u > %u\n",
2863 (unsigned int)outdata.dsize,
2864 (unsigned int)len));
2865 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
2866 return -1;
2869 /* make sure we null terminate the returned strings */
2870 for (i=0; i < ifaces->num; i++) {
2871 ifaces->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
2874 *_ifaces = (struct ctdb_iface_list_old *)talloc_memdup(mem_ctx,
2875 outdata.dptr,
2876 outdata.dsize);
2877 talloc_free(outdata.dptr);
2878 if (*_ifaces == NULL) {
2879 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
2880 "talloc_memdup size %u failed\n",
2881 (unsigned int)outdata.dsize));
2882 return -1;
2885 return 0;
2888 int ctdb_ctrl_set_iface_link(struct ctdb_context *ctdb,
2889 struct timeval timeout, uint32_t destnode,
2890 TALLOC_CTX *mem_ctx,
2891 const struct ctdb_iface *info)
2893 int ret;
2894 TDB_DATA indata;
2895 int32_t res;
2897 indata.dptr = discard_const_p(uint8_t, info);
2898 indata.dsize = sizeof(*info);
2900 ret = ctdb_control(ctdb, destnode, 0,
2901 CTDB_CONTROL_SET_IFACE_LINK_STATE, 0, indata,
2902 mem_ctx, NULL, &res, &timeout, NULL);
2903 if (ret != 0 || res != 0) {
2904 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set iface link "
2905 "failed ret:%d res:%d\n",
2906 ret, res));
2907 return -1;
2910 return 0;
2914 set/clear the permanent disabled bit on a remote node
2916 int ctdb_ctrl_modflags(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
2917 uint32_t set, uint32_t clear)
2919 int ret;
2920 TDB_DATA data;
2921 struct ctdb_node_map_old *nodemap=NULL;
2922 struct ctdb_node_flag_change c;
2923 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2924 uint32_t recmaster;
2925 uint32_t *nodes;
2928 /* find the recovery master */
2929 ret = ctdb_ctrl_getrecmaster(ctdb, tmp_ctx, timeout, CTDB_CURRENT_NODE, &recmaster);
2930 if (ret != 0) {
2931 DEBUG(DEBUG_ERR, (__location__ " Unable to get recmaster from local node\n"));
2932 talloc_free(tmp_ctx);
2933 return ret;
2937 /* read the node flags from the recmaster */
2938 ret = ctdb_ctrl_getnodemap(ctdb, timeout, recmaster, tmp_ctx, &nodemap);
2939 if (ret != 0) {
2940 DEBUG(DEBUG_ERR, (__location__ " Unable to get nodemap from node %u\n", destnode));
2941 talloc_free(tmp_ctx);
2942 return -1;
2944 if (destnode >= nodemap->num) {
2945 DEBUG(DEBUG_ERR,(__location__ " Nodemap from recmaster does not contain node %d\n", destnode));
2946 talloc_free(tmp_ctx);
2947 return -1;
2950 c.pnn = destnode;
2951 c.old_flags = nodemap->nodes[destnode].flags;
2952 c.new_flags = c.old_flags;
2953 c.new_flags |= set;
2954 c.new_flags &= ~clear;
2956 data.dsize = sizeof(c);
2957 data.dptr = (unsigned char *)&c;
2959 /* send the flags update to all connected nodes */
2960 nodes = list_of_connected_nodes(ctdb, nodemap, tmp_ctx, true);
2962 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_MODIFY_FLAGS,
2963 nodes, 0,
2964 timeout, false, data,
2965 NULL, NULL,
2966 NULL) != 0) {
2967 DEBUG(DEBUG_ERR, (__location__ " Unable to update nodeflags on remote nodes\n"));
2969 talloc_free(tmp_ctx);
2970 return -1;
2973 talloc_free(tmp_ctx);
2974 return 0;
2979 get all tunables
2981 int ctdb_ctrl_get_all_tunables(struct ctdb_context *ctdb,
2982 struct timeval timeout,
2983 uint32_t destnode,
2984 struct ctdb_tunable_list *tunables)
2986 TDB_DATA outdata;
2987 int ret;
2988 int32_t res;
2990 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_ALL_TUNABLES, 0, tdb_null, ctdb,
2991 &outdata, &res, &timeout, NULL);
2992 if (ret != 0 || res != 0) {
2993 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get all tunables failed\n"));
2994 return -1;
2997 if (outdata.dsize != sizeof(*tunables)) {
2998 DEBUG(DEBUG_ERR,(__location__ " bad data size %u in ctdb_ctrl_get_all_tunables should be %u\n",
2999 (unsigned)outdata.dsize, (unsigned)sizeof(*tunables)));
3000 return -1;
3003 *tunables = *(struct ctdb_tunable_list *)outdata.dptr;
3004 talloc_free(outdata.dptr);
3005 return 0;
3009 add a public address to a node
3011 int ctdb_ctrl_add_public_ip(struct ctdb_context *ctdb,
3012 struct timeval timeout, uint32_t destnode,
3013 struct ctdb_addr_info_old *pub)
3015 TDB_DATA data;
3016 int32_t res;
3017 int ret;
3019 data.dsize = offsetof(struct ctdb_addr_info_old, iface) + pub->len;
3020 data.dptr = (unsigned char *)pub;
3022 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_ADD_PUBLIC_IP, 0, data, NULL,
3023 NULL, &res, &timeout, NULL);
3024 if (ret != 0 || res != 0) {
3025 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for add_public_ip failed\n"));
3026 return -1;
3029 return 0;
3033 delete a public address from a node
3035 int ctdb_ctrl_del_public_ip(struct ctdb_context *ctdb,
3036 struct timeval timeout, uint32_t destnode,
3037 struct ctdb_addr_info_old *pub)
3039 TDB_DATA data;
3040 int32_t res;
3041 int ret;
3043 data.dsize = offsetof(struct ctdb_addr_info_old, iface) + pub->len;
3044 data.dptr = (unsigned char *)pub;
3046 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_DEL_PUBLIC_IP, 0, data, NULL,
3047 NULL, &res, &timeout, NULL);
3048 if (ret != 0 || res != 0) {
3049 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for del_public_ip failed\n"));
3050 return -1;
3053 return 0;
3057 send a gratious arp
3059 int ctdb_ctrl_gratious_arp(struct ctdb_context *ctdb,
3060 struct timeval timeout, uint32_t destnode,
3061 ctdb_sock_addr *addr, const char *ifname)
3063 TDB_DATA data;
3064 int32_t res;
3065 int ret, len;
3066 struct ctdb_addr_info_old *gratious_arp;
3067 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3070 len = strlen(ifname)+1;
3071 gratious_arp = talloc_size(tmp_ctx,
3072 offsetof(struct ctdb_addr_info_old, iface) + len);
3073 CTDB_NO_MEMORY(ctdb, gratious_arp);
3075 gratious_arp->addr = *addr;
3076 gratious_arp->len = len;
3077 memcpy(&gratious_arp->iface[0], ifname, len);
3080 data.dsize = offsetof(struct ctdb_addr_info_old, iface) + len;
3081 data.dptr = (unsigned char *)gratious_arp;
3083 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SEND_GRATUITOUS_ARP, 0, data, NULL,
3084 NULL, &res, &timeout, NULL);
3085 if (ret != 0 || res != 0) {
3086 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for gratious_arp failed\n"));
3087 talloc_free(tmp_ctx);
3088 return -1;
3091 talloc_free(tmp_ctx);
3092 return 0;
3096 get a list of all tcp tickles that a node knows about for a particular vnn
3098 int ctdb_ctrl_get_tcp_tickles(struct ctdb_context *ctdb,
3099 struct timeval timeout, uint32_t destnode,
3100 TALLOC_CTX *mem_ctx,
3101 ctdb_sock_addr *addr,
3102 struct ctdb_tickle_list_old **list)
3104 int ret;
3105 TDB_DATA data, outdata;
3106 int32_t status;
3108 data.dptr = (uint8_t*)addr;
3109 data.dsize = sizeof(ctdb_sock_addr);
3111 ret = ctdb_control(ctdb, destnode, 0,
3112 CTDB_CONTROL_GET_TCP_TICKLE_LIST, 0, data,
3113 mem_ctx, &outdata, &status, NULL, NULL);
3114 if (ret != 0 || status != 0) {
3115 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get tcp tickles failed\n"));
3116 return -1;
3119 *list = (struct ctdb_tickle_list_old *)outdata.dptr;
3121 return status;
3125 initialise the ctdb daemon for client applications
3127 NOTE: In current code the daemon does not fork. This is for testing purposes only
3128 and to simplify the code.
3130 struct ctdb_context *ctdb_init(struct tevent_context *ev)
3132 int ret;
3133 struct ctdb_context *ctdb;
3135 ctdb = talloc_zero(ev, struct ctdb_context);
3136 if (ctdb == NULL) {
3137 DEBUG(DEBUG_ERR,(__location__ " talloc_zero failed.\n"));
3138 return NULL;
3140 ctdb->ev = ev;
3141 /* Wrap early to exercise code. */
3142 ret = reqid_init(ctdb, INT_MAX-200, &ctdb->idr);
3143 if (ret != 0) {
3144 DEBUG(DEBUG_ERR, ("reqid_init failed (%s)\n", strerror(ret)));
3145 talloc_free(ctdb);
3146 return NULL;
3149 ret = srvid_init(ctdb, &ctdb->srv);
3150 if (ret != 0) {
3151 DEBUG(DEBUG_ERR, ("srvid_init failed (%s)\n", strerror(ret)));
3152 talloc_free(ctdb);
3153 return NULL;
3156 ret = ctdb_set_socketname(ctdb, CTDB_SOCKET);
3157 if (ret != 0) {
3158 DEBUG(DEBUG_ERR,(__location__ " ctdb_set_socketname failed.\n"));
3159 talloc_free(ctdb);
3160 return NULL;
3163 ctdb->statistics.statistics_start_time = timeval_current();
3165 return ctdb;
3170 set some ctdb flags
3172 void ctdb_set_flags(struct ctdb_context *ctdb, unsigned flags)
3174 ctdb->flags |= flags;
3178 setup the local socket name
3180 int ctdb_set_socketname(struct ctdb_context *ctdb, const char *socketname)
3182 ctdb->daemon.name = talloc_strdup(ctdb, socketname);
3183 CTDB_NO_MEMORY(ctdb, ctdb->daemon.name);
3185 return 0;
3188 const char *ctdb_get_socketname(struct ctdb_context *ctdb)
3190 return ctdb->daemon.name;
3194 return the pnn of this node
3196 uint32_t ctdb_get_pnn(struct ctdb_context *ctdb)
3198 return ctdb->pnn;
3203 get the uptime of a remote node
3205 struct ctdb_client_control_state *
3206 ctdb_ctrl_uptime_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode)
3208 return ctdb_control_send(ctdb, destnode, 0,
3209 CTDB_CONTROL_UPTIME, 0, tdb_null,
3210 mem_ctx, &timeout, NULL);
3213 int ctdb_ctrl_uptime_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, struct ctdb_uptime **uptime)
3215 int ret;
3216 int32_t res;
3217 TDB_DATA outdata;
3219 ret = ctdb_control_recv(ctdb, state, mem_ctx, &outdata, &res, NULL);
3220 if (ret != 0 || res != 0) {
3221 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_uptime_recv failed\n"));
3222 return -1;
3225 *uptime = (struct ctdb_uptime *)talloc_steal(mem_ctx, outdata.dptr);
3227 return 0;
3230 int ctdb_ctrl_uptime(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, struct ctdb_uptime **uptime)
3232 struct ctdb_client_control_state *state;
3234 state = ctdb_ctrl_uptime_send(ctdb, mem_ctx, timeout, destnode);
3235 return ctdb_ctrl_uptime_recv(ctdb, mem_ctx, state, uptime);
3239 send a control to execute the "recovered" event script on a node
3241 int ctdb_ctrl_end_recovery(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
3243 int ret;
3244 int32_t status;
3246 ret = ctdb_control(ctdb, destnode, 0,
3247 CTDB_CONTROL_END_RECOVERY, 0, tdb_null,
3248 NULL, NULL, &status, &timeout, NULL);
3249 if (ret != 0 || status != 0) {
3250 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for end_recovery failed\n"));
3251 return -1;
3254 return 0;
3258 callback for the async helpers used when sending the same control
3259 to multiple nodes in parallell.
3261 static void async_callback(struct ctdb_client_control_state *state)
3263 struct client_async_data *data = talloc_get_type(state->async.private_data, struct client_async_data);
3264 struct ctdb_context *ctdb = talloc_get_type(state->ctdb, struct ctdb_context);
3265 int ret;
3266 TDB_DATA outdata;
3267 int32_t res = -1;
3268 uint32_t destnode = state->c->hdr.destnode;
3270 outdata.dsize = 0;
3271 outdata.dptr = NULL;
3273 /* one more node has responded with recmode data */
3274 data->count--;
3276 /* if we failed to push the db, then return an error and let
3277 the main loop try again.
3279 if (state->state != CTDB_CONTROL_DONE) {
3280 if ( !data->dont_log_errors) {
3281 DEBUG(DEBUG_ERR,("Async operation failed with state %d, opcode:%u\n", state->state, data->opcode));
3283 data->fail_count++;
3284 if (state->state == CTDB_CONTROL_TIMEOUT) {
3285 res = -ETIME;
3286 } else {
3287 res = -1;
3289 if (data->fail_callback) {
3290 data->fail_callback(ctdb, destnode, res, outdata,
3291 data->callback_data);
3293 return;
3296 state->async.fn = NULL;
3298 ret = ctdb_control_recv(ctdb, state, data, &outdata, &res, NULL);
3299 if ((ret != 0) || (res != 0)) {
3300 if ( !data->dont_log_errors) {
3301 DEBUG(DEBUG_ERR,("Async operation failed with ret=%d res=%d opcode=%u\n", ret, (int)res, data->opcode));
3303 data->fail_count++;
3304 if (data->fail_callback) {
3305 data->fail_callback(ctdb, destnode, res, outdata,
3306 data->callback_data);
3309 if ((ret == 0) && (data->callback != NULL)) {
3310 data->callback(ctdb, destnode, res, outdata,
3311 data->callback_data);
3316 void ctdb_client_async_add(struct client_async_data *data, struct ctdb_client_control_state *state)
3318 /* set up the callback functions */
3319 state->async.fn = async_callback;
3320 state->async.private_data = data;
3322 /* one more control to wait for to complete */
3323 data->count++;
3327 /* wait for up to the maximum number of seconds allowed
3328 or until all nodes we expect a response from has replied
3330 int ctdb_client_async_wait(struct ctdb_context *ctdb, struct client_async_data *data)
3332 while (data->count > 0) {
3333 tevent_loop_once(ctdb->ev);
3335 if (data->fail_count != 0) {
3336 if (!data->dont_log_errors) {
3337 DEBUG(DEBUG_ERR,("Async wait failed - fail_count=%u\n",
3338 data->fail_count));
3340 return -1;
3342 return 0;
3347 perform a simple control on the listed nodes
3348 The control cannot return data
3350 int ctdb_client_async_control(struct ctdb_context *ctdb,
3351 enum ctdb_controls opcode,
3352 uint32_t *nodes,
3353 uint64_t srvid,
3354 struct timeval timeout,
3355 bool dont_log_errors,
3356 TDB_DATA data,
3357 client_async_callback client_callback,
3358 client_async_callback fail_callback,
3359 void *callback_data)
3361 struct client_async_data *async_data;
3362 struct ctdb_client_control_state *state;
3363 int j, num_nodes;
3365 async_data = talloc_zero(ctdb, struct client_async_data);
3366 CTDB_NO_MEMORY_FATAL(ctdb, async_data);
3367 async_data->dont_log_errors = dont_log_errors;
3368 async_data->callback = client_callback;
3369 async_data->fail_callback = fail_callback;
3370 async_data->callback_data = callback_data;
3371 async_data->opcode = opcode;
3373 num_nodes = talloc_get_size(nodes) / sizeof(uint32_t);
3375 /* loop over all nodes and send an async control to each of them */
3376 for (j=0; j<num_nodes; j++) {
3377 uint32_t pnn = nodes[j];
3379 state = ctdb_control_send(ctdb, pnn, srvid, opcode,
3380 0, data, async_data, &timeout, NULL);
3381 if (state == NULL) {
3382 DEBUG(DEBUG_ERR,(__location__ " Failed to call async control %u\n", (unsigned)opcode));
3383 talloc_free(async_data);
3384 return -1;
3387 ctdb_client_async_add(async_data, state);
3390 if (ctdb_client_async_wait(ctdb, async_data) != 0) {
3391 talloc_free(async_data);
3392 return -1;
3395 talloc_free(async_data);
3396 return 0;
3399 uint32_t *list_of_vnnmap_nodes(struct ctdb_context *ctdb,
3400 struct ctdb_vnn_map *vnn_map,
3401 TALLOC_CTX *mem_ctx,
3402 bool include_self)
3404 int i, j, num_nodes;
3405 uint32_t *nodes;
3407 for (i=num_nodes=0;i<vnn_map->size;i++) {
3408 if (vnn_map->map[i] == ctdb->pnn && !include_self) {
3409 continue;
3411 num_nodes++;
3414 nodes = talloc_array(mem_ctx, uint32_t, num_nodes);
3415 CTDB_NO_MEMORY_FATAL(ctdb, nodes);
3417 for (i=j=0;i<vnn_map->size;i++) {
3418 if (vnn_map->map[i] == ctdb->pnn && !include_self) {
3419 continue;
3421 nodes[j++] = vnn_map->map[i];
3424 return nodes;
3427 /* Get list of nodes not including those with flags specified by mask.
3428 * If exclude_pnn is not -1 then exclude that pnn from the list.
3430 uint32_t *list_of_nodes(struct ctdb_context *ctdb,
3431 struct ctdb_node_map_old *node_map,
3432 TALLOC_CTX *mem_ctx,
3433 uint32_t mask,
3434 int exclude_pnn)
3436 int i, j, num_nodes;
3437 uint32_t *nodes;
3439 for (i=num_nodes=0;i<node_map->num;i++) {
3440 if (node_map->nodes[i].flags & mask) {
3441 continue;
3443 if (node_map->nodes[i].pnn == exclude_pnn) {
3444 continue;
3446 num_nodes++;
3449 nodes = talloc_array(mem_ctx, uint32_t, num_nodes);
3450 CTDB_NO_MEMORY_FATAL(ctdb, nodes);
3452 for (i=j=0;i<node_map->num;i++) {
3453 if (node_map->nodes[i].flags & mask) {
3454 continue;
3456 if (node_map->nodes[i].pnn == exclude_pnn) {
3457 continue;
3459 nodes[j++] = node_map->nodes[i].pnn;
3462 return nodes;
3465 uint32_t *list_of_active_nodes(struct ctdb_context *ctdb,
3466 struct ctdb_node_map_old *node_map,
3467 TALLOC_CTX *mem_ctx,
3468 bool include_self)
3470 return list_of_nodes(ctdb, node_map, mem_ctx, NODE_FLAGS_INACTIVE,
3471 include_self ? -1 : ctdb->pnn);
3474 uint32_t *list_of_connected_nodes(struct ctdb_context *ctdb,
3475 struct ctdb_node_map_old *node_map,
3476 TALLOC_CTX *mem_ctx,
3477 bool include_self)
3479 return list_of_nodes(ctdb, node_map, mem_ctx, NODE_FLAGS_DISCONNECTED,
3480 include_self ? -1 : ctdb->pnn);
3484 this is used to test if a pnn lock exists and if it exists will return
3485 the number of connections that pnn has reported or -1 if that recovery
3486 daemon is not running.
3489 ctdb_read_pnn_lock(int fd, int32_t pnn)
3491 struct flock lock;
3492 char c;
3494 lock.l_type = F_WRLCK;
3495 lock.l_whence = SEEK_SET;
3496 lock.l_start = pnn;
3497 lock.l_len = 1;
3498 lock.l_pid = 0;
3500 if (fcntl(fd, F_GETLK, &lock) != 0) {
3501 DEBUG(DEBUG_ERR, (__location__ " F_GETLK failed with %s\n", strerror(errno)));
3502 return -1;
3505 if (lock.l_type == F_UNLCK) {
3506 return -1;
3509 if (pread(fd, &c, 1, pnn) == -1) {
3510 DEBUG(DEBUG_CRIT,(__location__ " failed read pnn count - %s\n", strerror(errno)));
3511 return -1;
3514 return c;
3518 get capabilities of a remote node
3520 struct ctdb_client_control_state *
3521 ctdb_ctrl_getcapabilities_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode)
3523 return ctdb_control_send(ctdb, destnode, 0,
3524 CTDB_CONTROL_GET_CAPABILITIES, 0, tdb_null,
3525 mem_ctx, &timeout, NULL);
3528 int ctdb_ctrl_getcapabilities_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *capabilities)
3530 int ret;
3531 int32_t res;
3532 TDB_DATA outdata;
3534 ret = ctdb_control_recv(ctdb, state, mem_ctx, &outdata, &res, NULL);
3535 if ( (ret != 0) || (res != 0) ) {
3536 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_getcapabilities_recv failed\n"));
3537 return -1;
3540 if (capabilities) {
3541 *capabilities = *((uint32_t *)outdata.dptr);
3544 return 0;
3547 int ctdb_ctrl_getcapabilities(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *capabilities)
3549 struct ctdb_client_control_state *state;
3550 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
3551 int ret;
3553 state = ctdb_ctrl_getcapabilities_send(ctdb, tmp_ctx, timeout, destnode);
3554 ret = ctdb_ctrl_getcapabilities_recv(ctdb, tmp_ctx, state, capabilities);
3555 talloc_free(tmp_ctx);
3556 return ret;
3559 static void get_capabilities_callback(struct ctdb_context *ctdb,
3560 uint32_t node_pnn, int32_t res,
3561 TDB_DATA outdata, void *callback_data)
3563 struct ctdb_node_capabilities *caps =
3564 talloc_get_type(callback_data,
3565 struct ctdb_node_capabilities);
3567 if ( (outdata.dsize != sizeof(uint32_t)) || (outdata.dptr == NULL) ) {
3568 DEBUG(DEBUG_ERR, (__location__ " Invalid length/pointer for getcap callback : %u %p\n", (unsigned)outdata.dsize, outdata.dptr));
3569 return;
3572 if (node_pnn >= talloc_array_length(caps)) {
3573 DEBUG(DEBUG_ERR,
3574 (__location__ " unexpected PNN %u\n", node_pnn));
3575 return;
3578 caps[node_pnn].retrieved = true;
3579 caps[node_pnn].capabilities = *((uint32_t *)outdata.dptr);
3582 struct ctdb_node_capabilities *
3583 ctdb_get_capabilities(struct ctdb_context *ctdb,
3584 TALLOC_CTX *mem_ctx,
3585 struct timeval timeout,
3586 struct ctdb_node_map_old *nodemap)
3588 uint32_t *nodes;
3589 uint32_t i, res;
3590 struct ctdb_node_capabilities *ret;
3592 nodes = list_of_active_nodes(ctdb, nodemap, mem_ctx, true);
3594 ret = talloc_array(mem_ctx, struct ctdb_node_capabilities,
3595 nodemap->num);
3596 CTDB_NO_MEMORY_NULL(ctdb, ret);
3597 /* Prepopulate the expected PNNs */
3598 for (i = 0; i < talloc_array_length(ret); i++) {
3599 ret[i].retrieved = false;
3602 res = ctdb_client_async_control(ctdb, CTDB_CONTROL_GET_CAPABILITIES,
3603 nodes, 0, timeout,
3604 false, tdb_null,
3605 get_capabilities_callback, NULL,
3606 ret);
3607 if (res != 0) {
3608 DEBUG(DEBUG_ERR,
3609 (__location__ " Failed to read node capabilities.\n"));
3610 TALLOC_FREE(ret);
3613 return ret;
3616 uint32_t *
3617 ctdb_get_node_capabilities(struct ctdb_node_capabilities *caps,
3618 uint32_t pnn)
3620 if (pnn < talloc_array_length(caps) && caps[pnn].retrieved) {
3621 return &caps[pnn].capabilities;
3624 return NULL;
3627 bool ctdb_node_has_capabilities(struct ctdb_node_capabilities *caps,
3628 uint32_t pnn,
3629 uint32_t capabilities_required)
3631 uint32_t *capp = ctdb_get_node_capabilities(caps, pnn);
3632 return (capp != NULL) &&
3633 ((*capp & capabilities_required) == capabilities_required);
3637 static struct ctdb_server_id server_id_fetch(struct ctdb_context *ctdb, uint32_t reqid)
3639 struct ctdb_server_id id;
3641 id.pid = getpid();
3642 id.task_id = reqid;
3643 id.vnn = ctdb_get_pnn(ctdb);
3644 id.unique_id = id.vnn;
3645 id.unique_id = (id.unique_id << 32) | reqid;
3647 return id;
3650 /* This is basically a copy from Samba's server_id.*. However, a
3651 * dependency chain stops us from using Samba's version, so use a
3652 * renamed copy until a better solution is found. */
3653 static bool ctdb_server_id_equal(struct ctdb_server_id *id1, struct ctdb_server_id *id2)
3655 if (id1->pid != id2->pid) {
3656 return false;
3659 if (id1->task_id != id2->task_id) {
3660 return false;
3663 if (id1->vnn != id2->vnn) {
3664 return false;
3667 if (id1->unique_id != id2->unique_id) {
3668 return false;
3671 return true;
3674 static bool server_id_exists(struct ctdb_context *ctdb,
3675 struct ctdb_server_id *id)
3677 int ret;
3679 ret = ctdb_ctrl_process_exists(ctdb, id->vnn, id->pid);
3680 if (ret == 0) {
3681 return true;
3684 return false;
3687 static bool g_lock_parse(TALLOC_CTX *mem_ctx, TDB_DATA data,
3688 struct ctdb_g_lock_list **locks)
3690 struct ctdb_g_lock_list *recs;
3692 recs = talloc_zero(mem_ctx, struct ctdb_g_lock_list);
3693 if (recs == NULL) {
3694 return false;
3697 if (data.dsize == 0) {
3698 goto done;
3701 if (data.dsize % sizeof(struct ctdb_g_lock) != 0) {
3702 DEBUG(DEBUG_ERR, (__location__ "invalid data size %lu in g_lock record\n",
3703 (unsigned long)data.dsize));
3704 talloc_free(recs);
3705 return false;
3708 recs->num = data.dsize / sizeof(struct ctdb_g_lock);
3709 recs->lock = talloc_memdup(mem_ctx, data.dptr, data.dsize);
3710 if (recs->lock == NULL) {
3711 talloc_free(recs);
3712 return false;
3715 done:
3716 if (locks != NULL) {
3717 *locks = recs;
3720 return true;
3724 static bool g_lock_lock(TALLOC_CTX *mem_ctx,
3725 struct ctdb_db_context *ctdb_db,
3726 const char *keyname, uint32_t reqid)
3728 TDB_DATA key, data;
3729 struct ctdb_record_handle *h;
3730 struct ctdb_g_lock_list *locks;
3731 struct ctdb_server_id id;
3732 struct timeval t_start;
3733 int i;
3735 key.dptr = (uint8_t *)discard_const(keyname);
3736 key.dsize = strlen(keyname) + 1;
3738 t_start = timeval_current();
3740 again:
3741 /* Keep trying for an hour. */
3742 if (timeval_elapsed(&t_start) > 3600) {
3743 return false;
3746 h = ctdb_fetch_lock(ctdb_db, mem_ctx, key, &data);
3747 if (h == NULL) {
3748 return false;
3751 if (!g_lock_parse(h, data, &locks)) {
3752 DEBUG(DEBUG_ERR, ("g_lock: error parsing locks\n"));
3753 talloc_free(data.dptr);
3754 talloc_free(h);
3755 return false;
3758 talloc_free(data.dptr);
3760 id = server_id_fetch(ctdb_db->ctdb, reqid);
3762 i = 0;
3763 while (i < locks->num) {
3764 if (ctdb_server_id_equal(&locks->lock[i].sid, &id)) {
3765 /* Internal error */
3766 talloc_free(h);
3767 return false;
3770 if (!server_id_exists(ctdb_db->ctdb, &locks->lock[i].sid)) {
3771 if (i < locks->num-1) {
3772 locks->lock[i] = locks->lock[locks->num-1];
3774 locks->num--;
3775 continue;
3778 /* This entry is locked. */
3779 DEBUG(DEBUG_INFO, ("g_lock: lock already granted for "
3780 "pid=0x%llx taskid=%x vnn=%d id=0x%llx\n",
3781 (unsigned long long)id.pid,
3782 id.task_id, id.vnn,
3783 (unsigned long long)id.unique_id));
3784 talloc_free(h);
3785 goto again;
3788 locks->lock = talloc_realloc(locks, locks->lock, struct ctdb_g_lock,
3789 locks->num+1);
3790 if (locks->lock == NULL) {
3791 talloc_free(h);
3792 return false;
3795 locks->lock[locks->num].type = CTDB_G_LOCK_WRITE;
3796 locks->lock[locks->num].sid = id;
3797 locks->num++;
3799 data.dptr = (uint8_t *)locks->lock;
3800 data.dsize = locks->num * sizeof(struct ctdb_g_lock);
3802 if (ctdb_record_store(h, data) != 0) {
3803 DEBUG(DEBUG_ERR, ("g_lock: failed to write transaction lock for "
3804 "pid=0x%llx taskid=%x vnn=%d id=0x%llx\n",
3805 (unsigned long long)id.pid,
3806 id.task_id, id.vnn,
3807 (unsigned long long)id.unique_id));
3808 talloc_free(h);
3809 return false;
3812 DEBUG(DEBUG_INFO, ("g_lock: lock granted for "
3813 "pid=0x%llx taskid=%x vnn=%d id=0x%llx\n",
3814 (unsigned long long)id.pid,
3815 id.task_id, id.vnn,
3816 (unsigned long long)id.unique_id));
3818 talloc_free(h);
3819 return true;
3822 static bool g_lock_unlock(TALLOC_CTX *mem_ctx,
3823 struct ctdb_db_context *ctdb_db,
3824 const char *keyname, uint32_t reqid)
3826 TDB_DATA key, data;
3827 struct ctdb_record_handle *h;
3828 struct ctdb_g_lock_list *locks;
3829 struct ctdb_server_id id;
3830 int i;
3831 bool found = false;
3833 key.dptr = (uint8_t *)discard_const(keyname);
3834 key.dsize = strlen(keyname) + 1;
3835 h = ctdb_fetch_lock(ctdb_db, mem_ctx, key, &data);
3836 if (h == NULL) {
3837 return false;
3840 if (!g_lock_parse(h, data, &locks)) {
3841 DEBUG(DEBUG_ERR, ("g_lock: error parsing locks\n"));
3842 talloc_free(data.dptr);
3843 talloc_free(h);
3844 return false;
3847 talloc_free(data.dptr);
3849 id = server_id_fetch(ctdb_db->ctdb, reqid);
3851 for (i=0; i<locks->num; i++) {
3852 if (ctdb_server_id_equal(&locks->lock[i].sid, &id)) {
3853 if (i < locks->num-1) {
3854 locks->lock[i] = locks->lock[locks->num-1];
3856 locks->num--;
3857 found = true;
3858 break;
3862 if (!found) {
3863 DEBUG(DEBUG_ERR, ("g_lock: lock not found\n"));
3864 talloc_free(h);
3865 return false;
3868 data.dptr = (uint8_t *)locks->lock;
3869 data.dsize = locks->num * sizeof(struct ctdb_g_lock);
3871 if (ctdb_record_store(h, data) != 0) {
3872 talloc_free(h);
3873 return false;
3876 talloc_free(h);
3877 return true;
3881 struct ctdb_transaction_handle {
3882 struct ctdb_db_context *ctdb_db;
3883 struct ctdb_db_context *g_lock_db;
3884 char *lock_name;
3885 uint32_t reqid;
3887 * we store reads and writes done under a transaction:
3888 * - one list stores both reads and writes (m_all)
3889 * - the other just writes (m_write)
3891 struct ctdb_marshall_buffer *m_all;
3892 struct ctdb_marshall_buffer *m_write;
3895 static int ctdb_transaction_destructor(struct ctdb_transaction_handle *h)
3897 g_lock_unlock(h, h->g_lock_db, h->lock_name, h->reqid);
3898 reqid_remove(h->ctdb_db->ctdb->idr, h->reqid);
3899 return 0;
3904 * start a transaction on a database
3906 struct ctdb_transaction_handle *ctdb_transaction_start(struct ctdb_db_context *ctdb_db,
3907 TALLOC_CTX *mem_ctx)
3909 struct ctdb_transaction_handle *h;
3911 h = talloc_zero(mem_ctx, struct ctdb_transaction_handle);
3912 if (h == NULL) {
3913 DEBUG(DEBUG_ERR, (__location__ " memory allocation error\n"));
3914 return NULL;
3917 h->ctdb_db = ctdb_db;
3918 h->lock_name = talloc_asprintf(h, "transaction_db_0x%08x",
3919 (unsigned int)ctdb_db->db_id);
3920 if (h->lock_name == NULL) {
3921 DEBUG(DEBUG_ERR, (__location__ " talloc asprintf failed\n"));
3922 talloc_free(h);
3923 return NULL;
3926 h->g_lock_db = ctdb_attach(h->ctdb_db->ctdb, timeval_current_ofs(3,0),
3927 "g_lock.tdb", false, 0);
3928 if (!h->g_lock_db) {
3929 DEBUG(DEBUG_ERR, (__location__ " unable to attach to g_lock.tdb\n"));
3930 talloc_free(h);
3931 return NULL;
3934 h->reqid = reqid_new(h->ctdb_db->ctdb->idr, h);
3936 if (!g_lock_lock(h, h->g_lock_db, h->lock_name, h->reqid)) {
3937 DEBUG(DEBUG_ERR, (__location__ " Error locking g_lock.tdb\n"));
3938 talloc_free(h);
3939 return NULL;
3942 talloc_set_destructor(h, ctdb_transaction_destructor);
3943 return h;
3947 * fetch a record inside a transaction
3949 int ctdb_transaction_fetch(struct ctdb_transaction_handle *h,
3950 TALLOC_CTX *mem_ctx,
3951 TDB_DATA key, TDB_DATA *data)
3953 struct ctdb_ltdb_header header;
3954 int ret;
3956 ZERO_STRUCT(header);
3958 ret = ctdb_ltdb_fetch(h->ctdb_db, key, &header, mem_ctx, data);
3959 if (ret == -1 && header.dmaster == (uint32_t)-1) {
3960 /* record doesn't exist yet */
3961 *data = tdb_null;
3962 ret = 0;
3965 if (ret != 0) {
3966 return ret;
3969 h->m_all = ctdb_marshall_add(h, h->m_all, h->ctdb_db->db_id, 1, key, NULL, *data);
3970 if (h->m_all == NULL) {
3971 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
3972 return -1;
3975 return 0;
3979 * stores a record inside a transaction
3981 int ctdb_transaction_store(struct ctdb_transaction_handle *h,
3982 TDB_DATA key, TDB_DATA data)
3984 TALLOC_CTX *tmp_ctx = talloc_new(h);
3985 struct ctdb_ltdb_header header;
3986 TDB_DATA olddata;
3987 int ret;
3989 /* we need the header so we can update the RSN */
3990 ret = ctdb_ltdb_fetch(h->ctdb_db, key, &header, tmp_ctx, &olddata);
3991 if (ret == -1 && header.dmaster == (uint32_t)-1) {
3992 /* the record doesn't exist - create one with us as dmaster.
3993 This is only safe because we are in a transaction and this
3994 is a persistent database */
3995 ZERO_STRUCT(header);
3996 } else if (ret != 0) {
3997 DEBUG(DEBUG_ERR,(__location__ " Failed to fetch record\n"));
3998 talloc_free(tmp_ctx);
3999 return ret;
4002 if (data.dsize == olddata.dsize &&
4003 memcmp(data.dptr, olddata.dptr, data.dsize) == 0 &&
4004 header.rsn != 0) {
4005 /* save writing the same data */
4006 talloc_free(tmp_ctx);
4007 return 0;
4010 header.dmaster = h->ctdb_db->ctdb->pnn;
4011 header.rsn++;
4013 h->m_all = ctdb_marshall_add(h, h->m_all, h->ctdb_db->db_id, 0, key, NULL, data);
4014 if (h->m_all == NULL) {
4015 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
4016 talloc_free(tmp_ctx);
4017 return -1;
4020 h->m_write = ctdb_marshall_add(h, h->m_write, h->ctdb_db->db_id, 0, key, &header, data);
4021 if (h->m_write == NULL) {
4022 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
4023 talloc_free(tmp_ctx);
4024 return -1;
4027 talloc_free(tmp_ctx);
4028 return 0;
4031 static int ctdb_fetch_db_seqnum(struct ctdb_db_context *ctdb_db, uint64_t *seqnum)
4033 const char *keyname = CTDB_DB_SEQNUM_KEY;
4034 TDB_DATA key, data;
4035 struct ctdb_ltdb_header header;
4036 int ret;
4038 key.dptr = (uint8_t *)discard_const(keyname);
4039 key.dsize = strlen(keyname) + 1;
4041 ret = ctdb_ltdb_fetch(ctdb_db, key, &header, ctdb_db, &data);
4042 if (ret != 0) {
4043 *seqnum = 0;
4044 return 0;
4047 if (data.dsize == 0) {
4048 *seqnum = 0;
4049 return 0;
4052 if (data.dsize != sizeof(*seqnum)) {
4053 DEBUG(DEBUG_ERR, (__location__ " Invalid data recived len=%zi\n",
4054 data.dsize));
4055 talloc_free(data.dptr);
4056 return -1;
4059 *seqnum = *(uint64_t *)data.dptr;
4060 talloc_free(data.dptr);
4062 return 0;
4066 static int ctdb_store_db_seqnum(struct ctdb_transaction_handle *h,
4067 uint64_t seqnum)
4069 const char *keyname = CTDB_DB_SEQNUM_KEY;
4070 TDB_DATA key, data;
4072 key.dptr = (uint8_t *)discard_const(keyname);
4073 key.dsize = strlen(keyname) + 1;
4075 data.dptr = (uint8_t *)&seqnum;
4076 data.dsize = sizeof(seqnum);
4078 return ctdb_transaction_store(h, key, data);
4083 * commit a transaction
4085 int ctdb_transaction_commit(struct ctdb_transaction_handle *h)
4087 int ret;
4088 uint64_t old_seqnum, new_seqnum;
4089 int32_t status;
4090 struct timeval timeout;
4092 if (h->m_write == NULL) {
4093 /* no changes were made */
4094 talloc_free(h);
4095 return 0;
4098 ret = ctdb_fetch_db_seqnum(h->ctdb_db, &old_seqnum);
4099 if (ret != 0) {
4100 DEBUG(DEBUG_ERR, (__location__ " failed to fetch db sequence number\n"));
4101 ret = -1;
4102 goto done;
4105 new_seqnum = old_seqnum + 1;
4106 ret = ctdb_store_db_seqnum(h, new_seqnum);
4107 if (ret != 0) {
4108 DEBUG(DEBUG_ERR, (__location__ " failed to store db sequence number\n"));
4109 ret = -1;
4110 goto done;
4113 again:
4114 timeout = timeval_current_ofs(30,0);
4115 ret = ctdb_control(h->ctdb_db->ctdb, CTDB_CURRENT_NODE,
4116 h->ctdb_db->db_id,
4117 CTDB_CONTROL_TRANS3_COMMIT, 0,
4118 ctdb_marshall_finish(h->m_write), NULL, NULL,
4119 &status, &timeout, NULL);
4120 if (ret != 0 || status != 0) {
4122 * TRANS3_COMMIT control will only fail if recovery has been
4123 * triggered. Check if the database has been updated or not.
4125 ret = ctdb_fetch_db_seqnum(h->ctdb_db, &new_seqnum);
4126 if (ret != 0) {
4127 DEBUG(DEBUG_ERR, (__location__ " failed to fetch db sequence number\n"));
4128 goto done;
4131 if (new_seqnum == old_seqnum) {
4132 /* Database not yet updated, try again */
4133 goto again;
4136 if (new_seqnum != (old_seqnum + 1)) {
4137 DEBUG(DEBUG_ERR, (__location__ " new seqnum [%llu] != old seqnum [%llu] + 1\n",
4138 (long long unsigned)new_seqnum,
4139 (long long unsigned)old_seqnum));
4140 ret = -1;
4141 goto done;
4145 ret = 0;
4147 done:
4148 talloc_free(h);
4149 return ret;
4153 * cancel a transaction
4155 int ctdb_transaction_cancel(struct ctdb_transaction_handle *h)
4157 talloc_free(h);
4158 return 0;
4163 recovery daemon ping to main daemon
4165 int ctdb_ctrl_recd_ping(struct ctdb_context *ctdb)
4167 int ret;
4168 int32_t res;
4170 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_RECD_PING, 0, tdb_null,
4171 ctdb, NULL, &res, NULL, NULL);
4172 if (ret != 0 || res != 0) {
4173 DEBUG(DEBUG_ERR,("Failed to send recd ping\n"));
4174 return -1;
4177 return 0;
4181 get the status of running the monitor eventscripts: NULL means never run.
4183 int ctdb_ctrl_getscriptstatus(struct ctdb_context *ctdb,
4184 struct timeval timeout, uint32_t destnode,
4185 TALLOC_CTX *mem_ctx,
4186 enum ctdb_event type,
4187 struct ctdb_script_list_old **scripts)
4189 int ret;
4190 TDB_DATA outdata, indata;
4191 int32_t res;
4192 uint32_t uinttype = type;
4194 indata.dptr = (uint8_t *)&uinttype;
4195 indata.dsize = sizeof(uinttype);
4197 ret = ctdb_control(ctdb, destnode, 0,
4198 CTDB_CONTROL_GET_EVENT_SCRIPT_STATUS, 0, indata,
4199 mem_ctx, &outdata, &res, &timeout, NULL);
4200 if (ret != 0 || res != 0) {
4201 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getscriptstatus failed ret:%d res:%d\n", ret, res));
4202 return -1;
4205 if (outdata.dsize == 0) {
4206 *scripts = NULL;
4207 } else {
4208 *scripts = (struct ctdb_script_list_old *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
4209 talloc_free(outdata.dptr);
4212 return 0;
4216 tell the main daemon how long it took to lock the reclock file
4218 int ctdb_ctrl_report_recd_lock_latency(struct ctdb_context *ctdb, struct timeval timeout, double latency)
4220 int ret;
4221 int32_t res;
4222 TDB_DATA data;
4224 data.dptr = (uint8_t *)&latency;
4225 data.dsize = sizeof(latency);
4227 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_RECD_RECLOCK_LATENCY, 0, data,
4228 ctdb, NULL, &res, NULL, NULL);
4229 if (ret != 0 || res != 0) {
4230 DEBUG(DEBUG_ERR,("Failed to send recd reclock latency\n"));
4231 return -1;
4234 return 0;
4238 get the name of the reclock file
4240 int ctdb_ctrl_getreclock(struct ctdb_context *ctdb, struct timeval timeout,
4241 uint32_t destnode, TALLOC_CTX *mem_ctx,
4242 const char **name)
4244 int ret;
4245 int32_t res;
4246 TDB_DATA data;
4248 ret = ctdb_control(ctdb, destnode, 0,
4249 CTDB_CONTROL_GET_RECLOCK_FILE, 0, tdb_null,
4250 mem_ctx, &data, &res, &timeout, NULL);
4251 if (ret != 0 || res != 0) {
4252 return -1;
4255 if (data.dsize == 0) {
4256 *name = NULL;
4257 } else {
4258 *name = talloc_strdup(mem_ctx, discard_const(data.dptr));
4260 talloc_free(data.dptr);
4262 return 0;
4266 stop a node
4268 int ctdb_ctrl_stop_node(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
4270 int ret;
4271 int32_t res;
4273 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_STOP_NODE, 0, tdb_null,
4274 ctdb, NULL, &res, &timeout, NULL);
4275 if (ret != 0 || res != 0) {
4276 DEBUG(DEBUG_ERR,("Failed to stop node\n"));
4277 return -1;
4280 return 0;
4284 continue a node
4286 int ctdb_ctrl_continue_node(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
4288 int ret;
4290 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_CONTINUE_NODE, 0, tdb_null,
4291 ctdb, NULL, NULL, &timeout, NULL);
4292 if (ret != 0) {
4293 DEBUG(DEBUG_ERR,("Failed to continue node\n"));
4294 return -1;
4297 return 0;
4301 set the lmaster role for a node
4303 int ctdb_ctrl_setlmasterrole(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t lmasterrole)
4305 int ret;
4306 TDB_DATA data;
4307 int32_t res;
4309 data.dsize = sizeof(lmasterrole);
4310 data.dptr = (uint8_t *)&lmasterrole;
4312 ret = ctdb_control(ctdb, destnode, 0,
4313 CTDB_CONTROL_SET_LMASTERROLE, 0, data,
4314 NULL, NULL, &res, &timeout, NULL);
4315 if (ret != 0 || res != 0) {
4316 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setlmasterrole failed\n"));
4317 return -1;
4320 return 0;
4324 set the recmaster role for a node
4326 int ctdb_ctrl_setrecmasterrole(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmasterrole)
4328 int ret;
4329 TDB_DATA data;
4330 int32_t res;
4332 data.dsize = sizeof(recmasterrole);
4333 data.dptr = (uint8_t *)&recmasterrole;
4335 ret = ctdb_control(ctdb, destnode, 0,
4336 CTDB_CONTROL_SET_RECMASTERROLE, 0, data,
4337 NULL, NULL, &res, &timeout, NULL);
4338 if (ret != 0 || res != 0) {
4339 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setrecmasterrole failed\n"));
4340 return -1;
4343 return 0;
4346 /* enable an eventscript
4348 int ctdb_ctrl_enablescript(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, const char *script)
4350 int ret;
4351 TDB_DATA data;
4352 int32_t res;
4354 data.dsize = strlen(script) + 1;
4355 data.dptr = discard_const(script);
4357 ret = ctdb_control(ctdb, destnode, 0,
4358 CTDB_CONTROL_ENABLE_SCRIPT, 0, data,
4359 NULL, NULL, &res, &timeout, NULL);
4360 if (ret != 0 || res != 0) {
4361 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for enablescript failed\n"));
4362 return -1;
4365 return 0;
4368 /* disable an eventscript
4370 int ctdb_ctrl_disablescript(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, const char *script)
4372 int ret;
4373 TDB_DATA data;
4374 int32_t res;
4376 data.dsize = strlen(script) + 1;
4377 data.dptr = discard_const(script);
4379 ret = ctdb_control(ctdb, destnode, 0,
4380 CTDB_CONTROL_DISABLE_SCRIPT, 0, data,
4381 NULL, NULL, &res, &timeout, NULL);
4382 if (ret != 0 || res != 0) {
4383 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for disablescript failed\n"));
4384 return -1;
4387 return 0;
4391 int ctdb_ctrl_set_ban(struct ctdb_context *ctdb, struct timeval timeout,
4392 uint32_t destnode, struct ctdb_ban_state *bantime)
4394 int ret;
4395 TDB_DATA data;
4396 int32_t res;
4398 data.dsize = sizeof(*bantime);
4399 data.dptr = (uint8_t *)bantime;
4401 ret = ctdb_control(ctdb, destnode, 0,
4402 CTDB_CONTROL_SET_BAN_STATE, 0, data,
4403 NULL, NULL, &res, &timeout, NULL);
4404 if (ret != 0 || res != 0) {
4405 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set ban state failed\n"));
4406 return -1;
4409 return 0;
4413 int ctdb_ctrl_get_ban(struct ctdb_context *ctdb, struct timeval timeout,
4414 uint32_t destnode, TALLOC_CTX *mem_ctx,
4415 struct ctdb_ban_state **bantime)
4417 int ret;
4418 TDB_DATA outdata;
4419 int32_t res;
4420 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
4422 ret = ctdb_control(ctdb, destnode, 0,
4423 CTDB_CONTROL_GET_BAN_STATE, 0, tdb_null,
4424 tmp_ctx, &outdata, &res, &timeout, NULL);
4425 if (ret != 0 || res != 0) {
4426 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set ban state failed\n"));
4427 talloc_free(tmp_ctx);
4428 return -1;
4431 *bantime = (struct ctdb_ban_state *)talloc_steal(mem_ctx, outdata.dptr);
4432 talloc_free(tmp_ctx);
4434 return 0;
4437 int ctdb_ctrl_getstathistory(struct ctdb_context *ctdb,
4438 struct timeval timeout, uint32_t destnode,
4439 TALLOC_CTX *mem_ctx,
4440 struct ctdb_statistics_list_old **stats)
4442 int ret;
4443 TDB_DATA outdata;
4444 int32_t res;
4446 ret = ctdb_control(ctdb, destnode, 0,
4447 CTDB_CONTROL_GET_STAT_HISTORY, 0, tdb_null,
4448 mem_ctx, &outdata, &res, &timeout, NULL);
4449 if (ret != 0 || res != 0 || outdata.dsize == 0) {
4450 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getstathistory failed ret:%d res:%d\n", ret, res));
4451 return -1;
4454 *stats = (struct ctdb_statistics_list_old *)talloc_memdup(mem_ctx,
4455 outdata.dptr,
4456 outdata.dsize);
4457 talloc_free(outdata.dptr);
4459 return 0;
4462 struct ctdb_ltdb_header *ctdb_header_from_record_handle(struct ctdb_record_handle *h)
4464 if (h == NULL) {
4465 return NULL;
4468 return &h->header;
4472 struct ctdb_client_control_state *
4473 ctdb_ctrl_updaterecord_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, struct ctdb_db_context *ctdb_db, TDB_DATA key, struct ctdb_ltdb_header *header, TDB_DATA data)
4475 struct ctdb_client_control_state *handle;
4476 struct ctdb_marshall_buffer *m;
4477 struct ctdb_rec_data_old *rec;
4478 TDB_DATA outdata;
4480 m = talloc_zero(mem_ctx, struct ctdb_marshall_buffer);
4481 if (m == NULL) {
4482 DEBUG(DEBUG_ERR, ("Failed to allocate marshall buffer for update record\n"));
4483 return NULL;
4486 m->db_id = ctdb_db->db_id;
4488 rec = ctdb_marshall_record(m, 0, key, header, data);
4489 if (rec == NULL) {
4490 DEBUG(DEBUG_ERR,("Failed to marshall record for update record\n"));
4491 talloc_free(m);
4492 return NULL;
4494 m = talloc_realloc_size(mem_ctx, m, rec->length + offsetof(struct ctdb_marshall_buffer, data));
4495 if (m == NULL) {
4496 DEBUG(DEBUG_CRIT,(__location__ " Failed to expand recdata\n"));
4497 talloc_free(m);
4498 return NULL;
4500 m->count++;
4501 memcpy((uint8_t *)m + offsetof(struct ctdb_marshall_buffer, data), rec, rec->length);
4504 outdata.dptr = (uint8_t *)m;
4505 outdata.dsize = talloc_get_size(m);
4507 handle = ctdb_control_send(ctdb, destnode, 0,
4508 CTDB_CONTROL_UPDATE_RECORD, 0, outdata,
4509 mem_ctx, &timeout, NULL);
4510 talloc_free(m);
4511 return handle;
4514 int ctdb_ctrl_updaterecord_recv(struct ctdb_context *ctdb, struct ctdb_client_control_state *state)
4516 int ret;
4517 int32_t res;
4519 ret = ctdb_control_recv(ctdb, state, state, NULL, &res, NULL);
4520 if ( (ret != 0) || (res != 0) ){
4521 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_update_record_recv failed\n"));
4522 return -1;
4525 return 0;
4529 ctdb_ctrl_updaterecord(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, struct ctdb_db_context *ctdb_db, TDB_DATA key, struct ctdb_ltdb_header *header, TDB_DATA data)
4531 struct ctdb_client_control_state *state;
4533 state = ctdb_ctrl_updaterecord_send(ctdb, mem_ctx, timeout, destnode, ctdb_db, key, header, data);
4534 return ctdb_ctrl_updaterecord_recv(ctdb, state);
4543 set a database to be readonly
4545 struct ctdb_client_control_state *
4546 ctdb_ctrl_set_db_readonly_send(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid)
4548 TDB_DATA data;
4550 data.dptr = (uint8_t *)&dbid;
4551 data.dsize = sizeof(dbid);
4553 return ctdb_control_send(ctdb, destnode, 0,
4554 CTDB_CONTROL_SET_DB_READONLY, 0, data,
4555 ctdb, NULL, NULL);
4558 int ctdb_ctrl_set_db_readonly_recv(struct ctdb_context *ctdb, struct ctdb_client_control_state *state)
4560 int ret;
4561 int32_t res;
4563 ret = ctdb_control_recv(ctdb, state, ctdb, NULL, &res, NULL);
4564 if (ret != 0 || res != 0) {
4565 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_set_db_readonly_recv failed ret:%d res:%d\n", ret, res));
4566 return -1;
4569 return 0;
4572 int ctdb_ctrl_set_db_readonly(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid)
4574 struct ctdb_client_control_state *state;
4576 state = ctdb_ctrl_set_db_readonly_send(ctdb, destnode, dbid);
4577 return ctdb_ctrl_set_db_readonly_recv(ctdb, state);
4581 set a database to be sticky
4583 struct ctdb_client_control_state *
4584 ctdb_ctrl_set_db_sticky_send(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid)
4586 TDB_DATA data;
4588 data.dptr = (uint8_t *)&dbid;
4589 data.dsize = sizeof(dbid);
4591 return ctdb_control_send(ctdb, destnode, 0,
4592 CTDB_CONTROL_SET_DB_STICKY, 0, data,
4593 ctdb, NULL, NULL);
4596 int ctdb_ctrl_set_db_sticky_recv(struct ctdb_context *ctdb, struct ctdb_client_control_state *state)
4598 int ret;
4599 int32_t res;
4601 ret = ctdb_control_recv(ctdb, state, ctdb, NULL, &res, NULL);
4602 if (ret != 0 || res != 0) {
4603 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_set_db_sticky_recv failed ret:%d res:%d\n", ret, res));
4604 return -1;
4607 return 0;
4610 int ctdb_ctrl_set_db_sticky(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid)
4612 struct ctdb_client_control_state *state;
4614 state = ctdb_ctrl_set_db_sticky_send(ctdb, destnode, dbid);
4615 return ctdb_ctrl_set_db_sticky_recv(ctdb, state);