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/>.
22 #include "system/network.h"
23 #include "system/filesys.h"
24 #include "system/locale.h"
30 #include "lib/tdb_wrap/tdb_wrap.h"
31 #include "lib/util/dlinklist.h"
32 #include "lib/util/time.h"
33 #include "lib/util/debug.h"
34 #include "lib/util/samba_util.h"
36 #include "ctdb_private.h"
37 #include "ctdb_client.h"
39 #include "common/reqid.h"
40 #include "common/system.h"
41 #include "common/common.h"
42 #include "common/logging.h"
45 allocate a packet for use in client<->daemon communication
47 struct ctdb_req_header *_ctdbd_allocate_pkt(struct ctdb_context *ctdb,
49 enum ctdb_operation operation,
50 size_t length, size_t slength,
54 struct ctdb_req_header *hdr;
56 length = MAX(length, slength);
57 size = (length+(CTDB_DS_ALIGNMENT-1)) & ~(CTDB_DS_ALIGNMENT-1);
59 hdr = (struct ctdb_req_header *)talloc_zero_size(mem_ctx, size);
61 DEBUG(DEBUG_ERR,("Unable to allocate packet for operation %u of length %u\n",
62 operation, (unsigned)length));
65 talloc_set_name_const(hdr, type);
67 hdr->operation = operation;
68 hdr->ctdb_magic = CTDB_MAGIC;
69 hdr->ctdb_version = CTDB_PROTOCOL;
70 hdr->srcnode = ctdb->pnn;
72 hdr->generation = ctdb->vnn_map->generation;
79 local version of ctdb_call
81 int ctdb_call_local(struct ctdb_db_context *ctdb_db, struct ctdb_call *call,
82 struct ctdb_ltdb_header *header, TALLOC_CTX *mem_ctx,
83 TDB_DATA *data, bool updatetdb)
85 struct ctdb_call_info *c;
86 struct ctdb_registered_call *fn;
87 struct ctdb_context *ctdb = ctdb_db->ctdb;
89 c = talloc(ctdb, struct ctdb_call_info);
90 CTDB_NO_MEMORY(ctdb, c);
93 c->call_data = &call->call_data;
94 c->record_data.dptr = talloc_memdup(c, data->dptr, data->dsize);
95 c->record_data.dsize = data->dsize;
96 CTDB_NO_MEMORY(ctdb, c->record_data.dptr);
102 for (fn=ctdb_db->calls;fn;fn=fn->next) {
103 if (fn->id == call->call_id) break;
106 ctdb_set_error(ctdb, "Unknown call id %u\n", call->call_id);
111 if (fn->fn(c) != 0) {
112 ctdb_set_error(ctdb, "ctdb_call %u failed\n", call->call_id);
117 /* we need to force the record to be written out if this was a remote access */
118 if (c->new_data == NULL) {
119 c->new_data = &c->record_data;
122 if (c->new_data && updatetdb) {
123 /* XXX check that we always have the lock here? */
124 if (ctdb_ltdb_store(ctdb_db, call->key, header, *c->new_data) != 0) {
125 ctdb_set_error(ctdb, "ctdb_call tdb_store failed\n");
132 call->reply_data = *c->reply_data;
134 talloc_steal(call, call->reply_data.dptr);
135 talloc_set_name_const(call->reply_data.dptr, __location__);
137 call->reply_data.dptr = NULL;
138 call->reply_data.dsize = 0;
140 call->status = c->status;
149 queue a packet for sending from client to daemon
151 static int ctdb_client_queue_pkt(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
153 return ctdb_queue_send(ctdb->daemon.queue, (uint8_t *)hdr, hdr->length);
158 called when a CTDB_REPLY_CALL packet comes in in the client
160 This packet comes in response to a CTDB_REQ_CALL request packet. It
161 contains any reply data from the call
163 static void ctdb_client_reply_call(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
165 struct ctdb_reply_call_old *c = (struct ctdb_reply_call_old *)hdr;
166 struct ctdb_client_call_state *state;
168 state = reqid_find(ctdb->idr, hdr->reqid, struct ctdb_client_call_state);
170 DEBUG(DEBUG_ERR,(__location__ " reqid %u not found\n", hdr->reqid));
174 if (hdr->reqid != state->reqid) {
175 /* we found a record but it was the wrong one */
176 DEBUG(DEBUG_ERR, ("Dropped client call reply with reqid:%u\n",hdr->reqid));
180 state->call->reply_data.dptr = c->data;
181 state->call->reply_data.dsize = c->datalen;
182 state->call->status = c->status;
184 talloc_steal(state, c);
186 state->state = CTDB_CALL_DONE;
188 if (state->async.fn) {
189 state->async.fn(state);
193 void ctdb_request_message(struct ctdb_context *ctdb,
194 struct ctdb_req_header *hdr)
196 struct ctdb_req_message_old *c = (struct ctdb_req_message_old *)hdr;
199 data.dsize = c->datalen;
200 data.dptr = talloc_memdup(c, &c->data[0], c->datalen);
201 if (data.dptr == NULL) {
202 DEBUG(DEBUG_ERR, (__location__ " Memory allocation failure\n"));
206 srvid_dispatch(ctdb->srv, c->srvid, CTDB_SRVID_ALL, data);
209 static void ctdb_client_reply_control(struct ctdb_context *ctdb, struct ctdb_req_header *hdr);
212 this is called in the client, when data comes in from the daemon
214 void ctdb_client_read_cb(uint8_t *data, size_t cnt, void *args)
216 struct ctdb_context *ctdb = talloc_get_type(args, struct ctdb_context);
217 struct ctdb_req_header *hdr = (struct ctdb_req_header *)data;
220 /* place the packet as a child of a tmp_ctx. We then use
221 talloc_free() below to free it. If any of the calls want
222 to keep it, then they will steal it somewhere else, and the
223 talloc_free() will be a no-op */
224 tmp_ctx = talloc_new(ctdb);
225 talloc_steal(tmp_ctx, hdr);
228 DEBUG(DEBUG_CRIT,("Daemon has exited - shutting down client\n"));
232 if (cnt < sizeof(*hdr)) {
233 DEBUG(DEBUG_CRIT,("Bad packet length %u in client\n", (unsigned)cnt));
236 if (cnt != hdr->length) {
237 ctdb_set_error(ctdb, "Bad header length %u expected %u in client\n",
238 (unsigned)hdr->length, (unsigned)cnt);
242 if (hdr->ctdb_magic != CTDB_MAGIC) {
243 ctdb_set_error(ctdb, "Non CTDB packet rejected in client\n");
247 if (hdr->ctdb_version != CTDB_PROTOCOL) {
248 ctdb_set_error(ctdb, "Bad CTDB version 0x%x rejected in client\n", hdr->ctdb_version);
252 switch (hdr->operation) {
253 case CTDB_REPLY_CALL:
254 ctdb_client_reply_call(ctdb, hdr);
257 case CTDB_REQ_MESSAGE:
258 ctdb_request_message(ctdb, hdr);
261 case CTDB_REPLY_CONTROL:
262 ctdb_client_reply_control(ctdb, hdr);
266 DEBUG(DEBUG_CRIT,("bogus operation code:%u\n",hdr->operation));
270 talloc_free(tmp_ctx);
274 connect to a unix domain socket
276 int ctdb_socket_connect(struct ctdb_context *ctdb)
278 struct sockaddr_un addr;
280 memset(&addr, 0, sizeof(addr));
281 addr.sun_family = AF_UNIX;
282 strncpy(addr.sun_path, ctdb->daemon.name, sizeof(addr.sun_path)-1);
284 ctdb->daemon.sd = socket(AF_UNIX, SOCK_STREAM, 0);
285 if (ctdb->daemon.sd == -1) {
286 DEBUG(DEBUG_ERR,(__location__ " Failed to open client socket. Errno:%s(%d)\n", strerror(errno), errno));
290 if (connect(ctdb->daemon.sd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
291 close(ctdb->daemon.sd);
292 ctdb->daemon.sd = -1;
293 DEBUG(DEBUG_ERR,(__location__ " Failed to connect client socket to daemon. Errno:%s(%d)\n", strerror(errno), errno));
297 set_blocking(ctdb->daemon.sd, false);
298 set_close_on_exec(ctdb->daemon.sd);
300 ctdb->daemon.queue = ctdb_queue_setup(ctdb, ctdb, ctdb->daemon.sd,
302 ctdb_client_read_cb, ctdb, "to-ctdbd");
307 struct ctdb_record_handle {
308 struct ctdb_db_context *ctdb_db;
311 struct ctdb_ltdb_header header;
316 make a recv call to the local ctdb daemon - called from client context
318 This is called when the program wants to wait for a ctdb_call to complete and get the
319 results. This call will block unless the call has already completed.
321 int ctdb_call_recv(struct ctdb_client_call_state *state, struct ctdb_call *call)
327 while (state->state < CTDB_CALL_DONE) {
328 tevent_loop_once(state->ctdb_db->ctdb->ev);
330 if (state->state != CTDB_CALL_DONE) {
331 DEBUG(DEBUG_ERR,(__location__ " ctdb_call_recv failed\n"));
336 if (state->call->reply_data.dsize) {
337 call->reply_data.dptr = talloc_memdup(state->ctdb_db,
338 state->call->reply_data.dptr,
339 state->call->reply_data.dsize);
340 call->reply_data.dsize = state->call->reply_data.dsize;
342 call->reply_data.dptr = NULL;
343 call->reply_data.dsize = 0;
345 call->status = state->call->status;
355 destroy a ctdb_call in client
357 static int ctdb_client_call_destructor(struct ctdb_client_call_state *state)
359 reqid_remove(state->ctdb_db->ctdb->idr, state->reqid);
364 construct an event driven local ctdb_call
366 this is used so that locally processed ctdb_call requests are processed
367 in an event driven manner
369 static struct ctdb_client_call_state *ctdb_client_call_local_send(struct ctdb_db_context *ctdb_db,
370 struct ctdb_call *call,
371 struct ctdb_ltdb_header *header,
374 struct ctdb_client_call_state *state;
375 struct ctdb_context *ctdb = ctdb_db->ctdb;
378 state = talloc_zero(ctdb_db, struct ctdb_client_call_state);
379 CTDB_NO_MEMORY_NULL(ctdb, state);
380 state->call = talloc_zero(state, struct ctdb_call);
381 CTDB_NO_MEMORY_NULL(ctdb, state->call);
383 talloc_steal(state, data->dptr);
385 state->state = CTDB_CALL_DONE;
386 *(state->call) = *call;
387 state->ctdb_db = ctdb_db;
389 ret = ctdb_call_local(ctdb_db, state->call, header, state, data, true);
391 DEBUG(DEBUG_DEBUG,("ctdb_call_local() failed, ignoring return code %d\n", ret));
398 make a ctdb call to the local daemon - async send. Called from client context.
400 This constructs a ctdb_call request and queues it for processing.
401 This call never blocks.
403 struct ctdb_client_call_state *ctdb_call_send(struct ctdb_db_context *ctdb_db,
404 struct ctdb_call *call)
406 struct ctdb_client_call_state *state;
407 struct ctdb_context *ctdb = ctdb_db->ctdb;
408 struct ctdb_ltdb_header header;
412 struct ctdb_req_call_old *c;
414 /* if the domain socket is not yet open, open it */
415 if (ctdb->daemon.sd==-1) {
416 ctdb_socket_connect(ctdb);
419 ret = ctdb_ltdb_lock(ctdb_db, call->key);
421 DEBUG(DEBUG_ERR,(__location__ " Failed to get chainlock\n"));
425 ret = ctdb_ltdb_fetch(ctdb_db, call->key, &header, ctdb_db, &data);
427 if ((call->flags & CTDB_IMMEDIATE_MIGRATION) && (header.flags & CTDB_REC_RO_HAVE_DELEGATIONS)) {
431 if (ret == 0 && header.dmaster == ctdb->pnn) {
432 state = ctdb_client_call_local_send(ctdb_db, call, &header, &data);
433 talloc_free(data.dptr);
434 ctdb_ltdb_unlock(ctdb_db, call->key);
438 ctdb_ltdb_unlock(ctdb_db, call->key);
439 talloc_free(data.dptr);
441 state = talloc_zero(ctdb_db, struct ctdb_client_call_state);
443 DEBUG(DEBUG_ERR, (__location__ " failed to allocate state\n"));
446 state->call = talloc_zero(state, struct ctdb_call);
447 if (state->call == NULL) {
448 DEBUG(DEBUG_ERR, (__location__ " failed to allocate state->call\n"));
452 len = offsetof(struct ctdb_req_call_old, data) + call->key.dsize + call->call_data.dsize;
453 c = ctdbd_allocate_pkt(ctdb, state, CTDB_REQ_CALL, len, struct ctdb_req_call_old);
455 DEBUG(DEBUG_ERR, (__location__ " failed to allocate packet\n"));
459 state->reqid = reqid_new(ctdb->idr, state);
460 state->ctdb_db = ctdb_db;
461 talloc_set_destructor(state, ctdb_client_call_destructor);
463 c->hdr.reqid = state->reqid;
464 c->flags = call->flags;
465 c->db_id = ctdb_db->db_id;
466 c->callid = call->call_id;
468 c->keylen = call->key.dsize;
469 c->calldatalen = call->call_data.dsize;
470 memcpy(&c->data[0], call->key.dptr, call->key.dsize);
471 memcpy(&c->data[call->key.dsize],
472 call->call_data.dptr, call->call_data.dsize);
473 *(state->call) = *call;
474 state->call->call_data.dptr = &c->data[call->key.dsize];
475 state->call->key.dptr = &c->data[0];
477 state->state = CTDB_CALL_WAIT;
480 ctdb_client_queue_pkt(ctdb, &c->hdr);
487 full ctdb_call. Equivalent to a ctdb_call_send() followed by a ctdb_call_recv()
489 int ctdb_call(struct ctdb_db_context *ctdb_db, struct ctdb_call *call)
491 struct ctdb_client_call_state *state;
493 state = ctdb_call_send(ctdb_db, call);
494 return ctdb_call_recv(state, call);
499 tell the daemon what messaging srvid we will use, and register the message
500 handler function in the client
502 int ctdb_client_set_message_handler(struct ctdb_context *ctdb, uint64_t srvid,
503 srvid_handler_fn handler,
509 res = ctdb_control(ctdb, CTDB_CURRENT_NODE, srvid,
510 CTDB_CONTROL_REGISTER_SRVID, 0,
511 tdb_null, NULL, NULL, &status, NULL, NULL);
512 if (res != 0 || status != 0) {
514 ("Failed to register srvid %llu\n",
515 (unsigned long long)srvid));
519 /* also need to register the handler with our own ctdb structure */
520 return srvid_register(ctdb->srv, ctdb, srvid, handler, private_data);
524 tell the daemon we no longer want a srvid
526 int ctdb_client_remove_message_handler(struct ctdb_context *ctdb,
527 uint64_t srvid, void *private_data)
532 res = ctdb_control(ctdb, CTDB_CURRENT_NODE, srvid,
533 CTDB_CONTROL_DEREGISTER_SRVID, 0,
534 tdb_null, NULL, NULL, &status, NULL, NULL);
535 if (res != 0 || status != 0) {
537 ("Failed to deregister srvid %llu\n",
538 (unsigned long long)srvid));
542 /* also need to register the handler with our own ctdb structure */
543 srvid_deregister(ctdb->srv, srvid, private_data);
550 int ctdb_client_check_message_handlers(struct ctdb_context *ctdb, uint64_t *ids, uint32_t num,
553 TDB_DATA indata, outdata;
558 indata.dptr = (uint8_t *)ids;
559 indata.dsize = num * sizeof(*ids);
561 res = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_CHECK_SRVIDS, 0,
562 indata, ctdb, &outdata, &status, NULL, NULL);
563 if (res != 0 || status != 0) {
564 DEBUG(DEBUG_ERR, (__location__ " failed to check srvids\n"));
568 if (outdata.dsize != num*sizeof(uint8_t)) {
569 DEBUG(DEBUG_ERR, (__location__ " expected %lu bytes, received %zi bytes\n",
570 (long unsigned int)num*sizeof(uint8_t),
572 talloc_free(outdata.dptr);
576 for (i=0; i<num; i++) {
577 result[i] = outdata.dptr[i];
580 talloc_free(outdata.dptr);
585 send a message - from client context
587 int ctdb_client_send_message(struct ctdb_context *ctdb, uint32_t pnn,
588 uint64_t srvid, TDB_DATA data)
590 struct ctdb_req_message_old *r;
593 len = offsetof(struct ctdb_req_message_old, data) + data.dsize;
594 r = ctdbd_allocate_pkt(ctdb, ctdb, CTDB_REQ_MESSAGE,
595 len, struct ctdb_req_message_old);
596 CTDB_NO_MEMORY(ctdb, r);
598 r->hdr.destnode = pnn;
600 r->datalen = data.dsize;
601 memcpy(&r->data[0], data.dptr, data.dsize);
603 res = ctdb_client_queue_pkt(ctdb, &r->hdr);
610 cancel a ctdb_fetch_lock operation, releasing the lock
612 static int fetch_lock_destructor(struct ctdb_record_handle *h)
614 ctdb_ltdb_unlock(h->ctdb_db, h->key);
619 force the migration of a record to this node
621 static int ctdb_client_force_migration(struct ctdb_db_context *ctdb_db, TDB_DATA key)
623 struct ctdb_call call;
625 call.call_id = CTDB_NULL_FUNC;
627 call.flags = CTDB_IMMEDIATE_MIGRATION;
628 return ctdb_call(ctdb_db, &call);
632 try to fetch a readonly copy of a record
635 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)
639 struct ctdb_call call;
642 call.call_id = CTDB_FETCH_WITH_HEADER_FUNC;
643 call.call_data.dptr = NULL;
644 call.call_data.dsize = 0;
646 call.flags = CTDB_WANT_READONLY;
647 ret = ctdb_call(ctdb_db, &call);
652 if (call.reply_data.dsize < sizeof(struct ctdb_ltdb_header)) {
656 *hdr = talloc_memdup(mem_ctx, &call.reply_data.dptr[0], sizeof(struct ctdb_ltdb_header));
658 talloc_free(call.reply_data.dptr);
662 data->dsize = call.reply_data.dsize - sizeof(struct ctdb_ltdb_header);
663 data->dptr = talloc_memdup(mem_ctx, &call.reply_data.dptr[sizeof(struct ctdb_ltdb_header)], data->dsize);
664 if (data->dptr == NULL) {
665 talloc_free(call.reply_data.dptr);
674 get a lock on a record, and return the records data. Blocks until it gets the lock
676 struct ctdb_record_handle *ctdb_fetch_lock(struct ctdb_db_context *ctdb_db, TALLOC_CTX *mem_ctx,
677 TDB_DATA key, TDB_DATA *data)
680 struct ctdb_record_handle *h;
683 procedure is as follows:
685 1) get the chain lock.
686 2) check if we are dmaster
687 3) if we are the dmaster then return handle
688 4) if not dmaster then ask ctdb daemon to make us dmaster, and wait for
690 5) when we get the reply, goto (1)
693 h = talloc_zero(mem_ctx, struct ctdb_record_handle);
698 h->ctdb_db = ctdb_db;
700 h->key.dptr = talloc_memdup(h, key.dptr, key.dsize);
701 if (h->key.dptr == NULL) {
707 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: key=%*.*s\n", (int)key.dsize, (int)key.dsize,
708 (const char *)key.dptr));
711 /* step 1 - get the chain lock */
712 ret = ctdb_ltdb_lock(ctdb_db, key);
714 DEBUG(DEBUG_ERR, (__location__ " failed to lock ltdb record\n"));
719 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: got chain lock\n"));
721 talloc_set_destructor(h, fetch_lock_destructor);
723 ret = ctdb_ltdb_fetch(ctdb_db, key, &h->header, h, data);
725 /* when torturing, ensure we test the remote path */
726 if ((ctdb_db->ctdb->flags & CTDB_FLAG_TORTURE) &&
728 h->header.dmaster = (uint32_t)-1;
732 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: done local fetch\n"));
734 if (ret != 0 || h->header.dmaster != ctdb_db->ctdb->pnn) {
735 ctdb_ltdb_unlock(ctdb_db, key);
736 ret = ctdb_client_force_migration(ctdb_db, key);
738 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: force_migration failed\n"));
745 /* if this is a request for read/write and we have delegations
746 we have to revoke all delegations first
748 if ((h->header.dmaster == ctdb_db->ctdb->pnn) &&
749 (h->header.flags & CTDB_REC_RO_HAVE_DELEGATIONS)) {
750 ctdb_ltdb_unlock(ctdb_db, key);
751 ret = ctdb_client_force_migration(ctdb_db, key);
753 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
760 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: we are dmaster - done\n"));
765 get a readonly lock on a record, and return the records data. Blocks until it gets the lock
767 struct ctdb_record_handle *
768 ctdb_fetch_readonly_lock(
769 struct ctdb_db_context *ctdb_db, TALLOC_CTX *mem_ctx,
770 TDB_DATA key, TDB_DATA *data,
774 struct ctdb_record_handle *h;
775 struct ctdb_ltdb_header *roheader = NULL;
777 h = talloc_zero(mem_ctx, struct ctdb_record_handle);
782 h->ctdb_db = ctdb_db;
784 h->key.dptr = talloc_memdup(h, key.dptr, key.dsize);
785 if (h->key.dptr == NULL) {
796 talloc_free(roheader);
799 talloc_free(data->dptr);
803 /* Lock the record/chain */
804 ret = ctdb_ltdb_lock(ctdb_db, key);
806 DEBUG(DEBUG_ERR, (__location__ " failed to lock ltdb record\n"));
811 talloc_set_destructor(h, fetch_lock_destructor);
813 /* Check if record exists yet in the TDB */
814 ret = ctdb_ltdb_fetch_with_header(ctdb_db, key, &h->header, h, data);
816 ctdb_ltdb_unlock(ctdb_db, key);
817 ret = ctdb_client_force_migration(ctdb_db, key);
819 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
826 /* if this is a request for read/write and we have delegations
827 we have to revoke all delegations first
830 && (h->header.dmaster == ctdb_db->ctdb->pnn)
831 && (h->header.flags & CTDB_REC_RO_HAVE_DELEGATIONS)) {
832 ctdb_ltdb_unlock(ctdb_db, key);
833 ret = ctdb_client_force_migration(ctdb_db, key);
835 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
842 /* if we are dmaster, just return the handle */
843 if (h->header.dmaster == ctdb_db->ctdb->pnn) {
847 if (read_only != 0) {
848 TDB_DATA rodata = {NULL, 0};
850 if ((h->header.flags & CTDB_REC_RO_HAVE_READONLY)
851 || (h->header.flags & CTDB_REC_RO_HAVE_DELEGATIONS)) {
855 ctdb_ltdb_unlock(ctdb_db, key);
856 ret = ctdb_client_fetch_readonly(ctdb_db, key, h, &roheader, &rodata);
858 DEBUG(DEBUG_ERR,("ctdb_fetch_readonly_lock: failed. force migration and try again\n"));
859 ret = ctdb_client_force_migration(ctdb_db, key);
861 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
869 if (!(roheader->flags&CTDB_REC_RO_HAVE_READONLY)) {
870 ret = ctdb_client_force_migration(ctdb_db, key);
872 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
880 ret = ctdb_ltdb_lock(ctdb_db, key);
882 DEBUG(DEBUG_ERR, (__location__ " failed to lock ltdb record\n"));
887 ret = ctdb_ltdb_fetch_with_header(ctdb_db, key, &h->header, h, data);
889 ctdb_ltdb_unlock(ctdb_db, key);
891 ret = ctdb_client_force_migration(ctdb_db, key);
893 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
904 /* we are not dmaster and this was not a request for a readonly lock
905 * so unlock the record, migrate it and try again
907 ctdb_ltdb_unlock(ctdb_db, key);
908 ret = ctdb_client_force_migration(ctdb_db, key);
910 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: force_migration failed\n"));
918 store some data to the record that was locked with ctdb_fetch_lock()
920 int ctdb_record_store(struct ctdb_record_handle *h, TDB_DATA data)
922 if (h->ctdb_db->persistent) {
923 DEBUG(DEBUG_ERR, (__location__ " ctdb_record_store prohibited for persistent dbs\n"));
927 return ctdb_ltdb_store(h->ctdb_db, h->key, &h->header, data);
931 non-locking fetch of a record
933 int ctdb_fetch(struct ctdb_db_context *ctdb_db, TALLOC_CTX *mem_ctx,
934 TDB_DATA key, TDB_DATA *data)
936 struct ctdb_call call;
939 call.call_id = CTDB_FETCH_FUNC;
940 call.call_data.dptr = NULL;
941 call.call_data.dsize = 0;
944 ret = ctdb_call(ctdb_db, &call);
947 *data = call.reply_data;
948 talloc_steal(mem_ctx, data->dptr);
957 called when a control completes or timesout to invoke the callback
958 function the user provided
960 static void invoke_control_callback(struct tevent_context *ev,
961 struct tevent_timer *te,
962 struct timeval t, void *private_data)
964 struct ctdb_client_control_state *state;
965 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
968 state = talloc_get_type(private_data, struct ctdb_client_control_state);
969 talloc_steal(tmp_ctx, state);
971 ret = ctdb_control_recv(state->ctdb, state, state,
976 DEBUG(DEBUG_DEBUG,("ctdb_control_recv() failed, ignoring return code %d\n", ret));
979 talloc_free(tmp_ctx);
983 called when a CTDB_REPLY_CONTROL packet comes in in the client
985 This packet comes in response to a CTDB_REQ_CONTROL request packet. It
986 contains any reply data from the control
988 static void ctdb_client_reply_control(struct ctdb_context *ctdb,
989 struct ctdb_req_header *hdr)
991 struct ctdb_reply_control_old *c = (struct ctdb_reply_control_old *)hdr;
992 struct ctdb_client_control_state *state;
994 state = reqid_find(ctdb->idr, hdr->reqid, struct ctdb_client_control_state);
996 DEBUG(DEBUG_ERR,(__location__ " reqid %u not found\n", hdr->reqid));
1000 if (hdr->reqid != state->reqid) {
1001 /* we found a record but it was the wrong one */
1002 DEBUG(DEBUG_ERR, ("Dropped orphaned reply control with reqid:%u\n",hdr->reqid));
1006 state->outdata.dptr = c->data;
1007 state->outdata.dsize = c->datalen;
1008 state->status = c->status;
1010 state->errormsg = talloc_strndup(state,
1011 (char *)&c->data[c->datalen],
1015 /* state->outdata now uses resources from c so we don't want c
1016 to just dissappear from under us while state is still alive
1018 talloc_steal(state, c);
1020 state->state = CTDB_CONTROL_DONE;
1022 /* if we had a callback registered for this control, pull the response
1023 and call the callback.
1025 if (state->async.fn) {
1026 tevent_add_timer(ctdb->ev, state, timeval_zero(),
1027 invoke_control_callback, state);
1033 destroy a ctdb_control in client
1035 static int ctdb_client_control_destructor(struct ctdb_client_control_state *state)
1037 reqid_remove(state->ctdb->idr, state->reqid);
1042 /* time out handler for ctdb_control */
1043 static void control_timeout_func(struct tevent_context *ev,
1044 struct tevent_timer *te,
1045 struct timeval t, void *private_data)
1047 struct ctdb_client_control_state *state = talloc_get_type(private_data, struct ctdb_client_control_state);
1049 DEBUG(DEBUG_ERR,(__location__ " control timed out. reqid:%u opcode:%u "
1050 "dstnode:%u\n", state->reqid, state->c->opcode,
1051 state->c->hdr.destnode));
1053 state->state = CTDB_CONTROL_TIMEOUT;
1055 /* if we had a callback registered for this control, pull the response
1056 and call the callback.
1058 if (state->async.fn) {
1059 tevent_add_timer(state->ctdb->ev, state, timeval_zero(),
1060 invoke_control_callback, state);
1064 /* async version of send control request */
1065 struct ctdb_client_control_state *ctdb_control_send(struct ctdb_context *ctdb,
1066 uint32_t destnode, uint64_t srvid,
1067 uint32_t opcode, uint32_t flags, TDB_DATA data,
1068 TALLOC_CTX *mem_ctx,
1069 struct timeval *timeout,
1072 struct ctdb_client_control_state *state;
1074 struct ctdb_req_control_old *c;
1081 /* if the domain socket is not yet open, open it */
1082 if (ctdb->daemon.sd==-1) {
1083 ctdb_socket_connect(ctdb);
1086 state = talloc_zero(mem_ctx, struct ctdb_client_control_state);
1087 CTDB_NO_MEMORY_NULL(ctdb, state);
1090 state->reqid = reqid_new(ctdb->idr, state);
1091 state->state = CTDB_CONTROL_WAIT;
1092 state->errormsg = NULL;
1094 talloc_set_destructor(state, ctdb_client_control_destructor);
1096 len = offsetof(struct ctdb_req_control_old, data) + data.dsize;
1097 c = ctdbd_allocate_pkt(ctdb, state, CTDB_REQ_CONTROL,
1098 len, struct ctdb_req_control_old);
1100 CTDB_NO_MEMORY_NULL(ctdb, c);
1101 c->hdr.reqid = state->reqid;
1102 c->hdr.destnode = destnode;
1107 c->datalen = data.dsize;
1109 memcpy(&c->data[0], data.dptr, data.dsize);
1113 if (timeout && !timeval_is_zero(timeout)) {
1114 tevent_add_timer(ctdb->ev, state, *timeout,
1115 control_timeout_func, state);
1118 ret = ctdb_client_queue_pkt(ctdb, &(c->hdr));
1124 if (flags & CTDB_CTRL_FLAG_NOREPLY) {
1133 /* async version of receive control reply */
1134 int ctdb_control_recv(struct ctdb_context *ctdb,
1135 struct ctdb_client_control_state *state,
1136 TALLOC_CTX *mem_ctx,
1137 TDB_DATA *outdata, int32_t *status, char **errormsg)
1139 TALLOC_CTX *tmp_ctx;
1141 if (status != NULL) {
1144 if (errormsg != NULL) {
1148 if (state == NULL) {
1152 /* prevent double free of state */
1153 tmp_ctx = talloc_new(ctdb);
1154 talloc_steal(tmp_ctx, state);
1156 /* loop one event at a time until we either timeout or the control
1159 while (state->state == CTDB_CONTROL_WAIT) {
1160 tevent_loop_once(ctdb->ev);
1163 if (state->state != CTDB_CONTROL_DONE) {
1164 DEBUG(DEBUG_ERR,(__location__ " ctdb_control_recv failed\n"));
1165 if (state->async.fn) {
1166 state->async.fn(state);
1168 talloc_free(tmp_ctx);
1172 if (state->errormsg) {
1173 int s = (state->status == 0 ? -1 : state->status);
1174 DEBUG(DEBUG_ERR,("ctdb_control error: '%s'\n", state->errormsg));
1176 (*errormsg) = talloc_move(mem_ctx, &state->errormsg);
1178 if (state->async.fn) {
1179 state->async.fn(state);
1181 talloc_free(tmp_ctx);
1186 *outdata = state->outdata;
1187 outdata->dptr = talloc_memdup(mem_ctx, outdata->dptr, outdata->dsize);
1191 *status = state->status;
1194 if (state->async.fn) {
1195 state->async.fn(state);
1198 talloc_free(tmp_ctx);
1205 send a ctdb control message
1206 timeout specifies how long we should wait for a reply.
1207 if timeout is NULL we wait indefinitely
1209 int ctdb_control(struct ctdb_context *ctdb, uint32_t destnode, uint64_t srvid,
1210 uint32_t opcode, uint32_t flags, TDB_DATA data,
1211 TALLOC_CTX *mem_ctx, TDB_DATA *outdata, int32_t *status,
1212 struct timeval *timeout,
1215 struct ctdb_client_control_state *state;
1217 state = ctdb_control_send(ctdb, destnode, srvid, opcode,
1218 flags, data, mem_ctx,
1221 /* FIXME: Error conditions in ctdb_control_send return NULL without
1222 * setting errormsg. So, there is no way to distinguish between sucess
1223 * and failure when CTDB_CTRL_FLAG_NOREPLY is set */
1224 if (flags & CTDB_CTRL_FLAG_NOREPLY) {
1225 if (status != NULL) {
1231 return ctdb_control_recv(ctdb, state, mem_ctx, outdata, status,
1239 a process exists call. Returns 0 if process exists, -1 otherwise
1241 int ctdb_ctrl_process_exists(struct ctdb_context *ctdb, uint32_t destnode, pid_t pid)
1247 data.dptr = (uint8_t*)&pid;
1248 data.dsize = sizeof(pid);
1250 ret = ctdb_control(ctdb, destnode, 0,
1251 CTDB_CONTROL_PROCESS_EXISTS, 0, data,
1252 NULL, NULL, &status, NULL, NULL);
1254 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for process_exists failed\n"));
1262 get remote statistics
1264 int ctdb_ctrl_statistics(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_statistics *status)
1270 ret = ctdb_control(ctdb, destnode, 0,
1271 CTDB_CONTROL_STATISTICS, 0, tdb_null,
1272 ctdb, &data, &res, NULL, NULL);
1273 if (ret != 0 || res != 0) {
1274 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for statistics failed\n"));
1278 if (data.dsize != sizeof(struct ctdb_statistics)) {
1279 DEBUG(DEBUG_ERR,(__location__ " Wrong statistics size %u - expected %u\n",
1280 (unsigned)data.dsize, (unsigned)sizeof(struct ctdb_statistics)));
1284 *status = *(struct ctdb_statistics *)data.dptr;
1285 talloc_free(data.dptr);
1293 int ctdb_ctrl_dbstatistics(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid,
1294 TALLOC_CTX *mem_ctx, struct ctdb_db_statistics_old **dbstat)
1297 TDB_DATA indata, outdata;
1299 struct ctdb_db_statistics_old *wire, *s;
1303 indata.dptr = (uint8_t *)&dbid;
1304 indata.dsize = sizeof(dbid);
1306 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_DB_STATISTICS,
1307 0, indata, ctdb, &outdata, &res, NULL, NULL);
1308 if (ret != 0 || res != 0) {
1309 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for dbstatistics failed\n"));
1313 if (outdata.dsize < offsetof(struct ctdb_db_statistics_old, hot_keys_wire)) {
1314 DEBUG(DEBUG_ERR,(__location__ " Wrong dbstatistics size %zi - expected >= %lu\n",
1316 (long unsigned int)sizeof(struct ctdb_statistics)));
1320 s = talloc_zero(mem_ctx, struct ctdb_db_statistics_old);
1322 talloc_free(outdata.dptr);
1323 CTDB_NO_MEMORY(ctdb, s);
1326 wire = (struct ctdb_db_statistics_old *)outdata.dptr;
1327 memcpy(s, wire, offsetof(struct ctdb_db_statistics_old, hot_keys_wire));
1328 ptr = &wire->hot_keys_wire[0];
1329 for (i=0; i<wire->num_hot_keys; i++) {
1330 s->hot_keys[i].key.dptr = talloc_size(mem_ctx, s->hot_keys[i].key.dsize);
1331 if (s->hot_keys[i].key.dptr == NULL) {
1332 talloc_free(outdata.dptr);
1333 CTDB_NO_MEMORY(ctdb, s->hot_keys[i].key.dptr);
1336 memcpy(s->hot_keys[i].key.dptr, ptr, s->hot_keys[i].key.dsize);
1337 ptr += wire->hot_keys[i].key.dsize;
1340 talloc_free(outdata.dptr);
1346 shutdown a remote ctdb node
1348 int ctdb_ctrl_shutdown(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
1350 struct ctdb_client_control_state *state;
1352 state = ctdb_control_send(ctdb, destnode, 0,
1353 CTDB_CONTROL_SHUTDOWN, 0, tdb_null,
1354 NULL, &timeout, NULL);
1355 if (state == NULL) {
1356 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for shutdown failed\n"));
1364 get vnn map from a remote node
1366 int ctdb_ctrl_getvnnmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_vnn_map **vnnmap)
1371 struct ctdb_vnn_map_wire *map;
1373 ret = ctdb_control(ctdb, destnode, 0,
1374 CTDB_CONTROL_GETVNNMAP, 0, tdb_null,
1375 mem_ctx, &outdata, &res, &timeout, NULL);
1376 if (ret != 0 || res != 0) {
1377 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getvnnmap failed\n"));
1381 map = (struct ctdb_vnn_map_wire *)outdata.dptr;
1382 if (outdata.dsize < offsetof(struct ctdb_vnn_map_wire, map) ||
1383 outdata.dsize != map->size*sizeof(uint32_t) + offsetof(struct ctdb_vnn_map_wire, map)) {
1384 DEBUG(DEBUG_ERR,("Bad vnn map size received in ctdb_ctrl_getvnnmap\n"));
1388 (*vnnmap) = talloc(mem_ctx, struct ctdb_vnn_map);
1389 CTDB_NO_MEMORY(ctdb, *vnnmap);
1390 (*vnnmap)->generation = map->generation;
1391 (*vnnmap)->size = map->size;
1392 (*vnnmap)->map = talloc_array(*vnnmap, uint32_t, map->size);
1394 CTDB_NO_MEMORY(ctdb, (*vnnmap)->map);
1395 memcpy((*vnnmap)->map, map->map, sizeof(uint32_t)*map->size);
1396 talloc_free(outdata.dptr);
1403 get the recovery mode of a remote node
1405 struct ctdb_client_control_state *
1406 ctdb_ctrl_getrecmode_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode)
1408 return ctdb_control_send(ctdb, destnode, 0,
1409 CTDB_CONTROL_GET_RECMODE, 0, tdb_null,
1410 mem_ctx, &timeout, NULL);
1413 int ctdb_ctrl_getrecmode_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *recmode)
1418 ret = ctdb_control_recv(ctdb, state, mem_ctx, NULL, &res, NULL);
1420 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_getrecmode_recv failed\n"));
1425 *recmode = (uint32_t)res;
1431 int ctdb_ctrl_getrecmode(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, uint32_t *recmode)
1433 struct ctdb_client_control_state *state;
1435 state = ctdb_ctrl_getrecmode_send(ctdb, mem_ctx, timeout, destnode);
1436 return ctdb_ctrl_getrecmode_recv(ctdb, mem_ctx, state, recmode);
1443 set the recovery mode of a remote node
1445 int ctdb_ctrl_setrecmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmode)
1451 data.dsize = sizeof(uint32_t);
1452 data.dptr = (unsigned char *)&recmode;
1454 ret = ctdb_control(ctdb, destnode, 0,
1455 CTDB_CONTROL_SET_RECMODE, 0, data,
1456 NULL, NULL, &res, &timeout, NULL);
1457 if (ret != 0 || res != 0) {
1458 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setrecmode failed\n"));
1468 get the recovery master of a remote node
1470 struct ctdb_client_control_state *
1471 ctdb_ctrl_getrecmaster_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx,
1472 struct timeval timeout, uint32_t destnode)
1474 return ctdb_control_send(ctdb, destnode, 0,
1475 CTDB_CONTROL_GET_RECMASTER, 0, tdb_null,
1476 mem_ctx, &timeout, NULL);
1479 int ctdb_ctrl_getrecmaster_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *recmaster)
1484 ret = ctdb_control_recv(ctdb, state, mem_ctx, NULL, &res, NULL);
1486 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_getrecmaster_recv failed\n"));
1491 *recmaster = (uint32_t)res;
1497 int ctdb_ctrl_getrecmaster(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, uint32_t *recmaster)
1499 struct ctdb_client_control_state *state;
1501 state = ctdb_ctrl_getrecmaster_send(ctdb, mem_ctx, timeout, destnode);
1502 return ctdb_ctrl_getrecmaster_recv(ctdb, mem_ctx, state, recmaster);
1507 set the recovery master of a remote node
1509 int ctdb_ctrl_setrecmaster(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmaster)
1516 data.dsize = sizeof(uint32_t);
1517 data.dptr = (unsigned char *)&recmaster;
1519 ret = ctdb_control(ctdb, destnode, 0,
1520 CTDB_CONTROL_SET_RECMASTER, 0, data,
1521 NULL, NULL, &res, &timeout, NULL);
1522 if (ret != 0 || res != 0) {
1523 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setrecmaster failed\n"));
1532 get a list of databases off a remote node
1534 int ctdb_ctrl_getdbmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
1535 TALLOC_CTX *mem_ctx, struct ctdb_dbid_map_old **dbmap)
1541 ret = ctdb_control(ctdb, destnode, 0,
1542 CTDB_CONTROL_GET_DBMAP, 0, tdb_null,
1543 mem_ctx, &outdata, &res, &timeout, NULL);
1544 if (ret != 0 || res != 0) {
1545 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getdbmap failed ret:%d res:%d\n", ret, res));
1549 *dbmap = (struct ctdb_dbid_map_old *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
1550 talloc_free(outdata.dptr);
1556 get a list of nodes (vnn and flags ) from a remote node
1558 int ctdb_ctrl_getnodemap(struct ctdb_context *ctdb,
1559 struct timeval timeout, uint32_t destnode,
1560 TALLOC_CTX *mem_ctx, struct ctdb_node_map_old **nodemap)
1566 ret = ctdb_control(ctdb, destnode, 0,
1567 CTDB_CONTROL_GET_NODEMAP, 0, tdb_null,
1568 mem_ctx, &outdata, &res, &timeout, NULL);
1569 if (ret != 0 || res != 0 || outdata.dsize == 0) {
1570 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getnodes failed ret:%d res:%d\n", ret, res));
1574 *nodemap = (struct ctdb_node_map_old *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
1575 talloc_free(outdata.dptr);
1580 load nodes file on a remote node and return as a node map
1582 int ctdb_ctrl_getnodesfile(struct ctdb_context *ctdb,
1583 struct timeval timeout, uint32_t destnode,
1584 TALLOC_CTX *mem_ctx, struct ctdb_node_map_old **nodemap)
1590 ret = ctdb_control(ctdb, destnode, 0,
1591 CTDB_CONTROL_GET_NODES_FILE, 0, tdb_null,
1592 mem_ctx, &outdata, &res, &timeout, NULL);
1593 if (ret != 0 || res != 0 || outdata.dsize == 0) {
1594 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getnodes failed ret:%d res:%d\n", ret, res));
1598 *nodemap = (struct ctdb_node_map_old *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
1599 talloc_free(outdata.dptr);
1605 drop the transport, reload the nodes file and restart the transport
1607 int ctdb_ctrl_reload_nodes_file(struct ctdb_context *ctdb,
1608 struct timeval timeout, uint32_t destnode)
1613 ret = ctdb_control(ctdb, destnode, 0,
1614 CTDB_CONTROL_RELOAD_NODES_FILE, 0, tdb_null,
1615 NULL, NULL, &res, &timeout, NULL);
1616 if (ret != 0 || res != 0) {
1617 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for reloadnodesfile failed\n"));
1626 set vnn map on a node
1628 int ctdb_ctrl_setvnnmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
1629 TALLOC_CTX *mem_ctx, struct ctdb_vnn_map *vnnmap)
1634 struct ctdb_vnn_map_wire *map;
1637 len = offsetof(struct ctdb_vnn_map_wire, map) + sizeof(uint32_t)*vnnmap->size;
1638 map = talloc_size(mem_ctx, len);
1639 CTDB_NO_MEMORY(ctdb, map);
1641 map->generation = vnnmap->generation;
1642 map->size = vnnmap->size;
1643 memcpy(map->map, vnnmap->map, sizeof(uint32_t)*map->size);
1646 data.dptr = (uint8_t *)map;
1648 ret = ctdb_control(ctdb, destnode, 0,
1649 CTDB_CONTROL_SETVNNMAP, 0, data,
1650 NULL, NULL, &res, &timeout, NULL);
1651 if (ret != 0 || res != 0) {
1652 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setvnnmap failed\n"));
1663 async send for pull database
1665 struct ctdb_client_control_state *ctdb_ctrl_pulldb_send(
1666 struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid,
1667 uint32_t lmaster, TALLOC_CTX *mem_ctx, struct timeval timeout)
1670 struct ctdb_pulldb *pull;
1671 struct ctdb_client_control_state *state;
1673 pull = talloc(mem_ctx, struct ctdb_pulldb);
1674 CTDB_NO_MEMORY_NULL(ctdb, pull);
1677 pull->lmaster = lmaster;
1679 indata.dsize = sizeof(struct ctdb_pulldb);
1680 indata.dptr = (unsigned char *)pull;
1682 state = ctdb_control_send(ctdb, destnode, 0,
1683 CTDB_CONTROL_PULL_DB, 0, indata,
1684 mem_ctx, &timeout, NULL);
1691 async recv for pull database
1693 int ctdb_ctrl_pulldb_recv(
1694 struct ctdb_context *ctdb,
1695 TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state,
1701 ret = ctdb_control_recv(ctdb, state, mem_ctx, outdata, &res, NULL);
1702 if ( (ret != 0) || (res != 0) ){
1703 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_pulldb_recv failed\n"));
1711 pull all keys and records for a specific database on a node
1713 int ctdb_ctrl_pulldb(struct ctdb_context *ctdb, uint32_t destnode,
1714 uint32_t dbid, uint32_t lmaster,
1715 TALLOC_CTX *mem_ctx, struct timeval timeout,
1718 struct ctdb_client_control_state *state;
1720 state = ctdb_ctrl_pulldb_send(ctdb, destnode, dbid, lmaster, mem_ctx,
1723 return ctdb_ctrl_pulldb_recv(ctdb, mem_ctx, state, outdata);
1728 change dmaster for all keys in the database to the new value
1730 int ctdb_ctrl_setdmaster(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
1731 TALLOC_CTX *mem_ctx, uint32_t dbid, uint32_t dmaster)
1737 indata.dsize = 2*sizeof(uint32_t);
1738 indata.dptr = (unsigned char *)talloc_array(mem_ctx, uint32_t, 2);
1740 ((uint32_t *)(&indata.dptr[0]))[0] = dbid;
1741 ((uint32_t *)(&indata.dptr[0]))[1] = dmaster;
1743 ret = ctdb_control(ctdb, destnode, 0,
1744 CTDB_CONTROL_SET_DMASTER, 0, indata,
1745 NULL, NULL, &res, &timeout, NULL);
1746 if (ret != 0 || res != 0) {
1747 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setdmaster failed\n"));
1755 ping a node, return number of clients connected
1757 int ctdb_ctrl_ping(struct ctdb_context *ctdb, uint32_t destnode)
1762 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_PING, 0,
1763 tdb_null, NULL, NULL, &res, NULL, NULL);
1770 int ctdb_ctrl_get_runstate(struct ctdb_context *ctdb,
1771 struct timeval timeout,
1779 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_RUNSTATE, 0,
1780 tdb_null, ctdb, &outdata, &res, &timeout, NULL);
1781 if (ret != 0 || res != 0) {
1782 DEBUG(DEBUG_ERR,("ctdb_control for get_runstate failed\n"));
1783 return ret != 0 ? ret : res;
1786 if (outdata.dsize != sizeof(uint32_t)) {
1787 DEBUG(DEBUG_ERR,("Invalid return data in get_runstate\n"));
1788 talloc_free(outdata.dptr);
1792 if (runstate != NULL) {
1793 *runstate = *(uint32_t *)outdata.dptr;
1795 talloc_free(outdata.dptr);
1801 find the real path to a ltdb
1803 int ctdb_ctrl_getdbpath(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t dbid, TALLOC_CTX *mem_ctx,
1810 data.dptr = (uint8_t *)&dbid;
1811 data.dsize = sizeof(dbid);
1813 ret = ctdb_control(ctdb, destnode, 0,
1814 CTDB_CONTROL_GETDBPATH, 0, data,
1815 mem_ctx, &data, &res, &timeout, NULL);
1816 if (ret != 0 || res != 0) {
1820 (*path) = talloc_strndup(mem_ctx, (const char *)data.dptr, data.dsize);
1821 if ((*path) == NULL) {
1825 talloc_free(data.dptr);
1831 find the name of a db
1833 int ctdb_ctrl_getdbname(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t dbid, TALLOC_CTX *mem_ctx,
1840 data.dptr = (uint8_t *)&dbid;
1841 data.dsize = sizeof(dbid);
1843 ret = ctdb_control(ctdb, destnode, 0,
1844 CTDB_CONTROL_GET_DBNAME, 0, data,
1845 mem_ctx, &data, &res, &timeout, NULL);
1846 if (ret != 0 || res != 0) {
1850 (*name) = talloc_strndup(mem_ctx, (const char *)data.dptr, data.dsize);
1851 if ((*name) == NULL) {
1855 talloc_free(data.dptr);
1861 get the health status of a db
1863 int ctdb_ctrl_getdbhealth(struct ctdb_context *ctdb,
1864 struct timeval timeout,
1866 uint32_t dbid, TALLOC_CTX *mem_ctx,
1867 const char **reason)
1873 data.dptr = (uint8_t *)&dbid;
1874 data.dsize = sizeof(dbid);
1876 ret = ctdb_control(ctdb, destnode, 0,
1877 CTDB_CONTROL_DB_GET_HEALTH, 0, data,
1878 mem_ctx, &data, &res, &timeout, NULL);
1879 if (ret != 0 || res != 0) {
1883 if (data.dsize == 0) {
1888 (*reason) = talloc_strndup(mem_ctx, (const char *)data.dptr, data.dsize);
1889 if ((*reason) == NULL) {
1893 talloc_free(data.dptr);
1899 * get db sequence number
1901 int ctdb_ctrl_getdbseqnum(struct ctdb_context *ctdb, struct timeval timeout,
1902 uint32_t destnode, uint32_t dbid, uint64_t *seqnum)
1906 TDB_DATA data, outdata;
1908 data.dptr = (uint8_t *)&dbid;
1909 data.dsize = sizeof(uint64_t); /* This is just wrong */
1911 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_DB_SEQNUM,
1912 0, data, ctdb, &outdata, &res, &timeout, NULL);
1913 if (ret != 0 || res != 0) {
1914 DEBUG(DEBUG_ERR,("ctdb_control for getdbesqnum failed\n"));
1918 if (outdata.dsize != sizeof(uint64_t)) {
1919 DEBUG(DEBUG_ERR,("Invalid return data in get_dbseqnum\n"));
1920 talloc_free(outdata.dptr);
1924 if (seqnum != NULL) {
1925 *seqnum = *(uint64_t *)outdata.dptr;
1927 talloc_free(outdata.dptr);
1935 int ctdb_ctrl_createdb(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
1936 TALLOC_CTX *mem_ctx, const char *name, bool persistent)
1941 uint64_t tdb_flags = 0;
1943 data.dptr = discard_const(name);
1944 data.dsize = strlen(name)+1;
1946 /* Make sure that volatile databases use jenkins hash */
1948 tdb_flags = TDB_INCOMPATIBLE_HASH;
1951 #ifdef TDB_MUTEX_LOCKING
1952 if (!persistent && ctdb->tunable.mutex_enabled == 1) {
1953 tdb_flags |= (TDB_MUTEX_LOCKING | TDB_CLEAR_IF_FIRST);
1957 ret = ctdb_control(ctdb, destnode, tdb_flags,
1958 persistent?CTDB_CONTROL_DB_ATTACH_PERSISTENT:CTDB_CONTROL_DB_ATTACH,
1960 mem_ctx, &data, &res, &timeout, NULL);
1962 if (ret != 0 || res != 0) {
1970 get debug level on a node
1972 int ctdb_ctrl_get_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, int32_t *level)
1978 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_DEBUG, 0, tdb_null,
1979 ctdb, &data, &res, NULL, NULL);
1980 if (ret != 0 || res != 0) {
1983 if (data.dsize != sizeof(int32_t)) {
1984 DEBUG(DEBUG_ERR,("Bad control reply size in ctdb_get_debuglevel (got %u)\n",
1985 (unsigned)data.dsize));
1988 *level = *(int32_t *)data.dptr;
1989 talloc_free(data.dptr);
1994 set debug level on a node
1996 int ctdb_ctrl_set_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, int32_t level)
2002 data.dptr = (uint8_t *)&level;
2003 data.dsize = sizeof(level);
2005 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SET_DEBUG, 0, data,
2006 NULL, NULL, &res, NULL, NULL);
2007 if (ret != 0 || res != 0) {
2015 get a list of connected nodes
2017 uint32_t *ctdb_get_connected_nodes(struct ctdb_context *ctdb,
2018 struct timeval timeout,
2019 TALLOC_CTX *mem_ctx,
2020 uint32_t *num_nodes)
2022 struct ctdb_node_map_old *map=NULL;
2028 ret = ctdb_ctrl_getnodemap(ctdb, timeout, CTDB_CURRENT_NODE, mem_ctx, &map);
2033 nodes = talloc_array(mem_ctx, uint32_t, map->num);
2034 if (nodes == NULL) {
2038 for (i=0;i<map->num;i++) {
2039 if (!(map->nodes[i].flags & NODE_FLAGS_DISCONNECTED)) {
2040 nodes[*num_nodes] = map->nodes[i].pnn;
2052 int ctdb_statistics_reset(struct ctdb_context *ctdb, uint32_t destnode)
2057 ret = ctdb_control(ctdb, destnode, 0,
2058 CTDB_CONTROL_STATISTICS_RESET, 0, tdb_null,
2059 NULL, NULL, &res, NULL, NULL);
2060 if (ret != 0 || res != 0) {
2061 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for reset statistics failed\n"));
2068 attach to a specific database - client call
2070 struct ctdb_db_context *ctdb_attach(struct ctdb_context *ctdb,
2071 struct timeval timeout,
2076 struct ctdb_db_context *ctdb_db;
2080 #ifdef TDB_MUTEX_LOCKING
2081 uint32_t mutex_enabled = 0;
2084 ctdb_db = ctdb_db_handle(ctdb, name);
2089 ctdb_db = talloc_zero(ctdb, struct ctdb_db_context);
2090 CTDB_NO_MEMORY_NULL(ctdb, ctdb_db);
2092 ctdb_db->ctdb = ctdb;
2093 ctdb_db->db_name = talloc_strdup(ctdb_db, name);
2094 CTDB_NO_MEMORY_NULL(ctdb, ctdb_db->db_name);
2096 data.dptr = discard_const(name);
2097 data.dsize = strlen(name)+1;
2099 /* CTDB has switched to using jenkins hash for volatile databases.
2100 * Even if tdb_flags do not explicitly mention TDB_INCOMPATIBLE_HASH,
2104 tdb_flags |= TDB_INCOMPATIBLE_HASH;
2107 #ifdef TDB_MUTEX_LOCKING
2109 ret = ctdb_ctrl_get_tunable(ctdb, timeval_current_ofs(3,0),
2114 DEBUG(DEBUG_WARNING, ("Assuming no mutex support.\n"));
2117 if (mutex_enabled == 1) {
2118 tdb_flags |= (TDB_MUTEX_LOCKING | TDB_CLEAR_IF_FIRST);
2123 /* tell ctdb daemon to attach */
2124 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, tdb_flags,
2125 persistent?CTDB_CONTROL_DB_ATTACH_PERSISTENT:CTDB_CONTROL_DB_ATTACH,
2126 0, data, ctdb_db, &data, &res, NULL, NULL);
2127 if (ret != 0 || res != 0 || data.dsize != sizeof(uint32_t)) {
2128 DEBUG(DEBUG_ERR,("Failed to attach to database '%s'\n", name));
2129 talloc_free(ctdb_db);
2133 ctdb_db->db_id = *(uint32_t *)data.dptr;
2134 talloc_free(data.dptr);
2136 ret = ctdb_ctrl_getdbpath(ctdb, timeout, CTDB_CURRENT_NODE, ctdb_db->db_id, ctdb_db, &ctdb_db->db_path);
2138 DEBUG(DEBUG_ERR,("Failed to get dbpath for database '%s'\n", name));
2139 talloc_free(ctdb_db);
2144 tdb_flags = TDB_DEFAULT;
2146 tdb_flags = TDB_NOSYNC;
2147 #ifdef TDB_MUTEX_LOCKING
2148 if (mutex_enabled) {
2149 tdb_flags |= (TDB_MUTEX_LOCKING | TDB_CLEAR_IF_FIRST);
2153 if (ctdb->valgrinding) {
2154 tdb_flags |= TDB_NOMMAP;
2156 tdb_flags |= TDB_DISALLOW_NESTING;
2158 ctdb_db->ltdb = tdb_wrap_open(ctdb_db, ctdb_db->db_path, 0, tdb_flags,
2160 if (ctdb_db->ltdb == NULL) {
2161 ctdb_set_error(ctdb, "Failed to open tdb '%s'\n", ctdb_db->db_path);
2162 talloc_free(ctdb_db);
2166 ctdb_db->persistent = persistent;
2168 DLIST_ADD(ctdb->db_list, ctdb_db);
2170 /* add well known functions */
2171 ctdb_set_call(ctdb_db, ctdb_null_func, CTDB_NULL_FUNC);
2172 ctdb_set_call(ctdb_db, ctdb_fetch_func, CTDB_FETCH_FUNC);
2173 ctdb_set_call(ctdb_db, ctdb_fetch_with_header_func, CTDB_FETCH_WITH_HEADER_FUNC);
2179 * detach from a specific database - client call
2181 int ctdb_detach(struct ctdb_context *ctdb, uint32_t db_id)
2187 data.dsize = sizeof(db_id);
2188 data.dptr = (uint8_t *)&db_id;
2190 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_DB_DETACH,
2191 0, data, NULL, NULL, &status, NULL, NULL);
2192 if (ret != 0 || status != 0) {
2199 setup a call for a database
2201 int ctdb_set_call(struct ctdb_db_context *ctdb_db, ctdb_fn_t fn, uint32_t id)
2203 struct ctdb_registered_call *call;
2205 /* register locally */
2206 call = talloc(ctdb_db, struct ctdb_registered_call);
2210 DLIST_ADD(ctdb_db->calls, call);
2215 struct traverse_state {
2218 ctdb_traverse_func fn;
2220 bool listemptyrecords;
2224 called on each key during a ctdb_traverse
2226 static void traverse_handler(uint64_t srvid, TDB_DATA data, void *p)
2228 struct traverse_state *state = (struct traverse_state *)p;
2229 struct ctdb_rec_data_old *d = (struct ctdb_rec_data_old *)data.dptr;
2232 if (data.dsize < sizeof(uint32_t) || d->length != data.dsize) {
2233 DEBUG(DEBUG_ERR, ("Bad data size %u in traverse_handler\n",
2234 (unsigned)data.dsize));
2239 key.dsize = d->keylen;
2240 key.dptr = &d->data[0];
2241 data.dsize = d->datalen;
2242 data.dptr = &d->data[d->keylen];
2244 if (key.dsize == 0 && data.dsize == 0) {
2245 /* end of traverse */
2250 if (!state->listemptyrecords &&
2251 data.dsize == sizeof(struct ctdb_ltdb_header))
2253 /* empty records are deleted records in ctdb */
2257 if (state->fn(key, data, state->private_data) != 0) {
2265 * start a cluster wide traverse, calling the supplied fn on each record
2266 * return the number of records traversed, or -1 on error
2268 * Extendet variant with a flag to signal whether empty records should
2271 static int ctdb_traverse_ext(struct ctdb_db_context *ctdb_db,
2272 ctdb_traverse_func fn,
2273 bool withemptyrecords,
2277 struct ctdb_traverse_start_ext t;
2280 uint64_t srvid = (getpid() | 0xFLL<<60);
2281 struct traverse_state state;
2285 state.private_data = private_data;
2287 state.listemptyrecords = withemptyrecords;
2289 ret = ctdb_client_set_message_handler(ctdb_db->ctdb, srvid, traverse_handler, &state);
2291 DEBUG(DEBUG_ERR,("Failed to setup traverse handler\n"));
2295 t.db_id = ctdb_db->db_id;
2298 t.withemptyrecords = withemptyrecords;
2300 data.dptr = (uint8_t *)&t;
2301 data.dsize = sizeof(t);
2303 ret = ctdb_control(ctdb_db->ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_TRAVERSE_START_EXT, 0,
2304 data, NULL, NULL, &status, NULL, NULL);
2305 if (ret != 0 || status != 0) {
2306 DEBUG(DEBUG_ERR,("ctdb_traverse_all failed\n"));
2307 ctdb_client_remove_message_handler(ctdb_db->ctdb, srvid, &state);
2311 while (!state.done) {
2312 tevent_loop_once(ctdb_db->ctdb->ev);
2315 ret = ctdb_client_remove_message_handler(ctdb_db->ctdb, srvid, &state);
2317 DEBUG(DEBUG_ERR,("Failed to remove ctdb_traverse handler\n"));
2325 * start a cluster wide traverse, calling the supplied fn on each record
2326 * return the number of records traversed, or -1 on error
2328 * Standard version which does not list the empty records:
2329 * These are considered deleted.
2331 int ctdb_traverse(struct ctdb_db_context *ctdb_db, ctdb_traverse_func fn, void *private_data)
2333 return ctdb_traverse_ext(ctdb_db, fn, false, private_data);
2336 #define ISASCII(x) (isprint(x) && !strchr("\"\\", (x)))
2338 called on each key during a catdb
2340 int ctdb_dumpdb_record(TDB_DATA key, TDB_DATA data, void *p)
2343 struct ctdb_dump_db_context *c = (struct ctdb_dump_db_context *)p;
2345 struct ctdb_ltdb_header *h = (struct ctdb_ltdb_header *)data.dptr;
2347 fprintf(f, "key(%u) = \"", (unsigned)key.dsize);
2348 for (i=0;i<key.dsize;i++) {
2349 if (ISASCII(key.dptr[i])) {
2350 fprintf(f, "%c", key.dptr[i]);
2352 fprintf(f, "\\%02X", key.dptr[i]);
2357 fprintf(f, "dmaster: %u\n", h->dmaster);
2358 fprintf(f, "rsn: %llu\n", (unsigned long long)h->rsn);
2360 if (c->printlmaster && c->ctdb->vnn_map != NULL) {
2361 fprintf(f, "lmaster: %u\n", ctdb_lmaster(c->ctdb, &key));
2365 fprintf(f, "hash: 0x%08x\n", ctdb_hash(&key));
2368 if (c->printrecordflags) {
2369 fprintf(f, "flags: 0x%08x", h->flags);
2370 if (h->flags & CTDB_REC_FLAG_MIGRATED_WITH_DATA) printf(" MIGRATED_WITH_DATA");
2371 if (h->flags & CTDB_REC_FLAG_VACUUM_MIGRATED) printf(" VACUUM_MIGRATED");
2372 if (h->flags & CTDB_REC_FLAG_AUTOMATIC) printf(" AUTOMATIC");
2373 if (h->flags & CTDB_REC_RO_HAVE_DELEGATIONS) printf(" RO_HAVE_DELEGATIONS");
2374 if (h->flags & CTDB_REC_RO_HAVE_READONLY) printf(" RO_HAVE_READONLY");
2375 if (h->flags & CTDB_REC_RO_REVOKING_READONLY) printf(" RO_REVOKING_READONLY");
2376 if (h->flags & CTDB_REC_RO_REVOKE_COMPLETE) printf(" RO_REVOKE_COMPLETE");
2380 if (c->printdatasize) {
2381 fprintf(f, "data size: %u\n", (unsigned)data.dsize);
2383 fprintf(f, "data(%u) = \"", (unsigned)(data.dsize - sizeof(*h)));
2384 for (i=sizeof(*h);i<data.dsize;i++) {
2385 if (ISASCII(data.dptr[i])) {
2386 fprintf(f, "%c", data.dptr[i]);
2388 fprintf(f, "\\%02X", data.dptr[i]);
2400 convenience function to list all keys to stdout
2402 int ctdb_dump_db(struct ctdb_db_context *ctdb_db,
2403 struct ctdb_dump_db_context *ctx)
2405 return ctdb_traverse_ext(ctdb_db, ctdb_dumpdb_record,
2406 ctx->printemptyrecords, ctx);
2410 get the pid of a ctdb daemon
2412 int ctdb_ctrl_getpid(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *pid)
2417 ret = ctdb_control(ctdb, destnode, 0,
2418 CTDB_CONTROL_GET_PID, 0, tdb_null,
2419 NULL, NULL, &res, &timeout, NULL);
2421 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getpid failed\n"));
2432 async freeze send control
2434 struct ctdb_client_control_state *
2435 ctdb_ctrl_freeze_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, uint32_t priority)
2437 return ctdb_control_send(ctdb, destnode, priority,
2438 CTDB_CONTROL_FREEZE, 0, tdb_null,
2439 mem_ctx, &timeout, NULL);
2443 async freeze recv control
2445 int ctdb_ctrl_freeze_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state)
2450 ret = ctdb_control_recv(ctdb, state, mem_ctx, NULL, &res, NULL);
2451 if ( (ret != 0) || (res != 0) ){
2452 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_freeze_recv failed\n"));
2460 freeze databases of a certain priority
2462 int ctdb_ctrl_freeze_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t priority)
2464 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2465 struct ctdb_client_control_state *state;
2468 state = ctdb_ctrl_freeze_send(ctdb, tmp_ctx, timeout, destnode, priority);
2469 ret = ctdb_ctrl_freeze_recv(ctdb, tmp_ctx, state);
2470 talloc_free(tmp_ctx);
2475 /* Freeze all databases */
2476 int ctdb_ctrl_freeze(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2480 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
2481 if (ctdb_ctrl_freeze_priority(ctdb, timeout, destnode, i) != 0) {
2489 thaw databases of a certain priority
2491 int ctdb_ctrl_thaw_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t priority)
2496 ret = ctdb_control(ctdb, destnode, priority,
2497 CTDB_CONTROL_THAW, 0, tdb_null,
2498 NULL, NULL, &res, &timeout, NULL);
2499 if (ret != 0 || res != 0) {
2500 DEBUG(DEBUG_ERR,(__location__ " ctdb_control thaw failed\n"));
2507 /* thaw all databases */
2508 int ctdb_ctrl_thaw(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2510 return ctdb_ctrl_thaw_priority(ctdb, timeout, destnode, 0);
2514 get pnn of a node, or -1
2516 int ctdb_ctrl_getpnn(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2521 ret = ctdb_control(ctdb, destnode, 0,
2522 CTDB_CONTROL_GET_PNN, 0, tdb_null,
2523 NULL, NULL, &res, &timeout, NULL);
2525 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getpnn failed\n"));
2533 get the monitoring mode of a remote node
2535 int ctdb_ctrl_getmonmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *monmode)
2540 ret = ctdb_control(ctdb, destnode, 0,
2541 CTDB_CONTROL_GET_MONMODE, 0, tdb_null,
2542 NULL, NULL, &res, &timeout, NULL);
2544 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getmonmode failed\n"));
2555 set the monitoring mode of a remote node to active
2557 int ctdb_ctrl_enable_monmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2562 ret = ctdb_control(ctdb, destnode, 0,
2563 CTDB_CONTROL_ENABLE_MONITOR, 0, tdb_null,
2564 NULL, NULL,NULL, &timeout, NULL);
2566 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for enable_monitor failed\n"));
2576 set the monitoring mode of a remote node to disable
2578 int ctdb_ctrl_disable_monmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2583 ret = ctdb_control(ctdb, destnode, 0,
2584 CTDB_CONTROL_DISABLE_MONITOR, 0, tdb_null,
2585 NULL, NULL, NULL, &timeout, NULL);
2587 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for disable_monitor failed\n"));
2599 sent to a node to make it take over an ip address
2601 int ctdb_ctrl_takeover_ip(struct ctdb_context *ctdb, struct timeval timeout,
2602 uint32_t destnode, struct ctdb_public_ip *ip)
2608 data.dsize = sizeof(*ip);
2609 data.dptr = (uint8_t *)ip;
2611 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_TAKEOVER_IP, 0,
2612 data, NULL, NULL, &res, &timeout, NULL);
2613 if (ret != 0 || res != 0) {
2614 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for takeover_ip failed\n"));
2623 sent to a node to make it release an ip address
2625 int ctdb_ctrl_release_ip(struct ctdb_context *ctdb, struct timeval timeout,
2626 uint32_t destnode, struct ctdb_public_ip *ip)
2632 data.dsize = sizeof(*ip);
2633 data.dptr = (uint8_t *)ip;
2635 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_RELEASE_IP, 0,
2636 data, NULL, NULL, &res, &timeout, NULL);
2637 if (ret != 0 || res != 0) {
2638 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for release_ip failed\n"));
2649 int ctdb_ctrl_get_tunable(struct ctdb_context *ctdb,
2650 struct timeval timeout,
2652 const char *name, uint32_t *value)
2654 struct ctdb_control_get_tunable *t;
2655 TDB_DATA data, outdata;
2659 data.dsize = offsetof(struct ctdb_control_get_tunable, name) + strlen(name) + 1;
2660 data.dptr = talloc_size(ctdb, data.dsize);
2661 CTDB_NO_MEMORY(ctdb, data.dptr);
2663 t = (struct ctdb_control_get_tunable *)data.dptr;
2664 t->length = strlen(name)+1;
2665 memcpy(t->name, name, t->length);
2667 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_TUNABLE, 0, data, ctdb,
2668 &outdata, &res, &timeout, NULL);
2669 talloc_free(data.dptr);
2670 if (ret != 0 || res != 0) {
2671 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get_tunable failed\n"));
2672 return ret != 0 ? ret : res;
2675 if (outdata.dsize != sizeof(uint32_t)) {
2676 DEBUG(DEBUG_ERR,("Invalid return data in get_tunable\n"));
2677 talloc_free(outdata.dptr);
2681 *value = *(uint32_t *)outdata.dptr;
2682 talloc_free(outdata.dptr);
2690 int ctdb_ctrl_set_tunable(struct ctdb_context *ctdb,
2691 struct timeval timeout,
2693 const char *name, uint32_t value)
2695 struct ctdb_tunable_old *t;
2700 data.dsize = offsetof(struct ctdb_tunable_old, name) + strlen(name) + 1;
2701 data.dptr = talloc_size(ctdb, data.dsize);
2702 CTDB_NO_MEMORY(ctdb, data.dptr);
2704 t = (struct ctdb_tunable_old *)data.dptr;
2705 t->length = strlen(name)+1;
2706 memcpy(t->name, name, t->length);
2709 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SET_TUNABLE, 0, data, NULL,
2710 NULL, &res, &timeout, NULL);
2711 talloc_free(data.dptr);
2712 if ((ret != 0) || (res == -1)) {
2713 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set_tunable failed\n"));
2723 int ctdb_ctrl_list_tunables(struct ctdb_context *ctdb,
2724 struct timeval timeout,
2726 TALLOC_CTX *mem_ctx,
2727 const char ***list, uint32_t *count)
2732 struct ctdb_control_list_tunable *t;
2735 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_LIST_TUNABLES, 0, tdb_null,
2736 mem_ctx, &outdata, &res, &timeout, NULL);
2737 if (ret != 0 || res != 0) {
2738 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for list_tunables failed\n"));
2742 t = (struct ctdb_control_list_tunable *)outdata.dptr;
2743 if (outdata.dsize < offsetof(struct ctdb_control_list_tunable, data) ||
2744 t->length > outdata.dsize-offsetof(struct ctdb_control_list_tunable, data)) {
2745 DEBUG(DEBUG_ERR,("Invalid data in list_tunables reply\n"));
2746 talloc_free(outdata.dptr);
2750 p = talloc_strndup(mem_ctx, (char *)t->data, t->length);
2751 CTDB_NO_MEMORY(ctdb, p);
2753 talloc_free(outdata.dptr);
2758 for (s=strtok_r(p, ":", &ptr); s; s=strtok_r(NULL, ":", &ptr)) {
2759 (*list) = talloc_realloc(mem_ctx, *list, const char *, 1+(*count));
2760 CTDB_NO_MEMORY(ctdb, *list);
2761 (*list)[*count] = talloc_strdup(*list, s);
2762 CTDB_NO_MEMORY(ctdb, (*list)[*count]);
2772 int ctdb_ctrl_get_public_ips_flags(struct ctdb_context *ctdb,
2773 struct timeval timeout, uint32_t destnode,
2774 TALLOC_CTX *mem_ctx,
2776 struct ctdb_public_ip_list_old **ips)
2782 ret = ctdb_control(ctdb, destnode, 0,
2783 CTDB_CONTROL_GET_PUBLIC_IPS, flags, tdb_null,
2784 mem_ctx, &outdata, &res, &timeout, NULL);
2785 if (ret != 0 || res != 0) {
2786 DEBUG(DEBUG_ERR,(__location__
2787 " ctdb_control for getpublicips failed ret:%d res:%d\n",
2792 *ips = (struct ctdb_public_ip_list_old *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
2793 talloc_free(outdata.dptr);
2798 int ctdb_ctrl_get_public_ips(struct ctdb_context *ctdb,
2799 struct timeval timeout, uint32_t destnode,
2800 TALLOC_CTX *mem_ctx,
2801 struct ctdb_public_ip_list_old **ips)
2803 return ctdb_ctrl_get_public_ips_flags(ctdb, timeout,
2808 int ctdb_ctrl_get_public_ip_info(struct ctdb_context *ctdb,
2809 struct timeval timeout, uint32_t destnode,
2810 TALLOC_CTX *mem_ctx,
2811 const ctdb_sock_addr *addr,
2812 struct ctdb_public_ip_info_old **_info)
2818 struct ctdb_public_ip_info_old *info;
2822 indata.dptr = discard_const_p(uint8_t, addr);
2823 indata.dsize = sizeof(*addr);
2825 ret = ctdb_control(ctdb, destnode, 0,
2826 CTDB_CONTROL_GET_PUBLIC_IP_INFO, 0, indata,
2827 mem_ctx, &outdata, &res, &timeout, NULL);
2828 if (ret != 0 || res != 0) {
2829 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
2830 "failed ret:%d res:%d\n",
2835 len = offsetof(struct ctdb_public_ip_info_old, ifaces);
2836 if (len > outdata.dsize) {
2837 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
2838 "returned invalid data with size %u > %u\n",
2839 (unsigned int)outdata.dsize,
2840 (unsigned int)len));
2841 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
2845 info = (struct ctdb_public_ip_info_old *)outdata.dptr;
2846 len += info->num*sizeof(struct ctdb_iface);
2848 if (len > outdata.dsize) {
2849 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
2850 "returned invalid data with size %u > %u\n",
2851 (unsigned int)outdata.dsize,
2852 (unsigned int)len));
2853 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
2857 /* make sure we null terminate the returned strings */
2858 for (i=0; i < info->num; i++) {
2859 info->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
2862 *_info = (struct ctdb_public_ip_info_old *)talloc_memdup(mem_ctx,
2865 talloc_free(outdata.dptr);
2866 if (*_info == NULL) {
2867 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
2868 "talloc_memdup size %u failed\n",
2869 (unsigned int)outdata.dsize));
2876 int ctdb_ctrl_get_ifaces(struct ctdb_context *ctdb,
2877 struct timeval timeout, uint32_t destnode,
2878 TALLOC_CTX *mem_ctx,
2879 struct ctdb_iface_list_old **_ifaces)
2884 struct ctdb_iface_list_old *ifaces;
2888 ret = ctdb_control(ctdb, destnode, 0,
2889 CTDB_CONTROL_GET_IFACES, 0, tdb_null,
2890 mem_ctx, &outdata, &res, &timeout, NULL);
2891 if (ret != 0 || res != 0) {
2892 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
2893 "failed ret:%d res:%d\n",
2898 len = offsetof(struct ctdb_iface_list_old, ifaces);
2899 if (len > outdata.dsize) {
2900 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
2901 "returned invalid data with size %u > %u\n",
2902 (unsigned int)outdata.dsize,
2903 (unsigned int)len));
2904 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
2908 ifaces = (struct ctdb_iface_list_old *)outdata.dptr;
2909 len += ifaces->num*sizeof(struct ctdb_iface);
2911 if (len > outdata.dsize) {
2912 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
2913 "returned invalid data with size %u > %u\n",
2914 (unsigned int)outdata.dsize,
2915 (unsigned int)len));
2916 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
2920 /* make sure we null terminate the returned strings */
2921 for (i=0; i < ifaces->num; i++) {
2922 ifaces->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
2925 *_ifaces = (struct ctdb_iface_list_old *)talloc_memdup(mem_ctx,
2928 talloc_free(outdata.dptr);
2929 if (*_ifaces == NULL) {
2930 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
2931 "talloc_memdup size %u failed\n",
2932 (unsigned int)outdata.dsize));
2939 int ctdb_ctrl_set_iface_link(struct ctdb_context *ctdb,
2940 struct timeval timeout, uint32_t destnode,
2941 TALLOC_CTX *mem_ctx,
2942 const struct ctdb_iface *info)
2948 indata.dptr = discard_const_p(uint8_t, info);
2949 indata.dsize = sizeof(*info);
2951 ret = ctdb_control(ctdb, destnode, 0,
2952 CTDB_CONTROL_SET_IFACE_LINK_STATE, 0, indata,
2953 mem_ctx, NULL, &res, &timeout, NULL);
2954 if (ret != 0 || res != 0) {
2955 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set iface link "
2956 "failed ret:%d res:%d\n",
2965 set/clear the permanent disabled bit on a remote node
2967 int ctdb_ctrl_modflags(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
2968 uint32_t set, uint32_t clear)
2972 struct ctdb_node_map_old *nodemap=NULL;
2973 struct ctdb_node_flag_change c;
2974 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2979 /* find the recovery master */
2980 ret = ctdb_ctrl_getrecmaster(ctdb, tmp_ctx, timeout, CTDB_CURRENT_NODE, &recmaster);
2982 DEBUG(DEBUG_ERR, (__location__ " Unable to get recmaster from local node\n"));
2983 talloc_free(tmp_ctx);
2988 /* read the node flags from the recmaster */
2989 ret = ctdb_ctrl_getnodemap(ctdb, timeout, recmaster, tmp_ctx, &nodemap);
2991 DEBUG(DEBUG_ERR, (__location__ " Unable to get nodemap from node %u\n", destnode));
2992 talloc_free(tmp_ctx);
2995 if (destnode >= nodemap->num) {
2996 DEBUG(DEBUG_ERR,(__location__ " Nodemap from recmaster does not contain node %d\n", destnode));
2997 talloc_free(tmp_ctx);
3002 c.old_flags = nodemap->nodes[destnode].flags;
3003 c.new_flags = c.old_flags;
3005 c.new_flags &= ~clear;
3007 data.dsize = sizeof(c);
3008 data.dptr = (unsigned char *)&c;
3010 /* send the flags update to all connected nodes */
3011 nodes = list_of_connected_nodes(ctdb, nodemap, tmp_ctx, true);
3013 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_MODIFY_FLAGS,
3015 timeout, false, data,
3018 DEBUG(DEBUG_ERR, (__location__ " Unable to update nodeflags on remote nodes\n"));
3020 talloc_free(tmp_ctx);
3024 talloc_free(tmp_ctx);
3032 int ctdb_ctrl_get_all_tunables(struct ctdb_context *ctdb,
3033 struct timeval timeout,
3035 struct ctdb_tunable_list *tunables)
3041 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_ALL_TUNABLES, 0, tdb_null, ctdb,
3042 &outdata, &res, &timeout, NULL);
3043 if (ret != 0 || res != 0) {
3044 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get all tunables failed\n"));
3048 if (outdata.dsize != sizeof(*tunables)) {
3049 DEBUG(DEBUG_ERR,(__location__ " bad data size %u in ctdb_ctrl_get_all_tunables should be %u\n",
3050 (unsigned)outdata.dsize, (unsigned)sizeof(*tunables)));
3054 *tunables = *(struct ctdb_tunable_list *)outdata.dptr;
3055 talloc_free(outdata.dptr);
3060 add a public address to a node
3062 int ctdb_ctrl_add_public_ip(struct ctdb_context *ctdb,
3063 struct timeval timeout, uint32_t destnode,
3064 struct ctdb_addr_info_old *pub)
3070 data.dsize = offsetof(struct ctdb_addr_info_old, iface) + pub->len;
3071 data.dptr = (unsigned char *)pub;
3073 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_ADD_PUBLIC_IP, 0, data, NULL,
3074 NULL, &res, &timeout, NULL);
3075 if (ret != 0 || res != 0) {
3076 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for add_public_ip failed\n"));
3084 delete a public address from a node
3086 int ctdb_ctrl_del_public_ip(struct ctdb_context *ctdb,
3087 struct timeval timeout, uint32_t destnode,
3088 struct ctdb_addr_info_old *pub)
3094 data.dsize = offsetof(struct ctdb_addr_info_old, iface) + pub->len;
3095 data.dptr = (unsigned char *)pub;
3097 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_DEL_PUBLIC_IP, 0, data, NULL,
3098 NULL, &res, &timeout, NULL);
3099 if (ret != 0 || res != 0) {
3100 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for del_public_ip failed\n"));
3110 int ctdb_ctrl_gratious_arp(struct ctdb_context *ctdb,
3111 struct timeval timeout, uint32_t destnode,
3112 ctdb_sock_addr *addr, const char *ifname)
3117 struct ctdb_addr_info_old *gratious_arp;
3118 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3121 len = strlen(ifname)+1;
3122 gratious_arp = talloc_size(tmp_ctx,
3123 offsetof(struct ctdb_addr_info_old, iface) + len);
3124 CTDB_NO_MEMORY(ctdb, gratious_arp);
3126 gratious_arp->addr = *addr;
3127 gratious_arp->len = len;
3128 memcpy(&gratious_arp->iface[0], ifname, len);
3131 data.dsize = offsetof(struct ctdb_addr_info_old, iface) + len;
3132 data.dptr = (unsigned char *)gratious_arp;
3134 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SEND_GRATUITOUS_ARP, 0, data, NULL,
3135 NULL, &res, &timeout, NULL);
3136 if (ret != 0 || res != 0) {
3137 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for gratious_arp failed\n"));
3138 talloc_free(tmp_ctx);
3142 talloc_free(tmp_ctx);
3147 get a list of all tcp tickles that a node knows about for a particular vnn
3149 int ctdb_ctrl_get_tcp_tickles(struct ctdb_context *ctdb,
3150 struct timeval timeout, uint32_t destnode,
3151 TALLOC_CTX *mem_ctx,
3152 ctdb_sock_addr *addr,
3153 struct ctdb_tickle_list_old **list)
3156 TDB_DATA data, outdata;
3159 data.dptr = (uint8_t*)addr;
3160 data.dsize = sizeof(ctdb_sock_addr);
3162 ret = ctdb_control(ctdb, destnode, 0,
3163 CTDB_CONTROL_GET_TCP_TICKLE_LIST, 0, data,
3164 mem_ctx, &outdata, &status, NULL, NULL);
3165 if (ret != 0 || status != 0) {
3166 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get tcp tickles failed\n"));
3170 *list = (struct ctdb_tickle_list_old *)outdata.dptr;
3176 initialise the ctdb daemon for client applications
3178 NOTE: In current code the daemon does not fork. This is for testing purposes only
3179 and to simplify the code.
3181 struct ctdb_context *ctdb_init(struct tevent_context *ev)
3184 struct ctdb_context *ctdb;
3186 ctdb = talloc_zero(ev, struct ctdb_context);
3188 DEBUG(DEBUG_ERR,(__location__ " talloc_zero failed.\n"));
3192 /* Wrap early to exercise code. */
3193 ret = reqid_init(ctdb, INT_MAX-200, &ctdb->idr);
3195 DEBUG(DEBUG_ERR, ("reqid_init failed (%s)\n", strerror(ret)));
3200 ret = srvid_init(ctdb, &ctdb->srv);
3202 DEBUG(DEBUG_ERR, ("srvid_init failed (%s)\n", strerror(ret)));
3207 ret = ctdb_set_socketname(ctdb, CTDB_SOCKET);
3209 DEBUG(DEBUG_ERR,(__location__ " ctdb_set_socketname failed.\n"));
3214 ctdb->statistics.statistics_start_time = timeval_current();
3223 void ctdb_set_flags(struct ctdb_context *ctdb, unsigned flags)
3225 ctdb->flags |= flags;
3229 setup the local socket name
3231 int ctdb_set_socketname(struct ctdb_context *ctdb, const char *socketname)
3233 ctdb->daemon.name = talloc_strdup(ctdb, socketname);
3234 CTDB_NO_MEMORY(ctdb, ctdb->daemon.name);
3239 const char *ctdb_get_socketname(struct ctdb_context *ctdb)
3241 return ctdb->daemon.name;
3245 return the pnn of this node
3247 uint32_t ctdb_get_pnn(struct ctdb_context *ctdb)
3254 get the uptime of a remote node
3256 struct ctdb_client_control_state *
3257 ctdb_ctrl_uptime_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode)
3259 return ctdb_control_send(ctdb, destnode, 0,
3260 CTDB_CONTROL_UPTIME, 0, tdb_null,
3261 mem_ctx, &timeout, NULL);
3264 int ctdb_ctrl_uptime_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, struct ctdb_uptime **uptime)
3270 ret = ctdb_control_recv(ctdb, state, mem_ctx, &outdata, &res, NULL);
3271 if (ret != 0 || res != 0) {
3272 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_uptime_recv failed\n"));
3276 *uptime = (struct ctdb_uptime *)talloc_steal(mem_ctx, outdata.dptr);
3281 int ctdb_ctrl_uptime(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, struct ctdb_uptime **uptime)
3283 struct ctdb_client_control_state *state;
3285 state = ctdb_ctrl_uptime_send(ctdb, mem_ctx, timeout, destnode);
3286 return ctdb_ctrl_uptime_recv(ctdb, mem_ctx, state, uptime);
3290 send a control to execute the "recovered" event script on a node
3292 int ctdb_ctrl_end_recovery(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
3297 ret = ctdb_control(ctdb, destnode, 0,
3298 CTDB_CONTROL_END_RECOVERY, 0, tdb_null,
3299 NULL, NULL, &status, &timeout, NULL);
3300 if (ret != 0 || status != 0) {
3301 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for end_recovery failed\n"));
3309 callback for the async helpers used when sending the same control
3310 to multiple nodes in parallell.
3312 static void async_callback(struct ctdb_client_control_state *state)
3314 struct client_async_data *data = talloc_get_type(state->async.private_data, struct client_async_data);
3315 struct ctdb_context *ctdb = talloc_get_type(state->ctdb, struct ctdb_context);
3319 uint32_t destnode = state->c->hdr.destnode;
3322 outdata.dptr = NULL;
3324 /* one more node has responded with recmode data */
3327 /* if we failed to push the db, then return an error and let
3328 the main loop try again.
3330 if (state->state != CTDB_CONTROL_DONE) {
3331 if ( !data->dont_log_errors) {
3332 DEBUG(DEBUG_ERR,("Async operation failed with state %d, opcode:%u\n", state->state, data->opcode));
3335 if (state->state == CTDB_CONTROL_TIMEOUT) {
3340 if (data->fail_callback) {
3341 data->fail_callback(ctdb, destnode, res, outdata,
3342 data->callback_data);
3347 state->async.fn = NULL;
3349 ret = ctdb_control_recv(ctdb, state, data, &outdata, &res, NULL);
3350 if ((ret != 0) || (res != 0)) {
3351 if ( !data->dont_log_errors) {
3352 DEBUG(DEBUG_ERR,("Async operation failed with ret=%d res=%d opcode=%u\n", ret, (int)res, data->opcode));
3355 if (data->fail_callback) {
3356 data->fail_callback(ctdb, destnode, res, outdata,
3357 data->callback_data);
3360 if ((ret == 0) && (data->callback != NULL)) {
3361 data->callback(ctdb, destnode, res, outdata,
3362 data->callback_data);
3367 void ctdb_client_async_add(struct client_async_data *data, struct ctdb_client_control_state *state)
3369 /* set up the callback functions */
3370 state->async.fn = async_callback;
3371 state->async.private_data = data;
3373 /* one more control to wait for to complete */
3378 /* wait for up to the maximum number of seconds allowed
3379 or until all nodes we expect a response from has replied
3381 int ctdb_client_async_wait(struct ctdb_context *ctdb, struct client_async_data *data)
3383 while (data->count > 0) {
3384 tevent_loop_once(ctdb->ev);
3386 if (data->fail_count != 0) {
3387 if (!data->dont_log_errors) {
3388 DEBUG(DEBUG_ERR,("Async wait failed - fail_count=%u\n",
3398 perform a simple control on the listed nodes
3399 The control cannot return data
3401 int ctdb_client_async_control(struct ctdb_context *ctdb,
3402 enum ctdb_controls opcode,
3405 struct timeval timeout,
3406 bool dont_log_errors,
3408 client_async_callback client_callback,
3409 client_async_callback fail_callback,
3410 void *callback_data)
3412 struct client_async_data *async_data;
3413 struct ctdb_client_control_state *state;
3416 async_data = talloc_zero(ctdb, struct client_async_data);
3417 CTDB_NO_MEMORY_FATAL(ctdb, async_data);
3418 async_data->dont_log_errors = dont_log_errors;
3419 async_data->callback = client_callback;
3420 async_data->fail_callback = fail_callback;
3421 async_data->callback_data = callback_data;
3422 async_data->opcode = opcode;
3424 num_nodes = talloc_get_size(nodes) / sizeof(uint32_t);
3426 /* loop over all nodes and send an async control to each of them */
3427 for (j=0; j<num_nodes; j++) {
3428 uint32_t pnn = nodes[j];
3430 state = ctdb_control_send(ctdb, pnn, srvid, opcode,
3431 0, data, async_data, &timeout, NULL);
3432 if (state == NULL) {
3433 DEBUG(DEBUG_ERR,(__location__ " Failed to call async control %u\n", (unsigned)opcode));
3434 talloc_free(async_data);
3438 ctdb_client_async_add(async_data, state);
3441 if (ctdb_client_async_wait(ctdb, async_data) != 0) {
3442 talloc_free(async_data);
3446 talloc_free(async_data);
3450 uint32_t *list_of_vnnmap_nodes(struct ctdb_context *ctdb,
3451 struct ctdb_vnn_map *vnn_map,
3452 TALLOC_CTX *mem_ctx,
3455 int i, j, num_nodes;
3458 for (i=num_nodes=0;i<vnn_map->size;i++) {
3459 if (vnn_map->map[i] == ctdb->pnn && !include_self) {
3465 nodes = talloc_array(mem_ctx, uint32_t, num_nodes);
3466 CTDB_NO_MEMORY_FATAL(ctdb, nodes);
3468 for (i=j=0;i<vnn_map->size;i++) {
3469 if (vnn_map->map[i] == ctdb->pnn && !include_self) {
3472 nodes[j++] = vnn_map->map[i];
3478 /* Get list of nodes not including those with flags specified by mask.
3479 * If exclude_pnn is not -1 then exclude that pnn from the list.
3481 uint32_t *list_of_nodes(struct ctdb_context *ctdb,
3482 struct ctdb_node_map_old *node_map,
3483 TALLOC_CTX *mem_ctx,
3487 int i, j, num_nodes;
3490 for (i=num_nodes=0;i<node_map->num;i++) {
3491 if (node_map->nodes[i].flags & mask) {
3494 if (node_map->nodes[i].pnn == exclude_pnn) {
3500 nodes = talloc_array(mem_ctx, uint32_t, num_nodes);
3501 CTDB_NO_MEMORY_FATAL(ctdb, nodes);
3503 for (i=j=0;i<node_map->num;i++) {
3504 if (node_map->nodes[i].flags & mask) {
3507 if (node_map->nodes[i].pnn == exclude_pnn) {
3510 nodes[j++] = node_map->nodes[i].pnn;
3516 uint32_t *list_of_active_nodes(struct ctdb_context *ctdb,
3517 struct ctdb_node_map_old *node_map,
3518 TALLOC_CTX *mem_ctx,
3521 return list_of_nodes(ctdb, node_map, mem_ctx, NODE_FLAGS_INACTIVE,
3522 include_self ? -1 : ctdb->pnn);
3525 uint32_t *list_of_connected_nodes(struct ctdb_context *ctdb,
3526 struct ctdb_node_map_old *node_map,
3527 TALLOC_CTX *mem_ctx,
3530 return list_of_nodes(ctdb, node_map, mem_ctx, NODE_FLAGS_DISCONNECTED,
3531 include_self ? -1 : ctdb->pnn);
3535 this is used to test if a pnn lock exists and if it exists will return
3536 the number of connections that pnn has reported or -1 if that recovery
3537 daemon is not running.
3540 ctdb_read_pnn_lock(int fd, int32_t pnn)
3545 lock.l_type = F_WRLCK;
3546 lock.l_whence = SEEK_SET;
3551 if (fcntl(fd, F_GETLK, &lock) != 0) {
3552 DEBUG(DEBUG_ERR, (__location__ " F_GETLK failed with %s\n", strerror(errno)));
3556 if (lock.l_type == F_UNLCK) {
3560 if (pread(fd, &c, 1, pnn) == -1) {
3561 DEBUG(DEBUG_CRIT,(__location__ " failed read pnn count - %s\n", strerror(errno)));
3569 get capabilities of a remote node
3571 struct ctdb_client_control_state *
3572 ctdb_ctrl_getcapabilities_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode)
3574 return ctdb_control_send(ctdb, destnode, 0,
3575 CTDB_CONTROL_GET_CAPABILITIES, 0, tdb_null,
3576 mem_ctx, &timeout, NULL);
3579 int ctdb_ctrl_getcapabilities_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *capabilities)
3585 ret = ctdb_control_recv(ctdb, state, mem_ctx, &outdata, &res, NULL);
3586 if ( (ret != 0) || (res != 0) ) {
3587 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_getcapabilities_recv failed\n"));
3592 *capabilities = *((uint32_t *)outdata.dptr);
3598 int ctdb_ctrl_getcapabilities(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *capabilities)
3600 struct ctdb_client_control_state *state;
3601 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
3604 state = ctdb_ctrl_getcapabilities_send(ctdb, tmp_ctx, timeout, destnode);
3605 ret = ctdb_ctrl_getcapabilities_recv(ctdb, tmp_ctx, state, capabilities);
3606 talloc_free(tmp_ctx);
3610 static void get_capabilities_callback(struct ctdb_context *ctdb,
3611 uint32_t node_pnn, int32_t res,
3612 TDB_DATA outdata, void *callback_data)
3614 struct ctdb_node_capabilities *caps =
3615 talloc_get_type(callback_data,
3616 struct ctdb_node_capabilities);
3618 if ( (outdata.dsize != sizeof(uint32_t)) || (outdata.dptr == NULL) ) {
3619 DEBUG(DEBUG_ERR, (__location__ " Invalid length/pointer for getcap callback : %u %p\n", (unsigned)outdata.dsize, outdata.dptr));
3623 if (node_pnn >= talloc_array_length(caps)) {
3625 (__location__ " unexpected PNN %u\n", node_pnn));
3629 caps[node_pnn].retrieved = true;
3630 caps[node_pnn].capabilities = *((uint32_t *)outdata.dptr);
3633 struct ctdb_node_capabilities *
3634 ctdb_get_capabilities(struct ctdb_context *ctdb,
3635 TALLOC_CTX *mem_ctx,
3636 struct timeval timeout,
3637 struct ctdb_node_map_old *nodemap)
3641 struct ctdb_node_capabilities *ret;
3643 nodes = list_of_active_nodes(ctdb, nodemap, mem_ctx, true);
3645 ret = talloc_array(mem_ctx, struct ctdb_node_capabilities,
3647 CTDB_NO_MEMORY_NULL(ctdb, ret);
3648 /* Prepopulate the expected PNNs */
3649 for (i = 0; i < talloc_array_length(ret); i++) {
3650 ret[i].retrieved = false;
3653 res = ctdb_client_async_control(ctdb, CTDB_CONTROL_GET_CAPABILITIES,
3656 get_capabilities_callback, NULL,
3660 (__location__ " Failed to read node capabilities.\n"));
3668 ctdb_get_node_capabilities(struct ctdb_node_capabilities *caps,
3671 if (pnn < talloc_array_length(caps) && caps[pnn].retrieved) {
3672 return &caps[pnn].capabilities;
3678 bool ctdb_node_has_capabilities(struct ctdb_node_capabilities *caps,
3680 uint32_t capabilities_required)
3682 uint32_t *capp = ctdb_get_node_capabilities(caps, pnn);
3683 return (capp != NULL) &&
3684 ((*capp & capabilities_required) == capabilities_required);
3688 static struct ctdb_server_id server_id_fetch(struct ctdb_context *ctdb, uint32_t reqid)
3690 struct ctdb_server_id id;
3694 id.vnn = ctdb_get_pnn(ctdb);
3695 id.unique_id = id.vnn;
3696 id.unique_id = (id.unique_id << 32) | reqid;
3701 /* This is basically a copy from Samba's server_id.*. However, a
3702 * dependency chain stops us from using Samba's version, so use a
3703 * renamed copy until a better solution is found. */
3704 static bool ctdb_server_id_equal(struct ctdb_server_id *id1, struct ctdb_server_id *id2)
3706 if (id1->pid != id2->pid) {
3710 if (id1->task_id != id2->task_id) {
3714 if (id1->vnn != id2->vnn) {
3718 if (id1->unique_id != id2->unique_id) {
3725 static bool server_id_exists(struct ctdb_context *ctdb,
3726 struct ctdb_server_id *id)
3730 ret = ctdb_ctrl_process_exists(ctdb, id->vnn, id->pid);
3738 static bool g_lock_parse(TALLOC_CTX *mem_ctx, TDB_DATA data,
3739 struct ctdb_g_lock_list **locks)
3741 struct ctdb_g_lock_list *recs;
3743 recs = talloc_zero(mem_ctx, struct ctdb_g_lock_list);
3748 if (data.dsize == 0) {
3752 if (data.dsize % sizeof(struct ctdb_g_lock) != 0) {
3753 DEBUG(DEBUG_ERR, (__location__ "invalid data size %lu in g_lock record\n",
3754 (unsigned long)data.dsize));
3759 recs->num = data.dsize / sizeof(struct ctdb_g_lock);
3760 recs->lock = talloc_memdup(mem_ctx, data.dptr, data.dsize);
3761 if (recs->lock == NULL) {
3767 if (locks != NULL) {
3775 static bool g_lock_lock(TALLOC_CTX *mem_ctx,
3776 struct ctdb_db_context *ctdb_db,
3777 const char *keyname, uint32_t reqid)
3780 struct ctdb_record_handle *h;
3781 struct ctdb_g_lock_list *locks;
3782 struct ctdb_server_id id;
3783 struct timeval t_start;
3786 key.dptr = (uint8_t *)discard_const(keyname);
3787 key.dsize = strlen(keyname) + 1;
3789 t_start = timeval_current();
3792 /* Keep trying for an hour. */
3793 if (timeval_elapsed(&t_start) > 3600) {
3797 h = ctdb_fetch_lock(ctdb_db, mem_ctx, key, &data);
3802 if (!g_lock_parse(h, data, &locks)) {
3803 DEBUG(DEBUG_ERR, ("g_lock: error parsing locks\n"));
3804 talloc_free(data.dptr);
3809 talloc_free(data.dptr);
3811 id = server_id_fetch(ctdb_db->ctdb, reqid);
3814 while (i < locks->num) {
3815 if (ctdb_server_id_equal(&locks->lock[i].sid, &id)) {
3816 /* Internal error */
3821 if (!server_id_exists(ctdb_db->ctdb, &locks->lock[i].sid)) {
3822 if (i < locks->num-1) {
3823 locks->lock[i] = locks->lock[locks->num-1];
3829 /* This entry is locked. */
3830 DEBUG(DEBUG_INFO, ("g_lock: lock already granted for "
3831 "pid=0x%llx taskid=%x vnn=%d id=0x%llx\n",
3832 (unsigned long long)id.pid,
3834 (unsigned long long)id.unique_id));
3839 locks->lock = talloc_realloc(locks, locks->lock, struct ctdb_g_lock,
3841 if (locks->lock == NULL) {
3846 locks->lock[locks->num].type = CTDB_G_LOCK_WRITE;
3847 locks->lock[locks->num].sid = id;
3850 data.dptr = (uint8_t *)locks->lock;
3851 data.dsize = locks->num * sizeof(struct ctdb_g_lock);
3853 if (ctdb_record_store(h, data) != 0) {
3854 DEBUG(DEBUG_ERR, ("g_lock: failed to write transaction lock for "
3855 "pid=0x%llx taskid=%x vnn=%d id=0x%llx\n",
3856 (unsigned long long)id.pid,
3858 (unsigned long long)id.unique_id));
3863 DEBUG(DEBUG_INFO, ("g_lock: lock granted for "
3864 "pid=0x%llx taskid=%x vnn=%d id=0x%llx\n",
3865 (unsigned long long)id.pid,
3867 (unsigned long long)id.unique_id));
3873 static bool g_lock_unlock(TALLOC_CTX *mem_ctx,
3874 struct ctdb_db_context *ctdb_db,
3875 const char *keyname, uint32_t reqid)
3878 struct ctdb_record_handle *h;
3879 struct ctdb_g_lock_list *locks;
3880 struct ctdb_server_id id;
3884 key.dptr = (uint8_t *)discard_const(keyname);
3885 key.dsize = strlen(keyname) + 1;
3886 h = ctdb_fetch_lock(ctdb_db, mem_ctx, key, &data);
3891 if (!g_lock_parse(h, data, &locks)) {
3892 DEBUG(DEBUG_ERR, ("g_lock: error parsing locks\n"));
3893 talloc_free(data.dptr);
3898 talloc_free(data.dptr);
3900 id = server_id_fetch(ctdb_db->ctdb, reqid);
3902 for (i=0; i<locks->num; i++) {
3903 if (ctdb_server_id_equal(&locks->lock[i].sid, &id)) {
3904 if (i < locks->num-1) {
3905 locks->lock[i] = locks->lock[locks->num-1];
3914 DEBUG(DEBUG_ERR, ("g_lock: lock not found\n"));
3919 data.dptr = (uint8_t *)locks->lock;
3920 data.dsize = locks->num * sizeof(struct ctdb_g_lock);
3922 if (ctdb_record_store(h, data) != 0) {
3932 struct ctdb_transaction_handle {
3933 struct ctdb_db_context *ctdb_db;
3934 struct ctdb_db_context *g_lock_db;
3938 * we store reads and writes done under a transaction:
3939 * - one list stores both reads and writes (m_all)
3940 * - the other just writes (m_write)
3942 struct ctdb_marshall_buffer *m_all;
3943 struct ctdb_marshall_buffer *m_write;
3946 static int ctdb_transaction_destructor(struct ctdb_transaction_handle *h)
3948 g_lock_unlock(h, h->g_lock_db, h->lock_name, h->reqid);
3949 reqid_remove(h->ctdb_db->ctdb->idr, h->reqid);
3955 * start a transaction on a database
3957 struct ctdb_transaction_handle *ctdb_transaction_start(struct ctdb_db_context *ctdb_db,
3958 TALLOC_CTX *mem_ctx)
3960 struct ctdb_transaction_handle *h;
3962 h = talloc_zero(mem_ctx, struct ctdb_transaction_handle);
3964 DEBUG(DEBUG_ERR, (__location__ " memory allocation error\n"));
3968 h->ctdb_db = ctdb_db;
3969 h->lock_name = talloc_asprintf(h, "transaction_db_0x%08x",
3970 (unsigned int)ctdb_db->db_id);
3971 if (h->lock_name == NULL) {
3972 DEBUG(DEBUG_ERR, (__location__ " talloc asprintf failed\n"));
3977 h->g_lock_db = ctdb_attach(h->ctdb_db->ctdb, timeval_current_ofs(3,0),
3978 "g_lock.tdb", false, 0);
3979 if (!h->g_lock_db) {
3980 DEBUG(DEBUG_ERR, (__location__ " unable to attach to g_lock.tdb\n"));
3985 h->reqid = reqid_new(h->ctdb_db->ctdb->idr, h);
3987 if (!g_lock_lock(h, h->g_lock_db, h->lock_name, h->reqid)) {
3988 DEBUG(DEBUG_ERR, (__location__ " Error locking g_lock.tdb\n"));
3993 talloc_set_destructor(h, ctdb_transaction_destructor);
3998 * fetch a record inside a transaction
4000 int ctdb_transaction_fetch(struct ctdb_transaction_handle *h,
4001 TALLOC_CTX *mem_ctx,
4002 TDB_DATA key, TDB_DATA *data)
4004 struct ctdb_ltdb_header header;
4007 ZERO_STRUCT(header);
4009 ret = ctdb_ltdb_fetch(h->ctdb_db, key, &header, mem_ctx, data);
4010 if (ret == -1 && header.dmaster == (uint32_t)-1) {
4011 /* record doesn't exist yet */
4020 h->m_all = ctdb_marshall_add(h, h->m_all, h->ctdb_db->db_id, 1, key, NULL, *data);
4021 if (h->m_all == NULL) {
4022 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
4030 * stores a record inside a transaction
4032 int ctdb_transaction_store(struct ctdb_transaction_handle *h,
4033 TDB_DATA key, TDB_DATA data)
4035 TALLOC_CTX *tmp_ctx = talloc_new(h);
4036 struct ctdb_ltdb_header header;
4040 /* we need the header so we can update the RSN */
4041 ret = ctdb_ltdb_fetch(h->ctdb_db, key, &header, tmp_ctx, &olddata);
4042 if (ret == -1 && header.dmaster == (uint32_t)-1) {
4043 /* the record doesn't exist - create one with us as dmaster.
4044 This is only safe because we are in a transaction and this
4045 is a persistent database */
4046 ZERO_STRUCT(header);
4047 } else if (ret != 0) {
4048 DEBUG(DEBUG_ERR,(__location__ " Failed to fetch record\n"));
4049 talloc_free(tmp_ctx);
4053 if (data.dsize == olddata.dsize &&
4054 memcmp(data.dptr, olddata.dptr, data.dsize) == 0 &&
4056 /* save writing the same data */
4057 talloc_free(tmp_ctx);
4061 header.dmaster = h->ctdb_db->ctdb->pnn;
4064 h->m_all = ctdb_marshall_add(h, h->m_all, h->ctdb_db->db_id, 0, key, NULL, data);
4065 if (h->m_all == NULL) {
4066 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
4067 talloc_free(tmp_ctx);
4071 h->m_write = ctdb_marshall_add(h, h->m_write, h->ctdb_db->db_id, 0, key, &header, data);
4072 if (h->m_write == NULL) {
4073 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
4074 talloc_free(tmp_ctx);
4078 talloc_free(tmp_ctx);
4082 static int ctdb_fetch_db_seqnum(struct ctdb_db_context *ctdb_db, uint64_t *seqnum)
4084 const char *keyname = CTDB_DB_SEQNUM_KEY;
4086 struct ctdb_ltdb_header header;
4089 key.dptr = (uint8_t *)discard_const(keyname);
4090 key.dsize = strlen(keyname) + 1;
4092 ret = ctdb_ltdb_fetch(ctdb_db, key, &header, ctdb_db, &data);
4098 if (data.dsize == 0) {
4103 if (data.dsize != sizeof(*seqnum)) {
4104 DEBUG(DEBUG_ERR, (__location__ " Invalid data recived len=%zi\n",
4106 talloc_free(data.dptr);
4110 *seqnum = *(uint64_t *)data.dptr;
4111 talloc_free(data.dptr);
4117 static int ctdb_store_db_seqnum(struct ctdb_transaction_handle *h,
4120 const char *keyname = CTDB_DB_SEQNUM_KEY;
4123 key.dptr = (uint8_t *)discard_const(keyname);
4124 key.dsize = strlen(keyname) + 1;
4126 data.dptr = (uint8_t *)&seqnum;
4127 data.dsize = sizeof(seqnum);
4129 return ctdb_transaction_store(h, key, data);
4134 * commit a transaction
4136 int ctdb_transaction_commit(struct ctdb_transaction_handle *h)
4139 uint64_t old_seqnum, new_seqnum;
4141 struct timeval timeout;
4143 if (h->m_write == NULL) {
4144 /* no changes were made */
4149 ret = ctdb_fetch_db_seqnum(h->ctdb_db, &old_seqnum);
4151 DEBUG(DEBUG_ERR, (__location__ " failed to fetch db sequence number\n"));
4156 new_seqnum = old_seqnum + 1;
4157 ret = ctdb_store_db_seqnum(h, new_seqnum);
4159 DEBUG(DEBUG_ERR, (__location__ " failed to store db sequence number\n"));
4165 timeout = timeval_current_ofs(30,0);
4166 ret = ctdb_control(h->ctdb_db->ctdb, CTDB_CURRENT_NODE,
4168 CTDB_CONTROL_TRANS3_COMMIT, 0,
4169 ctdb_marshall_finish(h->m_write), NULL, NULL,
4170 &status, &timeout, NULL);
4171 if (ret != 0 || status != 0) {
4173 * TRANS3_COMMIT control will only fail if recovery has been
4174 * triggered. Check if the database has been updated or not.
4176 ret = ctdb_fetch_db_seqnum(h->ctdb_db, &new_seqnum);
4178 DEBUG(DEBUG_ERR, (__location__ " failed to fetch db sequence number\n"));
4182 if (new_seqnum == old_seqnum) {
4183 /* Database not yet updated, try again */
4187 if (new_seqnum != (old_seqnum + 1)) {
4188 DEBUG(DEBUG_ERR, (__location__ " new seqnum [%llu] != old seqnum [%llu] + 1\n",
4189 (long long unsigned)new_seqnum,
4190 (long long unsigned)old_seqnum));
4204 * cancel a transaction
4206 int ctdb_transaction_cancel(struct ctdb_transaction_handle *h)
4214 recovery daemon ping to main daemon
4216 int ctdb_ctrl_recd_ping(struct ctdb_context *ctdb)
4221 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_RECD_PING, 0, tdb_null,
4222 ctdb, NULL, &res, NULL, NULL);
4223 if (ret != 0 || res != 0) {
4224 DEBUG(DEBUG_ERR,("Failed to send recd ping\n"));
4232 get the status of running the monitor eventscripts: NULL means never run.
4234 int ctdb_ctrl_getscriptstatus(struct ctdb_context *ctdb,
4235 struct timeval timeout, uint32_t destnode,
4236 TALLOC_CTX *mem_ctx,
4237 enum ctdb_event type,
4238 struct ctdb_script_list_old **scripts)
4241 TDB_DATA outdata, indata;
4243 uint32_t uinttype = type;
4245 indata.dptr = (uint8_t *)&uinttype;
4246 indata.dsize = sizeof(uinttype);
4248 ret = ctdb_control(ctdb, destnode, 0,
4249 CTDB_CONTROL_GET_EVENT_SCRIPT_STATUS, 0, indata,
4250 mem_ctx, &outdata, &res, &timeout, NULL);
4251 if (ret != 0 || res != 0) {
4252 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getscriptstatus failed ret:%d res:%d\n", ret, res));
4256 if (outdata.dsize == 0) {
4259 *scripts = (struct ctdb_script_list_old *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
4260 talloc_free(outdata.dptr);
4267 tell the main daemon how long it took to lock the reclock file
4269 int ctdb_ctrl_report_recd_lock_latency(struct ctdb_context *ctdb, struct timeval timeout, double latency)
4275 data.dptr = (uint8_t *)&latency;
4276 data.dsize = sizeof(latency);
4278 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_RECD_RECLOCK_LATENCY, 0, data,
4279 ctdb, NULL, &res, NULL, NULL);
4280 if (ret != 0 || res != 0) {
4281 DEBUG(DEBUG_ERR,("Failed to send recd reclock latency\n"));
4289 get the name of the reclock file
4291 int ctdb_ctrl_getreclock(struct ctdb_context *ctdb, struct timeval timeout,
4292 uint32_t destnode, TALLOC_CTX *mem_ctx,
4299 ret = ctdb_control(ctdb, destnode, 0,
4300 CTDB_CONTROL_GET_RECLOCK_FILE, 0, tdb_null,
4301 mem_ctx, &data, &res, &timeout, NULL);
4302 if (ret != 0 || res != 0) {
4306 if (data.dsize == 0) {
4309 *name = talloc_strdup(mem_ctx, discard_const(data.dptr));
4311 talloc_free(data.dptr);
4319 int ctdb_ctrl_stop_node(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
4324 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_STOP_NODE, 0, tdb_null,
4325 ctdb, NULL, &res, &timeout, NULL);
4326 if (ret != 0 || res != 0) {
4327 DEBUG(DEBUG_ERR,("Failed to stop node\n"));
4337 int ctdb_ctrl_continue_node(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
4341 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_CONTINUE_NODE, 0, tdb_null,
4342 ctdb, NULL, NULL, &timeout, NULL);
4344 DEBUG(DEBUG_ERR,("Failed to continue node\n"));
4352 set the lmaster role for a node
4354 int ctdb_ctrl_setlmasterrole(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t lmasterrole)
4360 data.dsize = sizeof(lmasterrole);
4361 data.dptr = (uint8_t *)&lmasterrole;
4363 ret = ctdb_control(ctdb, destnode, 0,
4364 CTDB_CONTROL_SET_LMASTERROLE, 0, data,
4365 NULL, NULL, &res, &timeout, NULL);
4366 if (ret != 0 || res != 0) {
4367 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setlmasterrole failed\n"));
4375 set the recmaster role for a node
4377 int ctdb_ctrl_setrecmasterrole(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmasterrole)
4383 data.dsize = sizeof(recmasterrole);
4384 data.dptr = (uint8_t *)&recmasterrole;
4386 ret = ctdb_control(ctdb, destnode, 0,
4387 CTDB_CONTROL_SET_RECMASTERROLE, 0, data,
4388 NULL, NULL, &res, &timeout, NULL);
4389 if (ret != 0 || res != 0) {
4390 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setrecmasterrole failed\n"));
4397 /* enable an eventscript
4399 int ctdb_ctrl_enablescript(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, const char *script)
4405 data.dsize = strlen(script) + 1;
4406 data.dptr = discard_const(script);
4408 ret = ctdb_control(ctdb, destnode, 0,
4409 CTDB_CONTROL_ENABLE_SCRIPT, 0, data,
4410 NULL, NULL, &res, &timeout, NULL);
4411 if (ret != 0 || res != 0) {
4412 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for enablescript failed\n"));
4419 /* disable an eventscript
4421 int ctdb_ctrl_disablescript(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, const char *script)
4427 data.dsize = strlen(script) + 1;
4428 data.dptr = discard_const(script);
4430 ret = ctdb_control(ctdb, destnode, 0,
4431 CTDB_CONTROL_DISABLE_SCRIPT, 0, data,
4432 NULL, NULL, &res, &timeout, NULL);
4433 if (ret != 0 || res != 0) {
4434 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for disablescript failed\n"));
4442 int ctdb_ctrl_set_ban(struct ctdb_context *ctdb, struct timeval timeout,
4443 uint32_t destnode, struct ctdb_ban_state *bantime)
4449 data.dsize = sizeof(*bantime);
4450 data.dptr = (uint8_t *)bantime;
4452 ret = ctdb_control(ctdb, destnode, 0,
4453 CTDB_CONTROL_SET_BAN_STATE, 0, data,
4454 NULL, NULL, &res, &timeout, NULL);
4455 if (ret != 0 || res != 0) {
4456 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set ban state failed\n"));
4464 int ctdb_ctrl_get_ban(struct ctdb_context *ctdb, struct timeval timeout,
4465 uint32_t destnode, TALLOC_CTX *mem_ctx,
4466 struct ctdb_ban_state **bantime)
4471 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
4473 ret = ctdb_control(ctdb, destnode, 0,
4474 CTDB_CONTROL_GET_BAN_STATE, 0, tdb_null,
4475 tmp_ctx, &outdata, &res, &timeout, NULL);
4476 if (ret != 0 || res != 0) {
4477 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set ban state failed\n"));
4478 talloc_free(tmp_ctx);
4482 *bantime = (struct ctdb_ban_state *)talloc_steal(mem_ctx, outdata.dptr);
4483 talloc_free(tmp_ctx);
4489 int ctdb_ctrl_set_db_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, struct ctdb_db_priority *db_prio)
4494 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
4496 data.dptr = (uint8_t*)db_prio;
4497 data.dsize = sizeof(*db_prio);
4499 ret = ctdb_control(ctdb, destnode, 0,
4500 CTDB_CONTROL_SET_DB_PRIORITY, 0, data,
4501 tmp_ctx, NULL, &res, &timeout, NULL);
4502 if (ret != 0 || res != 0) {
4503 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set_db_priority failed\n"));
4504 talloc_free(tmp_ctx);
4508 talloc_free(tmp_ctx);
4513 int ctdb_ctrl_get_db_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t db_id, uint32_t *priority)
4518 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
4520 data.dptr = (uint8_t*)&db_id;
4521 data.dsize = sizeof(db_id);
4523 ret = ctdb_control(ctdb, destnode, 0,
4524 CTDB_CONTROL_GET_DB_PRIORITY, 0, data,
4525 tmp_ctx, NULL, &res, &timeout, NULL);
4526 if (ret != 0 || res < 0) {
4527 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get_db_priority failed\n"));
4528 talloc_free(tmp_ctx);
4536 talloc_free(tmp_ctx);
4541 int ctdb_ctrl_getstathistory(struct ctdb_context *ctdb,
4542 struct timeval timeout, uint32_t destnode,
4543 TALLOC_CTX *mem_ctx,
4544 struct ctdb_statistics_list_old **stats)
4550 ret = ctdb_control(ctdb, destnode, 0,
4551 CTDB_CONTROL_GET_STAT_HISTORY, 0, tdb_null,
4552 mem_ctx, &outdata, &res, &timeout, NULL);
4553 if (ret != 0 || res != 0 || outdata.dsize == 0) {
4554 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getstathistory failed ret:%d res:%d\n", ret, res));
4558 *stats = (struct ctdb_statistics_list_old *)talloc_memdup(mem_ctx,
4561 talloc_free(outdata.dptr);
4566 struct ctdb_ltdb_header *ctdb_header_from_record_handle(struct ctdb_record_handle *h)
4576 struct ctdb_client_control_state *
4577 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)
4579 struct ctdb_client_control_state *handle;
4580 struct ctdb_marshall_buffer *m;
4581 struct ctdb_rec_data_old *rec;
4584 m = talloc_zero(mem_ctx, struct ctdb_marshall_buffer);
4586 DEBUG(DEBUG_ERR, ("Failed to allocate marshall buffer for update record\n"));
4590 m->db_id = ctdb_db->db_id;
4592 rec = ctdb_marshall_record(m, 0, key, header, data);
4594 DEBUG(DEBUG_ERR,("Failed to marshall record for update record\n"));
4598 m = talloc_realloc_size(mem_ctx, m, rec->length + offsetof(struct ctdb_marshall_buffer, data));
4600 DEBUG(DEBUG_CRIT,(__location__ " Failed to expand recdata\n"));
4605 memcpy((uint8_t *)m + offsetof(struct ctdb_marshall_buffer, data), rec, rec->length);
4608 outdata.dptr = (uint8_t *)m;
4609 outdata.dsize = talloc_get_size(m);
4611 handle = ctdb_control_send(ctdb, destnode, 0,
4612 CTDB_CONTROL_UPDATE_RECORD, 0, outdata,
4613 mem_ctx, &timeout, NULL);
4618 int ctdb_ctrl_updaterecord_recv(struct ctdb_context *ctdb, struct ctdb_client_control_state *state)
4623 ret = ctdb_control_recv(ctdb, state, state, NULL, &res, NULL);
4624 if ( (ret != 0) || (res != 0) ){
4625 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_update_record_recv failed\n"));
4633 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)
4635 struct ctdb_client_control_state *state;
4637 state = ctdb_ctrl_updaterecord_send(ctdb, mem_ctx, timeout, destnode, ctdb_db, key, header, data);
4638 return ctdb_ctrl_updaterecord_recv(ctdb, state);
4647 set a database to be readonly
4649 struct ctdb_client_control_state *
4650 ctdb_ctrl_set_db_readonly_send(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid)
4654 data.dptr = (uint8_t *)&dbid;
4655 data.dsize = sizeof(dbid);
4657 return ctdb_control_send(ctdb, destnode, 0,
4658 CTDB_CONTROL_SET_DB_READONLY, 0, data,
4662 int ctdb_ctrl_set_db_readonly_recv(struct ctdb_context *ctdb, struct ctdb_client_control_state *state)
4667 ret = ctdb_control_recv(ctdb, state, ctdb, NULL, &res, NULL);
4668 if (ret != 0 || res != 0) {
4669 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_set_db_readonly_recv failed ret:%d res:%d\n", ret, res));
4676 int ctdb_ctrl_set_db_readonly(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid)
4678 struct ctdb_client_control_state *state;
4680 state = ctdb_ctrl_set_db_readonly_send(ctdb, destnode, dbid);
4681 return ctdb_ctrl_set_db_readonly_recv(ctdb, state);
4685 set a database to be sticky
4687 struct ctdb_client_control_state *
4688 ctdb_ctrl_set_db_sticky_send(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid)
4692 data.dptr = (uint8_t *)&dbid;
4693 data.dsize = sizeof(dbid);
4695 return ctdb_control_send(ctdb, destnode, 0,
4696 CTDB_CONTROL_SET_DB_STICKY, 0, data,
4700 int ctdb_ctrl_set_db_sticky_recv(struct ctdb_context *ctdb, struct ctdb_client_control_state *state)
4705 ret = ctdb_control_recv(ctdb, state, ctdb, NULL, &res, NULL);
4706 if (ret != 0 || res != 0) {
4707 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_set_db_sticky_recv failed ret:%d res:%d\n", ret, res));
4714 int ctdb_ctrl_set_db_sticky(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid)
4716 struct ctdb_client_control_state *state;
4718 state = ctdb_ctrl_set_db_sticky_send(ctdb, destnode, dbid);
4719 return ctdb_ctrl_set_db_sticky_recv(ctdb, state);