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 "system/network.h"
26 #include "system/filesys.h"
27 #include "system/locale.h"
29 #include "../include/ctdb_private.h"
30 #include "lib/util/dlinklist.h"
35 allocate a packet for use in client<->daemon communication
37 struct ctdb_req_header *_ctdbd_allocate_pkt(struct ctdb_context *ctdb,
39 enum ctdb_operation operation,
40 size_t length, size_t slength,
44 struct ctdb_req_header *hdr;
46 length = MAX(length, slength);
47 size = (length+(CTDB_DS_ALIGNMENT-1)) & ~(CTDB_DS_ALIGNMENT-1);
49 hdr = (struct ctdb_req_header *)talloc_zero_size(mem_ctx, size);
51 DEBUG(DEBUG_ERR,("Unable to allocate packet for operation %u of length %u\n",
52 operation, (unsigned)length));
55 talloc_set_name_const(hdr, type);
57 hdr->operation = operation;
58 hdr->ctdb_magic = CTDB_MAGIC;
59 hdr->ctdb_version = CTDB_VERSION;
60 hdr->srcnode = ctdb->pnn;
62 hdr->generation = ctdb->vnn_map->generation;
69 local version of ctdb_call
71 int ctdb_call_local(struct ctdb_db_context *ctdb_db, struct ctdb_call *call,
72 struct ctdb_ltdb_header *header, TALLOC_CTX *mem_ctx,
73 TDB_DATA *data, bool updatetdb, uint32_t caller)
75 struct ctdb_call_info *c;
76 struct ctdb_registered_call *fn;
77 struct ctdb_context *ctdb = ctdb_db->ctdb;
79 c = talloc(ctdb, struct ctdb_call_info);
80 CTDB_NO_MEMORY(ctdb, c);
83 c->call_data = &call->call_data;
84 c->record_data.dptr = talloc_memdup(c, data->dptr, data->dsize);
85 c->record_data.dsize = data->dsize;
86 CTDB_NO_MEMORY(ctdb, c->record_data.dptr);
92 for (fn=ctdb_db->calls;fn;fn=fn->next) {
93 if (fn->id == call->call_id) break;
96 ctdb_set_error(ctdb, "Unknown call id %u\n", call->call_id);
101 if (fn->fn(c) != 0) {
102 ctdb_set_error(ctdb, "ctdb_call %u failed\n", call->call_id);
107 /* we need to force the record to be written out if this was a remote access */
108 if (header->laccessor != caller) {
111 header->laccessor = caller;
114 /* we need to force the record to be written out if this was a remote access,
115 so that the lacount is updated */
116 if (c->new_data == NULL && header->laccessor != ctdb->pnn) {
117 c->new_data = &c->record_data;
120 if (c->new_data && updatetdb) {
121 /* XXX check that we always have the lock here? */
122 if (ctdb_ltdb_store(ctdb_db, call->key, header, *c->new_data) != 0) {
123 ctdb_set_error(ctdb, "ctdb_call tdb_store failed\n");
130 call->reply_data = *c->reply_data;
132 talloc_steal(call, call->reply_data.dptr);
133 talloc_set_name_const(call->reply_data.dptr, __location__);
135 call->reply_data.dptr = NULL;
136 call->reply_data.dsize = 0;
138 call->status = c->status;
147 queue a packet for sending from client to daemon
149 static int ctdb_client_queue_pkt(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
151 return ctdb_queue_send(ctdb->daemon.queue, (uint8_t *)hdr, hdr->length);
156 called when a CTDB_REPLY_CALL packet comes in in the client
158 This packet comes in response to a CTDB_REQ_CALL request packet. It
159 contains any reply data from the call
161 static void ctdb_client_reply_call(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
163 struct ctdb_reply_call *c = (struct ctdb_reply_call *)hdr;
164 struct ctdb_client_call_state *state;
166 state = ctdb_reqid_find(ctdb, hdr->reqid, struct ctdb_client_call_state);
168 DEBUG(DEBUG_ERR,(__location__ " reqid %u not found\n", hdr->reqid));
172 if (hdr->reqid != state->reqid) {
173 /* we found a record but it was the wrong one */
174 DEBUG(DEBUG_ERR, ("Dropped client call reply with reqid:%u\n",hdr->reqid));
178 state->call->reply_data.dptr = c->data;
179 state->call->reply_data.dsize = c->datalen;
180 state->call->status = c->status;
182 talloc_steal(state, c);
184 state->state = CTDB_CALL_DONE;
186 if (state->async.fn) {
187 state->async.fn(state);
191 static void ctdb_client_reply_control(struct ctdb_context *ctdb, struct ctdb_req_header *hdr);
194 this is called in the client, when data comes in from the daemon
196 void ctdb_client_read_cb(uint8_t *data, size_t cnt, void *args)
198 struct ctdb_context *ctdb = talloc_get_type(args, struct ctdb_context);
199 struct ctdb_req_header *hdr = (struct ctdb_req_header *)data;
202 /* place the packet as a child of a tmp_ctx. We then use
203 talloc_free() below to free it. If any of the calls want
204 to keep it, then they will steal it somewhere else, and the
205 talloc_free() will be a no-op */
206 tmp_ctx = talloc_new(ctdb);
207 talloc_steal(tmp_ctx, hdr);
210 DEBUG(DEBUG_INFO,("Daemon has exited - shutting down client\n"));
214 if (cnt < sizeof(*hdr)) {
215 DEBUG(DEBUG_CRIT,("Bad packet length %u in client\n", (unsigned)cnt));
218 if (cnt != hdr->length) {
219 ctdb_set_error(ctdb, "Bad header length %u expected %u in client\n",
220 (unsigned)hdr->length, (unsigned)cnt);
224 if (hdr->ctdb_magic != CTDB_MAGIC) {
225 ctdb_set_error(ctdb, "Non CTDB packet rejected in client\n");
229 if (hdr->ctdb_version != CTDB_VERSION) {
230 ctdb_set_error(ctdb, "Bad CTDB version 0x%x rejected in client\n", hdr->ctdb_version);
234 switch (hdr->operation) {
235 case CTDB_REPLY_CALL:
236 ctdb_client_reply_call(ctdb, hdr);
239 case CTDB_REQ_MESSAGE:
240 ctdb_request_message(ctdb, hdr);
243 case CTDB_REPLY_CONTROL:
244 ctdb_client_reply_control(ctdb, hdr);
248 DEBUG(DEBUG_CRIT,("bogus operation code:%u\n",hdr->operation));
252 talloc_free(tmp_ctx);
256 connect to a unix domain socket
258 int ctdb_socket_connect(struct ctdb_context *ctdb)
260 struct sockaddr_un addr;
262 memset(&addr, 0, sizeof(addr));
263 addr.sun_family = AF_UNIX;
264 strncpy(addr.sun_path, ctdb->daemon.name, sizeof(addr.sun_path));
266 ctdb->daemon.sd = socket(AF_UNIX, SOCK_STREAM, 0);
267 if (ctdb->daemon.sd == -1) {
268 DEBUG(DEBUG_ERR,(__location__ " Failed to open client socket. Errno:%s(%d)\n", strerror(errno), errno));
272 if (connect(ctdb->daemon.sd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
273 close(ctdb->daemon.sd);
274 ctdb->daemon.sd = -1;
275 DEBUG(DEBUG_ERR,(__location__ " Failed to connect client socket to daemon. Errno:%s(%d)\n", strerror(errno), errno));
279 set_nonblocking(ctdb->daemon.sd);
280 set_close_on_exec(ctdb->daemon.sd);
282 ctdb->daemon.queue = ctdb_queue_setup(ctdb, ctdb, ctdb->daemon.sd,
284 ctdb_client_read_cb, ctdb, "to-ctdbd");
289 struct ctdb_record_handle {
290 struct ctdb_db_context *ctdb_db;
293 struct ctdb_ltdb_header header;
298 make a recv call to the local ctdb daemon - called from client context
300 This is called when the program wants to wait for a ctdb_call to complete and get the
301 results. This call will block unless the call has already completed.
303 int ctdb_call_recv(struct ctdb_client_call_state *state, struct ctdb_call *call)
309 while (state->state < CTDB_CALL_DONE) {
310 event_loop_once(state->ctdb_db->ctdb->ev);
312 if (state->state != CTDB_CALL_DONE) {
313 DEBUG(DEBUG_ERR,(__location__ " ctdb_call_recv failed\n"));
318 if (state->call->reply_data.dsize) {
319 call->reply_data.dptr = talloc_memdup(state->ctdb_db,
320 state->call->reply_data.dptr,
321 state->call->reply_data.dsize);
322 call->reply_data.dsize = state->call->reply_data.dsize;
324 call->reply_data.dptr = NULL;
325 call->reply_data.dsize = 0;
327 call->status = state->call->status;
337 destroy a ctdb_call in client
339 static int ctdb_client_call_destructor(struct ctdb_client_call_state *state)
341 ctdb_reqid_remove(state->ctdb_db->ctdb, state->reqid);
346 construct an event driven local ctdb_call
348 this is used so that locally processed ctdb_call requests are processed
349 in an event driven manner
351 static struct ctdb_client_call_state *ctdb_client_call_local_send(struct ctdb_db_context *ctdb_db,
352 struct ctdb_call *call,
353 struct ctdb_ltdb_header *header,
356 struct ctdb_client_call_state *state;
357 struct ctdb_context *ctdb = ctdb_db->ctdb;
360 state = talloc_zero(ctdb_db, struct ctdb_client_call_state);
361 CTDB_NO_MEMORY_NULL(ctdb, state);
362 state->call = talloc_zero(state, struct ctdb_call);
363 CTDB_NO_MEMORY_NULL(ctdb, state->call);
365 talloc_steal(state, data->dptr);
367 state->state = CTDB_CALL_DONE;
368 *(state->call) = *call;
369 state->ctdb_db = ctdb_db;
371 ret = ctdb_call_local(ctdb_db, state->call, header, state, data, true, ctdb->pnn);
373 DEBUG(DEBUG_DEBUG,("ctdb_call_local() failed, ignoring return code %d\n", ret));
380 make a ctdb call to the local daemon - async send. Called from client context.
382 This constructs a ctdb_call request and queues it for processing.
383 This call never blocks.
385 struct ctdb_client_call_state *ctdb_call_send(struct ctdb_db_context *ctdb_db,
386 struct ctdb_call *call)
388 struct ctdb_client_call_state *state;
389 struct ctdb_context *ctdb = ctdb_db->ctdb;
390 struct ctdb_ltdb_header header;
394 struct ctdb_req_call *c;
396 /* if the domain socket is not yet open, open it */
397 if (ctdb->daemon.sd==-1) {
398 ctdb_socket_connect(ctdb);
401 ret = ctdb_ltdb_lock(ctdb_db, call->key);
403 DEBUG(DEBUG_ERR,(__location__ " Failed to get chainlock\n"));
407 ret = ctdb_ltdb_fetch(ctdb_db, call->key, &header, ctdb_db, &data);
409 if ((call->flags & CTDB_IMMEDIATE_MIGRATION) && (header.flags & CTDB_REC_RO_HAVE_DELEGATIONS)) {
413 if (ret == 0 && header.dmaster == ctdb->pnn) {
414 state = ctdb_client_call_local_send(ctdb_db, call, &header, &data);
415 talloc_free(data.dptr);
416 ctdb_ltdb_unlock(ctdb_db, call->key);
420 ctdb_ltdb_unlock(ctdb_db, call->key);
421 talloc_free(data.dptr);
423 state = talloc_zero(ctdb_db, struct ctdb_client_call_state);
425 DEBUG(DEBUG_ERR, (__location__ " failed to allocate state\n"));
428 state->call = talloc_zero(state, struct ctdb_call);
429 if (state->call == NULL) {
430 DEBUG(DEBUG_ERR, (__location__ " failed to allocate state->call\n"));
434 len = offsetof(struct ctdb_req_call, data) + call->key.dsize + call->call_data.dsize;
435 c = ctdbd_allocate_pkt(ctdb, state, CTDB_REQ_CALL, len, struct ctdb_req_call);
437 DEBUG(DEBUG_ERR, (__location__ " failed to allocate packet\n"));
441 state->reqid = ctdb_reqid_new(ctdb, state);
442 state->ctdb_db = ctdb_db;
443 talloc_set_destructor(state, ctdb_client_call_destructor);
445 c->hdr.reqid = state->reqid;
446 c->flags = call->flags;
447 c->db_id = ctdb_db->db_id;
448 c->callid = call->call_id;
450 c->keylen = call->key.dsize;
451 c->calldatalen = call->call_data.dsize;
452 memcpy(&c->data[0], call->key.dptr, call->key.dsize);
453 memcpy(&c->data[call->key.dsize],
454 call->call_data.dptr, call->call_data.dsize);
455 *(state->call) = *call;
456 state->call->call_data.dptr = &c->data[call->key.dsize];
457 state->call->key.dptr = &c->data[0];
459 state->state = CTDB_CALL_WAIT;
462 ctdb_client_queue_pkt(ctdb, &c->hdr);
469 full ctdb_call. Equivalent to a ctdb_call_send() followed by a ctdb_call_recv()
471 int ctdb_call(struct ctdb_db_context *ctdb_db, struct ctdb_call *call)
473 struct ctdb_client_call_state *state;
475 state = ctdb_call_send(ctdb_db, call);
476 return ctdb_call_recv(state, call);
481 tell the daemon what messaging srvid we will use, and register the message
482 handler function in the client
484 int ctdb_client_set_message_handler(struct ctdb_context *ctdb, uint64_t srvid,
485 ctdb_msg_fn_t handler,
492 res = ctdb_control(ctdb, CTDB_CURRENT_NODE, srvid, CTDB_CONTROL_REGISTER_SRVID, 0,
493 tdb_null, NULL, NULL, &status, NULL, NULL);
494 if (res != 0 || status != 0) {
495 DEBUG(DEBUG_ERR,("Failed to register srvid %llu\n", (unsigned long long)srvid));
499 /* also need to register the handler with our own ctdb structure */
500 return ctdb_register_message_handler(ctdb, ctdb, srvid, handler, private_data);
504 tell the daemon we no longer want a srvid
506 int ctdb_client_remove_message_handler(struct ctdb_context *ctdb, uint64_t srvid, void *private_data)
511 res = ctdb_control(ctdb, CTDB_CURRENT_NODE, srvid, CTDB_CONTROL_DEREGISTER_SRVID, 0,
512 tdb_null, NULL, NULL, &status, NULL, NULL);
513 if (res != 0 || status != 0) {
514 DEBUG(DEBUG_ERR,("Failed to deregister srvid %llu\n", (unsigned long long)srvid));
518 /* also need to register the handler with our own ctdb structure */
519 ctdb_deregister_message_handler(ctdb, srvid, private_data);
525 send a message - from client context
527 int ctdb_client_send_message(struct ctdb_context *ctdb, uint32_t pnn,
528 uint64_t srvid, TDB_DATA data)
530 struct ctdb_req_message *r;
533 len = offsetof(struct ctdb_req_message, data) + data.dsize;
534 r = ctdbd_allocate_pkt(ctdb, ctdb, CTDB_REQ_MESSAGE,
535 len, struct ctdb_req_message);
536 CTDB_NO_MEMORY(ctdb, r);
538 r->hdr.destnode = pnn;
540 r->datalen = data.dsize;
541 memcpy(&r->data[0], data.dptr, data.dsize);
543 res = ctdb_client_queue_pkt(ctdb, &r->hdr);
554 cancel a ctdb_fetch_lock operation, releasing the lock
556 static int fetch_lock_destructor(struct ctdb_record_handle *h)
558 ctdb_ltdb_unlock(h->ctdb_db, h->key);
563 force the migration of a record to this node
565 static int ctdb_client_force_migration(struct ctdb_db_context *ctdb_db, TDB_DATA key)
567 struct ctdb_call call;
569 call.call_id = CTDB_NULL_FUNC;
571 call.flags = CTDB_IMMEDIATE_MIGRATION;
572 return ctdb_call(ctdb_db, &call);
576 try to fetch a readonly copy of a record
579 ctdb_client_fetch_readonly(struct ctdb_db_context *ctdb_db, TDB_DATA key, TALLOC_CTX *mem_ctx, struct ctdb_ltdb_header **hdr, TDB_DATA *data)
583 struct ctdb_call call;
586 call.call_id = CTDB_FETCH_WITH_HEADER_FUNC;
587 call.call_data.dptr = NULL;
588 call.call_data.dsize = 0;
590 call.flags = CTDB_WANT_READONLY;
591 ret = ctdb_call(ctdb_db, &call);
596 if (call.reply_data.dsize < sizeof(struct ctdb_ltdb_header)) {
600 *hdr = talloc_memdup(mem_ctx, &call.reply_data.dptr[0], sizeof(struct ctdb_ltdb_header));
602 talloc_free(call.reply_data.dptr);
606 data->dsize = call.reply_data.dsize - sizeof(struct ctdb_ltdb_header);
607 data->dptr = talloc_memdup(mem_ctx, &call.reply_data.dptr[sizeof(struct ctdb_ltdb_header)], data->dsize);
608 if (data->dptr == NULL) {
609 talloc_free(call.reply_data.dptr);
618 get a lock on a record, and return the records data. Blocks until it gets the lock
620 struct ctdb_record_handle *ctdb_fetch_lock(struct ctdb_db_context *ctdb_db, TALLOC_CTX *mem_ctx,
621 TDB_DATA key, TDB_DATA *data)
624 struct ctdb_record_handle *h;
627 procedure is as follows:
629 1) get the chain lock.
630 2) check if we are dmaster
631 3) if we are the dmaster then return handle
632 4) if not dmaster then ask ctdb daemon to make us dmaster, and wait for
634 5) when we get the reply, goto (1)
637 h = talloc_zero(mem_ctx, struct ctdb_record_handle);
642 h->ctdb_db = ctdb_db;
644 h->key.dptr = talloc_memdup(h, key.dptr, key.dsize);
645 if (h->key.dptr == NULL) {
651 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: key=%*.*s\n", (int)key.dsize, (int)key.dsize,
652 (const char *)key.dptr));
655 /* step 1 - get the chain lock */
656 ret = ctdb_ltdb_lock(ctdb_db, key);
658 DEBUG(DEBUG_ERR, (__location__ " failed to lock ltdb record\n"));
663 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: got chain lock\n"));
665 talloc_set_destructor(h, fetch_lock_destructor);
667 ret = ctdb_ltdb_fetch(ctdb_db, key, &h->header, h, data);
669 /* when torturing, ensure we test the remote path */
670 if ((ctdb_db->ctdb->flags & CTDB_FLAG_TORTURE) &&
672 h->header.dmaster = (uint32_t)-1;
676 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: done local fetch\n"));
678 if (ret != 0 || h->header.dmaster != ctdb_db->ctdb->pnn) {
679 ctdb_ltdb_unlock(ctdb_db, key);
680 ret = ctdb_client_force_migration(ctdb_db, key);
682 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: force_migration failed\n"));
689 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: we are dmaster - done\n"));
694 get a readonly lock on a record, and return the records data. Blocks until it gets the lock
696 struct ctdb_record_handle *
697 ctdb_fetch_readonly_lock(
698 struct ctdb_db_context *ctdb_db, TALLOC_CTX *mem_ctx,
699 TDB_DATA key, TDB_DATA *data,
703 struct ctdb_record_handle *h;
704 struct ctdb_ltdb_header *roheader = NULL;
706 h = talloc_zero(mem_ctx, struct ctdb_record_handle);
711 h->ctdb_db = ctdb_db;
713 h->key.dptr = talloc_memdup(h, key.dptr, key.dsize);
714 if (h->key.dptr == NULL) {
725 talloc_free(roheader);
728 talloc_free(data->dptr);
732 /* Lock the record/chain */
733 ret = ctdb_ltdb_lock(ctdb_db, key);
735 DEBUG(DEBUG_ERR, (__location__ " failed to lock ltdb record\n"));
740 talloc_set_destructor(h, fetch_lock_destructor);
742 /* Check if record exists yet in the TDB */
743 ret = ctdb_ltdb_fetch_with_header(ctdb_db, key, &h->header, h, data);
745 ctdb_ltdb_unlock(ctdb_db, key);
746 ret = ctdb_client_force_migration(ctdb_db, key);
748 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
755 /* if this is a request for read/write and we have delegations
756 we have to revoke all delegations first
759 && (h->header.dmaster == ctdb_db->ctdb->pnn)
760 && (h->header.flags & CTDB_REC_RO_HAVE_DELEGATIONS)) {
761 ctdb_ltdb_unlock(ctdb_db, key);
762 ret = ctdb_client_force_migration(ctdb_db, key);
764 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
771 /* if we are dmaster, just return the handle */
772 if (h->header.dmaster == ctdb_db->ctdb->pnn) {
776 if (read_only != 0) {
777 TDB_DATA rodata = {NULL, 0};
779 if ((h->header.flags & CTDB_REC_RO_HAVE_READONLY)
780 || (h->header.flags & CTDB_REC_RO_HAVE_DELEGATIONS)) {
784 ctdb_ltdb_unlock(ctdb_db, key);
785 ret = ctdb_client_fetch_readonly(ctdb_db, key, h, &roheader, &rodata);
787 DEBUG(DEBUG_ERR,("ctdb_fetch_readonly_lock: failed. force migration and try again\n"));
788 ret = ctdb_client_force_migration(ctdb_db, key);
790 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
798 if (!(roheader->flags&CTDB_REC_RO_HAVE_READONLY)) {
799 ret = ctdb_client_force_migration(ctdb_db, key);
801 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
809 ret = ctdb_ltdb_lock(ctdb_db, key);
811 DEBUG(DEBUG_ERR, (__location__ " failed to lock ltdb record\n"));
816 ret = ctdb_ltdb_fetch_with_header(ctdb_db, key, &h->header, h, data);
818 ctdb_ltdb_unlock(ctdb_db, key);
820 ret = ctdb_client_force_migration(ctdb_db, key);
822 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
833 /* we are not dmaster and this was not a request for a readonly lock
834 * so unlock the record, migrate it and try again
836 ctdb_ltdb_unlock(ctdb_db, key);
837 ret = ctdb_client_force_migration(ctdb_db, key);
839 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: force_migration failed\n"));
847 store some data to the record that was locked with ctdb_fetch_lock()
849 int ctdb_record_store(struct ctdb_record_handle *h, TDB_DATA data)
851 if (h->ctdb_db->persistent) {
852 DEBUG(DEBUG_ERR, (__location__ " ctdb_record_store prohibited for persistent dbs\n"));
856 return ctdb_ltdb_store(h->ctdb_db, h->key, &h->header, data);
860 non-locking fetch of a record
862 int ctdb_fetch(struct ctdb_db_context *ctdb_db, TALLOC_CTX *mem_ctx,
863 TDB_DATA key, TDB_DATA *data)
865 struct ctdb_call call;
868 call.call_id = CTDB_FETCH_FUNC;
869 call.call_data.dptr = NULL;
870 call.call_data.dsize = 0;
873 ret = ctdb_call(ctdb_db, &call);
876 *data = call.reply_data;
877 talloc_steal(mem_ctx, data->dptr);
886 called when a control completes or timesout to invoke the callback
887 function the user provided
889 static void invoke_control_callback(struct event_context *ev, struct timed_event *te,
890 struct timeval t, void *private_data)
892 struct ctdb_client_control_state *state;
893 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
896 state = talloc_get_type(private_data, struct ctdb_client_control_state);
897 talloc_steal(tmp_ctx, state);
899 ret = ctdb_control_recv(state->ctdb, state, state,
904 DEBUG(DEBUG_DEBUG,("ctdb_control_recv() failed, ignoring return code %d\n", ret));
907 talloc_free(tmp_ctx);
911 called when a CTDB_REPLY_CONTROL packet comes in in the client
913 This packet comes in response to a CTDB_REQ_CONTROL request packet. It
914 contains any reply data from the control
916 static void ctdb_client_reply_control(struct ctdb_context *ctdb,
917 struct ctdb_req_header *hdr)
919 struct ctdb_reply_control *c = (struct ctdb_reply_control *)hdr;
920 struct ctdb_client_control_state *state;
922 state = ctdb_reqid_find(ctdb, hdr->reqid, struct ctdb_client_control_state);
924 DEBUG(DEBUG_ERR,(__location__ " reqid %u not found\n", hdr->reqid));
928 if (hdr->reqid != state->reqid) {
929 /* we found a record but it was the wrong one */
930 DEBUG(DEBUG_ERR, ("Dropped orphaned reply control with reqid:%u\n",hdr->reqid));
934 state->outdata.dptr = c->data;
935 state->outdata.dsize = c->datalen;
936 state->status = c->status;
938 state->errormsg = talloc_strndup(state,
939 (char *)&c->data[c->datalen],
943 /* state->outdata now uses resources from c so we dont want c
944 to just dissappear from under us while state is still alive
946 talloc_steal(state, c);
948 state->state = CTDB_CONTROL_DONE;
950 /* if we had a callback registered for this control, pull the response
951 and call the callback.
953 if (state->async.fn) {
954 event_add_timed(ctdb->ev, state, timeval_zero(), invoke_control_callback, state);
960 destroy a ctdb_control in client
962 static int ctdb_client_control_destructor(struct ctdb_client_control_state *state)
964 ctdb_reqid_remove(state->ctdb, state->reqid);
969 /* time out handler for ctdb_control */
970 static void control_timeout_func(struct event_context *ev, struct timed_event *te,
971 struct timeval t, void *private_data)
973 struct ctdb_client_control_state *state = talloc_get_type(private_data, struct ctdb_client_control_state);
975 DEBUG(DEBUG_ERR,(__location__ " control timed out. reqid:%u opcode:%u "
976 "dstnode:%u\n", state->reqid, state->c->opcode,
977 state->c->hdr.destnode));
979 state->state = CTDB_CONTROL_TIMEOUT;
981 /* if we had a callback registered for this control, pull the response
982 and call the callback.
984 if (state->async.fn) {
985 event_add_timed(state->ctdb->ev, state, timeval_zero(), invoke_control_callback, state);
989 /* async version of send control request */
990 struct ctdb_client_control_state *ctdb_control_send(struct ctdb_context *ctdb,
991 uint32_t destnode, uint64_t srvid,
992 uint32_t opcode, uint32_t flags, TDB_DATA data,
994 struct timeval *timeout,
997 struct ctdb_client_control_state *state;
999 struct ctdb_req_control *c;
1006 /* if the domain socket is not yet open, open it */
1007 if (ctdb->daemon.sd==-1) {
1008 ctdb_socket_connect(ctdb);
1011 state = talloc_zero(mem_ctx, struct ctdb_client_control_state);
1012 CTDB_NO_MEMORY_NULL(ctdb, state);
1015 state->reqid = ctdb_reqid_new(ctdb, state);
1016 state->state = CTDB_CONTROL_WAIT;
1017 state->errormsg = NULL;
1019 talloc_set_destructor(state, ctdb_client_control_destructor);
1021 len = offsetof(struct ctdb_req_control, data) + data.dsize;
1022 c = ctdbd_allocate_pkt(ctdb, state, CTDB_REQ_CONTROL,
1023 len, struct ctdb_req_control);
1025 CTDB_NO_MEMORY_NULL(ctdb, c);
1026 c->hdr.reqid = state->reqid;
1027 c->hdr.destnode = destnode;
1032 c->datalen = data.dsize;
1034 memcpy(&c->data[0], data.dptr, data.dsize);
1038 if (timeout && !timeval_is_zero(timeout)) {
1039 event_add_timed(ctdb->ev, state, *timeout, control_timeout_func, state);
1042 ret = ctdb_client_queue_pkt(ctdb, &(c->hdr));
1048 if (flags & CTDB_CTRL_FLAG_NOREPLY) {
1057 /* async version of receive control reply */
1058 int ctdb_control_recv(struct ctdb_context *ctdb,
1059 struct ctdb_client_control_state *state,
1060 TALLOC_CTX *mem_ctx,
1061 TDB_DATA *outdata, int32_t *status, char **errormsg)
1063 TALLOC_CTX *tmp_ctx;
1065 if (status != NULL) {
1068 if (errormsg != NULL) {
1072 if (state == NULL) {
1076 /* prevent double free of state */
1077 tmp_ctx = talloc_new(ctdb);
1078 talloc_steal(tmp_ctx, state);
1080 /* loop one event at a time until we either timeout or the control
1083 while (state->state == CTDB_CONTROL_WAIT) {
1084 event_loop_once(ctdb->ev);
1087 if (state->state != CTDB_CONTROL_DONE) {
1088 DEBUG(DEBUG_ERR,(__location__ " ctdb_control_recv failed\n"));
1089 if (state->async.fn) {
1090 state->async.fn(state);
1092 talloc_free(tmp_ctx);
1096 if (state->errormsg) {
1097 DEBUG(DEBUG_ERR,("ctdb_control error: '%s'\n", state->errormsg));
1099 (*errormsg) = talloc_move(mem_ctx, &state->errormsg);
1101 if (state->async.fn) {
1102 state->async.fn(state);
1104 talloc_free(tmp_ctx);
1109 *outdata = state->outdata;
1110 outdata->dptr = talloc_memdup(mem_ctx, outdata->dptr, outdata->dsize);
1114 *status = state->status;
1117 if (state->async.fn) {
1118 state->async.fn(state);
1121 talloc_free(tmp_ctx);
1128 send a ctdb control message
1129 timeout specifies how long we should wait for a reply.
1130 if timeout is NULL we wait indefinitely
1132 int ctdb_control(struct ctdb_context *ctdb, uint32_t destnode, uint64_t srvid,
1133 uint32_t opcode, uint32_t flags, TDB_DATA data,
1134 TALLOC_CTX *mem_ctx, TDB_DATA *outdata, int32_t *status,
1135 struct timeval *timeout,
1138 struct ctdb_client_control_state *state;
1140 state = ctdb_control_send(ctdb, destnode, srvid, opcode,
1141 flags, data, mem_ctx,
1143 return ctdb_control_recv(ctdb, state, mem_ctx, outdata, status,
1151 a process exists call. Returns 0 if process exists, -1 otherwise
1153 int ctdb_ctrl_process_exists(struct ctdb_context *ctdb, uint32_t destnode, pid_t pid)
1159 data.dptr = (uint8_t*)&pid;
1160 data.dsize = sizeof(pid);
1162 ret = ctdb_control(ctdb, destnode, 0,
1163 CTDB_CONTROL_PROCESS_EXISTS, 0, data,
1164 NULL, NULL, &status, NULL, NULL);
1166 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for process_exists failed\n"));
1174 get remote statistics
1176 int ctdb_ctrl_statistics(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_statistics *status)
1182 ret = ctdb_control(ctdb, destnode, 0,
1183 CTDB_CONTROL_STATISTICS, 0, tdb_null,
1184 ctdb, &data, &res, NULL, NULL);
1185 if (ret != 0 || res != 0) {
1186 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for statistics failed\n"));
1190 if (data.dsize != sizeof(struct ctdb_statistics)) {
1191 DEBUG(DEBUG_ERR,(__location__ " Wrong statistics size %u - expected %u\n",
1192 (unsigned)data.dsize, (unsigned)sizeof(struct ctdb_statistics)));
1196 *status = *(struct ctdb_statistics *)data.dptr;
1197 talloc_free(data.dptr);
1203 shutdown a remote ctdb node
1205 int ctdb_ctrl_shutdown(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
1207 struct ctdb_client_control_state *state;
1209 state = ctdb_control_send(ctdb, destnode, 0,
1210 CTDB_CONTROL_SHUTDOWN, 0, tdb_null,
1211 NULL, &timeout, NULL);
1212 if (state == NULL) {
1213 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for shutdown failed\n"));
1221 get vnn map from a remote node
1223 int ctdb_ctrl_getvnnmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_vnn_map **vnnmap)
1228 struct ctdb_vnn_map_wire *map;
1230 ret = ctdb_control(ctdb, destnode, 0,
1231 CTDB_CONTROL_GETVNNMAP, 0, tdb_null,
1232 mem_ctx, &outdata, &res, &timeout, NULL);
1233 if (ret != 0 || res != 0) {
1234 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getvnnmap failed\n"));
1238 map = (struct ctdb_vnn_map_wire *)outdata.dptr;
1239 if (outdata.dsize < offsetof(struct ctdb_vnn_map_wire, map) ||
1240 outdata.dsize != map->size*sizeof(uint32_t) + offsetof(struct ctdb_vnn_map_wire, map)) {
1241 DEBUG(DEBUG_ERR,("Bad vnn map size received in ctdb_ctrl_getvnnmap\n"));
1245 (*vnnmap) = talloc(mem_ctx, struct ctdb_vnn_map);
1246 CTDB_NO_MEMORY(ctdb, *vnnmap);
1247 (*vnnmap)->generation = map->generation;
1248 (*vnnmap)->size = map->size;
1249 (*vnnmap)->map = talloc_array(*vnnmap, uint32_t, map->size);
1251 CTDB_NO_MEMORY(ctdb, (*vnnmap)->map);
1252 memcpy((*vnnmap)->map, map->map, sizeof(uint32_t)*map->size);
1253 talloc_free(outdata.dptr);
1260 get the recovery mode of a remote node
1262 struct ctdb_client_control_state *
1263 ctdb_ctrl_getrecmode_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode)
1265 return ctdb_control_send(ctdb, destnode, 0,
1266 CTDB_CONTROL_GET_RECMODE, 0, tdb_null,
1267 mem_ctx, &timeout, NULL);
1270 int ctdb_ctrl_getrecmode_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *recmode)
1275 ret = ctdb_control_recv(ctdb, state, mem_ctx, NULL, &res, NULL);
1277 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_getrecmode_recv failed\n"));
1282 *recmode = (uint32_t)res;
1288 int ctdb_ctrl_getrecmode(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, uint32_t *recmode)
1290 struct ctdb_client_control_state *state;
1292 state = ctdb_ctrl_getrecmode_send(ctdb, mem_ctx, timeout, destnode);
1293 return ctdb_ctrl_getrecmode_recv(ctdb, mem_ctx, state, recmode);
1300 set the recovery mode of a remote node
1302 int ctdb_ctrl_setrecmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmode)
1308 data.dsize = sizeof(uint32_t);
1309 data.dptr = (unsigned char *)&recmode;
1311 ret = ctdb_control(ctdb, destnode, 0,
1312 CTDB_CONTROL_SET_RECMODE, 0, data,
1313 NULL, NULL, &res, &timeout, NULL);
1314 if (ret != 0 || res != 0) {
1315 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setrecmode failed\n"));
1325 get the recovery master of a remote node
1327 struct ctdb_client_control_state *
1328 ctdb_ctrl_getrecmaster_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx,
1329 struct timeval timeout, uint32_t destnode)
1331 return ctdb_control_send(ctdb, destnode, 0,
1332 CTDB_CONTROL_GET_RECMASTER, 0, tdb_null,
1333 mem_ctx, &timeout, NULL);
1336 int ctdb_ctrl_getrecmaster_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *recmaster)
1341 ret = ctdb_control_recv(ctdb, state, mem_ctx, NULL, &res, NULL);
1343 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_getrecmaster_recv failed\n"));
1348 *recmaster = (uint32_t)res;
1354 int ctdb_ctrl_getrecmaster(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, uint32_t *recmaster)
1356 struct ctdb_client_control_state *state;
1358 state = ctdb_ctrl_getrecmaster_send(ctdb, mem_ctx, timeout, destnode);
1359 return ctdb_ctrl_getrecmaster_recv(ctdb, mem_ctx, state, recmaster);
1364 set the recovery master of a remote node
1366 int ctdb_ctrl_setrecmaster(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmaster)
1373 data.dsize = sizeof(uint32_t);
1374 data.dptr = (unsigned char *)&recmaster;
1376 ret = ctdb_control(ctdb, destnode, 0,
1377 CTDB_CONTROL_SET_RECMASTER, 0, data,
1378 NULL, NULL, &res, &timeout, NULL);
1379 if (ret != 0 || res != 0) {
1380 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setrecmaster failed\n"));
1389 get a list of databases off a remote node
1391 int ctdb_ctrl_getdbmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
1392 TALLOC_CTX *mem_ctx, struct ctdb_dbid_map **dbmap)
1398 ret = ctdb_control(ctdb, destnode, 0,
1399 CTDB_CONTROL_GET_DBMAP, 0, tdb_null,
1400 mem_ctx, &outdata, &res, &timeout, NULL);
1401 if (ret != 0 || res != 0) {
1402 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getdbmap failed ret:%d res:%d\n", ret, res));
1406 *dbmap = (struct ctdb_dbid_map *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
1407 talloc_free(outdata.dptr);
1413 get a list of nodes (vnn and flags ) from a remote node
1415 int ctdb_ctrl_getnodemap(struct ctdb_context *ctdb,
1416 struct timeval timeout, uint32_t destnode,
1417 TALLOC_CTX *mem_ctx, struct ctdb_node_map **nodemap)
1423 ret = ctdb_control(ctdb, destnode, 0,
1424 CTDB_CONTROL_GET_NODEMAP, 0, tdb_null,
1425 mem_ctx, &outdata, &res, &timeout, NULL);
1426 if (ret == 0 && res == -1 && outdata.dsize == 0) {
1427 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getnodes failed, falling back to ipv4-only control\n"));
1428 return ctdb_ctrl_getnodemapv4(ctdb, timeout, destnode, mem_ctx, nodemap);
1430 if (ret != 0 || res != 0 || outdata.dsize == 0) {
1431 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getnodes failed ret:%d res:%d\n", ret, res));
1435 *nodemap = (struct ctdb_node_map *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
1436 talloc_free(outdata.dptr);
1442 old style ipv4-only get a list of nodes (vnn and flags ) from a remote node
1444 int ctdb_ctrl_getnodemapv4(struct ctdb_context *ctdb,
1445 struct timeval timeout, uint32_t destnode,
1446 TALLOC_CTX *mem_ctx, struct ctdb_node_map **nodemap)
1450 struct ctdb_node_mapv4 *nodemapv4;
1453 ret = ctdb_control(ctdb, destnode, 0,
1454 CTDB_CONTROL_GET_NODEMAPv4, 0, tdb_null,
1455 mem_ctx, &outdata, &res, &timeout, NULL);
1456 if (ret != 0 || res != 0 || outdata.dsize == 0) {
1457 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getnodesv4 failed ret:%d res:%d\n", ret, res));
1461 nodemapv4 = (struct ctdb_node_mapv4 *)outdata.dptr;
1463 len = offsetof(struct ctdb_node_map, nodes) + nodemapv4->num*sizeof(struct ctdb_node_and_flags);
1464 (*nodemap) = talloc_zero_size(mem_ctx, len);
1465 CTDB_NO_MEMORY(ctdb, (*nodemap));
1467 (*nodemap)->num = nodemapv4->num;
1468 for (i=0; i<nodemapv4->num; i++) {
1469 (*nodemap)->nodes[i].pnn = nodemapv4->nodes[i].pnn;
1470 (*nodemap)->nodes[i].flags = nodemapv4->nodes[i].flags;
1471 (*nodemap)->nodes[i].addr.ip = nodemapv4->nodes[i].sin;
1472 (*nodemap)->nodes[i].addr.sa.sa_family = AF_INET;
1475 talloc_free(outdata.dptr);
1481 drop the transport, reload the nodes file and restart the transport
1483 int ctdb_ctrl_reload_nodes_file(struct ctdb_context *ctdb,
1484 struct timeval timeout, uint32_t destnode)
1489 ret = ctdb_control(ctdb, destnode, 0,
1490 CTDB_CONTROL_RELOAD_NODES_FILE, 0, tdb_null,
1491 NULL, NULL, &res, &timeout, NULL);
1492 if (ret != 0 || res != 0) {
1493 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for reloadnodesfile failed\n"));
1502 set vnn map on a node
1504 int ctdb_ctrl_setvnnmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
1505 TALLOC_CTX *mem_ctx, struct ctdb_vnn_map *vnnmap)
1510 struct ctdb_vnn_map_wire *map;
1513 len = offsetof(struct ctdb_vnn_map_wire, map) + sizeof(uint32_t)*vnnmap->size;
1514 map = talloc_size(mem_ctx, len);
1515 CTDB_NO_MEMORY(ctdb, map);
1517 map->generation = vnnmap->generation;
1518 map->size = vnnmap->size;
1519 memcpy(map->map, vnnmap->map, sizeof(uint32_t)*map->size);
1522 data.dptr = (uint8_t *)map;
1524 ret = ctdb_control(ctdb, destnode, 0,
1525 CTDB_CONTROL_SETVNNMAP, 0, data,
1526 NULL, NULL, &res, &timeout, NULL);
1527 if (ret != 0 || res != 0) {
1528 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setvnnmap failed\n"));
1539 async send for pull database
1541 struct ctdb_client_control_state *ctdb_ctrl_pulldb_send(
1542 struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid,
1543 uint32_t lmaster, TALLOC_CTX *mem_ctx, struct timeval timeout)
1546 struct ctdb_control_pulldb *pull;
1547 struct ctdb_client_control_state *state;
1549 pull = talloc(mem_ctx, struct ctdb_control_pulldb);
1550 CTDB_NO_MEMORY_NULL(ctdb, pull);
1553 pull->lmaster = lmaster;
1555 indata.dsize = sizeof(struct ctdb_control_pulldb);
1556 indata.dptr = (unsigned char *)pull;
1558 state = ctdb_control_send(ctdb, destnode, 0,
1559 CTDB_CONTROL_PULL_DB, 0, indata,
1560 mem_ctx, &timeout, NULL);
1567 async recv for pull database
1569 int ctdb_ctrl_pulldb_recv(
1570 struct ctdb_context *ctdb,
1571 TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state,
1577 ret = ctdb_control_recv(ctdb, state, mem_ctx, outdata, &res, NULL);
1578 if ( (ret != 0) || (res != 0) ){
1579 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_pulldb_recv failed\n"));
1587 pull all keys and records for a specific database on a node
1589 int ctdb_ctrl_pulldb(struct ctdb_context *ctdb, uint32_t destnode,
1590 uint32_t dbid, uint32_t lmaster,
1591 TALLOC_CTX *mem_ctx, struct timeval timeout,
1594 struct ctdb_client_control_state *state;
1596 state = ctdb_ctrl_pulldb_send(ctdb, destnode, dbid, lmaster, mem_ctx,
1599 return ctdb_ctrl_pulldb_recv(ctdb, mem_ctx, state, outdata);
1604 change dmaster for all keys in the database to the new value
1606 int ctdb_ctrl_setdmaster(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
1607 TALLOC_CTX *mem_ctx, uint32_t dbid, uint32_t dmaster)
1613 indata.dsize = 2*sizeof(uint32_t);
1614 indata.dptr = (unsigned char *)talloc_array(mem_ctx, uint32_t, 2);
1616 ((uint32_t *)(&indata.dptr[0]))[0] = dbid;
1617 ((uint32_t *)(&indata.dptr[0]))[1] = dmaster;
1619 ret = ctdb_control(ctdb, destnode, 0,
1620 CTDB_CONTROL_SET_DMASTER, 0, indata,
1621 NULL, NULL, &res, &timeout, NULL);
1622 if (ret != 0 || res != 0) {
1623 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setdmaster failed\n"));
1631 ping a node, return number of clients connected
1633 int ctdb_ctrl_ping(struct ctdb_context *ctdb, uint32_t destnode)
1638 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_PING, 0,
1639 tdb_null, NULL, NULL, &res, NULL, NULL);
1647 find the real path to a ltdb
1649 int ctdb_ctrl_getdbpath(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t dbid, TALLOC_CTX *mem_ctx,
1656 data.dptr = (uint8_t *)&dbid;
1657 data.dsize = sizeof(dbid);
1659 ret = ctdb_control(ctdb, destnode, 0,
1660 CTDB_CONTROL_GETDBPATH, 0, data,
1661 mem_ctx, &data, &res, &timeout, NULL);
1662 if (ret != 0 || res != 0) {
1666 (*path) = talloc_strndup(mem_ctx, (const char *)data.dptr, data.dsize);
1667 if ((*path) == NULL) {
1671 talloc_free(data.dptr);
1677 find the name of a db
1679 int ctdb_ctrl_getdbname(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t dbid, TALLOC_CTX *mem_ctx,
1686 data.dptr = (uint8_t *)&dbid;
1687 data.dsize = sizeof(dbid);
1689 ret = ctdb_control(ctdb, destnode, 0,
1690 CTDB_CONTROL_GET_DBNAME, 0, data,
1691 mem_ctx, &data, &res, &timeout, NULL);
1692 if (ret != 0 || res != 0) {
1696 (*name) = talloc_strndup(mem_ctx, (const char *)data.dptr, data.dsize);
1697 if ((*name) == NULL) {
1701 talloc_free(data.dptr);
1707 get the health status of a db
1709 int ctdb_ctrl_getdbhealth(struct ctdb_context *ctdb,
1710 struct timeval timeout,
1712 uint32_t dbid, TALLOC_CTX *mem_ctx,
1713 const char **reason)
1719 data.dptr = (uint8_t *)&dbid;
1720 data.dsize = sizeof(dbid);
1722 ret = ctdb_control(ctdb, destnode, 0,
1723 CTDB_CONTROL_DB_GET_HEALTH, 0, data,
1724 mem_ctx, &data, &res, &timeout, NULL);
1725 if (ret != 0 || res != 0) {
1729 if (data.dsize == 0) {
1734 (*reason) = talloc_strndup(mem_ctx, (const char *)data.dptr, data.dsize);
1735 if ((*reason) == NULL) {
1739 talloc_free(data.dptr);
1747 int ctdb_ctrl_createdb(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
1748 TALLOC_CTX *mem_ctx, const char *name, bool persistent)
1754 data.dptr = discard_const(name);
1755 data.dsize = strlen(name)+1;
1757 ret = ctdb_control(ctdb, destnode, 0,
1758 persistent?CTDB_CONTROL_DB_ATTACH_PERSISTENT:CTDB_CONTROL_DB_ATTACH,
1760 mem_ctx, &data, &res, &timeout, NULL);
1762 if (ret != 0 || res != 0) {
1770 get debug level on a node
1772 int ctdb_ctrl_get_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, int32_t *level)
1778 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_DEBUG, 0, tdb_null,
1779 ctdb, &data, &res, NULL, NULL);
1780 if (ret != 0 || res != 0) {
1783 if (data.dsize != sizeof(int32_t)) {
1784 DEBUG(DEBUG_ERR,("Bad control reply size in ctdb_get_debuglevel (got %u)\n",
1785 (unsigned)data.dsize));
1788 *level = *(int32_t *)data.dptr;
1789 talloc_free(data.dptr);
1794 set debug level on a node
1796 int ctdb_ctrl_set_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, int32_t level)
1802 data.dptr = (uint8_t *)&level;
1803 data.dsize = sizeof(level);
1805 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SET_DEBUG, 0, data,
1806 NULL, NULL, &res, NULL, NULL);
1807 if (ret != 0 || res != 0) {
1815 get a list of connected nodes
1817 uint32_t *ctdb_get_connected_nodes(struct ctdb_context *ctdb,
1818 struct timeval timeout,
1819 TALLOC_CTX *mem_ctx,
1820 uint32_t *num_nodes)
1822 struct ctdb_node_map *map=NULL;
1828 ret = ctdb_ctrl_getnodemap(ctdb, timeout, CTDB_CURRENT_NODE, mem_ctx, &map);
1833 nodes = talloc_array(mem_ctx, uint32_t, map->num);
1834 if (nodes == NULL) {
1838 for (i=0;i<map->num;i++) {
1839 if (!(map->nodes[i].flags & NODE_FLAGS_DISCONNECTED)) {
1840 nodes[*num_nodes] = map->nodes[i].pnn;
1852 int ctdb_statistics_reset(struct ctdb_context *ctdb, uint32_t destnode)
1857 ret = ctdb_control(ctdb, destnode, 0,
1858 CTDB_CONTROL_STATISTICS_RESET, 0, tdb_null,
1859 NULL, NULL, &res, NULL, NULL);
1860 if (ret != 0 || res != 0) {
1861 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for reset statistics failed\n"));
1868 attach to a specific database - client call
1870 struct ctdb_db_context *ctdb_attach(struct ctdb_context *ctdb,
1871 struct timeval timeout,
1876 struct ctdb_db_context *ctdb_db;
1881 ctdb_db = ctdb_db_handle(ctdb, name);
1886 ctdb_db = talloc_zero(ctdb, struct ctdb_db_context);
1887 CTDB_NO_MEMORY_NULL(ctdb, ctdb_db);
1889 ctdb_db->ctdb = ctdb;
1890 ctdb_db->db_name = talloc_strdup(ctdb_db, name);
1891 CTDB_NO_MEMORY_NULL(ctdb, ctdb_db->db_name);
1893 data.dptr = discard_const(name);
1894 data.dsize = strlen(name)+1;
1896 /* tell ctdb daemon to attach */
1897 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, tdb_flags,
1898 persistent?CTDB_CONTROL_DB_ATTACH_PERSISTENT:CTDB_CONTROL_DB_ATTACH,
1899 0, data, ctdb_db, &data, &res, NULL, NULL);
1900 if (ret != 0 || res != 0 || data.dsize != sizeof(uint32_t)) {
1901 DEBUG(DEBUG_ERR,("Failed to attach to database '%s'\n", name));
1902 talloc_free(ctdb_db);
1906 ctdb_db->db_id = *(uint32_t *)data.dptr;
1907 talloc_free(data.dptr);
1909 ret = ctdb_ctrl_getdbpath(ctdb, timeout, CTDB_CURRENT_NODE, ctdb_db->db_id, ctdb_db, &ctdb_db->db_path);
1911 DEBUG(DEBUG_ERR,("Failed to get dbpath for database '%s'\n", name));
1912 talloc_free(ctdb_db);
1916 tdb_flags = persistent?TDB_DEFAULT:TDB_NOSYNC;
1917 if (ctdb->valgrinding) {
1918 tdb_flags |= TDB_NOMMAP;
1920 tdb_flags |= TDB_DISALLOW_NESTING;
1922 ctdb_db->ltdb = tdb_wrap_open(ctdb, ctdb_db->db_path, 0, tdb_flags, O_RDWR, 0);
1923 if (ctdb_db->ltdb == NULL) {
1924 ctdb_set_error(ctdb, "Failed to open tdb '%s'\n", ctdb_db->db_path);
1925 talloc_free(ctdb_db);
1929 ctdb_db->persistent = persistent;
1931 DLIST_ADD(ctdb->db_list, ctdb_db);
1933 /* add well known functions */
1934 ctdb_set_call(ctdb_db, ctdb_null_func, CTDB_NULL_FUNC);
1935 ctdb_set_call(ctdb_db, ctdb_fetch_func, CTDB_FETCH_FUNC);
1936 ctdb_set_call(ctdb_db, ctdb_fetch_with_header_func, CTDB_FETCH_WITH_HEADER_FUNC);
1943 setup a call for a database
1945 int ctdb_set_call(struct ctdb_db_context *ctdb_db, ctdb_fn_t fn, uint32_t id)
1947 struct ctdb_registered_call *call;
1952 struct ctdb_control_set_call c;
1955 /* this is no longer valid with the separate daemon architecture */
1956 c.db_id = ctdb_db->db_id;
1960 data.dptr = (uint8_t *)&c;
1961 data.dsize = sizeof(c);
1963 ret = ctdb_control(ctdb_db->ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_SET_CALL, 0,
1964 data, NULL, NULL, &status, NULL, NULL);
1965 if (ret != 0 || status != 0) {
1966 DEBUG(DEBUG_ERR,("ctdb_set_call failed for call %u\n", id));
1971 /* also register locally */
1972 call = talloc(ctdb_db, struct ctdb_registered_call);
1976 DLIST_ADD(ctdb_db->calls, call);
1981 struct traverse_state {
1984 ctdb_traverse_func fn;
1986 bool listemptyrecords;
1990 called on each key during a ctdb_traverse
1992 static void traverse_handler(struct ctdb_context *ctdb, uint64_t srvid, TDB_DATA data, void *p)
1994 struct traverse_state *state = (struct traverse_state *)p;
1995 struct ctdb_rec_data *d = (struct ctdb_rec_data *)data.dptr;
1998 if (data.dsize < sizeof(uint32_t) ||
1999 d->length != data.dsize) {
2000 DEBUG(DEBUG_ERR,("Bad data size %u in traverse_handler\n", (unsigned)data.dsize));
2005 key.dsize = d->keylen;
2006 key.dptr = &d->data[0];
2007 data.dsize = d->datalen;
2008 data.dptr = &d->data[d->keylen];
2010 if (key.dsize == 0 && data.dsize == 0) {
2011 /* end of traverse */
2016 if (!state->listemptyrecords &&
2017 data.dsize == sizeof(struct ctdb_ltdb_header))
2019 /* empty records are deleted records in ctdb */
2023 if (state->fn(ctdb, key, data, state->private_data) != 0) {
2031 * start a cluster wide traverse, calling the supplied fn on each record
2032 * return the number of records traversed, or -1 on error
2034 * Extendet variant with a flag to signal whether empty records should
2037 static int ctdb_traverse_ext(struct ctdb_db_context *ctdb_db,
2038 ctdb_traverse_func fn,
2039 bool withemptyrecords,
2043 struct ctdb_traverse_start_ext t;
2046 uint64_t srvid = (getpid() | 0xFLL<<60);
2047 struct traverse_state state;
2051 state.private_data = private_data;
2053 state.listemptyrecords = withemptyrecords;
2055 ret = ctdb_client_set_message_handler(ctdb_db->ctdb, srvid, traverse_handler, &state);
2057 DEBUG(DEBUG_ERR,("Failed to setup traverse handler\n"));
2061 t.db_id = ctdb_db->db_id;
2064 t.withemptyrecords = withemptyrecords;
2066 data.dptr = (uint8_t *)&t;
2067 data.dsize = sizeof(t);
2069 ret = ctdb_control(ctdb_db->ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_TRAVERSE_START_EXT, 0,
2070 data, NULL, NULL, &status, NULL, NULL);
2071 if (ret != 0 || status != 0) {
2072 DEBUG(DEBUG_ERR,("ctdb_traverse_all failed\n"));
2073 ctdb_client_remove_message_handler(ctdb_db->ctdb, srvid, &state);
2077 while (!state.done) {
2078 event_loop_once(ctdb_db->ctdb->ev);
2081 ret = ctdb_client_remove_message_handler(ctdb_db->ctdb, srvid, &state);
2083 DEBUG(DEBUG_ERR,("Failed to remove ctdb_traverse handler\n"));
2091 * start a cluster wide traverse, calling the supplied fn on each record
2092 * return the number of records traversed, or -1 on error
2094 * Standard version which does not list the empty records:
2095 * These are considered deleted.
2097 int ctdb_traverse(struct ctdb_db_context *ctdb_db, ctdb_traverse_func fn, void *private_data)
2099 return ctdb_traverse_ext(ctdb_db, fn, false, private_data);
2102 #define ISASCII(x) (isprint(x) && !strchr("\"\\", (x)))
2104 called on each key during a catdb
2106 int ctdb_dumpdb_record(struct ctdb_context *ctdb, TDB_DATA key, TDB_DATA data, void *p)
2109 struct ctdb_dump_db_context *c = (struct ctdb_dump_db_context *)p;
2111 struct ctdb_ltdb_header *h = (struct ctdb_ltdb_header *)data.dptr;
2113 fprintf(f, "key(%u) = \"", (unsigned)key.dsize);
2114 for (i=0;i<key.dsize;i++) {
2115 if (ISASCII(key.dptr[i])) {
2116 fprintf(f, "%c", key.dptr[i]);
2118 fprintf(f, "\\%02X", key.dptr[i]);
2123 fprintf(f, "dmaster: %u\n", h->dmaster);
2124 fprintf(f, "rsn: %llu\n", (unsigned long long)h->rsn);
2126 if (c->printlmaster && ctdb->vnn_map != NULL) {
2127 fprintf(f, "lmaster: %u\n", ctdb_lmaster(ctdb, &key));
2131 fprintf(f, "hash: 0x%08x\n", ctdb_hash(&key));
2134 if (c->printrecordflags) {
2135 fprintf(f, "flags: 0x%08x", h->flags);
2136 if (h->flags & CTDB_REC_FLAG_MIGRATED_WITH_DATA) printf(" MIGRATED_WITH_DATA");
2137 if (h->flags & CTDB_REC_FLAG_VACUUM_MIGRATED) printf(" VACUUM_MIGRATED");
2138 if (h->flags & CTDB_REC_FLAG_AUTOMATIC) printf(" AUTOMATIC");
2139 if (h->flags & CTDB_REC_RO_HAVE_DELEGATIONS) printf(" RO_HAVE_DELEGATIONS");
2140 if (h->flags & CTDB_REC_RO_HAVE_READONLY) printf(" RO_HAVE_READONLY");
2141 if (h->flags & CTDB_REC_RO_REVOKING_READONLY) printf(" RO_REVOKING_READONLY");
2142 if (h->flags & CTDB_REC_RO_REVOKE_COMPLETE) printf(" RO_REVOKE_COMPLETE");
2146 if (c->printdatasize) {
2147 fprintf(f, "data size: %u\n", (unsigned)data.dsize);
2149 fprintf(f, "data(%u) = \"", (unsigned)(data.dsize - sizeof(*h)));
2150 for (i=sizeof(*h);i<data.dsize;i++) {
2151 if (ISASCII(data.dptr[i])) {
2152 fprintf(f, "%c", data.dptr[i]);
2154 fprintf(f, "\\%02X", data.dptr[i]);
2166 convenience function to list all keys to stdout
2168 int ctdb_dump_db(struct ctdb_db_context *ctdb_db,
2169 struct ctdb_dump_db_context *ctx)
2171 return ctdb_traverse_ext(ctdb_db, ctdb_dumpdb_record,
2172 ctx->printemptyrecords, ctx);
2176 get the pid of a ctdb daemon
2178 int ctdb_ctrl_getpid(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *pid)
2183 ret = ctdb_control(ctdb, destnode, 0,
2184 CTDB_CONTROL_GET_PID, 0, tdb_null,
2185 NULL, NULL, &res, &timeout, NULL);
2187 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getpid failed\n"));
2198 async freeze send control
2200 struct ctdb_client_control_state *
2201 ctdb_ctrl_freeze_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, uint32_t priority)
2203 return ctdb_control_send(ctdb, destnode, priority,
2204 CTDB_CONTROL_FREEZE, 0, tdb_null,
2205 mem_ctx, &timeout, NULL);
2209 async freeze recv control
2211 int ctdb_ctrl_freeze_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state)
2216 ret = ctdb_control_recv(ctdb, state, mem_ctx, NULL, &res, NULL);
2217 if ( (ret != 0) || (res != 0) ){
2218 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_freeze_recv failed\n"));
2226 freeze databases of a certain priority
2228 int ctdb_ctrl_freeze_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t priority)
2230 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2231 struct ctdb_client_control_state *state;
2234 state = ctdb_ctrl_freeze_send(ctdb, tmp_ctx, timeout, destnode, priority);
2235 ret = ctdb_ctrl_freeze_recv(ctdb, tmp_ctx, state);
2236 talloc_free(tmp_ctx);
2241 /* Freeze all databases */
2242 int ctdb_ctrl_freeze(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2246 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
2247 if (ctdb_ctrl_freeze_priority(ctdb, timeout, destnode, i) != 0) {
2255 thaw databases of a certain priority
2257 int ctdb_ctrl_thaw_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t priority)
2262 ret = ctdb_control(ctdb, destnode, priority,
2263 CTDB_CONTROL_THAW, 0, tdb_null,
2264 NULL, NULL, &res, &timeout, NULL);
2265 if (ret != 0 || res != 0) {
2266 DEBUG(DEBUG_ERR,(__location__ " ctdb_control thaw failed\n"));
2273 /* thaw all databases */
2274 int ctdb_ctrl_thaw(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2276 return ctdb_ctrl_thaw_priority(ctdb, timeout, destnode, 0);
2280 get pnn of a node, or -1
2282 int ctdb_ctrl_getpnn(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2287 ret = ctdb_control(ctdb, destnode, 0,
2288 CTDB_CONTROL_GET_PNN, 0, tdb_null,
2289 NULL, NULL, &res, &timeout, NULL);
2291 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getpnn failed\n"));
2299 get the monitoring mode of a remote node
2301 int ctdb_ctrl_getmonmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *monmode)
2306 ret = ctdb_control(ctdb, destnode, 0,
2307 CTDB_CONTROL_GET_MONMODE, 0, tdb_null,
2308 NULL, NULL, &res, &timeout, NULL);
2310 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getmonmode failed\n"));
2321 set the monitoring mode of a remote node to active
2323 int ctdb_ctrl_enable_monmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2328 ret = ctdb_control(ctdb, destnode, 0,
2329 CTDB_CONTROL_ENABLE_MONITOR, 0, tdb_null,
2330 NULL, NULL,NULL, &timeout, NULL);
2332 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for enable_monitor failed\n"));
2342 set the monitoring mode of a remote node to disable
2344 int ctdb_ctrl_disable_monmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2349 ret = ctdb_control(ctdb, destnode, 0,
2350 CTDB_CONTROL_DISABLE_MONITOR, 0, tdb_null,
2351 NULL, NULL, NULL, &timeout, NULL);
2353 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for disable_monitor failed\n"));
2365 sent to a node to make it take over an ip address
2367 int ctdb_ctrl_takeover_ip(struct ctdb_context *ctdb, struct timeval timeout,
2368 uint32_t destnode, struct ctdb_public_ip *ip)
2371 struct ctdb_public_ipv4 ipv4;
2375 if (ip->addr.sa.sa_family == AF_INET) {
2377 ipv4.sin = ip->addr.ip;
2379 data.dsize = sizeof(ipv4);
2380 data.dptr = (uint8_t *)&ipv4;
2382 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_TAKEOVER_IPv4, 0, data, NULL,
2383 NULL, &res, &timeout, NULL);
2385 data.dsize = sizeof(*ip);
2386 data.dptr = (uint8_t *)ip;
2388 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_TAKEOVER_IP, 0, data, NULL,
2389 NULL, &res, &timeout, NULL);
2392 if (ret != 0 || res != 0) {
2393 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for takeover_ip failed\n"));
2402 sent to a node to make it release an ip address
2404 int ctdb_ctrl_release_ip(struct ctdb_context *ctdb, struct timeval timeout,
2405 uint32_t destnode, struct ctdb_public_ip *ip)
2408 struct ctdb_public_ipv4 ipv4;
2412 if (ip->addr.sa.sa_family == AF_INET) {
2414 ipv4.sin = ip->addr.ip;
2416 data.dsize = sizeof(ipv4);
2417 data.dptr = (uint8_t *)&ipv4;
2419 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_RELEASE_IPv4, 0, data, NULL,
2420 NULL, &res, &timeout, NULL);
2422 data.dsize = sizeof(*ip);
2423 data.dptr = (uint8_t *)ip;
2425 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_RELEASE_IP, 0, data, NULL,
2426 NULL, &res, &timeout, NULL);
2429 if (ret != 0 || res != 0) {
2430 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for release_ip failed\n"));
2441 int ctdb_ctrl_get_tunable(struct ctdb_context *ctdb,
2442 struct timeval timeout,
2444 const char *name, uint32_t *value)
2446 struct ctdb_control_get_tunable *t;
2447 TDB_DATA data, outdata;
2451 data.dsize = offsetof(struct ctdb_control_get_tunable, name) + strlen(name) + 1;
2452 data.dptr = talloc_size(ctdb, data.dsize);
2453 CTDB_NO_MEMORY(ctdb, data.dptr);
2455 t = (struct ctdb_control_get_tunable *)data.dptr;
2456 t->length = strlen(name)+1;
2457 memcpy(t->name, name, t->length);
2459 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_TUNABLE, 0, data, ctdb,
2460 &outdata, &res, &timeout, NULL);
2461 talloc_free(data.dptr);
2462 if (ret != 0 || res != 0) {
2463 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get_tunable failed\n"));
2467 if (outdata.dsize != sizeof(uint32_t)) {
2468 DEBUG(DEBUG_ERR,("Invalid return data in get_tunable\n"));
2469 talloc_free(outdata.dptr);
2473 *value = *(uint32_t *)outdata.dptr;
2474 talloc_free(outdata.dptr);
2482 int ctdb_ctrl_set_tunable(struct ctdb_context *ctdb,
2483 struct timeval timeout,
2485 const char *name, uint32_t value)
2487 struct ctdb_control_set_tunable *t;
2492 data.dsize = offsetof(struct ctdb_control_set_tunable, name) + strlen(name) + 1;
2493 data.dptr = talloc_size(ctdb, data.dsize);
2494 CTDB_NO_MEMORY(ctdb, data.dptr);
2496 t = (struct ctdb_control_set_tunable *)data.dptr;
2497 t->length = strlen(name)+1;
2498 memcpy(t->name, name, t->length);
2501 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SET_TUNABLE, 0, data, NULL,
2502 NULL, &res, &timeout, NULL);
2503 talloc_free(data.dptr);
2504 if (ret != 0 || res != 0) {
2505 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set_tunable failed\n"));
2515 int ctdb_ctrl_list_tunables(struct ctdb_context *ctdb,
2516 struct timeval timeout,
2518 TALLOC_CTX *mem_ctx,
2519 const char ***list, uint32_t *count)
2524 struct ctdb_control_list_tunable *t;
2527 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_LIST_TUNABLES, 0, tdb_null,
2528 mem_ctx, &outdata, &res, &timeout, NULL);
2529 if (ret != 0 || res != 0) {
2530 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for list_tunables failed\n"));
2534 t = (struct ctdb_control_list_tunable *)outdata.dptr;
2535 if (outdata.dsize < offsetof(struct ctdb_control_list_tunable, data) ||
2536 t->length > outdata.dsize-offsetof(struct ctdb_control_list_tunable, data)) {
2537 DEBUG(DEBUG_ERR,("Invalid data in list_tunables reply\n"));
2538 talloc_free(outdata.dptr);
2542 p = talloc_strndup(mem_ctx, (char *)t->data, t->length);
2543 CTDB_NO_MEMORY(ctdb, p);
2545 talloc_free(outdata.dptr);
2550 for (s=strtok_r(p, ":", &ptr); s; s=strtok_r(NULL, ":", &ptr)) {
2551 (*list) = talloc_realloc(mem_ctx, *list, const char *, 1+(*count));
2552 CTDB_NO_MEMORY(ctdb, *list);
2553 (*list)[*count] = talloc_strdup(*list, s);
2554 CTDB_NO_MEMORY(ctdb, (*list)[*count]);
2564 int ctdb_ctrl_get_public_ips_flags(struct ctdb_context *ctdb,
2565 struct timeval timeout, uint32_t destnode,
2566 TALLOC_CTX *mem_ctx,
2568 struct ctdb_all_public_ips **ips)
2574 ret = ctdb_control(ctdb, destnode, 0,
2575 CTDB_CONTROL_GET_PUBLIC_IPS, flags, tdb_null,
2576 mem_ctx, &outdata, &res, &timeout, NULL);
2577 if (ret == 0 && res == -1) {
2578 DEBUG(DEBUG_ERR,(__location__ " ctdb_control to get public ips failed, falling back to ipv4-only version\n"));
2579 return ctdb_ctrl_get_public_ipsv4(ctdb, timeout, destnode, mem_ctx, ips);
2581 if (ret != 0 || res != 0) {
2582 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getpublicips failed ret:%d res:%d\n", ret, res));
2586 *ips = (struct ctdb_all_public_ips *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
2587 talloc_free(outdata.dptr);
2592 int ctdb_ctrl_get_public_ips(struct ctdb_context *ctdb,
2593 struct timeval timeout, uint32_t destnode,
2594 TALLOC_CTX *mem_ctx,
2595 struct ctdb_all_public_ips **ips)
2597 return ctdb_ctrl_get_public_ips_flags(ctdb, timeout,
2602 int ctdb_ctrl_get_public_ipsv4(struct ctdb_context *ctdb,
2603 struct timeval timeout, uint32_t destnode,
2604 TALLOC_CTX *mem_ctx, struct ctdb_all_public_ips **ips)
2609 struct ctdb_all_public_ipsv4 *ipsv4;
2611 ret = ctdb_control(ctdb, destnode, 0,
2612 CTDB_CONTROL_GET_PUBLIC_IPSv4, 0, tdb_null,
2613 mem_ctx, &outdata, &res, &timeout, NULL);
2614 if (ret != 0 || res != 0) {
2615 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getpublicips failed\n"));
2619 ipsv4 = (struct ctdb_all_public_ipsv4 *)outdata.dptr;
2620 len = offsetof(struct ctdb_all_public_ips, ips) +
2621 ipsv4->num*sizeof(struct ctdb_public_ip);
2622 *ips = talloc_zero_size(mem_ctx, len);
2623 CTDB_NO_MEMORY(ctdb, *ips);
2624 (*ips)->num = ipsv4->num;
2625 for (i=0; i<ipsv4->num; i++) {
2626 (*ips)->ips[i].pnn = ipsv4->ips[i].pnn;
2627 (*ips)->ips[i].addr.ip = ipsv4->ips[i].sin;
2630 talloc_free(outdata.dptr);
2635 int ctdb_ctrl_get_public_ip_info(struct ctdb_context *ctdb,
2636 struct timeval timeout, uint32_t destnode,
2637 TALLOC_CTX *mem_ctx,
2638 const ctdb_sock_addr *addr,
2639 struct ctdb_control_public_ip_info **_info)
2645 struct ctdb_control_public_ip_info *info;
2649 indata.dptr = discard_const_p(uint8_t, addr);
2650 indata.dsize = sizeof(*addr);
2652 ret = ctdb_control(ctdb, destnode, 0,
2653 CTDB_CONTROL_GET_PUBLIC_IP_INFO, 0, indata,
2654 mem_ctx, &outdata, &res, &timeout, NULL);
2655 if (ret != 0 || res != 0) {
2656 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
2657 "failed ret:%d res:%d\n",
2662 len = offsetof(struct ctdb_control_public_ip_info, ifaces);
2663 if (len > outdata.dsize) {
2664 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
2665 "returned invalid data with size %u > %u\n",
2666 (unsigned int)outdata.dsize,
2667 (unsigned int)len));
2668 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
2672 info = (struct ctdb_control_public_ip_info *)outdata.dptr;
2673 len += info->num*sizeof(struct ctdb_control_iface_info);
2675 if (len > outdata.dsize) {
2676 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
2677 "returned invalid data with size %u > %u\n",
2678 (unsigned int)outdata.dsize,
2679 (unsigned int)len));
2680 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
2684 /* make sure we null terminate the returned strings */
2685 for (i=0; i < info->num; i++) {
2686 info->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
2689 *_info = (struct ctdb_control_public_ip_info *)talloc_memdup(mem_ctx,
2692 talloc_free(outdata.dptr);
2693 if (*_info == NULL) {
2694 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
2695 "talloc_memdup size %u failed\n",
2696 (unsigned int)outdata.dsize));
2703 int ctdb_ctrl_get_ifaces(struct ctdb_context *ctdb,
2704 struct timeval timeout, uint32_t destnode,
2705 TALLOC_CTX *mem_ctx,
2706 struct ctdb_control_get_ifaces **_ifaces)
2711 struct ctdb_control_get_ifaces *ifaces;
2715 ret = ctdb_control(ctdb, destnode, 0,
2716 CTDB_CONTROL_GET_IFACES, 0, tdb_null,
2717 mem_ctx, &outdata, &res, &timeout, NULL);
2718 if (ret != 0 || res != 0) {
2719 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
2720 "failed ret:%d res:%d\n",
2725 len = offsetof(struct ctdb_control_get_ifaces, ifaces);
2726 if (len > outdata.dsize) {
2727 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
2728 "returned invalid data with size %u > %u\n",
2729 (unsigned int)outdata.dsize,
2730 (unsigned int)len));
2731 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
2735 ifaces = (struct ctdb_control_get_ifaces *)outdata.dptr;
2736 len += ifaces->num*sizeof(struct ctdb_control_iface_info);
2738 if (len > outdata.dsize) {
2739 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
2740 "returned invalid data with size %u > %u\n",
2741 (unsigned int)outdata.dsize,
2742 (unsigned int)len));
2743 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
2747 /* make sure we null terminate the returned strings */
2748 for (i=0; i < ifaces->num; i++) {
2749 ifaces->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
2752 *_ifaces = (struct ctdb_control_get_ifaces *)talloc_memdup(mem_ctx,
2755 talloc_free(outdata.dptr);
2756 if (*_ifaces == NULL) {
2757 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
2758 "talloc_memdup size %u failed\n",
2759 (unsigned int)outdata.dsize));
2766 int ctdb_ctrl_set_iface_link(struct ctdb_context *ctdb,
2767 struct timeval timeout, uint32_t destnode,
2768 TALLOC_CTX *mem_ctx,
2769 const struct ctdb_control_iface_info *info)
2775 indata.dptr = discard_const_p(uint8_t, info);
2776 indata.dsize = sizeof(*info);
2778 ret = ctdb_control(ctdb, destnode, 0,
2779 CTDB_CONTROL_SET_IFACE_LINK_STATE, 0, indata,
2780 mem_ctx, NULL, &res, &timeout, NULL);
2781 if (ret != 0 || res != 0) {
2782 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set iface link "
2783 "failed ret:%d res:%d\n",
2792 set/clear the permanent disabled bit on a remote node
2794 int ctdb_ctrl_modflags(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
2795 uint32_t set, uint32_t clear)
2799 struct ctdb_node_map *nodemap=NULL;
2800 struct ctdb_node_flag_change c;
2801 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2806 /* find the recovery master */
2807 ret = ctdb_ctrl_getrecmaster(ctdb, tmp_ctx, timeout, CTDB_CURRENT_NODE, &recmaster);
2809 DEBUG(DEBUG_ERR, (__location__ " Unable to get recmaster from local node\n"));
2810 talloc_free(tmp_ctx);
2815 /* read the node flags from the recmaster */
2816 ret = ctdb_ctrl_getnodemap(ctdb, timeout, recmaster, tmp_ctx, &nodemap);
2818 DEBUG(DEBUG_ERR, (__location__ " Unable to get nodemap from node %u\n", destnode));
2819 talloc_free(tmp_ctx);
2822 if (destnode >= nodemap->num) {
2823 DEBUG(DEBUG_ERR,(__location__ " Nodemap from recmaster does not contain node %d\n", destnode));
2824 talloc_free(tmp_ctx);
2829 c.old_flags = nodemap->nodes[destnode].flags;
2830 c.new_flags = c.old_flags;
2832 c.new_flags &= ~clear;
2834 data.dsize = sizeof(c);
2835 data.dptr = (unsigned char *)&c;
2837 /* send the flags update to all connected nodes */
2838 nodes = list_of_connected_nodes(ctdb, nodemap, tmp_ctx, true);
2840 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_MODIFY_FLAGS,
2842 timeout, false, data,
2845 DEBUG(DEBUG_ERR, (__location__ " Unable to update nodeflags on remote nodes\n"));
2847 talloc_free(tmp_ctx);
2851 talloc_free(tmp_ctx);
2859 int ctdb_ctrl_get_all_tunables(struct ctdb_context *ctdb,
2860 struct timeval timeout,
2862 struct ctdb_tunable *tunables)
2868 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_ALL_TUNABLES, 0, tdb_null, ctdb,
2869 &outdata, &res, &timeout, NULL);
2870 if (ret != 0 || res != 0) {
2871 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get all tunables failed\n"));
2875 if (outdata.dsize != sizeof(*tunables)) {
2876 DEBUG(DEBUG_ERR,(__location__ " bad data size %u in ctdb_ctrl_get_all_tunables should be %u\n",
2877 (unsigned)outdata.dsize, (unsigned)sizeof(*tunables)));
2881 *tunables = *(struct ctdb_tunable *)outdata.dptr;
2882 talloc_free(outdata.dptr);
2887 add a public address to a node
2889 int ctdb_ctrl_add_public_ip(struct ctdb_context *ctdb,
2890 struct timeval timeout,
2892 struct ctdb_control_ip_iface *pub)
2898 data.dsize = offsetof(struct ctdb_control_ip_iface, iface) + pub->len;
2899 data.dptr = (unsigned char *)pub;
2901 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_ADD_PUBLIC_IP, 0, data, NULL,
2902 NULL, &res, &timeout, NULL);
2903 if (ret != 0 || res != 0) {
2904 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for add_public_ip failed\n"));
2912 delete a public address from a node
2914 int ctdb_ctrl_del_public_ip(struct ctdb_context *ctdb,
2915 struct timeval timeout,
2917 struct ctdb_control_ip_iface *pub)
2923 data.dsize = offsetof(struct ctdb_control_ip_iface, iface) + pub->len;
2924 data.dptr = (unsigned char *)pub;
2926 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_DEL_PUBLIC_IP, 0, data, NULL,
2927 NULL, &res, &timeout, NULL);
2928 if (ret != 0 || res != 0) {
2929 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for del_public_ip failed\n"));
2937 kill a tcp connection
2939 int ctdb_ctrl_killtcp(struct ctdb_context *ctdb,
2940 struct timeval timeout,
2942 struct ctdb_control_killtcp *killtcp)
2948 data.dsize = sizeof(struct ctdb_control_killtcp);
2949 data.dptr = (unsigned char *)killtcp;
2951 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_KILL_TCP, 0, data, NULL,
2952 NULL, &res, &timeout, NULL);
2953 if (ret != 0 || res != 0) {
2954 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for killtcp failed\n"));
2964 int ctdb_ctrl_gratious_arp(struct ctdb_context *ctdb,
2965 struct timeval timeout,
2967 ctdb_sock_addr *addr,
2973 struct ctdb_control_gratious_arp *gratious_arp;
2974 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2977 len = strlen(ifname)+1;
2978 gratious_arp = talloc_size(tmp_ctx,
2979 offsetof(struct ctdb_control_gratious_arp, iface) + len);
2980 CTDB_NO_MEMORY(ctdb, gratious_arp);
2982 gratious_arp->addr = *addr;
2983 gratious_arp->len = len;
2984 memcpy(&gratious_arp->iface[0], ifname, len);
2987 data.dsize = offsetof(struct ctdb_control_gratious_arp, iface) + len;
2988 data.dptr = (unsigned char *)gratious_arp;
2990 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SEND_GRATIOUS_ARP, 0, data, NULL,
2991 NULL, &res, &timeout, NULL);
2992 if (ret != 0 || res != 0) {
2993 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for gratious_arp failed\n"));
2994 talloc_free(tmp_ctx);
2998 talloc_free(tmp_ctx);
3003 get a list of all tcp tickles that a node knows about for a particular vnn
3005 int ctdb_ctrl_get_tcp_tickles(struct ctdb_context *ctdb,
3006 struct timeval timeout, uint32_t destnode,
3007 TALLOC_CTX *mem_ctx,
3008 ctdb_sock_addr *addr,
3009 struct ctdb_control_tcp_tickle_list **list)
3012 TDB_DATA data, outdata;
3015 data.dptr = (uint8_t*)addr;
3016 data.dsize = sizeof(ctdb_sock_addr);
3018 ret = ctdb_control(ctdb, destnode, 0,
3019 CTDB_CONTROL_GET_TCP_TICKLE_LIST, 0, data,
3020 mem_ctx, &outdata, &status, NULL, NULL);
3021 if (ret != 0 || status != 0) {
3022 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get tcp tickles failed\n"));
3026 *list = (struct ctdb_control_tcp_tickle_list *)outdata.dptr;
3032 register a server id
3034 int ctdb_ctrl_register_server_id(struct ctdb_context *ctdb,
3035 struct timeval timeout,
3036 struct ctdb_server_id *id)
3042 data.dsize = sizeof(struct ctdb_server_id);
3043 data.dptr = (unsigned char *)id;
3045 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0,
3046 CTDB_CONTROL_REGISTER_SERVER_ID,
3048 NULL, &res, &timeout, NULL);
3049 if (ret != 0 || res != 0) {
3050 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for register server id failed\n"));
3058 unregister a server id
3060 int ctdb_ctrl_unregister_server_id(struct ctdb_context *ctdb,
3061 struct timeval timeout,
3062 struct ctdb_server_id *id)
3068 data.dsize = sizeof(struct ctdb_server_id);
3069 data.dptr = (unsigned char *)id;
3071 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0,
3072 CTDB_CONTROL_UNREGISTER_SERVER_ID,
3074 NULL, &res, &timeout, NULL);
3075 if (ret != 0 || res != 0) {
3076 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for unregister server id failed\n"));
3085 check if a server id exists
3087 if a server id does exist, return *status == 1, otherwise *status == 0
3089 int ctdb_ctrl_check_server_id(struct ctdb_context *ctdb,
3090 struct timeval timeout,
3092 struct ctdb_server_id *id,
3099 data.dsize = sizeof(struct ctdb_server_id);
3100 data.dptr = (unsigned char *)id;
3102 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_CHECK_SERVER_ID,
3104 NULL, &res, &timeout, NULL);
3106 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for check server id failed\n"));
3120 get the list of server ids that are registered on a node
3122 int ctdb_ctrl_get_server_id_list(struct ctdb_context *ctdb,
3123 TALLOC_CTX *mem_ctx,
3124 struct timeval timeout, uint32_t destnode,
3125 struct ctdb_server_id_list **svid_list)
3131 ret = ctdb_control(ctdb, destnode, 0,
3132 CTDB_CONTROL_GET_SERVER_ID_LIST, 0, tdb_null,
3133 mem_ctx, &outdata, &res, &timeout, NULL);
3134 if (ret != 0 || res != 0) {
3135 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get_server_id_list failed\n"));
3139 *svid_list = (struct ctdb_server_id_list *)talloc_steal(mem_ctx, outdata.dptr);
3145 initialise the ctdb daemon for client applications
3147 NOTE: In current code the daemon does not fork. This is for testing purposes only
3148 and to simplify the code.
3150 struct ctdb_context *ctdb_init(struct event_context *ev)
3153 struct ctdb_context *ctdb;
3155 ctdb = talloc_zero(ev, struct ctdb_context);
3157 DEBUG(DEBUG_ERR,(__location__ " talloc_zero failed.\n"));
3161 ctdb->idr = idr_init(ctdb);
3162 /* Wrap early to exercise code. */
3163 ctdb->lastid = INT_MAX-200;
3164 CTDB_NO_MEMORY_NULL(ctdb, ctdb->idr);
3166 ret = ctdb_set_socketname(ctdb, CTDB_PATH);
3168 DEBUG(DEBUG_ERR,(__location__ " ctdb_set_socketname failed.\n"));
3173 ctdb->statistics.statistics_start_time = timeval_current();
3182 void ctdb_set_flags(struct ctdb_context *ctdb, unsigned flags)
3184 ctdb->flags |= flags;
3188 setup the local socket name
3190 int ctdb_set_socketname(struct ctdb_context *ctdb, const char *socketname)
3192 ctdb->daemon.name = talloc_strdup(ctdb, socketname);
3193 CTDB_NO_MEMORY(ctdb, ctdb->daemon.name);
3198 const char *ctdb_get_socketname(struct ctdb_context *ctdb)
3200 return ctdb->daemon.name;
3204 return the pnn of this node
3206 uint32_t ctdb_get_pnn(struct ctdb_context *ctdb)
3213 get the uptime of a remote node
3215 struct ctdb_client_control_state *
3216 ctdb_ctrl_uptime_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode)
3218 return ctdb_control_send(ctdb, destnode, 0,
3219 CTDB_CONTROL_UPTIME, 0, tdb_null,
3220 mem_ctx, &timeout, NULL);
3223 int ctdb_ctrl_uptime_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, struct ctdb_uptime **uptime)
3229 ret = ctdb_control_recv(ctdb, state, mem_ctx, &outdata, &res, NULL);
3230 if (ret != 0 || res != 0) {
3231 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_uptime_recv failed\n"));
3235 *uptime = (struct ctdb_uptime *)talloc_steal(mem_ctx, outdata.dptr);
3240 int ctdb_ctrl_uptime(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, struct ctdb_uptime **uptime)
3242 struct ctdb_client_control_state *state;
3244 state = ctdb_ctrl_uptime_send(ctdb, mem_ctx, timeout, destnode);
3245 return ctdb_ctrl_uptime_recv(ctdb, mem_ctx, state, uptime);
3249 send a control to execute the "recovered" event script on a node
3251 int ctdb_ctrl_end_recovery(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
3256 ret = ctdb_control(ctdb, destnode, 0,
3257 CTDB_CONTROL_END_RECOVERY, 0, tdb_null,
3258 NULL, NULL, &status, &timeout, NULL);
3259 if (ret != 0 || status != 0) {
3260 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for end_recovery failed\n"));
3268 callback for the async helpers used when sending the same control
3269 to multiple nodes in parallell.
3271 static void async_callback(struct ctdb_client_control_state *state)
3273 struct client_async_data *data = talloc_get_type(state->async.private_data, struct client_async_data);
3274 struct ctdb_context *ctdb = talloc_get_type(state->ctdb, struct ctdb_context);
3278 uint32_t destnode = state->c->hdr.destnode;
3280 /* one more node has responded with recmode data */
3283 /* if we failed to push the db, then return an error and let
3284 the main loop try again.
3286 if (state->state != CTDB_CONTROL_DONE) {
3287 if ( !data->dont_log_errors) {
3288 DEBUG(DEBUG_ERR,("Async operation failed with state %d, opcode:%u\n", state->state, data->opcode));
3291 if (data->fail_callback) {
3292 data->fail_callback(ctdb, destnode, res, outdata,
3293 data->callback_data);
3298 state->async.fn = NULL;
3300 ret = ctdb_control_recv(ctdb, state, data, &outdata, &res, NULL);
3301 if ((ret != 0) || (res != 0)) {
3302 if ( !data->dont_log_errors) {
3303 DEBUG(DEBUG_ERR,("Async operation failed with ret=%d res=%d opcode=%u\n", ret, (int)res, data->opcode));
3306 if (data->fail_callback) {
3307 data->fail_callback(ctdb, destnode, res, outdata,
3308 data->callback_data);
3311 if ((ret == 0) && (data->callback != NULL)) {
3312 data->callback(ctdb, destnode, res, outdata,
3313 data->callback_data);
3318 void ctdb_client_async_add(struct client_async_data *data, struct ctdb_client_control_state *state)
3320 /* set up the callback functions */
3321 state->async.fn = async_callback;
3322 state->async.private_data = data;
3324 /* one more control to wait for to complete */
3329 /* wait for up to the maximum number of seconds allowed
3330 or until all nodes we expect a response from has replied
3332 int ctdb_client_async_wait(struct ctdb_context *ctdb, struct client_async_data *data)
3334 while (data->count > 0) {
3335 event_loop_once(ctdb->ev);
3337 if (data->fail_count != 0) {
3338 if (!data->dont_log_errors) {
3339 DEBUG(DEBUG_ERR,("Async wait failed - fail_count=%u\n",
3349 perform a simple control on the listed nodes
3350 The control cannot return data
3352 int ctdb_client_async_control(struct ctdb_context *ctdb,
3353 enum ctdb_controls opcode,
3356 struct timeval timeout,
3357 bool dont_log_errors,
3359 client_async_callback client_callback,
3360 client_async_callback fail_callback,
3361 void *callback_data)
3363 struct client_async_data *async_data;
3364 struct ctdb_client_control_state *state;
3367 async_data = talloc_zero(ctdb, struct client_async_data);
3368 CTDB_NO_MEMORY_FATAL(ctdb, async_data);
3369 async_data->dont_log_errors = dont_log_errors;
3370 async_data->callback = client_callback;
3371 async_data->fail_callback = fail_callback;
3372 async_data->callback_data = callback_data;
3373 async_data->opcode = opcode;
3375 num_nodes = talloc_get_size(nodes) / sizeof(uint32_t);
3377 /* loop over all nodes and send an async control to each of them */
3378 for (j=0; j<num_nodes; j++) {
3379 uint32_t pnn = nodes[j];
3381 state = ctdb_control_send(ctdb, pnn, srvid, opcode,
3382 0, data, async_data, &timeout, NULL);
3383 if (state == NULL) {
3384 DEBUG(DEBUG_ERR,(__location__ " Failed to call async control %u\n", (unsigned)opcode));
3385 talloc_free(async_data);
3389 ctdb_client_async_add(async_data, state);
3392 if (ctdb_client_async_wait(ctdb, async_data) != 0) {
3393 talloc_free(async_data);
3397 talloc_free(async_data);
3401 uint32_t *list_of_vnnmap_nodes(struct ctdb_context *ctdb,
3402 struct ctdb_vnn_map *vnn_map,
3403 TALLOC_CTX *mem_ctx,
3406 int i, j, num_nodes;
3409 for (i=num_nodes=0;i<vnn_map->size;i++) {
3410 if (vnn_map->map[i] == ctdb->pnn && !include_self) {
3416 nodes = talloc_array(mem_ctx, uint32_t, num_nodes);
3417 CTDB_NO_MEMORY_FATAL(ctdb, nodes);
3419 for (i=j=0;i<vnn_map->size;i++) {
3420 if (vnn_map->map[i] == ctdb->pnn && !include_self) {
3423 nodes[j++] = vnn_map->map[i];
3429 /* Get list of nodes not including those with flags specified by mask.
3430 * If exclude_pnn is not -1 then exclude that pnn from the list.
3432 uint32_t *list_of_nodes(struct ctdb_context *ctdb,
3433 struct ctdb_node_map *node_map,
3434 TALLOC_CTX *mem_ctx,
3438 int i, j, num_nodes;
3441 for (i=num_nodes=0;i<node_map->num;i++) {
3442 if (node_map->nodes[i].flags & mask) {
3445 if (node_map->nodes[i].pnn == exclude_pnn) {
3451 nodes = talloc_array(mem_ctx, uint32_t, num_nodes);
3452 CTDB_NO_MEMORY_FATAL(ctdb, nodes);
3454 for (i=j=0;i<node_map->num;i++) {
3455 if (node_map->nodes[i].flags & mask) {
3458 if (node_map->nodes[i].pnn == exclude_pnn) {
3461 nodes[j++] = node_map->nodes[i].pnn;
3467 uint32_t *list_of_active_nodes(struct ctdb_context *ctdb,
3468 struct ctdb_node_map *node_map,
3469 TALLOC_CTX *mem_ctx,
3472 return list_of_nodes(ctdb, node_map, mem_ctx, NODE_FLAGS_INACTIVE,
3473 include_self ? -1 : ctdb->pnn);
3476 uint32_t *list_of_active_nodes_except_pnn(struct ctdb_context *ctdb,
3477 struct ctdb_node_map *node_map,
3478 TALLOC_CTX *mem_ctx,
3481 return list_of_nodes(ctdb, node_map, mem_ctx, NODE_FLAGS_INACTIVE, pnn);
3484 uint32_t *list_of_connected_nodes(struct ctdb_context *ctdb,
3485 struct ctdb_node_map *node_map,
3486 TALLOC_CTX *mem_ctx,
3489 return list_of_nodes(ctdb, node_map, mem_ctx, NODE_FLAGS_DISCONNECTED,
3490 include_self ? -1 : ctdb->pnn);
3494 this is used to test if a pnn lock exists and if it exists will return
3495 the number of connections that pnn has reported or -1 if that recovery
3496 daemon is not running.
3499 ctdb_read_pnn_lock(int fd, int32_t pnn)
3504 lock.l_type = F_WRLCK;
3505 lock.l_whence = SEEK_SET;
3510 if (fcntl(fd, F_GETLK, &lock) != 0) {
3511 DEBUG(DEBUG_ERR, (__location__ " F_GETLK failed with %s\n", strerror(errno)));
3515 if (lock.l_type == F_UNLCK) {
3519 if (pread(fd, &c, 1, pnn) == -1) {
3520 DEBUG(DEBUG_CRIT,(__location__ " failed read pnn count - %s\n", strerror(errno)));
3528 get capabilities of a remote node
3530 struct ctdb_client_control_state *
3531 ctdb_ctrl_getcapabilities_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode)
3533 return ctdb_control_send(ctdb, destnode, 0,
3534 CTDB_CONTROL_GET_CAPABILITIES, 0, tdb_null,
3535 mem_ctx, &timeout, NULL);
3538 int ctdb_ctrl_getcapabilities_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *capabilities)
3544 ret = ctdb_control_recv(ctdb, state, mem_ctx, &outdata, &res, NULL);
3545 if ( (ret != 0) || (res != 0) ) {
3546 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_getcapabilities_recv failed\n"));
3551 *capabilities = *((uint32_t *)outdata.dptr);
3557 int ctdb_ctrl_getcapabilities(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *capabilities)
3559 struct ctdb_client_control_state *state;
3560 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
3563 state = ctdb_ctrl_getcapabilities_send(ctdb, tmp_ctx, timeout, destnode);
3564 ret = ctdb_ctrl_getcapabilities_recv(ctdb, tmp_ctx, state, capabilities);
3565 talloc_free(tmp_ctx);
3570 * check whether a transaction is active on a given db on a given node
3572 int32_t ctdb_ctrl_transaction_active(struct ctdb_context *ctdb,
3580 indata.dptr = (uint8_t *)&db_id;
3581 indata.dsize = sizeof(db_id);
3583 ret = ctdb_control(ctdb, destnode, 0,
3584 CTDB_CONTROL_TRANS2_ACTIVE,
3585 0, indata, NULL, NULL, &status,
3589 DEBUG(DEBUG_ERR, (__location__ " ctdb control for transaction_active failed\n"));
3597 struct ctdb_transaction_handle {
3598 struct ctdb_db_context *ctdb_db;
3601 * we store the reads and writes done under a transaction:
3602 * - one list stores both reads and writes (m_all),
3603 * - the other just writes (m_write)
3605 struct ctdb_marshall_buffer *m_all;
3606 struct ctdb_marshall_buffer *m_write;
3609 /* start a transaction on a database */
3610 static int ctdb_transaction_destructor(struct ctdb_transaction_handle *h)
3612 tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
3616 /* start a transaction on a database */
3617 static int ctdb_transaction_fetch_start(struct ctdb_transaction_handle *h)
3619 struct ctdb_record_handle *rh;
3622 struct ctdb_ltdb_header header;
3623 TALLOC_CTX *tmp_ctx;
3624 const char *keyname = CTDB_TRANSACTION_LOCK_KEY;
3626 struct ctdb_db_context *ctdb_db = h->ctdb_db;
3630 key.dptr = discard_const(keyname);
3631 key.dsize = strlen(keyname);
3633 if (!ctdb_db->persistent) {
3634 DEBUG(DEBUG_ERR,(__location__ " Attempted transaction on non-persistent database\n"));
3639 tmp_ctx = talloc_new(h);
3641 rh = ctdb_fetch_lock(ctdb_db, tmp_ctx, key, NULL);
3643 DEBUG(DEBUG_ERR,(__location__ " Failed to fetch_lock database\n"));
3644 talloc_free(tmp_ctx);
3648 status = ctdb_ctrl_transaction_active(ctdb_db->ctdb,
3652 unsigned long int usec = (1000 + random()) % 100000;
3653 DEBUG(DEBUG_DEBUG, (__location__ " transaction is active "
3654 "on db_id[0x%08x]. waiting for %lu "
3656 ctdb_db->db_id, usec));
3657 talloc_free(tmp_ctx);
3663 * store the pid in the database:
3664 * it is not enough that the node is dmaster...
3667 data.dptr = (unsigned char *)&pid;
3668 data.dsize = sizeof(pid_t);
3670 rh->header.dmaster = ctdb_db->ctdb->pnn;
3671 ret = ctdb_ltdb_store(ctdb_db, key, &(rh->header), data);
3673 DEBUG(DEBUG_ERR, (__location__ " Failed to store pid in "
3674 "transaction record\n"));
3675 talloc_free(tmp_ctx);
3681 ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
3683 DEBUG(DEBUG_ERR,(__location__ " Failed to start tdb transaction\n"));
3684 talloc_free(tmp_ctx);
3688 ret = ctdb_ltdb_fetch(ctdb_db, key, &header, tmp_ctx, &data);
3690 DEBUG(DEBUG_ERR,(__location__ " Failed to re-fetch transaction "
3691 "lock record inside transaction\n"));
3692 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
3693 talloc_free(tmp_ctx);
3697 if (header.dmaster != ctdb_db->ctdb->pnn) {
3698 DEBUG(DEBUG_DEBUG,(__location__ " not dmaster any more on "
3699 "transaction lock record\n"));
3700 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
3701 talloc_free(tmp_ctx);
3705 if ((data.dsize != sizeof(pid_t)) || (*(pid_t *)(data.dptr) != pid)) {
3706 DEBUG(DEBUG_DEBUG, (__location__ " my pid is not stored in "
3707 "the transaction lock record\n"));
3708 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
3709 talloc_free(tmp_ctx);
3713 talloc_free(tmp_ctx);
3719 /* start a transaction on a database */
3720 struct ctdb_transaction_handle *ctdb_transaction_start(struct ctdb_db_context *ctdb_db,
3721 TALLOC_CTX *mem_ctx)
3723 struct ctdb_transaction_handle *h;
3726 h = talloc_zero(mem_ctx, struct ctdb_transaction_handle);
3728 DEBUG(DEBUG_ERR,(__location__ " oom for transaction handle\n"));
3732 h->ctdb_db = ctdb_db;
3734 ret = ctdb_transaction_fetch_start(h);
3740 talloc_set_destructor(h, ctdb_transaction_destructor);
3748 fetch a record inside a transaction
3750 int ctdb_transaction_fetch(struct ctdb_transaction_handle *h,
3751 TALLOC_CTX *mem_ctx,
3752 TDB_DATA key, TDB_DATA *data)
3754 struct ctdb_ltdb_header header;
3757 ZERO_STRUCT(header);
3759 ret = ctdb_ltdb_fetch(h->ctdb_db, key, &header, mem_ctx, data);
3760 if (ret == -1 && header.dmaster == (uint32_t)-1) {
3761 /* record doesn't exist yet */
3770 if (!h->in_replay) {
3771 h->m_all = ctdb_marshall_add(h, h->m_all, h->ctdb_db->db_id, 1, key, NULL, *data);
3772 if (h->m_all == NULL) {
3773 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
3782 stores a record inside a transaction
3784 int ctdb_transaction_store(struct ctdb_transaction_handle *h,
3785 TDB_DATA key, TDB_DATA data)
3787 TALLOC_CTX *tmp_ctx = talloc_new(h);
3788 struct ctdb_ltdb_header header;
3792 ZERO_STRUCT(header);
3794 /* we need the header so we can update the RSN */
3795 ret = ctdb_ltdb_fetch(h->ctdb_db, key, &header, tmp_ctx, &olddata);
3796 if (ret == -1 && header.dmaster == (uint32_t)-1) {
3797 /* the record doesn't exist - create one with us as dmaster.
3798 This is only safe because we are in a transaction and this
3799 is a persistent database */
3800 ZERO_STRUCT(header);
3801 } else if (ret != 0) {
3802 DEBUG(DEBUG_ERR,(__location__ " Failed to fetch record\n"));
3803 talloc_free(tmp_ctx);
3807 if (data.dsize == olddata.dsize &&
3808 memcmp(data.dptr, olddata.dptr, data.dsize) == 0) {
3809 /* save writing the same data */
3810 talloc_free(tmp_ctx);
3814 header.dmaster = h->ctdb_db->ctdb->pnn;
3817 if (!h->in_replay) {
3818 h->m_all = ctdb_marshall_add(h, h->m_all, h->ctdb_db->db_id, 0, key, NULL, data);
3819 if (h->m_all == NULL) {
3820 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
3821 talloc_free(tmp_ctx);
3826 h->m_write = ctdb_marshall_add(h, h->m_write, h->ctdb_db->db_id, 0, key, &header, data);
3827 if (h->m_write == NULL) {
3828 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
3829 talloc_free(tmp_ctx);
3833 ret = ctdb_ltdb_store(h->ctdb_db, key, &header, data);
3835 talloc_free(tmp_ctx);
3841 replay a transaction
3843 static int ctdb_replay_transaction(struct ctdb_transaction_handle *h)
3846 struct ctdb_rec_data *rec = NULL;
3848 h->in_replay = true;
3849 talloc_free(h->m_write);
3852 ret = ctdb_transaction_fetch_start(h);
3857 for (i=0;i<h->m_all->count;i++) {
3860 rec = ctdb_marshall_loop_next(h->m_all, rec, NULL, NULL, &key, &data);
3862 DEBUG(DEBUG_ERR, (__location__ " Out of records in ctdb_replay_transaction?\n"));
3866 if (rec->reqid == 0) {
3868 if (ctdb_transaction_store(h, key, data) != 0) {
3873 TALLOC_CTX *tmp_ctx = talloc_new(h);
3875 if (ctdb_transaction_fetch(h, tmp_ctx, key, &data2) != 0) {
3876 talloc_free(tmp_ctx);
3879 if (data2.dsize != data.dsize ||
3880 memcmp(data2.dptr, data.dptr, data.dsize) != 0) {
3881 /* the record has changed on us - we have to give up */
3882 talloc_free(tmp_ctx);
3885 talloc_free(tmp_ctx);
3892 tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
3898 commit a transaction
3900 int ctdb_transaction_commit(struct ctdb_transaction_handle *h)
3904 struct ctdb_context *ctdb = h->ctdb_db->ctdb;
3905 struct timeval timeout;
3906 enum ctdb_controls failure_control = CTDB_CONTROL_TRANS2_ERROR;
3908 talloc_set_destructor(h, NULL);
3910 /* our commit strategy is quite complex.
3912 - we first try to commit the changes to all other nodes
3914 - if that works, then we commit locally and we are done
3916 - if a commit on another node fails, then we need to cancel
3917 the transaction, then restart the transaction (thus
3918 opening a window of time for a pending recovery to
3919 complete), then replay the transaction, checking all the
3920 reads and writes (checking that reads give the same data,
3921 and writes succeed). Then we retry the transaction to the
3926 if (h->m_write == NULL) {
3927 /* no changes were made */
3928 tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
3933 /* tell ctdbd to commit to the other nodes */
3934 timeout = timeval_current_ofs(1, 0);
3935 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
3936 retries==0?CTDB_CONTROL_TRANS2_COMMIT:CTDB_CONTROL_TRANS2_COMMIT_RETRY, 0,
3937 ctdb_marshall_finish(h->m_write), NULL, NULL, &status,
3939 if (ret != 0 || status != 0) {
3940 tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
3941 DEBUG(DEBUG_NOTICE, (__location__ " transaction commit%s failed"
3942 ", retrying after 1 second...\n",
3943 (retries==0)?"":"retry "));
3947 failure_control = CTDB_CONTROL_TRANS2_ERROR;
3949 /* work out what error code we will give if we
3950 have to fail the operation */
3951 switch ((enum ctdb_trans2_commit_error)status) {
3952 case CTDB_TRANS2_COMMIT_SUCCESS:
3953 case CTDB_TRANS2_COMMIT_SOMEFAIL:
3954 case CTDB_TRANS2_COMMIT_TIMEOUT:
3955 failure_control = CTDB_CONTROL_TRANS2_ERROR;
3957 case CTDB_TRANS2_COMMIT_ALLFAIL:
3958 failure_control = CTDB_CONTROL_TRANS2_FINISHED;
3963 if (++retries == 100) {
3964 DEBUG(DEBUG_ERR,(__location__ " Giving up transaction on db 0x%08x after %d retries failure_control=%u\n",
3965 h->ctdb_db->db_id, retries, (unsigned)failure_control));
3966 ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
3967 failure_control, CTDB_CTRL_FLAG_NOREPLY,
3968 tdb_null, NULL, NULL, NULL, NULL, NULL);
3973 if (ctdb_replay_transaction(h) != 0) {
3974 DEBUG(DEBUG_ERR, (__location__ " Failed to replay "
3975 "transaction on db 0x%08x, "
3976 "failure control =%u\n",
3978 (unsigned)failure_control));
3979 ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
3980 failure_control, CTDB_CTRL_FLAG_NOREPLY,
3981 tdb_null, NULL, NULL, NULL, NULL, NULL);
3987 failure_control = CTDB_CONTROL_TRANS2_ERROR;
3990 /* do the real commit locally */
3991 ret = tdb_transaction_commit(h->ctdb_db->ltdb->tdb);
3993 DEBUG(DEBUG_ERR, (__location__ " Failed to commit transaction "
3994 "on db id 0x%08x locally, "
3995 "failure_control=%u\n",
3997 (unsigned)failure_control));
3998 ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
3999 failure_control, CTDB_CTRL_FLAG_NOREPLY,
4000 tdb_null, NULL, NULL, NULL, NULL, NULL);
4005 /* tell ctdbd that we are finished with our local commit */
4006 ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
4007 CTDB_CONTROL_TRANS2_FINISHED, CTDB_CTRL_FLAG_NOREPLY,
4008 tdb_null, NULL, NULL, NULL, NULL, NULL);
4014 recovery daemon ping to main daemon
4016 int ctdb_ctrl_recd_ping(struct ctdb_context *ctdb)
4021 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_RECD_PING, 0, tdb_null,
4022 ctdb, NULL, &res, NULL, NULL);
4023 if (ret != 0 || res != 0) {
4024 DEBUG(DEBUG_ERR,("Failed to send recd ping\n"));
4031 /* When forking the main daemon and the child process needs to connect
4032 * back to the daemon as a client process, this function can be used
4033 * to change the ctdb context from daemon into client mode. The child
4034 * process must be created using ctdb_fork() and not fork() -
4035 * ctdb_fork() does some necessary housekeeping.
4037 int switch_from_server_to_client(struct ctdb_context *ctdb, const char *fmt, ...)
4042 /* Add extra information so we can identify this in the logs */
4044 debug_extra = talloc_strdup_append(talloc_vasprintf(NULL, fmt, ap), ":");
4047 /* get a new event context */
4048 ctdb->ev = event_context_init(ctdb);
4049 tevent_loop_allow_nesting(ctdb->ev);
4051 /* Connect to main CTDB daemon */
4052 ret = ctdb_socket_connect(ctdb);
4054 DEBUG(DEBUG_ALERT, (__location__ " Failed to init ctdb client\n"));
4058 ctdb->can_send_controls = true;
4064 get the status of running the monitor eventscripts: NULL means never run.
4066 int ctdb_ctrl_getscriptstatus(struct ctdb_context *ctdb,
4067 struct timeval timeout, uint32_t destnode,
4068 TALLOC_CTX *mem_ctx, enum ctdb_eventscript_call type,
4069 struct ctdb_scripts_wire **scripts)
4072 TDB_DATA outdata, indata;
4074 uint32_t uinttype = type;
4076 indata.dptr = (uint8_t *)&uinttype;
4077 indata.dsize = sizeof(uinttype);
4079 ret = ctdb_control(ctdb, destnode, 0,
4080 CTDB_CONTROL_GET_EVENT_SCRIPT_STATUS, 0, indata,
4081 mem_ctx, &outdata, &res, &timeout, NULL);
4082 if (ret != 0 || res != 0) {
4083 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getscriptstatus failed ret:%d res:%d\n", ret, res));
4087 if (outdata.dsize == 0) {
4090 *scripts = (struct ctdb_scripts_wire *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
4091 talloc_free(outdata.dptr);
4098 tell the main daemon how long it took to lock the reclock file
4100 int ctdb_ctrl_report_recd_lock_latency(struct ctdb_context *ctdb, struct timeval timeout, double latency)
4106 data.dptr = (uint8_t *)&latency;
4107 data.dsize = sizeof(latency);
4109 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_RECD_RECLOCK_LATENCY, 0, data,
4110 ctdb, NULL, &res, NULL, NULL);
4111 if (ret != 0 || res != 0) {
4112 DEBUG(DEBUG_ERR,("Failed to send recd reclock latency\n"));
4120 get the name of the reclock file
4122 int ctdb_ctrl_getreclock(struct ctdb_context *ctdb, struct timeval timeout,
4123 uint32_t destnode, TALLOC_CTX *mem_ctx,
4130 ret = ctdb_control(ctdb, destnode, 0,
4131 CTDB_CONTROL_GET_RECLOCK_FILE, 0, tdb_null,
4132 mem_ctx, &data, &res, &timeout, NULL);
4133 if (ret != 0 || res != 0) {
4137 if (data.dsize == 0) {
4140 *name = talloc_strdup(mem_ctx, discard_const(data.dptr));
4142 talloc_free(data.dptr);
4148 set the reclock filename for a node
4150 int ctdb_ctrl_setreclock(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, const char *reclock)
4156 if (reclock == NULL) {
4160 data.dsize = strlen(reclock) + 1;
4161 data.dptr = discard_const(reclock);
4164 ret = ctdb_control(ctdb, destnode, 0,
4165 CTDB_CONTROL_SET_RECLOCK_FILE, 0, data,
4166 NULL, NULL, &res, &timeout, NULL);
4167 if (ret != 0 || res != 0) {
4168 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setreclock failed\n"));
4178 int ctdb_ctrl_stop_node(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
4183 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_STOP_NODE, 0, tdb_null,
4184 ctdb, NULL, &res, &timeout, NULL);
4185 if (ret != 0 || res != 0) {
4186 DEBUG(DEBUG_ERR,("Failed to stop node\n"));
4196 int ctdb_ctrl_continue_node(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
4200 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_CONTINUE_NODE, 0, tdb_null,
4201 ctdb, NULL, NULL, &timeout, NULL);
4203 DEBUG(DEBUG_ERR,("Failed to continue node\n"));
4211 set the natgw state for a node
4213 int ctdb_ctrl_setnatgwstate(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t natgwstate)
4219 data.dsize = sizeof(natgwstate);
4220 data.dptr = (uint8_t *)&natgwstate;
4222 ret = ctdb_control(ctdb, destnode, 0,
4223 CTDB_CONTROL_SET_NATGWSTATE, 0, data,
4224 NULL, NULL, &res, &timeout, NULL);
4225 if (ret != 0 || res != 0) {
4226 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setnatgwstate failed\n"));
4234 set the lmaster role for a node
4236 int ctdb_ctrl_setlmasterrole(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t lmasterrole)
4242 data.dsize = sizeof(lmasterrole);
4243 data.dptr = (uint8_t *)&lmasterrole;
4245 ret = ctdb_control(ctdb, destnode, 0,
4246 CTDB_CONTROL_SET_LMASTERROLE, 0, data,
4247 NULL, NULL, &res, &timeout, NULL);
4248 if (ret != 0 || res != 0) {
4249 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setlmasterrole failed\n"));
4257 set the recmaster role for a node
4259 int ctdb_ctrl_setrecmasterrole(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmasterrole)
4265 data.dsize = sizeof(recmasterrole);
4266 data.dptr = (uint8_t *)&recmasterrole;
4268 ret = ctdb_control(ctdb, destnode, 0,
4269 CTDB_CONTROL_SET_RECMASTERROLE, 0, data,
4270 NULL, NULL, &res, &timeout, NULL);
4271 if (ret != 0 || res != 0) {
4272 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setrecmasterrole failed\n"));
4279 /* enable an eventscript
4281 int ctdb_ctrl_enablescript(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, const char *script)
4287 data.dsize = strlen(script) + 1;
4288 data.dptr = discard_const(script);
4290 ret = ctdb_control(ctdb, destnode, 0,
4291 CTDB_CONTROL_ENABLE_SCRIPT, 0, data,
4292 NULL, NULL, &res, &timeout, NULL);
4293 if (ret != 0 || res != 0) {
4294 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for enablescript failed\n"));
4301 /* disable an eventscript
4303 int ctdb_ctrl_disablescript(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, const char *script)
4309 data.dsize = strlen(script) + 1;
4310 data.dptr = discard_const(script);
4312 ret = ctdb_control(ctdb, destnode, 0,
4313 CTDB_CONTROL_DISABLE_SCRIPT, 0, data,
4314 NULL, NULL, &res, &timeout, NULL);
4315 if (ret != 0 || res != 0) {
4316 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for disablescript failed\n"));
4324 int ctdb_ctrl_set_ban(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, struct ctdb_ban_time *bantime)
4330 data.dsize = sizeof(*bantime);
4331 data.dptr = (uint8_t *)bantime;
4333 ret = ctdb_control(ctdb, destnode, 0,
4334 CTDB_CONTROL_SET_BAN_STATE, 0, data,
4335 NULL, NULL, &res, &timeout, NULL);
4336 if (ret != 0 || res != 0) {
4337 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set ban state failed\n"));
4345 int ctdb_ctrl_get_ban(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_ban_time **bantime)
4350 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
4352 ret = ctdb_control(ctdb, destnode, 0,
4353 CTDB_CONTROL_GET_BAN_STATE, 0, tdb_null,
4354 tmp_ctx, &outdata, &res, &timeout, NULL);
4355 if (ret != 0 || res != 0) {
4356 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set ban state failed\n"));
4357 talloc_free(tmp_ctx);
4361 *bantime = (struct ctdb_ban_time *)talloc_steal(mem_ctx, outdata.dptr);
4362 talloc_free(tmp_ctx);
4368 int ctdb_ctrl_set_db_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, struct ctdb_db_priority *db_prio)
4373 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
4375 data.dptr = (uint8_t*)db_prio;
4376 data.dsize = sizeof(*db_prio);
4378 ret = ctdb_control(ctdb, destnode, 0,
4379 CTDB_CONTROL_SET_DB_PRIORITY, 0, data,
4380 tmp_ctx, NULL, &res, &timeout, NULL);
4381 if (ret != 0 || res != 0) {
4382 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set_db_priority failed\n"));
4383 talloc_free(tmp_ctx);
4387 talloc_free(tmp_ctx);
4392 int ctdb_ctrl_get_db_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t db_id, uint32_t *priority)
4397 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
4399 data.dptr = (uint8_t*)&db_id;
4400 data.dsize = sizeof(db_id);
4402 ret = ctdb_control(ctdb, destnode, 0,
4403 CTDB_CONTROL_GET_DB_PRIORITY, 0, data,
4404 tmp_ctx, NULL, &res, &timeout, NULL);
4405 if (ret != 0 || res < 0) {
4406 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get_db_priority failed\n"));
4407 talloc_free(tmp_ctx);
4415 talloc_free(tmp_ctx);
4420 int ctdb_ctrl_getstathistory(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_statistics_wire **stats)
4426 ret = ctdb_control(ctdb, destnode, 0,
4427 CTDB_CONTROL_GET_STAT_HISTORY, 0, tdb_null,
4428 mem_ctx, &outdata, &res, &timeout, NULL);
4429 if (ret != 0 || res != 0 || outdata.dsize == 0) {
4430 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getstathistory failed ret:%d res:%d\n", ret, res));
4434 *stats = (struct ctdb_statistics_wire *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
4435 talloc_free(outdata.dptr);
4440 struct ctdb_ltdb_header *ctdb_header_from_record_handle(struct ctdb_record_handle *h)
4450 struct ctdb_client_control_state *
4451 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)
4453 struct ctdb_client_control_state *handle;
4454 struct ctdb_marshall_buffer *m;
4455 struct ctdb_rec_data *rec;
4458 m = talloc_zero(mem_ctx, struct ctdb_marshall_buffer);
4460 DEBUG(DEBUG_ERR, ("Failed to allocate marshall buffer for update record\n"));
4464 m->db_id = ctdb_db->db_id;
4466 rec = ctdb_marshall_record(m, 0, key, header, data);
4468 DEBUG(DEBUG_ERR,("Failed to marshall record for update record\n"));
4472 m = talloc_realloc_size(mem_ctx, m, rec->length + offsetof(struct ctdb_marshall_buffer, data));
4474 DEBUG(DEBUG_CRIT,(__location__ " Failed to expand recdata\n"));
4479 memcpy((uint8_t *)m + offsetof(struct ctdb_marshall_buffer, data), rec, rec->length);
4482 outdata.dptr = (uint8_t *)m;
4483 outdata.dsize = talloc_get_size(m);
4485 handle = ctdb_control_send(ctdb, destnode, 0,
4486 CTDB_CONTROL_UPDATE_RECORD, 0, outdata,
4487 mem_ctx, &timeout, NULL);
4492 int ctdb_ctrl_updaterecord_recv(struct ctdb_context *ctdb, struct ctdb_client_control_state *state)
4497 ret = ctdb_control_recv(ctdb, state, state, NULL, &res, NULL);
4498 if ( (ret != 0) || (res != 0) ){
4499 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_update_record_recv failed\n"));
4507 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)
4509 struct ctdb_client_control_state *state;
4511 state = ctdb_ctrl_updaterecord_send(ctdb, mem_ctx, timeout, destnode, ctdb_db, key, header, data);
4512 return ctdb_ctrl_updaterecord_recv(ctdb, state);
4521 set a database to be readonly
4523 struct ctdb_client_control_state *
4524 ctdb_ctrl_set_db_readonly_send(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid)
4528 data.dptr = (uint8_t *)&dbid;
4529 data.dsize = sizeof(dbid);
4531 return ctdb_control_send(ctdb, destnode, 0,
4532 CTDB_CONTROL_SET_DB_READONLY, 0, data,
4536 int ctdb_ctrl_set_db_readonly_recv(struct ctdb_context *ctdb, struct ctdb_client_control_state *state)
4541 ret = ctdb_control_recv(ctdb, state, ctdb, NULL, &res, NULL);
4542 if (ret != 0 || res != 0) {
4543 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_set_db_readonly_recv failed ret:%d res:%d\n", ret, res));
4550 int ctdb_ctrl_set_db_readonly(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid)
4552 struct ctdb_client_control_state *state;
4554 state = ctdb_ctrl_set_db_readonly_send(ctdb, destnode, dbid);
4555 return ctdb_ctrl_set_db_readonly_recv(ctdb, state);
4559 set a database to be sticky
4561 struct ctdb_client_control_state *
4562 ctdb_ctrl_set_db_sticky_send(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid)
4566 data.dptr = (uint8_t *)&dbid;
4567 data.dsize = sizeof(dbid);
4569 return ctdb_control_send(ctdb, destnode, 0,
4570 CTDB_CONTROL_SET_DB_STICKY, 0, data,
4574 int ctdb_ctrl_set_db_sticky_recv(struct ctdb_context *ctdb, struct ctdb_client_control_state *state)
4579 ret = ctdb_control_recv(ctdb, state, ctdb, NULL, &res, NULL);
4580 if (ret != 0 || res != 0) {
4581 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_set_db_sticky_recv failed ret:%d res:%d\n", ret, res));
4588 int ctdb_ctrl_set_db_sticky(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid)
4590 struct ctdb_client_control_state *state;
4592 state = ctdb_ctrl_set_db_sticky_send(ctdb, destnode, dbid);
4593 return ctdb_ctrl_set_db_sticky_recv(ctdb, state);