4 Copyright (C) Andrew Tridgell 2007
5 Copyright (C) Ronnie Sahlberg 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, see <http://www.gnu.org/licenses/>.
23 #include "lib/tdb/include/tdb.h"
24 #include "lib/util/dlinklist.h"
25 #include "lib/events/events.h"
26 #include "system/network.h"
27 #include "system/filesys.h"
28 #include "system/locale.h"
30 #include "include/ctdb_protocol.h"
31 #include "include/ctdb_private.h"
32 #include "lib/util/dlinklist.h"
36 struct ctdb_record_handle {
37 struct ctdb_db_context *ctdb_db;
40 struct ctdb_ltdb_header header;
45 make a recv call to the local ctdb daemon - called from client context
47 This is called when the program wants to wait for a ctdb_call to complete and get the
48 results. This call will block unless the call has already completed.
50 int ctdb_call_recv(struct ctdb_client_call_state *state, struct ctdb_call *call)
56 while (state->state < CTDB_CALL_DONE) {
57 event_loop_once(state->ctdb_db->ctdb->ev);
59 if (state->state != CTDB_CALL_DONE) {
60 DEBUG(DEBUG_ERR,(__location__ " ctdb_call_recv failed\n"));
65 if (state->call->reply_data.dsize) {
66 call->reply_data.dptr = talloc_memdup(state->ctdb_db,
67 state->call->reply_data.dptr,
68 state->call->reply_data.dsize);
69 call->reply_data.dsize = state->call->reply_data.dsize;
71 call->reply_data.dptr = NULL;
72 call->reply_data.dsize = 0;
74 call->status = state->call->status;
87 full ctdb_call. Equivalent to a ctdb_call_send() followed by a ctdb_call_recv()
89 int ctdb_call(struct ctdb_db_context *ctdb_db, struct ctdb_call *call)
91 struct ctdb_client_call_state *state;
93 state = ctdb_call_send(ctdb_db, call);
94 return ctdb_call_recv(state, call);
102 cancel a ctdb_fetch_lock operation, releasing the lock
104 static int fetch_lock_destructor(struct ctdb_record_handle *h)
106 ctdb_ltdb_unlock(h->ctdb_db, h->key);
111 force the migration of a record to this node
113 static int ctdb_client_force_migration(struct ctdb_db_context *ctdb_db, TDB_DATA key)
115 struct ctdb_call call;
117 call.call_id = CTDB_NULL_FUNC;
119 call.flags = CTDB_IMMEDIATE_MIGRATION;
120 return ctdb_call(ctdb_db, &call);
124 get a lock on a record, and return the records data. Blocks until it gets the lock
126 struct ctdb_record_handle *ctdb_fetch_lock(struct ctdb_db_context *ctdb_db, TALLOC_CTX *mem_ctx,
127 TDB_DATA key, TDB_DATA *data)
130 struct ctdb_record_handle *h;
133 procedure is as follows:
135 1) get the chain lock.
136 2) check if we are dmaster
137 3) if we are the dmaster then return handle
138 4) if not dmaster then ask ctdb daemon to make us dmaster, and wait for
140 5) when we get the reply, goto (1)
143 h = talloc_zero(mem_ctx, struct ctdb_record_handle);
148 h->ctdb_db = ctdb_db;
150 h->key.dptr = talloc_memdup(h, key.dptr, key.dsize);
151 if (h->key.dptr == NULL) {
157 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: key=%*.*s\n", (int)key.dsize, (int)key.dsize,
158 (const char *)key.dptr));
161 /* step 1 - get the chain lock */
162 ret = ctdb_ltdb_lock(ctdb_db, key);
164 DEBUG(DEBUG_ERR, (__location__ " failed to lock ltdb record\n"));
169 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: got chain lock\n"));
171 talloc_set_destructor(h, fetch_lock_destructor);
173 ret = ctdb_ltdb_fetch(ctdb_db, key, &h->header, h, data);
175 /* when torturing, ensure we test the remote path */
176 if ((ctdb_db->ctdb->flags & CTDB_FLAG_TORTURE) &&
178 h->header.dmaster = (uint32_t)-1;
182 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: done local fetch\n"));
184 if (ret != 0 || h->header.dmaster != ctdb_db->ctdb->pnn) {
185 ctdb_ltdb_unlock(ctdb_db, key);
186 ret = ctdb_client_force_migration(ctdb_db, key);
188 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: force_migration failed\n"));
195 DEBUG(DEBUG_DEBUG,("ctdb_fetch_lock: we are dmaster - done\n"));
200 store some data to the record that was locked with ctdb_fetch_lock()
202 int ctdb_record_store(struct ctdb_record_handle *h, TDB_DATA data)
204 if (h->ctdb_db->persistent) {
205 DEBUG(DEBUG_ERR, (__location__ " ctdb_record_store prohibited for persistent dbs\n"));
209 return ctdb_ltdb_store(h->ctdb_db, h->key, &h->header, data);
213 non-locking fetch of a record
215 int ctdb_fetch(struct ctdb_db_context *ctdb_db, TALLOC_CTX *mem_ctx,
216 TDB_DATA key, TDB_DATA *data)
218 struct ctdb_call call;
221 call.call_id = CTDB_FETCH_FUNC;
222 call.call_data.dptr = NULL;
223 call.call_data.dsize = 0;
225 ret = ctdb_call(ctdb_db, &call);
228 *data = call.reply_data;
229 talloc_steal(mem_ctx, data->dptr);
243 send a ctdb control message
244 timeout specifies how long we should wait for a reply.
245 if timeout is NULL we wait indefinitely
247 int ctdb_control(struct ctdb_context *ctdb, uint32_t destnode, uint64_t srvid,
248 uint32_t opcode, uint32_t flags, TDB_DATA data,
249 TALLOC_CTX *mem_ctx, TDB_DATA *outdata, int32_t *status,
250 struct timeval *timeout,
253 struct ctdb_client_control_state *state;
255 state = ctdb_control_send(ctdb, destnode, srvid, opcode,
256 flags, data, mem_ctx,
258 return ctdb_control_recv(ctdb, state, mem_ctx, outdata, status,
266 a process exists call. Returns 0 if process exists, -1 otherwise
268 int ctdb_ctrl_process_exists(struct ctdb_context *ctdb, uint32_t destnode, pid_t pid)
274 data.dptr = (uint8_t*)&pid;
275 data.dsize = sizeof(pid);
277 ret = ctdb_control(ctdb, destnode, 0,
278 CTDB_CONTROL_PROCESS_EXISTS, 0, data,
279 NULL, NULL, &status, NULL, NULL);
281 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for process_exists failed\n"));
289 get remote statistics
291 int ctdb_ctrl_statistics(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_statistics *status)
297 ret = ctdb_control(ctdb, destnode, 0,
298 CTDB_CONTROL_STATISTICS, 0, tdb_null,
299 ctdb, &data, &res, NULL, NULL);
300 if (ret != 0 || res != 0) {
301 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for statistics failed\n"));
305 if (data.dsize != sizeof(struct ctdb_statistics)) {
306 DEBUG(DEBUG_ERR,(__location__ " Wrong statistics size %u - expected %u\n",
307 (unsigned)data.dsize, (unsigned)sizeof(struct ctdb_statistics)));
311 *status = *(struct ctdb_statistics *)data.dptr;
312 talloc_free(data.dptr);
318 shutdown a remote ctdb node
320 int ctdb_ctrl_shutdown(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
322 struct ctdb_client_control_state *state;
324 state = ctdb_control_send(ctdb, destnode, 0,
325 CTDB_CONTROL_SHUTDOWN, 0, tdb_null,
326 NULL, &timeout, NULL);
328 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for shutdown failed\n"));
336 get vnn map from a remote node
338 int ctdb_ctrl_getvnnmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_vnn_map **vnnmap)
343 struct ctdb_vnn_map_wire *map;
345 ret = ctdb_control(ctdb, destnode, 0,
346 CTDB_CONTROL_GETVNNMAP, 0, tdb_null,
347 mem_ctx, &outdata, &res, &timeout, NULL);
348 if (ret != 0 || res != 0) {
349 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getvnnmap failed\n"));
353 map = (struct ctdb_vnn_map_wire *)outdata.dptr;
354 if (outdata.dsize < offsetof(struct ctdb_vnn_map_wire, map) ||
355 outdata.dsize != map->size*sizeof(uint32_t) + offsetof(struct ctdb_vnn_map_wire, map)) {
356 DEBUG(DEBUG_ERR,("Bad vnn map size received in ctdb_ctrl_getvnnmap\n"));
360 (*vnnmap) = talloc(mem_ctx, struct ctdb_vnn_map);
361 CTDB_NO_MEMORY(ctdb, *vnnmap);
362 (*vnnmap)->generation = map->generation;
363 (*vnnmap)->size = map->size;
364 (*vnnmap)->map = talloc_array(*vnnmap, uint32_t, map->size);
366 CTDB_NO_MEMORY(ctdb, (*vnnmap)->map);
367 memcpy((*vnnmap)->map, map->map, sizeof(uint32_t)*map->size);
368 talloc_free(outdata.dptr);
375 get the recovery mode of a remote node
377 struct ctdb_client_control_state *
378 ctdb_ctrl_getrecmode_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode)
380 return ctdb_control_send(ctdb, destnode, 0,
381 CTDB_CONTROL_GET_RECMODE, 0, tdb_null,
382 mem_ctx, &timeout, NULL);
385 int ctdb_ctrl_getrecmode_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *recmode)
390 ret = ctdb_control_recv(ctdb, state, mem_ctx, NULL, &res, NULL);
392 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_getrecmode_recv failed\n"));
397 *recmode = (uint32_t)res;
403 int ctdb_ctrl_getrecmode(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, uint32_t *recmode)
405 struct ctdb_client_control_state *state;
407 state = ctdb_ctrl_getrecmode_send(ctdb, mem_ctx, timeout, destnode);
408 return ctdb_ctrl_getrecmode_recv(ctdb, mem_ctx, state, recmode);
415 set the recovery mode of a remote node
417 int ctdb_ctrl_setrecmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmode)
423 data.dsize = sizeof(uint32_t);
424 data.dptr = (unsigned char *)&recmode;
426 ret = ctdb_control(ctdb, destnode, 0,
427 CTDB_CONTROL_SET_RECMODE, 0, data,
428 NULL, NULL, &res, &timeout, NULL);
429 if (ret != 0 || res != 0) {
430 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setrecmode failed\n"));
440 get the recovery master of a remote node
442 struct ctdb_client_control_state *
443 ctdb_ctrl_getrecmaster_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx,
444 struct timeval timeout, uint32_t destnode)
446 return ctdb_control_send(ctdb, destnode, 0,
447 CTDB_CONTROL_GET_RECMASTER, 0, tdb_null,
448 mem_ctx, &timeout, NULL);
451 int ctdb_ctrl_getrecmaster_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *recmaster)
456 ret = ctdb_control_recv(ctdb, state, mem_ctx, NULL, &res, NULL);
458 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_getrecmaster_recv failed\n"));
463 *recmaster = (uint32_t)res;
469 int ctdb_ctrl_getrecmaster(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, uint32_t *recmaster)
471 struct ctdb_client_control_state *state;
473 state = ctdb_ctrl_getrecmaster_send(ctdb, mem_ctx, timeout, destnode);
474 return ctdb_ctrl_getrecmaster_recv(ctdb, mem_ctx, state, recmaster);
479 set the recovery master of a remote node
481 int ctdb_ctrl_setrecmaster(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmaster)
488 data.dsize = sizeof(uint32_t);
489 data.dptr = (unsigned char *)&recmaster;
491 ret = ctdb_control(ctdb, destnode, 0,
492 CTDB_CONTROL_SET_RECMASTER, 0, data,
493 NULL, NULL, &res, &timeout, NULL);
494 if (ret != 0 || res != 0) {
495 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setrecmaster failed\n"));
504 get a list of databases off a remote node
506 int ctdb_ctrl_getdbmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
507 TALLOC_CTX *mem_ctx, struct ctdb_dbid_map **dbmap)
513 ret = ctdb_control(ctdb, destnode, 0,
514 CTDB_CONTROL_GET_DBMAP, 0, tdb_null,
515 mem_ctx, &outdata, &res, &timeout, NULL);
516 if (ret != 0 || res != 0) {
517 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getdbmap failed ret:%d res:%d\n", ret, res));
521 *dbmap = (struct ctdb_dbid_map *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
522 talloc_free(outdata.dptr);
528 get a list of nodes (vnn and flags ) from a remote node
530 int ctdb_ctrl_getnodemap(struct ctdb_context *ctdb,
531 struct timeval timeout, uint32_t destnode,
532 TALLOC_CTX *mem_ctx, struct ctdb_node_map **nodemap)
538 ret = ctdb_control(ctdb, destnode, 0,
539 CTDB_CONTROL_GET_NODEMAP, 0, tdb_null,
540 mem_ctx, &outdata, &res, &timeout, NULL);
541 if (ret == 0 && res == -1 && outdata.dsize == 0) {
542 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getnodes failed, falling back to ipv4-only control\n"));
543 return ctdb_ctrl_getnodemapv4(ctdb, timeout, destnode, mem_ctx, nodemap);
545 if (ret != 0 || res != 0 || outdata.dsize == 0) {
546 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getnodes failed ret:%d res:%d\n", ret, res));
550 *nodemap = (struct ctdb_node_map *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
551 talloc_free(outdata.dptr);
557 old style ipv4-only get a list of nodes (vnn and flags ) from a remote node
559 int ctdb_ctrl_getnodemapv4(struct ctdb_context *ctdb,
560 struct timeval timeout, uint32_t destnode,
561 TALLOC_CTX *mem_ctx, struct ctdb_node_map **nodemap)
565 struct ctdb_node_mapv4 *nodemapv4;
568 ret = ctdb_control(ctdb, destnode, 0,
569 CTDB_CONTROL_GET_NODEMAPv4, 0, tdb_null,
570 mem_ctx, &outdata, &res, &timeout, NULL);
571 if (ret != 0 || res != 0 || outdata.dsize == 0) {
572 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getnodesv4 failed ret:%d res:%d\n", ret, res));
576 nodemapv4 = (struct ctdb_node_mapv4 *)outdata.dptr;
578 len = offsetof(struct ctdb_node_map, nodes) + nodemapv4->num*sizeof(struct ctdb_node_and_flags);
579 (*nodemap) = talloc_zero_size(mem_ctx, len);
580 CTDB_NO_MEMORY(ctdb, (*nodemap));
582 (*nodemap)->num = nodemapv4->num;
583 for (i=0; i<nodemapv4->num; i++) {
584 (*nodemap)->nodes[i].pnn = nodemapv4->nodes[i].pnn;
585 (*nodemap)->nodes[i].flags = nodemapv4->nodes[i].flags;
586 (*nodemap)->nodes[i].addr.ip = nodemapv4->nodes[i].sin;
587 (*nodemap)->nodes[i].addr.sa.sa_family = AF_INET;
590 talloc_free(outdata.dptr);
596 drop the transport, reload the nodes file and restart the transport
598 int ctdb_ctrl_reload_nodes_file(struct ctdb_context *ctdb,
599 struct timeval timeout, uint32_t destnode)
604 ret = ctdb_control(ctdb, destnode, 0,
605 CTDB_CONTROL_RELOAD_NODES_FILE, 0, tdb_null,
606 NULL, NULL, &res, &timeout, NULL);
607 if (ret != 0 || res != 0) {
608 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for reloadnodesfile failed\n"));
617 set vnn map on a node
619 int ctdb_ctrl_setvnnmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
620 TALLOC_CTX *mem_ctx, struct ctdb_vnn_map *vnnmap)
625 struct ctdb_vnn_map_wire *map;
628 len = offsetof(struct ctdb_vnn_map_wire, map) + sizeof(uint32_t)*vnnmap->size;
629 map = talloc_size(mem_ctx, len);
630 CTDB_NO_MEMORY(ctdb, map);
632 map->generation = vnnmap->generation;
633 map->size = vnnmap->size;
634 memcpy(map->map, vnnmap->map, sizeof(uint32_t)*map->size);
637 data.dptr = (uint8_t *)map;
639 ret = ctdb_control(ctdb, destnode, 0,
640 CTDB_CONTROL_SETVNNMAP, 0, data,
641 NULL, NULL, &res, &timeout, NULL);
642 if (ret != 0 || res != 0) {
643 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setvnnmap failed\n"));
654 async send for pull database
656 struct ctdb_client_control_state *ctdb_ctrl_pulldb_send(
657 struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid,
658 uint32_t lmaster, TALLOC_CTX *mem_ctx, struct timeval timeout)
661 struct ctdb_control_pulldb *pull;
662 struct ctdb_client_control_state *state;
664 pull = talloc(mem_ctx, struct ctdb_control_pulldb);
665 CTDB_NO_MEMORY_NULL(ctdb, pull);
668 pull->lmaster = lmaster;
670 indata.dsize = sizeof(struct ctdb_control_pulldb);
671 indata.dptr = (unsigned char *)pull;
673 state = ctdb_control_send(ctdb, destnode, 0,
674 CTDB_CONTROL_PULL_DB, 0, indata,
675 mem_ctx, &timeout, NULL);
682 async recv for pull database
684 int ctdb_ctrl_pulldb_recv(
685 struct ctdb_context *ctdb,
686 TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state,
692 ret = ctdb_control_recv(ctdb, state, mem_ctx, outdata, &res, NULL);
693 if ( (ret != 0) || (res != 0) ){
694 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_pulldb_recv failed\n"));
702 pull all keys and records for a specific database on a node
704 int ctdb_ctrl_pulldb(struct ctdb_context *ctdb, uint32_t destnode,
705 uint32_t dbid, uint32_t lmaster,
706 TALLOC_CTX *mem_ctx, struct timeval timeout,
709 struct ctdb_client_control_state *state;
711 state = ctdb_ctrl_pulldb_send(ctdb, destnode, dbid, lmaster, mem_ctx,
714 return ctdb_ctrl_pulldb_recv(ctdb, mem_ctx, state, outdata);
719 change dmaster for all keys in the database to the new value
721 int ctdb_ctrl_setdmaster(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
722 TALLOC_CTX *mem_ctx, uint32_t dbid, uint32_t dmaster)
728 indata.dsize = 2*sizeof(uint32_t);
729 indata.dptr = (unsigned char *)talloc_array(mem_ctx, uint32_t, 2);
731 ((uint32_t *)(&indata.dptr[0]))[0] = dbid;
732 ((uint32_t *)(&indata.dptr[0]))[1] = dmaster;
734 ret = ctdb_control(ctdb, destnode, 0,
735 CTDB_CONTROL_SET_DMASTER, 0, indata,
736 NULL, NULL, &res, &timeout, NULL);
737 if (ret != 0 || res != 0) {
738 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setdmaster failed\n"));
746 ping a node, return number of clients connected
748 int ctdb_ctrl_ping(struct ctdb_context *ctdb, uint32_t destnode)
753 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_PING, 0,
754 tdb_null, NULL, NULL, &res, NULL, NULL);
762 find the real path to a ltdb
764 int ctdb_ctrl_getdbpath(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t dbid, TALLOC_CTX *mem_ctx,
771 data.dptr = (uint8_t *)&dbid;
772 data.dsize = sizeof(dbid);
774 ret = ctdb_control(ctdb, destnode, 0,
775 CTDB_CONTROL_GETDBPATH, 0, data,
776 mem_ctx, &data, &res, &timeout, NULL);
777 if (ret != 0 || res != 0) {
781 (*path) = talloc_strndup(mem_ctx, (const char *)data.dptr, data.dsize);
782 if ((*path) == NULL) {
786 talloc_free(data.dptr);
792 find the name of a db
794 int ctdb_ctrl_getdbname(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t dbid, TALLOC_CTX *mem_ctx,
801 data.dptr = (uint8_t *)&dbid;
802 data.dsize = sizeof(dbid);
804 ret = ctdb_control(ctdb, destnode, 0,
805 CTDB_CONTROL_GET_DBNAME, 0, data,
806 mem_ctx, &data, &res, &timeout, NULL);
807 if (ret != 0 || res != 0) {
811 (*name) = talloc_strndup(mem_ctx, (const char *)data.dptr, data.dsize);
812 if ((*name) == NULL) {
816 talloc_free(data.dptr);
822 get the health status of a db
824 int ctdb_ctrl_getdbhealth(struct ctdb_context *ctdb,
825 struct timeval timeout,
827 uint32_t dbid, TALLOC_CTX *mem_ctx,
834 data.dptr = (uint8_t *)&dbid;
835 data.dsize = sizeof(dbid);
837 ret = ctdb_control(ctdb, destnode, 0,
838 CTDB_CONTROL_DB_GET_HEALTH, 0, data,
839 mem_ctx, &data, &res, &timeout, NULL);
840 if (ret != 0 || res != 0) {
844 if (data.dsize == 0) {
849 (*reason) = talloc_strndup(mem_ctx, (const char *)data.dptr, data.dsize);
850 if ((*reason) == NULL) {
854 talloc_free(data.dptr);
862 int ctdb_ctrl_createdb(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
863 TALLOC_CTX *mem_ctx, const char *name, bool persistent)
869 data.dptr = discard_const(name);
870 data.dsize = strlen(name)+1;
872 ret = ctdb_control(ctdb, destnode, 0,
873 persistent?CTDB_CONTROL_DB_ATTACH_PERSISTENT:CTDB_CONTROL_DB_ATTACH,
875 mem_ctx, &data, &res, &timeout, NULL);
877 if (ret != 0 || res != 0) {
885 get debug level on a node
887 int ctdb_ctrl_get_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, int32_t *level)
893 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_DEBUG, 0, tdb_null,
894 ctdb, &data, &res, NULL, NULL);
895 if (ret != 0 || res != 0) {
898 if (data.dsize != sizeof(int32_t)) {
899 DEBUG(DEBUG_ERR,("Bad control reply size in ctdb_get_debuglevel (got %u)\n",
900 (unsigned)data.dsize));
903 *level = *(int32_t *)data.dptr;
904 talloc_free(data.dptr);
909 set debug level on a node
911 int ctdb_ctrl_set_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, int32_t level)
917 data.dptr = (uint8_t *)&level;
918 data.dsize = sizeof(level);
920 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SET_DEBUG, 0, data,
921 NULL, NULL, &res, NULL, NULL);
922 if (ret != 0 || res != 0) {
930 get a list of connected nodes
932 uint32_t *ctdb_get_connected_nodes(struct ctdb_context *ctdb,
933 struct timeval timeout,
937 struct ctdb_node_map *map=NULL;
943 ret = ctdb_ctrl_getnodemap(ctdb, timeout, CTDB_CURRENT_NODE, mem_ctx, &map);
948 nodes = talloc_array(mem_ctx, uint32_t, map->num);
953 for (i=0;i<map->num;i++) {
954 if (!(map->nodes[i].flags & NODE_FLAGS_DISCONNECTED)) {
955 nodes[*num_nodes] = map->nodes[i].pnn;
967 int ctdb_statistics_reset(struct ctdb_context *ctdb, uint32_t destnode)
972 ret = ctdb_control(ctdb, destnode, 0,
973 CTDB_CONTROL_STATISTICS_RESET, 0, tdb_null,
974 NULL, NULL, &res, NULL, NULL);
975 if (ret != 0 || res != 0) {
976 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for reset statistics failed\n"));
983 this is the dummy null procedure that all databases support
985 static int ctdb_null_func(struct ctdb_call_info *call)
991 this is a plain fetch procedure that all databases support
993 static int ctdb_fetch_func(struct ctdb_call_info *call)
995 call->reply_data = &call->record_data;
1000 attach to a specific database - client call
1002 struct ctdb_db_context *ctdb_attach(struct ctdb_context *ctdb, const char *name, bool persistent, uint32_t tdb_flags)
1004 struct ctdb_db_context *ctdb_db;
1009 ctdb_db = ctdb_db_handle(ctdb, name);
1014 ctdb_db = talloc_zero(ctdb, struct ctdb_db_context);
1015 CTDB_NO_MEMORY_NULL(ctdb, ctdb_db);
1017 ctdb_db->ctdb = ctdb;
1018 ctdb_db->db_name = talloc_strdup(ctdb_db, name);
1019 CTDB_NO_MEMORY_NULL(ctdb, ctdb_db->db_name);
1021 data.dptr = discard_const(name);
1022 data.dsize = strlen(name)+1;
1024 /* tell ctdb daemon to attach */
1025 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, tdb_flags,
1026 persistent?CTDB_CONTROL_DB_ATTACH_PERSISTENT:CTDB_CONTROL_DB_ATTACH,
1027 0, data, ctdb_db, &data, &res, NULL, NULL);
1028 if (ret != 0 || res != 0 || data.dsize != sizeof(uint32_t)) {
1029 DEBUG(DEBUG_ERR,("Failed to attach to database '%s'\n", name));
1030 talloc_free(ctdb_db);
1034 ctdb_db->db_id = *(uint32_t *)data.dptr;
1035 talloc_free(data.dptr);
1037 ret = ctdb_ctrl_getdbpath(ctdb, timeval_current_ofs(2, 0), CTDB_CURRENT_NODE, ctdb_db->db_id, ctdb_db, &ctdb_db->db_path);
1039 DEBUG(DEBUG_ERR,("Failed to get dbpath for database '%s'\n", name));
1040 talloc_free(ctdb_db);
1044 tdb_flags = persistent?TDB_DEFAULT:TDB_NOSYNC;
1045 if (ctdb->valgrinding) {
1046 tdb_flags |= TDB_NOMMAP;
1048 tdb_flags |= TDB_DISALLOW_NESTING;
1050 ctdb_db->ltdb = tdb_wrap_open(ctdb, ctdb_db->db_path, 0, tdb_flags, O_RDWR, 0);
1051 if (ctdb_db->ltdb == NULL) {
1052 ctdb_set_error(ctdb, "Failed to open tdb '%s'\n", ctdb_db->db_path);
1053 talloc_free(ctdb_db);
1057 ctdb_db->persistent = persistent;
1059 DLIST_ADD(ctdb->db_list, ctdb_db);
1061 /* add well known functions */
1062 ctdb_set_call(ctdb_db, ctdb_null_func, CTDB_NULL_FUNC);
1063 ctdb_set_call(ctdb_db, ctdb_fetch_func, CTDB_FETCH_FUNC);
1070 setup a call for a database
1072 int ctdb_set_call(struct ctdb_db_context *ctdb_db, ctdb_fn_t fn, uint32_t id)
1074 struct ctdb_registered_call *call;
1079 struct ctdb_control_set_call c;
1082 /* this is no longer valid with the separate daemon architecture */
1083 c.db_id = ctdb_db->db_id;
1087 data.dptr = (uint8_t *)&c;
1088 data.dsize = sizeof(c);
1090 ret = ctdb_control(ctdb_db->ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_SET_CALL, 0,
1091 data, NULL, NULL, &status, NULL, NULL);
1092 if (ret != 0 || status != 0) {
1093 DEBUG(DEBUG_ERR,("ctdb_set_call failed for call %u\n", id));
1098 /* also register locally */
1099 call = talloc(ctdb_db, struct ctdb_registered_call);
1103 DLIST_ADD(ctdb_db->calls, call);
1108 struct traverse_state {
1111 ctdb_traverse_func fn;
1116 called on each key during a ctdb_traverse
1118 static void traverse_handler(struct ctdb_context *ctdb, uint64_t srvid, TDB_DATA data, void *p)
1120 struct traverse_state *state = (struct traverse_state *)p;
1121 struct ctdb_rec_data *d = (struct ctdb_rec_data *)data.dptr;
1124 if (data.dsize < sizeof(uint32_t) ||
1125 d->length != data.dsize) {
1126 DEBUG(DEBUG_ERR,("Bad data size %u in traverse_handler\n", (unsigned)data.dsize));
1131 key.dsize = d->keylen;
1132 key.dptr = &d->data[0];
1133 data.dsize = d->datalen;
1134 data.dptr = &d->data[d->keylen];
1136 if (key.dsize == 0 && data.dsize == 0) {
1137 /* end of traverse */
1142 if (data.dsize == sizeof(struct ctdb_ltdb_header)) {
1143 /* empty records are deleted records in ctdb */
1147 if (state->fn(ctdb, key, data, state->private_data) != 0) {
1156 start a cluster wide traverse, calling the supplied fn on each record
1157 return the number of records traversed, or -1 on error
1159 int ctdb_traverse(struct ctdb_db_context *ctdb_db, ctdb_traverse_func fn, void *private_data)
1162 struct ctdb_traverse_start t;
1165 uint64_t srvid = (getpid() | 0xFLL<<60);
1166 struct traverse_state state;
1170 state.private_data = private_data;
1173 ret = ctdb_set_message_handler(ctdb_db->ctdb, srvid, traverse_handler, &state);
1175 DEBUG(DEBUG_ERR,("Failed to setup traverse handler\n"));
1179 t.db_id = ctdb_db->db_id;
1183 data.dptr = (uint8_t *)&t;
1184 data.dsize = sizeof(t);
1186 ret = ctdb_control(ctdb_db->ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_TRAVERSE_START, 0,
1187 data, NULL, NULL, &status, NULL, NULL);
1188 if (ret != 0 || status != 0) {
1189 DEBUG(DEBUG_ERR,("ctdb_traverse_all failed\n"));
1190 ctdb_remove_message_handler(ctdb_db->ctdb, srvid, &state);
1194 while (!state.done) {
1195 event_loop_once(ctdb_db->ctdb->ev);
1198 ret = ctdb_remove_message_handler(ctdb_db->ctdb, srvid, &state);
1200 DEBUG(DEBUG_ERR,("Failed to remove ctdb_traverse handler\n"));
1207 #define ISASCII(x) ((x>31)&&(x<128))
1209 called on each key during a catdb
1211 int ctdb_dumpdb_record(struct ctdb_context *ctdb, TDB_DATA key, TDB_DATA data, void *p)
1214 FILE *f = (FILE *)p;
1215 struct ctdb_ltdb_header *h = (struct ctdb_ltdb_header *)data.dptr;
1217 fprintf(f, "key(%u) = \"", (unsigned)key.dsize);
1218 for (i=0;i<key.dsize;i++) {
1219 if (ISASCII(key.dptr[i])) {
1220 fprintf(f, "%c", key.dptr[i]);
1222 fprintf(f, "\\%02X", key.dptr[i]);
1227 fprintf(f, "dmaster: %u\n", h->dmaster);
1228 fprintf(f, "rsn: %llu\n", (unsigned long long)h->rsn);
1230 fprintf(f, "data(%u) = \"", (unsigned)(data.dsize - sizeof(*h)));
1231 for (i=sizeof(*h);i<data.dsize;i++) {
1232 if (ISASCII(data.dptr[i])) {
1233 fprintf(f, "%c", data.dptr[i]);
1235 fprintf(f, "\\%02X", data.dptr[i]);
1246 convenience function to list all keys to stdout
1248 int ctdb_dump_db(struct ctdb_db_context *ctdb_db, FILE *f)
1250 return ctdb_traverse(ctdb_db, ctdb_dumpdb_record, f);
1254 get the pid of a ctdb daemon
1256 int ctdb_ctrl_getpid(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *pid)
1261 ret = ctdb_control(ctdb, destnode, 0,
1262 CTDB_CONTROL_GET_PID, 0, tdb_null,
1263 NULL, NULL, &res, &timeout, NULL);
1265 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getpid failed\n"));
1276 async freeze send control
1278 struct ctdb_client_control_state *
1279 ctdb_ctrl_freeze_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, uint32_t priority)
1281 return ctdb_control_send(ctdb, destnode, priority,
1282 CTDB_CONTROL_FREEZE, 0, tdb_null,
1283 mem_ctx, &timeout, NULL);
1287 async freeze recv control
1289 int ctdb_ctrl_freeze_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state)
1294 ret = ctdb_control_recv(ctdb, state, mem_ctx, NULL, &res, NULL);
1295 if ( (ret != 0) || (res != 0) ){
1296 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_freeze_recv failed\n"));
1304 freeze databases of a certain priority
1306 int ctdb_ctrl_freeze_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t priority)
1308 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1309 struct ctdb_client_control_state *state;
1312 state = ctdb_ctrl_freeze_send(ctdb, tmp_ctx, timeout, destnode, priority);
1313 ret = ctdb_ctrl_freeze_recv(ctdb, tmp_ctx, state);
1314 talloc_free(tmp_ctx);
1319 /* Freeze all databases */
1320 int ctdb_ctrl_freeze(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
1324 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
1325 if (ctdb_ctrl_freeze_priority(ctdb, timeout, destnode, i) != 0) {
1333 thaw databases of a certain priority
1335 int ctdb_ctrl_thaw_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t priority)
1340 ret = ctdb_control(ctdb, destnode, priority,
1341 CTDB_CONTROL_THAW, 0, tdb_null,
1342 NULL, NULL, &res, &timeout, NULL);
1343 if (ret != 0 || res != 0) {
1344 DEBUG(DEBUG_ERR,(__location__ " ctdb_control thaw failed\n"));
1351 /* thaw all databases */
1352 int ctdb_ctrl_thaw(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
1354 return ctdb_ctrl_thaw_priority(ctdb, timeout, destnode, 0);
1358 get pnn of a node, or -1
1360 int ctdb_ctrl_getpnn(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
1365 ret = ctdb_control(ctdb, destnode, 0,
1366 CTDB_CONTROL_GET_PNN, 0, tdb_null,
1367 NULL, NULL, &res, &timeout, NULL);
1369 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getpnn failed\n"));
1377 get the monitoring mode of a remote node
1379 int ctdb_ctrl_getmonmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *monmode)
1384 ret = ctdb_control(ctdb, destnode, 0,
1385 CTDB_CONTROL_GET_MONMODE, 0, tdb_null,
1386 NULL, NULL, &res, &timeout, NULL);
1388 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getmonmode failed\n"));
1399 set the monitoring mode of a remote node to active
1401 int ctdb_ctrl_enable_monmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
1406 ret = ctdb_control(ctdb, destnode, 0,
1407 CTDB_CONTROL_ENABLE_MONITOR, 0, tdb_null,
1408 NULL, NULL,NULL, &timeout, NULL);
1410 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for enable_monitor failed\n"));
1420 set the monitoring mode of a remote node to disable
1422 int ctdb_ctrl_disable_monmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
1427 ret = ctdb_control(ctdb, destnode, 0,
1428 CTDB_CONTROL_DISABLE_MONITOR, 0, tdb_null,
1429 NULL, NULL, NULL, &timeout, NULL);
1431 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for disable_monitor failed\n"));
1443 sent to a node to make it take over an ip address
1445 int ctdb_ctrl_takeover_ip(struct ctdb_context *ctdb, struct timeval timeout,
1446 uint32_t destnode, struct ctdb_public_ip *ip)
1449 struct ctdb_public_ipv4 ipv4;
1453 if (ip->addr.sa.sa_family == AF_INET) {
1455 ipv4.sin = ip->addr.ip;
1457 data.dsize = sizeof(ipv4);
1458 data.dptr = (uint8_t *)&ipv4;
1460 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_TAKEOVER_IPv4, 0, data, NULL,
1461 NULL, &res, &timeout, NULL);
1463 data.dsize = sizeof(*ip);
1464 data.dptr = (uint8_t *)ip;
1466 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_TAKEOVER_IP, 0, data, NULL,
1467 NULL, &res, &timeout, NULL);
1470 if (ret != 0 || res != 0) {
1471 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for takeover_ip failed\n"));
1480 sent to a node to make it release an ip address
1482 int ctdb_ctrl_release_ip(struct ctdb_context *ctdb, struct timeval timeout,
1483 uint32_t destnode, struct ctdb_public_ip *ip)
1486 struct ctdb_public_ipv4 ipv4;
1490 if (ip->addr.sa.sa_family == AF_INET) {
1492 ipv4.sin = ip->addr.ip;
1494 data.dsize = sizeof(ipv4);
1495 data.dptr = (uint8_t *)&ipv4;
1497 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_RELEASE_IPv4, 0, data, NULL,
1498 NULL, &res, &timeout, NULL);
1500 data.dsize = sizeof(*ip);
1501 data.dptr = (uint8_t *)ip;
1503 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_RELEASE_IP, 0, data, NULL,
1504 NULL, &res, &timeout, NULL);
1507 if (ret != 0 || res != 0) {
1508 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for release_ip failed\n"));
1519 int ctdb_ctrl_get_tunable(struct ctdb_context *ctdb,
1520 struct timeval timeout,
1522 const char *name, uint32_t *value)
1524 struct ctdb_control_get_tunable *t;
1525 TDB_DATA data, outdata;
1529 data.dsize = offsetof(struct ctdb_control_get_tunable, name) + strlen(name) + 1;
1530 data.dptr = talloc_size(ctdb, data.dsize);
1531 CTDB_NO_MEMORY(ctdb, data.dptr);
1533 t = (struct ctdb_control_get_tunable *)data.dptr;
1534 t->length = strlen(name)+1;
1535 memcpy(t->name, name, t->length);
1537 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_TUNABLE, 0, data, ctdb,
1538 &outdata, &res, &timeout, NULL);
1539 talloc_free(data.dptr);
1540 if (ret != 0 || res != 0) {
1541 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get_tunable failed\n"));
1545 if (outdata.dsize != sizeof(uint32_t)) {
1546 DEBUG(DEBUG_ERR,("Invalid return data in get_tunable\n"));
1547 talloc_free(outdata.dptr);
1551 *value = *(uint32_t *)outdata.dptr;
1552 talloc_free(outdata.dptr);
1560 int ctdb_ctrl_set_tunable(struct ctdb_context *ctdb,
1561 struct timeval timeout,
1563 const char *name, uint32_t value)
1565 struct ctdb_control_set_tunable *t;
1570 data.dsize = offsetof(struct ctdb_control_set_tunable, name) + strlen(name) + 1;
1571 data.dptr = talloc_size(ctdb, data.dsize);
1572 CTDB_NO_MEMORY(ctdb, data.dptr);
1574 t = (struct ctdb_control_set_tunable *)data.dptr;
1575 t->length = strlen(name)+1;
1576 memcpy(t->name, name, t->length);
1579 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SET_TUNABLE, 0, data, NULL,
1580 NULL, &res, &timeout, NULL);
1581 talloc_free(data.dptr);
1582 if (ret != 0 || res != 0) {
1583 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set_tunable failed\n"));
1593 int ctdb_ctrl_list_tunables(struct ctdb_context *ctdb,
1594 struct timeval timeout,
1596 TALLOC_CTX *mem_ctx,
1597 const char ***list, uint32_t *count)
1602 struct ctdb_control_list_tunable *t;
1605 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_LIST_TUNABLES, 0, tdb_null,
1606 mem_ctx, &outdata, &res, &timeout, NULL);
1607 if (ret != 0 || res != 0) {
1608 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for list_tunables failed\n"));
1612 t = (struct ctdb_control_list_tunable *)outdata.dptr;
1613 if (outdata.dsize < offsetof(struct ctdb_control_list_tunable, data) ||
1614 t->length > outdata.dsize-offsetof(struct ctdb_control_list_tunable, data)) {
1615 DEBUG(DEBUG_ERR,("Invalid data in list_tunables reply\n"));
1616 talloc_free(outdata.dptr);
1620 p = talloc_strndup(mem_ctx, (char *)t->data, t->length);
1621 CTDB_NO_MEMORY(ctdb, p);
1623 talloc_free(outdata.dptr);
1628 for (s=strtok_r(p, ":", &ptr); s; s=strtok_r(NULL, ":", &ptr)) {
1629 (*list) = talloc_realloc(mem_ctx, *list, const char *, 1+(*count));
1630 CTDB_NO_MEMORY(ctdb, *list);
1631 (*list)[*count] = talloc_strdup(*list, s);
1632 CTDB_NO_MEMORY(ctdb, (*list)[*count]);
1642 int ctdb_ctrl_get_public_ips_flags(struct ctdb_context *ctdb,
1643 struct timeval timeout, uint32_t destnode,
1644 TALLOC_CTX *mem_ctx,
1646 struct ctdb_all_public_ips **ips)
1652 ret = ctdb_control(ctdb, destnode, 0,
1653 CTDB_CONTROL_GET_PUBLIC_IPS, flags, tdb_null,
1654 mem_ctx, &outdata, &res, &timeout, NULL);
1655 if (ret == 0 && res == -1) {
1656 DEBUG(DEBUG_ERR,(__location__ " ctdb_control to get public ips failed, falling back to ipv4-only version\n"));
1657 return ctdb_ctrl_get_public_ipsv4(ctdb, timeout, destnode, mem_ctx, ips);
1659 if (ret != 0 || res != 0) {
1660 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getpublicips failed ret:%d res:%d\n", ret, res));
1664 *ips = (struct ctdb_all_public_ips *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
1665 talloc_free(outdata.dptr);
1670 int ctdb_ctrl_get_public_ips(struct ctdb_context *ctdb,
1671 struct timeval timeout, uint32_t destnode,
1672 TALLOC_CTX *mem_ctx,
1673 struct ctdb_all_public_ips **ips)
1675 return ctdb_ctrl_get_public_ips_flags(ctdb, timeout,
1680 int ctdb_ctrl_get_public_ipsv4(struct ctdb_context *ctdb,
1681 struct timeval timeout, uint32_t destnode,
1682 TALLOC_CTX *mem_ctx, struct ctdb_all_public_ips **ips)
1687 struct ctdb_all_public_ipsv4 *ipsv4;
1689 ret = ctdb_control(ctdb, destnode, 0,
1690 CTDB_CONTROL_GET_PUBLIC_IPSv4, 0, tdb_null,
1691 mem_ctx, &outdata, &res, &timeout, NULL);
1692 if (ret != 0 || res != 0) {
1693 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getpublicips failed\n"));
1697 ipsv4 = (struct ctdb_all_public_ipsv4 *)outdata.dptr;
1698 len = offsetof(struct ctdb_all_public_ips, ips) +
1699 ipsv4->num*sizeof(struct ctdb_public_ip);
1700 *ips = talloc_zero_size(mem_ctx, len);
1701 CTDB_NO_MEMORY(ctdb, *ips);
1702 (*ips)->num = ipsv4->num;
1703 for (i=0; i<ipsv4->num; i++) {
1704 (*ips)->ips[i].pnn = ipsv4->ips[i].pnn;
1705 (*ips)->ips[i].addr.ip = ipsv4->ips[i].sin;
1708 talloc_free(outdata.dptr);
1713 int ctdb_ctrl_get_public_ip_info(struct ctdb_context *ctdb,
1714 struct timeval timeout, uint32_t destnode,
1715 TALLOC_CTX *mem_ctx,
1716 const ctdb_sock_addr *addr,
1717 struct ctdb_control_public_ip_info **_info)
1723 struct ctdb_control_public_ip_info *info;
1727 indata.dptr = discard_const_p(uint8_t, addr);
1728 indata.dsize = sizeof(*addr);
1730 ret = ctdb_control(ctdb, destnode, 0,
1731 CTDB_CONTROL_GET_PUBLIC_IP_INFO, 0, indata,
1732 mem_ctx, &outdata, &res, &timeout, NULL);
1733 if (ret != 0 || res != 0) {
1734 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
1735 "failed ret:%d res:%d\n",
1740 len = offsetof(struct ctdb_control_public_ip_info, ifaces);
1741 if (len > outdata.dsize) {
1742 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
1743 "returned invalid data with size %u > %u\n",
1744 (unsigned int)outdata.dsize,
1745 (unsigned int)len));
1746 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
1750 info = (struct ctdb_control_public_ip_info *)outdata.dptr;
1751 len += info->num*sizeof(struct ctdb_control_iface_info);
1753 if (len > outdata.dsize) {
1754 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
1755 "returned invalid data with size %u > %u\n",
1756 (unsigned int)outdata.dsize,
1757 (unsigned int)len));
1758 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
1762 /* make sure we null terminate the returned strings */
1763 for (i=0; i < info->num; i++) {
1764 info->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
1767 *_info = (struct ctdb_control_public_ip_info *)talloc_memdup(mem_ctx,
1770 talloc_free(outdata.dptr);
1771 if (*_info == NULL) {
1772 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
1773 "talloc_memdup size %u failed\n",
1774 (unsigned int)outdata.dsize));
1781 int ctdb_ctrl_get_ifaces(struct ctdb_context *ctdb,
1782 struct timeval timeout, uint32_t destnode,
1783 TALLOC_CTX *mem_ctx,
1784 struct ctdb_control_get_ifaces **_ifaces)
1789 struct ctdb_control_get_ifaces *ifaces;
1793 ret = ctdb_control(ctdb, destnode, 0,
1794 CTDB_CONTROL_GET_IFACES, 0, tdb_null,
1795 mem_ctx, &outdata, &res, &timeout, NULL);
1796 if (ret != 0 || res != 0) {
1797 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
1798 "failed ret:%d res:%d\n",
1803 len = offsetof(struct ctdb_control_get_ifaces, ifaces);
1804 if (len > outdata.dsize) {
1805 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
1806 "returned invalid data with size %u > %u\n",
1807 (unsigned int)outdata.dsize,
1808 (unsigned int)len));
1809 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
1813 ifaces = (struct ctdb_control_get_ifaces *)outdata.dptr;
1814 len += ifaces->num*sizeof(struct ctdb_control_iface_info);
1816 if (len > outdata.dsize) {
1817 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
1818 "returned invalid data with size %u > %u\n",
1819 (unsigned int)outdata.dsize,
1820 (unsigned int)len));
1821 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
1825 /* make sure we null terminate the returned strings */
1826 for (i=0; i < ifaces->num; i++) {
1827 ifaces->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
1830 *_ifaces = (struct ctdb_control_get_ifaces *)talloc_memdup(mem_ctx,
1833 talloc_free(outdata.dptr);
1834 if (*_ifaces == NULL) {
1835 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
1836 "talloc_memdup size %u failed\n",
1837 (unsigned int)outdata.dsize));
1844 int ctdb_ctrl_set_iface_link(struct ctdb_context *ctdb,
1845 struct timeval timeout, uint32_t destnode,
1846 TALLOC_CTX *mem_ctx,
1847 const struct ctdb_control_iface_info *info)
1853 indata.dptr = discard_const_p(uint8_t, info);
1854 indata.dsize = sizeof(*info);
1856 ret = ctdb_control(ctdb, destnode, 0,
1857 CTDB_CONTROL_SET_IFACE_LINK_STATE, 0, indata,
1858 mem_ctx, NULL, &res, &timeout, NULL);
1859 if (ret != 0 || res != 0) {
1860 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set iface link "
1861 "failed ret:%d res:%d\n",
1870 set/clear the permanent disabled bit on a remote node
1872 int ctdb_ctrl_modflags(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
1873 uint32_t set, uint32_t clear)
1877 struct ctdb_node_map *nodemap=NULL;
1878 struct ctdb_node_flag_change c;
1879 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1884 /* find the recovery master */
1885 ret = ctdb_ctrl_getrecmaster(ctdb, tmp_ctx, timeout, CTDB_CURRENT_NODE, &recmaster);
1887 DEBUG(DEBUG_ERR, (__location__ " Unable to get recmaster from local node\n"));
1888 talloc_free(tmp_ctx);
1893 /* read the node flags from the recmaster */
1894 ret = ctdb_ctrl_getnodemap(ctdb, timeout, recmaster, tmp_ctx, &nodemap);
1896 DEBUG(DEBUG_ERR, (__location__ " Unable to get nodemap from node %u\n", destnode));
1897 talloc_free(tmp_ctx);
1900 if (destnode >= nodemap->num) {
1901 DEBUG(DEBUG_ERR,(__location__ " Nodemap from recmaster does not contain node %d\n", destnode));
1902 talloc_free(tmp_ctx);
1907 c.old_flags = nodemap->nodes[destnode].flags;
1908 c.new_flags = c.old_flags;
1910 c.new_flags &= ~clear;
1912 data.dsize = sizeof(c);
1913 data.dptr = (unsigned char *)&c;
1915 /* send the flags update to all connected nodes */
1916 nodes = list_of_connected_nodes(ctdb, nodemap, tmp_ctx, true);
1918 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_MODIFY_FLAGS,
1920 timeout, false, data,
1923 DEBUG(DEBUG_ERR, (__location__ " Unable to update nodeflags on remote nodes\n"));
1925 talloc_free(tmp_ctx);
1929 talloc_free(tmp_ctx);
1937 int ctdb_ctrl_get_all_tunables(struct ctdb_context *ctdb,
1938 struct timeval timeout,
1940 struct ctdb_tunable *tunables)
1946 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_ALL_TUNABLES, 0, tdb_null, ctdb,
1947 &outdata, &res, &timeout, NULL);
1948 if (ret != 0 || res != 0) {
1949 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get all tunables failed\n"));
1953 if (outdata.dsize != sizeof(*tunables)) {
1954 DEBUG(DEBUG_ERR,(__location__ " bad data size %u in ctdb_ctrl_get_all_tunables should be %u\n",
1955 (unsigned)outdata.dsize, (unsigned)sizeof(*tunables)));
1959 *tunables = *(struct ctdb_tunable *)outdata.dptr;
1960 talloc_free(outdata.dptr);
1965 add a public address to a node
1967 int ctdb_ctrl_add_public_ip(struct ctdb_context *ctdb,
1968 struct timeval timeout,
1970 struct ctdb_control_ip_iface *pub)
1976 data.dsize = offsetof(struct ctdb_control_ip_iface, iface) + pub->len;
1977 data.dptr = (unsigned char *)pub;
1979 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_ADD_PUBLIC_IP, 0, data, NULL,
1980 NULL, &res, &timeout, NULL);
1981 if (ret != 0 || res != 0) {
1982 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for add_public_ip failed\n"));
1990 delete a public address from a node
1992 int ctdb_ctrl_del_public_ip(struct ctdb_context *ctdb,
1993 struct timeval timeout,
1995 struct ctdb_control_ip_iface *pub)
2001 data.dsize = offsetof(struct ctdb_control_ip_iface, iface) + pub->len;
2002 data.dptr = (unsigned char *)pub;
2004 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_DEL_PUBLIC_IP, 0, data, NULL,
2005 NULL, &res, &timeout, NULL);
2006 if (ret != 0 || res != 0) {
2007 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for del_public_ip failed\n"));
2015 kill a tcp connection
2017 int ctdb_ctrl_killtcp(struct ctdb_context *ctdb,
2018 struct timeval timeout,
2020 struct ctdb_control_killtcp *killtcp)
2026 data.dsize = sizeof(struct ctdb_control_killtcp);
2027 data.dptr = (unsigned char *)killtcp;
2029 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_KILL_TCP, 0, data, NULL,
2030 NULL, &res, &timeout, NULL);
2031 if (ret != 0 || res != 0) {
2032 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for killtcp failed\n"));
2042 int ctdb_ctrl_gratious_arp(struct ctdb_context *ctdb,
2043 struct timeval timeout,
2045 ctdb_sock_addr *addr,
2051 struct ctdb_control_gratious_arp *gratious_arp;
2052 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2055 len = strlen(ifname)+1;
2056 gratious_arp = talloc_size(tmp_ctx,
2057 offsetof(struct ctdb_control_gratious_arp, iface) + len);
2058 CTDB_NO_MEMORY(ctdb, gratious_arp);
2060 gratious_arp->addr = *addr;
2061 gratious_arp->len = len;
2062 memcpy(&gratious_arp->iface[0], ifname, len);
2065 data.dsize = offsetof(struct ctdb_control_gratious_arp, iface) + len;
2066 data.dptr = (unsigned char *)gratious_arp;
2068 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SEND_GRATIOUS_ARP, 0, data, NULL,
2069 NULL, &res, &timeout, NULL);
2070 if (ret != 0 || res != 0) {
2071 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for gratious_arp failed\n"));
2072 talloc_free(tmp_ctx);
2076 talloc_free(tmp_ctx);
2081 get a list of all tcp tickles that a node knows about for a particular vnn
2083 int ctdb_ctrl_get_tcp_tickles(struct ctdb_context *ctdb,
2084 struct timeval timeout, uint32_t destnode,
2085 TALLOC_CTX *mem_ctx,
2086 ctdb_sock_addr *addr,
2087 struct ctdb_control_tcp_tickle_list **list)
2090 TDB_DATA data, outdata;
2093 data.dptr = (uint8_t*)addr;
2094 data.dsize = sizeof(ctdb_sock_addr);
2096 ret = ctdb_control(ctdb, destnode, 0,
2097 CTDB_CONTROL_GET_TCP_TICKLE_LIST, 0, data,
2098 mem_ctx, &outdata, &status, NULL, NULL);
2099 if (ret != 0 || status != 0) {
2100 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get tcp tickles failed\n"));
2104 *list = (struct ctdb_control_tcp_tickle_list *)outdata.dptr;
2110 register a server id
2112 int ctdb_ctrl_register_server_id(struct ctdb_context *ctdb,
2113 struct timeval timeout,
2114 struct ctdb_server_id *id)
2120 data.dsize = sizeof(struct ctdb_server_id);
2121 data.dptr = (unsigned char *)id;
2123 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0,
2124 CTDB_CONTROL_REGISTER_SERVER_ID,
2126 NULL, &res, &timeout, NULL);
2127 if (ret != 0 || res != 0) {
2128 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for register server id failed\n"));
2136 unregister a server id
2138 int ctdb_ctrl_unregister_server_id(struct ctdb_context *ctdb,
2139 struct timeval timeout,
2140 struct ctdb_server_id *id)
2146 data.dsize = sizeof(struct ctdb_server_id);
2147 data.dptr = (unsigned char *)id;
2149 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0,
2150 CTDB_CONTROL_UNREGISTER_SERVER_ID,
2152 NULL, &res, &timeout, NULL);
2153 if (ret != 0 || res != 0) {
2154 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for unregister server id failed\n"));
2163 check if a server id exists
2165 if a server id does exist, return *status == 1, otherwise *status == 0
2167 int ctdb_ctrl_check_server_id(struct ctdb_context *ctdb,
2168 struct timeval timeout,
2170 struct ctdb_server_id *id,
2177 data.dsize = sizeof(struct ctdb_server_id);
2178 data.dptr = (unsigned char *)id;
2180 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_CHECK_SERVER_ID,
2182 NULL, &res, &timeout, NULL);
2184 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for check server id failed\n"));
2198 get the list of server ids that are registered on a node
2200 int ctdb_ctrl_get_server_id_list(struct ctdb_context *ctdb,
2201 TALLOC_CTX *mem_ctx,
2202 struct timeval timeout, uint32_t destnode,
2203 struct ctdb_server_id_list **svid_list)
2209 ret = ctdb_control(ctdb, destnode, 0,
2210 CTDB_CONTROL_GET_SERVER_ID_LIST, 0, tdb_null,
2211 mem_ctx, &outdata, &res, &timeout, NULL);
2212 if (ret != 0 || res != 0) {
2213 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get_server_id_list failed\n"));
2217 *svid_list = (struct ctdb_server_id_list *)talloc_steal(mem_ctx, outdata.dptr);
2223 initialise the ctdb daemon for client applications
2225 NOTE: In current code the daemon does not fork. This is for testing purposes only
2226 and to simplify the code.
2228 struct ctdb_context *ctdb_init(struct event_context *ev)
2231 struct ctdb_context *ctdb;
2233 ctdb = talloc_zero(ev, struct ctdb_context);
2235 DEBUG(DEBUG_ERR,(__location__ " talloc_zero failed.\n"));
2239 ctdb->idr = idr_init(ctdb);
2240 CTDB_NO_MEMORY_NULL(ctdb, ctdb->idr);
2242 ret = ctdb_set_socketname(ctdb, CTDB_PATH);
2244 DEBUG(DEBUG_ERR,(__location__ " ctdb_set_socketname failed.\n"));
2256 void ctdb_set_flags(struct ctdb_context *ctdb, unsigned flags)
2258 ctdb->flags |= flags;
2263 return the pnn of this node
2265 uint32_t ctdb_get_pnn(struct ctdb_context *ctdb)
2272 get the uptime of a remote node
2274 struct ctdb_client_control_state *
2275 ctdb_ctrl_uptime_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode)
2277 return ctdb_control_send(ctdb, destnode, 0,
2278 CTDB_CONTROL_UPTIME, 0, tdb_null,
2279 mem_ctx, &timeout, NULL);
2282 int ctdb_ctrl_uptime_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, struct ctdb_uptime **uptime)
2288 ret = ctdb_control_recv(ctdb, state, mem_ctx, &outdata, &res, NULL);
2289 if (ret != 0 || res != 0) {
2290 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_uptime_recv failed\n"));
2294 *uptime = (struct ctdb_uptime *)talloc_steal(mem_ctx, outdata.dptr);
2299 int ctdb_ctrl_uptime(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, struct ctdb_uptime **uptime)
2301 struct ctdb_client_control_state *state;
2303 state = ctdb_ctrl_uptime_send(ctdb, mem_ctx, timeout, destnode);
2304 return ctdb_ctrl_uptime_recv(ctdb, mem_ctx, state, uptime);
2308 send a control to execute the "recovered" event script on a node
2310 int ctdb_ctrl_end_recovery(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2315 ret = ctdb_control(ctdb, destnode, 0,
2316 CTDB_CONTROL_END_RECOVERY, 0, tdb_null,
2317 NULL, NULL, &status, &timeout, NULL);
2318 if (ret != 0 || status != 0) {
2319 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for end_recovery failed\n"));
2327 callback for the async helpers used when sending the same control
2328 to multiple nodes in parallell.
2330 static void async_callback(struct ctdb_client_control_state *state)
2332 struct client_async_data *data = talloc_get_type(state->async.private_data, struct client_async_data);
2333 struct ctdb_context *ctdb = talloc_get_type(state->ctdb, struct ctdb_context);
2337 uint32_t destnode = state->c->hdr.destnode;
2339 /* one more node has responded with recmode data */
2342 /* if we failed to push the db, then return an error and let
2343 the main loop try again.
2345 if (state->state != CTDB_CONTROL_DONE) {
2346 if ( !data->dont_log_errors) {
2347 DEBUG(DEBUG_ERR,("Async operation failed with state %d, opcode:%u\n", state->state, data->opcode));
2350 if (data->fail_callback) {
2351 data->fail_callback(ctdb, destnode, res, outdata,
2352 data->callback_data);
2357 state->async.fn = NULL;
2359 ret = ctdb_control_recv(ctdb, state, data, &outdata, &res, NULL);
2360 if ((ret != 0) || (res != 0)) {
2361 if ( !data->dont_log_errors) {
2362 DEBUG(DEBUG_ERR,("Async operation failed with ret=%d res=%d opcode=%u\n", ret, (int)res, data->opcode));
2365 if (data->fail_callback) {
2366 data->fail_callback(ctdb, destnode, res, outdata,
2367 data->callback_data);
2370 if ((ret == 0) && (data->callback != NULL)) {
2371 data->callback(ctdb, destnode, res, outdata,
2372 data->callback_data);
2377 void ctdb_client_async_add(struct client_async_data *data, struct ctdb_client_control_state *state)
2379 /* set up the callback functions */
2380 state->async.fn = async_callback;
2381 state->async.private_data = data;
2383 /* one more control to wait for to complete */
2388 /* wait for up to the maximum number of seconds allowed
2389 or until all nodes we expect a response from has replied
2391 int ctdb_client_async_wait(struct ctdb_context *ctdb, struct client_async_data *data)
2393 while (data->count > 0) {
2394 event_loop_once(ctdb->ev);
2396 if (data->fail_count != 0) {
2397 if (!data->dont_log_errors) {
2398 DEBUG(DEBUG_ERR,("Async wait failed - fail_count=%u\n",
2408 perform a simple control on the listed nodes
2409 The control cannot return data
2411 int ctdb_client_async_control(struct ctdb_context *ctdb,
2412 enum ctdb_controls opcode,
2415 struct timeval timeout,
2416 bool dont_log_errors,
2418 client_async_callback client_callback,
2419 client_async_callback fail_callback,
2420 void *callback_data)
2422 struct client_async_data *async_data;
2423 struct ctdb_client_control_state *state;
2426 async_data = talloc_zero(ctdb, struct client_async_data);
2427 CTDB_NO_MEMORY_FATAL(ctdb, async_data);
2428 async_data->dont_log_errors = dont_log_errors;
2429 async_data->callback = client_callback;
2430 async_data->fail_callback = fail_callback;
2431 async_data->callback_data = callback_data;
2432 async_data->opcode = opcode;
2434 num_nodes = talloc_get_size(nodes) / sizeof(uint32_t);
2436 /* loop over all nodes and send an async control to each of them */
2437 for (j=0; j<num_nodes; j++) {
2438 uint32_t pnn = nodes[j];
2440 state = ctdb_control_send(ctdb, pnn, srvid, opcode,
2441 0, data, async_data, &timeout, NULL);
2442 if (state == NULL) {
2443 DEBUG(DEBUG_ERR,(__location__ " Failed to call async control %u\n", (unsigned)opcode));
2444 talloc_free(async_data);
2448 ctdb_client_async_add(async_data, state);
2451 if (ctdb_client_async_wait(ctdb, async_data) != 0) {
2452 talloc_free(async_data);
2456 talloc_free(async_data);
2460 uint32_t *list_of_vnnmap_nodes(struct ctdb_context *ctdb,
2461 struct ctdb_vnn_map *vnn_map,
2462 TALLOC_CTX *mem_ctx,
2465 int i, j, num_nodes;
2468 for (i=num_nodes=0;i<vnn_map->size;i++) {
2469 if (vnn_map->map[i] == ctdb->pnn && !include_self) {
2475 nodes = talloc_array(mem_ctx, uint32_t, num_nodes);
2476 CTDB_NO_MEMORY_FATAL(ctdb, nodes);
2478 for (i=j=0;i<vnn_map->size;i++) {
2479 if (vnn_map->map[i] == ctdb->pnn && !include_self) {
2482 nodes[j++] = vnn_map->map[i];
2488 uint32_t *list_of_active_nodes(struct ctdb_context *ctdb,
2489 struct ctdb_node_map *node_map,
2490 TALLOC_CTX *mem_ctx,
2493 int i, j, num_nodes;
2496 for (i=num_nodes=0;i<node_map->num;i++) {
2497 if (node_map->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2500 if (node_map->nodes[i].pnn == ctdb->pnn && !include_self) {
2506 nodes = talloc_array(mem_ctx, uint32_t, num_nodes);
2507 CTDB_NO_MEMORY_FATAL(ctdb, nodes);
2509 for (i=j=0;i<node_map->num;i++) {
2510 if (node_map->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2513 if (node_map->nodes[i].pnn == ctdb->pnn && !include_self) {
2516 nodes[j++] = node_map->nodes[i].pnn;
2522 uint32_t *list_of_active_nodes_except_pnn(struct ctdb_context *ctdb,
2523 struct ctdb_node_map *node_map,
2524 TALLOC_CTX *mem_ctx,
2527 int i, j, num_nodes;
2530 for (i=num_nodes=0;i<node_map->num;i++) {
2531 if (node_map->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2534 if (node_map->nodes[i].pnn == pnn) {
2540 nodes = talloc_array(mem_ctx, uint32_t, num_nodes);
2541 CTDB_NO_MEMORY_FATAL(ctdb, nodes);
2543 for (i=j=0;i<node_map->num;i++) {
2544 if (node_map->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2547 if (node_map->nodes[i].pnn == pnn) {
2550 nodes[j++] = node_map->nodes[i].pnn;
2556 uint32_t *list_of_connected_nodes(struct ctdb_context *ctdb,
2557 struct ctdb_node_map *node_map,
2558 TALLOC_CTX *mem_ctx,
2561 int i, j, num_nodes;
2564 for (i=num_nodes=0;i<node_map->num;i++) {
2565 if (node_map->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
2568 if (node_map->nodes[i].pnn == ctdb->pnn && !include_self) {
2574 nodes = talloc_array(mem_ctx, uint32_t, num_nodes);
2575 CTDB_NO_MEMORY_FATAL(ctdb, nodes);
2577 for (i=j=0;i<node_map->num;i++) {
2578 if (node_map->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
2581 if (node_map->nodes[i].pnn == ctdb->pnn && !include_self) {
2584 nodes[j++] = node_map->nodes[i].pnn;
2591 this is used to test if a pnn lock exists and if it exists will return
2592 the number of connections that pnn has reported or -1 if that recovery
2593 daemon is not running.
2596 ctdb_read_pnn_lock(int fd, int32_t pnn)
2601 lock.l_type = F_WRLCK;
2602 lock.l_whence = SEEK_SET;
2607 if (fcntl(fd, F_GETLK, &lock) != 0) {
2608 DEBUG(DEBUG_ERR, (__location__ " F_GETLK failed with %s\n", strerror(errno)));
2612 if (lock.l_type == F_UNLCK) {
2616 if (pread(fd, &c, 1, pnn) == -1) {
2617 DEBUG(DEBUG_CRIT,(__location__ " failed read pnn count - %s\n", strerror(errno)));
2625 get capabilities of a remote node
2627 struct ctdb_client_control_state *
2628 ctdb_ctrl_getcapabilities_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode)
2630 return ctdb_control_send(ctdb, destnode, 0,
2631 CTDB_CONTROL_GET_CAPABILITIES, 0, tdb_null,
2632 mem_ctx, &timeout, NULL);
2635 int ctdb_ctrl_getcapabilities_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *capabilities)
2641 ret = ctdb_control_recv(ctdb, state, mem_ctx, &outdata, &res, NULL);
2642 if ( (ret != 0) || (res != 0) ) {
2643 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_getcapabilities_recv failed\n"));
2648 *capabilities = *((uint32_t *)outdata.dptr);
2654 int ctdb_ctrl_getcapabilities(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *capabilities)
2656 struct ctdb_client_control_state *state;
2657 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
2660 state = ctdb_ctrl_getcapabilities_send(ctdb, tmp_ctx, timeout, destnode);
2661 ret = ctdb_ctrl_getcapabilities_recv(ctdb, tmp_ctx, state, capabilities);
2662 talloc_free(tmp_ctx);
2667 * check whether a transaction is active on a given db on a given node
2669 int32_t ctdb_ctrl_transaction_active(struct ctdb_context *ctdb,
2677 indata.dptr = (uint8_t *)&db_id;
2678 indata.dsize = sizeof(db_id);
2680 ret = ctdb_control(ctdb, destnode, 0,
2681 CTDB_CONTROL_TRANS2_ACTIVE,
2682 0, indata, NULL, NULL, &status,
2686 DEBUG(DEBUG_ERR, (__location__ " ctdb control for transaction_active failed\n"));
2694 struct ctdb_transaction_handle {
2695 struct ctdb_db_context *ctdb_db;
2698 * we store the reads and writes done under a transaction:
2699 * - one list stores both reads and writes (m_all),
2700 * - the other just writes (m_write)
2702 struct ctdb_marshall_buffer *m_all;
2703 struct ctdb_marshall_buffer *m_write;
2706 /* start a transaction on a database */
2707 static int ctdb_transaction_destructor(struct ctdb_transaction_handle *h)
2709 tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
2713 /* start a transaction on a database */
2714 static int ctdb_transaction_fetch_start(struct ctdb_transaction_handle *h)
2716 struct ctdb_record_handle *rh;
2719 struct ctdb_ltdb_header header;
2720 TALLOC_CTX *tmp_ctx;
2721 const char *keyname = CTDB_TRANSACTION_LOCK_KEY;
2723 struct ctdb_db_context *ctdb_db = h->ctdb_db;
2727 key.dptr = discard_const(keyname);
2728 key.dsize = strlen(keyname);
2730 if (!ctdb_db->persistent) {
2731 DEBUG(DEBUG_ERR,(__location__ " Attempted transaction on non-persistent database\n"));
2736 tmp_ctx = talloc_new(h);
2738 rh = ctdb_fetch_lock(ctdb_db, tmp_ctx, key, NULL);
2740 DEBUG(DEBUG_ERR,(__location__ " Failed to fetch_lock database\n"));
2741 talloc_free(tmp_ctx);
2745 status = ctdb_ctrl_transaction_active(ctdb_db->ctdb,
2749 unsigned long int usec = (1000 + random()) % 100000;
2750 DEBUG(DEBUG_DEBUG, (__location__ " transaction is active "
2751 "on db_id[0x%08x]. waiting for %lu "
2753 ctdb_db->db_id, usec));
2754 talloc_free(tmp_ctx);
2760 * store the pid in the database:
2761 * it is not enough that the node is dmaster...
2764 data.dptr = (unsigned char *)&pid;
2765 data.dsize = sizeof(pid_t);
2767 rh->header.dmaster = ctdb_db->ctdb->pnn;
2768 ret = ctdb_ltdb_store(ctdb_db, key, &(rh->header), data);
2770 DEBUG(DEBUG_ERR, (__location__ " Failed to store pid in "
2771 "transaction record\n"));
2772 talloc_free(tmp_ctx);
2778 ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
2780 DEBUG(DEBUG_ERR,(__location__ " Failed to start tdb transaction\n"));
2781 talloc_free(tmp_ctx);
2785 ret = ctdb_ltdb_fetch(ctdb_db, key, &header, tmp_ctx, &data);
2787 DEBUG(DEBUG_ERR,(__location__ " Failed to re-fetch transaction "
2788 "lock record inside transaction\n"));
2789 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
2790 talloc_free(tmp_ctx);
2794 if (header.dmaster != ctdb_db->ctdb->pnn) {
2795 DEBUG(DEBUG_DEBUG,(__location__ " not dmaster any more on "
2796 "transaction lock record\n"));
2797 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
2798 talloc_free(tmp_ctx);
2802 if ((data.dsize != sizeof(pid_t)) || (*(pid_t *)(data.dptr) != pid)) {
2803 DEBUG(DEBUG_DEBUG, (__location__ " my pid is not stored in "
2804 "the transaction lock record\n"));
2805 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
2806 talloc_free(tmp_ctx);
2810 talloc_free(tmp_ctx);
2816 /* start a transaction on a database */
2817 struct ctdb_transaction_handle *ctdb_transaction_start(struct ctdb_db_context *ctdb_db,
2818 TALLOC_CTX *mem_ctx)
2820 struct ctdb_transaction_handle *h;
2823 h = talloc_zero(mem_ctx, struct ctdb_transaction_handle);
2825 DEBUG(DEBUG_ERR,(__location__ " oom for transaction handle\n"));
2829 h->ctdb_db = ctdb_db;
2831 ret = ctdb_transaction_fetch_start(h);
2837 talloc_set_destructor(h, ctdb_transaction_destructor);
2845 fetch a record inside a transaction
2847 int ctdb_transaction_fetch(struct ctdb_transaction_handle *h,
2848 TALLOC_CTX *mem_ctx,
2849 TDB_DATA key, TDB_DATA *data)
2851 struct ctdb_ltdb_header header;
2854 ZERO_STRUCT(header);
2856 ret = ctdb_ltdb_fetch(h->ctdb_db, key, &header, mem_ctx, data);
2857 if (ret == -1 && header.dmaster == (uint32_t)-1) {
2858 /* record doesn't exist yet */
2867 if (!h->in_replay) {
2868 h->m_all = ctdb_marshall_add(h, h->m_all, h->ctdb_db->db_id, 1, key, NULL, *data);
2869 if (h->m_all == NULL) {
2870 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
2879 stores a record inside a transaction
2881 int ctdb_transaction_store(struct ctdb_transaction_handle *h,
2882 TDB_DATA key, TDB_DATA data)
2884 TALLOC_CTX *tmp_ctx = talloc_new(h);
2885 struct ctdb_ltdb_header header;
2889 ZERO_STRUCT(header);
2891 /* we need the header so we can update the RSN */
2892 ret = ctdb_ltdb_fetch(h->ctdb_db, key, &header, tmp_ctx, &olddata);
2893 if (ret == -1 && header.dmaster == (uint32_t)-1) {
2894 /* the record doesn't exist - create one with us as dmaster.
2895 This is only safe because we are in a transaction and this
2896 is a persistent database */
2897 ZERO_STRUCT(header);
2898 } else if (ret != 0) {
2899 DEBUG(DEBUG_ERR,(__location__ " Failed to fetch record\n"));
2900 talloc_free(tmp_ctx);
2904 if (data.dsize == olddata.dsize &&
2905 memcmp(data.dptr, olddata.dptr, data.dsize) == 0) {
2906 /* save writing the same data */
2907 talloc_free(tmp_ctx);
2911 header.dmaster = h->ctdb_db->ctdb->pnn;
2914 if (!h->in_replay) {
2915 h->m_all = ctdb_marshall_add(h, h->m_all, h->ctdb_db->db_id, 0, key, NULL, data);
2916 if (h->m_all == NULL) {
2917 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
2918 talloc_free(tmp_ctx);
2923 h->m_write = ctdb_marshall_add(h, h->m_write, h->ctdb_db->db_id, 0, key, &header, data);
2924 if (h->m_write == NULL) {
2925 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
2926 talloc_free(tmp_ctx);
2930 ret = ctdb_ltdb_store(h->ctdb_db, key, &header, data);
2932 talloc_free(tmp_ctx);
2938 replay a transaction
2940 static int ctdb_replay_transaction(struct ctdb_transaction_handle *h)
2943 struct ctdb_rec_data *rec = NULL;
2945 h->in_replay = true;
2946 talloc_free(h->m_write);
2949 ret = ctdb_transaction_fetch_start(h);
2954 for (i=0;i<h->m_all->count;i++) {
2957 rec = ctdb_marshall_loop_next(h->m_all, rec, NULL, NULL, &key, &data);
2959 DEBUG(DEBUG_ERR, (__location__ " Out of records in ctdb_replay_transaction?\n"));
2963 if (rec->reqid == 0) {
2965 if (ctdb_transaction_store(h, key, data) != 0) {
2970 TALLOC_CTX *tmp_ctx = talloc_new(h);
2972 if (ctdb_transaction_fetch(h, tmp_ctx, key, &data2) != 0) {
2973 talloc_free(tmp_ctx);
2976 if (data2.dsize != data.dsize ||
2977 memcmp(data2.dptr, data.dptr, data.dsize) != 0) {
2978 /* the record has changed on us - we have to give up */
2979 talloc_free(tmp_ctx);
2982 talloc_free(tmp_ctx);
2989 tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
2995 commit a transaction
2997 int ctdb_transaction_commit(struct ctdb_transaction_handle *h)
3001 struct ctdb_context *ctdb = h->ctdb_db->ctdb;
3002 struct timeval timeout;
3003 enum ctdb_controls failure_control = CTDB_CONTROL_TRANS2_ERROR;
3005 talloc_set_destructor(h, NULL);
3007 /* our commit strategy is quite complex.
3009 - we first try to commit the changes to all other nodes
3011 - if that works, then we commit locally and we are done
3013 - if a commit on another node fails, then we need to cancel
3014 the transaction, then restart the transaction (thus
3015 opening a window of time for a pending recovery to
3016 complete), then replay the transaction, checking all the
3017 reads and writes (checking that reads give the same data,
3018 and writes succeed). Then we retry the transaction to the
3023 if (h->m_write == NULL) {
3024 /* no changes were made */
3025 tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
3030 /* tell ctdbd to commit to the other nodes */
3031 timeout = timeval_current_ofs(1, 0);
3032 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
3033 retries==0?CTDB_CONTROL_TRANS2_COMMIT:CTDB_CONTROL_TRANS2_COMMIT_RETRY, 0,
3034 ctdb_marshall_finish(h->m_write), NULL, NULL, &status,
3036 if (ret != 0 || status != 0) {
3037 tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
3038 DEBUG(DEBUG_NOTICE, (__location__ " transaction commit%s failed"
3039 ", retrying after 1 second...\n",
3040 (retries==0)?"":"retry "));
3044 failure_control = CTDB_CONTROL_TRANS2_ERROR;
3046 /* work out what error code we will give if we
3047 have to fail the operation */
3048 switch ((enum ctdb_trans2_commit_error)status) {
3049 case CTDB_TRANS2_COMMIT_SUCCESS:
3050 case CTDB_TRANS2_COMMIT_SOMEFAIL:
3051 case CTDB_TRANS2_COMMIT_TIMEOUT:
3052 failure_control = CTDB_CONTROL_TRANS2_ERROR;
3054 case CTDB_TRANS2_COMMIT_ALLFAIL:
3055 failure_control = CTDB_CONTROL_TRANS2_FINISHED;
3060 if (++retries == 100) {
3061 DEBUG(DEBUG_ERR,(__location__ " Giving up transaction on db 0x%08x after %d retries failure_control=%u\n",
3062 h->ctdb_db->db_id, retries, (unsigned)failure_control));
3063 ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
3064 failure_control, CTDB_CTRL_FLAG_NOREPLY,
3065 tdb_null, NULL, NULL, NULL, NULL, NULL);
3070 if (ctdb_replay_transaction(h) != 0) {
3071 DEBUG(DEBUG_ERR, (__location__ " Failed to replay "
3072 "transaction on db 0x%08x, "
3073 "failure control =%u\n",
3075 (unsigned)failure_control));
3076 ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
3077 failure_control, CTDB_CTRL_FLAG_NOREPLY,
3078 tdb_null, NULL, NULL, NULL, NULL, NULL);
3084 failure_control = CTDB_CONTROL_TRANS2_ERROR;
3087 /* do the real commit locally */
3088 ret = tdb_transaction_commit(h->ctdb_db->ltdb->tdb);
3090 DEBUG(DEBUG_ERR, (__location__ " Failed to commit transaction "
3091 "on db id 0x%08x locally, "
3092 "failure_control=%u\n",
3094 (unsigned)failure_control));
3095 ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
3096 failure_control, CTDB_CTRL_FLAG_NOREPLY,
3097 tdb_null, NULL, NULL, NULL, NULL, NULL);
3102 /* tell ctdbd that we are finished with our local commit */
3103 ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
3104 CTDB_CONTROL_TRANS2_FINISHED, CTDB_CTRL_FLAG_NOREPLY,
3105 tdb_null, NULL, NULL, NULL, NULL, NULL);
3111 recovery daemon ping to main daemon
3113 int ctdb_ctrl_recd_ping(struct ctdb_context *ctdb)
3118 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_RECD_PING, 0, tdb_null,
3119 ctdb, NULL, &res, NULL, NULL);
3120 if (ret != 0 || res != 0) {
3121 DEBUG(DEBUG_ERR,("Failed to send recd ping\n"));
3128 /* when forking the main daemon and the child process needs to connect back
3129 * to the daemon as a client process, this function can be used to change
3130 * the ctdb context from daemon into client mode
3132 int switch_from_server_to_client(struct ctdb_context *ctdb)
3136 /* shutdown the transport */
3137 if (ctdb->methods) {
3138 ctdb->methods->shutdown(ctdb);
3141 /* get a new event context */
3142 talloc_free(ctdb->ev);
3143 ctdb->ev = event_context_init(ctdb);
3145 close(ctdb->daemon.sd);
3146 ctdb->daemon.sd = -1;
3148 /* initialise ctdb */
3149 ret = ctdb_socket_connect(ctdb);
3151 DEBUG(DEBUG_ALERT, (__location__ " Failed to init ctdb client\n"));
3159 get the status of running the monitor eventscripts: NULL means never run.
3161 int ctdb_ctrl_getscriptstatus(struct ctdb_context *ctdb,
3162 struct timeval timeout, uint32_t destnode,
3163 TALLOC_CTX *mem_ctx, enum ctdb_eventscript_call type,
3164 struct ctdb_scripts_wire **script_status)
3167 TDB_DATA outdata, indata;
3169 uint32_t uinttype = type;
3171 indata.dptr = (uint8_t *)&uinttype;
3172 indata.dsize = sizeof(uinttype);
3174 ret = ctdb_control(ctdb, destnode, 0,
3175 CTDB_CONTROL_GET_EVENT_SCRIPT_STATUS, 0, indata,
3176 mem_ctx, &outdata, &res, &timeout, NULL);
3177 if (ret != 0 || res != 0) {
3178 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getscriptstatus failed ret:%d res:%d\n", ret, res));
3182 if (outdata.dsize == 0) {
3183 *script_status = NULL;
3185 *script_status = (struct ctdb_scripts_wire *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
3186 talloc_free(outdata.dptr);
3193 tell the main daemon how long it took to lock the reclock file
3195 int ctdb_ctrl_report_recd_lock_latency(struct ctdb_context *ctdb, struct timeval timeout, double latency)
3201 data.dptr = (uint8_t *)&latency;
3202 data.dsize = sizeof(latency);
3204 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_RECD_RECLOCK_LATENCY, 0, data,
3205 ctdb, NULL, &res, NULL, NULL);
3206 if (ret != 0 || res != 0) {
3207 DEBUG(DEBUG_ERR,("Failed to send recd reclock latency\n"));
3215 get the name of the reclock file
3217 int ctdb_ctrl_getreclock(struct ctdb_context *ctdb, struct timeval timeout,
3218 uint32_t destnode, TALLOC_CTX *mem_ctx,
3225 ret = ctdb_control(ctdb, destnode, 0,
3226 CTDB_CONTROL_GET_RECLOCK_FILE, 0, tdb_null,
3227 mem_ctx, &data, &res, &timeout, NULL);
3228 if (ret != 0 || res != 0) {
3232 if (data.dsize == 0) {
3235 *name = talloc_strdup(mem_ctx, discard_const(data.dptr));
3237 talloc_free(data.dptr);
3243 set the reclock filename for a node
3245 int ctdb_ctrl_setreclock(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, const char *reclock)
3251 if (reclock == NULL) {
3255 data.dsize = strlen(reclock) + 1;
3256 data.dptr = discard_const(reclock);
3259 ret = ctdb_control(ctdb, destnode, 0,
3260 CTDB_CONTROL_SET_RECLOCK_FILE, 0, data,
3261 NULL, NULL, &res, &timeout, NULL);
3262 if (ret != 0 || res != 0) {
3263 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setreclock failed\n"));
3273 int ctdb_ctrl_stop_node(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
3278 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_STOP_NODE, 0, tdb_null,
3279 ctdb, NULL, &res, &timeout, NULL);
3280 if (ret != 0 || res != 0) {
3281 DEBUG(DEBUG_ERR,("Failed to stop node\n"));
3291 int ctdb_ctrl_continue_node(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
3295 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_CONTINUE_NODE, 0, tdb_null,
3296 ctdb, NULL, NULL, &timeout, NULL);
3298 DEBUG(DEBUG_ERR,("Failed to continue node\n"));
3306 set the natgw state for a node
3308 int ctdb_ctrl_setnatgwstate(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t natgwstate)
3314 data.dsize = sizeof(natgwstate);
3315 data.dptr = (uint8_t *)&natgwstate;
3317 ret = ctdb_control(ctdb, destnode, 0,
3318 CTDB_CONTROL_SET_NATGWSTATE, 0, data,
3319 NULL, NULL, &res, &timeout, NULL);
3320 if (ret != 0 || res != 0) {
3321 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setnatgwstate failed\n"));
3329 set the lmaster role for a node
3331 int ctdb_ctrl_setlmasterrole(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t lmasterrole)
3337 data.dsize = sizeof(lmasterrole);
3338 data.dptr = (uint8_t *)&lmasterrole;
3340 ret = ctdb_control(ctdb, destnode, 0,
3341 CTDB_CONTROL_SET_LMASTERROLE, 0, data,
3342 NULL, NULL, &res, &timeout, NULL);
3343 if (ret != 0 || res != 0) {
3344 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setlmasterrole failed\n"));
3352 set the recmaster role for a node
3354 int ctdb_ctrl_setrecmasterrole(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmasterrole)
3360 data.dsize = sizeof(recmasterrole);
3361 data.dptr = (uint8_t *)&recmasterrole;
3363 ret = ctdb_control(ctdb, destnode, 0,
3364 CTDB_CONTROL_SET_RECMASTERROLE, 0, data,
3365 NULL, NULL, &res, &timeout, NULL);
3366 if (ret != 0 || res != 0) {
3367 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setrecmasterrole failed\n"));
3374 /* enable an eventscript
3376 int ctdb_ctrl_enablescript(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, const char *script)
3382 data.dsize = strlen(script) + 1;
3383 data.dptr = discard_const(script);
3385 ret = ctdb_control(ctdb, destnode, 0,
3386 CTDB_CONTROL_ENABLE_SCRIPT, 0, data,
3387 NULL, NULL, &res, &timeout, NULL);
3388 if (ret != 0 || res != 0) {
3389 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for enablescript failed\n"));
3396 /* disable an eventscript
3398 int ctdb_ctrl_disablescript(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, const char *script)
3404 data.dsize = strlen(script) + 1;
3405 data.dptr = discard_const(script);
3407 ret = ctdb_control(ctdb, destnode, 0,
3408 CTDB_CONTROL_DISABLE_SCRIPT, 0, data,
3409 NULL, NULL, &res, &timeout, NULL);
3410 if (ret != 0 || res != 0) {
3411 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for disablescript failed\n"));
3419 int ctdb_ctrl_set_ban(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, struct ctdb_ban_time *bantime)
3425 data.dsize = sizeof(*bantime);
3426 data.dptr = (uint8_t *)bantime;
3428 ret = ctdb_control(ctdb, destnode, 0,
3429 CTDB_CONTROL_SET_BAN_STATE, 0, data,
3430 NULL, NULL, &res, &timeout, NULL);
3431 if (ret != 0 || res != 0) {
3432 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set ban state failed\n"));
3440 int ctdb_ctrl_get_ban(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_ban_time **bantime)
3445 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
3447 ret = ctdb_control(ctdb, destnode, 0,
3448 CTDB_CONTROL_GET_BAN_STATE, 0, tdb_null,
3449 tmp_ctx, &outdata, &res, &timeout, NULL);
3450 if (ret != 0 || res != 0) {
3451 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set ban state failed\n"));
3452 talloc_free(tmp_ctx);
3456 *bantime = (struct ctdb_ban_time *)talloc_steal(mem_ctx, outdata.dptr);
3457 talloc_free(tmp_ctx);
3463 int ctdb_ctrl_set_db_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, struct ctdb_db_priority *db_prio)
3468 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
3470 data.dptr = (uint8_t*)db_prio;
3471 data.dsize = sizeof(*db_prio);
3473 ret = ctdb_control(ctdb, destnode, 0,
3474 CTDB_CONTROL_SET_DB_PRIORITY, 0, data,
3475 tmp_ctx, NULL, &res, &timeout, NULL);
3476 if (ret != 0 || res != 0) {
3477 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set_db_priority failed\n"));
3478 talloc_free(tmp_ctx);
3482 talloc_free(tmp_ctx);
3487 int ctdb_ctrl_get_db_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t db_id, uint32_t *priority)
3492 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
3494 data.dptr = (uint8_t*)&db_id;
3495 data.dsize = sizeof(db_id);
3497 ret = ctdb_control(ctdb, destnode, 0,
3498 CTDB_CONTROL_GET_DB_PRIORITY, 0, data,
3499 tmp_ctx, NULL, &res, &timeout, NULL);
3500 if (ret != 0 || res < 0) {
3501 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set_db_priority failed\n"));
3502 talloc_free(tmp_ctx);
3510 talloc_free(tmp_ctx);