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/>.
23 #include "lib/tdb/include/tdb.h"
24 #include "lib/util/dlinklist.h"
25 #include "lib/tevent/tevent.h"
26 #include "system/network.h"
27 #include "system/filesys.h"
28 #include "system/locale.h"
30 #include "../include/ctdb_private.h"
31 #include "lib/util/dlinklist.h"
36 allocate a packet for use in client<->daemon communication
38 struct ctdb_req_header *_ctdbd_allocate_pkt(struct ctdb_context *ctdb,
40 enum ctdb_operation operation,
41 size_t length, size_t slength,
45 struct ctdb_req_header *hdr;
47 length = MAX(length, slength);
48 size = (length+(CTDB_DS_ALIGNMENT-1)) & ~(CTDB_DS_ALIGNMENT-1);
50 hdr = (struct ctdb_req_header *)talloc_size(mem_ctx, size);
52 DEBUG(DEBUG_ERR,("Unable to allocate packet for operation %u of length %u\n",
53 operation, (unsigned)length));
56 talloc_set_name_const(hdr, type);
57 memset(hdr, 0, slength);
59 hdr->operation = operation;
60 hdr->ctdb_magic = CTDB_MAGIC;
61 hdr->ctdb_version = CTDB_VERSION;
62 hdr->srcnode = ctdb->pnn;
64 hdr->generation = ctdb->vnn_map->generation;
71 local version of ctdb_call
73 int ctdb_call_local(struct ctdb_db_context *ctdb_db, struct ctdb_call *call,
74 struct ctdb_ltdb_header *header, TALLOC_CTX *mem_ctx,
77 struct ctdb_call_info *c;
78 struct ctdb_registered_call *fn;
79 struct ctdb_context *ctdb = ctdb_db->ctdb;
81 c = talloc(ctdb, struct ctdb_call_info);
82 CTDB_NO_MEMORY(ctdb, c);
85 c->call_data = &call->call_data;
86 c->record_data.dptr = talloc_memdup(c, data->dptr, data->dsize);
87 c->record_data.dsize = data->dsize;
88 CTDB_NO_MEMORY(ctdb, c->record_data.dptr);
94 for (fn=ctdb_db->calls;fn;fn=fn->next) {
95 if (fn->id == call->call_id) break;
98 ctdb_set_error(ctdb, "Unknown call id %u\n", call->call_id);
103 if (fn->fn(c) != 0) {
104 ctdb_set_error(ctdb, "ctdb_call %u failed\n", call->call_id);
109 /* we need to force the record to be written out if this was a remote access */
110 if (c->new_data == NULL) {
111 c->new_data = &c->record_data;
115 /* XXX check that we always have the lock here? */
116 if (ctdb_ltdb_store(ctdb_db, call->key, header, *c->new_data) != 0) {
117 ctdb_set_error(ctdb, "ctdb_call tdb_store failed\n");
124 call->reply_data = *c->reply_data;
126 talloc_steal(call, call->reply_data.dptr);
127 talloc_set_name_const(call->reply_data.dptr, __location__);
129 call->reply_data.dptr = NULL;
130 call->reply_data.dsize = 0;
132 call->status = c->status;
141 queue a packet for sending from client to daemon
143 static int ctdb_client_queue_pkt(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
145 return ctdb_queue_send(ctdb->daemon.queue, (uint8_t *)hdr, hdr->length);
150 called when a CTDB_REPLY_CALL packet comes in in the client
152 This packet comes in response to a CTDB_REQ_CALL request packet. It
153 contains any reply data from the call
155 static void ctdb_client_reply_call(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
157 struct ctdb_reply_call *c = (struct ctdb_reply_call *)hdr;
158 struct ctdb_client_call_state *state;
160 state = ctdb_reqid_find(ctdb, hdr->reqid, struct ctdb_client_call_state);
162 DEBUG(DEBUG_ERR,(__location__ " reqid %u not found\n", hdr->reqid));
166 if (hdr->reqid != state->reqid) {
167 /* we found a record but it was the wrong one */
168 DEBUG(DEBUG_ERR, ("Dropped client call reply with reqid:%u\n",hdr->reqid));
172 state->call->reply_data.dptr = c->data;
173 state->call->reply_data.dsize = c->datalen;
174 state->call->status = c->status;
176 talloc_steal(state, c);
178 state->state = CTDB_CALL_DONE;
180 if (state->async.fn) {
181 state->async.fn(state);
185 static void ctdb_client_reply_control(struct ctdb_context *ctdb, struct ctdb_req_header *hdr);
188 this is called in the client, when data comes in from the daemon
190 static void ctdb_client_read_cb(uint8_t *data, size_t cnt, void *args)
192 struct ctdb_context *ctdb = talloc_get_type(args, struct ctdb_context);
193 struct ctdb_req_header *hdr = (struct ctdb_req_header *)data;
196 /* place the packet as a child of a tmp_ctx. We then use
197 talloc_free() below to free it. If any of the calls want
198 to keep it, then they will steal it somewhere else, and the
199 talloc_free() will be a no-op */
200 tmp_ctx = talloc_new(ctdb);
201 talloc_steal(tmp_ctx, hdr);
204 DEBUG(DEBUG_INFO,("Daemon has exited - shutting down client\n"));
208 if (cnt < sizeof(*hdr)) {
209 DEBUG(DEBUG_CRIT,("Bad packet length %u in client\n", (unsigned)cnt));
212 if (cnt != hdr->length) {
213 ctdb_set_error(ctdb, "Bad header length %u expected %u in client\n",
214 (unsigned)hdr->length, (unsigned)cnt);
218 if (hdr->ctdb_magic != CTDB_MAGIC) {
219 ctdb_set_error(ctdb, "Non CTDB packet rejected in client\n");
223 if (hdr->ctdb_version != CTDB_VERSION) {
224 ctdb_set_error(ctdb, "Bad CTDB version 0x%x rejected in client\n", hdr->ctdb_version);
228 switch (hdr->operation) {
229 case CTDB_REPLY_CALL:
230 ctdb_client_reply_call(ctdb, hdr);
233 case CTDB_REQ_MESSAGE:
234 ctdb_request_message(ctdb, hdr);
237 case CTDB_REPLY_CONTROL:
238 ctdb_client_reply_control(ctdb, hdr);
242 DEBUG(DEBUG_CRIT,("bogus operation code:%u\n",hdr->operation));
246 talloc_free(tmp_ctx);
250 connect with exponential backoff, thanks Stevens
252 #define CONNECT_MAXSLEEP 64
253 static int ctdb_connect_retry(struct ctdb_context *ctdb)
255 struct sockaddr_un addr;
259 memset(&addr, 0, sizeof(addr));
260 addr.sun_family = AF_UNIX;
261 strncpy(addr.sun_path, ctdb->daemon.name, sizeof(addr.sun_path));
263 for (secs = 1; secs <= CONNECT_MAXSLEEP; secs *= 2) {
264 ret = connect(ctdb->daemon.sd, (struct sockaddr *)&addr,
266 if ((ret == 0) || (errno != EAGAIN)) {
270 if (secs <= (CONNECT_MAXSLEEP / 2)) {
271 DEBUG(DEBUG_ERR,("connect failed: %s, retry in %d second(s)\n",
272 strerror(errno), secs));
281 connect to a unix domain socket
283 int ctdb_socket_connect(struct ctdb_context *ctdb)
285 ctdb->daemon.sd = socket(AF_UNIX, SOCK_STREAM, 0);
286 if (ctdb->daemon.sd == -1) {
287 DEBUG(DEBUG_ERR,(__location__ " Failed to open client socket. Errno:%s(%d)\n", strerror(errno), errno));
291 set_nonblocking(ctdb->daemon.sd);
292 set_close_on_exec(ctdb->daemon.sd);
294 if (ctdb_connect_retry(ctdb) == -1) {
295 DEBUG(DEBUG_ERR,(__location__ " Failed to connect client socket to daemon. Errno:%s(%d)\n", strerror(errno), errno));
296 close(ctdb->daemon.sd);
297 ctdb->daemon.sd = -1;
301 ctdb->daemon.queue = ctdb_queue_setup(ctdb, ctdb, ctdb->daemon.sd,
303 ctdb_client_read_cb, ctdb, "to-ctdbd");
308 struct ctdb_record_handle {
309 struct ctdb_db_context *ctdb_db;
312 struct ctdb_ltdb_header header;
317 make a recv call to the local ctdb daemon - called from client context
319 This is called when the program wants to wait for a ctdb_call to complete and get the
320 results. This call will block unless the call has already completed.
322 int ctdb_call_recv(struct ctdb_client_call_state *state, struct ctdb_call *call)
328 while (state->state < CTDB_CALL_DONE) {
329 event_loop_once(state->ctdb_db->ctdb->ev);
331 if (state->state != CTDB_CALL_DONE) {
332 DEBUG(DEBUG_ERR,(__location__ " ctdb_call_recv failed\n"));
337 if (state->call->reply_data.dsize) {
338 call->reply_data.dptr = talloc_memdup(state->ctdb_db,
339 state->call->reply_data.dptr,
340 state->call->reply_data.dsize);
341 call->reply_data.dsize = state->call->reply_data.dsize;
343 call->reply_data.dptr = NULL;
344 call->reply_data.dsize = 0;
346 call->status = state->call->status;
356 destroy a ctdb_call in client
358 static int ctdb_client_call_destructor(struct ctdb_client_call_state *state)
360 ctdb_reqid_remove(state->ctdb_db->ctdb, state->reqid);
365 construct an event driven local ctdb_call
367 this is used so that locally processed ctdb_call requests are processed
368 in an event driven manner
370 static struct ctdb_client_call_state *ctdb_client_call_local_send(struct ctdb_db_context *ctdb_db,
371 struct ctdb_call *call,
372 struct ctdb_ltdb_header *header,
375 struct ctdb_client_call_state *state;
376 struct ctdb_context *ctdb = ctdb_db->ctdb;
379 state = talloc_zero(ctdb_db, struct ctdb_client_call_state);
380 CTDB_NO_MEMORY_NULL(ctdb, state);
381 state->call = talloc_zero(state, struct ctdb_call);
382 CTDB_NO_MEMORY_NULL(ctdb, state->call);
384 talloc_steal(state, data->dptr);
386 state->state = CTDB_CALL_DONE;
387 *(state->call) = *call;
388 state->ctdb_db = ctdb_db;
390 ret = ctdb_call_local(ctdb_db, state->call, header, state, data);
396 make a ctdb call to the local daemon - async send. Called from client context.
398 This constructs a ctdb_call request and queues it for processing.
399 This call never blocks.
401 struct ctdb_client_call_state *ctdb_call_send(struct ctdb_db_context *ctdb_db,
402 struct ctdb_call *call)
404 struct ctdb_client_call_state *state;
405 struct ctdb_context *ctdb = ctdb_db->ctdb;
406 struct ctdb_ltdb_header header;
410 struct ctdb_req_call *c;
412 /* if the domain socket is not yet open, open it */
413 if (ctdb->daemon.sd==-1) {
414 ctdb_socket_connect(ctdb);
417 ret = ctdb_ltdb_lock(ctdb_db, call->key);
419 DEBUG(DEBUG_ERR,(__location__ " Failed to get chainlock\n"));
423 ret = ctdb_ltdb_fetch(ctdb_db, call->key, &header, ctdb_db, &data);
425 if (ret == 0 && header.dmaster == ctdb->pnn) {
426 state = ctdb_client_call_local_send(ctdb_db, call, &header, &data);
427 talloc_free(data.dptr);
428 ctdb_ltdb_unlock(ctdb_db, call->key);
432 ctdb_ltdb_unlock(ctdb_db, call->key);
433 talloc_free(data.dptr);
435 state = talloc_zero(ctdb_db, struct ctdb_client_call_state);
437 DEBUG(DEBUG_ERR, (__location__ " failed to allocate state\n"));
440 state->call = talloc_zero(state, struct ctdb_call);
441 if (state->call == NULL) {
442 DEBUG(DEBUG_ERR, (__location__ " failed to allocate state->call\n"));
446 len = offsetof(struct ctdb_req_call, data) + call->key.dsize + call->call_data.dsize;
447 c = ctdbd_allocate_pkt(ctdb, state, CTDB_REQ_CALL, len, struct ctdb_req_call);
449 DEBUG(DEBUG_ERR, (__location__ " failed to allocate packet\n"));
453 state->reqid = ctdb_reqid_new(ctdb, state);
454 state->ctdb_db = ctdb_db;
455 talloc_set_destructor(state, ctdb_client_call_destructor);
457 c->hdr.reqid = state->reqid;
458 c->flags = call->flags;
459 c->db_id = ctdb_db->db_id;
460 c->callid = call->call_id;
462 c->keylen = call->key.dsize;
463 c->calldatalen = call->call_data.dsize;
464 memcpy(&c->data[0], call->key.dptr, call->key.dsize);
465 memcpy(&c->data[call->key.dsize],
466 call->call_data.dptr, call->call_data.dsize);
467 *(state->call) = *call;
468 state->call->call_data.dptr = &c->data[call->key.dsize];
469 state->call->key.dptr = &c->data[0];
471 state->state = CTDB_CALL_WAIT;
474 ctdb_client_queue_pkt(ctdb, &c->hdr);
481 full ctdb_call. Equivalent to a ctdb_call_send() followed by a ctdb_call_recv()
483 int ctdb_call(struct ctdb_db_context *ctdb_db, struct ctdb_call *call)
485 struct ctdb_client_call_state *state;
487 state = ctdb_call_send(ctdb_db, call);
488 return ctdb_call_recv(state, call);
493 tell the daemon what messaging srvid we will use, and register the message
494 handler function in the client
496 int ctdb_client_set_message_handler(struct ctdb_context *ctdb, uint64_t srvid,
497 ctdb_msg_fn_t handler,
504 res = ctdb_control(ctdb, CTDB_CURRENT_NODE, srvid, CTDB_CONTROL_REGISTER_SRVID, 0,
505 tdb_null, NULL, NULL, &status, NULL, NULL);
506 if (res != 0 || status != 0) {
507 DEBUG(DEBUG_ERR,("Failed to register srvid %llu\n", (unsigned long long)srvid));
511 /* also need to register the handler with our own ctdb structure */
512 return ctdb_register_message_handler(ctdb, ctdb, srvid, handler, private_data);
516 tell the daemon we no longer want a srvid
518 int ctdb_client_remove_message_handler(struct ctdb_context *ctdb, uint64_t srvid, void *private_data)
523 res = ctdb_control(ctdb, CTDB_CURRENT_NODE, srvid, CTDB_CONTROL_DEREGISTER_SRVID, 0,
524 tdb_null, NULL, NULL, &status, NULL, NULL);
525 if (res != 0 || status != 0) {
526 DEBUG(DEBUG_ERR,("Failed to deregister srvid %llu\n", (unsigned long long)srvid));
530 /* also need to register the handler with our own ctdb structure */
531 ctdb_deregister_message_handler(ctdb, srvid, private_data);
537 send a message - from client context
539 int ctdb_client_send_message(struct ctdb_context *ctdb, uint32_t pnn,
540 uint64_t srvid, TDB_DATA data)
542 struct ctdb_req_message *r;
545 len = offsetof(struct ctdb_req_message, data) + data.dsize;
546 r = ctdbd_allocate_pkt(ctdb, ctdb, CTDB_REQ_MESSAGE,
547 len, struct ctdb_req_message);
548 CTDB_NO_MEMORY(ctdb, r);
550 r->hdr.destnode = pnn;
552 r->datalen = data.dsize;
553 memcpy(&r->data[0], data.dptr, data.dsize);
555 res = ctdb_client_queue_pkt(ctdb, &r->hdr);
566 cancel a ctdb_fetch_lock operation, releasing the lock
568 static int fetch_lock_destructor(struct ctdb_record_handle *h)
570 ctdb_ltdb_unlock(h->ctdb_db, h->key);
575 force the migration of a record to this node
577 static int ctdb_client_force_migration(struct ctdb_db_context *ctdb_db, TDB_DATA key)
579 struct ctdb_call call;
581 call.call_id = CTDB_NULL_FUNC;
583 call.flags = CTDB_IMMEDIATE_MIGRATION;
584 return ctdb_call(ctdb_db, &call);
588 get a lock on a record, and return the records data. Blocks until it gets the lock
590 struct ctdb_record_handle *ctdb_fetch_lock(struct ctdb_db_context *ctdb_db, TALLOC_CTX *mem_ctx,
591 TDB_DATA key, TDB_DATA *data)
594 struct ctdb_record_handle *h;
597 procedure is as follows:
599 1) get the chain lock.
600 2) check if we are dmaster
601 3) if we are the dmaster then return handle
602 4) if not dmaster then ask ctdb daemon to make us dmaster, and wait for
604 5) when we get the reply, goto (1)
607 h = talloc_zero(mem_ctx, struct ctdb_record_handle);
612 h->ctdb_db = ctdb_db;
614 h->key.dptr = talloc_memdup(h, key.dptr, key.dsize);
615 if (h->key.dptr == NULL) {
621 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: key=%*.*s\n", (int)key.dsize, (int)key.dsize,
622 (const char *)key.dptr));
625 /* step 1 - get the chain lock */
626 ret = ctdb_ltdb_lock(ctdb_db, key);
628 DEBUG(DEBUG_ERR, (__location__ " failed to lock ltdb record\n"));
633 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: got chain lock\n"));
635 talloc_set_destructor(h, fetch_lock_destructor);
637 ret = ctdb_ltdb_fetch(ctdb_db, key, &h->header, h, data);
639 /* when torturing, ensure we test the remote path */
640 if ((ctdb_db->ctdb->flags & CTDB_FLAG_TORTURE) &&
642 h->header.dmaster = (uint32_t)-1;
646 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: done local fetch\n"));
648 if (ret != 0 || h->header.dmaster != ctdb_db->ctdb->pnn) {
649 ctdb_ltdb_unlock(ctdb_db, key);
650 ret = ctdb_client_force_migration(ctdb_db, key);
652 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: force_migration failed\n"));
659 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: we are dmaster - done\n"));
664 store some data to the record that was locked with ctdb_fetch_lock()
666 int ctdb_record_store(struct ctdb_record_handle *h, TDB_DATA data)
668 if (h->ctdb_db->persistent) {
669 DEBUG(DEBUG_ERR, (__location__ " ctdb_record_store prohibited for persistent dbs\n"));
673 return ctdb_ltdb_store(h->ctdb_db, h->key, &h->header, data);
677 non-locking fetch of a record
679 int ctdb_fetch(struct ctdb_db_context *ctdb_db, TALLOC_CTX *mem_ctx,
680 TDB_DATA key, TDB_DATA *data)
682 struct ctdb_call call;
685 call.call_id = CTDB_FETCH_FUNC;
686 call.call_data.dptr = NULL;
687 call.call_data.dsize = 0;
689 ret = ctdb_call(ctdb_db, &call);
692 *data = call.reply_data;
693 talloc_steal(mem_ctx, data->dptr);
702 called when a control completes or timesout to invoke the callback
703 function the user provided
705 static void invoke_control_callback(struct event_context *ev, struct timed_event *te,
706 struct timeval t, void *private_data)
708 struct ctdb_client_control_state *state;
709 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
712 state = talloc_get_type(private_data, struct ctdb_client_control_state);
713 talloc_steal(tmp_ctx, state);
715 ret = ctdb_control_recv(state->ctdb, state, state,
720 talloc_free(tmp_ctx);
724 called when a CTDB_REPLY_CONTROL packet comes in in the client
726 This packet comes in response to a CTDB_REQ_CONTROL request packet. It
727 contains any reply data from the control
729 static void ctdb_client_reply_control(struct ctdb_context *ctdb,
730 struct ctdb_req_header *hdr)
732 struct ctdb_reply_control *c = (struct ctdb_reply_control *)hdr;
733 struct ctdb_client_control_state *state;
735 state = ctdb_reqid_find(ctdb, hdr->reqid, struct ctdb_client_control_state);
737 DEBUG(DEBUG_ERR,(__location__ " reqid %u not found\n", hdr->reqid));
741 if (hdr->reqid != state->reqid) {
742 /* we found a record but it was the wrong one */
743 DEBUG(DEBUG_ERR, ("Dropped orphaned reply control with reqid:%u\n",hdr->reqid));
747 state->outdata.dptr = c->data;
748 state->outdata.dsize = c->datalen;
749 state->status = c->status;
751 state->errormsg = talloc_strndup(state,
752 (char *)&c->data[c->datalen],
756 /* state->outdata now uses resources from c so we dont want c
757 to just dissappear from under us while state is still alive
759 talloc_steal(state, c);
761 state->state = CTDB_CONTROL_DONE;
763 /* if we had a callback registered for this control, pull the response
764 and call the callback.
766 if (state->async.fn) {
767 event_add_timed(ctdb->ev, state, timeval_zero(), invoke_control_callback, state);
773 destroy a ctdb_control in client
775 static int ctdb_control_destructor(struct ctdb_client_control_state *state)
777 ctdb_reqid_remove(state->ctdb, state->reqid);
782 /* time out handler for ctdb_control */
783 static void control_timeout_func(struct event_context *ev, struct timed_event *te,
784 struct timeval t, void *private_data)
786 struct ctdb_client_control_state *state = talloc_get_type(private_data, struct ctdb_client_control_state);
788 DEBUG(DEBUG_ERR,(__location__ " control timed out. reqid:%u opcode:%u "
789 "dstnode:%u\n", state->reqid, state->c->opcode,
790 state->c->hdr.destnode));
792 state->state = CTDB_CONTROL_TIMEOUT;
794 /* if we had a callback registered for this control, pull the response
795 and call the callback.
797 if (state->async.fn) {
798 event_add_timed(state->ctdb->ev, state, timeval_zero(), invoke_control_callback, state);
802 /* async version of send control request */
803 struct ctdb_client_control_state *ctdb_control_send(struct ctdb_context *ctdb,
804 uint32_t destnode, uint64_t srvid,
805 uint32_t opcode, uint32_t flags, TDB_DATA data,
807 struct timeval *timeout,
810 struct ctdb_client_control_state *state;
812 struct ctdb_req_control *c;
819 /* if the domain socket is not yet open, open it */
820 if (ctdb->daemon.sd==-1) {
821 ctdb_socket_connect(ctdb);
824 state = talloc_zero(mem_ctx, struct ctdb_client_control_state);
825 CTDB_NO_MEMORY_NULL(ctdb, state);
828 state->reqid = ctdb_reqid_new(ctdb, state);
829 state->state = CTDB_CONTROL_WAIT;
830 state->errormsg = NULL;
832 talloc_set_destructor(state, ctdb_control_destructor);
834 len = offsetof(struct ctdb_req_control, data) + data.dsize;
835 c = ctdbd_allocate_pkt(ctdb, state, CTDB_REQ_CONTROL,
836 len, struct ctdb_req_control);
838 CTDB_NO_MEMORY_NULL(ctdb, c);
839 c->hdr.reqid = state->reqid;
840 c->hdr.destnode = destnode;
845 c->datalen = data.dsize;
847 memcpy(&c->data[0], data.dptr, data.dsize);
851 if (timeout && !timeval_is_zero(timeout)) {
852 event_add_timed(ctdb->ev, state, *timeout, control_timeout_func, state);
855 ret = ctdb_client_queue_pkt(ctdb, &(c->hdr));
861 if (flags & CTDB_CTRL_FLAG_NOREPLY) {
870 /* async version of receive control reply */
871 int ctdb_control_recv(struct ctdb_context *ctdb,
872 struct ctdb_client_control_state *state,
874 TDB_DATA *outdata, int32_t *status, char **errormsg)
878 if (status != NULL) {
881 if (errormsg != NULL) {
889 /* prevent double free of state */
890 tmp_ctx = talloc_new(ctdb);
891 talloc_steal(tmp_ctx, state);
893 /* loop one event at a time until we either timeout or the control
896 while (state->state == CTDB_CONTROL_WAIT) {
897 event_loop_once(ctdb->ev);
900 if (state->state != CTDB_CONTROL_DONE) {
901 DEBUG(DEBUG_ERR,(__location__ " ctdb_control_recv failed\n"));
902 if (state->async.fn) {
903 state->async.fn(state);
905 talloc_free(tmp_ctx);
909 if (state->errormsg) {
910 DEBUG(DEBUG_ERR,("ctdb_control error: '%s'\n", state->errormsg));
912 (*errormsg) = talloc_move(mem_ctx, &state->errormsg);
914 if (state->async.fn) {
915 state->async.fn(state);
917 talloc_free(tmp_ctx);
922 *outdata = state->outdata;
923 outdata->dptr = talloc_memdup(mem_ctx, outdata->dptr, outdata->dsize);
927 *status = state->status;
930 if (state->async.fn) {
931 state->async.fn(state);
934 talloc_free(tmp_ctx);
941 send a ctdb control message
942 timeout specifies how long we should wait for a reply.
943 if timeout is NULL we wait indefinitely
945 int ctdb_control(struct ctdb_context *ctdb, uint32_t destnode, uint64_t srvid,
946 uint32_t opcode, uint32_t flags, TDB_DATA data,
947 TALLOC_CTX *mem_ctx, TDB_DATA *outdata, int32_t *status,
948 struct timeval *timeout,
951 struct ctdb_client_control_state *state;
953 state = ctdb_control_send(ctdb, destnode, srvid, opcode,
954 flags, data, mem_ctx,
956 return ctdb_control_recv(ctdb, state, mem_ctx, outdata, status,
964 a process exists call. Returns 0 if process exists, -1 otherwise
966 int ctdb_ctrl_process_exists(struct ctdb_context *ctdb, uint32_t destnode, pid_t pid)
972 data.dptr = (uint8_t*)&pid;
973 data.dsize = sizeof(pid);
975 ret = ctdb_control(ctdb, destnode, 0,
976 CTDB_CONTROL_PROCESS_EXISTS, 0, data,
977 NULL, NULL, &status, NULL, NULL);
979 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for process_exists failed\n"));
987 get remote statistics
989 int ctdb_ctrl_statistics(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_statistics *status)
995 ret = ctdb_control(ctdb, destnode, 0,
996 CTDB_CONTROL_STATISTICS, 0, tdb_null,
997 ctdb, &data, &res, NULL, NULL);
998 if (ret != 0 || res != 0) {
999 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for statistics failed\n"));
1003 if (data.dsize != sizeof(struct ctdb_statistics)) {
1004 DEBUG(DEBUG_ERR,(__location__ " Wrong statistics size %u - expected %u\n",
1005 (unsigned)data.dsize, (unsigned)sizeof(struct ctdb_statistics)));
1009 *status = *(struct ctdb_statistics *)data.dptr;
1010 talloc_free(data.dptr);
1016 shutdown a remote ctdb node
1018 int ctdb_ctrl_shutdown(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
1020 struct ctdb_client_control_state *state;
1022 state = ctdb_control_send(ctdb, destnode, 0,
1023 CTDB_CONTROL_SHUTDOWN, 0, tdb_null,
1024 NULL, &timeout, NULL);
1025 if (state == NULL) {
1026 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for shutdown failed\n"));
1034 get vnn map from a remote node
1036 int ctdb_ctrl_getvnnmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_vnn_map **vnnmap)
1041 struct ctdb_vnn_map_wire *map;
1043 ret = ctdb_control(ctdb, destnode, 0,
1044 CTDB_CONTROL_GETVNNMAP, 0, tdb_null,
1045 mem_ctx, &outdata, &res, &timeout, NULL);
1046 if (ret != 0 || res != 0) {
1047 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getvnnmap failed\n"));
1051 map = (struct ctdb_vnn_map_wire *)outdata.dptr;
1052 if (outdata.dsize < offsetof(struct ctdb_vnn_map_wire, map) ||
1053 outdata.dsize != map->size*sizeof(uint32_t) + offsetof(struct ctdb_vnn_map_wire, map)) {
1054 DEBUG(DEBUG_ERR,("Bad vnn map size received in ctdb_ctrl_getvnnmap\n"));
1058 (*vnnmap) = talloc(mem_ctx, struct ctdb_vnn_map);
1059 CTDB_NO_MEMORY(ctdb, *vnnmap);
1060 (*vnnmap)->generation = map->generation;
1061 (*vnnmap)->size = map->size;
1062 (*vnnmap)->map = talloc_array(*vnnmap, uint32_t, map->size);
1064 CTDB_NO_MEMORY(ctdb, (*vnnmap)->map);
1065 memcpy((*vnnmap)->map, map->map, sizeof(uint32_t)*map->size);
1066 talloc_free(outdata.dptr);
1073 get the recovery mode of a remote node
1075 struct ctdb_client_control_state *
1076 ctdb_ctrl_getrecmode_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode)
1078 return ctdb_control_send(ctdb, destnode, 0,
1079 CTDB_CONTROL_GET_RECMODE, 0, tdb_null,
1080 mem_ctx, &timeout, NULL);
1083 int ctdb_ctrl_getrecmode_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *recmode)
1088 ret = ctdb_control_recv(ctdb, state, mem_ctx, NULL, &res, NULL);
1090 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_getrecmode_recv failed\n"));
1095 *recmode = (uint32_t)res;
1101 int ctdb_ctrl_getrecmode(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, uint32_t *recmode)
1103 struct ctdb_client_control_state *state;
1105 state = ctdb_ctrl_getrecmode_send(ctdb, mem_ctx, timeout, destnode);
1106 return ctdb_ctrl_getrecmode_recv(ctdb, mem_ctx, state, recmode);
1113 set the recovery mode of a remote node
1115 int ctdb_ctrl_setrecmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmode)
1121 data.dsize = sizeof(uint32_t);
1122 data.dptr = (unsigned char *)&recmode;
1124 ret = ctdb_control(ctdb, destnode, 0,
1125 CTDB_CONTROL_SET_RECMODE, 0, data,
1126 NULL, NULL, &res, &timeout, NULL);
1127 if (ret != 0 || res != 0) {
1128 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setrecmode failed\n"));
1138 get the recovery master of a remote node
1140 struct ctdb_client_control_state *
1141 ctdb_ctrl_getrecmaster_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx,
1142 struct timeval timeout, uint32_t destnode)
1144 return ctdb_control_send(ctdb, destnode, 0,
1145 CTDB_CONTROL_GET_RECMASTER, 0, tdb_null,
1146 mem_ctx, &timeout, NULL);
1149 int ctdb_ctrl_getrecmaster_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *recmaster)
1154 ret = ctdb_control_recv(ctdb, state, mem_ctx, NULL, &res, NULL);
1156 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_getrecmaster_recv failed\n"));
1161 *recmaster = (uint32_t)res;
1167 int ctdb_ctrl_getrecmaster(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, uint32_t *recmaster)
1169 struct ctdb_client_control_state *state;
1171 state = ctdb_ctrl_getrecmaster_send(ctdb, mem_ctx, timeout, destnode);
1172 return ctdb_ctrl_getrecmaster_recv(ctdb, mem_ctx, state, recmaster);
1177 set the recovery master of a remote node
1179 int ctdb_ctrl_setrecmaster(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmaster)
1186 data.dsize = sizeof(uint32_t);
1187 data.dptr = (unsigned char *)&recmaster;
1189 ret = ctdb_control(ctdb, destnode, 0,
1190 CTDB_CONTROL_SET_RECMASTER, 0, data,
1191 NULL, NULL, &res, &timeout, NULL);
1192 if (ret != 0 || res != 0) {
1193 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setrecmaster failed\n"));
1202 get a list of databases off a remote node
1204 int ctdb_ctrl_getdbmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
1205 TALLOC_CTX *mem_ctx, struct ctdb_dbid_map **dbmap)
1211 ret = ctdb_control(ctdb, destnode, 0,
1212 CTDB_CONTROL_GET_DBMAP, 0, tdb_null,
1213 mem_ctx, &outdata, &res, &timeout, NULL);
1214 if (ret != 0 || res != 0) {
1215 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getdbmap failed ret:%d res:%d\n", ret, res));
1219 *dbmap = (struct ctdb_dbid_map *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
1220 talloc_free(outdata.dptr);
1226 get a list of nodes (vnn and flags ) from a remote node
1228 int ctdb_ctrl_getnodemap(struct ctdb_context *ctdb,
1229 struct timeval timeout, uint32_t destnode,
1230 TALLOC_CTX *mem_ctx, struct ctdb_node_map **nodemap)
1236 ret = ctdb_control(ctdb, destnode, 0,
1237 CTDB_CONTROL_GET_NODEMAP, 0, tdb_null,
1238 mem_ctx, &outdata, &res, &timeout, NULL);
1239 if (ret == 0 && res == -1 && outdata.dsize == 0) {
1240 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getnodes failed, falling back to ipv4-only control\n"));
1241 return ctdb_ctrl_getnodemapv4(ctdb, timeout, destnode, mem_ctx, nodemap);
1243 if (ret != 0 || res != 0 || outdata.dsize == 0) {
1244 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getnodes failed ret:%d res:%d\n", ret, res));
1248 *nodemap = (struct ctdb_node_map *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
1249 talloc_free(outdata.dptr);
1255 old style ipv4-only get a list of nodes (vnn and flags ) from a remote node
1257 int ctdb_ctrl_getnodemapv4(struct ctdb_context *ctdb,
1258 struct timeval timeout, uint32_t destnode,
1259 TALLOC_CTX *mem_ctx, struct ctdb_node_map **nodemap)
1263 struct ctdb_node_mapv4 *nodemapv4;
1266 ret = ctdb_control(ctdb, destnode, 0,
1267 CTDB_CONTROL_GET_NODEMAPv4, 0, tdb_null,
1268 mem_ctx, &outdata, &res, &timeout, NULL);
1269 if (ret != 0 || res != 0 || outdata.dsize == 0) {
1270 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getnodesv4 failed ret:%d res:%d\n", ret, res));
1274 nodemapv4 = (struct ctdb_node_mapv4 *)outdata.dptr;
1276 len = offsetof(struct ctdb_node_map, nodes) + nodemapv4->num*sizeof(struct ctdb_node_and_flags);
1277 (*nodemap) = talloc_zero_size(mem_ctx, len);
1278 CTDB_NO_MEMORY(ctdb, (*nodemap));
1280 (*nodemap)->num = nodemapv4->num;
1281 for (i=0; i<nodemapv4->num; i++) {
1282 (*nodemap)->nodes[i].pnn = nodemapv4->nodes[i].pnn;
1283 (*nodemap)->nodes[i].flags = nodemapv4->nodes[i].flags;
1284 (*nodemap)->nodes[i].addr.ip = nodemapv4->nodes[i].sin;
1285 (*nodemap)->nodes[i].addr.sa.sa_family = AF_INET;
1288 talloc_free(outdata.dptr);
1294 drop the transport, reload the nodes file and restart the transport
1296 int ctdb_ctrl_reload_nodes_file(struct ctdb_context *ctdb,
1297 struct timeval timeout, uint32_t destnode)
1302 ret = ctdb_control(ctdb, destnode, 0,
1303 CTDB_CONTROL_RELOAD_NODES_FILE, 0, tdb_null,
1304 NULL, NULL, &res, &timeout, NULL);
1305 if (ret != 0 || res != 0) {
1306 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for reloadnodesfile failed\n"));
1315 set vnn map on a node
1317 int ctdb_ctrl_setvnnmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
1318 TALLOC_CTX *mem_ctx, struct ctdb_vnn_map *vnnmap)
1323 struct ctdb_vnn_map_wire *map;
1326 len = offsetof(struct ctdb_vnn_map_wire, map) + sizeof(uint32_t)*vnnmap->size;
1327 map = talloc_size(mem_ctx, len);
1328 CTDB_NO_MEMORY(ctdb, map);
1330 map->generation = vnnmap->generation;
1331 map->size = vnnmap->size;
1332 memcpy(map->map, vnnmap->map, sizeof(uint32_t)*map->size);
1335 data.dptr = (uint8_t *)map;
1337 ret = ctdb_control(ctdb, destnode, 0,
1338 CTDB_CONTROL_SETVNNMAP, 0, data,
1339 NULL, NULL, &res, &timeout, NULL);
1340 if (ret != 0 || res != 0) {
1341 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setvnnmap failed\n"));
1352 async send for pull database
1354 struct ctdb_client_control_state *ctdb_ctrl_pulldb_send(
1355 struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid,
1356 uint32_t lmaster, TALLOC_CTX *mem_ctx, struct timeval timeout)
1359 struct ctdb_control_pulldb *pull;
1360 struct ctdb_client_control_state *state;
1362 pull = talloc(mem_ctx, struct ctdb_control_pulldb);
1363 CTDB_NO_MEMORY_NULL(ctdb, pull);
1366 pull->lmaster = lmaster;
1368 indata.dsize = sizeof(struct ctdb_control_pulldb);
1369 indata.dptr = (unsigned char *)pull;
1371 state = ctdb_control_send(ctdb, destnode, 0,
1372 CTDB_CONTROL_PULL_DB, 0, indata,
1373 mem_ctx, &timeout, NULL);
1380 async recv for pull database
1382 int ctdb_ctrl_pulldb_recv(
1383 struct ctdb_context *ctdb,
1384 TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state,
1390 ret = ctdb_control_recv(ctdb, state, mem_ctx, outdata, &res, NULL);
1391 if ( (ret != 0) || (res != 0) ){
1392 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_pulldb_recv failed\n"));
1400 pull all keys and records for a specific database on a node
1402 int ctdb_ctrl_pulldb(struct ctdb_context *ctdb, uint32_t destnode,
1403 uint32_t dbid, uint32_t lmaster,
1404 TALLOC_CTX *mem_ctx, struct timeval timeout,
1407 struct ctdb_client_control_state *state;
1409 state = ctdb_ctrl_pulldb_send(ctdb, destnode, dbid, lmaster, mem_ctx,
1412 return ctdb_ctrl_pulldb_recv(ctdb, mem_ctx, state, outdata);
1417 change dmaster for all keys in the database to the new value
1419 int ctdb_ctrl_setdmaster(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
1420 TALLOC_CTX *mem_ctx, uint32_t dbid, uint32_t dmaster)
1426 indata.dsize = 2*sizeof(uint32_t);
1427 indata.dptr = (unsigned char *)talloc_array(mem_ctx, uint32_t, 2);
1429 ((uint32_t *)(&indata.dptr[0]))[0] = dbid;
1430 ((uint32_t *)(&indata.dptr[0]))[1] = dmaster;
1432 ret = ctdb_control(ctdb, destnode, 0,
1433 CTDB_CONTROL_SET_DMASTER, 0, indata,
1434 NULL, NULL, &res, &timeout, NULL);
1435 if (ret != 0 || res != 0) {
1436 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setdmaster failed\n"));
1444 ping a node, return number of clients connected
1446 int ctdb_ctrl_ping(struct ctdb_context *ctdb, uint32_t destnode)
1451 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_PING, 0,
1452 tdb_null, NULL, NULL, &res, NULL, NULL);
1460 find the real path to a ltdb
1462 int ctdb_ctrl_getdbpath(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t dbid, TALLOC_CTX *mem_ctx,
1469 data.dptr = (uint8_t *)&dbid;
1470 data.dsize = sizeof(dbid);
1472 ret = ctdb_control(ctdb, destnode, 0,
1473 CTDB_CONTROL_GETDBPATH, 0, data,
1474 mem_ctx, &data, &res, &timeout, NULL);
1475 if (ret != 0 || res != 0) {
1479 (*path) = talloc_strndup(mem_ctx, (const char *)data.dptr, data.dsize);
1480 if ((*path) == NULL) {
1484 talloc_free(data.dptr);
1490 find the name of a db
1492 int ctdb_ctrl_getdbname(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t dbid, TALLOC_CTX *mem_ctx,
1499 data.dptr = (uint8_t *)&dbid;
1500 data.dsize = sizeof(dbid);
1502 ret = ctdb_control(ctdb, destnode, 0,
1503 CTDB_CONTROL_GET_DBNAME, 0, data,
1504 mem_ctx, &data, &res, &timeout, NULL);
1505 if (ret != 0 || res != 0) {
1509 (*name) = talloc_strndup(mem_ctx, (const char *)data.dptr, data.dsize);
1510 if ((*name) == NULL) {
1514 talloc_free(data.dptr);
1520 get the health status of a db
1522 int ctdb_ctrl_getdbhealth(struct ctdb_context *ctdb,
1523 struct timeval timeout,
1525 uint32_t dbid, TALLOC_CTX *mem_ctx,
1526 const char **reason)
1532 data.dptr = (uint8_t *)&dbid;
1533 data.dsize = sizeof(dbid);
1535 ret = ctdb_control(ctdb, destnode, 0,
1536 CTDB_CONTROL_DB_GET_HEALTH, 0, data,
1537 mem_ctx, &data, &res, &timeout, NULL);
1538 if (ret != 0 || res != 0) {
1542 if (data.dsize == 0) {
1547 (*reason) = talloc_strndup(mem_ctx, (const char *)data.dptr, data.dsize);
1548 if ((*reason) == NULL) {
1552 talloc_free(data.dptr);
1560 int ctdb_ctrl_createdb(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
1561 TALLOC_CTX *mem_ctx, const char *name, bool persistent)
1567 data.dptr = discard_const(name);
1568 data.dsize = strlen(name)+1;
1570 ret = ctdb_control(ctdb, destnode, 0,
1571 persistent?CTDB_CONTROL_DB_ATTACH_PERSISTENT:CTDB_CONTROL_DB_ATTACH,
1573 mem_ctx, &data, &res, &timeout, NULL);
1575 if (ret != 0 || res != 0) {
1583 get debug level on a node
1585 int ctdb_ctrl_get_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, int32_t *level)
1591 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_DEBUG, 0, tdb_null,
1592 ctdb, &data, &res, NULL, NULL);
1593 if (ret != 0 || res != 0) {
1596 if (data.dsize != sizeof(int32_t)) {
1597 DEBUG(DEBUG_ERR,("Bad control reply size in ctdb_get_debuglevel (got %u)\n",
1598 (unsigned)data.dsize));
1601 *level = *(int32_t *)data.dptr;
1602 talloc_free(data.dptr);
1607 set debug level on a node
1609 int ctdb_ctrl_set_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, int32_t level)
1615 data.dptr = (uint8_t *)&level;
1616 data.dsize = sizeof(level);
1618 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SET_DEBUG, 0, data,
1619 NULL, NULL, &res, NULL, NULL);
1620 if (ret != 0 || res != 0) {
1628 get a list of connected nodes
1630 uint32_t *ctdb_get_connected_nodes(struct ctdb_context *ctdb,
1631 struct timeval timeout,
1632 TALLOC_CTX *mem_ctx,
1633 uint32_t *num_nodes)
1635 struct ctdb_node_map *map=NULL;
1641 ret = ctdb_ctrl_getnodemap(ctdb, timeout, CTDB_CURRENT_NODE, mem_ctx, &map);
1646 nodes = talloc_array(mem_ctx, uint32_t, map->num);
1647 if (nodes == NULL) {
1651 for (i=0;i<map->num;i++) {
1652 if (!(map->nodes[i].flags & NODE_FLAGS_DISCONNECTED)) {
1653 nodes[*num_nodes] = map->nodes[i].pnn;
1665 int ctdb_statistics_reset(struct ctdb_context *ctdb, uint32_t destnode)
1670 ret = ctdb_control(ctdb, destnode, 0,
1671 CTDB_CONTROL_STATISTICS_RESET, 0, tdb_null,
1672 NULL, NULL, &res, NULL, NULL);
1673 if (ret != 0 || res != 0) {
1674 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for reset statistics failed\n"));
1681 this is the dummy null procedure that all databases support
1683 static int ctdb_null_func(struct ctdb_call_info *call)
1689 this is a plain fetch procedure that all databases support
1691 static int ctdb_fetch_func(struct ctdb_call_info *call)
1693 call->reply_data = &call->record_data;
1698 this is a plain fetch procedure that all databases support
1699 this returns the full record including the ltdb header
1701 static int ctdb_fetch_with_header_func(struct ctdb_call_info *call)
1703 call->reply_data = talloc(call, TDB_DATA);
1704 if (call->reply_data == NULL) {
1707 call->reply_data->dsize = sizeof(struct ctdb_ltdb_header) + call->record_data.dsize;
1708 call->reply_data->dptr = talloc_size(call->reply_data, call->reply_data->dsize);
1709 if (call->reply_data->dptr == NULL) {
1712 memcpy(call->reply_data->dptr, call->header, sizeof(struct ctdb_ltdb_header));
1713 memcpy(&call->reply_data->dptr[sizeof(struct ctdb_ltdb_header)], call->record_data.dptr, call->record_data.dsize);
1719 attach to a specific database - client call
1721 struct ctdb_db_context *ctdb_attach(struct ctdb_context *ctdb, const char *name, bool persistent, uint32_t tdb_flags)
1723 struct ctdb_db_context *ctdb_db;
1728 ctdb_db = ctdb_db_handle(ctdb, name);
1733 ctdb_db = talloc_zero(ctdb, struct ctdb_db_context);
1734 CTDB_NO_MEMORY_NULL(ctdb, ctdb_db);
1736 ctdb_db->ctdb = ctdb;
1737 ctdb_db->db_name = talloc_strdup(ctdb_db, name);
1738 CTDB_NO_MEMORY_NULL(ctdb, ctdb_db->db_name);
1740 data.dptr = discard_const(name);
1741 data.dsize = strlen(name)+1;
1743 /* tell ctdb daemon to attach */
1744 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, tdb_flags,
1745 persistent?CTDB_CONTROL_DB_ATTACH_PERSISTENT:CTDB_CONTROL_DB_ATTACH,
1746 0, data, ctdb_db, &data, &res, NULL, NULL);
1747 if (ret != 0 || res != 0 || data.dsize != sizeof(uint32_t)) {
1748 DEBUG(DEBUG_ERR,("Failed to attach to database '%s'\n", name));
1749 talloc_free(ctdb_db);
1753 ctdb_db->db_id = *(uint32_t *)data.dptr;
1754 talloc_free(data.dptr);
1756 ret = ctdb_ctrl_getdbpath(ctdb, timeval_current_ofs(2, 0), CTDB_CURRENT_NODE, ctdb_db->db_id, ctdb_db, &ctdb_db->db_path);
1758 DEBUG(DEBUG_ERR,("Failed to get dbpath for database '%s'\n", name));
1759 talloc_free(ctdb_db);
1763 tdb_flags = persistent?TDB_DEFAULT:TDB_NOSYNC;
1764 if (ctdb->valgrinding) {
1765 tdb_flags |= TDB_NOMMAP;
1767 tdb_flags |= TDB_DISALLOW_NESTING;
1769 ctdb_db->ltdb = tdb_wrap_open(ctdb, ctdb_db->db_path, 0, tdb_flags, O_RDWR, 0);
1770 if (ctdb_db->ltdb == NULL) {
1771 ctdb_set_error(ctdb, "Failed to open tdb '%s'\n", ctdb_db->db_path);
1772 talloc_free(ctdb_db);
1776 ctdb_db->persistent = persistent;
1778 DLIST_ADD(ctdb->db_list, ctdb_db);
1780 /* add well known functions */
1781 ctdb_set_call(ctdb_db, ctdb_null_func, CTDB_NULL_FUNC);
1782 ctdb_set_call(ctdb_db, ctdb_fetch_func, CTDB_FETCH_FUNC);
1783 ctdb_set_call(ctdb_db, ctdb_fetch_with_header_func, CTDB_FETCH_WITH_HEADER_FUNC);
1790 setup a call for a database
1792 int ctdb_set_call(struct ctdb_db_context *ctdb_db, ctdb_fn_t fn, uint32_t id)
1794 struct ctdb_registered_call *call;
1799 struct ctdb_control_set_call c;
1802 /* this is no longer valid with the separate daemon architecture */
1803 c.db_id = ctdb_db->db_id;
1807 data.dptr = (uint8_t *)&c;
1808 data.dsize = sizeof(c);
1810 ret = ctdb_control(ctdb_db->ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_SET_CALL, 0,
1811 data, NULL, NULL, &status, NULL, NULL);
1812 if (ret != 0 || status != 0) {
1813 DEBUG(DEBUG_ERR,("ctdb_set_call failed for call %u\n", id));
1818 /* also register locally */
1819 call = talloc(ctdb_db, struct ctdb_registered_call);
1823 DLIST_ADD(ctdb_db->calls, call);
1828 struct traverse_state {
1831 ctdb_traverse_func fn;
1836 called on each key during a ctdb_traverse
1838 static void traverse_handler(struct ctdb_context *ctdb, uint64_t srvid, TDB_DATA data, void *p)
1840 struct traverse_state *state = (struct traverse_state *)p;
1841 struct ctdb_rec_data *d = (struct ctdb_rec_data *)data.dptr;
1844 if (data.dsize < sizeof(uint32_t) ||
1845 d->length != data.dsize) {
1846 DEBUG(DEBUG_ERR,("Bad data size %u in traverse_handler\n", (unsigned)data.dsize));
1851 key.dsize = d->keylen;
1852 key.dptr = &d->data[0];
1853 data.dsize = d->datalen;
1854 data.dptr = &d->data[d->keylen];
1856 if (key.dsize == 0 && data.dsize == 0) {
1857 /* end of traverse */
1862 if (data.dsize == sizeof(struct ctdb_ltdb_header)) {
1863 /* empty records are deleted records in ctdb */
1867 if (state->fn(ctdb, key, data, state->private_data) != 0) {
1876 start a cluster wide traverse, calling the supplied fn on each record
1877 return the number of records traversed, or -1 on error
1879 int ctdb_traverse(struct ctdb_db_context *ctdb_db, ctdb_traverse_func fn, void *private_data)
1882 struct ctdb_traverse_start t;
1885 uint64_t srvid = (getpid() | 0xFLL<<60);
1886 struct traverse_state state;
1890 state.private_data = private_data;
1893 ret = ctdb_client_set_message_handler(ctdb_db->ctdb, srvid, traverse_handler, &state);
1895 DEBUG(DEBUG_ERR,("Failed to setup traverse handler\n"));
1899 t.db_id = ctdb_db->db_id;
1903 data.dptr = (uint8_t *)&t;
1904 data.dsize = sizeof(t);
1906 ret = ctdb_control(ctdb_db->ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_TRAVERSE_START, 0,
1907 data, NULL, NULL, &status, NULL, NULL);
1908 if (ret != 0 || status != 0) {
1909 DEBUG(DEBUG_ERR,("ctdb_traverse_all failed\n"));
1910 ctdb_client_remove_message_handler(ctdb_db->ctdb, srvid, &state);
1914 while (!state.done) {
1915 event_loop_once(ctdb_db->ctdb->ev);
1918 ret = ctdb_client_remove_message_handler(ctdb_db->ctdb, srvid, &state);
1920 DEBUG(DEBUG_ERR,("Failed to remove ctdb_traverse handler\n"));
1927 #define ISASCII(x) (isprint(x) && !strchr("\"\\", (x)))
1929 called on each key during a catdb
1931 int ctdb_dumpdb_record(struct ctdb_context *ctdb, TDB_DATA key, TDB_DATA data, void *p)
1934 FILE *f = (FILE *)p;
1935 struct ctdb_ltdb_header *h = (struct ctdb_ltdb_header *)data.dptr;
1937 fprintf(f, "key(%u) = \"", (unsigned)key.dsize);
1938 for (i=0;i<key.dsize;i++) {
1939 if (ISASCII(key.dptr[i])) {
1940 fprintf(f, "%c", key.dptr[i]);
1942 fprintf(f, "\\%02X", key.dptr[i]);
1947 fprintf(f, "dmaster: %u\n", h->dmaster);
1948 fprintf(f, "rsn: %llu\n", (unsigned long long)h->rsn);
1950 fprintf(f, "data(%u) = \"", (unsigned)(data.dsize - sizeof(*h)));
1951 for (i=sizeof(*h);i<data.dsize;i++) {
1952 if (ISASCII(data.dptr[i])) {
1953 fprintf(f, "%c", data.dptr[i]);
1955 fprintf(f, "\\%02X", data.dptr[i]);
1966 convenience function to list all keys to stdout
1968 int ctdb_dump_db(struct ctdb_db_context *ctdb_db, FILE *f)
1970 return ctdb_traverse(ctdb_db, ctdb_dumpdb_record, f);
1974 get the pid of a ctdb daemon
1976 int ctdb_ctrl_getpid(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *pid)
1981 ret = ctdb_control(ctdb, destnode, 0,
1982 CTDB_CONTROL_GET_PID, 0, tdb_null,
1983 NULL, NULL, &res, &timeout, NULL);
1985 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getpid failed\n"));
1996 async freeze send control
1998 struct ctdb_client_control_state *
1999 ctdb_ctrl_freeze_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, uint32_t priority)
2001 return ctdb_control_send(ctdb, destnode, priority,
2002 CTDB_CONTROL_FREEZE, 0, tdb_null,
2003 mem_ctx, &timeout, NULL);
2007 async freeze recv control
2009 int ctdb_ctrl_freeze_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state)
2014 ret = ctdb_control_recv(ctdb, state, mem_ctx, NULL, &res, NULL);
2015 if ( (ret != 0) || (res != 0) ){
2016 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_freeze_recv failed\n"));
2024 freeze databases of a certain priority
2026 int ctdb_ctrl_freeze_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t priority)
2028 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2029 struct ctdb_client_control_state *state;
2032 state = ctdb_ctrl_freeze_send(ctdb, tmp_ctx, timeout, destnode, priority);
2033 ret = ctdb_ctrl_freeze_recv(ctdb, tmp_ctx, state);
2034 talloc_free(tmp_ctx);
2039 /* Freeze all databases */
2040 int ctdb_ctrl_freeze(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2044 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
2045 if (ctdb_ctrl_freeze_priority(ctdb, timeout, destnode, i) != 0) {
2053 thaw databases of a certain priority
2055 int ctdb_ctrl_thaw_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t priority)
2060 ret = ctdb_control(ctdb, destnode, priority,
2061 CTDB_CONTROL_THAW, 0, tdb_null,
2062 NULL, NULL, &res, &timeout, NULL);
2063 if (ret != 0 || res != 0) {
2064 DEBUG(DEBUG_ERR,(__location__ " ctdb_control thaw failed\n"));
2071 /* thaw all databases */
2072 int ctdb_ctrl_thaw(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2074 return ctdb_ctrl_thaw_priority(ctdb, timeout, destnode, 0);
2078 get pnn of a node, or -1
2080 int ctdb_ctrl_getpnn(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2085 ret = ctdb_control(ctdb, destnode, 0,
2086 CTDB_CONTROL_GET_PNN, 0, tdb_null,
2087 NULL, NULL, &res, &timeout, NULL);
2089 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getpnn failed\n"));
2097 get the monitoring mode of a remote node
2099 int ctdb_ctrl_getmonmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *monmode)
2104 ret = ctdb_control(ctdb, destnode, 0,
2105 CTDB_CONTROL_GET_MONMODE, 0, tdb_null,
2106 NULL, NULL, &res, &timeout, NULL);
2108 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getmonmode failed\n"));
2119 set the monitoring mode of a remote node to active
2121 int ctdb_ctrl_enable_monmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2126 ret = ctdb_control(ctdb, destnode, 0,
2127 CTDB_CONTROL_ENABLE_MONITOR, 0, tdb_null,
2128 NULL, NULL,NULL, &timeout, NULL);
2130 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for enable_monitor failed\n"));
2140 set the monitoring mode of a remote node to disable
2142 int ctdb_ctrl_disable_monmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2147 ret = ctdb_control(ctdb, destnode, 0,
2148 CTDB_CONTROL_DISABLE_MONITOR, 0, tdb_null,
2149 NULL, NULL, NULL, &timeout, NULL);
2151 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for disable_monitor failed\n"));
2163 sent to a node to make it take over an ip address
2165 int ctdb_ctrl_takeover_ip(struct ctdb_context *ctdb, struct timeval timeout,
2166 uint32_t destnode, struct ctdb_public_ip *ip)
2169 struct ctdb_public_ipv4 ipv4;
2173 if (ip->addr.sa.sa_family == AF_INET) {
2175 ipv4.sin = ip->addr.ip;
2177 data.dsize = sizeof(ipv4);
2178 data.dptr = (uint8_t *)&ipv4;
2180 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_TAKEOVER_IPv4, 0, data, NULL,
2181 NULL, &res, &timeout, NULL);
2183 data.dsize = sizeof(*ip);
2184 data.dptr = (uint8_t *)ip;
2186 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_TAKEOVER_IP, 0, data, NULL,
2187 NULL, &res, &timeout, NULL);
2190 if (ret != 0 || res != 0) {
2191 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for takeover_ip failed\n"));
2200 sent to a node to make it release an ip address
2202 int ctdb_ctrl_release_ip(struct ctdb_context *ctdb, struct timeval timeout,
2203 uint32_t destnode, struct ctdb_public_ip *ip)
2206 struct ctdb_public_ipv4 ipv4;
2210 if (ip->addr.sa.sa_family == AF_INET) {
2212 ipv4.sin = ip->addr.ip;
2214 data.dsize = sizeof(ipv4);
2215 data.dptr = (uint8_t *)&ipv4;
2217 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_RELEASE_IPv4, 0, data, NULL,
2218 NULL, &res, &timeout, NULL);
2220 data.dsize = sizeof(*ip);
2221 data.dptr = (uint8_t *)ip;
2223 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_RELEASE_IP, 0, data, NULL,
2224 NULL, &res, &timeout, NULL);
2227 if (ret != 0 || res != 0) {
2228 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for release_ip failed\n"));
2239 int ctdb_ctrl_get_tunable(struct ctdb_context *ctdb,
2240 struct timeval timeout,
2242 const char *name, uint32_t *value)
2244 struct ctdb_control_get_tunable *t;
2245 TDB_DATA data, outdata;
2249 data.dsize = offsetof(struct ctdb_control_get_tunable, name) + strlen(name) + 1;
2250 data.dptr = talloc_size(ctdb, data.dsize);
2251 CTDB_NO_MEMORY(ctdb, data.dptr);
2253 t = (struct ctdb_control_get_tunable *)data.dptr;
2254 t->length = strlen(name)+1;
2255 memcpy(t->name, name, t->length);
2257 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_TUNABLE, 0, data, ctdb,
2258 &outdata, &res, &timeout, NULL);
2259 talloc_free(data.dptr);
2260 if (ret != 0 || res != 0) {
2261 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get_tunable failed\n"));
2265 if (outdata.dsize != sizeof(uint32_t)) {
2266 DEBUG(DEBUG_ERR,("Invalid return data in get_tunable\n"));
2267 talloc_free(outdata.dptr);
2271 *value = *(uint32_t *)outdata.dptr;
2272 talloc_free(outdata.dptr);
2280 int ctdb_ctrl_set_tunable(struct ctdb_context *ctdb,
2281 struct timeval timeout,
2283 const char *name, uint32_t value)
2285 struct ctdb_control_set_tunable *t;
2290 data.dsize = offsetof(struct ctdb_control_set_tunable, name) + strlen(name) + 1;
2291 data.dptr = talloc_size(ctdb, data.dsize);
2292 CTDB_NO_MEMORY(ctdb, data.dptr);
2294 t = (struct ctdb_control_set_tunable *)data.dptr;
2295 t->length = strlen(name)+1;
2296 memcpy(t->name, name, t->length);
2299 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SET_TUNABLE, 0, data, NULL,
2300 NULL, &res, &timeout, NULL);
2301 talloc_free(data.dptr);
2302 if (ret != 0 || res != 0) {
2303 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set_tunable failed\n"));
2313 int ctdb_ctrl_list_tunables(struct ctdb_context *ctdb,
2314 struct timeval timeout,
2316 TALLOC_CTX *mem_ctx,
2317 const char ***list, uint32_t *count)
2322 struct ctdb_control_list_tunable *t;
2325 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_LIST_TUNABLES, 0, tdb_null,
2326 mem_ctx, &outdata, &res, &timeout, NULL);
2327 if (ret != 0 || res != 0) {
2328 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for list_tunables failed\n"));
2332 t = (struct ctdb_control_list_tunable *)outdata.dptr;
2333 if (outdata.dsize < offsetof(struct ctdb_control_list_tunable, data) ||
2334 t->length > outdata.dsize-offsetof(struct ctdb_control_list_tunable, data)) {
2335 DEBUG(DEBUG_ERR,("Invalid data in list_tunables reply\n"));
2336 talloc_free(outdata.dptr);
2340 p = talloc_strndup(mem_ctx, (char *)t->data, t->length);
2341 CTDB_NO_MEMORY(ctdb, p);
2343 talloc_free(outdata.dptr);
2348 for (s=strtok_r(p, ":", &ptr); s; s=strtok_r(NULL, ":", &ptr)) {
2349 (*list) = talloc_realloc(mem_ctx, *list, const char *, 1+(*count));
2350 CTDB_NO_MEMORY(ctdb, *list);
2351 (*list)[*count] = talloc_strdup(*list, s);
2352 CTDB_NO_MEMORY(ctdb, (*list)[*count]);
2362 int ctdb_ctrl_get_public_ips_flags(struct ctdb_context *ctdb,
2363 struct timeval timeout, uint32_t destnode,
2364 TALLOC_CTX *mem_ctx,
2366 struct ctdb_all_public_ips **ips)
2372 ret = ctdb_control(ctdb, destnode, 0,
2373 CTDB_CONTROL_GET_PUBLIC_IPS, flags, tdb_null,
2374 mem_ctx, &outdata, &res, &timeout, NULL);
2375 if (ret == 0 && res == -1) {
2376 DEBUG(DEBUG_ERR,(__location__ " ctdb_control to get public ips failed, falling back to ipv4-only version\n"));
2377 return ctdb_ctrl_get_public_ipsv4(ctdb, timeout, destnode, mem_ctx, ips);
2379 if (ret != 0 || res != 0) {
2380 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getpublicips failed ret:%d res:%d\n", ret, res));
2384 *ips = (struct ctdb_all_public_ips *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
2385 talloc_free(outdata.dptr);
2390 int ctdb_ctrl_get_public_ips(struct ctdb_context *ctdb,
2391 struct timeval timeout, uint32_t destnode,
2392 TALLOC_CTX *mem_ctx,
2393 struct ctdb_all_public_ips **ips)
2395 return ctdb_ctrl_get_public_ips_flags(ctdb, timeout,
2400 int ctdb_ctrl_get_public_ipsv4(struct ctdb_context *ctdb,
2401 struct timeval timeout, uint32_t destnode,
2402 TALLOC_CTX *mem_ctx, struct ctdb_all_public_ips **ips)
2407 struct ctdb_all_public_ipsv4 *ipsv4;
2409 ret = ctdb_control(ctdb, destnode, 0,
2410 CTDB_CONTROL_GET_PUBLIC_IPSv4, 0, tdb_null,
2411 mem_ctx, &outdata, &res, &timeout, NULL);
2412 if (ret != 0 || res != 0) {
2413 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getpublicips failed\n"));
2417 ipsv4 = (struct ctdb_all_public_ipsv4 *)outdata.dptr;
2418 len = offsetof(struct ctdb_all_public_ips, ips) +
2419 ipsv4->num*sizeof(struct ctdb_public_ip);
2420 *ips = talloc_zero_size(mem_ctx, len);
2421 CTDB_NO_MEMORY(ctdb, *ips);
2422 (*ips)->num = ipsv4->num;
2423 for (i=0; i<ipsv4->num; i++) {
2424 (*ips)->ips[i].pnn = ipsv4->ips[i].pnn;
2425 (*ips)->ips[i].addr.ip = ipsv4->ips[i].sin;
2428 talloc_free(outdata.dptr);
2433 int ctdb_ctrl_get_public_ip_info(struct ctdb_context *ctdb,
2434 struct timeval timeout, uint32_t destnode,
2435 TALLOC_CTX *mem_ctx,
2436 const ctdb_sock_addr *addr,
2437 struct ctdb_control_public_ip_info **_info)
2443 struct ctdb_control_public_ip_info *info;
2447 indata.dptr = discard_const_p(uint8_t, addr);
2448 indata.dsize = sizeof(*addr);
2450 ret = ctdb_control(ctdb, destnode, 0,
2451 CTDB_CONTROL_GET_PUBLIC_IP_INFO, 0, indata,
2452 mem_ctx, &outdata, &res, &timeout, NULL);
2453 if (ret != 0 || res != 0) {
2454 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
2455 "failed ret:%d res:%d\n",
2460 len = offsetof(struct ctdb_control_public_ip_info, ifaces);
2461 if (len > outdata.dsize) {
2462 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
2463 "returned invalid data with size %u > %u\n",
2464 (unsigned int)outdata.dsize,
2465 (unsigned int)len));
2466 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
2470 info = (struct ctdb_control_public_ip_info *)outdata.dptr;
2471 len += info->num*sizeof(struct ctdb_control_iface_info);
2473 if (len > outdata.dsize) {
2474 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
2475 "returned invalid data with size %u > %u\n",
2476 (unsigned int)outdata.dsize,
2477 (unsigned int)len));
2478 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
2482 /* make sure we null terminate the returned strings */
2483 for (i=0; i < info->num; i++) {
2484 info->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
2487 *_info = (struct ctdb_control_public_ip_info *)talloc_memdup(mem_ctx,
2490 talloc_free(outdata.dptr);
2491 if (*_info == NULL) {
2492 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
2493 "talloc_memdup size %u failed\n",
2494 (unsigned int)outdata.dsize));
2501 int ctdb_ctrl_get_ifaces(struct ctdb_context *ctdb,
2502 struct timeval timeout, uint32_t destnode,
2503 TALLOC_CTX *mem_ctx,
2504 struct ctdb_control_get_ifaces **_ifaces)
2509 struct ctdb_control_get_ifaces *ifaces;
2513 ret = ctdb_control(ctdb, destnode, 0,
2514 CTDB_CONTROL_GET_IFACES, 0, tdb_null,
2515 mem_ctx, &outdata, &res, &timeout, NULL);
2516 if (ret != 0 || res != 0) {
2517 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
2518 "failed ret:%d res:%d\n",
2523 len = offsetof(struct ctdb_control_get_ifaces, ifaces);
2524 if (len > outdata.dsize) {
2525 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
2526 "returned invalid data with size %u > %u\n",
2527 (unsigned int)outdata.dsize,
2528 (unsigned int)len));
2529 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
2533 ifaces = (struct ctdb_control_get_ifaces *)outdata.dptr;
2534 len += ifaces->num*sizeof(struct ctdb_control_iface_info);
2536 if (len > outdata.dsize) {
2537 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
2538 "returned invalid data with size %u > %u\n",
2539 (unsigned int)outdata.dsize,
2540 (unsigned int)len));
2541 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
2545 /* make sure we null terminate the returned strings */
2546 for (i=0; i < ifaces->num; i++) {
2547 ifaces->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
2550 *_ifaces = (struct ctdb_control_get_ifaces *)talloc_memdup(mem_ctx,
2553 talloc_free(outdata.dptr);
2554 if (*_ifaces == NULL) {
2555 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
2556 "talloc_memdup size %u failed\n",
2557 (unsigned int)outdata.dsize));
2564 int ctdb_ctrl_set_iface_link(struct ctdb_context *ctdb,
2565 struct timeval timeout, uint32_t destnode,
2566 TALLOC_CTX *mem_ctx,
2567 const struct ctdb_control_iface_info *info)
2573 indata.dptr = discard_const_p(uint8_t, info);
2574 indata.dsize = sizeof(*info);
2576 ret = ctdb_control(ctdb, destnode, 0,
2577 CTDB_CONTROL_SET_IFACE_LINK_STATE, 0, indata,
2578 mem_ctx, NULL, &res, &timeout, NULL);
2579 if (ret != 0 || res != 0) {
2580 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set iface link "
2581 "failed ret:%d res:%d\n",
2590 set/clear the permanent disabled bit on a remote node
2592 int ctdb_ctrl_modflags(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
2593 uint32_t set, uint32_t clear)
2597 struct ctdb_node_map *nodemap=NULL;
2598 struct ctdb_node_flag_change c;
2599 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2604 /* find the recovery master */
2605 ret = ctdb_ctrl_getrecmaster(ctdb, tmp_ctx, timeout, CTDB_CURRENT_NODE, &recmaster);
2607 DEBUG(DEBUG_ERR, (__location__ " Unable to get recmaster from local node\n"));
2608 talloc_free(tmp_ctx);
2613 /* read the node flags from the recmaster */
2614 ret = ctdb_ctrl_getnodemap(ctdb, timeout, recmaster, tmp_ctx, &nodemap);
2616 DEBUG(DEBUG_ERR, (__location__ " Unable to get nodemap from node %u\n", destnode));
2617 talloc_free(tmp_ctx);
2620 if (destnode >= nodemap->num) {
2621 DEBUG(DEBUG_ERR,(__location__ " Nodemap from recmaster does not contain node %d\n", destnode));
2622 talloc_free(tmp_ctx);
2627 c.old_flags = nodemap->nodes[destnode].flags;
2628 c.new_flags = c.old_flags;
2630 c.new_flags &= ~clear;
2632 data.dsize = sizeof(c);
2633 data.dptr = (unsigned char *)&c;
2635 /* send the flags update to all connected nodes */
2636 nodes = list_of_connected_nodes(ctdb, nodemap, tmp_ctx, true);
2638 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_MODIFY_FLAGS,
2640 timeout, false, data,
2643 DEBUG(DEBUG_ERR, (__location__ " Unable to update nodeflags on remote nodes\n"));
2645 talloc_free(tmp_ctx);
2649 talloc_free(tmp_ctx);
2657 int ctdb_ctrl_get_all_tunables(struct ctdb_context *ctdb,
2658 struct timeval timeout,
2660 struct ctdb_tunable *tunables)
2666 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_ALL_TUNABLES, 0, tdb_null, ctdb,
2667 &outdata, &res, &timeout, NULL);
2668 if (ret != 0 || res != 0) {
2669 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get all tunables failed\n"));
2673 if (outdata.dsize != sizeof(*tunables)) {
2674 DEBUG(DEBUG_ERR,(__location__ " bad data size %u in ctdb_ctrl_get_all_tunables should be %u\n",
2675 (unsigned)outdata.dsize, (unsigned)sizeof(*tunables)));
2679 *tunables = *(struct ctdb_tunable *)outdata.dptr;
2680 talloc_free(outdata.dptr);
2685 add a public address to a node
2687 int ctdb_ctrl_add_public_ip(struct ctdb_context *ctdb,
2688 struct timeval timeout,
2690 struct ctdb_control_ip_iface *pub)
2696 data.dsize = offsetof(struct ctdb_control_ip_iface, iface) + pub->len;
2697 data.dptr = (unsigned char *)pub;
2699 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_ADD_PUBLIC_IP, 0, data, NULL,
2700 NULL, &res, &timeout, NULL);
2701 if (ret != 0 || res != 0) {
2702 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for add_public_ip failed\n"));
2710 delete a public address from a node
2712 int ctdb_ctrl_del_public_ip(struct ctdb_context *ctdb,
2713 struct timeval timeout,
2715 struct ctdb_control_ip_iface *pub)
2721 data.dsize = offsetof(struct ctdb_control_ip_iface, iface) + pub->len;
2722 data.dptr = (unsigned char *)pub;
2724 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_DEL_PUBLIC_IP, 0, data, NULL,
2725 NULL, &res, &timeout, NULL);
2726 if (ret != 0 || res != 0) {
2727 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for del_public_ip failed\n"));
2735 kill a tcp connection
2737 int ctdb_ctrl_killtcp(struct ctdb_context *ctdb,
2738 struct timeval timeout,
2740 struct ctdb_control_killtcp *killtcp)
2746 data.dsize = sizeof(struct ctdb_control_killtcp);
2747 data.dptr = (unsigned char *)killtcp;
2749 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_KILL_TCP, 0, data, NULL,
2750 NULL, &res, &timeout, NULL);
2751 if (ret != 0 || res != 0) {
2752 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for killtcp failed\n"));
2762 int ctdb_ctrl_gratious_arp(struct ctdb_context *ctdb,
2763 struct timeval timeout,
2765 ctdb_sock_addr *addr,
2771 struct ctdb_control_gratious_arp *gratious_arp;
2772 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2775 len = strlen(ifname)+1;
2776 gratious_arp = talloc_size(tmp_ctx,
2777 offsetof(struct ctdb_control_gratious_arp, iface) + len);
2778 CTDB_NO_MEMORY(ctdb, gratious_arp);
2780 gratious_arp->addr = *addr;
2781 gratious_arp->len = len;
2782 memcpy(&gratious_arp->iface[0], ifname, len);
2785 data.dsize = offsetof(struct ctdb_control_gratious_arp, iface) + len;
2786 data.dptr = (unsigned char *)gratious_arp;
2788 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SEND_GRATIOUS_ARP, 0, data, NULL,
2789 NULL, &res, &timeout, NULL);
2790 if (ret != 0 || res != 0) {
2791 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for gratious_arp failed\n"));
2792 talloc_free(tmp_ctx);
2796 talloc_free(tmp_ctx);
2801 get a list of all tcp tickles that a node knows about for a particular vnn
2803 int ctdb_ctrl_get_tcp_tickles(struct ctdb_context *ctdb,
2804 struct timeval timeout, uint32_t destnode,
2805 TALLOC_CTX *mem_ctx,
2806 ctdb_sock_addr *addr,
2807 struct ctdb_control_tcp_tickle_list **list)
2810 TDB_DATA data, outdata;
2813 data.dptr = (uint8_t*)addr;
2814 data.dsize = sizeof(ctdb_sock_addr);
2816 ret = ctdb_control(ctdb, destnode, 0,
2817 CTDB_CONTROL_GET_TCP_TICKLE_LIST, 0, data,
2818 mem_ctx, &outdata, &status, NULL, NULL);
2819 if (ret != 0 || status != 0) {
2820 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get tcp tickles failed\n"));
2824 *list = (struct ctdb_control_tcp_tickle_list *)outdata.dptr;
2830 register a server id
2832 int ctdb_ctrl_register_server_id(struct ctdb_context *ctdb,
2833 struct timeval timeout,
2834 struct ctdb_server_id *id)
2840 data.dsize = sizeof(struct ctdb_server_id);
2841 data.dptr = (unsigned char *)id;
2843 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0,
2844 CTDB_CONTROL_REGISTER_SERVER_ID,
2846 NULL, &res, &timeout, NULL);
2847 if (ret != 0 || res != 0) {
2848 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for register server id failed\n"));
2856 unregister a server id
2858 int ctdb_ctrl_unregister_server_id(struct ctdb_context *ctdb,
2859 struct timeval timeout,
2860 struct ctdb_server_id *id)
2866 data.dsize = sizeof(struct ctdb_server_id);
2867 data.dptr = (unsigned char *)id;
2869 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0,
2870 CTDB_CONTROL_UNREGISTER_SERVER_ID,
2872 NULL, &res, &timeout, NULL);
2873 if (ret != 0 || res != 0) {
2874 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for unregister server id failed\n"));
2883 check if a server id exists
2885 if a server id does exist, return *status == 1, otherwise *status == 0
2887 int ctdb_ctrl_check_server_id(struct ctdb_context *ctdb,
2888 struct timeval timeout,
2890 struct ctdb_server_id *id,
2897 data.dsize = sizeof(struct ctdb_server_id);
2898 data.dptr = (unsigned char *)id;
2900 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_CHECK_SERVER_ID,
2902 NULL, &res, &timeout, NULL);
2904 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for check server id failed\n"));
2918 get the list of server ids that are registered on a node
2920 int ctdb_ctrl_get_server_id_list(struct ctdb_context *ctdb,
2921 TALLOC_CTX *mem_ctx,
2922 struct timeval timeout, uint32_t destnode,
2923 struct ctdb_server_id_list **svid_list)
2929 ret = ctdb_control(ctdb, destnode, 0,
2930 CTDB_CONTROL_GET_SERVER_ID_LIST, 0, tdb_null,
2931 mem_ctx, &outdata, &res, &timeout, NULL);
2932 if (ret != 0 || res != 0) {
2933 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get_server_id_list failed\n"));
2937 *svid_list = (struct ctdb_server_id_list *)talloc_steal(mem_ctx, outdata.dptr);
2943 initialise the ctdb daemon for client applications
2945 NOTE: In current code the daemon does not fork. This is for testing purposes only
2946 and to simplify the code.
2948 struct ctdb_context *ctdb_init(struct event_context *ev)
2951 struct ctdb_context *ctdb;
2953 ctdb = talloc_zero(ev, struct ctdb_context);
2955 DEBUG(DEBUG_ERR,(__location__ " talloc_zero failed.\n"));
2959 ctdb->idr = idr_init(ctdb);
2960 /* Wrap early to exercise code. */
2961 ctdb->lastid = INT_MAX-200;
2962 CTDB_NO_MEMORY_NULL(ctdb, ctdb->idr);
2964 ret = ctdb_set_socketname(ctdb, CTDB_PATH);
2966 DEBUG(DEBUG_ERR,(__location__ " ctdb_set_socketname failed.\n"));
2971 ctdb->statistics.statistics_start_time = timeval_current();
2980 void ctdb_set_flags(struct ctdb_context *ctdb, unsigned flags)
2982 ctdb->flags |= flags;
2986 setup the local socket name
2988 int ctdb_set_socketname(struct ctdb_context *ctdb, const char *socketname)
2990 ctdb->daemon.name = talloc_strdup(ctdb, socketname);
2991 CTDB_NO_MEMORY(ctdb, ctdb->daemon.name);
2996 const char *ctdb_get_socketname(struct ctdb_context *ctdb)
2998 return ctdb->daemon.name;
3002 return the pnn of this node
3004 uint32_t ctdb_get_pnn(struct ctdb_context *ctdb)
3011 get the uptime of a remote node
3013 struct ctdb_client_control_state *
3014 ctdb_ctrl_uptime_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode)
3016 return ctdb_control_send(ctdb, destnode, 0,
3017 CTDB_CONTROL_UPTIME, 0, tdb_null,
3018 mem_ctx, &timeout, NULL);
3021 int ctdb_ctrl_uptime_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, struct ctdb_uptime **uptime)
3027 ret = ctdb_control_recv(ctdb, state, mem_ctx, &outdata, &res, NULL);
3028 if (ret != 0 || res != 0) {
3029 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_uptime_recv failed\n"));
3033 *uptime = (struct ctdb_uptime *)talloc_steal(mem_ctx, outdata.dptr);
3038 int ctdb_ctrl_uptime(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, struct ctdb_uptime **uptime)
3040 struct ctdb_client_control_state *state;
3042 state = ctdb_ctrl_uptime_send(ctdb, mem_ctx, timeout, destnode);
3043 return ctdb_ctrl_uptime_recv(ctdb, mem_ctx, state, uptime);
3047 send a control to execute the "recovered" event script on a node
3049 int ctdb_ctrl_end_recovery(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
3054 ret = ctdb_control(ctdb, destnode, 0,
3055 CTDB_CONTROL_END_RECOVERY, 0, tdb_null,
3056 NULL, NULL, &status, &timeout, NULL);
3057 if (ret != 0 || status != 0) {
3058 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for end_recovery failed\n"));
3066 callback for the async helpers used when sending the same control
3067 to multiple nodes in parallell.
3069 static void async_callback(struct ctdb_client_control_state *state)
3071 struct client_async_data *data = talloc_get_type(state->async.private_data, struct client_async_data);
3072 struct ctdb_context *ctdb = talloc_get_type(state->ctdb, struct ctdb_context);
3076 uint32_t destnode = state->c->hdr.destnode;
3078 /* one more node has responded with recmode data */
3081 /* if we failed to push the db, then return an error and let
3082 the main loop try again.
3084 if (state->state != CTDB_CONTROL_DONE) {
3085 if ( !data->dont_log_errors) {
3086 DEBUG(DEBUG_ERR,("Async operation failed with state %d, opcode:%u\n", state->state, data->opcode));
3089 if (data->fail_callback) {
3090 data->fail_callback(ctdb, destnode, res, outdata,
3091 data->callback_data);
3096 state->async.fn = NULL;
3098 ret = ctdb_control_recv(ctdb, state, data, &outdata, &res, NULL);
3099 if ((ret != 0) || (res != 0)) {
3100 if ( !data->dont_log_errors) {
3101 DEBUG(DEBUG_ERR,("Async operation failed with ret=%d res=%d opcode=%u\n", ret, (int)res, data->opcode));
3104 if (data->fail_callback) {
3105 data->fail_callback(ctdb, destnode, res, outdata,
3106 data->callback_data);
3109 if ((ret == 0) && (data->callback != NULL)) {
3110 data->callback(ctdb, destnode, res, outdata,
3111 data->callback_data);
3116 void ctdb_client_async_add(struct client_async_data *data, struct ctdb_client_control_state *state)
3118 /* set up the callback functions */
3119 state->async.fn = async_callback;
3120 state->async.private_data = data;
3122 /* one more control to wait for to complete */
3127 /* wait for up to the maximum number of seconds allowed
3128 or until all nodes we expect a response from has replied
3130 int ctdb_client_async_wait(struct ctdb_context *ctdb, struct client_async_data *data)
3132 while (data->count > 0) {
3133 event_loop_once(ctdb->ev);
3135 if (data->fail_count != 0) {
3136 if (!data->dont_log_errors) {
3137 DEBUG(DEBUG_ERR,("Async wait failed - fail_count=%u\n",
3147 perform a simple control on the listed nodes
3148 The control cannot return data
3150 int ctdb_client_async_control(struct ctdb_context *ctdb,
3151 enum ctdb_controls opcode,
3154 struct timeval timeout,
3155 bool dont_log_errors,
3157 client_async_callback client_callback,
3158 client_async_callback fail_callback,
3159 void *callback_data)
3161 struct client_async_data *async_data;
3162 struct ctdb_client_control_state *state;
3165 async_data = talloc_zero(ctdb, struct client_async_data);
3166 CTDB_NO_MEMORY_FATAL(ctdb, async_data);
3167 async_data->dont_log_errors = dont_log_errors;
3168 async_data->callback = client_callback;
3169 async_data->fail_callback = fail_callback;
3170 async_data->callback_data = callback_data;
3171 async_data->opcode = opcode;
3173 num_nodes = talloc_get_size(nodes) / sizeof(uint32_t);
3175 /* loop over all nodes and send an async control to each of them */
3176 for (j=0; j<num_nodes; j++) {
3177 uint32_t pnn = nodes[j];
3179 state = ctdb_control_send(ctdb, pnn, srvid, opcode,
3180 0, data, async_data, &timeout, NULL);
3181 if (state == NULL) {
3182 DEBUG(DEBUG_ERR,(__location__ " Failed to call async control %u\n", (unsigned)opcode));
3183 talloc_free(async_data);
3187 ctdb_client_async_add(async_data, state);
3190 if (ctdb_client_async_wait(ctdb, async_data) != 0) {
3191 talloc_free(async_data);
3195 talloc_free(async_data);
3199 uint32_t *list_of_vnnmap_nodes(struct ctdb_context *ctdb,
3200 struct ctdb_vnn_map *vnn_map,
3201 TALLOC_CTX *mem_ctx,
3204 int i, j, num_nodes;
3207 for (i=num_nodes=0;i<vnn_map->size;i++) {
3208 if (vnn_map->map[i] == ctdb->pnn && !include_self) {
3214 nodes = talloc_array(mem_ctx, uint32_t, num_nodes);
3215 CTDB_NO_MEMORY_FATAL(ctdb, nodes);
3217 for (i=j=0;i<vnn_map->size;i++) {
3218 if (vnn_map->map[i] == ctdb->pnn && !include_self) {
3221 nodes[j++] = vnn_map->map[i];
3227 uint32_t *list_of_active_nodes(struct ctdb_context *ctdb,
3228 struct ctdb_node_map *node_map,
3229 TALLOC_CTX *mem_ctx,
3232 int i, j, num_nodes;
3235 for (i=num_nodes=0;i<node_map->num;i++) {
3236 if (node_map->nodes[i].flags & NODE_FLAGS_INACTIVE) {
3239 if (node_map->nodes[i].pnn == ctdb->pnn && !include_self) {
3245 nodes = talloc_array(mem_ctx, uint32_t, num_nodes);
3246 CTDB_NO_MEMORY_FATAL(ctdb, nodes);
3248 for (i=j=0;i<node_map->num;i++) {
3249 if (node_map->nodes[i].flags & NODE_FLAGS_INACTIVE) {
3252 if (node_map->nodes[i].pnn == ctdb->pnn && !include_self) {
3255 nodes[j++] = node_map->nodes[i].pnn;
3261 uint32_t *list_of_active_nodes_except_pnn(struct ctdb_context *ctdb,
3262 struct ctdb_node_map *node_map,
3263 TALLOC_CTX *mem_ctx,
3266 int i, j, num_nodes;
3269 for (i=num_nodes=0;i<node_map->num;i++) {
3270 if (node_map->nodes[i].flags & NODE_FLAGS_INACTIVE) {
3273 if (node_map->nodes[i].pnn == pnn) {
3279 nodes = talloc_array(mem_ctx, uint32_t, num_nodes);
3280 CTDB_NO_MEMORY_FATAL(ctdb, nodes);
3282 for (i=j=0;i<node_map->num;i++) {
3283 if (node_map->nodes[i].flags & NODE_FLAGS_INACTIVE) {
3286 if (node_map->nodes[i].pnn == pnn) {
3289 nodes[j++] = node_map->nodes[i].pnn;
3295 uint32_t *list_of_connected_nodes(struct ctdb_context *ctdb,
3296 struct ctdb_node_map *node_map,
3297 TALLOC_CTX *mem_ctx,
3300 int i, j, num_nodes;
3303 for (i=num_nodes=0;i<node_map->num;i++) {
3304 if (node_map->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
3307 if (node_map->nodes[i].pnn == ctdb->pnn && !include_self) {
3313 nodes = talloc_array(mem_ctx, uint32_t, num_nodes);
3314 CTDB_NO_MEMORY_FATAL(ctdb, nodes);
3316 for (i=j=0;i<node_map->num;i++) {
3317 if (node_map->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
3320 if (node_map->nodes[i].pnn == ctdb->pnn && !include_self) {
3323 nodes[j++] = node_map->nodes[i].pnn;
3330 this is used to test if a pnn lock exists and if it exists will return
3331 the number of connections that pnn has reported or -1 if that recovery
3332 daemon is not running.
3335 ctdb_read_pnn_lock(int fd, int32_t pnn)
3340 lock.l_type = F_WRLCK;
3341 lock.l_whence = SEEK_SET;
3346 if (fcntl(fd, F_GETLK, &lock) != 0) {
3347 DEBUG(DEBUG_ERR, (__location__ " F_GETLK failed with %s\n", strerror(errno)));
3351 if (lock.l_type == F_UNLCK) {
3355 if (pread(fd, &c, 1, pnn) == -1) {
3356 DEBUG(DEBUG_CRIT,(__location__ " failed read pnn count - %s\n", strerror(errno)));
3364 get capabilities of a remote node
3366 struct ctdb_client_control_state *
3367 ctdb_ctrl_getcapabilities_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode)
3369 return ctdb_control_send(ctdb, destnode, 0,
3370 CTDB_CONTROL_GET_CAPABILITIES, 0, tdb_null,
3371 mem_ctx, &timeout, NULL);
3374 int ctdb_ctrl_getcapabilities_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *capabilities)
3380 ret = ctdb_control_recv(ctdb, state, mem_ctx, &outdata, &res, NULL);
3381 if ( (ret != 0) || (res != 0) ) {
3382 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_getcapabilities_recv failed\n"));
3387 *capabilities = *((uint32_t *)outdata.dptr);
3393 int ctdb_ctrl_getcapabilities(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *capabilities)
3395 struct ctdb_client_control_state *state;
3396 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
3399 state = ctdb_ctrl_getcapabilities_send(ctdb, tmp_ctx, timeout, destnode);
3400 ret = ctdb_ctrl_getcapabilities_recv(ctdb, tmp_ctx, state, capabilities);
3401 talloc_free(tmp_ctx);
3406 * check whether a transaction is active on a given db on a given node
3408 int32_t ctdb_ctrl_transaction_active(struct ctdb_context *ctdb,
3416 indata.dptr = (uint8_t *)&db_id;
3417 indata.dsize = sizeof(db_id);
3419 ret = ctdb_control(ctdb, destnode, 0,
3420 CTDB_CONTROL_TRANS2_ACTIVE,
3421 0, indata, NULL, NULL, &status,
3425 DEBUG(DEBUG_ERR, (__location__ " ctdb control for transaction_active failed\n"));
3433 struct ctdb_transaction_handle {
3434 struct ctdb_db_context *ctdb_db;
3437 * we store the reads and writes done under a transaction:
3438 * - one list stores both reads and writes (m_all),
3439 * - the other just writes (m_write)
3441 struct ctdb_marshall_buffer *m_all;
3442 struct ctdb_marshall_buffer *m_write;
3445 /* start a transaction on a database */
3446 static int ctdb_transaction_destructor(struct ctdb_transaction_handle *h)
3448 tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
3452 /* start a transaction on a database */
3453 static int ctdb_transaction_fetch_start(struct ctdb_transaction_handle *h)
3455 struct ctdb_record_handle *rh;
3458 struct ctdb_ltdb_header header;
3459 TALLOC_CTX *tmp_ctx;
3460 const char *keyname = CTDB_TRANSACTION_LOCK_KEY;
3462 struct ctdb_db_context *ctdb_db = h->ctdb_db;
3466 key.dptr = discard_const(keyname);
3467 key.dsize = strlen(keyname);
3469 if (!ctdb_db->persistent) {
3470 DEBUG(DEBUG_ERR,(__location__ " Attempted transaction on non-persistent database\n"));
3475 tmp_ctx = talloc_new(h);
3477 rh = ctdb_fetch_lock(ctdb_db, tmp_ctx, key, NULL);
3479 DEBUG(DEBUG_ERR,(__location__ " Failed to fetch_lock database\n"));
3480 talloc_free(tmp_ctx);
3484 status = ctdb_ctrl_transaction_active(ctdb_db->ctdb,
3488 unsigned long int usec = (1000 + random()) % 100000;
3489 DEBUG(DEBUG_DEBUG, (__location__ " transaction is active "
3490 "on db_id[0x%08x]. waiting for %lu "
3492 ctdb_db->db_id, usec));
3493 talloc_free(tmp_ctx);
3499 * store the pid in the database:
3500 * it is not enough that the node is dmaster...
3503 data.dptr = (unsigned char *)&pid;
3504 data.dsize = sizeof(pid_t);
3506 rh->header.dmaster = ctdb_db->ctdb->pnn;
3507 ret = ctdb_ltdb_store(ctdb_db, key, &(rh->header), data);
3509 DEBUG(DEBUG_ERR, (__location__ " Failed to store pid in "
3510 "transaction record\n"));
3511 talloc_free(tmp_ctx);
3517 ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
3519 DEBUG(DEBUG_ERR,(__location__ " Failed to start tdb transaction\n"));
3520 talloc_free(tmp_ctx);
3524 ret = ctdb_ltdb_fetch(ctdb_db, key, &header, tmp_ctx, &data);
3526 DEBUG(DEBUG_ERR,(__location__ " Failed to re-fetch transaction "
3527 "lock record inside transaction\n"));
3528 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
3529 talloc_free(tmp_ctx);
3533 if (header.dmaster != ctdb_db->ctdb->pnn) {
3534 DEBUG(DEBUG_DEBUG,(__location__ " not dmaster any more on "
3535 "transaction lock record\n"));
3536 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
3537 talloc_free(tmp_ctx);
3541 if ((data.dsize != sizeof(pid_t)) || (*(pid_t *)(data.dptr) != pid)) {
3542 DEBUG(DEBUG_DEBUG, (__location__ " my pid is not stored in "
3543 "the transaction lock record\n"));
3544 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
3545 talloc_free(tmp_ctx);
3549 talloc_free(tmp_ctx);
3555 /* start a transaction on a database */
3556 struct ctdb_transaction_handle *ctdb_transaction_start(struct ctdb_db_context *ctdb_db,
3557 TALLOC_CTX *mem_ctx)
3559 struct ctdb_transaction_handle *h;
3562 h = talloc_zero(mem_ctx, struct ctdb_transaction_handle);
3564 DEBUG(DEBUG_ERR,(__location__ " oom for transaction handle\n"));
3568 h->ctdb_db = ctdb_db;
3570 ret = ctdb_transaction_fetch_start(h);
3576 talloc_set_destructor(h, ctdb_transaction_destructor);
3584 fetch a record inside a transaction
3586 int ctdb_transaction_fetch(struct ctdb_transaction_handle *h,
3587 TALLOC_CTX *mem_ctx,
3588 TDB_DATA key, TDB_DATA *data)
3590 struct ctdb_ltdb_header header;
3593 ZERO_STRUCT(header);
3595 ret = ctdb_ltdb_fetch(h->ctdb_db, key, &header, mem_ctx, data);
3596 if (ret == -1 && header.dmaster == (uint32_t)-1) {
3597 /* record doesn't exist yet */
3606 if (!h->in_replay) {
3607 h->m_all = ctdb_marshall_add(h, h->m_all, h->ctdb_db->db_id, 1, key, NULL, *data);
3608 if (h->m_all == NULL) {
3609 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
3618 stores a record inside a transaction
3620 int ctdb_transaction_store(struct ctdb_transaction_handle *h,
3621 TDB_DATA key, TDB_DATA data)
3623 TALLOC_CTX *tmp_ctx = talloc_new(h);
3624 struct ctdb_ltdb_header header;
3628 ZERO_STRUCT(header);
3630 /* we need the header so we can update the RSN */
3631 ret = ctdb_ltdb_fetch(h->ctdb_db, key, &header, tmp_ctx, &olddata);
3632 if (ret == -1 && header.dmaster == (uint32_t)-1) {
3633 /* the record doesn't exist - create one with us as dmaster.
3634 This is only safe because we are in a transaction and this
3635 is a persistent database */
3636 ZERO_STRUCT(header);
3637 } else if (ret != 0) {
3638 DEBUG(DEBUG_ERR,(__location__ " Failed to fetch record\n"));
3639 talloc_free(tmp_ctx);
3643 if (data.dsize == olddata.dsize &&
3644 memcmp(data.dptr, olddata.dptr, data.dsize) == 0) {
3645 /* save writing the same data */
3646 talloc_free(tmp_ctx);
3650 header.dmaster = h->ctdb_db->ctdb->pnn;
3653 if (!h->in_replay) {
3654 h->m_all = ctdb_marshall_add(h, h->m_all, h->ctdb_db->db_id, 0, key, NULL, data);
3655 if (h->m_all == NULL) {
3656 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
3657 talloc_free(tmp_ctx);
3662 h->m_write = ctdb_marshall_add(h, h->m_write, h->ctdb_db->db_id, 0, key, &header, data);
3663 if (h->m_write == NULL) {
3664 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
3665 talloc_free(tmp_ctx);
3669 ret = ctdb_ltdb_store(h->ctdb_db, key, &header, data);
3671 talloc_free(tmp_ctx);
3677 replay a transaction
3679 static int ctdb_replay_transaction(struct ctdb_transaction_handle *h)
3682 struct ctdb_rec_data *rec = NULL;
3684 h->in_replay = true;
3685 talloc_free(h->m_write);
3688 ret = ctdb_transaction_fetch_start(h);
3693 for (i=0;i<h->m_all->count;i++) {
3696 rec = ctdb_marshall_loop_next(h->m_all, rec, NULL, NULL, &key, &data);
3698 DEBUG(DEBUG_ERR, (__location__ " Out of records in ctdb_replay_transaction?\n"));
3702 if (rec->reqid == 0) {
3704 if (ctdb_transaction_store(h, key, data) != 0) {
3709 TALLOC_CTX *tmp_ctx = talloc_new(h);
3711 if (ctdb_transaction_fetch(h, tmp_ctx, key, &data2) != 0) {
3712 talloc_free(tmp_ctx);
3715 if (data2.dsize != data.dsize ||
3716 memcmp(data2.dptr, data.dptr, data.dsize) != 0) {
3717 /* the record has changed on us - we have to give up */
3718 talloc_free(tmp_ctx);
3721 talloc_free(tmp_ctx);
3728 tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
3734 commit a transaction
3736 int ctdb_transaction_commit(struct ctdb_transaction_handle *h)
3740 struct ctdb_context *ctdb = h->ctdb_db->ctdb;
3741 struct timeval timeout;
3742 enum ctdb_controls failure_control = CTDB_CONTROL_TRANS2_ERROR;
3744 talloc_set_destructor(h, NULL);
3746 /* our commit strategy is quite complex.
3748 - we first try to commit the changes to all other nodes
3750 - if that works, then we commit locally and we are done
3752 - if a commit on another node fails, then we need to cancel
3753 the transaction, then restart the transaction (thus
3754 opening a window of time for a pending recovery to
3755 complete), then replay the transaction, checking all the
3756 reads and writes (checking that reads give the same data,
3757 and writes succeed). Then we retry the transaction to the
3762 if (h->m_write == NULL) {
3763 /* no changes were made */
3764 tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
3769 /* tell ctdbd to commit to the other nodes */
3770 timeout = timeval_current_ofs(1, 0);
3771 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
3772 retries==0?CTDB_CONTROL_TRANS2_COMMIT:CTDB_CONTROL_TRANS2_COMMIT_RETRY, 0,
3773 ctdb_marshall_finish(h->m_write), NULL, NULL, &status,
3775 if (ret != 0 || status != 0) {
3776 tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
3777 DEBUG(DEBUG_NOTICE, (__location__ " transaction commit%s failed"
3778 ", retrying after 1 second...\n",
3779 (retries==0)?"":"retry "));
3783 failure_control = CTDB_CONTROL_TRANS2_ERROR;
3785 /* work out what error code we will give if we
3786 have to fail the operation */
3787 switch ((enum ctdb_trans2_commit_error)status) {
3788 case CTDB_TRANS2_COMMIT_SUCCESS:
3789 case CTDB_TRANS2_COMMIT_SOMEFAIL:
3790 case CTDB_TRANS2_COMMIT_TIMEOUT:
3791 failure_control = CTDB_CONTROL_TRANS2_ERROR;
3793 case CTDB_TRANS2_COMMIT_ALLFAIL:
3794 failure_control = CTDB_CONTROL_TRANS2_FINISHED;
3799 if (++retries == 100) {
3800 DEBUG(DEBUG_ERR,(__location__ " Giving up transaction on db 0x%08x after %d retries failure_control=%u\n",
3801 h->ctdb_db->db_id, retries, (unsigned)failure_control));
3802 ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
3803 failure_control, CTDB_CTRL_FLAG_NOREPLY,
3804 tdb_null, NULL, NULL, NULL, NULL, NULL);
3809 if (ctdb_replay_transaction(h) != 0) {
3810 DEBUG(DEBUG_ERR, (__location__ " Failed to replay "
3811 "transaction on db 0x%08x, "
3812 "failure control =%u\n",
3814 (unsigned)failure_control));
3815 ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
3816 failure_control, CTDB_CTRL_FLAG_NOREPLY,
3817 tdb_null, NULL, NULL, NULL, NULL, NULL);
3823 failure_control = CTDB_CONTROL_TRANS2_ERROR;
3826 /* do the real commit locally */
3827 ret = tdb_transaction_commit(h->ctdb_db->ltdb->tdb);
3829 DEBUG(DEBUG_ERR, (__location__ " Failed to commit transaction "
3830 "on db id 0x%08x locally, "
3831 "failure_control=%u\n",
3833 (unsigned)failure_control));
3834 ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
3835 failure_control, CTDB_CTRL_FLAG_NOREPLY,
3836 tdb_null, NULL, NULL, NULL, NULL, NULL);
3841 /* tell ctdbd that we are finished with our local commit */
3842 ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
3843 CTDB_CONTROL_TRANS2_FINISHED, CTDB_CTRL_FLAG_NOREPLY,
3844 tdb_null, NULL, NULL, NULL, NULL, NULL);
3850 recovery daemon ping to main daemon
3852 int ctdb_ctrl_recd_ping(struct ctdb_context *ctdb)
3857 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_RECD_PING, 0, tdb_null,
3858 ctdb, NULL, &res, NULL, NULL);
3859 if (ret != 0 || res != 0) {
3860 DEBUG(DEBUG_ERR,("Failed to send recd ping\n"));
3867 /* when forking the main daemon and the child process needs to connect back
3868 * to the daemon as a client process, this function can be used to change
3869 * the ctdb context from daemon into client mode
3871 int switch_from_server_to_client(struct ctdb_context *ctdb, const char *fmt, ...)
3876 /* Add extra information so we can identify this in the logs */
3878 debug_extra = talloc_strdup_append(talloc_vasprintf(NULL, fmt, ap), ":");
3881 /* shutdown the transport */
3882 if (ctdb->methods) {
3883 ctdb->methods->shutdown(ctdb);
3886 /* get a new event context */
3887 talloc_free(ctdb->ev);
3888 ctdb->ev = event_context_init(ctdb);
3889 tevent_loop_allow_nesting(ctdb->ev);
3891 close(ctdb->daemon.sd);
3892 ctdb->daemon.sd = -1;
3894 /* the client does not need to be realtime */
3895 if (ctdb->do_setsched) {
3896 ctdb_restore_scheduler(ctdb);
3899 /* initialise ctdb */
3900 ret = ctdb_socket_connect(ctdb);
3902 DEBUG(DEBUG_ALERT, (__location__ " Failed to init ctdb client\n"));
3910 get the status of running the monitor eventscripts: NULL means never run.
3912 int ctdb_ctrl_getscriptstatus(struct ctdb_context *ctdb,
3913 struct timeval timeout, uint32_t destnode,
3914 TALLOC_CTX *mem_ctx, enum ctdb_eventscript_call type,
3915 struct ctdb_scripts_wire **script_status)
3918 TDB_DATA outdata, indata;
3920 uint32_t uinttype = type;
3922 indata.dptr = (uint8_t *)&uinttype;
3923 indata.dsize = sizeof(uinttype);
3925 ret = ctdb_control(ctdb, destnode, 0,
3926 CTDB_CONTROL_GET_EVENT_SCRIPT_STATUS, 0, indata,
3927 mem_ctx, &outdata, &res, &timeout, NULL);
3928 if (ret != 0 || res != 0) {
3929 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getscriptstatus failed ret:%d res:%d\n", ret, res));
3933 if (outdata.dsize == 0) {
3934 *script_status = NULL;
3936 *script_status = (struct ctdb_scripts_wire *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
3937 talloc_free(outdata.dptr);
3944 tell the main daemon how long it took to lock the reclock file
3946 int ctdb_ctrl_report_recd_lock_latency(struct ctdb_context *ctdb, struct timeval timeout, double latency)
3952 data.dptr = (uint8_t *)&latency;
3953 data.dsize = sizeof(latency);
3955 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_RECD_RECLOCK_LATENCY, 0, data,
3956 ctdb, NULL, &res, NULL, NULL);
3957 if (ret != 0 || res != 0) {
3958 DEBUG(DEBUG_ERR,("Failed to send recd reclock latency\n"));
3966 get the name of the reclock file
3968 int ctdb_ctrl_getreclock(struct ctdb_context *ctdb, struct timeval timeout,
3969 uint32_t destnode, TALLOC_CTX *mem_ctx,
3976 ret = ctdb_control(ctdb, destnode, 0,
3977 CTDB_CONTROL_GET_RECLOCK_FILE, 0, tdb_null,
3978 mem_ctx, &data, &res, &timeout, NULL);
3979 if (ret != 0 || res != 0) {
3983 if (data.dsize == 0) {
3986 *name = talloc_strdup(mem_ctx, discard_const(data.dptr));
3988 talloc_free(data.dptr);
3994 set the reclock filename for a node
3996 int ctdb_ctrl_setreclock(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, const char *reclock)
4002 if (reclock == NULL) {
4006 data.dsize = strlen(reclock) + 1;
4007 data.dptr = discard_const(reclock);
4010 ret = ctdb_control(ctdb, destnode, 0,
4011 CTDB_CONTROL_SET_RECLOCK_FILE, 0, data,
4012 NULL, NULL, &res, &timeout, NULL);
4013 if (ret != 0 || res != 0) {
4014 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setreclock failed\n"));
4024 int ctdb_ctrl_stop_node(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
4029 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_STOP_NODE, 0, tdb_null,
4030 ctdb, NULL, &res, &timeout, NULL);
4031 if (ret != 0 || res != 0) {
4032 DEBUG(DEBUG_ERR,("Failed to stop node\n"));
4042 int ctdb_ctrl_continue_node(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
4046 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_CONTINUE_NODE, 0, tdb_null,
4047 ctdb, NULL, NULL, &timeout, NULL);
4049 DEBUG(DEBUG_ERR,("Failed to continue node\n"));
4057 set the natgw state for a node
4059 int ctdb_ctrl_setnatgwstate(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t natgwstate)
4065 data.dsize = sizeof(natgwstate);
4066 data.dptr = (uint8_t *)&natgwstate;
4068 ret = ctdb_control(ctdb, destnode, 0,
4069 CTDB_CONTROL_SET_NATGWSTATE, 0, data,
4070 NULL, NULL, &res, &timeout, NULL);
4071 if (ret != 0 || res != 0) {
4072 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setnatgwstate failed\n"));
4080 set the lmaster role for a node
4082 int ctdb_ctrl_setlmasterrole(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t lmasterrole)
4088 data.dsize = sizeof(lmasterrole);
4089 data.dptr = (uint8_t *)&lmasterrole;
4091 ret = ctdb_control(ctdb, destnode, 0,
4092 CTDB_CONTROL_SET_LMASTERROLE, 0, data,
4093 NULL, NULL, &res, &timeout, NULL);
4094 if (ret != 0 || res != 0) {
4095 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setlmasterrole failed\n"));
4103 set the recmaster role for a node
4105 int ctdb_ctrl_setrecmasterrole(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmasterrole)
4111 data.dsize = sizeof(recmasterrole);
4112 data.dptr = (uint8_t *)&recmasterrole;
4114 ret = ctdb_control(ctdb, destnode, 0,
4115 CTDB_CONTROL_SET_RECMASTERROLE, 0, data,
4116 NULL, NULL, &res, &timeout, NULL);
4117 if (ret != 0 || res != 0) {
4118 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setrecmasterrole failed\n"));
4125 /* enable an eventscript
4127 int ctdb_ctrl_enablescript(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, const char *script)
4133 data.dsize = strlen(script) + 1;
4134 data.dptr = discard_const(script);
4136 ret = ctdb_control(ctdb, destnode, 0,
4137 CTDB_CONTROL_ENABLE_SCRIPT, 0, data,
4138 NULL, NULL, &res, &timeout, NULL);
4139 if (ret != 0 || res != 0) {
4140 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for enablescript failed\n"));
4147 /* disable an eventscript
4149 int ctdb_ctrl_disablescript(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, const char *script)
4155 data.dsize = strlen(script) + 1;
4156 data.dptr = discard_const(script);
4158 ret = ctdb_control(ctdb, destnode, 0,
4159 CTDB_CONTROL_DISABLE_SCRIPT, 0, data,
4160 NULL, NULL, &res, &timeout, NULL);
4161 if (ret != 0 || res != 0) {
4162 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for disablescript failed\n"));
4170 int ctdb_ctrl_set_ban(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, struct ctdb_ban_time *bantime)
4176 data.dsize = sizeof(*bantime);
4177 data.dptr = (uint8_t *)bantime;
4179 ret = ctdb_control(ctdb, destnode, 0,
4180 CTDB_CONTROL_SET_BAN_STATE, 0, data,
4181 NULL, NULL, &res, &timeout, NULL);
4182 if (ret != 0 || res != 0) {
4183 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set ban state failed\n"));
4191 int ctdb_ctrl_get_ban(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_ban_time **bantime)
4196 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
4198 ret = ctdb_control(ctdb, destnode, 0,
4199 CTDB_CONTROL_GET_BAN_STATE, 0, tdb_null,
4200 tmp_ctx, &outdata, &res, &timeout, NULL);
4201 if (ret != 0 || res != 0) {
4202 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set ban state failed\n"));
4203 talloc_free(tmp_ctx);
4207 *bantime = (struct ctdb_ban_time *)talloc_steal(mem_ctx, outdata.dptr);
4208 talloc_free(tmp_ctx);
4214 int ctdb_ctrl_set_db_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, struct ctdb_db_priority *db_prio)
4219 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
4221 data.dptr = (uint8_t*)db_prio;
4222 data.dsize = sizeof(*db_prio);
4224 ret = ctdb_control(ctdb, destnode, 0,
4225 CTDB_CONTROL_SET_DB_PRIORITY, 0, data,
4226 tmp_ctx, NULL, &res, &timeout, NULL);
4227 if (ret != 0 || res != 0) {
4228 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set_db_priority failed\n"));
4229 talloc_free(tmp_ctx);
4233 talloc_free(tmp_ctx);
4238 int ctdb_ctrl_get_db_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t db_id, uint32_t *priority)
4243 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
4245 data.dptr = (uint8_t*)&db_id;
4246 data.dsize = sizeof(db_id);
4248 ret = ctdb_control(ctdb, destnode, 0,
4249 CTDB_CONTROL_GET_DB_PRIORITY, 0, data,
4250 tmp_ctx, NULL, &res, &timeout, NULL);
4251 if (ret != 0 || res < 0) {
4252 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set_db_priority failed\n"));
4253 talloc_free(tmp_ctx);
4261 talloc_free(tmp_ctx);
4266 int ctdb_ctrl_getstathistory(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_statistics_wire **stats)
4272 ret = ctdb_control(ctdb, destnode, 0,
4273 CTDB_CONTROL_GET_STAT_HISTORY, 0, tdb_null,
4274 mem_ctx, &outdata, &res, &timeout, NULL);
4275 if (ret != 0 || res != 0 || outdata.dsize == 0) {
4276 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getstathistory failed ret:%d res:%d\n", ret, res));
4280 *stats = (struct ctdb_statistics_wire *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
4281 talloc_free(outdata.dptr);
4286 struct ctdb_ltdb_header *ctdb_header_from_record_handle(struct ctdb_record_handle *h)
4296 struct ctdb_client_control_state *
4297 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)
4299 struct ctdb_client_control_state *handle;
4300 struct ctdb_marshall_buffer *m;
4301 struct ctdb_rec_data *rec;
4304 m = talloc_zero(mem_ctx, struct ctdb_marshall_buffer);
4306 DEBUG(DEBUG_ERR, ("Failed to allocate marshall buffer for update record\n"));
4310 m->db_id = ctdb_db->db_id;
4312 rec = ctdb_marshall_record(m, 0, key, header, data);
4314 DEBUG(DEBUG_ERR,("Failed to marshall record for update record\n"));
4318 m = talloc_realloc_size(mem_ctx, m, rec->length + offsetof(struct ctdb_marshall_buffer, data));
4320 DEBUG(DEBUG_CRIT,(__location__ " Failed to expand recdata\n"));
4325 memcpy((uint8_t *)m + offsetof(struct ctdb_marshall_buffer, data), rec, rec->length);
4328 outdata.dptr = (uint8_t *)m;
4329 outdata.dsize = talloc_get_size(m);
4331 handle = ctdb_control_send(ctdb, destnode, 0,
4332 CTDB_CONTROL_UPDATE_RECORD, 0, outdata,
4333 mem_ctx, &timeout, NULL);
4338 int ctdb_ctrl_updaterecord_recv(struct ctdb_context *ctdb, struct ctdb_client_control_state *state)
4343 ret = ctdb_control_recv(ctdb, state, state, NULL, &res, NULL);
4344 if ( (ret != 0) || (res != 0) ){
4345 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_update_record_recv failed\n"));
4353 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)
4355 struct ctdb_client_control_state *state;
4357 state = ctdb_ctrl_updaterecord_send(ctdb, mem_ctx, timeout, destnode, ctdb_db, key, header, data);
4358 return ctdb_ctrl_updaterecord_recv(ctdb, state);