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_zero(mem_ctx, 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);
99 for (fn=ctdb_db->calls;fn;fn=fn->next) {
100 if (fn->id == call->call_id) break;
103 ctdb_set_error(ctdb, "Unknown call id %u\n", call->call_id);
108 if (fn->fn(c) != 0) {
109 ctdb_set_error(ctdb, "ctdb_call %u failed\n", call->call_id);
114 /* we need to force the record to be written out if this was a remote access */
115 if (c->new_data == NULL) {
116 c->new_data = &c->record_data;
119 if (c->new_data && updatetdb) {
120 /* XXX check that we always have the lock here? */
121 if (ctdb_ltdb_store(ctdb_db, call->key, header, *c->new_data) != 0) {
122 ctdb_set_error(ctdb, "ctdb_call tdb_store failed\n");
129 call->reply_data = *c->reply_data;
131 talloc_steal(call, call->reply_data.dptr);
132 talloc_set_name_const(call->reply_data.dptr, __location__);
134 call->reply_data.dptr = NULL;
135 call->reply_data.dsize = 0;
137 call->status = c->status;
146 queue a packet for sending from client to daemon
148 static int ctdb_client_queue_pkt(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
150 return ctdb_queue_send(ctdb->daemon.queue, (uint8_t *)hdr, hdr->length);
155 called when a CTDB_REPLY_CALL packet comes in in the client
157 This packet comes in response to a CTDB_REQ_CALL request packet. It
158 contains any reply data from the call
160 static void ctdb_client_reply_call(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
162 struct ctdb_reply_call_old *c = (struct ctdb_reply_call_old *)hdr;
163 struct ctdb_client_call_state *state;
165 state = reqid_find(ctdb->idr, hdr->reqid, struct ctdb_client_call_state);
167 DEBUG(DEBUG_ERR,(__location__ " reqid %u not found\n", hdr->reqid));
171 if (hdr->reqid != state->reqid) {
172 /* we found a record but it was the wrong one */
173 DEBUG(DEBUG_ERR, ("Dropped client call reply with reqid:%u\n",hdr->reqid));
177 state->call->reply_data.dptr = c->data;
178 state->call->reply_data.dsize = c->datalen;
179 state->call->status = c->status;
181 talloc_steal(state, c);
183 state->state = CTDB_CALL_DONE;
185 if (state->async.fn) {
186 state->async.fn(state);
190 void ctdb_request_message(struct ctdb_context *ctdb,
191 struct ctdb_req_header *hdr)
193 struct ctdb_req_message_old *c = (struct ctdb_req_message_old *)hdr;
196 data.dsize = c->datalen;
197 data.dptr = talloc_memdup(c, &c->data[0], c->datalen);
198 if (data.dptr == NULL) {
199 DEBUG(DEBUG_ERR, (__location__ " Memory allocation failure\n"));
203 srvid_dispatch(ctdb->srv, c->srvid, CTDB_SRVID_ALL, data);
206 static void ctdb_client_reply_control(struct ctdb_context *ctdb, struct ctdb_req_header *hdr);
209 this is called in the client, when data comes in from the daemon
211 void ctdb_client_read_cb(uint8_t *data, size_t cnt, void *args)
213 struct ctdb_context *ctdb = talloc_get_type(args, struct ctdb_context);
214 struct ctdb_req_header *hdr = (struct ctdb_req_header *)data;
217 /* place the packet as a child of a tmp_ctx. We then use
218 talloc_free() below to free it. If any of the calls want
219 to keep it, then they will steal it somewhere else, and the
220 talloc_free() will be a no-op */
221 tmp_ctx = talloc_new(ctdb);
222 talloc_steal(tmp_ctx, hdr);
225 DEBUG(DEBUG_CRIT,("Daemon has exited - shutting down client\n"));
229 if (cnt < sizeof(*hdr)) {
230 DEBUG(DEBUG_CRIT,("Bad packet length %u in client\n", (unsigned)cnt));
233 if (cnt != hdr->length) {
234 ctdb_set_error(ctdb, "Bad header length %u expected %u in client\n",
235 (unsigned)hdr->length, (unsigned)cnt);
239 if (hdr->ctdb_magic != CTDB_MAGIC) {
240 ctdb_set_error(ctdb, "Non CTDB packet rejected in client\n");
244 if (hdr->ctdb_version != CTDB_PROTOCOL) {
245 ctdb_set_error(ctdb, "Bad CTDB version 0x%x rejected in client\n", hdr->ctdb_version);
249 switch (hdr->operation) {
250 case CTDB_REPLY_CALL:
251 ctdb_client_reply_call(ctdb, hdr);
254 case CTDB_REQ_MESSAGE:
255 ctdb_request_message(ctdb, hdr);
258 case CTDB_REPLY_CONTROL:
259 ctdb_client_reply_control(ctdb, hdr);
263 DEBUG(DEBUG_CRIT,("bogus operation code:%u\n",hdr->operation));
267 talloc_free(tmp_ctx);
271 connect to a unix domain socket
273 int ctdb_socket_connect(struct ctdb_context *ctdb)
275 struct sockaddr_un addr;
278 memset(&addr, 0, sizeof(addr));
279 addr.sun_family = AF_UNIX;
280 strncpy(addr.sun_path, ctdb->daemon.name, sizeof(addr.sun_path)-1);
282 ctdb->daemon.sd = socket(AF_UNIX, SOCK_STREAM, 0);
283 if (ctdb->daemon.sd == -1) {
284 DEBUG(DEBUG_ERR,(__location__ " Failed to open client socket. Errno:%s(%d)\n", strerror(errno), errno));
288 if (connect(ctdb->daemon.sd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
291 "Failed to connect client socket to daemon (%s)\n",
293 close(ctdb->daemon.sd);
294 ctdb->daemon.sd = -1;
298 ret = set_blocking(ctdb->daemon.sd, false);
302 " failed to set socket non-blocking (%s)\n",
304 close(ctdb->daemon.sd);
305 ctdb->daemon.sd = -1;
309 set_close_on_exec(ctdb->daemon.sd);
311 ctdb->daemon.queue = ctdb_queue_setup(ctdb, ctdb, ctdb->daemon.sd,
313 ctdb_client_read_cb, ctdb, "to-ctdbd");
318 struct ctdb_record_handle {
319 struct ctdb_db_context *ctdb_db;
322 struct ctdb_ltdb_header header;
327 make a recv call to the local ctdb daemon - called from client context
329 This is called when the program wants to wait for a ctdb_call to complete and get the
330 results. This call will block unless the call has already completed.
332 int ctdb_call_recv(struct ctdb_client_call_state *state, struct ctdb_call *call)
338 while (state->state < CTDB_CALL_DONE) {
339 tevent_loop_once(state->ctdb_db->ctdb->ev);
341 if (state->state != CTDB_CALL_DONE) {
342 DEBUG(DEBUG_ERR,(__location__ " ctdb_call_recv failed\n"));
347 if (state->call->reply_data.dsize) {
348 call->reply_data.dptr = talloc_memdup(state->ctdb_db,
349 state->call->reply_data.dptr,
350 state->call->reply_data.dsize);
351 call->reply_data.dsize = state->call->reply_data.dsize;
353 call->reply_data.dptr = NULL;
354 call->reply_data.dsize = 0;
356 call->status = state->call->status;
366 destroy a ctdb_call in client
368 static int ctdb_client_call_destructor(struct ctdb_client_call_state *state)
370 reqid_remove(state->ctdb_db->ctdb->idr, state->reqid);
375 construct an event driven local ctdb_call
377 this is used so that locally processed ctdb_call requests are processed
378 in an event driven manner
380 static struct ctdb_client_call_state *ctdb_client_call_local_send(struct ctdb_db_context *ctdb_db,
381 struct ctdb_call *call,
382 struct ctdb_ltdb_header *header,
385 struct ctdb_client_call_state *state;
386 struct ctdb_context *ctdb = ctdb_db->ctdb;
389 state = talloc_zero(ctdb_db, struct ctdb_client_call_state);
390 CTDB_NO_MEMORY_NULL(ctdb, state);
391 state->call = talloc_zero(state, struct ctdb_call);
392 CTDB_NO_MEMORY_NULL(ctdb, state->call);
394 talloc_steal(state, data->dptr);
396 state->state = CTDB_CALL_DONE;
397 *(state->call) = *call;
398 state->ctdb_db = ctdb_db;
400 ret = ctdb_call_local(ctdb_db, state->call, header, state, data, true);
402 DEBUG(DEBUG_DEBUG,("ctdb_call_local() failed, ignoring return code %d\n", ret));
409 make a ctdb call to the local daemon - async send. Called from client context.
411 This constructs a ctdb_call request and queues it for processing.
412 This call never blocks.
414 struct ctdb_client_call_state *ctdb_call_send(struct ctdb_db_context *ctdb_db,
415 struct ctdb_call *call)
417 struct ctdb_client_call_state *state;
418 struct ctdb_context *ctdb = ctdb_db->ctdb;
419 struct ctdb_ltdb_header header;
423 struct ctdb_req_call_old *c;
425 /* if the domain socket is not yet open, open it */
426 if (ctdb->daemon.sd==-1) {
427 ctdb_socket_connect(ctdb);
430 ret = ctdb_ltdb_lock(ctdb_db, call->key);
432 DEBUG(DEBUG_ERR,(__location__ " Failed to get chainlock\n"));
436 ret = ctdb_ltdb_fetch(ctdb_db, call->key, &header, ctdb_db, &data);
438 if ((call->flags & CTDB_IMMEDIATE_MIGRATION) && (header.flags & CTDB_REC_RO_HAVE_DELEGATIONS)) {
442 if (ret == 0 && header.dmaster == ctdb->pnn) {
443 state = ctdb_client_call_local_send(ctdb_db, call, &header, &data);
444 talloc_free(data.dptr);
445 ctdb_ltdb_unlock(ctdb_db, call->key);
449 ctdb_ltdb_unlock(ctdb_db, call->key);
450 talloc_free(data.dptr);
452 state = talloc_zero(ctdb_db, struct ctdb_client_call_state);
454 DEBUG(DEBUG_ERR, (__location__ " failed to allocate state\n"));
457 state->call = talloc_zero(state, struct ctdb_call);
458 if (state->call == NULL) {
459 DEBUG(DEBUG_ERR, (__location__ " failed to allocate state->call\n"));
463 len = offsetof(struct ctdb_req_call_old, data) + call->key.dsize + call->call_data.dsize;
464 c = ctdbd_allocate_pkt(ctdb, state, CTDB_REQ_CALL, len, struct ctdb_req_call_old);
466 DEBUG(DEBUG_ERR, (__location__ " failed to allocate packet\n"));
470 state->reqid = reqid_new(ctdb->idr, state);
471 state->ctdb_db = ctdb_db;
472 talloc_set_destructor(state, ctdb_client_call_destructor);
474 c->hdr.reqid = state->reqid;
475 c->flags = call->flags;
476 c->db_id = ctdb_db->db_id;
477 c->callid = call->call_id;
479 c->keylen = call->key.dsize;
480 c->calldatalen = call->call_data.dsize;
481 memcpy(&c->data[0], call->key.dptr, call->key.dsize);
482 memcpy(&c->data[call->key.dsize],
483 call->call_data.dptr, call->call_data.dsize);
484 *(state->call) = *call;
485 state->call->call_data.dptr = &c->data[call->key.dsize];
486 state->call->key.dptr = &c->data[0];
488 state->state = CTDB_CALL_WAIT;
491 ctdb_client_queue_pkt(ctdb, &c->hdr);
498 full ctdb_call. Equivalent to a ctdb_call_send() followed by a ctdb_call_recv()
500 int ctdb_call(struct ctdb_db_context *ctdb_db, struct ctdb_call *call)
502 struct ctdb_client_call_state *state;
504 state = ctdb_call_send(ctdb_db, call);
505 return ctdb_call_recv(state, call);
510 tell the daemon what messaging srvid we will use, and register the message
511 handler function in the client
513 int ctdb_client_set_message_handler(struct ctdb_context *ctdb, uint64_t srvid,
514 srvid_handler_fn handler,
520 res = ctdb_control(ctdb, CTDB_CURRENT_NODE, srvid,
521 CTDB_CONTROL_REGISTER_SRVID, 0,
522 tdb_null, NULL, NULL, &status, NULL, NULL);
523 if (res != 0 || status != 0) {
525 ("Failed to register srvid %llu\n",
526 (unsigned long long)srvid));
530 /* also need to register the handler with our own ctdb structure */
531 return srvid_register(ctdb->srv, ctdb, srvid, handler, private_data);
535 tell the daemon we no longer want a srvid
537 int ctdb_client_remove_message_handler(struct ctdb_context *ctdb,
538 uint64_t srvid, void *private_data)
543 res = ctdb_control(ctdb, CTDB_CURRENT_NODE, srvid,
544 CTDB_CONTROL_DEREGISTER_SRVID, 0,
545 tdb_null, NULL, NULL, &status, NULL, NULL);
546 if (res != 0 || status != 0) {
548 ("Failed to deregister srvid %llu\n",
549 (unsigned long long)srvid));
553 /* also need to register the handler with our own ctdb structure */
554 srvid_deregister(ctdb->srv, srvid, private_data);
559 send a message - from client context
561 int ctdb_client_send_message(struct ctdb_context *ctdb, uint32_t pnn,
562 uint64_t srvid, TDB_DATA data)
564 struct ctdb_req_message_old *r;
567 len = offsetof(struct ctdb_req_message_old, data) + data.dsize;
568 r = ctdbd_allocate_pkt(ctdb, ctdb, CTDB_REQ_MESSAGE,
569 len, struct ctdb_req_message_old);
570 CTDB_NO_MEMORY(ctdb, r);
572 r->hdr.destnode = pnn;
574 r->datalen = data.dsize;
575 memcpy(&r->data[0], data.dptr, data.dsize);
577 res = ctdb_client_queue_pkt(ctdb, &r->hdr);
584 cancel a ctdb_fetch_lock operation, releasing the lock
586 static int fetch_lock_destructor(struct ctdb_record_handle *h)
588 ctdb_ltdb_unlock(h->ctdb_db, h->key);
593 force the migration of a record to this node
595 static int ctdb_client_force_migration(struct ctdb_db_context *ctdb_db, TDB_DATA key)
597 struct ctdb_call call;
599 call.call_id = CTDB_NULL_FUNC;
601 call.flags = CTDB_IMMEDIATE_MIGRATION;
602 return ctdb_call(ctdb_db, &call);
606 try to fetch a readonly copy of a record
609 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)
613 struct ctdb_call call;
616 call.call_id = CTDB_FETCH_WITH_HEADER_FUNC;
617 call.call_data.dptr = NULL;
618 call.call_data.dsize = 0;
620 call.flags = CTDB_WANT_READONLY;
621 ret = ctdb_call(ctdb_db, &call);
626 if (call.reply_data.dsize < sizeof(struct ctdb_ltdb_header)) {
630 *hdr = talloc_memdup(mem_ctx, &call.reply_data.dptr[0], sizeof(struct ctdb_ltdb_header));
632 talloc_free(call.reply_data.dptr);
636 data->dsize = call.reply_data.dsize - sizeof(struct ctdb_ltdb_header);
637 data->dptr = talloc_memdup(mem_ctx, &call.reply_data.dptr[sizeof(struct ctdb_ltdb_header)], data->dsize);
638 if (data->dptr == NULL) {
639 talloc_free(call.reply_data.dptr);
648 get a lock on a record, and return the records data. Blocks until it gets the lock
650 struct ctdb_record_handle *ctdb_fetch_lock(struct ctdb_db_context *ctdb_db, TALLOC_CTX *mem_ctx,
651 TDB_DATA key, TDB_DATA *data)
654 struct ctdb_record_handle *h;
657 procedure is as follows:
659 1) get the chain lock.
660 2) check if we are dmaster
661 3) if we are the dmaster then return handle
662 4) if not dmaster then ask ctdb daemon to make us dmaster, and wait for
664 5) when we get the reply, goto (1)
667 h = talloc_zero(mem_ctx, struct ctdb_record_handle);
672 h->ctdb_db = ctdb_db;
674 h->key.dptr = talloc_memdup(h, key.dptr, key.dsize);
675 if (h->key.dptr == NULL) {
681 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: key=%*.*s\n", (int)key.dsize, (int)key.dsize,
682 (const char *)key.dptr));
685 /* step 1 - get the chain lock */
686 ret = ctdb_ltdb_lock(ctdb_db, key);
688 DEBUG(DEBUG_ERR, (__location__ " failed to lock ltdb record\n"));
693 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: got chain lock\n"));
695 talloc_set_destructor(h, fetch_lock_destructor);
697 ret = ctdb_ltdb_fetch(ctdb_db, key, &h->header, h, data);
699 /* when torturing, ensure we test the remote path */
700 if ((ctdb_db->ctdb->flags & CTDB_FLAG_TORTURE) &&
702 h->header.dmaster = (uint32_t)-1;
706 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: done local fetch\n"));
708 if (ret != 0 || h->header.dmaster != ctdb_db->ctdb->pnn) {
709 ctdb_ltdb_unlock(ctdb_db, key);
710 ret = ctdb_client_force_migration(ctdb_db, key);
712 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: force_migration failed\n"));
719 /* if this is a request for read/write and we have delegations
720 we have to revoke all delegations first
722 if ((h->header.dmaster == ctdb_db->ctdb->pnn) &&
723 (h->header.flags & CTDB_REC_RO_HAVE_DELEGATIONS)) {
724 ctdb_ltdb_unlock(ctdb_db, key);
725 ret = ctdb_client_force_migration(ctdb_db, key);
727 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
734 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: we are dmaster - done\n"));
739 get a readonly lock on a record, and return the records data. Blocks until it gets the lock
741 struct ctdb_record_handle *
742 ctdb_fetch_readonly_lock(
743 struct ctdb_db_context *ctdb_db, TALLOC_CTX *mem_ctx,
744 TDB_DATA key, TDB_DATA *data,
748 struct ctdb_record_handle *h;
749 struct ctdb_ltdb_header *roheader = NULL;
751 h = talloc_zero(mem_ctx, struct ctdb_record_handle);
756 h->ctdb_db = ctdb_db;
758 h->key.dptr = talloc_memdup(h, key.dptr, key.dsize);
759 if (h->key.dptr == NULL) {
770 talloc_free(roheader);
773 talloc_free(data->dptr);
777 /* Lock the record/chain */
778 ret = ctdb_ltdb_lock(ctdb_db, key);
780 DEBUG(DEBUG_ERR, (__location__ " failed to lock ltdb record\n"));
785 talloc_set_destructor(h, fetch_lock_destructor);
787 /* Check if record exists yet in the TDB */
788 ret = ctdb_ltdb_fetch_with_header(ctdb_db, key, &h->header, h, data);
790 ctdb_ltdb_unlock(ctdb_db, key);
791 ret = ctdb_client_force_migration(ctdb_db, key);
793 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
800 /* if this is a request for read/write and we have delegations
801 we have to revoke all delegations first
804 && (h->header.dmaster == ctdb_db->ctdb->pnn)
805 && (h->header.flags & CTDB_REC_RO_HAVE_DELEGATIONS)) {
806 ctdb_ltdb_unlock(ctdb_db, key);
807 ret = ctdb_client_force_migration(ctdb_db, key);
809 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
816 /* if we are dmaster, just return the handle */
817 if (h->header.dmaster == ctdb_db->ctdb->pnn) {
821 if (read_only != 0) {
822 TDB_DATA rodata = {NULL, 0};
824 if ((h->header.flags & CTDB_REC_RO_HAVE_READONLY)
825 || (h->header.flags & CTDB_REC_RO_HAVE_DELEGATIONS)) {
829 ctdb_ltdb_unlock(ctdb_db, key);
830 ret = ctdb_client_fetch_readonly(ctdb_db, key, h, &roheader, &rodata);
832 DEBUG(DEBUG_ERR,("ctdb_fetch_readonly_lock: failed. force migration and try again\n"));
833 ret = ctdb_client_force_migration(ctdb_db, key);
835 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
843 if (!(roheader->flags&CTDB_REC_RO_HAVE_READONLY)) {
844 ret = ctdb_client_force_migration(ctdb_db, key);
846 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
854 ret = ctdb_ltdb_lock(ctdb_db, key);
856 DEBUG(DEBUG_ERR, (__location__ " failed to lock ltdb record\n"));
861 ret = ctdb_ltdb_fetch_with_header(ctdb_db, key, &h->header, h, data);
863 ctdb_ltdb_unlock(ctdb_db, key);
865 ret = ctdb_client_force_migration(ctdb_db, key);
867 DEBUG(DEBUG_DEBUG,("ctdb_fetch_readonly_lock: force_migration failed\n"));
878 /* we are not dmaster and this was not a request for a readonly lock
879 * so unlock the record, migrate it and try again
881 ctdb_ltdb_unlock(ctdb_db, key);
882 ret = ctdb_client_force_migration(ctdb_db, key);
884 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: force_migration failed\n"));
892 store some data to the record that was locked with ctdb_fetch_lock()
894 int ctdb_record_store(struct ctdb_record_handle *h, TDB_DATA data)
896 if (! ctdb_db_volatile(h->ctdb_db)) {
898 ("ctdb_record_store prohibited for non-volatile dbs\n"));
902 return ctdb_ltdb_store(h->ctdb_db, h->key, &h->header, data);
906 non-locking fetch of a record
908 int ctdb_fetch(struct ctdb_db_context *ctdb_db, TALLOC_CTX *mem_ctx,
909 TDB_DATA key, TDB_DATA *data)
911 struct ctdb_call call;
914 call.call_id = CTDB_FETCH_FUNC;
915 call.call_data.dptr = NULL;
916 call.call_data.dsize = 0;
919 ret = ctdb_call(ctdb_db, &call);
922 *data = call.reply_data;
923 talloc_steal(mem_ctx, data->dptr);
932 called when a control completes or timesout to invoke the callback
933 function the user provided
935 static void invoke_control_callback(struct tevent_context *ev,
936 struct tevent_timer *te,
937 struct timeval t, void *private_data)
939 struct ctdb_client_control_state *state;
940 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
943 state = talloc_get_type(private_data, struct ctdb_client_control_state);
944 talloc_steal(tmp_ctx, state);
946 ret = ctdb_control_recv(state->ctdb, state, state,
951 DEBUG(DEBUG_DEBUG,("ctdb_control_recv() failed, ignoring return code %d\n", ret));
954 talloc_free(tmp_ctx);
958 called when a CTDB_REPLY_CONTROL packet comes in in the client
960 This packet comes in response to a CTDB_REQ_CONTROL request packet. It
961 contains any reply data from the control
963 static void ctdb_client_reply_control(struct ctdb_context *ctdb,
964 struct ctdb_req_header *hdr)
966 struct ctdb_reply_control_old *c = (struct ctdb_reply_control_old *)hdr;
967 struct ctdb_client_control_state *state;
969 state = reqid_find(ctdb->idr, hdr->reqid, struct ctdb_client_control_state);
971 DEBUG(DEBUG_ERR,(__location__ " reqid %u not found\n", hdr->reqid));
975 if (hdr->reqid != state->reqid) {
976 /* we found a record but it was the wrong one */
977 DEBUG(DEBUG_ERR, ("Dropped orphaned reply control with reqid:%u\n",hdr->reqid));
981 state->outdata.dptr = c->data;
982 state->outdata.dsize = c->datalen;
983 state->status = c->status;
985 state->errormsg = talloc_strndup(state,
986 (char *)&c->data[c->datalen],
990 /* state->outdata now uses resources from c so we don't want c
991 to just dissappear from under us while state is still alive
993 talloc_steal(state, c);
995 state->state = CTDB_CONTROL_DONE;
997 /* if we had a callback registered for this control, pull the response
998 and call the callback.
1000 if (state->async.fn) {
1001 tevent_add_timer(ctdb->ev, state, timeval_zero(),
1002 invoke_control_callback, state);
1008 destroy a ctdb_control in client
1010 static int ctdb_client_control_destructor(struct ctdb_client_control_state *state)
1012 reqid_remove(state->ctdb->idr, state->reqid);
1017 /* time out handler for ctdb_control */
1018 static void control_timeout_func(struct tevent_context *ev,
1019 struct tevent_timer *te,
1020 struct timeval t, void *private_data)
1022 struct ctdb_client_control_state *state = talloc_get_type(private_data, struct ctdb_client_control_state);
1024 DEBUG(DEBUG_ERR,(__location__ " control timed out. reqid:%u opcode:%u "
1025 "dstnode:%u\n", state->reqid, state->c->opcode,
1026 state->c->hdr.destnode));
1028 state->state = CTDB_CONTROL_TIMEOUT;
1030 /* if we had a callback registered for this control, pull the response
1031 and call the callback.
1033 if (state->async.fn) {
1034 tevent_add_timer(state->ctdb->ev, state, timeval_zero(),
1035 invoke_control_callback, state);
1039 /* async version of send control request */
1040 struct ctdb_client_control_state *ctdb_control_send(struct ctdb_context *ctdb,
1041 uint32_t destnode, uint64_t srvid,
1042 uint32_t opcode, uint32_t flags, TDB_DATA data,
1043 TALLOC_CTX *mem_ctx,
1044 struct timeval *timeout,
1047 struct ctdb_client_control_state *state;
1049 struct ctdb_req_control_old *c;
1056 /* if the domain socket is not yet open, open it */
1057 if (ctdb->daemon.sd==-1) {
1058 ctdb_socket_connect(ctdb);
1061 state = talloc_zero(mem_ctx, struct ctdb_client_control_state);
1062 CTDB_NO_MEMORY_NULL(ctdb, state);
1065 state->reqid = reqid_new(ctdb->idr, state);
1066 state->state = CTDB_CONTROL_WAIT;
1067 state->errormsg = NULL;
1069 talloc_set_destructor(state, ctdb_client_control_destructor);
1071 len = offsetof(struct ctdb_req_control_old, data) + data.dsize;
1072 c = ctdbd_allocate_pkt(ctdb, state, CTDB_REQ_CONTROL,
1073 len, struct ctdb_req_control_old);
1075 CTDB_NO_MEMORY_NULL(ctdb, c);
1076 c->hdr.reqid = state->reqid;
1077 c->hdr.destnode = destnode;
1082 c->datalen = data.dsize;
1084 memcpy(&c->data[0], data.dptr, data.dsize);
1088 if (timeout && !timeval_is_zero(timeout)) {
1089 tevent_add_timer(ctdb->ev, state, *timeout,
1090 control_timeout_func, state);
1093 ret = ctdb_client_queue_pkt(ctdb, &(c->hdr));
1099 if (flags & CTDB_CTRL_FLAG_NOREPLY) {
1108 /* async version of receive control reply */
1109 int ctdb_control_recv(struct ctdb_context *ctdb,
1110 struct ctdb_client_control_state *state,
1111 TALLOC_CTX *mem_ctx,
1112 TDB_DATA *outdata, int32_t *status, char **errormsg)
1114 TALLOC_CTX *tmp_ctx;
1116 if (status != NULL) {
1119 if (errormsg != NULL) {
1123 if (state == NULL) {
1127 /* prevent double free of state */
1128 tmp_ctx = talloc_new(ctdb);
1129 talloc_steal(tmp_ctx, state);
1131 /* loop one event at a time until we either timeout or the control
1134 while (state->state == CTDB_CONTROL_WAIT) {
1135 tevent_loop_once(ctdb->ev);
1138 if (state->state != CTDB_CONTROL_DONE) {
1139 DEBUG(DEBUG_ERR,(__location__ " ctdb_control_recv failed\n"));
1140 if (state->async.fn) {
1141 state->async.fn(state);
1143 talloc_free(tmp_ctx);
1147 if (state->errormsg) {
1148 int s = (state->status == 0 ? -1 : state->status);
1149 DEBUG(DEBUG_ERR,("ctdb_control error: '%s'\n", state->errormsg));
1151 (*errormsg) = talloc_move(mem_ctx, &state->errormsg);
1153 if (state->async.fn) {
1154 state->async.fn(state);
1156 talloc_free(tmp_ctx);
1161 *outdata = state->outdata;
1162 outdata->dptr = talloc_memdup(mem_ctx, outdata->dptr, outdata->dsize);
1166 *status = state->status;
1169 if (state->async.fn) {
1170 state->async.fn(state);
1173 talloc_free(tmp_ctx);
1180 send a ctdb control message
1181 timeout specifies how long we should wait for a reply.
1182 if timeout is NULL we wait indefinitely
1184 int ctdb_control(struct ctdb_context *ctdb, uint32_t destnode, uint64_t srvid,
1185 uint32_t opcode, uint32_t flags, TDB_DATA data,
1186 TALLOC_CTX *mem_ctx, TDB_DATA *outdata, int32_t *status,
1187 struct timeval *timeout,
1190 struct ctdb_client_control_state *state;
1192 state = ctdb_control_send(ctdb, destnode, srvid, opcode,
1193 flags, data, mem_ctx,
1196 /* FIXME: Error conditions in ctdb_control_send return NULL without
1197 * setting errormsg. So, there is no way to distinguish between sucess
1198 * and failure when CTDB_CTRL_FLAG_NOREPLY is set */
1199 if (flags & CTDB_CTRL_FLAG_NOREPLY) {
1200 if (status != NULL) {
1206 return ctdb_control_recv(ctdb, state, mem_ctx, outdata, status,
1214 a process exists call. Returns 0 if process exists, -1 otherwise
1216 int ctdb_ctrl_process_exists(struct ctdb_context *ctdb, uint32_t destnode, pid_t pid)
1222 data.dptr = (uint8_t*)&pid;
1223 data.dsize = sizeof(pid);
1225 ret = ctdb_control(ctdb, destnode, 0,
1226 CTDB_CONTROL_PROCESS_EXISTS, 0, data,
1227 NULL, NULL, &status, NULL, NULL);
1229 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for process_exists failed\n"));
1237 get remote statistics
1239 int ctdb_ctrl_statistics(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_statistics *status)
1245 ret = ctdb_control(ctdb, destnode, 0,
1246 CTDB_CONTROL_STATISTICS, 0, tdb_null,
1247 ctdb, &data, &res, NULL, NULL);
1248 if (ret != 0 || res != 0) {
1249 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for statistics failed\n"));
1253 if (data.dsize != sizeof(struct ctdb_statistics)) {
1254 DEBUG(DEBUG_ERR,(__location__ " Wrong statistics size %u - expected %u\n",
1255 (unsigned)data.dsize, (unsigned)sizeof(struct ctdb_statistics)));
1259 *status = *(struct ctdb_statistics *)data.dptr;
1260 talloc_free(data.dptr);
1268 int ctdb_ctrl_dbstatistics(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid,
1269 TALLOC_CTX *mem_ctx, struct ctdb_db_statistics_old **dbstat)
1272 TDB_DATA indata, outdata;
1274 struct ctdb_db_statistics_old *wire, *s;
1278 indata.dptr = (uint8_t *)&dbid;
1279 indata.dsize = sizeof(dbid);
1281 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_DB_STATISTICS,
1282 0, indata, ctdb, &outdata, &res, NULL, NULL);
1283 if (ret != 0 || res != 0) {
1284 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for dbstatistics failed\n"));
1288 if (outdata.dsize < offsetof(struct ctdb_db_statistics_old, hot_keys_wire)) {
1289 DEBUG(DEBUG_ERR,(__location__ " Wrong dbstatistics size %zi - expected >= %lu\n",
1291 (long unsigned int)sizeof(struct ctdb_statistics)));
1295 s = talloc_zero(mem_ctx, struct ctdb_db_statistics_old);
1297 talloc_free(outdata.dptr);
1298 CTDB_NO_MEMORY(ctdb, s);
1301 wire = (struct ctdb_db_statistics_old *)outdata.dptr;
1302 memcpy(s, wire, offsetof(struct ctdb_db_statistics_old, hot_keys_wire));
1303 ptr = &wire->hot_keys_wire[0];
1304 for (i=0; i<wire->num_hot_keys; i++) {
1305 s->hot_keys[i].key.dptr = talloc_size(mem_ctx, s->hot_keys[i].key.dsize);
1306 if (s->hot_keys[i].key.dptr == NULL) {
1307 talloc_free(outdata.dptr);
1308 CTDB_NO_MEMORY(ctdb, s->hot_keys[i].key.dptr);
1311 memcpy(s->hot_keys[i].key.dptr, ptr, s->hot_keys[i].key.dsize);
1312 ptr += wire->hot_keys[i].key.dsize;
1315 talloc_free(outdata.dptr);
1321 shutdown a remote ctdb node
1323 int ctdb_ctrl_shutdown(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
1325 struct ctdb_client_control_state *state;
1327 state = ctdb_control_send(ctdb, destnode, 0,
1328 CTDB_CONTROL_SHUTDOWN, 0, tdb_null,
1329 NULL, &timeout, NULL);
1330 if (state == NULL) {
1331 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for shutdown failed\n"));
1339 get vnn map from a remote node
1341 int ctdb_ctrl_getvnnmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_vnn_map **vnnmap)
1346 struct ctdb_vnn_map_wire *map;
1348 ret = ctdb_control(ctdb, destnode, 0,
1349 CTDB_CONTROL_GETVNNMAP, 0, tdb_null,
1350 mem_ctx, &outdata, &res, &timeout, NULL);
1351 if (ret != 0 || res != 0) {
1352 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getvnnmap failed\n"));
1356 map = (struct ctdb_vnn_map_wire *)outdata.dptr;
1357 if (outdata.dsize < offsetof(struct ctdb_vnn_map_wire, map) ||
1358 outdata.dsize != map->size*sizeof(uint32_t) + offsetof(struct ctdb_vnn_map_wire, map)) {
1359 DEBUG(DEBUG_ERR,("Bad vnn map size received in ctdb_ctrl_getvnnmap\n"));
1363 (*vnnmap) = talloc(mem_ctx, struct ctdb_vnn_map);
1364 CTDB_NO_MEMORY(ctdb, *vnnmap);
1365 (*vnnmap)->generation = map->generation;
1366 (*vnnmap)->size = map->size;
1367 (*vnnmap)->map = talloc_array(*vnnmap, uint32_t, map->size);
1369 CTDB_NO_MEMORY(ctdb, (*vnnmap)->map);
1370 memcpy((*vnnmap)->map, map->map, sizeof(uint32_t)*map->size);
1371 talloc_free(outdata.dptr);
1378 get the recovery mode of a remote node
1380 struct ctdb_client_control_state *
1381 ctdb_ctrl_getrecmode_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode)
1383 return ctdb_control_send(ctdb, destnode, 0,
1384 CTDB_CONTROL_GET_RECMODE, 0, tdb_null,
1385 mem_ctx, &timeout, NULL);
1388 int ctdb_ctrl_getrecmode_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *recmode)
1393 ret = ctdb_control_recv(ctdb, state, mem_ctx, NULL, &res, NULL);
1395 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_getrecmode_recv failed\n"));
1400 *recmode = (uint32_t)res;
1406 int ctdb_ctrl_getrecmode(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, uint32_t *recmode)
1408 struct ctdb_client_control_state *state;
1410 state = ctdb_ctrl_getrecmode_send(ctdb, mem_ctx, timeout, destnode);
1411 return ctdb_ctrl_getrecmode_recv(ctdb, mem_ctx, state, recmode);
1418 set the recovery mode of a remote node
1420 int ctdb_ctrl_setrecmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmode)
1426 data.dsize = sizeof(uint32_t);
1427 data.dptr = (unsigned char *)&recmode;
1429 ret = ctdb_control(ctdb, destnode, 0,
1430 CTDB_CONTROL_SET_RECMODE, 0, data,
1431 NULL, NULL, &res, &timeout, NULL);
1432 if (ret != 0 || res != 0) {
1433 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setrecmode failed\n"));
1443 get the recovery master of a remote node
1445 struct ctdb_client_control_state *
1446 ctdb_ctrl_getrecmaster_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx,
1447 struct timeval timeout, uint32_t destnode)
1449 return ctdb_control_send(ctdb, destnode, 0,
1450 CTDB_CONTROL_GET_RECMASTER, 0, tdb_null,
1451 mem_ctx, &timeout, NULL);
1454 int ctdb_ctrl_getrecmaster_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *recmaster)
1459 ret = ctdb_control_recv(ctdb, state, mem_ctx, NULL, &res, NULL);
1461 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_getrecmaster_recv failed\n"));
1466 *recmaster = (uint32_t)res;
1472 int ctdb_ctrl_getrecmaster(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, uint32_t *recmaster)
1474 struct ctdb_client_control_state *state;
1476 state = ctdb_ctrl_getrecmaster_send(ctdb, mem_ctx, timeout, destnode);
1477 return ctdb_ctrl_getrecmaster_recv(ctdb, mem_ctx, state, recmaster);
1482 set the recovery master of a remote node
1484 int ctdb_ctrl_setrecmaster(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmaster)
1491 data.dsize = sizeof(uint32_t);
1492 data.dptr = (unsigned char *)&recmaster;
1494 ret = ctdb_control(ctdb, destnode, 0,
1495 CTDB_CONTROL_SET_RECMASTER, 0, data,
1496 NULL, NULL, &res, &timeout, NULL);
1497 if (ret != 0 || res != 0) {
1498 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setrecmaster failed\n"));
1507 get a list of databases off a remote node
1509 int ctdb_ctrl_getdbmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
1510 TALLOC_CTX *mem_ctx, struct ctdb_dbid_map_old **dbmap)
1516 ret = ctdb_control(ctdb, destnode, 0,
1517 CTDB_CONTROL_GET_DBMAP, 0, tdb_null,
1518 mem_ctx, &outdata, &res, &timeout, NULL);
1519 if (ret != 0 || res != 0) {
1520 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getdbmap failed ret:%d res:%d\n", ret, res));
1524 *dbmap = (struct ctdb_dbid_map_old *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
1525 talloc_free(outdata.dptr);
1531 get a list of nodes (vnn and flags ) from a remote node
1533 int ctdb_ctrl_getnodemap(struct ctdb_context *ctdb,
1534 struct timeval timeout, uint32_t destnode,
1535 TALLOC_CTX *mem_ctx, struct ctdb_node_map_old **nodemap)
1541 ret = ctdb_control(ctdb, destnode, 0,
1542 CTDB_CONTROL_GET_NODEMAP, 0, tdb_null,
1543 mem_ctx, &outdata, &res, &timeout, NULL);
1544 if (ret != 0 || res != 0 || outdata.dsize == 0) {
1545 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getnodes failed ret:%d res:%d\n", ret, res));
1549 *nodemap = (struct ctdb_node_map_old *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
1550 talloc_free(outdata.dptr);
1555 load nodes file on a remote node and return as a node map
1557 int ctdb_ctrl_getnodesfile(struct ctdb_context *ctdb,
1558 struct timeval timeout, uint32_t destnode,
1559 TALLOC_CTX *mem_ctx, struct ctdb_node_map_old **nodemap)
1565 ret = ctdb_control(ctdb, destnode, 0,
1566 CTDB_CONTROL_GET_NODES_FILE, 0, tdb_null,
1567 mem_ctx, &outdata, &res, &timeout, NULL);
1568 if (ret != 0 || res != 0 || outdata.dsize == 0) {
1569 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getnodes failed ret:%d res:%d\n", ret, res));
1573 *nodemap = (struct ctdb_node_map_old *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
1574 talloc_free(outdata.dptr);
1580 drop the transport, reload the nodes file and restart the transport
1582 int ctdb_ctrl_reload_nodes_file(struct ctdb_context *ctdb,
1583 struct timeval timeout, uint32_t destnode)
1588 ret = ctdb_control(ctdb, destnode, 0,
1589 CTDB_CONTROL_RELOAD_NODES_FILE, 0, tdb_null,
1590 NULL, NULL, &res, &timeout, NULL);
1591 if (ret != 0 || res != 0) {
1592 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for reloadnodesfile failed\n"));
1601 set vnn map on a node
1603 int ctdb_ctrl_setvnnmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
1604 TALLOC_CTX *mem_ctx, struct ctdb_vnn_map *vnnmap)
1609 struct ctdb_vnn_map_wire *map;
1612 len = offsetof(struct ctdb_vnn_map_wire, map) + sizeof(uint32_t)*vnnmap->size;
1613 map = talloc_size(mem_ctx, len);
1614 CTDB_NO_MEMORY(ctdb, map);
1616 map->generation = vnnmap->generation;
1617 map->size = vnnmap->size;
1618 memcpy(map->map, vnnmap->map, sizeof(uint32_t)*map->size);
1621 data.dptr = (uint8_t *)map;
1623 ret = ctdb_control(ctdb, destnode, 0,
1624 CTDB_CONTROL_SETVNNMAP, 0, data,
1625 NULL, NULL, &res, &timeout, NULL);
1626 if (ret != 0 || res != 0) {
1627 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setvnnmap failed\n"));
1638 async send for pull database
1640 struct ctdb_client_control_state *ctdb_ctrl_pulldb_send(
1641 struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid,
1642 uint32_t lmaster, TALLOC_CTX *mem_ctx, struct timeval timeout)
1645 struct ctdb_pulldb *pull;
1646 struct ctdb_client_control_state *state;
1648 pull = talloc(mem_ctx, struct ctdb_pulldb);
1649 CTDB_NO_MEMORY_NULL(ctdb, pull);
1652 pull->lmaster = lmaster;
1654 indata.dsize = sizeof(struct ctdb_pulldb);
1655 indata.dptr = (unsigned char *)pull;
1657 state = ctdb_control_send(ctdb, destnode, 0,
1658 CTDB_CONTROL_PULL_DB, 0, indata,
1659 mem_ctx, &timeout, NULL);
1666 async recv for pull database
1668 int ctdb_ctrl_pulldb_recv(
1669 struct ctdb_context *ctdb,
1670 TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state,
1676 ret = ctdb_control_recv(ctdb, state, mem_ctx, outdata, &res, NULL);
1677 if ( (ret != 0) || (res != 0) ){
1678 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_pulldb_recv failed\n"));
1686 pull all keys and records for a specific database on a node
1688 int ctdb_ctrl_pulldb(struct ctdb_context *ctdb, uint32_t destnode,
1689 uint32_t dbid, uint32_t lmaster,
1690 TALLOC_CTX *mem_ctx, struct timeval timeout,
1693 struct ctdb_client_control_state *state;
1695 state = ctdb_ctrl_pulldb_send(ctdb, destnode, dbid, lmaster, mem_ctx,
1698 return ctdb_ctrl_pulldb_recv(ctdb, mem_ctx, state, outdata);
1703 change dmaster for all keys in the database to the new value
1705 int ctdb_ctrl_setdmaster(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
1706 TALLOC_CTX *mem_ctx, uint32_t dbid, uint32_t dmaster)
1712 indata.dsize = 2*sizeof(uint32_t);
1713 indata.dptr = (unsigned char *)talloc_array(mem_ctx, uint32_t, 2);
1715 ((uint32_t *)(&indata.dptr[0]))[0] = dbid;
1716 ((uint32_t *)(&indata.dptr[0]))[1] = dmaster;
1718 ret = ctdb_control(ctdb, destnode, 0,
1719 CTDB_CONTROL_SET_DMASTER, 0, indata,
1720 NULL, NULL, &res, &timeout, NULL);
1721 if (ret != 0 || res != 0) {
1722 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setdmaster failed\n"));
1730 ping a node, return number of clients connected
1732 int ctdb_ctrl_ping(struct ctdb_context *ctdb, uint32_t destnode)
1737 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_PING, 0,
1738 tdb_null, NULL, NULL, &res, NULL, NULL);
1745 int ctdb_ctrl_get_runstate(struct ctdb_context *ctdb,
1746 struct timeval timeout,
1754 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_RUNSTATE, 0,
1755 tdb_null, ctdb, &outdata, &res, &timeout, NULL);
1756 if (ret != 0 || res != 0) {
1757 DEBUG(DEBUG_ERR,("ctdb_control for get_runstate failed\n"));
1758 return ret != 0 ? ret : res;
1761 if (outdata.dsize != sizeof(uint32_t)) {
1762 DEBUG(DEBUG_ERR,("Invalid return data in get_runstate\n"));
1763 talloc_free(outdata.dptr);
1767 if (runstate != NULL) {
1768 *runstate = *(uint32_t *)outdata.dptr;
1770 talloc_free(outdata.dptr);
1776 find the real path to a ltdb
1778 int ctdb_ctrl_getdbpath(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t dbid, TALLOC_CTX *mem_ctx,
1785 data.dptr = (uint8_t *)&dbid;
1786 data.dsize = sizeof(dbid);
1788 ret = ctdb_control(ctdb, destnode, 0,
1789 CTDB_CONTROL_GETDBPATH, 0, data,
1790 mem_ctx, &data, &res, &timeout, NULL);
1791 if (ret != 0 || res != 0) {
1795 (*path) = talloc_strndup(mem_ctx, (const char *)data.dptr, data.dsize);
1796 if ((*path) == NULL) {
1800 talloc_free(data.dptr);
1806 find the name of a db
1808 int ctdb_ctrl_getdbname(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t dbid, TALLOC_CTX *mem_ctx,
1815 data.dptr = (uint8_t *)&dbid;
1816 data.dsize = sizeof(dbid);
1818 ret = ctdb_control(ctdb, destnode, 0,
1819 CTDB_CONTROL_GET_DBNAME, 0, data,
1820 mem_ctx, &data, &res, &timeout, NULL);
1821 if (ret != 0 || res != 0) {
1825 (*name) = talloc_strndup(mem_ctx, (const char *)data.dptr, data.dsize);
1826 if ((*name) == NULL) {
1830 talloc_free(data.dptr);
1836 get the health status of a db
1838 int ctdb_ctrl_getdbhealth(struct ctdb_context *ctdb,
1839 struct timeval timeout,
1841 uint32_t dbid, TALLOC_CTX *mem_ctx,
1842 const char **reason)
1848 data.dptr = (uint8_t *)&dbid;
1849 data.dsize = sizeof(dbid);
1851 ret = ctdb_control(ctdb, destnode, 0,
1852 CTDB_CONTROL_DB_GET_HEALTH, 0, data,
1853 mem_ctx, &data, &res, &timeout, NULL);
1854 if (ret != 0 || res != 0) {
1858 if (data.dsize == 0) {
1863 (*reason) = talloc_strndup(mem_ctx, (const char *)data.dptr, data.dsize);
1864 if ((*reason) == NULL) {
1868 talloc_free(data.dptr);
1874 * get db sequence number
1876 int ctdb_ctrl_getdbseqnum(struct ctdb_context *ctdb, struct timeval timeout,
1877 uint32_t destnode, uint32_t dbid, uint64_t *seqnum)
1881 TDB_DATA data, outdata;
1882 uint8_t buf[sizeof(uint64_t)] = { 0 };
1884 *(uint32_t *)buf = dbid;
1886 data.dsize = sizeof(uint64_t);
1888 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_DB_SEQNUM,
1889 0, data, ctdb, &outdata, &res, &timeout, NULL);
1890 if (ret != 0 || res != 0) {
1891 DEBUG(DEBUG_ERR,("ctdb_control for getdbesqnum failed\n"));
1895 if (outdata.dsize != sizeof(uint64_t)) {
1896 DEBUG(DEBUG_ERR,("Invalid return data in get_dbseqnum\n"));
1897 talloc_free(outdata.dptr);
1901 if (seqnum != NULL) {
1902 *seqnum = *(uint64_t *)outdata.dptr;
1904 talloc_free(outdata.dptr);
1912 int ctdb_ctrl_createdb(struct ctdb_context *ctdb, struct timeval timeout,
1913 uint32_t destnode, TALLOC_CTX *mem_ctx,
1914 const char *name, uint8_t db_flags, uint32_t *db_id)
1921 data.dptr = discard_const(name);
1922 data.dsize = strlen(name)+1;
1924 if (db_flags & CTDB_DB_FLAGS_PERSISTENT) {
1925 opcode = CTDB_CONTROL_DB_ATTACH_PERSISTENT;
1926 } else if (db_flags & CTDB_DB_FLAGS_REPLICATED) {
1927 opcode = CTDB_CONTROL_DB_ATTACH_REPLICATED;
1929 opcode = CTDB_CONTROL_DB_ATTACH;
1932 ret = ctdb_control(ctdb, destnode, 0, opcode, 0, data,
1933 mem_ctx, &data, &res, &timeout, NULL);
1935 if (ret != 0 || res != 0) {
1939 if (data.dsize != sizeof(uint32_t)) {
1940 TALLOC_FREE(data.dptr);
1943 if (db_id != NULL) {
1944 *db_id = *(uint32_t *)data.dptr;
1946 talloc_free(data.dptr);
1952 get debug level on a node
1954 int ctdb_ctrl_get_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, int32_t *level)
1960 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_DEBUG, 0, tdb_null,
1961 ctdb, &data, &res, NULL, NULL);
1962 if (ret != 0 || res != 0) {
1965 if (data.dsize != sizeof(int32_t)) {
1966 DEBUG(DEBUG_ERR,("Bad control reply size in ctdb_get_debuglevel (got %u)\n",
1967 (unsigned)data.dsize));
1970 *level = *(int32_t *)data.dptr;
1971 talloc_free(data.dptr);
1976 set debug level on a node
1978 int ctdb_ctrl_set_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, int32_t level)
1984 data.dptr = (uint8_t *)&level;
1985 data.dsize = sizeof(level);
1987 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SET_DEBUG, 0, data,
1988 NULL, NULL, &res, NULL, NULL);
1989 if (ret != 0 || res != 0) {
1997 get a list of connected nodes
1999 uint32_t *ctdb_get_connected_nodes(struct ctdb_context *ctdb,
2000 struct timeval timeout,
2001 TALLOC_CTX *mem_ctx,
2002 uint32_t *num_nodes)
2004 struct ctdb_node_map_old *map=NULL;
2010 ret = ctdb_ctrl_getnodemap(ctdb, timeout, CTDB_CURRENT_NODE, mem_ctx, &map);
2015 nodes = talloc_array(mem_ctx, uint32_t, map->num);
2016 if (nodes == NULL) {
2020 for (i=0;i<map->num;i++) {
2021 if (!(map->nodes[i].flags & NODE_FLAGS_DISCONNECTED)) {
2022 nodes[*num_nodes] = map->nodes[i].pnn;
2034 int ctdb_statistics_reset(struct ctdb_context *ctdb, uint32_t destnode)
2039 ret = ctdb_control(ctdb, destnode, 0,
2040 CTDB_CONTROL_STATISTICS_RESET, 0, tdb_null,
2041 NULL, NULL, &res, NULL, NULL);
2042 if (ret != 0 || res != 0) {
2043 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for reset statistics failed\n"));
2052 int ctdb_ctrl_db_open_flags(struct ctdb_context *ctdb, uint32_t db_id,
2055 TDB_DATA indata, outdata;
2059 indata.dptr = (uint8_t *)&db_id;
2060 indata.dsize = sizeof(db_id);
2062 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0,
2063 CTDB_CONTROL_DB_OPEN_FLAGS, 0, indata,
2064 ctdb, &outdata, &res, NULL, NULL);
2065 if (ret != 0 || res != 0) {
2066 D_ERR("ctdb control for db open flags failed\n");
2070 if (outdata.dsize != sizeof(int32_t)) {
2071 D_ERR(__location__ " expected %zi bytes, received %zi bytes\n",
2072 sizeof(int32_t), outdata.dsize);
2073 talloc_free(outdata.dptr);
2077 *tdb_flags = *(int32_t *)outdata.dptr;
2078 talloc_free(outdata.dptr);
2083 attach to a specific database - client call
2085 struct ctdb_db_context *ctdb_attach(struct ctdb_context *ctdb,
2086 struct timeval timeout,
2090 struct ctdb_db_context *ctdb_db;
2094 ctdb_db = ctdb_db_handle(ctdb, name);
2099 ctdb_db = talloc_zero(ctdb, struct ctdb_db_context);
2100 CTDB_NO_MEMORY_NULL(ctdb, ctdb_db);
2102 ctdb_db->ctdb = ctdb;
2103 ctdb_db->db_name = talloc_strdup(ctdb_db, name);
2104 CTDB_NO_MEMORY_NULL(ctdb, ctdb_db->db_name);
2106 /* tell ctdb daemon to attach */
2107 ret = ctdb_ctrl_createdb(ctdb, timeout, CTDB_CURRENT_NODE,
2108 ctdb_db, name, db_flags, &ctdb_db->db_id);
2110 DEBUG(DEBUG_ERR,("Failed to attach to database '%s'\n", name));
2111 talloc_free(ctdb_db);
2115 ret = ctdb_ctrl_getdbpath(ctdb, timeout, CTDB_CURRENT_NODE, ctdb_db->db_id, ctdb_db, &ctdb_db->db_path);
2117 DEBUG(DEBUG_ERR,("Failed to get dbpath for database '%s'\n", name));
2118 talloc_free(ctdb_db);
2122 ret = ctdb_ctrl_db_open_flags(ctdb, ctdb_db->db_id, &tdb_flags);
2124 D_ERR("Failed to get tdb_flags for database '%s'\n", name);
2125 talloc_free(ctdb_db);
2129 ctdb_db->ltdb = tdb_wrap_open(ctdb_db, ctdb_db->db_path, 0, tdb_flags,
2131 if (ctdb_db->ltdb == NULL) {
2132 ctdb_set_error(ctdb, "Failed to open tdb '%s'\n", ctdb_db->db_path);
2133 talloc_free(ctdb_db);
2137 ctdb_db->db_flags = db_flags;
2139 DLIST_ADD(ctdb->db_list, ctdb_db);
2141 /* add well known functions */
2142 ctdb_set_call(ctdb_db, ctdb_null_func, CTDB_NULL_FUNC);
2143 ctdb_set_call(ctdb_db, ctdb_fetch_func, CTDB_FETCH_FUNC);
2144 ctdb_set_call(ctdb_db, ctdb_fetch_with_header_func, CTDB_FETCH_WITH_HEADER_FUNC);
2150 * detach from a specific database - client call
2152 int ctdb_detach(struct ctdb_context *ctdb, uint32_t db_id)
2158 data.dsize = sizeof(db_id);
2159 data.dptr = (uint8_t *)&db_id;
2161 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_DB_DETACH,
2162 0, data, NULL, NULL, &status, NULL, NULL);
2163 if (ret != 0 || status != 0) {
2170 setup a call for a database
2172 int ctdb_set_call(struct ctdb_db_context *ctdb_db, ctdb_fn_t fn, uint32_t id)
2174 struct ctdb_registered_call *call;
2176 /* register locally */
2177 call = talloc(ctdb_db, struct ctdb_registered_call);
2181 DLIST_ADD(ctdb_db->calls, call);
2186 struct traverse_state {
2189 ctdb_traverse_func fn;
2191 bool listemptyrecords;
2195 called on each key during a ctdb_traverse
2197 static void traverse_handler(uint64_t srvid, TDB_DATA data, void *p)
2199 struct traverse_state *state = (struct traverse_state *)p;
2200 struct ctdb_rec_data_old *d = (struct ctdb_rec_data_old *)data.dptr;
2203 if (data.dsize < sizeof(uint32_t) || d->length != data.dsize) {
2204 DEBUG(DEBUG_ERR, ("Bad data size %u in traverse_handler\n",
2205 (unsigned)data.dsize));
2210 key.dsize = d->keylen;
2211 key.dptr = &d->data[0];
2212 data.dsize = d->datalen;
2213 data.dptr = &d->data[d->keylen];
2215 if (key.dsize == 0 && data.dsize == 0) {
2216 /* end of traverse */
2221 if (!state->listemptyrecords &&
2222 data.dsize == sizeof(struct ctdb_ltdb_header))
2224 /* empty records are deleted records in ctdb */
2228 if (state->fn(key, data, state->private_data) != 0) {
2236 * start a cluster wide traverse, calling the supplied fn on each record
2237 * return the number of records traversed, or -1 on error
2239 * Extendet variant with a flag to signal whether empty records should
2242 static int ctdb_traverse_ext(struct ctdb_db_context *ctdb_db,
2243 ctdb_traverse_func fn,
2244 bool withemptyrecords,
2248 struct ctdb_traverse_start_ext t;
2251 uint64_t srvid = (getpid() | 0xFLL<<60);
2252 struct traverse_state state;
2256 state.private_data = private_data;
2258 state.listemptyrecords = withemptyrecords;
2260 ret = ctdb_client_set_message_handler(ctdb_db->ctdb, srvid, traverse_handler, &state);
2262 DEBUG(DEBUG_ERR,("Failed to setup traverse handler\n"));
2266 t.db_id = ctdb_db->db_id;
2269 t.withemptyrecords = withemptyrecords;
2271 data.dptr = (uint8_t *)&t;
2272 data.dsize = sizeof(t);
2274 ret = ctdb_control(ctdb_db->ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_TRAVERSE_START_EXT, 0,
2275 data, NULL, NULL, &status, NULL, NULL);
2276 if (ret != 0 || status != 0) {
2277 DEBUG(DEBUG_ERR,("ctdb_traverse_all failed\n"));
2278 ctdb_client_remove_message_handler(ctdb_db->ctdb, srvid, &state);
2282 while (!state.done) {
2283 tevent_loop_once(ctdb_db->ctdb->ev);
2286 ret = ctdb_client_remove_message_handler(ctdb_db->ctdb, srvid, &state);
2288 DEBUG(DEBUG_ERR,("Failed to remove ctdb_traverse handler\n"));
2296 * start a cluster wide traverse, calling the supplied fn on each record
2297 * return the number of records traversed, or -1 on error
2299 * Standard version which does not list the empty records:
2300 * These are considered deleted.
2302 int ctdb_traverse(struct ctdb_db_context *ctdb_db, ctdb_traverse_func fn, void *private_data)
2304 return ctdb_traverse_ext(ctdb_db, fn, false, private_data);
2307 #define ISASCII(x) (isprint(x) && !strchr("\"\\", (x)))
2309 called on each key during a catdb
2311 int ctdb_dumpdb_record(TDB_DATA key, TDB_DATA data, void *p)
2314 struct ctdb_dump_db_context *c = (struct ctdb_dump_db_context *)p;
2316 struct ctdb_ltdb_header *h = (struct ctdb_ltdb_header *)data.dptr;
2318 fprintf(f, "key(%u) = \"", (unsigned)key.dsize);
2319 for (i=0;i<key.dsize;i++) {
2320 if (ISASCII(key.dptr[i])) {
2321 fprintf(f, "%c", key.dptr[i]);
2323 fprintf(f, "\\%02X", key.dptr[i]);
2328 fprintf(f, "dmaster: %u\n", h->dmaster);
2329 fprintf(f, "rsn: %llu\n", (unsigned long long)h->rsn);
2331 if (c->printlmaster && c->ctdb->vnn_map != NULL) {
2332 fprintf(f, "lmaster: %u\n", ctdb_lmaster(c->ctdb, &key));
2336 fprintf(f, "hash: 0x%08x\n", ctdb_hash(&key));
2339 if (c->printrecordflags) {
2340 fprintf(f, "flags: 0x%08x", h->flags);
2341 if (h->flags & CTDB_REC_FLAG_MIGRATED_WITH_DATA) printf(" MIGRATED_WITH_DATA");
2342 if (h->flags & CTDB_REC_FLAG_VACUUM_MIGRATED) printf(" VACUUM_MIGRATED");
2343 if (h->flags & CTDB_REC_FLAG_AUTOMATIC) printf(" AUTOMATIC");
2344 if (h->flags & CTDB_REC_RO_HAVE_DELEGATIONS) printf(" RO_HAVE_DELEGATIONS");
2345 if (h->flags & CTDB_REC_RO_HAVE_READONLY) printf(" RO_HAVE_READONLY");
2346 if (h->flags & CTDB_REC_RO_REVOKING_READONLY) printf(" RO_REVOKING_READONLY");
2347 if (h->flags & CTDB_REC_RO_REVOKE_COMPLETE) printf(" RO_REVOKE_COMPLETE");
2351 if (c->printdatasize) {
2352 fprintf(f, "data size: %u\n", (unsigned)data.dsize);
2354 fprintf(f, "data(%u) = \"", (unsigned)(data.dsize - sizeof(*h)));
2355 for (i=sizeof(*h);i<data.dsize;i++) {
2356 if (ISASCII(data.dptr[i])) {
2357 fprintf(f, "%c", data.dptr[i]);
2359 fprintf(f, "\\%02X", data.dptr[i]);
2371 convenience function to list all keys to stdout
2373 int ctdb_dump_db(struct ctdb_db_context *ctdb_db,
2374 struct ctdb_dump_db_context *ctx)
2376 return ctdb_traverse_ext(ctdb_db, ctdb_dumpdb_record,
2377 ctx->printemptyrecords, ctx);
2381 get the pid of a ctdb daemon
2383 int ctdb_ctrl_getpid(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *pid)
2388 ret = ctdb_control(ctdb, destnode, 0,
2389 CTDB_CONTROL_GET_PID, 0, tdb_null,
2390 NULL, NULL, &res, &timeout, NULL);
2392 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getpid failed\n"));
2401 /* Freeze all databases */
2402 int ctdb_ctrl_freeze(struct ctdb_context *ctdb, struct timeval timeout,
2408 ret = ctdb_control(ctdb, destnode, 0,
2409 CTDB_CONTROL_FREEZE, 0, tdb_null,
2410 NULL, NULL, &res, &timeout, NULL);
2411 if (ret != 0 || res != 0) {
2412 DEBUG(DEBUG_ERR, ("ctdb_ctrl_freeze_priority failed\n"));
2420 get pnn of a node, or -1
2422 int ctdb_ctrl_getpnn(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2427 ret = ctdb_control(ctdb, destnode, 0,
2428 CTDB_CONTROL_GET_PNN, 0, tdb_null,
2429 NULL, NULL, &res, &timeout, NULL);
2431 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getpnn failed\n"));
2440 sent to a node to make it take over an ip address
2442 int ctdb_ctrl_takeover_ip(struct ctdb_context *ctdb, struct timeval timeout,
2443 uint32_t destnode, struct ctdb_public_ip *ip)
2449 data.dsize = sizeof(*ip);
2450 data.dptr = (uint8_t *)ip;
2452 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_TAKEOVER_IP, 0,
2453 data, NULL, NULL, &res, &timeout, NULL);
2454 if (ret != 0 || res != 0) {
2455 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for takeover_ip failed\n"));
2464 sent to a node to make it release an ip address
2466 int ctdb_ctrl_release_ip(struct ctdb_context *ctdb, struct timeval timeout,
2467 uint32_t destnode, struct ctdb_public_ip *ip)
2473 data.dsize = sizeof(*ip);
2474 data.dptr = (uint8_t *)ip;
2476 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_RELEASE_IP, 0,
2477 data, NULL, NULL, &res, &timeout, NULL);
2478 if (ret != 0 || res != 0) {
2479 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for release_ip failed\n"));
2490 int ctdb_ctrl_get_tunable(struct ctdb_context *ctdb,
2491 struct timeval timeout,
2493 const char *name, uint32_t *value)
2495 struct ctdb_control_get_tunable *t;
2496 TDB_DATA data, outdata;
2500 data.dsize = offsetof(struct ctdb_control_get_tunable, name) + strlen(name) + 1;
2501 data.dptr = talloc_size(ctdb, data.dsize);
2502 CTDB_NO_MEMORY(ctdb, data.dptr);
2504 t = (struct ctdb_control_get_tunable *)data.dptr;
2505 t->length = strlen(name)+1;
2506 memcpy(t->name, name, t->length);
2508 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_TUNABLE, 0, data, ctdb,
2509 &outdata, &res, &timeout, NULL);
2510 talloc_free(data.dptr);
2511 if (ret != 0 || res != 0) {
2512 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get_tunable failed\n"));
2513 return ret != 0 ? ret : res;
2516 if (outdata.dsize != sizeof(uint32_t)) {
2517 DEBUG(DEBUG_ERR,("Invalid return data in get_tunable\n"));
2518 talloc_free(outdata.dptr);
2522 *value = *(uint32_t *)outdata.dptr;
2523 talloc_free(outdata.dptr);
2531 int ctdb_ctrl_set_tunable(struct ctdb_context *ctdb,
2532 struct timeval timeout,
2534 const char *name, uint32_t value)
2536 struct ctdb_tunable_old *t;
2541 data.dsize = offsetof(struct ctdb_tunable_old, name) + strlen(name) + 1;
2542 data.dptr = talloc_size(ctdb, data.dsize);
2543 CTDB_NO_MEMORY(ctdb, data.dptr);
2545 t = (struct ctdb_tunable_old *)data.dptr;
2546 t->length = strlen(name)+1;
2547 memcpy(t->name, name, t->length);
2550 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SET_TUNABLE, 0, data, NULL,
2551 NULL, &res, &timeout, NULL);
2552 talloc_free(data.dptr);
2553 if ((ret != 0) || (res == -1)) {
2554 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set_tunable failed\n"));
2564 int ctdb_ctrl_list_tunables(struct ctdb_context *ctdb,
2565 struct timeval timeout,
2567 TALLOC_CTX *mem_ctx,
2568 const char ***list, uint32_t *count)
2573 struct ctdb_control_list_tunable *t;
2576 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_LIST_TUNABLES, 0, tdb_null,
2577 mem_ctx, &outdata, &res, &timeout, NULL);
2578 if (ret != 0 || res != 0) {
2579 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for list_tunables failed\n"));
2583 t = (struct ctdb_control_list_tunable *)outdata.dptr;
2584 if (outdata.dsize < offsetof(struct ctdb_control_list_tunable, data) ||
2585 t->length > outdata.dsize-offsetof(struct ctdb_control_list_tunable, data)) {
2586 DEBUG(DEBUG_ERR,("Invalid data in list_tunables reply\n"));
2587 talloc_free(outdata.dptr);
2591 p = talloc_strndup(mem_ctx, (char *)t->data, t->length);
2592 CTDB_NO_MEMORY(ctdb, p);
2594 talloc_free(outdata.dptr);
2599 for (s=strtok_r(p, ":", &ptr); s; s=strtok_r(NULL, ":", &ptr)) {
2600 (*list) = talloc_realloc(mem_ctx, *list, const char *, 1+(*count));
2601 CTDB_NO_MEMORY(ctdb, *list);
2602 (*list)[*count] = talloc_strdup(*list, s);
2603 CTDB_NO_MEMORY(ctdb, (*list)[*count]);
2613 int ctdb_ctrl_get_public_ips_flags(struct ctdb_context *ctdb,
2614 struct timeval timeout, uint32_t destnode,
2615 TALLOC_CTX *mem_ctx,
2617 struct ctdb_public_ip_list_old **ips)
2623 ret = ctdb_control(ctdb, destnode, 0,
2624 CTDB_CONTROL_GET_PUBLIC_IPS, flags, tdb_null,
2625 mem_ctx, &outdata, &res, &timeout, NULL);
2626 if (ret != 0 || res != 0) {
2627 DEBUG(DEBUG_ERR,(__location__
2628 " ctdb_control for getpublicips failed ret:%d res:%d\n",
2633 *ips = (struct ctdb_public_ip_list_old *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
2634 talloc_free(outdata.dptr);
2639 int ctdb_ctrl_get_public_ips(struct ctdb_context *ctdb,
2640 struct timeval timeout, uint32_t destnode,
2641 TALLOC_CTX *mem_ctx,
2642 struct ctdb_public_ip_list_old **ips)
2644 return ctdb_ctrl_get_public_ips_flags(ctdb, timeout,
2649 int ctdb_ctrl_get_public_ip_info(struct ctdb_context *ctdb,
2650 struct timeval timeout, uint32_t destnode,
2651 TALLOC_CTX *mem_ctx,
2652 const ctdb_sock_addr *addr,
2653 struct ctdb_public_ip_info_old **_info)
2659 struct ctdb_public_ip_info_old *info;
2663 indata.dptr = discard_const_p(uint8_t, addr);
2664 indata.dsize = sizeof(*addr);
2666 ret = ctdb_control(ctdb, destnode, 0,
2667 CTDB_CONTROL_GET_PUBLIC_IP_INFO, 0, indata,
2668 mem_ctx, &outdata, &res, &timeout, NULL);
2669 if (ret != 0 || res != 0) {
2670 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
2671 "failed ret:%d res:%d\n",
2676 len = offsetof(struct ctdb_public_ip_info_old, ifaces);
2677 if (len > outdata.dsize) {
2678 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
2679 "returned invalid data with size %u > %u\n",
2680 (unsigned int)outdata.dsize,
2681 (unsigned int)len));
2682 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
2686 info = (struct ctdb_public_ip_info_old *)outdata.dptr;
2687 len += info->num*sizeof(struct ctdb_iface);
2689 if (len > outdata.dsize) {
2690 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
2691 "returned invalid data with size %u > %u\n",
2692 (unsigned int)outdata.dsize,
2693 (unsigned int)len));
2694 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
2698 /* make sure we null terminate the returned strings */
2699 for (i=0; i < info->num; i++) {
2700 info->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
2703 *_info = (struct ctdb_public_ip_info_old *)talloc_memdup(mem_ctx,
2706 talloc_free(outdata.dptr);
2707 if (*_info == NULL) {
2708 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
2709 "talloc_memdup size %u failed\n",
2710 (unsigned int)outdata.dsize));
2717 int ctdb_ctrl_get_ifaces(struct ctdb_context *ctdb,
2718 struct timeval timeout, uint32_t destnode,
2719 TALLOC_CTX *mem_ctx,
2720 struct ctdb_iface_list_old **_ifaces)
2725 struct ctdb_iface_list_old *ifaces;
2729 ret = ctdb_control(ctdb, destnode, 0,
2730 CTDB_CONTROL_GET_IFACES, 0, tdb_null,
2731 mem_ctx, &outdata, &res, &timeout, NULL);
2732 if (ret != 0 || res != 0) {
2733 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
2734 "failed ret:%d res:%d\n",
2739 len = offsetof(struct ctdb_iface_list_old, ifaces);
2740 if (len > outdata.dsize) {
2741 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
2742 "returned invalid data with size %u > %u\n",
2743 (unsigned int)outdata.dsize,
2744 (unsigned int)len));
2745 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
2749 ifaces = (struct ctdb_iface_list_old *)outdata.dptr;
2750 len += ifaces->num*sizeof(struct ctdb_iface);
2752 if (len > outdata.dsize) {
2753 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
2754 "returned invalid data with size %u > %u\n",
2755 (unsigned int)outdata.dsize,
2756 (unsigned int)len));
2757 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
2761 /* make sure we null terminate the returned strings */
2762 for (i=0; i < ifaces->num; i++) {
2763 ifaces->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
2766 *_ifaces = (struct ctdb_iface_list_old *)talloc_memdup(mem_ctx,
2769 talloc_free(outdata.dptr);
2770 if (*_ifaces == NULL) {
2771 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
2772 "talloc_memdup size %u failed\n",
2773 (unsigned int)outdata.dsize));
2780 int ctdb_ctrl_set_iface_link(struct ctdb_context *ctdb,
2781 struct timeval timeout, uint32_t destnode,
2782 TALLOC_CTX *mem_ctx,
2783 const struct ctdb_iface *info)
2789 indata.dptr = discard_const_p(uint8_t, info);
2790 indata.dsize = sizeof(*info);
2792 ret = ctdb_control(ctdb, destnode, 0,
2793 CTDB_CONTROL_SET_IFACE_LINK_STATE, 0, indata,
2794 mem_ctx, NULL, &res, &timeout, NULL);
2795 if (ret != 0 || res != 0) {
2796 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set iface link "
2797 "failed ret:%d res:%d\n",
2806 set/clear the permanent disabled bit on a remote node
2808 int ctdb_ctrl_modflags(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
2809 uint32_t set, uint32_t clear)
2813 struct ctdb_node_map_old *nodemap=NULL;
2814 struct ctdb_node_flag_change c;
2815 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2820 /* find the recovery master */
2821 ret = ctdb_ctrl_getrecmaster(ctdb, tmp_ctx, timeout, CTDB_CURRENT_NODE, &recmaster);
2823 DEBUG(DEBUG_ERR, (__location__ " Unable to get recmaster from local node\n"));
2824 talloc_free(tmp_ctx);
2829 /* read the node flags from the recmaster */
2830 ret = ctdb_ctrl_getnodemap(ctdb, timeout, recmaster, tmp_ctx, &nodemap);
2832 DEBUG(DEBUG_ERR, (__location__ " Unable to get nodemap from node %u\n", destnode));
2833 talloc_free(tmp_ctx);
2836 if (destnode >= nodemap->num) {
2837 DEBUG(DEBUG_ERR,(__location__ " Nodemap from recmaster does not contain node %d\n", destnode));
2838 talloc_free(tmp_ctx);
2843 c.old_flags = nodemap->nodes[destnode].flags;
2844 c.new_flags = c.old_flags;
2846 c.new_flags &= ~clear;
2848 data.dsize = sizeof(c);
2849 data.dptr = (unsigned char *)&c;
2851 /* send the flags update to all connected nodes */
2852 nodes = list_of_connected_nodes(ctdb, nodemap, tmp_ctx, true);
2854 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_MODIFY_FLAGS,
2856 timeout, false, data,
2859 DEBUG(DEBUG_ERR, (__location__ " Unable to update nodeflags on remote nodes\n"));
2861 talloc_free(tmp_ctx);
2865 talloc_free(tmp_ctx);
2873 int ctdb_ctrl_get_all_tunables(struct ctdb_context *ctdb,
2874 struct timeval timeout,
2876 struct ctdb_tunable_list *tunables)
2882 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_ALL_TUNABLES, 0, tdb_null, ctdb,
2883 &outdata, &res, &timeout, NULL);
2884 if (ret != 0 || res != 0) {
2885 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get all tunables failed\n"));
2889 if (outdata.dsize != sizeof(*tunables)) {
2890 DEBUG(DEBUG_ERR,(__location__ " bad data size %u in ctdb_ctrl_get_all_tunables should be %u\n",
2891 (unsigned)outdata.dsize, (unsigned)sizeof(*tunables)));
2895 *tunables = *(struct ctdb_tunable_list *)outdata.dptr;
2896 talloc_free(outdata.dptr);
2901 add a public address to a node
2903 int ctdb_ctrl_add_public_ip(struct ctdb_context *ctdb,
2904 struct timeval timeout, uint32_t destnode,
2905 struct ctdb_addr_info_old *pub)
2911 data.dsize = offsetof(struct ctdb_addr_info_old, iface) + pub->len;
2912 data.dptr = (unsigned char *)pub;
2914 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_ADD_PUBLIC_IP, 0, data, NULL,
2915 NULL, &res, &timeout, NULL);
2916 if (ret != 0 || res != 0) {
2917 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for add_public_ip failed\n"));
2925 delete a public address from a node
2927 int ctdb_ctrl_del_public_ip(struct ctdb_context *ctdb,
2928 struct timeval timeout, uint32_t destnode,
2929 struct ctdb_addr_info_old *pub)
2935 data.dsize = offsetof(struct ctdb_addr_info_old, iface) + pub->len;
2936 data.dptr = (unsigned char *)pub;
2938 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_DEL_PUBLIC_IP, 0, data, NULL,
2939 NULL, &res, &timeout, NULL);
2940 if (ret != 0 || res != 0) {
2941 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for del_public_ip failed\n"));
2951 int ctdb_ctrl_gratious_arp(struct ctdb_context *ctdb,
2952 struct timeval timeout, uint32_t destnode,
2953 ctdb_sock_addr *addr, const char *ifname)
2958 struct ctdb_addr_info_old *gratious_arp;
2959 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2962 len = strlen(ifname)+1;
2963 gratious_arp = talloc_size(tmp_ctx,
2964 offsetof(struct ctdb_addr_info_old, iface) + len);
2965 CTDB_NO_MEMORY(ctdb, gratious_arp);
2967 gratious_arp->addr = *addr;
2968 gratious_arp->len = len;
2969 memcpy(&gratious_arp->iface[0], ifname, len);
2972 data.dsize = offsetof(struct ctdb_addr_info_old, iface) + len;
2973 data.dptr = (unsigned char *)gratious_arp;
2975 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SEND_GRATUITOUS_ARP, 0, data, NULL,
2976 NULL, &res, &timeout, NULL);
2977 if (ret != 0 || res != 0) {
2978 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for gratious_arp failed\n"));
2979 talloc_free(tmp_ctx);
2983 talloc_free(tmp_ctx);
2988 get a list of all tcp tickles that a node knows about for a particular vnn
2990 int ctdb_ctrl_get_tcp_tickles(struct ctdb_context *ctdb,
2991 struct timeval timeout, uint32_t destnode,
2992 TALLOC_CTX *mem_ctx,
2993 ctdb_sock_addr *addr,
2994 struct ctdb_tickle_list_old **list)
2997 TDB_DATA data, outdata;
3000 data.dptr = (uint8_t*)addr;
3001 data.dsize = sizeof(ctdb_sock_addr);
3003 ret = ctdb_control(ctdb, destnode, 0,
3004 CTDB_CONTROL_GET_TCP_TICKLE_LIST, 0, data,
3005 mem_ctx, &outdata, &status, NULL, NULL);
3006 if (ret != 0 || status != 0) {
3007 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get tcp tickles failed\n"));
3011 *list = (struct ctdb_tickle_list_old *)outdata.dptr;
3017 initialise the ctdb daemon for client applications
3019 NOTE: In current code the daemon does not fork. This is for testing purposes only
3020 and to simplify the code.
3022 struct ctdb_context *ctdb_init(struct tevent_context *ev)
3025 struct ctdb_context *ctdb;
3027 ctdb = talloc_zero(ev, struct ctdb_context);
3029 DEBUG(DEBUG_ERR,(__location__ " talloc_zero failed.\n"));
3033 /* Wrap early to exercise code. */
3034 ret = reqid_init(ctdb, INT_MAX-200, &ctdb->idr);
3036 DEBUG(DEBUG_ERR, ("reqid_init failed (%s)\n", strerror(ret)));
3041 ret = srvid_init(ctdb, &ctdb->srv);
3043 DEBUG(DEBUG_ERR, ("srvid_init failed (%s)\n", strerror(ret)));
3048 ret = ctdb_set_socketname(ctdb, CTDB_SOCKET);
3050 DEBUG(DEBUG_ERR,(__location__ " ctdb_set_socketname failed.\n"));
3055 ctdb->statistics.statistics_start_time = timeval_current();
3064 void ctdb_set_flags(struct ctdb_context *ctdb, unsigned flags)
3066 ctdb->flags |= flags;
3070 setup the local socket name
3072 int ctdb_set_socketname(struct ctdb_context *ctdb, const char *socketname)
3074 ctdb->daemon.name = talloc_strdup(ctdb, socketname);
3075 CTDB_NO_MEMORY(ctdb, ctdb->daemon.name);
3080 const char *ctdb_get_socketname(struct ctdb_context *ctdb)
3082 return ctdb->daemon.name;
3086 return the pnn of this node
3088 uint32_t ctdb_get_pnn(struct ctdb_context *ctdb)
3095 get the uptime of a remote node
3097 struct ctdb_client_control_state *
3098 ctdb_ctrl_uptime_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode)
3100 return ctdb_control_send(ctdb, destnode, 0,
3101 CTDB_CONTROL_UPTIME, 0, tdb_null,
3102 mem_ctx, &timeout, NULL);
3105 int ctdb_ctrl_uptime_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, struct ctdb_uptime **uptime)
3111 ret = ctdb_control_recv(ctdb, state, mem_ctx, &outdata, &res, NULL);
3112 if (ret != 0 || res != 0) {
3113 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_uptime_recv failed\n"));
3117 *uptime = (struct ctdb_uptime *)talloc_steal(mem_ctx, outdata.dptr);
3122 int ctdb_ctrl_uptime(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, struct ctdb_uptime **uptime)
3124 struct ctdb_client_control_state *state;
3126 state = ctdb_ctrl_uptime_send(ctdb, mem_ctx, timeout, destnode);
3127 return ctdb_ctrl_uptime_recv(ctdb, mem_ctx, state, uptime);
3131 send a control to execute the "recovered" event script on a node
3133 int ctdb_ctrl_end_recovery(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
3138 ret = ctdb_control(ctdb, destnode, 0,
3139 CTDB_CONTROL_END_RECOVERY, 0, tdb_null,
3140 NULL, NULL, &status, &timeout, NULL);
3141 if (ret != 0 || status != 0) {
3142 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for end_recovery failed\n"));
3150 callback for the async helpers used when sending the same control
3151 to multiple nodes in parallell.
3153 static void async_callback(struct ctdb_client_control_state *state)
3155 struct client_async_data *data = talloc_get_type(state->async.private_data, struct client_async_data);
3156 struct ctdb_context *ctdb = talloc_get_type(state->ctdb, struct ctdb_context);
3160 uint32_t destnode = state->c->hdr.destnode;
3163 outdata.dptr = NULL;
3165 /* one more node has responded with recmode data */
3168 /* if we failed to push the db, then return an error and let
3169 the main loop try again.
3171 if (state->state != CTDB_CONTROL_DONE) {
3172 if ( !data->dont_log_errors) {
3173 DEBUG(DEBUG_ERR,("Async operation failed with state %d, opcode:%u\n", state->state, data->opcode));
3176 if (state->state == CTDB_CONTROL_TIMEOUT) {
3181 if (data->fail_callback) {
3182 data->fail_callback(ctdb, destnode, res, outdata,
3183 data->callback_data);
3188 state->async.fn = NULL;
3190 ret = ctdb_control_recv(ctdb, state, data, &outdata, &res, NULL);
3191 if ((ret != 0) || (res != 0)) {
3192 if ( !data->dont_log_errors) {
3193 DEBUG(DEBUG_ERR,("Async operation failed with ret=%d res=%d opcode=%u\n", ret, (int)res, data->opcode));
3196 if (data->fail_callback) {
3197 data->fail_callback(ctdb, destnode, res, outdata,
3198 data->callback_data);
3201 if ((ret == 0) && (data->callback != NULL)) {
3202 data->callback(ctdb, destnode, res, outdata,
3203 data->callback_data);
3208 void ctdb_client_async_add(struct client_async_data *data, struct ctdb_client_control_state *state)
3210 /* set up the callback functions */
3211 state->async.fn = async_callback;
3212 state->async.private_data = data;
3214 /* one more control to wait for to complete */
3219 /* wait for up to the maximum number of seconds allowed
3220 or until all nodes we expect a response from has replied
3222 int ctdb_client_async_wait(struct ctdb_context *ctdb, struct client_async_data *data)
3224 while (data->count > 0) {
3225 tevent_loop_once(ctdb->ev);
3227 if (data->fail_count != 0) {
3228 if (!data->dont_log_errors) {
3229 DEBUG(DEBUG_ERR,("Async wait failed - fail_count=%u\n",
3239 perform a simple control on the listed nodes
3240 The control cannot return data
3242 int ctdb_client_async_control(struct ctdb_context *ctdb,
3243 enum ctdb_controls opcode,
3246 struct timeval timeout,
3247 bool dont_log_errors,
3249 client_async_callback client_callback,
3250 client_async_callback fail_callback,
3251 void *callback_data)
3253 struct client_async_data *async_data;
3254 struct ctdb_client_control_state *state;
3257 async_data = talloc_zero(ctdb, struct client_async_data);
3258 CTDB_NO_MEMORY_FATAL(ctdb, async_data);
3259 async_data->dont_log_errors = dont_log_errors;
3260 async_data->callback = client_callback;
3261 async_data->fail_callback = fail_callback;
3262 async_data->callback_data = callback_data;
3263 async_data->opcode = opcode;
3265 num_nodes = talloc_get_size(nodes) / sizeof(uint32_t);
3267 /* loop over all nodes and send an async control to each of them */
3268 for (j=0; j<num_nodes; j++) {
3269 uint32_t pnn = nodes[j];
3271 state = ctdb_control_send(ctdb, pnn, srvid, opcode,
3272 0, data, async_data, &timeout, NULL);
3273 if (state == NULL) {
3274 DEBUG(DEBUG_ERR,(__location__ " Failed to call async control %u\n", (unsigned)opcode));
3275 talloc_free(async_data);
3279 ctdb_client_async_add(async_data, state);
3282 if (ctdb_client_async_wait(ctdb, async_data) != 0) {
3283 talloc_free(async_data);
3287 talloc_free(async_data);
3291 uint32_t *list_of_vnnmap_nodes(struct ctdb_context *ctdb,
3292 struct ctdb_vnn_map *vnn_map,
3293 TALLOC_CTX *mem_ctx,
3296 int i, j, num_nodes;
3299 for (i=num_nodes=0;i<vnn_map->size;i++) {
3300 if (vnn_map->map[i] == ctdb->pnn && !include_self) {
3306 nodes = talloc_array(mem_ctx, uint32_t, num_nodes);
3307 CTDB_NO_MEMORY_FATAL(ctdb, nodes);
3309 for (i=j=0;i<vnn_map->size;i++) {
3310 if (vnn_map->map[i] == ctdb->pnn && !include_self) {
3313 nodes[j++] = vnn_map->map[i];
3319 /* Get list of nodes not including those with flags specified by mask.
3320 * If exclude_pnn is not -1 then exclude that pnn from the list.
3322 uint32_t *list_of_nodes(struct ctdb_context *ctdb,
3323 struct ctdb_node_map_old *node_map,
3324 TALLOC_CTX *mem_ctx,
3328 int i, j, num_nodes;
3331 for (i=num_nodes=0;i<node_map->num;i++) {
3332 if (node_map->nodes[i].flags & mask) {
3335 if (node_map->nodes[i].pnn == exclude_pnn) {
3341 nodes = talloc_array(mem_ctx, uint32_t, num_nodes);
3342 CTDB_NO_MEMORY_FATAL(ctdb, nodes);
3344 for (i=j=0;i<node_map->num;i++) {
3345 if (node_map->nodes[i].flags & mask) {
3348 if (node_map->nodes[i].pnn == exclude_pnn) {
3351 nodes[j++] = node_map->nodes[i].pnn;
3357 uint32_t *list_of_active_nodes(struct ctdb_context *ctdb,
3358 struct ctdb_node_map_old *node_map,
3359 TALLOC_CTX *mem_ctx,
3362 return list_of_nodes(ctdb, node_map, mem_ctx, NODE_FLAGS_INACTIVE,
3363 include_self ? -1 : ctdb->pnn);
3366 uint32_t *list_of_connected_nodes(struct ctdb_context *ctdb,
3367 struct ctdb_node_map_old *node_map,
3368 TALLOC_CTX *mem_ctx,
3371 return list_of_nodes(ctdb, node_map, mem_ctx, NODE_FLAGS_DISCONNECTED,
3372 include_self ? -1 : ctdb->pnn);
3376 this is used to test if a pnn lock exists and if it exists will return
3377 the number of connections that pnn has reported or -1 if that recovery
3378 daemon is not running.
3381 ctdb_read_pnn_lock(int fd, int32_t pnn)
3386 lock.l_type = F_WRLCK;
3387 lock.l_whence = SEEK_SET;
3392 if (fcntl(fd, F_GETLK, &lock) != 0) {
3393 DEBUG(DEBUG_ERR, (__location__ " F_GETLK failed with %s\n", strerror(errno)));
3397 if (lock.l_type == F_UNLCK) {
3401 if (pread(fd, &c, 1, pnn) == -1) {
3402 DEBUG(DEBUG_CRIT,(__location__ " failed read pnn count - %s\n", strerror(errno)));
3410 get capabilities of a remote node
3412 struct ctdb_client_control_state *
3413 ctdb_ctrl_getcapabilities_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode)
3415 return ctdb_control_send(ctdb, destnode, 0,
3416 CTDB_CONTROL_GET_CAPABILITIES, 0, tdb_null,
3417 mem_ctx, &timeout, NULL);
3420 int ctdb_ctrl_getcapabilities_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *capabilities)
3426 ret = ctdb_control_recv(ctdb, state, mem_ctx, &outdata, &res, NULL);
3427 if ( (ret != 0) || (res != 0) ) {
3428 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_getcapabilities_recv failed\n"));
3433 *capabilities = *((uint32_t *)outdata.dptr);
3439 int ctdb_ctrl_getcapabilities(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *capabilities)
3441 struct ctdb_client_control_state *state;
3442 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
3445 state = ctdb_ctrl_getcapabilities_send(ctdb, tmp_ctx, timeout, destnode);
3446 ret = ctdb_ctrl_getcapabilities_recv(ctdb, tmp_ctx, state, capabilities);
3447 talloc_free(tmp_ctx);
3451 static void get_capabilities_callback(struct ctdb_context *ctdb,
3452 uint32_t node_pnn, int32_t res,
3453 TDB_DATA outdata, void *callback_data)
3455 struct ctdb_node_capabilities *caps =
3456 talloc_get_type(callback_data,
3457 struct ctdb_node_capabilities);
3459 if ( (outdata.dsize != sizeof(uint32_t)) || (outdata.dptr == NULL) ) {
3460 DEBUG(DEBUG_ERR, (__location__ " Invalid length/pointer for getcap callback : %u %p\n", (unsigned)outdata.dsize, outdata.dptr));
3464 if (node_pnn >= talloc_array_length(caps)) {
3466 (__location__ " unexpected PNN %u\n", node_pnn));
3470 caps[node_pnn].retrieved = true;
3471 caps[node_pnn].capabilities = *((uint32_t *)outdata.dptr);
3474 struct ctdb_node_capabilities *
3475 ctdb_get_capabilities(struct ctdb_context *ctdb,
3476 TALLOC_CTX *mem_ctx,
3477 struct timeval timeout,
3478 struct ctdb_node_map_old *nodemap)
3482 struct ctdb_node_capabilities *ret;
3484 nodes = list_of_active_nodes(ctdb, nodemap, mem_ctx, true);
3486 ret = talloc_array(mem_ctx, struct ctdb_node_capabilities,
3488 CTDB_NO_MEMORY_NULL(ctdb, ret);
3489 /* Prepopulate the expected PNNs */
3490 for (i = 0; i < talloc_array_length(ret); i++) {
3491 ret[i].retrieved = false;
3494 res = ctdb_client_async_control(ctdb, CTDB_CONTROL_GET_CAPABILITIES,
3497 get_capabilities_callback, NULL,
3501 (__location__ " Failed to read node capabilities.\n"));
3509 ctdb_get_node_capabilities(struct ctdb_node_capabilities *caps,
3512 if (pnn < talloc_array_length(caps) && caps[pnn].retrieved) {
3513 return &caps[pnn].capabilities;
3519 bool ctdb_node_has_capabilities(struct ctdb_node_capabilities *caps,
3521 uint32_t capabilities_required)
3523 uint32_t *capp = ctdb_get_node_capabilities(caps, pnn);
3524 return (capp != NULL) &&
3525 ((*capp & capabilities_required) == capabilities_required);
3529 static struct ctdb_server_id server_id_fetch(struct ctdb_context *ctdb, uint32_t reqid)
3531 struct ctdb_server_id id;
3535 id.vnn = ctdb_get_pnn(ctdb);
3536 id.unique_id = id.vnn;
3537 id.unique_id = (id.unique_id << 32) | reqid;
3542 /* This is basically a copy from Samba's server_id.*. However, a
3543 * dependency chain stops us from using Samba's version, so use a
3544 * renamed copy until a better solution is found. */
3545 static bool ctdb_server_id_equal(struct ctdb_server_id *id1, struct ctdb_server_id *id2)
3547 if (id1->pid != id2->pid) {
3551 if (id1->task_id != id2->task_id) {
3555 if (id1->vnn != id2->vnn) {
3559 if (id1->unique_id != id2->unique_id) {
3566 static bool server_id_exists(struct ctdb_context *ctdb,
3567 struct ctdb_server_id *id)
3571 ret = ctdb_ctrl_process_exists(ctdb, id->vnn, id->pid);
3579 static bool g_lock_parse(TALLOC_CTX *mem_ctx, TDB_DATA data,
3580 struct ctdb_g_lock_list **locks)
3582 struct ctdb_g_lock_list *recs;
3584 recs = talloc_zero(mem_ctx, struct ctdb_g_lock_list);
3589 if (data.dsize == 0) {
3593 if (data.dsize % sizeof(struct ctdb_g_lock) != 0) {
3594 DEBUG(DEBUG_ERR, (__location__ "invalid data size %lu in g_lock record\n",
3595 (unsigned long)data.dsize));
3600 recs->num = data.dsize / sizeof(struct ctdb_g_lock);
3601 recs->lock = talloc_memdup(mem_ctx, data.dptr, data.dsize);
3602 if (recs->lock == NULL) {
3608 if (locks != NULL) {
3616 static bool g_lock_lock(TALLOC_CTX *mem_ctx,
3617 struct ctdb_db_context *ctdb_db,
3618 const char *keyname, uint32_t reqid)
3621 struct ctdb_record_handle *h;
3622 struct ctdb_g_lock_list *locks;
3623 struct ctdb_server_id id;
3624 struct timeval t_start;
3627 key.dptr = (uint8_t *)discard_const(keyname);
3628 key.dsize = strlen(keyname) + 1;
3630 t_start = timeval_current();
3633 /* Keep trying for an hour. */
3634 if (timeval_elapsed(&t_start) > 3600) {
3638 h = ctdb_fetch_lock(ctdb_db, mem_ctx, key, &data);
3643 if (!g_lock_parse(h, data, &locks)) {
3644 DEBUG(DEBUG_ERR, ("g_lock: error parsing locks\n"));
3645 talloc_free(data.dptr);
3650 talloc_free(data.dptr);
3652 id = server_id_fetch(ctdb_db->ctdb, reqid);
3655 while (i < locks->num) {
3656 if (ctdb_server_id_equal(&locks->lock[i].sid, &id)) {
3657 /* Internal error */
3662 if (!server_id_exists(ctdb_db->ctdb, &locks->lock[i].sid)) {
3663 if (i < locks->num-1) {
3664 locks->lock[i] = locks->lock[locks->num-1];
3670 /* This entry is locked. */
3671 DEBUG(DEBUG_INFO, ("g_lock: lock already granted for "
3672 "pid=0x%llx taskid=%x vnn=%d id=0x%llx\n",
3673 (unsigned long long)id.pid,
3675 (unsigned long long)id.unique_id));
3680 locks->lock = talloc_realloc(locks, locks->lock, struct ctdb_g_lock,
3682 if (locks->lock == NULL) {
3687 locks->lock[locks->num].type = CTDB_G_LOCK_WRITE;
3688 locks->lock[locks->num].sid = id;
3691 data.dptr = (uint8_t *)locks->lock;
3692 data.dsize = locks->num * sizeof(struct ctdb_g_lock);
3694 if (ctdb_record_store(h, data) != 0) {
3695 DEBUG(DEBUG_ERR, ("g_lock: failed to write transaction lock for "
3696 "pid=0x%llx taskid=%x vnn=%d id=0x%llx\n",
3697 (unsigned long long)id.pid,
3699 (unsigned long long)id.unique_id));
3704 DEBUG(DEBUG_INFO, ("g_lock: lock granted for "
3705 "pid=0x%llx taskid=%x vnn=%d id=0x%llx\n",
3706 (unsigned long long)id.pid,
3708 (unsigned long long)id.unique_id));
3714 static bool g_lock_unlock(TALLOC_CTX *mem_ctx,
3715 struct ctdb_db_context *ctdb_db,
3716 const char *keyname, uint32_t reqid)
3719 struct ctdb_record_handle *h;
3720 struct ctdb_g_lock_list *locks;
3721 struct ctdb_server_id id;
3725 key.dptr = (uint8_t *)discard_const(keyname);
3726 key.dsize = strlen(keyname) + 1;
3727 h = ctdb_fetch_lock(ctdb_db, mem_ctx, key, &data);
3732 if (!g_lock_parse(h, data, &locks)) {
3733 DEBUG(DEBUG_ERR, ("g_lock: error parsing locks\n"));
3734 talloc_free(data.dptr);
3739 talloc_free(data.dptr);
3741 id = server_id_fetch(ctdb_db->ctdb, reqid);
3743 for (i=0; i<locks->num; i++) {
3744 if (ctdb_server_id_equal(&locks->lock[i].sid, &id)) {
3745 if (i < locks->num-1) {
3746 locks->lock[i] = locks->lock[locks->num-1];
3755 DEBUG(DEBUG_ERR, ("g_lock: lock not found\n"));
3760 data.dptr = (uint8_t *)locks->lock;
3761 data.dsize = locks->num * sizeof(struct ctdb_g_lock);
3763 if (ctdb_record_store(h, data) != 0) {
3773 struct ctdb_transaction_handle {
3774 struct ctdb_db_context *ctdb_db;
3775 struct ctdb_db_context *g_lock_db;
3779 * we store reads and writes done under a transaction:
3780 * - one list stores both reads and writes (m_all)
3781 * - the other just writes (m_write)
3783 struct ctdb_marshall_buffer *m_all;
3784 struct ctdb_marshall_buffer *m_write;
3787 static int ctdb_transaction_destructor(struct ctdb_transaction_handle *h)
3789 g_lock_unlock(h, h->g_lock_db, h->lock_name, h->reqid);
3790 reqid_remove(h->ctdb_db->ctdb->idr, h->reqid);
3796 * start a transaction on a database
3798 struct ctdb_transaction_handle *ctdb_transaction_start(struct ctdb_db_context *ctdb_db,
3799 TALLOC_CTX *mem_ctx)
3801 struct ctdb_transaction_handle *h;
3803 h = talloc_zero(mem_ctx, struct ctdb_transaction_handle);
3805 DEBUG(DEBUG_ERR, (__location__ " memory allocation error\n"));
3809 h->ctdb_db = ctdb_db;
3810 h->lock_name = talloc_asprintf(h, "transaction_db_0x%08x",
3811 (unsigned int)ctdb_db->db_id);
3812 if (h->lock_name == NULL) {
3813 DEBUG(DEBUG_ERR, (__location__ " talloc asprintf failed\n"));
3818 h->g_lock_db = ctdb_attach(h->ctdb_db->ctdb, timeval_current_ofs(3,0),
3820 if (!h->g_lock_db) {
3821 DEBUG(DEBUG_ERR, (__location__ " unable to attach to g_lock.tdb\n"));
3826 h->reqid = reqid_new(h->ctdb_db->ctdb->idr, h);
3828 if (!g_lock_lock(h, h->g_lock_db, h->lock_name, h->reqid)) {
3829 DEBUG(DEBUG_ERR, (__location__ " Error locking g_lock.tdb\n"));
3834 talloc_set_destructor(h, ctdb_transaction_destructor);
3839 * fetch a record inside a transaction
3841 int ctdb_transaction_fetch(struct ctdb_transaction_handle *h,
3842 TALLOC_CTX *mem_ctx,
3843 TDB_DATA key, TDB_DATA *data)
3845 struct ctdb_ltdb_header header;
3848 ZERO_STRUCT(header);
3850 ret = ctdb_ltdb_fetch(h->ctdb_db, key, &header, mem_ctx, data);
3851 if (ret == -1 && header.dmaster == (uint32_t)-1) {
3852 /* record doesn't exist yet */
3861 h->m_all = ctdb_marshall_add(h, h->m_all, h->ctdb_db->db_id, 1, key, NULL, *data);
3862 if (h->m_all == NULL) {
3863 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
3871 * stores a record inside a transaction
3873 int ctdb_transaction_store(struct ctdb_transaction_handle *h,
3874 TDB_DATA key, TDB_DATA data)
3876 TALLOC_CTX *tmp_ctx = talloc_new(h);
3877 struct ctdb_ltdb_header header;
3881 /* we need the header so we can update the RSN */
3882 ret = ctdb_ltdb_fetch(h->ctdb_db, key, &header, tmp_ctx, &olddata);
3883 if (ret == -1 && header.dmaster == (uint32_t)-1) {
3884 /* the record doesn't exist - create one with us as dmaster.
3885 This is only safe because we are in a transaction and this
3886 is a persistent database */
3887 ZERO_STRUCT(header);
3888 } else if (ret != 0) {
3889 DEBUG(DEBUG_ERR,(__location__ " Failed to fetch record\n"));
3890 talloc_free(tmp_ctx);
3894 if (data.dsize == olddata.dsize &&
3895 memcmp(data.dptr, olddata.dptr, data.dsize) == 0 &&
3897 /* save writing the same data */
3898 talloc_free(tmp_ctx);
3902 header.dmaster = h->ctdb_db->ctdb->pnn;
3905 h->m_all = ctdb_marshall_add(h, h->m_all, h->ctdb_db->db_id, 0, key, NULL, data);
3906 if (h->m_all == NULL) {
3907 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
3908 talloc_free(tmp_ctx);
3912 h->m_write = ctdb_marshall_add(h, h->m_write, h->ctdb_db->db_id, 0, key, &header, data);
3913 if (h->m_write == NULL) {
3914 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
3915 talloc_free(tmp_ctx);
3919 talloc_free(tmp_ctx);
3923 static int ctdb_fetch_db_seqnum(struct ctdb_db_context *ctdb_db, uint64_t *seqnum)
3925 const char *keyname = CTDB_DB_SEQNUM_KEY;
3927 struct ctdb_ltdb_header header;
3930 key.dptr = (uint8_t *)discard_const(keyname);
3931 key.dsize = strlen(keyname) + 1;
3933 ret = ctdb_ltdb_fetch(ctdb_db, key, &header, ctdb_db, &data);
3939 if (data.dsize == 0) {
3944 if (data.dsize != sizeof(*seqnum)) {
3945 DEBUG(DEBUG_ERR, (__location__ " Invalid data received len=%zi\n",
3947 talloc_free(data.dptr);
3951 *seqnum = *(uint64_t *)data.dptr;
3952 talloc_free(data.dptr);
3958 static int ctdb_store_db_seqnum(struct ctdb_transaction_handle *h,
3961 const char *keyname = CTDB_DB_SEQNUM_KEY;
3964 key.dptr = (uint8_t *)discard_const(keyname);
3965 key.dsize = strlen(keyname) + 1;
3967 data.dptr = (uint8_t *)&seqnum;
3968 data.dsize = sizeof(seqnum);
3970 return ctdb_transaction_store(h, key, data);
3975 * commit a transaction
3977 int ctdb_transaction_commit(struct ctdb_transaction_handle *h)
3980 uint64_t old_seqnum, new_seqnum;
3982 struct timeval timeout;
3984 if (h->m_write == NULL) {
3985 /* no changes were made */
3990 ret = ctdb_fetch_db_seqnum(h->ctdb_db, &old_seqnum);
3992 DEBUG(DEBUG_ERR, (__location__ " failed to fetch db sequence number\n"));
3997 new_seqnum = old_seqnum + 1;
3998 ret = ctdb_store_db_seqnum(h, new_seqnum);
4000 DEBUG(DEBUG_ERR, (__location__ " failed to store db sequence number\n"));
4006 timeout = timeval_current_ofs(30,0);
4007 ret = ctdb_control(h->ctdb_db->ctdb, CTDB_CURRENT_NODE,
4009 CTDB_CONTROL_TRANS3_COMMIT, 0,
4010 ctdb_marshall_finish(h->m_write), NULL, NULL,
4011 &status, &timeout, NULL);
4012 if (ret != 0 || status != 0) {
4014 * TRANS3_COMMIT control will only fail if recovery has been
4015 * triggered. Check if the database has been updated or not.
4017 ret = ctdb_fetch_db_seqnum(h->ctdb_db, &new_seqnum);
4019 DEBUG(DEBUG_ERR, (__location__ " failed to fetch db sequence number\n"));
4023 if (new_seqnum == old_seqnum) {
4024 /* Database not yet updated, try again */
4028 if (new_seqnum != (old_seqnum + 1)) {
4029 DEBUG(DEBUG_ERR, (__location__ " new seqnum [%llu] != old seqnum [%llu] + 1\n",
4030 (long long unsigned)new_seqnum,
4031 (long long unsigned)old_seqnum));
4045 * cancel a transaction
4047 int ctdb_transaction_cancel(struct ctdb_transaction_handle *h)
4055 recovery daemon ping to main daemon
4057 int ctdb_ctrl_recd_ping(struct ctdb_context *ctdb)
4062 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_RECD_PING, 0, tdb_null,
4063 ctdb, NULL, &res, NULL, NULL);
4064 if (ret != 0 || res != 0) {
4065 DEBUG(DEBUG_ERR,("Failed to send recd ping\n"));
4073 tell the main daemon how long it took to lock the reclock file
4075 int ctdb_ctrl_report_recd_lock_latency(struct ctdb_context *ctdb, struct timeval timeout, double latency)
4081 data.dptr = (uint8_t *)&latency;
4082 data.dsize = sizeof(latency);
4084 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_RECD_RECLOCK_LATENCY, 0, data,
4085 ctdb, NULL, &res, NULL, NULL);
4086 if (ret != 0 || res != 0) {
4087 DEBUG(DEBUG_ERR,("Failed to send recd reclock latency\n"));
4095 get the name of the reclock file
4097 int ctdb_ctrl_getreclock(struct ctdb_context *ctdb, struct timeval timeout,
4098 uint32_t destnode, TALLOC_CTX *mem_ctx,
4105 ret = ctdb_control(ctdb, destnode, 0,
4106 CTDB_CONTROL_GET_RECLOCK_FILE, 0, tdb_null,
4107 mem_ctx, &data, &res, &timeout, NULL);
4108 if (ret != 0 || res != 0) {
4112 if (data.dsize == 0) {
4115 *name = talloc_strdup(mem_ctx, discard_const(data.dptr));
4117 talloc_free(data.dptr);
4125 int ctdb_ctrl_stop_node(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
4130 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_STOP_NODE, 0, tdb_null,
4131 ctdb, NULL, &res, &timeout, NULL);
4132 if (ret != 0 || res != 0) {
4133 DEBUG(DEBUG_ERR,("Failed to stop node\n"));
4143 int ctdb_ctrl_continue_node(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
4147 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_CONTINUE_NODE, 0, tdb_null,
4148 ctdb, NULL, NULL, &timeout, NULL);
4150 DEBUG(DEBUG_ERR,("Failed to continue node\n"));
4158 set the lmaster role for a node
4160 int ctdb_ctrl_setlmasterrole(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t lmasterrole)
4166 data.dsize = sizeof(lmasterrole);
4167 data.dptr = (uint8_t *)&lmasterrole;
4169 ret = ctdb_control(ctdb, destnode, 0,
4170 CTDB_CONTROL_SET_LMASTERROLE, 0, data,
4171 NULL, NULL, &res, &timeout, NULL);
4172 if (ret != 0 || res != 0) {
4173 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setlmasterrole failed\n"));
4181 set the recmaster role for a node
4183 int ctdb_ctrl_setrecmasterrole(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmasterrole)
4189 data.dsize = sizeof(recmasterrole);
4190 data.dptr = (uint8_t *)&recmasterrole;
4192 ret = ctdb_control(ctdb, destnode, 0,
4193 CTDB_CONTROL_SET_RECMASTERROLE, 0, data,
4194 NULL, NULL, &res, &timeout, NULL);
4195 if (ret != 0 || res != 0) {
4196 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setrecmasterrole failed\n"));
4203 int ctdb_ctrl_set_ban(struct ctdb_context *ctdb, struct timeval timeout,
4204 uint32_t destnode, struct ctdb_ban_state *bantime)
4210 data.dsize = sizeof(*bantime);
4211 data.dptr = (uint8_t *)bantime;
4213 ret = ctdb_control(ctdb, destnode, 0,
4214 CTDB_CONTROL_SET_BAN_STATE, 0, data,
4215 NULL, NULL, &res, &timeout, NULL);
4216 if (ret != 0 || res != 0) {
4217 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set ban state failed\n"));
4225 int ctdb_ctrl_get_ban(struct ctdb_context *ctdb, struct timeval timeout,
4226 uint32_t destnode, TALLOC_CTX *mem_ctx,
4227 struct ctdb_ban_state **bantime)
4232 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
4234 ret = ctdb_control(ctdb, destnode, 0,
4235 CTDB_CONTROL_GET_BAN_STATE, 0, tdb_null,
4236 tmp_ctx, &outdata, &res, &timeout, NULL);
4237 if (ret != 0 || res != 0) {
4238 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set ban state failed\n"));
4239 talloc_free(tmp_ctx);
4243 *bantime = (struct ctdb_ban_state *)talloc_steal(mem_ctx, outdata.dptr);
4244 talloc_free(tmp_ctx);
4249 int ctdb_ctrl_getstathistory(struct ctdb_context *ctdb,
4250 struct timeval timeout, uint32_t destnode,
4251 TALLOC_CTX *mem_ctx,
4252 struct ctdb_statistics_list_old **stats)
4258 ret = ctdb_control(ctdb, destnode, 0,
4259 CTDB_CONTROL_GET_STAT_HISTORY, 0, tdb_null,
4260 mem_ctx, &outdata, &res, &timeout, NULL);
4261 if (ret != 0 || res != 0 || outdata.dsize == 0) {
4262 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getstathistory failed ret:%d res:%d\n", ret, res));
4266 *stats = (struct ctdb_statistics_list_old *)talloc_memdup(mem_ctx,
4269 talloc_free(outdata.dptr);
4274 struct ctdb_ltdb_header *ctdb_header_from_record_handle(struct ctdb_record_handle *h)
4284 struct ctdb_client_control_state *
4285 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)
4287 struct ctdb_client_control_state *handle;
4288 struct ctdb_marshall_buffer *m;
4289 struct ctdb_rec_data_old *rec;
4292 m = talloc_zero(mem_ctx, struct ctdb_marshall_buffer);
4294 DEBUG(DEBUG_ERR, ("Failed to allocate marshall buffer for update record\n"));
4298 m->db_id = ctdb_db->db_id;
4300 rec = ctdb_marshall_record(m, 0, key, header, data);
4302 DEBUG(DEBUG_ERR,("Failed to marshall record for update record\n"));
4306 m = talloc_realloc_size(mem_ctx, m, rec->length + offsetof(struct ctdb_marshall_buffer, data));
4308 DEBUG(DEBUG_CRIT,(__location__ " Failed to expand recdata\n"));
4313 memcpy((uint8_t *)m + offsetof(struct ctdb_marshall_buffer, data), rec, rec->length);
4316 outdata.dptr = (uint8_t *)m;
4317 outdata.dsize = talloc_get_size(m);
4319 handle = ctdb_control_send(ctdb, destnode, 0,
4320 CTDB_CONTROL_UPDATE_RECORD, 0, outdata,
4321 mem_ctx, &timeout, NULL);
4326 int ctdb_ctrl_updaterecord_recv(struct ctdb_context *ctdb, struct ctdb_client_control_state *state)
4331 ret = ctdb_control_recv(ctdb, state, state, NULL, &res, NULL);
4332 if ( (ret != 0) || (res != 0) ){
4333 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_update_record_recv failed\n"));
4341 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)
4343 struct ctdb_client_control_state *state;
4345 state = ctdb_ctrl_updaterecord_send(ctdb, mem_ctx, timeout, destnode, ctdb_db, key, header, data);
4346 return ctdb_ctrl_updaterecord_recv(ctdb, state);
4355 set a database to be readonly
4357 struct ctdb_client_control_state *
4358 ctdb_ctrl_set_db_readonly_send(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid)
4362 data.dptr = (uint8_t *)&dbid;
4363 data.dsize = sizeof(dbid);
4365 return ctdb_control_send(ctdb, destnode, 0,
4366 CTDB_CONTROL_SET_DB_READONLY, 0, data,
4370 int ctdb_ctrl_set_db_readonly_recv(struct ctdb_context *ctdb, struct ctdb_client_control_state *state)
4375 ret = ctdb_control_recv(ctdb, state, ctdb, NULL, &res, NULL);
4376 if (ret != 0 || res != 0) {
4377 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_set_db_readonly_recv failed ret:%d res:%d\n", ret, res));
4384 int ctdb_ctrl_set_db_readonly(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid)
4386 struct ctdb_client_control_state *state;
4388 state = ctdb_ctrl_set_db_readonly_send(ctdb, destnode, dbid);
4389 return ctdb_ctrl_set_db_readonly_recv(ctdb, state);
4393 set a database to be sticky
4395 struct ctdb_client_control_state *
4396 ctdb_ctrl_set_db_sticky_send(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid)
4400 data.dptr = (uint8_t *)&dbid;
4401 data.dsize = sizeof(dbid);
4403 return ctdb_control_send(ctdb, destnode, 0,
4404 CTDB_CONTROL_SET_DB_STICKY, 0, data,
4408 int ctdb_ctrl_set_db_sticky_recv(struct ctdb_context *ctdb, struct ctdb_client_control_state *state)
4413 ret = ctdb_control_recv(ctdb, state, ctdb, NULL, &res, NULL);
4414 if (ret != 0 || res != 0) {
4415 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_set_db_sticky_recv failed ret:%d res:%d\n", ret, res));
4422 int ctdb_ctrl_set_db_sticky(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid)
4424 struct ctdb_client_control_state *state;
4426 state = ctdb_ctrl_set_db_sticky_send(ctdb, destnode, dbid);
4427 return ctdb_ctrl_set_db_sticky_recv(ctdb, state);