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/>.
24 #include "lib/util/dlinklist.h"
25 #include "system/network.h"
26 #include "system/filesys.h"
27 #include "system/locale.h"
29 #include "../include/ctdb_private.h"
30 #include "lib/util/dlinklist.h"
35 allocate a packet for use in client<->daemon communication
37 struct ctdb_req_header *_ctdbd_allocate_pkt(struct ctdb_context *ctdb,
39 enum ctdb_operation operation,
40 size_t length, size_t slength,
44 struct ctdb_req_header *hdr;
46 length = MAX(length, slength);
47 size = (length+(CTDB_DS_ALIGNMENT-1)) & ~(CTDB_DS_ALIGNMENT-1);
49 hdr = (struct ctdb_req_header *)talloc_zero_size(mem_ctx, size);
51 DEBUG(DEBUG_ERR,("Unable to allocate packet for operation %u of length %u\n",
52 operation, (unsigned)length));
55 talloc_set_name_const(hdr, type);
57 hdr->operation = operation;
58 hdr->ctdb_magic = CTDB_MAGIC;
59 hdr->ctdb_version = CTDB_VERSION;
60 hdr->srcnode = ctdb->pnn;
62 hdr->generation = ctdb->vnn_map->generation;
69 local version of ctdb_call
71 int ctdb_call_local(struct ctdb_db_context *ctdb_db, struct ctdb_call *call,
72 struct ctdb_ltdb_header *header, TALLOC_CTX *mem_ctx,
73 TDB_DATA *data, bool updatetdb)
75 struct ctdb_call_info *c;
76 struct ctdb_registered_call *fn;
77 struct ctdb_context *ctdb = ctdb_db->ctdb;
79 c = talloc(ctdb, struct ctdb_call_info);
80 CTDB_NO_MEMORY(ctdb, c);
83 c->call_data = &call->call_data;
84 c->record_data.dptr = talloc_memdup(c, data->dptr, data->dsize);
85 c->record_data.dsize = data->dsize;
86 CTDB_NO_MEMORY(ctdb, c->record_data.dptr);
92 for (fn=ctdb_db->calls;fn;fn=fn->next) {
93 if (fn->id == call->call_id) break;
96 ctdb_set_error(ctdb, "Unknown call id %u\n", call->call_id);
101 if (fn->fn(c) != 0) {
102 ctdb_set_error(ctdb, "ctdb_call %u failed\n", call->call_id);
107 /* we need to force the record to be written out if this was a remote access */
108 if (c->new_data == NULL) {
109 c->new_data = &c->record_data;
112 if (c->new_data && updatetdb) {
113 /* XXX check that we always have the lock here? */
114 if (ctdb_ltdb_store(ctdb_db, call->key, header, *c->new_data) != 0) {
115 ctdb_set_error(ctdb, "ctdb_call tdb_store failed\n");
122 call->reply_data = *c->reply_data;
124 talloc_steal(call, call->reply_data.dptr);
125 talloc_set_name_const(call->reply_data.dptr, __location__);
127 call->reply_data.dptr = NULL;
128 call->reply_data.dsize = 0;
130 call->status = c->status;
139 queue a packet for sending from client to daemon
141 static int ctdb_client_queue_pkt(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
143 return ctdb_queue_send(ctdb->daemon.queue, (uint8_t *)hdr, hdr->length);
148 called when a CTDB_REPLY_CALL packet comes in in the client
150 This packet comes in response to a CTDB_REQ_CALL request packet. It
151 contains any reply data from the call
153 static void ctdb_client_reply_call(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
155 struct ctdb_reply_call *c = (struct ctdb_reply_call *)hdr;
156 struct ctdb_client_call_state *state;
158 state = ctdb_reqid_find(ctdb, hdr->reqid, struct ctdb_client_call_state);
160 DEBUG(DEBUG_ERR,(__location__ " reqid %u not found\n", hdr->reqid));
164 if (hdr->reqid != state->reqid) {
165 /* we found a record but it was the wrong one */
166 DEBUG(DEBUG_ERR, ("Dropped client call reply with reqid:%u\n",hdr->reqid));
170 state->call->reply_data.dptr = c->data;
171 state->call->reply_data.dsize = c->datalen;
172 state->call->status = c->status;
174 talloc_steal(state, c);
176 state->state = CTDB_CALL_DONE;
178 if (state->async.fn) {
179 state->async.fn(state);
183 static void ctdb_client_reply_control(struct ctdb_context *ctdb, struct ctdb_req_header *hdr);
186 this is called in the client, when data comes in from the daemon
188 void ctdb_client_read_cb(uint8_t *data, size_t cnt, void *args)
190 struct ctdb_context *ctdb = talloc_get_type(args, struct ctdb_context);
191 struct ctdb_req_header *hdr = (struct ctdb_req_header *)data;
194 /* place the packet as a child of a tmp_ctx. We then use
195 talloc_free() below to free it. If any of the calls want
196 to keep it, then they will steal it somewhere else, and the
197 talloc_free() will be a no-op */
198 tmp_ctx = talloc_new(ctdb);
199 talloc_steal(tmp_ctx, hdr);
202 DEBUG(DEBUG_CRIT,("Daemon has exited - shutting down client\n"));
206 if (cnt < sizeof(*hdr)) {
207 DEBUG(DEBUG_CRIT,("Bad packet length %u in client\n", (unsigned)cnt));
210 if (cnt != hdr->length) {
211 ctdb_set_error(ctdb, "Bad header length %u expected %u in client\n",
212 (unsigned)hdr->length, (unsigned)cnt);
216 if (hdr->ctdb_magic != CTDB_MAGIC) {
217 ctdb_set_error(ctdb, "Non CTDB packet rejected in client\n");
221 if (hdr->ctdb_version != CTDB_VERSION) {
222 ctdb_set_error(ctdb, "Bad CTDB version 0x%x rejected in client\n", hdr->ctdb_version);
226 switch (hdr->operation) {
227 case CTDB_REPLY_CALL:
228 ctdb_client_reply_call(ctdb, hdr);
231 case CTDB_REQ_MESSAGE:
232 ctdb_request_message(ctdb, hdr);
235 case CTDB_REPLY_CONTROL:
236 ctdb_client_reply_control(ctdb, hdr);
240 DEBUG(DEBUG_CRIT,("bogus operation code:%u\n",hdr->operation));
244 talloc_free(tmp_ctx);
248 connect to a unix domain socket
250 int ctdb_socket_connect(struct ctdb_context *ctdb)
252 struct sockaddr_un addr;
254 memset(&addr, 0, sizeof(addr));
255 addr.sun_family = AF_UNIX;
256 strncpy(addr.sun_path, ctdb->daemon.name, sizeof(addr.sun_path));
258 ctdb->daemon.sd = socket(AF_UNIX, SOCK_STREAM, 0);
259 if (ctdb->daemon.sd == -1) {
260 DEBUG(DEBUG_ERR,(__location__ " Failed to open client socket. Errno:%s(%d)\n", strerror(errno), errno));
264 if (connect(ctdb->daemon.sd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
265 close(ctdb->daemon.sd);
266 ctdb->daemon.sd = -1;
267 DEBUG(DEBUG_ERR,(__location__ " Failed to connect client socket to daemon. Errno:%s(%d)\n", strerror(errno), errno));
271 set_nonblocking(ctdb->daemon.sd);
272 set_close_on_exec(ctdb->daemon.sd);
274 ctdb->daemon.queue = ctdb_queue_setup(ctdb, ctdb, ctdb->daemon.sd,
276 ctdb_client_read_cb, ctdb, "to-ctdbd");
281 struct ctdb_record_handle {
282 struct ctdb_db_context *ctdb_db;
285 struct ctdb_ltdb_header header;
290 make a recv call to the local ctdb daemon - called from client context
292 This is called when the program wants to wait for a ctdb_call to complete and get the
293 results. This call will block unless the call has already completed.
295 int ctdb_call_recv(struct ctdb_client_call_state *state, struct ctdb_call *call)
301 while (state->state < CTDB_CALL_DONE) {
302 event_loop_once(state->ctdb_db->ctdb->ev);
304 if (state->state != CTDB_CALL_DONE) {
305 DEBUG(DEBUG_ERR,(__location__ " ctdb_call_recv failed\n"));
310 if (state->call->reply_data.dsize) {
311 call->reply_data.dptr = talloc_memdup(state->ctdb_db,
312 state->call->reply_data.dptr,
313 state->call->reply_data.dsize);
314 call->reply_data.dsize = state->call->reply_data.dsize;
316 call->reply_data.dptr = NULL;
317 call->reply_data.dsize = 0;
319 call->status = state->call->status;
329 destroy a ctdb_call in client
331 static int ctdb_client_call_destructor(struct ctdb_client_call_state *state)
333 ctdb_reqid_remove(state->ctdb_db->ctdb, state->reqid);
338 construct an event driven local ctdb_call
340 this is used so that locally processed ctdb_call requests are processed
341 in an event driven manner
343 static struct ctdb_client_call_state *ctdb_client_call_local_send(struct ctdb_db_context *ctdb_db,
344 struct ctdb_call *call,
345 struct ctdb_ltdb_header *header,
348 struct ctdb_client_call_state *state;
349 struct ctdb_context *ctdb = ctdb_db->ctdb;
352 state = talloc_zero(ctdb_db, struct ctdb_client_call_state);
353 CTDB_NO_MEMORY_NULL(ctdb, state);
354 state->call = talloc_zero(state, struct ctdb_call);
355 CTDB_NO_MEMORY_NULL(ctdb, state->call);
357 talloc_steal(state, data->dptr);
359 state->state = CTDB_CALL_DONE;
360 *(state->call) = *call;
361 state->ctdb_db = ctdb_db;
363 ret = ctdb_call_local(ctdb_db, state->call, header, state, data, true);
365 DEBUG(DEBUG_DEBUG,("ctdb_call_local() failed, ignoring return code %d\n", ret));
372 make a ctdb call to the local daemon - async send. Called from client context.
374 This constructs a ctdb_call request and queues it for processing.
375 This call never blocks.
377 struct ctdb_client_call_state *ctdb_call_send(struct ctdb_db_context *ctdb_db,
378 struct ctdb_call *call)
380 struct ctdb_client_call_state *state;
381 struct ctdb_context *ctdb = ctdb_db->ctdb;
382 struct ctdb_ltdb_header header;
386 struct ctdb_req_call *c;
388 /* if the domain socket is not yet open, open it */
389 if (ctdb->daemon.sd==-1) {
390 ctdb_socket_connect(ctdb);
393 ret = ctdb_ltdb_lock(ctdb_db, call->key);
395 DEBUG(DEBUG_ERR,(__location__ " Failed to get chainlock\n"));
399 ret = ctdb_ltdb_fetch(ctdb_db, call->key, &header, ctdb_db, &data);
401 if ((call->flags & CTDB_IMMEDIATE_MIGRATION) && (header.flags & CTDB_REC_RO_HAVE_DELEGATIONS)) {
405 if (ret == 0 && header.dmaster == ctdb->pnn) {
406 state = ctdb_client_call_local_send(ctdb_db, call, &header, &data);
407 talloc_free(data.dptr);
408 ctdb_ltdb_unlock(ctdb_db, call->key);
412 ctdb_ltdb_unlock(ctdb_db, call->key);
413 talloc_free(data.dptr);
415 state = talloc_zero(ctdb_db, struct ctdb_client_call_state);
417 DEBUG(DEBUG_ERR, (__location__ " failed to allocate state\n"));
420 state->call = talloc_zero(state, struct ctdb_call);
421 if (state->call == NULL) {
422 DEBUG(DEBUG_ERR, (__location__ " failed to allocate state->call\n"));
426 len = offsetof(struct ctdb_req_call, data) + call->key.dsize + call->call_data.dsize;
427 c = ctdbd_allocate_pkt(ctdb, state, CTDB_REQ_CALL, len, struct ctdb_req_call);
429 DEBUG(DEBUG_ERR, (__location__ " failed to allocate packet\n"));
433 state->reqid = ctdb_reqid_new(ctdb, state);
434 state->ctdb_db = ctdb_db;
435 talloc_set_destructor(state, ctdb_client_call_destructor);
437 c->hdr.reqid = state->reqid;
438 c->flags = call->flags;
439 c->db_id = ctdb_db->db_id;
440 c->callid = call->call_id;
442 c->keylen = call->key.dsize;
443 c->calldatalen = call->call_data.dsize;
444 memcpy(&c->data[0], call->key.dptr, call->key.dsize);
445 memcpy(&c->data[call->key.dsize],
446 call->call_data.dptr, call->call_data.dsize);
447 *(state->call) = *call;
448 state->call->call_data.dptr = &c->data[call->key.dsize];
449 state->call->key.dptr = &c->data[0];
451 state->state = CTDB_CALL_WAIT;
454 ctdb_client_queue_pkt(ctdb, &c->hdr);
461 full ctdb_call. Equivalent to a ctdb_call_send() followed by a ctdb_call_recv()
463 int ctdb_call(struct ctdb_db_context *ctdb_db, struct ctdb_call *call)
465 struct ctdb_client_call_state *state;
467 state = ctdb_call_send(ctdb_db, call);
468 return ctdb_call_recv(state, call);
473 tell the daemon what messaging srvid we will use, and register the message
474 handler function in the client
476 int ctdb_client_set_message_handler(struct ctdb_context *ctdb, uint64_t srvid,
477 ctdb_msg_fn_t handler,
483 res = ctdb_control(ctdb, CTDB_CURRENT_NODE, srvid, CTDB_CONTROL_REGISTER_SRVID, 0,
484 tdb_null, NULL, NULL, &status, NULL, NULL);
485 if (res != 0 || status != 0) {
486 DEBUG(DEBUG_ERR,("Failed to register srvid %llu\n", (unsigned long long)srvid));
490 /* also need to register the handler with our own ctdb structure */
491 return ctdb_register_message_handler(ctdb, ctdb, srvid, handler, private_data);
495 tell the daemon we no longer want a srvid
497 int ctdb_client_remove_message_handler(struct ctdb_context *ctdb, uint64_t srvid, void *private_data)
502 res = ctdb_control(ctdb, CTDB_CURRENT_NODE, srvid, CTDB_CONTROL_DEREGISTER_SRVID, 0,
503 tdb_null, NULL, NULL, &status, NULL, NULL);
504 if (res != 0 || status != 0) {
505 DEBUG(DEBUG_ERR,("Failed to deregister srvid %llu\n", (unsigned long long)srvid));
509 /* also need to register the handler with our own ctdb structure */
510 ctdb_deregister_message_handler(ctdb, srvid, private_data);
517 int ctdb_client_check_message_handlers(struct ctdb_context *ctdb, uint64_t *ids, uint32_t num,
520 TDB_DATA indata, outdata;
525 indata.dptr = (uint8_t *)ids;
526 indata.dsize = num * sizeof(*ids);
528 res = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_CHECK_SRVIDS, 0,
529 indata, ctdb, &outdata, &status, NULL, NULL);
530 if (res != 0 || status != 0) {
531 DEBUG(DEBUG_ERR, (__location__ " failed to check srvids\n"));
535 if (outdata.dsize != num*sizeof(uint8_t)) {
536 DEBUG(DEBUG_ERR, (__location__ " expected %lu bytes, received %zi bytes\n",
537 num*sizeof(uint8_t), outdata.dsize));
538 talloc_free(outdata.dptr);
542 for (i=0; i<num; i++) {
543 result[i] = outdata.dptr[i];
546 talloc_free(outdata.dptr);
551 send a message - from client context
553 int ctdb_client_send_message(struct ctdb_context *ctdb, uint32_t pnn,
554 uint64_t srvid, TDB_DATA data)
556 struct ctdb_req_message *r;
559 len = offsetof(struct ctdb_req_message, data) + data.dsize;
560 r = ctdbd_allocate_pkt(ctdb, ctdb, CTDB_REQ_MESSAGE,
561 len, struct ctdb_req_message);
562 CTDB_NO_MEMORY(ctdb, r);
564 r->hdr.destnode = pnn;
566 r->datalen = data.dsize;
567 memcpy(&r->data[0], data.dptr, data.dsize);
569 res = ctdb_client_queue_pkt(ctdb, &r->hdr);
576 cancel a ctdb_fetch_lock operation, releasing the lock
578 static int fetch_lock_destructor(struct ctdb_record_handle *h)
580 ctdb_ltdb_unlock(h->ctdb_db, h->key);
585 force the migration of a record to this node
587 static int ctdb_client_force_migration(struct ctdb_db_context *ctdb_db, TDB_DATA key)
589 struct ctdb_call call;
591 call.call_id = CTDB_NULL_FUNC;
593 call.flags = CTDB_IMMEDIATE_MIGRATION;
594 return ctdb_call(ctdb_db, &call);
598 try to fetch a readonly copy of a record
601 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)
605 struct ctdb_call call;
608 call.call_id = CTDB_FETCH_WITH_HEADER_FUNC;
609 call.call_data.dptr = NULL;
610 call.call_data.dsize = 0;
612 call.flags = CTDB_WANT_READONLY;
613 ret = ctdb_call(ctdb_db, &call);
618 if (call.reply_data.dsize < sizeof(struct ctdb_ltdb_header)) {
622 *hdr = talloc_memdup(mem_ctx, &call.reply_data.dptr[0], sizeof(struct ctdb_ltdb_header));
624 talloc_free(call.reply_data.dptr);
628 data->dsize = call.reply_data.dsize - sizeof(struct ctdb_ltdb_header);
629 data->dptr = talloc_memdup(mem_ctx, &call.reply_data.dptr[sizeof(struct ctdb_ltdb_header)], data->dsize);
630 if (data->dptr == NULL) {
631 talloc_free(call.reply_data.dptr);
640 get a lock on a record, and return the records data. Blocks until it gets the lock
642 struct ctdb_record_handle *ctdb_fetch_lock(struct ctdb_db_context *ctdb_db, TALLOC_CTX *mem_ctx,
643 TDB_DATA key, TDB_DATA *data)
646 struct ctdb_record_handle *h;
649 procedure is as follows:
651 1) get the chain lock.
652 2) check if we are dmaster
653 3) if we are the dmaster then return handle
654 4) if not dmaster then ask ctdb daemon to make us dmaster, and wait for
656 5) when we get the reply, goto (1)
659 h = talloc_zero(mem_ctx, struct ctdb_record_handle);
664 h->ctdb_db = ctdb_db;
666 h->key.dptr = talloc_memdup(h, key.dptr, key.dsize);
667 if (h->key.dptr == NULL) {
673 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: key=%*.*s\n", (int)key.dsize, (int)key.dsize,
674 (const char *)key.dptr));
677 /* step 1 - get the chain lock */
678 ret = ctdb_ltdb_lock(ctdb_db, key);
680 DEBUG(DEBUG_ERR, (__location__ " failed to lock ltdb record\n"));
685 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: got chain lock\n"));
687 talloc_set_destructor(h, fetch_lock_destructor);
689 ret = ctdb_ltdb_fetch(ctdb_db, key, &h->header, h, data);
691 /* when torturing, ensure we test the remote path */
692 if ((ctdb_db->ctdb->flags & CTDB_FLAG_TORTURE) &&
694 h->header.dmaster = (uint32_t)-1;
698 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: done local fetch\n"));
700 if (ret != 0 || h->header.dmaster != ctdb_db->ctdb->pnn) {
701 ctdb_ltdb_unlock(ctdb_db, key);
702 ret = ctdb_client_force_migration(ctdb_db, key);
704 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: force_migration failed\n"));
711 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: we are dmaster - done\n"));
716 get a readonly lock on a record, and return the records data. Blocks until it gets the lock
718 struct ctdb_record_handle *
719 ctdb_fetch_readonly_lock(
720 struct ctdb_db_context *ctdb_db, TALLOC_CTX *mem_ctx,
721 TDB_DATA key, TDB_DATA *data,
725 struct ctdb_record_handle *h;
726 struct ctdb_ltdb_header *roheader = NULL;
728 h = talloc_zero(mem_ctx, struct ctdb_record_handle);
733 h->ctdb_db = ctdb_db;
735 h->key.dptr = talloc_memdup(h, key.dptr, key.dsize);
736 if (h->key.dptr == NULL) {
747 talloc_free(roheader);
750 talloc_free(data->dptr);
754 /* Lock the record/chain */
755 ret = ctdb_ltdb_lock(ctdb_db, key);
757 DEBUG(DEBUG_ERR, (__location__ " failed to lock ltdb record\n"));
762 talloc_set_destructor(h, fetch_lock_destructor);
764 /* Check if record exists yet in the TDB */
765 ret = ctdb_ltdb_fetch_with_header(ctdb_db, key, &h->header, h, data);
767 ctdb_ltdb_unlock(ctdb_db, key);
768 ret = ctdb_client_force_migration(ctdb_db, key);
770 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
777 /* if this is a request for read/write and we have delegations
778 we have to revoke all delegations first
781 && (h->header.dmaster == ctdb_db->ctdb->pnn)
782 && (h->header.flags & CTDB_REC_RO_HAVE_DELEGATIONS)) {
783 ctdb_ltdb_unlock(ctdb_db, key);
784 ret = ctdb_client_force_migration(ctdb_db, key);
786 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
793 /* if we are dmaster, just return the handle */
794 if (h->header.dmaster == ctdb_db->ctdb->pnn) {
798 if (read_only != 0) {
799 TDB_DATA rodata = {NULL, 0};
801 if ((h->header.flags & CTDB_REC_RO_HAVE_READONLY)
802 || (h->header.flags & CTDB_REC_RO_HAVE_DELEGATIONS)) {
806 ctdb_ltdb_unlock(ctdb_db, key);
807 ret = ctdb_client_fetch_readonly(ctdb_db, key, h, &roheader, &rodata);
809 DEBUG(DEBUG_ERR,("ctdb_fetch_readonly_lock: failed. force migration and try again\n"));
810 ret = ctdb_client_force_migration(ctdb_db, key);
812 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
820 if (!(roheader->flags&CTDB_REC_RO_HAVE_READONLY)) {
821 ret = ctdb_client_force_migration(ctdb_db, key);
823 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
831 ret = ctdb_ltdb_lock(ctdb_db, key);
833 DEBUG(DEBUG_ERR, (__location__ " failed to lock ltdb record\n"));
838 ret = ctdb_ltdb_fetch_with_header(ctdb_db, key, &h->header, h, data);
840 ctdb_ltdb_unlock(ctdb_db, key);
842 ret = ctdb_client_force_migration(ctdb_db, key);
844 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
855 /* we are not dmaster and this was not a request for a readonly lock
856 * so unlock the record, migrate it and try again
858 ctdb_ltdb_unlock(ctdb_db, key);
859 ret = ctdb_client_force_migration(ctdb_db, key);
861 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: force_migration failed\n"));
869 store some data to the record that was locked with ctdb_fetch_lock()
871 int ctdb_record_store(struct ctdb_record_handle *h, TDB_DATA data)
873 if (h->ctdb_db->persistent) {
874 DEBUG(DEBUG_ERR, (__location__ " ctdb_record_store prohibited for persistent dbs\n"));
878 return ctdb_ltdb_store(h->ctdb_db, h->key, &h->header, data);
882 non-locking fetch of a record
884 int ctdb_fetch(struct ctdb_db_context *ctdb_db, TALLOC_CTX *mem_ctx,
885 TDB_DATA key, TDB_DATA *data)
887 struct ctdb_call call;
890 call.call_id = CTDB_FETCH_FUNC;
891 call.call_data.dptr = NULL;
892 call.call_data.dsize = 0;
895 ret = ctdb_call(ctdb_db, &call);
898 *data = call.reply_data;
899 talloc_steal(mem_ctx, data->dptr);
908 called when a control completes or timesout to invoke the callback
909 function the user provided
911 static void invoke_control_callback(struct event_context *ev, struct timed_event *te,
912 struct timeval t, void *private_data)
914 struct ctdb_client_control_state *state;
915 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
918 state = talloc_get_type(private_data, struct ctdb_client_control_state);
919 talloc_steal(tmp_ctx, state);
921 ret = ctdb_control_recv(state->ctdb, state, state,
926 DEBUG(DEBUG_DEBUG,("ctdb_control_recv() failed, ignoring return code %d\n", ret));
929 talloc_free(tmp_ctx);
933 called when a CTDB_REPLY_CONTROL packet comes in in the client
935 This packet comes in response to a CTDB_REQ_CONTROL request packet. It
936 contains any reply data from the control
938 static void ctdb_client_reply_control(struct ctdb_context *ctdb,
939 struct ctdb_req_header *hdr)
941 struct ctdb_reply_control *c = (struct ctdb_reply_control *)hdr;
942 struct ctdb_client_control_state *state;
944 state = ctdb_reqid_find(ctdb, hdr->reqid, struct ctdb_client_control_state);
946 DEBUG(DEBUG_ERR,(__location__ " reqid %u not found\n", hdr->reqid));
950 if (hdr->reqid != state->reqid) {
951 /* we found a record but it was the wrong one */
952 DEBUG(DEBUG_ERR, ("Dropped orphaned reply control with reqid:%u\n",hdr->reqid));
956 state->outdata.dptr = c->data;
957 state->outdata.dsize = c->datalen;
958 state->status = c->status;
960 state->errormsg = talloc_strndup(state,
961 (char *)&c->data[c->datalen],
965 /* state->outdata now uses resources from c so we dont want c
966 to just dissappear from under us while state is still alive
968 talloc_steal(state, c);
970 state->state = CTDB_CONTROL_DONE;
972 /* if we had a callback registered for this control, pull the response
973 and call the callback.
975 if (state->async.fn) {
976 event_add_timed(ctdb->ev, state, timeval_zero(), invoke_control_callback, state);
982 destroy a ctdb_control in client
984 static int ctdb_client_control_destructor(struct ctdb_client_control_state *state)
986 ctdb_reqid_remove(state->ctdb, state->reqid);
991 /* time out handler for ctdb_control */
992 static void control_timeout_func(struct event_context *ev, struct timed_event *te,
993 struct timeval t, void *private_data)
995 struct ctdb_client_control_state *state = talloc_get_type(private_data, struct ctdb_client_control_state);
997 DEBUG(DEBUG_ERR,(__location__ " control timed out. reqid:%u opcode:%u "
998 "dstnode:%u\n", state->reqid, state->c->opcode,
999 state->c->hdr.destnode));
1001 state->state = CTDB_CONTROL_TIMEOUT;
1003 /* if we had a callback registered for this control, pull the response
1004 and call the callback.
1006 if (state->async.fn) {
1007 event_add_timed(state->ctdb->ev, state, timeval_zero(), invoke_control_callback, state);
1011 /* async version of send control request */
1012 struct ctdb_client_control_state *ctdb_control_send(struct ctdb_context *ctdb,
1013 uint32_t destnode, uint64_t srvid,
1014 uint32_t opcode, uint32_t flags, TDB_DATA data,
1015 TALLOC_CTX *mem_ctx,
1016 struct timeval *timeout,
1019 struct ctdb_client_control_state *state;
1021 struct ctdb_req_control *c;
1028 /* if the domain socket is not yet open, open it */
1029 if (ctdb->daemon.sd==-1) {
1030 ctdb_socket_connect(ctdb);
1033 state = talloc_zero(mem_ctx, struct ctdb_client_control_state);
1034 CTDB_NO_MEMORY_NULL(ctdb, state);
1037 state->reqid = ctdb_reqid_new(ctdb, state);
1038 state->state = CTDB_CONTROL_WAIT;
1039 state->errormsg = NULL;
1041 talloc_set_destructor(state, ctdb_client_control_destructor);
1043 len = offsetof(struct ctdb_req_control, data) + data.dsize;
1044 c = ctdbd_allocate_pkt(ctdb, state, CTDB_REQ_CONTROL,
1045 len, struct ctdb_req_control);
1047 CTDB_NO_MEMORY_NULL(ctdb, c);
1048 c->hdr.reqid = state->reqid;
1049 c->hdr.destnode = destnode;
1054 c->datalen = data.dsize;
1056 memcpy(&c->data[0], data.dptr, data.dsize);
1060 if (timeout && !timeval_is_zero(timeout)) {
1061 event_add_timed(ctdb->ev, state, *timeout, control_timeout_func, state);
1064 ret = ctdb_client_queue_pkt(ctdb, &(c->hdr));
1070 if (flags & CTDB_CTRL_FLAG_NOREPLY) {
1079 /* async version of receive control reply */
1080 int ctdb_control_recv(struct ctdb_context *ctdb,
1081 struct ctdb_client_control_state *state,
1082 TALLOC_CTX *mem_ctx,
1083 TDB_DATA *outdata, int32_t *status, char **errormsg)
1085 TALLOC_CTX *tmp_ctx;
1087 if (status != NULL) {
1090 if (errormsg != NULL) {
1094 if (state == NULL) {
1098 /* prevent double free of state */
1099 tmp_ctx = talloc_new(ctdb);
1100 talloc_steal(tmp_ctx, state);
1102 /* loop one event at a time until we either timeout or the control
1105 while (state->state == CTDB_CONTROL_WAIT) {
1106 event_loop_once(ctdb->ev);
1109 if (state->state != CTDB_CONTROL_DONE) {
1110 DEBUG(DEBUG_ERR,(__location__ " ctdb_control_recv failed\n"));
1111 if (state->async.fn) {
1112 state->async.fn(state);
1114 talloc_free(tmp_ctx);
1118 if (state->errormsg) {
1119 DEBUG(DEBUG_ERR,("ctdb_control error: '%s'\n", state->errormsg));
1121 (*errormsg) = talloc_move(mem_ctx, &state->errormsg);
1123 if (state->async.fn) {
1124 state->async.fn(state);
1126 talloc_free(tmp_ctx);
1131 *outdata = state->outdata;
1132 outdata->dptr = talloc_memdup(mem_ctx, outdata->dptr, outdata->dsize);
1136 *status = state->status;
1139 if (state->async.fn) {
1140 state->async.fn(state);
1143 talloc_free(tmp_ctx);
1150 send a ctdb control message
1151 timeout specifies how long we should wait for a reply.
1152 if timeout is NULL we wait indefinitely
1154 int ctdb_control(struct ctdb_context *ctdb, uint32_t destnode, uint64_t srvid,
1155 uint32_t opcode, uint32_t flags, TDB_DATA data,
1156 TALLOC_CTX *mem_ctx, TDB_DATA *outdata, int32_t *status,
1157 struct timeval *timeout,
1160 struct ctdb_client_control_state *state;
1162 state = ctdb_control_send(ctdb, destnode, srvid, opcode,
1163 flags, data, mem_ctx,
1166 /* FIXME: Error conditions in ctdb_control_send return NULL without
1167 * setting errormsg. So, there is no way to distinguish between sucess
1168 * and failure when CTDB_CTRL_FLAG_NOREPLY is set */
1169 if (flags & CTDB_CTRL_FLAG_NOREPLY) {
1170 if (status != NULL) {
1176 return ctdb_control_recv(ctdb, state, mem_ctx, outdata, status,
1184 a process exists call. Returns 0 if process exists, -1 otherwise
1186 int ctdb_ctrl_process_exists(struct ctdb_context *ctdb, uint32_t destnode, pid_t pid)
1192 data.dptr = (uint8_t*)&pid;
1193 data.dsize = sizeof(pid);
1195 ret = ctdb_control(ctdb, destnode, 0,
1196 CTDB_CONTROL_PROCESS_EXISTS, 0, data,
1197 NULL, NULL, &status, NULL, NULL);
1199 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for process_exists failed\n"));
1207 get remote statistics
1209 int ctdb_ctrl_statistics(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_statistics *status)
1215 ret = ctdb_control(ctdb, destnode, 0,
1216 CTDB_CONTROL_STATISTICS, 0, tdb_null,
1217 ctdb, &data, &res, NULL, NULL);
1218 if (ret != 0 || res != 0) {
1219 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for statistics failed\n"));
1223 if (data.dsize != sizeof(struct ctdb_statistics)) {
1224 DEBUG(DEBUG_ERR,(__location__ " Wrong statistics size %u - expected %u\n",
1225 (unsigned)data.dsize, (unsigned)sizeof(struct ctdb_statistics)));
1229 *status = *(struct ctdb_statistics *)data.dptr;
1230 talloc_free(data.dptr);
1236 shutdown a remote ctdb node
1238 int ctdb_ctrl_shutdown(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
1240 struct ctdb_client_control_state *state;
1242 state = ctdb_control_send(ctdb, destnode, 0,
1243 CTDB_CONTROL_SHUTDOWN, 0, tdb_null,
1244 NULL, &timeout, NULL);
1245 if (state == NULL) {
1246 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for shutdown failed\n"));
1254 get vnn map from a remote node
1256 int ctdb_ctrl_getvnnmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_vnn_map **vnnmap)
1261 struct ctdb_vnn_map_wire *map;
1263 ret = ctdb_control(ctdb, destnode, 0,
1264 CTDB_CONTROL_GETVNNMAP, 0, tdb_null,
1265 mem_ctx, &outdata, &res, &timeout, NULL);
1266 if (ret != 0 || res != 0) {
1267 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getvnnmap failed\n"));
1271 map = (struct ctdb_vnn_map_wire *)outdata.dptr;
1272 if (outdata.dsize < offsetof(struct ctdb_vnn_map_wire, map) ||
1273 outdata.dsize != map->size*sizeof(uint32_t) + offsetof(struct ctdb_vnn_map_wire, map)) {
1274 DEBUG(DEBUG_ERR,("Bad vnn map size received in ctdb_ctrl_getvnnmap\n"));
1278 (*vnnmap) = talloc(mem_ctx, struct ctdb_vnn_map);
1279 CTDB_NO_MEMORY(ctdb, *vnnmap);
1280 (*vnnmap)->generation = map->generation;
1281 (*vnnmap)->size = map->size;
1282 (*vnnmap)->map = talloc_array(*vnnmap, uint32_t, map->size);
1284 CTDB_NO_MEMORY(ctdb, (*vnnmap)->map);
1285 memcpy((*vnnmap)->map, map->map, sizeof(uint32_t)*map->size);
1286 talloc_free(outdata.dptr);
1293 get the recovery mode of a remote node
1295 struct ctdb_client_control_state *
1296 ctdb_ctrl_getrecmode_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode)
1298 return ctdb_control_send(ctdb, destnode, 0,
1299 CTDB_CONTROL_GET_RECMODE, 0, tdb_null,
1300 mem_ctx, &timeout, NULL);
1303 int ctdb_ctrl_getrecmode_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *recmode)
1308 ret = ctdb_control_recv(ctdb, state, mem_ctx, NULL, &res, NULL);
1310 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_getrecmode_recv failed\n"));
1315 *recmode = (uint32_t)res;
1321 int ctdb_ctrl_getrecmode(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, uint32_t *recmode)
1323 struct ctdb_client_control_state *state;
1325 state = ctdb_ctrl_getrecmode_send(ctdb, mem_ctx, timeout, destnode);
1326 return ctdb_ctrl_getrecmode_recv(ctdb, mem_ctx, state, recmode);
1333 set the recovery mode of a remote node
1335 int ctdb_ctrl_setrecmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmode)
1341 data.dsize = sizeof(uint32_t);
1342 data.dptr = (unsigned char *)&recmode;
1344 ret = ctdb_control(ctdb, destnode, 0,
1345 CTDB_CONTROL_SET_RECMODE, 0, data,
1346 NULL, NULL, &res, &timeout, NULL);
1347 if (ret != 0 || res != 0) {
1348 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setrecmode failed\n"));
1358 get the recovery master of a remote node
1360 struct ctdb_client_control_state *
1361 ctdb_ctrl_getrecmaster_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx,
1362 struct timeval timeout, uint32_t destnode)
1364 return ctdb_control_send(ctdb, destnode, 0,
1365 CTDB_CONTROL_GET_RECMASTER, 0, tdb_null,
1366 mem_ctx, &timeout, NULL);
1369 int ctdb_ctrl_getrecmaster_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *recmaster)
1374 ret = ctdb_control_recv(ctdb, state, mem_ctx, NULL, &res, NULL);
1376 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_getrecmaster_recv failed\n"));
1381 *recmaster = (uint32_t)res;
1387 int ctdb_ctrl_getrecmaster(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, uint32_t *recmaster)
1389 struct ctdb_client_control_state *state;
1391 state = ctdb_ctrl_getrecmaster_send(ctdb, mem_ctx, timeout, destnode);
1392 return ctdb_ctrl_getrecmaster_recv(ctdb, mem_ctx, state, recmaster);
1397 set the recovery master of a remote node
1399 int ctdb_ctrl_setrecmaster(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmaster)
1406 data.dsize = sizeof(uint32_t);
1407 data.dptr = (unsigned char *)&recmaster;
1409 ret = ctdb_control(ctdb, destnode, 0,
1410 CTDB_CONTROL_SET_RECMASTER, 0, data,
1411 NULL, NULL, &res, &timeout, NULL);
1412 if (ret != 0 || res != 0) {
1413 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setrecmaster failed\n"));
1422 get a list of databases off a remote node
1424 int ctdb_ctrl_getdbmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
1425 TALLOC_CTX *mem_ctx, struct ctdb_dbid_map **dbmap)
1431 ret = ctdb_control(ctdb, destnode, 0,
1432 CTDB_CONTROL_GET_DBMAP, 0, tdb_null,
1433 mem_ctx, &outdata, &res, &timeout, NULL);
1434 if (ret != 0 || res != 0) {
1435 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getdbmap failed ret:%d res:%d\n", ret, res));
1439 *dbmap = (struct ctdb_dbid_map *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
1440 talloc_free(outdata.dptr);
1446 get a list of nodes (vnn and flags ) from a remote node
1448 int ctdb_ctrl_getnodemap(struct ctdb_context *ctdb,
1449 struct timeval timeout, uint32_t destnode,
1450 TALLOC_CTX *mem_ctx, struct ctdb_node_map **nodemap)
1456 ret = ctdb_control(ctdb, destnode, 0,
1457 CTDB_CONTROL_GET_NODEMAP, 0, tdb_null,
1458 mem_ctx, &outdata, &res, &timeout, NULL);
1459 if (ret == 0 && res == -1 && outdata.dsize == 0) {
1460 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getnodes failed, falling back to ipv4-only control\n"));
1461 return ctdb_ctrl_getnodemapv4(ctdb, timeout, destnode, mem_ctx, nodemap);
1463 if (ret != 0 || res != 0 || outdata.dsize == 0) {
1464 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getnodes failed ret:%d res:%d\n", ret, res));
1468 *nodemap = (struct ctdb_node_map *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
1469 talloc_free(outdata.dptr);
1475 old style ipv4-only get a list of nodes (vnn and flags ) from a remote node
1477 int ctdb_ctrl_getnodemapv4(struct ctdb_context *ctdb,
1478 struct timeval timeout, uint32_t destnode,
1479 TALLOC_CTX *mem_ctx, struct ctdb_node_map **nodemap)
1483 struct ctdb_node_mapv4 *nodemapv4;
1486 ret = ctdb_control(ctdb, destnode, 0,
1487 CTDB_CONTROL_GET_NODEMAPv4, 0, tdb_null,
1488 mem_ctx, &outdata, &res, &timeout, NULL);
1489 if (ret != 0 || res != 0 || outdata.dsize == 0) {
1490 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getnodesv4 failed ret:%d res:%d\n", ret, res));
1494 nodemapv4 = (struct ctdb_node_mapv4 *)outdata.dptr;
1496 len = offsetof(struct ctdb_node_map, nodes) + nodemapv4->num*sizeof(struct ctdb_node_and_flags);
1497 (*nodemap) = talloc_zero_size(mem_ctx, len);
1498 CTDB_NO_MEMORY(ctdb, (*nodemap));
1500 (*nodemap)->num = nodemapv4->num;
1501 for (i=0; i<nodemapv4->num; i++) {
1502 (*nodemap)->nodes[i].pnn = nodemapv4->nodes[i].pnn;
1503 (*nodemap)->nodes[i].flags = nodemapv4->nodes[i].flags;
1504 (*nodemap)->nodes[i].addr.ip = nodemapv4->nodes[i].sin;
1505 (*nodemap)->nodes[i].addr.sa.sa_family = AF_INET;
1508 talloc_free(outdata.dptr);
1514 drop the transport, reload the nodes file and restart the transport
1516 int ctdb_ctrl_reload_nodes_file(struct ctdb_context *ctdb,
1517 struct timeval timeout, uint32_t destnode)
1522 ret = ctdb_control(ctdb, destnode, 0,
1523 CTDB_CONTROL_RELOAD_NODES_FILE, 0, tdb_null,
1524 NULL, NULL, &res, &timeout, NULL);
1525 if (ret != 0 || res != 0) {
1526 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for reloadnodesfile failed\n"));
1535 set vnn map on a node
1537 int ctdb_ctrl_setvnnmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
1538 TALLOC_CTX *mem_ctx, struct ctdb_vnn_map *vnnmap)
1543 struct ctdb_vnn_map_wire *map;
1546 len = offsetof(struct ctdb_vnn_map_wire, map) + sizeof(uint32_t)*vnnmap->size;
1547 map = talloc_size(mem_ctx, len);
1548 CTDB_NO_MEMORY(ctdb, map);
1550 map->generation = vnnmap->generation;
1551 map->size = vnnmap->size;
1552 memcpy(map->map, vnnmap->map, sizeof(uint32_t)*map->size);
1555 data.dptr = (uint8_t *)map;
1557 ret = ctdb_control(ctdb, destnode, 0,
1558 CTDB_CONTROL_SETVNNMAP, 0, data,
1559 NULL, NULL, &res, &timeout, NULL);
1560 if (ret != 0 || res != 0) {
1561 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setvnnmap failed\n"));
1572 async send for pull database
1574 struct ctdb_client_control_state *ctdb_ctrl_pulldb_send(
1575 struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid,
1576 uint32_t lmaster, TALLOC_CTX *mem_ctx, struct timeval timeout)
1579 struct ctdb_control_pulldb *pull;
1580 struct ctdb_client_control_state *state;
1582 pull = talloc(mem_ctx, struct ctdb_control_pulldb);
1583 CTDB_NO_MEMORY_NULL(ctdb, pull);
1586 pull->lmaster = lmaster;
1588 indata.dsize = sizeof(struct ctdb_control_pulldb);
1589 indata.dptr = (unsigned char *)pull;
1591 state = ctdb_control_send(ctdb, destnode, 0,
1592 CTDB_CONTROL_PULL_DB, 0, indata,
1593 mem_ctx, &timeout, NULL);
1600 async recv for pull database
1602 int ctdb_ctrl_pulldb_recv(
1603 struct ctdb_context *ctdb,
1604 TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state,
1610 ret = ctdb_control_recv(ctdb, state, mem_ctx, outdata, &res, NULL);
1611 if ( (ret != 0) || (res != 0) ){
1612 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_pulldb_recv failed\n"));
1620 pull all keys and records for a specific database on a node
1622 int ctdb_ctrl_pulldb(struct ctdb_context *ctdb, uint32_t destnode,
1623 uint32_t dbid, uint32_t lmaster,
1624 TALLOC_CTX *mem_ctx, struct timeval timeout,
1627 struct ctdb_client_control_state *state;
1629 state = ctdb_ctrl_pulldb_send(ctdb, destnode, dbid, lmaster, mem_ctx,
1632 return ctdb_ctrl_pulldb_recv(ctdb, mem_ctx, state, outdata);
1637 change dmaster for all keys in the database to the new value
1639 int ctdb_ctrl_setdmaster(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
1640 TALLOC_CTX *mem_ctx, uint32_t dbid, uint32_t dmaster)
1646 indata.dsize = 2*sizeof(uint32_t);
1647 indata.dptr = (unsigned char *)talloc_array(mem_ctx, uint32_t, 2);
1649 ((uint32_t *)(&indata.dptr[0]))[0] = dbid;
1650 ((uint32_t *)(&indata.dptr[0]))[1] = dmaster;
1652 ret = ctdb_control(ctdb, destnode, 0,
1653 CTDB_CONTROL_SET_DMASTER, 0, indata,
1654 NULL, NULL, &res, &timeout, NULL);
1655 if (ret != 0 || res != 0) {
1656 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setdmaster failed\n"));
1664 ping a node, return number of clients connected
1666 int ctdb_ctrl_ping(struct ctdb_context *ctdb, uint32_t destnode)
1671 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_PING, 0,
1672 tdb_null, NULL, NULL, &res, NULL, NULL);
1679 int ctdb_ctrl_get_runstate(struct ctdb_context *ctdb,
1680 struct timeval timeout,
1688 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_RUNSTATE, 0,
1689 tdb_null, ctdb, &outdata, &res, &timeout, NULL);
1690 if (ret != 0 || res != 0) {
1691 DEBUG(DEBUG_ERR,("ctdb_control for get_runstate failed\n"));
1692 return ret != 0 ? ret : res;
1695 if (outdata.dsize != sizeof(uint32_t)) {
1696 DEBUG(DEBUG_ERR,("Invalid return data in get_runstate\n"));
1697 talloc_free(outdata.dptr);
1701 if (runstate != NULL) {
1702 *runstate = *(uint32_t *)outdata.dptr;
1704 talloc_free(outdata.dptr);
1710 find the real path to a ltdb
1712 int ctdb_ctrl_getdbpath(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t dbid, TALLOC_CTX *mem_ctx,
1719 data.dptr = (uint8_t *)&dbid;
1720 data.dsize = sizeof(dbid);
1722 ret = ctdb_control(ctdb, destnode, 0,
1723 CTDB_CONTROL_GETDBPATH, 0, data,
1724 mem_ctx, &data, &res, &timeout, NULL);
1725 if (ret != 0 || res != 0) {
1729 (*path) = talloc_strndup(mem_ctx, (const char *)data.dptr, data.dsize);
1730 if ((*path) == NULL) {
1734 talloc_free(data.dptr);
1740 find the name of a db
1742 int ctdb_ctrl_getdbname(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t dbid, TALLOC_CTX *mem_ctx,
1749 data.dptr = (uint8_t *)&dbid;
1750 data.dsize = sizeof(dbid);
1752 ret = ctdb_control(ctdb, destnode, 0,
1753 CTDB_CONTROL_GET_DBNAME, 0, data,
1754 mem_ctx, &data, &res, &timeout, NULL);
1755 if (ret != 0 || res != 0) {
1759 (*name) = talloc_strndup(mem_ctx, (const char *)data.dptr, data.dsize);
1760 if ((*name) == NULL) {
1764 talloc_free(data.dptr);
1770 get the health status of a db
1772 int ctdb_ctrl_getdbhealth(struct ctdb_context *ctdb,
1773 struct timeval timeout,
1775 uint32_t dbid, TALLOC_CTX *mem_ctx,
1776 const char **reason)
1782 data.dptr = (uint8_t *)&dbid;
1783 data.dsize = sizeof(dbid);
1785 ret = ctdb_control(ctdb, destnode, 0,
1786 CTDB_CONTROL_DB_GET_HEALTH, 0, data,
1787 mem_ctx, &data, &res, &timeout, NULL);
1788 if (ret != 0 || res != 0) {
1792 if (data.dsize == 0) {
1797 (*reason) = talloc_strndup(mem_ctx, (const char *)data.dptr, data.dsize);
1798 if ((*reason) == NULL) {
1802 talloc_free(data.dptr);
1810 int ctdb_ctrl_createdb(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
1811 TALLOC_CTX *mem_ctx, const char *name, bool persistent)
1816 uint64_t tdb_flags = 0;
1818 data.dptr = discard_const(name);
1819 data.dsize = strlen(name)+1;
1821 /* Make sure that volatile databases use jenkins hash */
1823 tdb_flags = TDB_INCOMPATIBLE_HASH;
1826 ret = ctdb_control(ctdb, destnode, tdb_flags,
1827 persistent?CTDB_CONTROL_DB_ATTACH_PERSISTENT:CTDB_CONTROL_DB_ATTACH,
1829 mem_ctx, &data, &res, &timeout, NULL);
1831 if (ret != 0 || res != 0) {
1839 get debug level on a node
1841 int ctdb_ctrl_get_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, int32_t *level)
1847 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_DEBUG, 0, tdb_null,
1848 ctdb, &data, &res, NULL, NULL);
1849 if (ret != 0 || res != 0) {
1852 if (data.dsize != sizeof(int32_t)) {
1853 DEBUG(DEBUG_ERR,("Bad control reply size in ctdb_get_debuglevel (got %u)\n",
1854 (unsigned)data.dsize));
1857 *level = *(int32_t *)data.dptr;
1858 talloc_free(data.dptr);
1863 set debug level on a node
1865 int ctdb_ctrl_set_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, int32_t level)
1871 data.dptr = (uint8_t *)&level;
1872 data.dsize = sizeof(level);
1874 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SET_DEBUG, 0, data,
1875 NULL, NULL, &res, NULL, NULL);
1876 if (ret != 0 || res != 0) {
1884 get a list of connected nodes
1886 uint32_t *ctdb_get_connected_nodes(struct ctdb_context *ctdb,
1887 struct timeval timeout,
1888 TALLOC_CTX *mem_ctx,
1889 uint32_t *num_nodes)
1891 struct ctdb_node_map *map=NULL;
1897 ret = ctdb_ctrl_getnodemap(ctdb, timeout, CTDB_CURRENT_NODE, mem_ctx, &map);
1902 nodes = talloc_array(mem_ctx, uint32_t, map->num);
1903 if (nodes == NULL) {
1907 for (i=0;i<map->num;i++) {
1908 if (!(map->nodes[i].flags & NODE_FLAGS_DISCONNECTED)) {
1909 nodes[*num_nodes] = map->nodes[i].pnn;
1921 int ctdb_statistics_reset(struct ctdb_context *ctdb, uint32_t destnode)
1926 ret = ctdb_control(ctdb, destnode, 0,
1927 CTDB_CONTROL_STATISTICS_RESET, 0, tdb_null,
1928 NULL, NULL, &res, NULL, NULL);
1929 if (ret != 0 || res != 0) {
1930 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for reset statistics failed\n"));
1937 attach to a specific database - client call
1939 struct ctdb_db_context *ctdb_attach(struct ctdb_context *ctdb,
1940 struct timeval timeout,
1945 struct ctdb_db_context *ctdb_db;
1950 ctdb_db = ctdb_db_handle(ctdb, name);
1955 ctdb_db = talloc_zero(ctdb, struct ctdb_db_context);
1956 CTDB_NO_MEMORY_NULL(ctdb, ctdb_db);
1958 ctdb_db->ctdb = ctdb;
1959 ctdb_db->db_name = talloc_strdup(ctdb_db, name);
1960 CTDB_NO_MEMORY_NULL(ctdb, ctdb_db->db_name);
1962 data.dptr = discard_const(name);
1963 data.dsize = strlen(name)+1;
1965 /* CTDB has switched to using jenkins hash for volatile databases.
1966 * Even if tdb_flags do not explicitly mention TDB_INCOMPATIBLE_HASH,
1970 tdb_flags |= TDB_INCOMPATIBLE_HASH;
1973 /* tell ctdb daemon to attach */
1974 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, tdb_flags,
1975 persistent?CTDB_CONTROL_DB_ATTACH_PERSISTENT:CTDB_CONTROL_DB_ATTACH,
1976 0, data, ctdb_db, &data, &res, NULL, NULL);
1977 if (ret != 0 || res != 0 || data.dsize != sizeof(uint32_t)) {
1978 DEBUG(DEBUG_ERR,("Failed to attach to database '%s'\n", name));
1979 talloc_free(ctdb_db);
1983 ctdb_db->db_id = *(uint32_t *)data.dptr;
1984 talloc_free(data.dptr);
1986 ret = ctdb_ctrl_getdbpath(ctdb, timeout, CTDB_CURRENT_NODE, ctdb_db->db_id, ctdb_db, &ctdb_db->db_path);
1988 DEBUG(DEBUG_ERR,("Failed to get dbpath for database '%s'\n", name));
1989 talloc_free(ctdb_db);
1993 tdb_flags = persistent?TDB_DEFAULT:TDB_NOSYNC;
1994 if (ctdb->valgrinding) {
1995 tdb_flags |= TDB_NOMMAP;
1997 tdb_flags |= TDB_DISALLOW_NESTING;
1999 ctdb_db->ltdb = tdb_wrap_open(ctdb, ctdb_db->db_path, 0, tdb_flags, O_RDWR, 0);
2000 if (ctdb_db->ltdb == NULL) {
2001 ctdb_set_error(ctdb, "Failed to open tdb '%s'\n", ctdb_db->db_path);
2002 talloc_free(ctdb_db);
2006 ctdb_db->persistent = persistent;
2008 DLIST_ADD(ctdb->db_list, ctdb_db);
2010 /* add well known functions */
2011 ctdb_set_call(ctdb_db, ctdb_null_func, CTDB_NULL_FUNC);
2012 ctdb_set_call(ctdb_db, ctdb_fetch_func, CTDB_FETCH_FUNC);
2013 ctdb_set_call(ctdb_db, ctdb_fetch_with_header_func, CTDB_FETCH_WITH_HEADER_FUNC);
2020 setup a call for a database
2022 int ctdb_set_call(struct ctdb_db_context *ctdb_db, ctdb_fn_t fn, uint32_t id)
2024 struct ctdb_registered_call *call;
2029 struct ctdb_control_set_call c;
2032 /* this is no longer valid with the separate daemon architecture */
2033 c.db_id = ctdb_db->db_id;
2037 data.dptr = (uint8_t *)&c;
2038 data.dsize = sizeof(c);
2040 ret = ctdb_control(ctdb_db->ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_SET_CALL, 0,
2041 data, NULL, NULL, &status, NULL, NULL);
2042 if (ret != 0 || status != 0) {
2043 DEBUG(DEBUG_ERR,("ctdb_set_call failed for call %u\n", id));
2048 /* also register locally */
2049 call = talloc(ctdb_db, struct ctdb_registered_call);
2053 DLIST_ADD(ctdb_db->calls, call);
2058 struct traverse_state {
2061 ctdb_traverse_func fn;
2063 bool listemptyrecords;
2067 called on each key during a ctdb_traverse
2069 static void traverse_handler(struct ctdb_context *ctdb, uint64_t srvid, TDB_DATA data, void *p)
2071 struct traverse_state *state = (struct traverse_state *)p;
2072 struct ctdb_rec_data *d = (struct ctdb_rec_data *)data.dptr;
2075 if (data.dsize < sizeof(uint32_t) ||
2076 d->length != data.dsize) {
2077 DEBUG(DEBUG_ERR,("Bad data size %u in traverse_handler\n", (unsigned)data.dsize));
2082 key.dsize = d->keylen;
2083 key.dptr = &d->data[0];
2084 data.dsize = d->datalen;
2085 data.dptr = &d->data[d->keylen];
2087 if (key.dsize == 0 && data.dsize == 0) {
2088 /* end of traverse */
2093 if (!state->listemptyrecords &&
2094 data.dsize == sizeof(struct ctdb_ltdb_header))
2096 /* empty records are deleted records in ctdb */
2100 if (state->fn(ctdb, key, data, state->private_data) != 0) {
2108 * start a cluster wide traverse, calling the supplied fn on each record
2109 * return the number of records traversed, or -1 on error
2111 * Extendet variant with a flag to signal whether empty records should
2114 static int ctdb_traverse_ext(struct ctdb_db_context *ctdb_db,
2115 ctdb_traverse_func fn,
2116 bool withemptyrecords,
2120 struct ctdb_traverse_start_ext t;
2123 uint64_t srvid = (getpid() | 0xFLL<<60);
2124 struct traverse_state state;
2128 state.private_data = private_data;
2130 state.listemptyrecords = withemptyrecords;
2132 ret = ctdb_client_set_message_handler(ctdb_db->ctdb, srvid, traverse_handler, &state);
2134 DEBUG(DEBUG_ERR,("Failed to setup traverse handler\n"));
2138 t.db_id = ctdb_db->db_id;
2141 t.withemptyrecords = withemptyrecords;
2143 data.dptr = (uint8_t *)&t;
2144 data.dsize = sizeof(t);
2146 ret = ctdb_control(ctdb_db->ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_TRAVERSE_START_EXT, 0,
2147 data, NULL, NULL, &status, NULL, NULL);
2148 if (ret != 0 || status != 0) {
2149 DEBUG(DEBUG_ERR,("ctdb_traverse_all failed\n"));
2150 ctdb_client_remove_message_handler(ctdb_db->ctdb, srvid, &state);
2154 while (!state.done) {
2155 event_loop_once(ctdb_db->ctdb->ev);
2158 ret = ctdb_client_remove_message_handler(ctdb_db->ctdb, srvid, &state);
2160 DEBUG(DEBUG_ERR,("Failed to remove ctdb_traverse handler\n"));
2168 * start a cluster wide traverse, calling the supplied fn on each record
2169 * return the number of records traversed, or -1 on error
2171 * Standard version which does not list the empty records:
2172 * These are considered deleted.
2174 int ctdb_traverse(struct ctdb_db_context *ctdb_db, ctdb_traverse_func fn, void *private_data)
2176 return ctdb_traverse_ext(ctdb_db, fn, false, private_data);
2179 #define ISASCII(x) (isprint(x) && !strchr("\"\\", (x)))
2181 called on each key during a catdb
2183 int ctdb_dumpdb_record(struct ctdb_context *ctdb, TDB_DATA key, TDB_DATA data, void *p)
2186 struct ctdb_dump_db_context *c = (struct ctdb_dump_db_context *)p;
2188 struct ctdb_ltdb_header *h = (struct ctdb_ltdb_header *)data.dptr;
2190 fprintf(f, "key(%u) = \"", (unsigned)key.dsize);
2191 for (i=0;i<key.dsize;i++) {
2192 if (ISASCII(key.dptr[i])) {
2193 fprintf(f, "%c", key.dptr[i]);
2195 fprintf(f, "\\%02X", key.dptr[i]);
2200 fprintf(f, "dmaster: %u\n", h->dmaster);
2201 fprintf(f, "rsn: %llu\n", (unsigned long long)h->rsn);
2203 if (c->printlmaster && ctdb->vnn_map != NULL) {
2204 fprintf(f, "lmaster: %u\n", ctdb_lmaster(ctdb, &key));
2208 fprintf(f, "hash: 0x%08x\n", ctdb_hash(&key));
2211 if (c->printrecordflags) {
2212 fprintf(f, "flags: 0x%08x", h->flags);
2213 if (h->flags & CTDB_REC_FLAG_MIGRATED_WITH_DATA) printf(" MIGRATED_WITH_DATA");
2214 if (h->flags & CTDB_REC_FLAG_VACUUM_MIGRATED) printf(" VACUUM_MIGRATED");
2215 if (h->flags & CTDB_REC_FLAG_AUTOMATIC) printf(" AUTOMATIC");
2216 if (h->flags & CTDB_REC_RO_HAVE_DELEGATIONS) printf(" RO_HAVE_DELEGATIONS");
2217 if (h->flags & CTDB_REC_RO_HAVE_READONLY) printf(" RO_HAVE_READONLY");
2218 if (h->flags & CTDB_REC_RO_REVOKING_READONLY) printf(" RO_REVOKING_READONLY");
2219 if (h->flags & CTDB_REC_RO_REVOKE_COMPLETE) printf(" RO_REVOKE_COMPLETE");
2223 if (c->printdatasize) {
2224 fprintf(f, "data size: %u\n", (unsigned)data.dsize);
2226 fprintf(f, "data(%u) = \"", (unsigned)(data.dsize - sizeof(*h)));
2227 for (i=sizeof(*h);i<data.dsize;i++) {
2228 if (ISASCII(data.dptr[i])) {
2229 fprintf(f, "%c", data.dptr[i]);
2231 fprintf(f, "\\%02X", data.dptr[i]);
2243 convenience function to list all keys to stdout
2245 int ctdb_dump_db(struct ctdb_db_context *ctdb_db,
2246 struct ctdb_dump_db_context *ctx)
2248 return ctdb_traverse_ext(ctdb_db, ctdb_dumpdb_record,
2249 ctx->printemptyrecords, ctx);
2253 get the pid of a ctdb daemon
2255 int ctdb_ctrl_getpid(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *pid)
2260 ret = ctdb_control(ctdb, destnode, 0,
2261 CTDB_CONTROL_GET_PID, 0, tdb_null,
2262 NULL, NULL, &res, &timeout, NULL);
2264 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getpid failed\n"));
2275 async freeze send control
2277 struct ctdb_client_control_state *
2278 ctdb_ctrl_freeze_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, uint32_t priority)
2280 return ctdb_control_send(ctdb, destnode, priority,
2281 CTDB_CONTROL_FREEZE, 0, tdb_null,
2282 mem_ctx, &timeout, NULL);
2286 async freeze recv control
2288 int ctdb_ctrl_freeze_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state)
2293 ret = ctdb_control_recv(ctdb, state, mem_ctx, NULL, &res, NULL);
2294 if ( (ret != 0) || (res != 0) ){
2295 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_freeze_recv failed\n"));
2303 freeze databases of a certain priority
2305 int ctdb_ctrl_freeze_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t priority)
2307 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2308 struct ctdb_client_control_state *state;
2311 state = ctdb_ctrl_freeze_send(ctdb, tmp_ctx, timeout, destnode, priority);
2312 ret = ctdb_ctrl_freeze_recv(ctdb, tmp_ctx, state);
2313 talloc_free(tmp_ctx);
2318 /* Freeze all databases */
2319 int ctdb_ctrl_freeze(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2323 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
2324 if (ctdb_ctrl_freeze_priority(ctdb, timeout, destnode, i) != 0) {
2332 thaw databases of a certain priority
2334 int ctdb_ctrl_thaw_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t priority)
2339 ret = ctdb_control(ctdb, destnode, priority,
2340 CTDB_CONTROL_THAW, 0, tdb_null,
2341 NULL, NULL, &res, &timeout, NULL);
2342 if (ret != 0 || res != 0) {
2343 DEBUG(DEBUG_ERR,(__location__ " ctdb_control thaw failed\n"));
2350 /* thaw all databases */
2351 int ctdb_ctrl_thaw(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2353 return ctdb_ctrl_thaw_priority(ctdb, timeout, destnode, 0);
2357 get pnn of a node, or -1
2359 int ctdb_ctrl_getpnn(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2364 ret = ctdb_control(ctdb, destnode, 0,
2365 CTDB_CONTROL_GET_PNN, 0, tdb_null,
2366 NULL, NULL, &res, &timeout, NULL);
2368 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getpnn failed\n"));
2376 get the monitoring mode of a remote node
2378 int ctdb_ctrl_getmonmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *monmode)
2383 ret = ctdb_control(ctdb, destnode, 0,
2384 CTDB_CONTROL_GET_MONMODE, 0, tdb_null,
2385 NULL, NULL, &res, &timeout, NULL);
2387 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getmonmode failed\n"));
2398 set the monitoring mode of a remote node to active
2400 int ctdb_ctrl_enable_monmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2405 ret = ctdb_control(ctdb, destnode, 0,
2406 CTDB_CONTROL_ENABLE_MONITOR, 0, tdb_null,
2407 NULL, NULL,NULL, &timeout, NULL);
2409 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for enable_monitor failed\n"));
2419 set the monitoring mode of a remote node to disable
2421 int ctdb_ctrl_disable_monmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2426 ret = ctdb_control(ctdb, destnode, 0,
2427 CTDB_CONTROL_DISABLE_MONITOR, 0, tdb_null,
2428 NULL, NULL, NULL, &timeout, NULL);
2430 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for disable_monitor failed\n"));
2442 sent to a node to make it take over an ip address
2444 int ctdb_ctrl_takeover_ip(struct ctdb_context *ctdb, struct timeval timeout,
2445 uint32_t destnode, struct ctdb_public_ip *ip)
2448 struct ctdb_public_ipv4 ipv4;
2452 if (ip->addr.sa.sa_family == AF_INET) {
2454 ipv4.sin = ip->addr.ip;
2456 data.dsize = sizeof(ipv4);
2457 data.dptr = (uint8_t *)&ipv4;
2459 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_TAKEOVER_IPv4, 0, data, NULL,
2460 NULL, &res, &timeout, NULL);
2462 data.dsize = sizeof(*ip);
2463 data.dptr = (uint8_t *)ip;
2465 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_TAKEOVER_IP, 0, data, NULL,
2466 NULL, &res, &timeout, NULL);
2469 if (ret != 0 || res != 0) {
2470 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for takeover_ip failed\n"));
2479 sent to a node to make it release an ip address
2481 int ctdb_ctrl_release_ip(struct ctdb_context *ctdb, struct timeval timeout,
2482 uint32_t destnode, struct ctdb_public_ip *ip)
2485 struct ctdb_public_ipv4 ipv4;
2489 if (ip->addr.sa.sa_family == AF_INET) {
2491 ipv4.sin = ip->addr.ip;
2493 data.dsize = sizeof(ipv4);
2494 data.dptr = (uint8_t *)&ipv4;
2496 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_RELEASE_IPv4, 0, data, NULL,
2497 NULL, &res, &timeout, NULL);
2499 data.dsize = sizeof(*ip);
2500 data.dptr = (uint8_t *)ip;
2502 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_RELEASE_IP, 0, data, NULL,
2503 NULL, &res, &timeout, NULL);
2506 if (ret != 0 || res != 0) {
2507 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for release_ip failed\n"));
2518 int ctdb_ctrl_get_tunable(struct ctdb_context *ctdb,
2519 struct timeval timeout,
2521 const char *name, uint32_t *value)
2523 struct ctdb_control_get_tunable *t;
2524 TDB_DATA data, outdata;
2528 data.dsize = offsetof(struct ctdb_control_get_tunable, name) + strlen(name) + 1;
2529 data.dptr = talloc_size(ctdb, data.dsize);
2530 CTDB_NO_MEMORY(ctdb, data.dptr);
2532 t = (struct ctdb_control_get_tunable *)data.dptr;
2533 t->length = strlen(name)+1;
2534 memcpy(t->name, name, t->length);
2536 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_TUNABLE, 0, data, ctdb,
2537 &outdata, &res, &timeout, NULL);
2538 talloc_free(data.dptr);
2539 if (ret != 0 || res != 0) {
2540 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get_tunable failed\n"));
2541 return ret != 0 ? ret : res;
2544 if (outdata.dsize != sizeof(uint32_t)) {
2545 DEBUG(DEBUG_ERR,("Invalid return data in get_tunable\n"));
2546 talloc_free(outdata.dptr);
2550 *value = *(uint32_t *)outdata.dptr;
2551 talloc_free(outdata.dptr);
2559 int ctdb_ctrl_set_tunable(struct ctdb_context *ctdb,
2560 struct timeval timeout,
2562 const char *name, uint32_t value)
2564 struct ctdb_control_set_tunable *t;
2569 data.dsize = offsetof(struct ctdb_control_set_tunable, name) + strlen(name) + 1;
2570 data.dptr = talloc_size(ctdb, data.dsize);
2571 CTDB_NO_MEMORY(ctdb, data.dptr);
2573 t = (struct ctdb_control_set_tunable *)data.dptr;
2574 t->length = strlen(name)+1;
2575 memcpy(t->name, name, t->length);
2578 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SET_TUNABLE, 0, data, NULL,
2579 NULL, &res, &timeout, NULL);
2580 talloc_free(data.dptr);
2581 if (ret != 0 || res != 0) {
2582 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set_tunable failed\n"));
2592 int ctdb_ctrl_list_tunables(struct ctdb_context *ctdb,
2593 struct timeval timeout,
2595 TALLOC_CTX *mem_ctx,
2596 const char ***list, uint32_t *count)
2601 struct ctdb_control_list_tunable *t;
2604 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_LIST_TUNABLES, 0, tdb_null,
2605 mem_ctx, &outdata, &res, &timeout, NULL);
2606 if (ret != 0 || res != 0) {
2607 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for list_tunables failed\n"));
2611 t = (struct ctdb_control_list_tunable *)outdata.dptr;
2612 if (outdata.dsize < offsetof(struct ctdb_control_list_tunable, data) ||
2613 t->length > outdata.dsize-offsetof(struct ctdb_control_list_tunable, data)) {
2614 DEBUG(DEBUG_ERR,("Invalid data in list_tunables reply\n"));
2615 talloc_free(outdata.dptr);
2619 p = talloc_strndup(mem_ctx, (char *)t->data, t->length);
2620 CTDB_NO_MEMORY(ctdb, p);
2622 talloc_free(outdata.dptr);
2627 for (s=strtok_r(p, ":", &ptr); s; s=strtok_r(NULL, ":", &ptr)) {
2628 (*list) = talloc_realloc(mem_ctx, *list, const char *, 1+(*count));
2629 CTDB_NO_MEMORY(ctdb, *list);
2630 (*list)[*count] = talloc_strdup(*list, s);
2631 CTDB_NO_MEMORY(ctdb, (*list)[*count]);
2641 int ctdb_ctrl_get_public_ips_flags(struct ctdb_context *ctdb,
2642 struct timeval timeout, uint32_t destnode,
2643 TALLOC_CTX *mem_ctx,
2645 struct ctdb_all_public_ips **ips)
2651 ret = ctdb_control(ctdb, destnode, 0,
2652 CTDB_CONTROL_GET_PUBLIC_IPS, flags, tdb_null,
2653 mem_ctx, &outdata, &res, &timeout, NULL);
2654 if (ret == 0 && res == -1) {
2655 DEBUG(DEBUG_ERR,(__location__ " ctdb_control to get public ips failed, falling back to ipv4-only version\n"));
2656 return ctdb_ctrl_get_public_ipsv4(ctdb, timeout, destnode, mem_ctx, ips);
2658 if (ret != 0 || res != 0) {
2659 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getpublicips failed ret:%d res:%d\n", ret, res));
2663 *ips = (struct ctdb_all_public_ips *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
2664 talloc_free(outdata.dptr);
2669 int ctdb_ctrl_get_public_ips(struct ctdb_context *ctdb,
2670 struct timeval timeout, uint32_t destnode,
2671 TALLOC_CTX *mem_ctx,
2672 struct ctdb_all_public_ips **ips)
2674 return ctdb_ctrl_get_public_ips_flags(ctdb, timeout,
2679 int ctdb_ctrl_get_public_ipsv4(struct ctdb_context *ctdb,
2680 struct timeval timeout, uint32_t destnode,
2681 TALLOC_CTX *mem_ctx, struct ctdb_all_public_ips **ips)
2686 struct ctdb_all_public_ipsv4 *ipsv4;
2688 ret = ctdb_control(ctdb, destnode, 0,
2689 CTDB_CONTROL_GET_PUBLIC_IPSv4, 0, tdb_null,
2690 mem_ctx, &outdata, &res, &timeout, NULL);
2691 if (ret != 0 || res != 0) {
2692 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getpublicips failed\n"));
2696 ipsv4 = (struct ctdb_all_public_ipsv4 *)outdata.dptr;
2697 len = offsetof(struct ctdb_all_public_ips, ips) +
2698 ipsv4->num*sizeof(struct ctdb_public_ip);
2699 *ips = talloc_zero_size(mem_ctx, len);
2700 CTDB_NO_MEMORY(ctdb, *ips);
2701 (*ips)->num = ipsv4->num;
2702 for (i=0; i<ipsv4->num; i++) {
2703 (*ips)->ips[i].pnn = ipsv4->ips[i].pnn;
2704 (*ips)->ips[i].addr.ip = ipsv4->ips[i].sin;
2707 talloc_free(outdata.dptr);
2712 int ctdb_ctrl_get_public_ip_info(struct ctdb_context *ctdb,
2713 struct timeval timeout, uint32_t destnode,
2714 TALLOC_CTX *mem_ctx,
2715 const ctdb_sock_addr *addr,
2716 struct ctdb_control_public_ip_info **_info)
2722 struct ctdb_control_public_ip_info *info;
2726 indata.dptr = discard_const_p(uint8_t, addr);
2727 indata.dsize = sizeof(*addr);
2729 ret = ctdb_control(ctdb, destnode, 0,
2730 CTDB_CONTROL_GET_PUBLIC_IP_INFO, 0, indata,
2731 mem_ctx, &outdata, &res, &timeout, NULL);
2732 if (ret != 0 || res != 0) {
2733 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
2734 "failed ret:%d res:%d\n",
2739 len = offsetof(struct ctdb_control_public_ip_info, ifaces);
2740 if (len > outdata.dsize) {
2741 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
2742 "returned invalid data with size %u > %u\n",
2743 (unsigned int)outdata.dsize,
2744 (unsigned int)len));
2745 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
2749 info = (struct ctdb_control_public_ip_info *)outdata.dptr;
2750 len += info->num*sizeof(struct ctdb_control_iface_info);
2752 if (len > outdata.dsize) {
2753 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
2754 "returned invalid data with size %u > %u\n",
2755 (unsigned int)outdata.dsize,
2756 (unsigned int)len));
2757 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
2761 /* make sure we null terminate the returned strings */
2762 for (i=0; i < info->num; i++) {
2763 info->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
2766 *_info = (struct ctdb_control_public_ip_info *)talloc_memdup(mem_ctx,
2769 talloc_free(outdata.dptr);
2770 if (*_info == NULL) {
2771 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
2772 "talloc_memdup size %u failed\n",
2773 (unsigned int)outdata.dsize));
2780 int ctdb_ctrl_get_ifaces(struct ctdb_context *ctdb,
2781 struct timeval timeout, uint32_t destnode,
2782 TALLOC_CTX *mem_ctx,
2783 struct ctdb_control_get_ifaces **_ifaces)
2788 struct ctdb_control_get_ifaces *ifaces;
2792 ret = ctdb_control(ctdb, destnode, 0,
2793 CTDB_CONTROL_GET_IFACES, 0, tdb_null,
2794 mem_ctx, &outdata, &res, &timeout, NULL);
2795 if (ret != 0 || res != 0) {
2796 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
2797 "failed ret:%d res:%d\n",
2802 len = offsetof(struct ctdb_control_get_ifaces, ifaces);
2803 if (len > outdata.dsize) {
2804 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
2805 "returned invalid data with size %u > %u\n",
2806 (unsigned int)outdata.dsize,
2807 (unsigned int)len));
2808 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
2812 ifaces = (struct ctdb_control_get_ifaces *)outdata.dptr;
2813 len += ifaces->num*sizeof(struct ctdb_control_iface_info);
2815 if (len > outdata.dsize) {
2816 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
2817 "returned invalid data with size %u > %u\n",
2818 (unsigned int)outdata.dsize,
2819 (unsigned int)len));
2820 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
2824 /* make sure we null terminate the returned strings */
2825 for (i=0; i < ifaces->num; i++) {
2826 ifaces->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
2829 *_ifaces = (struct ctdb_control_get_ifaces *)talloc_memdup(mem_ctx,
2832 talloc_free(outdata.dptr);
2833 if (*_ifaces == NULL) {
2834 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
2835 "talloc_memdup size %u failed\n",
2836 (unsigned int)outdata.dsize));
2843 int ctdb_ctrl_set_iface_link(struct ctdb_context *ctdb,
2844 struct timeval timeout, uint32_t destnode,
2845 TALLOC_CTX *mem_ctx,
2846 const struct ctdb_control_iface_info *info)
2852 indata.dptr = discard_const_p(uint8_t, info);
2853 indata.dsize = sizeof(*info);
2855 ret = ctdb_control(ctdb, destnode, 0,
2856 CTDB_CONTROL_SET_IFACE_LINK_STATE, 0, indata,
2857 mem_ctx, NULL, &res, &timeout, NULL);
2858 if (ret != 0 || res != 0) {
2859 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set iface link "
2860 "failed ret:%d res:%d\n",
2869 set/clear the permanent disabled bit on a remote node
2871 int ctdb_ctrl_modflags(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
2872 uint32_t set, uint32_t clear)
2876 struct ctdb_node_map *nodemap=NULL;
2877 struct ctdb_node_flag_change c;
2878 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2883 /* find the recovery master */
2884 ret = ctdb_ctrl_getrecmaster(ctdb, tmp_ctx, timeout, CTDB_CURRENT_NODE, &recmaster);
2886 DEBUG(DEBUG_ERR, (__location__ " Unable to get recmaster from local node\n"));
2887 talloc_free(tmp_ctx);
2892 /* read the node flags from the recmaster */
2893 ret = ctdb_ctrl_getnodemap(ctdb, timeout, recmaster, tmp_ctx, &nodemap);
2895 DEBUG(DEBUG_ERR, (__location__ " Unable to get nodemap from node %u\n", destnode));
2896 talloc_free(tmp_ctx);
2899 if (destnode >= nodemap->num) {
2900 DEBUG(DEBUG_ERR,(__location__ " Nodemap from recmaster does not contain node %d\n", destnode));
2901 talloc_free(tmp_ctx);
2906 c.old_flags = nodemap->nodes[destnode].flags;
2907 c.new_flags = c.old_flags;
2909 c.new_flags &= ~clear;
2911 data.dsize = sizeof(c);
2912 data.dptr = (unsigned char *)&c;
2914 /* send the flags update to all connected nodes */
2915 nodes = list_of_connected_nodes(ctdb, nodemap, tmp_ctx, true);
2917 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_MODIFY_FLAGS,
2919 timeout, false, data,
2922 DEBUG(DEBUG_ERR, (__location__ " Unable to update nodeflags on remote nodes\n"));
2924 talloc_free(tmp_ctx);
2928 talloc_free(tmp_ctx);
2936 int ctdb_ctrl_get_all_tunables(struct ctdb_context *ctdb,
2937 struct timeval timeout,
2939 struct ctdb_tunable *tunables)
2945 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_ALL_TUNABLES, 0, tdb_null, ctdb,
2946 &outdata, &res, &timeout, NULL);
2947 if (ret != 0 || res != 0) {
2948 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get all tunables failed\n"));
2952 if (outdata.dsize != sizeof(*tunables)) {
2953 DEBUG(DEBUG_ERR,(__location__ " bad data size %u in ctdb_ctrl_get_all_tunables should be %u\n",
2954 (unsigned)outdata.dsize, (unsigned)sizeof(*tunables)));
2958 *tunables = *(struct ctdb_tunable *)outdata.dptr;
2959 talloc_free(outdata.dptr);
2964 add a public address to a node
2966 int ctdb_ctrl_add_public_ip(struct ctdb_context *ctdb,
2967 struct timeval timeout,
2969 struct ctdb_control_ip_iface *pub)
2975 data.dsize = offsetof(struct ctdb_control_ip_iface, iface) + pub->len;
2976 data.dptr = (unsigned char *)pub;
2978 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_ADD_PUBLIC_IP, 0, data, NULL,
2979 NULL, &res, &timeout, NULL);
2980 if (ret != 0 || res != 0) {
2981 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for add_public_ip failed\n"));
2989 delete a public address from a node
2991 int ctdb_ctrl_del_public_ip(struct ctdb_context *ctdb,
2992 struct timeval timeout,
2994 struct ctdb_control_ip_iface *pub)
3000 data.dsize = offsetof(struct ctdb_control_ip_iface, iface) + pub->len;
3001 data.dptr = (unsigned char *)pub;
3003 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_DEL_PUBLIC_IP, 0, data, NULL,
3004 NULL, &res, &timeout, NULL);
3005 if (ret != 0 || res != 0) {
3006 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for del_public_ip failed\n"));
3014 kill a tcp connection
3016 int ctdb_ctrl_killtcp(struct ctdb_context *ctdb,
3017 struct timeval timeout,
3019 struct ctdb_control_killtcp *killtcp)
3025 data.dsize = sizeof(struct ctdb_control_killtcp);
3026 data.dptr = (unsigned char *)killtcp;
3028 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_KILL_TCP, 0, data, NULL,
3029 NULL, &res, &timeout, NULL);
3030 if (ret != 0 || res != 0) {
3031 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for killtcp failed\n"));
3041 int ctdb_ctrl_gratious_arp(struct ctdb_context *ctdb,
3042 struct timeval timeout,
3044 ctdb_sock_addr *addr,
3050 struct ctdb_control_gratious_arp *gratious_arp;
3051 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3054 len = strlen(ifname)+1;
3055 gratious_arp = talloc_size(tmp_ctx,
3056 offsetof(struct ctdb_control_gratious_arp, iface) + len);
3057 CTDB_NO_MEMORY(ctdb, gratious_arp);
3059 gratious_arp->addr = *addr;
3060 gratious_arp->len = len;
3061 memcpy(&gratious_arp->iface[0], ifname, len);
3064 data.dsize = offsetof(struct ctdb_control_gratious_arp, iface) + len;
3065 data.dptr = (unsigned char *)gratious_arp;
3067 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SEND_GRATIOUS_ARP, 0, data, NULL,
3068 NULL, &res, &timeout, NULL);
3069 if (ret != 0 || res != 0) {
3070 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for gratious_arp failed\n"));
3071 talloc_free(tmp_ctx);
3075 talloc_free(tmp_ctx);
3080 get a list of all tcp tickles that a node knows about for a particular vnn
3082 int ctdb_ctrl_get_tcp_tickles(struct ctdb_context *ctdb,
3083 struct timeval timeout, uint32_t destnode,
3084 TALLOC_CTX *mem_ctx,
3085 ctdb_sock_addr *addr,
3086 struct ctdb_control_tcp_tickle_list **list)
3089 TDB_DATA data, outdata;
3092 data.dptr = (uint8_t*)addr;
3093 data.dsize = sizeof(ctdb_sock_addr);
3095 ret = ctdb_control(ctdb, destnode, 0,
3096 CTDB_CONTROL_GET_TCP_TICKLE_LIST, 0, data,
3097 mem_ctx, &outdata, &status, NULL, NULL);
3098 if (ret != 0 || status != 0) {
3099 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get tcp tickles failed\n"));
3103 *list = (struct ctdb_control_tcp_tickle_list *)outdata.dptr;
3109 register a server id
3111 int ctdb_ctrl_register_server_id(struct ctdb_context *ctdb,
3112 struct timeval timeout,
3113 struct ctdb_server_id *id)
3119 data.dsize = sizeof(struct ctdb_server_id);
3120 data.dptr = (unsigned char *)id;
3122 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0,
3123 CTDB_CONTROL_REGISTER_SERVER_ID,
3125 NULL, &res, &timeout, NULL);
3126 if (ret != 0 || res != 0) {
3127 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for register server id failed\n"));
3135 unregister a server id
3137 int ctdb_ctrl_unregister_server_id(struct ctdb_context *ctdb,
3138 struct timeval timeout,
3139 struct ctdb_server_id *id)
3145 data.dsize = sizeof(struct ctdb_server_id);
3146 data.dptr = (unsigned char *)id;
3148 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0,
3149 CTDB_CONTROL_UNREGISTER_SERVER_ID,
3151 NULL, &res, &timeout, NULL);
3152 if (ret != 0 || res != 0) {
3153 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for unregister server id failed\n"));
3162 check if a server id exists
3164 if a server id does exist, return *status == 1, otherwise *status == 0
3166 int ctdb_ctrl_check_server_id(struct ctdb_context *ctdb,
3167 struct timeval timeout,
3169 struct ctdb_server_id *id,
3176 data.dsize = sizeof(struct ctdb_server_id);
3177 data.dptr = (unsigned char *)id;
3179 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_CHECK_SERVER_ID,
3181 NULL, &res, &timeout, NULL);
3183 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for check server id failed\n"));
3197 get the list of server ids that are registered on a node
3199 int ctdb_ctrl_get_server_id_list(struct ctdb_context *ctdb,
3200 TALLOC_CTX *mem_ctx,
3201 struct timeval timeout, uint32_t destnode,
3202 struct ctdb_server_id_list **svid_list)
3208 ret = ctdb_control(ctdb, destnode, 0,
3209 CTDB_CONTROL_GET_SERVER_ID_LIST, 0, tdb_null,
3210 mem_ctx, &outdata, &res, &timeout, NULL);
3211 if (ret != 0 || res != 0) {
3212 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get_server_id_list failed\n"));
3216 *svid_list = (struct ctdb_server_id_list *)talloc_steal(mem_ctx, outdata.dptr);
3222 initialise the ctdb daemon for client applications
3224 NOTE: In current code the daemon does not fork. This is for testing purposes only
3225 and to simplify the code.
3227 struct ctdb_context *ctdb_init(struct event_context *ev)
3230 struct ctdb_context *ctdb;
3232 ctdb = talloc_zero(ev, struct ctdb_context);
3234 DEBUG(DEBUG_ERR,(__location__ " talloc_zero failed.\n"));
3238 ctdb->idr = idr_init(ctdb);
3239 /* Wrap early to exercise code. */
3240 ctdb->lastid = INT_MAX-200;
3241 CTDB_NO_MEMORY_NULL(ctdb, ctdb->idr);
3243 ret = ctdb_set_socketname(ctdb, CTDB_PATH);
3245 DEBUG(DEBUG_ERR,(__location__ " ctdb_set_socketname failed.\n"));
3250 ctdb->statistics.statistics_start_time = timeval_current();
3259 void ctdb_set_flags(struct ctdb_context *ctdb, unsigned flags)
3261 ctdb->flags |= flags;
3265 setup the local socket name
3267 int ctdb_set_socketname(struct ctdb_context *ctdb, const char *socketname)
3269 ctdb->daemon.name = talloc_strdup(ctdb, socketname);
3270 CTDB_NO_MEMORY(ctdb, ctdb->daemon.name);
3275 const char *ctdb_get_socketname(struct ctdb_context *ctdb)
3277 return ctdb->daemon.name;
3281 return the pnn of this node
3283 uint32_t ctdb_get_pnn(struct ctdb_context *ctdb)
3290 get the uptime of a remote node
3292 struct ctdb_client_control_state *
3293 ctdb_ctrl_uptime_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode)
3295 return ctdb_control_send(ctdb, destnode, 0,
3296 CTDB_CONTROL_UPTIME, 0, tdb_null,
3297 mem_ctx, &timeout, NULL);
3300 int ctdb_ctrl_uptime_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, struct ctdb_uptime **uptime)
3306 ret = ctdb_control_recv(ctdb, state, mem_ctx, &outdata, &res, NULL);
3307 if (ret != 0 || res != 0) {
3308 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_uptime_recv failed\n"));
3312 *uptime = (struct ctdb_uptime *)talloc_steal(mem_ctx, outdata.dptr);
3317 int ctdb_ctrl_uptime(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, struct ctdb_uptime **uptime)
3319 struct ctdb_client_control_state *state;
3321 state = ctdb_ctrl_uptime_send(ctdb, mem_ctx, timeout, destnode);
3322 return ctdb_ctrl_uptime_recv(ctdb, mem_ctx, state, uptime);
3326 send a control to execute the "recovered" event script on a node
3328 int ctdb_ctrl_end_recovery(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
3333 ret = ctdb_control(ctdb, destnode, 0,
3334 CTDB_CONTROL_END_RECOVERY, 0, tdb_null,
3335 NULL, NULL, &status, &timeout, NULL);
3336 if (ret != 0 || status != 0) {
3337 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for end_recovery failed\n"));
3345 callback for the async helpers used when sending the same control
3346 to multiple nodes in parallell.
3348 static void async_callback(struct ctdb_client_control_state *state)
3350 struct client_async_data *data = talloc_get_type(state->async.private_data, struct client_async_data);
3351 struct ctdb_context *ctdb = talloc_get_type(state->ctdb, struct ctdb_context);
3355 uint32_t destnode = state->c->hdr.destnode;
3357 /* one more node has responded with recmode data */
3360 /* if we failed to push the db, then return an error and let
3361 the main loop try again.
3363 if (state->state != CTDB_CONTROL_DONE) {
3364 if ( !data->dont_log_errors) {
3365 DEBUG(DEBUG_ERR,("Async operation failed with state %d, opcode:%u\n", state->state, data->opcode));
3368 if (state->state == CTDB_CONTROL_TIMEOUT) {
3373 if (data->fail_callback) {
3374 data->fail_callback(ctdb, destnode, res, outdata,
3375 data->callback_data);
3380 state->async.fn = NULL;
3382 ret = ctdb_control_recv(ctdb, state, data, &outdata, &res, NULL);
3383 if ((ret != 0) || (res != 0)) {
3384 if ( !data->dont_log_errors) {
3385 DEBUG(DEBUG_ERR,("Async operation failed with ret=%d res=%d opcode=%u\n", ret, (int)res, data->opcode));
3388 if (data->fail_callback) {
3389 data->fail_callback(ctdb, destnode, res, outdata,
3390 data->callback_data);
3393 if ((ret == 0) && (data->callback != NULL)) {
3394 data->callback(ctdb, destnode, res, outdata,
3395 data->callback_data);
3400 void ctdb_client_async_add(struct client_async_data *data, struct ctdb_client_control_state *state)
3402 /* set up the callback functions */
3403 state->async.fn = async_callback;
3404 state->async.private_data = data;
3406 /* one more control to wait for to complete */
3411 /* wait for up to the maximum number of seconds allowed
3412 or until all nodes we expect a response from has replied
3414 int ctdb_client_async_wait(struct ctdb_context *ctdb, struct client_async_data *data)
3416 while (data->count > 0) {
3417 event_loop_once(ctdb->ev);
3419 if (data->fail_count != 0) {
3420 if (!data->dont_log_errors) {
3421 DEBUG(DEBUG_ERR,("Async wait failed - fail_count=%u\n",
3431 perform a simple control on the listed nodes
3432 The control cannot return data
3434 int ctdb_client_async_control(struct ctdb_context *ctdb,
3435 enum ctdb_controls opcode,
3438 struct timeval timeout,
3439 bool dont_log_errors,
3441 client_async_callback client_callback,
3442 client_async_callback fail_callback,
3443 void *callback_data)
3445 struct client_async_data *async_data;
3446 struct ctdb_client_control_state *state;
3449 async_data = talloc_zero(ctdb, struct client_async_data);
3450 CTDB_NO_MEMORY_FATAL(ctdb, async_data);
3451 async_data->dont_log_errors = dont_log_errors;
3452 async_data->callback = client_callback;
3453 async_data->fail_callback = fail_callback;
3454 async_data->callback_data = callback_data;
3455 async_data->opcode = opcode;
3457 num_nodes = talloc_get_size(nodes) / sizeof(uint32_t);
3459 /* loop over all nodes and send an async control to each of them */
3460 for (j=0; j<num_nodes; j++) {
3461 uint32_t pnn = nodes[j];
3463 state = ctdb_control_send(ctdb, pnn, srvid, opcode,
3464 0, data, async_data, &timeout, NULL);
3465 if (state == NULL) {
3466 DEBUG(DEBUG_ERR,(__location__ " Failed to call async control %u\n", (unsigned)opcode));
3467 talloc_free(async_data);
3471 ctdb_client_async_add(async_data, state);
3474 if (ctdb_client_async_wait(ctdb, async_data) != 0) {
3475 talloc_free(async_data);
3479 talloc_free(async_data);
3483 uint32_t *list_of_vnnmap_nodes(struct ctdb_context *ctdb,
3484 struct ctdb_vnn_map *vnn_map,
3485 TALLOC_CTX *mem_ctx,
3488 int i, j, num_nodes;
3491 for (i=num_nodes=0;i<vnn_map->size;i++) {
3492 if (vnn_map->map[i] == ctdb->pnn && !include_self) {
3498 nodes = talloc_array(mem_ctx, uint32_t, num_nodes);
3499 CTDB_NO_MEMORY_FATAL(ctdb, nodes);
3501 for (i=j=0;i<vnn_map->size;i++) {
3502 if (vnn_map->map[i] == ctdb->pnn && !include_self) {
3505 nodes[j++] = vnn_map->map[i];
3511 /* Get list of nodes not including those with flags specified by mask.
3512 * If exclude_pnn is not -1 then exclude that pnn from the list.
3514 uint32_t *list_of_nodes(struct ctdb_context *ctdb,
3515 struct ctdb_node_map *node_map,
3516 TALLOC_CTX *mem_ctx,
3520 int i, j, num_nodes;
3523 for (i=num_nodes=0;i<node_map->num;i++) {
3524 if (node_map->nodes[i].flags & mask) {
3527 if (node_map->nodes[i].pnn == exclude_pnn) {
3533 nodes = talloc_array(mem_ctx, uint32_t, num_nodes);
3534 CTDB_NO_MEMORY_FATAL(ctdb, nodes);
3536 for (i=j=0;i<node_map->num;i++) {
3537 if (node_map->nodes[i].flags & mask) {
3540 if (node_map->nodes[i].pnn == exclude_pnn) {
3543 nodes[j++] = node_map->nodes[i].pnn;
3549 uint32_t *list_of_active_nodes(struct ctdb_context *ctdb,
3550 struct ctdb_node_map *node_map,
3551 TALLOC_CTX *mem_ctx,
3554 return list_of_nodes(ctdb, node_map, mem_ctx, NODE_FLAGS_INACTIVE,
3555 include_self ? -1 : ctdb->pnn);
3558 uint32_t *list_of_connected_nodes(struct ctdb_context *ctdb,
3559 struct ctdb_node_map *node_map,
3560 TALLOC_CTX *mem_ctx,
3563 return list_of_nodes(ctdb, node_map, mem_ctx, NODE_FLAGS_DISCONNECTED,
3564 include_self ? -1 : ctdb->pnn);
3568 this is used to test if a pnn lock exists and if it exists will return
3569 the number of connections that pnn has reported or -1 if that recovery
3570 daemon is not running.
3573 ctdb_read_pnn_lock(int fd, int32_t pnn)
3578 lock.l_type = F_WRLCK;
3579 lock.l_whence = SEEK_SET;
3584 if (fcntl(fd, F_GETLK, &lock) != 0) {
3585 DEBUG(DEBUG_ERR, (__location__ " F_GETLK failed with %s\n", strerror(errno)));
3589 if (lock.l_type == F_UNLCK) {
3593 if (pread(fd, &c, 1, pnn) == -1) {
3594 DEBUG(DEBUG_CRIT,(__location__ " failed read pnn count - %s\n", strerror(errno)));
3602 get capabilities of a remote node
3604 struct ctdb_client_control_state *
3605 ctdb_ctrl_getcapabilities_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode)
3607 return ctdb_control_send(ctdb, destnode, 0,
3608 CTDB_CONTROL_GET_CAPABILITIES, 0, tdb_null,
3609 mem_ctx, &timeout, NULL);
3612 int ctdb_ctrl_getcapabilities_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *capabilities)
3618 ret = ctdb_control_recv(ctdb, state, mem_ctx, &outdata, &res, NULL);
3619 if ( (ret != 0) || (res != 0) ) {
3620 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_getcapabilities_recv failed\n"));
3625 *capabilities = *((uint32_t *)outdata.dptr);
3631 int ctdb_ctrl_getcapabilities(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *capabilities)
3633 struct ctdb_client_control_state *state;
3634 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
3637 state = ctdb_ctrl_getcapabilities_send(ctdb, tmp_ctx, timeout, destnode);
3638 ret = ctdb_ctrl_getcapabilities_recv(ctdb, tmp_ctx, state, capabilities);
3639 talloc_free(tmp_ctx);
3644 * check whether a transaction is active on a given db on a given node
3646 int32_t ctdb_ctrl_transaction_active(struct ctdb_context *ctdb,
3654 indata.dptr = (uint8_t *)&db_id;
3655 indata.dsize = sizeof(db_id);
3657 ret = ctdb_control(ctdb, destnode, 0,
3658 CTDB_CONTROL_TRANS2_ACTIVE,
3659 0, indata, NULL, NULL, &status,
3663 DEBUG(DEBUG_ERR, (__location__ " ctdb control for transaction_active failed\n"));
3671 struct ctdb_transaction_handle {
3672 struct ctdb_db_context *ctdb_db;
3675 * we store the reads and writes done under a transaction:
3676 * - one list stores both reads and writes (m_all),
3677 * - the other just writes (m_write)
3679 struct ctdb_marshall_buffer *m_all;
3680 struct ctdb_marshall_buffer *m_write;
3683 /* start a transaction on a database */
3684 static int ctdb_transaction_destructor(struct ctdb_transaction_handle *h)
3686 tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
3690 /* start a transaction on a database */
3691 static int ctdb_transaction_fetch_start(struct ctdb_transaction_handle *h)
3693 struct ctdb_record_handle *rh;
3696 struct ctdb_ltdb_header header;
3697 TALLOC_CTX *tmp_ctx;
3698 const char *keyname = CTDB_TRANSACTION_LOCK_KEY;
3700 struct ctdb_db_context *ctdb_db = h->ctdb_db;
3704 key.dptr = discard_const(keyname);
3705 key.dsize = strlen(keyname);
3707 if (!ctdb_db->persistent) {
3708 DEBUG(DEBUG_ERR,(__location__ " Attempted transaction on non-persistent database\n"));
3713 tmp_ctx = talloc_new(h);
3715 rh = ctdb_fetch_lock(ctdb_db, tmp_ctx, key, NULL);
3717 DEBUG(DEBUG_ERR,(__location__ " Failed to fetch_lock database\n"));
3718 talloc_free(tmp_ctx);
3722 status = ctdb_ctrl_transaction_active(ctdb_db->ctdb,
3726 unsigned long int usec = (1000 + random()) % 100000;
3727 DEBUG(DEBUG_DEBUG, (__location__ " transaction is active "
3728 "on db_id[0x%08x]. waiting for %lu "
3730 ctdb_db->db_id, usec));
3731 talloc_free(tmp_ctx);
3737 * store the pid in the database:
3738 * it is not enough that the node is dmaster...
3741 data.dptr = (unsigned char *)&pid;
3742 data.dsize = sizeof(pid_t);
3744 rh->header.dmaster = ctdb_db->ctdb->pnn;
3745 ret = ctdb_ltdb_store(ctdb_db, key, &(rh->header), data);
3747 DEBUG(DEBUG_ERR, (__location__ " Failed to store pid in "
3748 "transaction record\n"));
3749 talloc_free(tmp_ctx);
3755 ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
3757 DEBUG(DEBUG_ERR,(__location__ " Failed to start tdb transaction\n"));
3758 talloc_free(tmp_ctx);
3762 ret = ctdb_ltdb_fetch(ctdb_db, key, &header, tmp_ctx, &data);
3764 DEBUG(DEBUG_ERR,(__location__ " Failed to re-fetch transaction "
3765 "lock record inside transaction\n"));
3766 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
3767 talloc_free(tmp_ctx);
3771 if (header.dmaster != ctdb_db->ctdb->pnn) {
3772 DEBUG(DEBUG_DEBUG,(__location__ " not dmaster any more on "
3773 "transaction lock record\n"));
3774 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
3775 talloc_free(tmp_ctx);
3779 if ((data.dsize != sizeof(pid_t)) || (*(pid_t *)(data.dptr) != pid)) {
3780 DEBUG(DEBUG_DEBUG, (__location__ " my pid is not stored in "
3781 "the transaction lock record\n"));
3782 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
3783 talloc_free(tmp_ctx);
3787 talloc_free(tmp_ctx);
3793 /* start a transaction on a database */
3794 struct ctdb_transaction_handle *ctdb_transaction_start(struct ctdb_db_context *ctdb_db,
3795 TALLOC_CTX *mem_ctx)
3797 struct ctdb_transaction_handle *h;
3800 h = talloc_zero(mem_ctx, struct ctdb_transaction_handle);
3802 DEBUG(DEBUG_ERR,(__location__ " oom for transaction handle\n"));
3806 h->ctdb_db = ctdb_db;
3808 ret = ctdb_transaction_fetch_start(h);
3814 talloc_set_destructor(h, ctdb_transaction_destructor);
3822 fetch a record inside a transaction
3824 int ctdb_transaction_fetch(struct ctdb_transaction_handle *h,
3825 TALLOC_CTX *mem_ctx,
3826 TDB_DATA key, TDB_DATA *data)
3828 struct ctdb_ltdb_header header;
3831 ZERO_STRUCT(header);
3833 ret = ctdb_ltdb_fetch(h->ctdb_db, key, &header, mem_ctx, data);
3834 if (ret == -1 && header.dmaster == (uint32_t)-1) {
3835 /* record doesn't exist yet */
3844 if (!h->in_replay) {
3845 h->m_all = ctdb_marshall_add(h, h->m_all, h->ctdb_db->db_id, 1, key, NULL, *data);
3846 if (h->m_all == NULL) {
3847 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
3856 stores a record inside a transaction
3858 int ctdb_transaction_store(struct ctdb_transaction_handle *h,
3859 TDB_DATA key, TDB_DATA data)
3861 TALLOC_CTX *tmp_ctx = talloc_new(h);
3862 struct ctdb_ltdb_header header;
3866 ZERO_STRUCT(header);
3868 /* we need the header so we can update the RSN */
3869 ret = ctdb_ltdb_fetch(h->ctdb_db, key, &header, tmp_ctx, &olddata);
3870 if (ret == -1 && header.dmaster == (uint32_t)-1) {
3871 /* the record doesn't exist - create one with us as dmaster.
3872 This is only safe because we are in a transaction and this
3873 is a persistent database */
3874 ZERO_STRUCT(header);
3875 } else if (ret != 0) {
3876 DEBUG(DEBUG_ERR,(__location__ " Failed to fetch record\n"));
3877 talloc_free(tmp_ctx);
3881 if (data.dsize == olddata.dsize &&
3882 memcmp(data.dptr, olddata.dptr, data.dsize) == 0) {
3883 /* save writing the same data */
3884 talloc_free(tmp_ctx);
3888 header.dmaster = h->ctdb_db->ctdb->pnn;
3891 if (!h->in_replay) {
3892 h->m_all = ctdb_marshall_add(h, h->m_all, h->ctdb_db->db_id, 0, key, NULL, data);
3893 if (h->m_all == NULL) {
3894 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
3895 talloc_free(tmp_ctx);
3900 h->m_write = ctdb_marshall_add(h, h->m_write, h->ctdb_db->db_id, 0, key, &header, data);
3901 if (h->m_write == NULL) {
3902 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
3903 talloc_free(tmp_ctx);
3907 ret = ctdb_ltdb_store(h->ctdb_db, key, &header, data);
3909 talloc_free(tmp_ctx);
3915 replay a transaction
3917 static int ctdb_replay_transaction(struct ctdb_transaction_handle *h)
3920 struct ctdb_rec_data *rec = NULL;
3922 h->in_replay = true;
3923 talloc_free(h->m_write);
3926 ret = ctdb_transaction_fetch_start(h);
3931 for (i=0;i<h->m_all->count;i++) {
3934 rec = ctdb_marshall_loop_next(h->m_all, rec, NULL, NULL, &key, &data);
3936 DEBUG(DEBUG_ERR, (__location__ " Out of records in ctdb_replay_transaction?\n"));
3940 if (rec->reqid == 0) {
3942 if (ctdb_transaction_store(h, key, data) != 0) {
3947 TALLOC_CTX *tmp_ctx = talloc_new(h);
3949 if (ctdb_transaction_fetch(h, tmp_ctx, key, &data2) != 0) {
3950 talloc_free(tmp_ctx);
3953 if (data2.dsize != data.dsize ||
3954 memcmp(data2.dptr, data.dptr, data.dsize) != 0) {
3955 /* the record has changed on us - we have to give up */
3956 talloc_free(tmp_ctx);
3959 talloc_free(tmp_ctx);
3966 tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
3972 commit a transaction
3974 int ctdb_transaction_commit(struct ctdb_transaction_handle *h)
3978 struct ctdb_context *ctdb = h->ctdb_db->ctdb;
3979 struct timeval timeout;
3980 enum ctdb_controls failure_control = CTDB_CONTROL_TRANS2_ERROR;
3982 talloc_set_destructor(h, NULL);
3984 /* our commit strategy is quite complex.
3986 - we first try to commit the changes to all other nodes
3988 - if that works, then we commit locally and we are done
3990 - if a commit on another node fails, then we need to cancel
3991 the transaction, then restart the transaction (thus
3992 opening a window of time for a pending recovery to
3993 complete), then replay the transaction, checking all the
3994 reads and writes (checking that reads give the same data,
3995 and writes succeed). Then we retry the transaction to the
4000 if (h->m_write == NULL) {
4001 /* no changes were made */
4002 tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
4007 /* tell ctdbd to commit to the other nodes */
4008 timeout = timeval_current_ofs(1, 0);
4009 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
4010 retries==0?CTDB_CONTROL_TRANS2_COMMIT:CTDB_CONTROL_TRANS2_COMMIT_RETRY, 0,
4011 ctdb_marshall_finish(h->m_write), NULL, NULL, &status,
4013 if (ret != 0 || status != 0) {
4014 tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
4015 DEBUG(DEBUG_NOTICE, (__location__ " transaction commit%s failed"
4016 ", retrying after 1 second...\n",
4017 (retries==0)?"":"retry "));
4021 failure_control = CTDB_CONTROL_TRANS2_ERROR;
4023 /* work out what error code we will give if we
4024 have to fail the operation */
4025 switch ((enum ctdb_trans2_commit_error)status) {
4026 case CTDB_TRANS2_COMMIT_SUCCESS:
4027 case CTDB_TRANS2_COMMIT_SOMEFAIL:
4028 case CTDB_TRANS2_COMMIT_TIMEOUT:
4029 failure_control = CTDB_CONTROL_TRANS2_ERROR;
4031 case CTDB_TRANS2_COMMIT_ALLFAIL:
4032 failure_control = CTDB_CONTROL_TRANS2_FINISHED;
4037 if (++retries == 100) {
4038 DEBUG(DEBUG_ERR,(__location__ " Giving up transaction on db 0x%08x after %d retries failure_control=%u\n",
4039 h->ctdb_db->db_id, retries, (unsigned)failure_control));
4040 ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
4041 failure_control, CTDB_CTRL_FLAG_NOREPLY,
4042 tdb_null, NULL, NULL, NULL, NULL, NULL);
4047 if (ctdb_replay_transaction(h) != 0) {
4048 DEBUG(DEBUG_ERR, (__location__ " Failed to replay "
4049 "transaction on db 0x%08x, "
4050 "failure control =%u\n",
4052 (unsigned)failure_control));
4053 ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
4054 failure_control, CTDB_CTRL_FLAG_NOREPLY,
4055 tdb_null, NULL, NULL, NULL, NULL, NULL);
4061 failure_control = CTDB_CONTROL_TRANS2_ERROR;
4064 /* do the real commit locally */
4065 ret = tdb_transaction_commit(h->ctdb_db->ltdb->tdb);
4067 DEBUG(DEBUG_ERR, (__location__ " Failed to commit transaction "
4068 "on db id 0x%08x locally, "
4069 "failure_control=%u\n",
4071 (unsigned)failure_control));
4072 ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
4073 failure_control, CTDB_CTRL_FLAG_NOREPLY,
4074 tdb_null, NULL, NULL, NULL, NULL, NULL);
4079 /* tell ctdbd that we are finished with our local commit */
4080 ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
4081 CTDB_CONTROL_TRANS2_FINISHED, CTDB_CTRL_FLAG_NOREPLY,
4082 tdb_null, NULL, NULL, NULL, NULL, NULL);
4088 recovery daemon ping to main daemon
4090 int ctdb_ctrl_recd_ping(struct ctdb_context *ctdb)
4095 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_RECD_PING, 0, tdb_null,
4096 ctdb, NULL, &res, NULL, NULL);
4097 if (ret != 0 || res != 0) {
4098 DEBUG(DEBUG_ERR,("Failed to send recd ping\n"));
4105 /* When forking the main daemon and the child process needs to connect
4106 * back to the daemon as a client process, this function can be used
4107 * to change the ctdb context from daemon into client mode. The child
4108 * process must be created using ctdb_fork() and not fork() -
4109 * ctdb_fork() does some necessary housekeeping.
4111 int switch_from_server_to_client(struct ctdb_context *ctdb, const char *fmt, ...)
4116 /* Add extra information so we can identify this in the logs */
4118 debug_extra = talloc_strdup_append(talloc_vasprintf(NULL, fmt, ap), ":");
4121 /* get a new event context */
4122 ctdb->ev = event_context_init(ctdb);
4123 tevent_loop_allow_nesting(ctdb->ev);
4125 /* Connect to main CTDB daemon */
4126 ret = ctdb_socket_connect(ctdb);
4128 DEBUG(DEBUG_ALERT, (__location__ " Failed to init ctdb client\n"));
4132 ctdb->can_send_controls = true;
4138 get the status of running the monitor eventscripts: NULL means never run.
4140 int ctdb_ctrl_getscriptstatus(struct ctdb_context *ctdb,
4141 struct timeval timeout, uint32_t destnode,
4142 TALLOC_CTX *mem_ctx, enum ctdb_eventscript_call type,
4143 struct ctdb_scripts_wire **scripts)
4146 TDB_DATA outdata, indata;
4148 uint32_t uinttype = type;
4150 indata.dptr = (uint8_t *)&uinttype;
4151 indata.dsize = sizeof(uinttype);
4153 ret = ctdb_control(ctdb, destnode, 0,
4154 CTDB_CONTROL_GET_EVENT_SCRIPT_STATUS, 0, indata,
4155 mem_ctx, &outdata, &res, &timeout, NULL);
4156 if (ret != 0 || res != 0) {
4157 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getscriptstatus failed ret:%d res:%d\n", ret, res));
4161 if (outdata.dsize == 0) {
4164 *scripts = (struct ctdb_scripts_wire *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
4165 talloc_free(outdata.dptr);
4172 tell the main daemon how long it took to lock the reclock file
4174 int ctdb_ctrl_report_recd_lock_latency(struct ctdb_context *ctdb, struct timeval timeout, double latency)
4180 data.dptr = (uint8_t *)&latency;
4181 data.dsize = sizeof(latency);
4183 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_RECD_RECLOCK_LATENCY, 0, data,
4184 ctdb, NULL, &res, NULL, NULL);
4185 if (ret != 0 || res != 0) {
4186 DEBUG(DEBUG_ERR,("Failed to send recd reclock latency\n"));
4194 get the name of the reclock file
4196 int ctdb_ctrl_getreclock(struct ctdb_context *ctdb, struct timeval timeout,
4197 uint32_t destnode, TALLOC_CTX *mem_ctx,
4204 ret = ctdb_control(ctdb, destnode, 0,
4205 CTDB_CONTROL_GET_RECLOCK_FILE, 0, tdb_null,
4206 mem_ctx, &data, &res, &timeout, NULL);
4207 if (ret != 0 || res != 0) {
4211 if (data.dsize == 0) {
4214 *name = talloc_strdup(mem_ctx, discard_const(data.dptr));
4216 talloc_free(data.dptr);
4222 set the reclock filename for a node
4224 int ctdb_ctrl_setreclock(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, const char *reclock)
4230 if (reclock == NULL) {
4234 data.dsize = strlen(reclock) + 1;
4235 data.dptr = discard_const(reclock);
4238 ret = ctdb_control(ctdb, destnode, 0,
4239 CTDB_CONTROL_SET_RECLOCK_FILE, 0, data,
4240 NULL, NULL, &res, &timeout, NULL);
4241 if (ret != 0 || res != 0) {
4242 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setreclock failed\n"));
4252 int ctdb_ctrl_stop_node(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
4257 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_STOP_NODE, 0, tdb_null,
4258 ctdb, NULL, &res, &timeout, NULL);
4259 if (ret != 0 || res != 0) {
4260 DEBUG(DEBUG_ERR,("Failed to stop node\n"));
4270 int ctdb_ctrl_continue_node(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
4274 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_CONTINUE_NODE, 0, tdb_null,
4275 ctdb, NULL, NULL, &timeout, NULL);
4277 DEBUG(DEBUG_ERR,("Failed to continue node\n"));
4285 set the natgw state for a node
4287 int ctdb_ctrl_setnatgwstate(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t natgwstate)
4293 data.dsize = sizeof(natgwstate);
4294 data.dptr = (uint8_t *)&natgwstate;
4296 ret = ctdb_control(ctdb, destnode, 0,
4297 CTDB_CONTROL_SET_NATGWSTATE, 0, data,
4298 NULL, NULL, &res, &timeout, NULL);
4299 if (ret != 0 || res != 0) {
4300 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setnatgwstate failed\n"));
4308 set the lmaster role for a node
4310 int ctdb_ctrl_setlmasterrole(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t lmasterrole)
4316 data.dsize = sizeof(lmasterrole);
4317 data.dptr = (uint8_t *)&lmasterrole;
4319 ret = ctdb_control(ctdb, destnode, 0,
4320 CTDB_CONTROL_SET_LMASTERROLE, 0, data,
4321 NULL, NULL, &res, &timeout, NULL);
4322 if (ret != 0 || res != 0) {
4323 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setlmasterrole failed\n"));
4331 set the recmaster role for a node
4333 int ctdb_ctrl_setrecmasterrole(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmasterrole)
4339 data.dsize = sizeof(recmasterrole);
4340 data.dptr = (uint8_t *)&recmasterrole;
4342 ret = ctdb_control(ctdb, destnode, 0,
4343 CTDB_CONTROL_SET_RECMASTERROLE, 0, data,
4344 NULL, NULL, &res, &timeout, NULL);
4345 if (ret != 0 || res != 0) {
4346 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setrecmasterrole failed\n"));
4353 /* enable an eventscript
4355 int ctdb_ctrl_enablescript(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, const char *script)
4361 data.dsize = strlen(script) + 1;
4362 data.dptr = discard_const(script);
4364 ret = ctdb_control(ctdb, destnode, 0,
4365 CTDB_CONTROL_ENABLE_SCRIPT, 0, data,
4366 NULL, NULL, &res, &timeout, NULL);
4367 if (ret != 0 || res != 0) {
4368 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for enablescript failed\n"));
4375 /* disable an eventscript
4377 int ctdb_ctrl_disablescript(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, const char *script)
4383 data.dsize = strlen(script) + 1;
4384 data.dptr = discard_const(script);
4386 ret = ctdb_control(ctdb, destnode, 0,
4387 CTDB_CONTROL_DISABLE_SCRIPT, 0, data,
4388 NULL, NULL, &res, &timeout, NULL);
4389 if (ret != 0 || res != 0) {
4390 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for disablescript failed\n"));
4398 int ctdb_ctrl_set_ban(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, struct ctdb_ban_time *bantime)
4404 data.dsize = sizeof(*bantime);
4405 data.dptr = (uint8_t *)bantime;
4407 ret = ctdb_control(ctdb, destnode, 0,
4408 CTDB_CONTROL_SET_BAN_STATE, 0, data,
4409 NULL, NULL, &res, &timeout, NULL);
4410 if (ret != 0 || res != 0) {
4411 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set ban state failed\n"));
4419 int ctdb_ctrl_get_ban(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_ban_time **bantime)
4424 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
4426 ret = ctdb_control(ctdb, destnode, 0,
4427 CTDB_CONTROL_GET_BAN_STATE, 0, tdb_null,
4428 tmp_ctx, &outdata, &res, &timeout, NULL);
4429 if (ret != 0 || res != 0) {
4430 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set ban state failed\n"));
4431 talloc_free(tmp_ctx);
4435 *bantime = (struct ctdb_ban_time *)talloc_steal(mem_ctx, outdata.dptr);
4436 talloc_free(tmp_ctx);
4442 int ctdb_ctrl_set_db_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, struct ctdb_db_priority *db_prio)
4447 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
4449 data.dptr = (uint8_t*)db_prio;
4450 data.dsize = sizeof(*db_prio);
4452 ret = ctdb_control(ctdb, destnode, 0,
4453 CTDB_CONTROL_SET_DB_PRIORITY, 0, data,
4454 tmp_ctx, NULL, &res, &timeout, NULL);
4455 if (ret != 0 || res != 0) {
4456 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set_db_priority failed\n"));
4457 talloc_free(tmp_ctx);
4461 talloc_free(tmp_ctx);
4466 int ctdb_ctrl_get_db_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t db_id, uint32_t *priority)
4471 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
4473 data.dptr = (uint8_t*)&db_id;
4474 data.dsize = sizeof(db_id);
4476 ret = ctdb_control(ctdb, destnode, 0,
4477 CTDB_CONTROL_GET_DB_PRIORITY, 0, data,
4478 tmp_ctx, NULL, &res, &timeout, NULL);
4479 if (ret != 0 || res < 0) {
4480 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get_db_priority failed\n"));
4481 talloc_free(tmp_ctx);
4489 talloc_free(tmp_ctx);
4494 int ctdb_ctrl_getstathistory(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_statistics_wire **stats)
4500 ret = ctdb_control(ctdb, destnode, 0,
4501 CTDB_CONTROL_GET_STAT_HISTORY, 0, tdb_null,
4502 mem_ctx, &outdata, &res, &timeout, NULL);
4503 if (ret != 0 || res != 0 || outdata.dsize == 0) {
4504 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getstathistory failed ret:%d res:%d\n", ret, res));
4508 *stats = (struct ctdb_statistics_wire *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
4509 talloc_free(outdata.dptr);
4514 struct ctdb_ltdb_header *ctdb_header_from_record_handle(struct ctdb_record_handle *h)
4524 struct ctdb_client_control_state *
4525 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)
4527 struct ctdb_client_control_state *handle;
4528 struct ctdb_marshall_buffer *m;
4529 struct ctdb_rec_data *rec;
4532 m = talloc_zero(mem_ctx, struct ctdb_marshall_buffer);
4534 DEBUG(DEBUG_ERR, ("Failed to allocate marshall buffer for update record\n"));
4538 m->db_id = ctdb_db->db_id;
4540 rec = ctdb_marshall_record(m, 0, key, header, data);
4542 DEBUG(DEBUG_ERR,("Failed to marshall record for update record\n"));
4546 m = talloc_realloc_size(mem_ctx, m, rec->length + offsetof(struct ctdb_marshall_buffer, data));
4548 DEBUG(DEBUG_CRIT,(__location__ " Failed to expand recdata\n"));
4553 memcpy((uint8_t *)m + offsetof(struct ctdb_marshall_buffer, data), rec, rec->length);
4556 outdata.dptr = (uint8_t *)m;
4557 outdata.dsize = talloc_get_size(m);
4559 handle = ctdb_control_send(ctdb, destnode, 0,
4560 CTDB_CONTROL_UPDATE_RECORD, 0, outdata,
4561 mem_ctx, &timeout, NULL);
4566 int ctdb_ctrl_updaterecord_recv(struct ctdb_context *ctdb, struct ctdb_client_control_state *state)
4571 ret = ctdb_control_recv(ctdb, state, state, NULL, &res, NULL);
4572 if ( (ret != 0) || (res != 0) ){
4573 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_update_record_recv failed\n"));
4581 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)
4583 struct ctdb_client_control_state *state;
4585 state = ctdb_ctrl_updaterecord_send(ctdb, mem_ctx, timeout, destnode, ctdb_db, key, header, data);
4586 return ctdb_ctrl_updaterecord_recv(ctdb, state);
4595 set a database to be readonly
4597 struct ctdb_client_control_state *
4598 ctdb_ctrl_set_db_readonly_send(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid)
4602 data.dptr = (uint8_t *)&dbid;
4603 data.dsize = sizeof(dbid);
4605 return ctdb_control_send(ctdb, destnode, 0,
4606 CTDB_CONTROL_SET_DB_READONLY, 0, data,
4610 int ctdb_ctrl_set_db_readonly_recv(struct ctdb_context *ctdb, struct ctdb_client_control_state *state)
4615 ret = ctdb_control_recv(ctdb, state, ctdb, NULL, &res, NULL);
4616 if (ret != 0 || res != 0) {
4617 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_set_db_readonly_recv failed ret:%d res:%d\n", ret, res));
4624 int ctdb_ctrl_set_db_readonly(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid)
4626 struct ctdb_client_control_state *state;
4628 state = ctdb_ctrl_set_db_readonly_send(ctdb, destnode, dbid);
4629 return ctdb_ctrl_set_db_readonly_recv(ctdb, state);
4633 set a database to be sticky
4635 struct ctdb_client_control_state *
4636 ctdb_ctrl_set_db_sticky_send(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid)
4640 data.dptr = (uint8_t *)&dbid;
4641 data.dsize = sizeof(dbid);
4643 return ctdb_control_send(ctdb, destnode, 0,
4644 CTDB_CONTROL_SET_DB_STICKY, 0, data,
4648 int ctdb_ctrl_set_db_sticky_recv(struct ctdb_context *ctdb, struct ctdb_client_control_state *state)
4653 ret = ctdb_control_recv(ctdb, state, ctdb, NULL, &res, NULL);
4654 if (ret != 0 || res != 0) {
4655 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_set_db_sticky_recv failed ret:%d res:%d\n", ret, res));
4662 int ctdb_ctrl_set_db_sticky(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid)
4664 struct ctdb_client_control_state *state;
4666 state = ctdb_ctrl_set_db_sticky_send(ctdb, destnode, dbid);
4667 return ctdb_ctrl_set_db_sticky_recv(ctdb, state);