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);
2225 void ctdb_set_flags(struct ctdb_context *ctdb, unsigned flags)
2227 ctdb->flags |= flags;
2232 return the pnn of this node
2234 uint32_t ctdb_get_pnn(struct ctdb_context *ctdb)
2241 get the uptime of a remote node
2243 struct ctdb_client_control_state *
2244 ctdb_ctrl_uptime_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode)
2246 return ctdb_control_send(ctdb, destnode, 0,
2247 CTDB_CONTROL_UPTIME, 0, tdb_null,
2248 mem_ctx, &timeout, NULL);
2251 int ctdb_ctrl_uptime_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, struct ctdb_uptime **uptime)
2257 ret = ctdb_control_recv(ctdb, state, mem_ctx, &outdata, &res, NULL);
2258 if (ret != 0 || res != 0) {
2259 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_uptime_recv failed\n"));
2263 *uptime = (struct ctdb_uptime *)talloc_steal(mem_ctx, outdata.dptr);
2268 int ctdb_ctrl_uptime(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, struct ctdb_uptime **uptime)
2270 struct ctdb_client_control_state *state;
2272 state = ctdb_ctrl_uptime_send(ctdb, mem_ctx, timeout, destnode);
2273 return ctdb_ctrl_uptime_recv(ctdb, mem_ctx, state, uptime);
2277 send a control to execute the "recovered" event script on a node
2279 int ctdb_ctrl_end_recovery(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2284 ret = ctdb_control(ctdb, destnode, 0,
2285 CTDB_CONTROL_END_RECOVERY, 0, tdb_null,
2286 NULL, NULL, &status, &timeout, NULL);
2287 if (ret != 0 || status != 0) {
2288 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for end_recovery failed\n"));
2296 callback for the async helpers used when sending the same control
2297 to multiple nodes in parallell.
2299 static void async_callback(struct ctdb_client_control_state *state)
2301 struct client_async_data *data = talloc_get_type(state->async.private_data, struct client_async_data);
2302 struct ctdb_context *ctdb = talloc_get_type(state->ctdb, struct ctdb_context);
2306 uint32_t destnode = state->c->hdr.destnode;
2308 /* one more node has responded with recmode data */
2311 /* if we failed to push the db, then return an error and let
2312 the main loop try again.
2314 if (state->state != CTDB_CONTROL_DONE) {
2315 if ( !data->dont_log_errors) {
2316 DEBUG(DEBUG_ERR,("Async operation failed with state %d, opcode:%u\n", state->state, data->opcode));
2319 if (data->fail_callback) {
2320 data->fail_callback(ctdb, destnode, res, outdata,
2321 data->callback_data);
2326 state->async.fn = NULL;
2328 ret = ctdb_control_recv(ctdb, state, data, &outdata, &res, NULL);
2329 if ((ret != 0) || (res != 0)) {
2330 if ( !data->dont_log_errors) {
2331 DEBUG(DEBUG_ERR,("Async operation failed with ret=%d res=%d opcode=%u\n", ret, (int)res, data->opcode));
2334 if (data->fail_callback) {
2335 data->fail_callback(ctdb, destnode, res, outdata,
2336 data->callback_data);
2339 if ((ret == 0) && (data->callback != NULL)) {
2340 data->callback(ctdb, destnode, res, outdata,
2341 data->callback_data);
2346 void ctdb_client_async_add(struct client_async_data *data, struct ctdb_client_control_state *state)
2348 /* set up the callback functions */
2349 state->async.fn = async_callback;
2350 state->async.private_data = data;
2352 /* one more control to wait for to complete */
2357 /* wait for up to the maximum number of seconds allowed
2358 or until all nodes we expect a response from has replied
2360 int ctdb_client_async_wait(struct ctdb_context *ctdb, struct client_async_data *data)
2362 while (data->count > 0) {
2363 event_loop_once(ctdb->ev);
2365 if (data->fail_count != 0) {
2366 if (!data->dont_log_errors) {
2367 DEBUG(DEBUG_ERR,("Async wait failed - fail_count=%u\n",
2377 perform a simple control on the listed nodes
2378 The control cannot return data
2380 int ctdb_client_async_control(struct ctdb_context *ctdb,
2381 enum ctdb_controls opcode,
2384 struct timeval timeout,
2385 bool dont_log_errors,
2387 client_async_callback client_callback,
2388 client_async_callback fail_callback,
2389 void *callback_data)
2391 struct client_async_data *async_data;
2392 struct ctdb_client_control_state *state;
2395 async_data = talloc_zero(ctdb, struct client_async_data);
2396 CTDB_NO_MEMORY_FATAL(ctdb, async_data);
2397 async_data->dont_log_errors = dont_log_errors;
2398 async_data->callback = client_callback;
2399 async_data->fail_callback = fail_callback;
2400 async_data->callback_data = callback_data;
2401 async_data->opcode = opcode;
2403 num_nodes = talloc_get_size(nodes) / sizeof(uint32_t);
2405 /* loop over all nodes and send an async control to each of them */
2406 for (j=0; j<num_nodes; j++) {
2407 uint32_t pnn = nodes[j];
2409 state = ctdb_control_send(ctdb, pnn, srvid, opcode,
2410 0, data, async_data, &timeout, NULL);
2411 if (state == NULL) {
2412 DEBUG(DEBUG_ERR,(__location__ " Failed to call async control %u\n", (unsigned)opcode));
2413 talloc_free(async_data);
2417 ctdb_client_async_add(async_data, state);
2420 if (ctdb_client_async_wait(ctdb, async_data) != 0) {
2421 talloc_free(async_data);
2425 talloc_free(async_data);
2429 uint32_t *list_of_vnnmap_nodes(struct ctdb_context *ctdb,
2430 struct ctdb_vnn_map *vnn_map,
2431 TALLOC_CTX *mem_ctx,
2434 int i, j, num_nodes;
2437 for (i=num_nodes=0;i<vnn_map->size;i++) {
2438 if (vnn_map->map[i] == ctdb->pnn && !include_self) {
2444 nodes = talloc_array(mem_ctx, uint32_t, num_nodes);
2445 CTDB_NO_MEMORY_FATAL(ctdb, nodes);
2447 for (i=j=0;i<vnn_map->size;i++) {
2448 if (vnn_map->map[i] == ctdb->pnn && !include_self) {
2451 nodes[j++] = vnn_map->map[i];
2457 uint32_t *list_of_active_nodes(struct ctdb_context *ctdb,
2458 struct ctdb_node_map *node_map,
2459 TALLOC_CTX *mem_ctx,
2462 int i, j, num_nodes;
2465 for (i=num_nodes=0;i<node_map->num;i++) {
2466 if (node_map->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2469 if (node_map->nodes[i].pnn == 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<node_map->num;i++) {
2479 if (node_map->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2482 if (node_map->nodes[i].pnn == ctdb->pnn && !include_self) {
2485 nodes[j++] = node_map->nodes[i].pnn;
2491 uint32_t *list_of_active_nodes_except_pnn(struct ctdb_context *ctdb,
2492 struct ctdb_node_map *node_map,
2493 TALLOC_CTX *mem_ctx,
2496 int i, j, num_nodes;
2499 for (i=num_nodes=0;i<node_map->num;i++) {
2500 if (node_map->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2503 if (node_map->nodes[i].pnn == pnn) {
2509 nodes = talloc_array(mem_ctx, uint32_t, num_nodes);
2510 CTDB_NO_MEMORY_FATAL(ctdb, nodes);
2512 for (i=j=0;i<node_map->num;i++) {
2513 if (node_map->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2516 if (node_map->nodes[i].pnn == pnn) {
2519 nodes[j++] = node_map->nodes[i].pnn;
2525 uint32_t *list_of_connected_nodes(struct ctdb_context *ctdb,
2526 struct ctdb_node_map *node_map,
2527 TALLOC_CTX *mem_ctx,
2530 int i, j, num_nodes;
2533 for (i=num_nodes=0;i<node_map->num;i++) {
2534 if (node_map->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
2537 if (node_map->nodes[i].pnn == ctdb->pnn && !include_self) {
2543 nodes = talloc_array(mem_ctx, uint32_t, num_nodes);
2544 CTDB_NO_MEMORY_FATAL(ctdb, nodes);
2546 for (i=j=0;i<node_map->num;i++) {
2547 if (node_map->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
2550 if (node_map->nodes[i].pnn == ctdb->pnn && !include_self) {
2553 nodes[j++] = node_map->nodes[i].pnn;
2560 this is used to test if a pnn lock exists and if it exists will return
2561 the number of connections that pnn has reported or -1 if that recovery
2562 daemon is not running.
2565 ctdb_read_pnn_lock(int fd, int32_t pnn)
2570 lock.l_type = F_WRLCK;
2571 lock.l_whence = SEEK_SET;
2576 if (fcntl(fd, F_GETLK, &lock) != 0) {
2577 DEBUG(DEBUG_ERR, (__location__ " F_GETLK failed with %s\n", strerror(errno)));
2581 if (lock.l_type == F_UNLCK) {
2585 if (pread(fd, &c, 1, pnn) == -1) {
2586 DEBUG(DEBUG_CRIT,(__location__ " failed read pnn count - %s\n", strerror(errno)));
2594 get capabilities of a remote node
2596 struct ctdb_client_control_state *
2597 ctdb_ctrl_getcapabilities_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode)
2599 return ctdb_control_send(ctdb, destnode, 0,
2600 CTDB_CONTROL_GET_CAPABILITIES, 0, tdb_null,
2601 mem_ctx, &timeout, NULL);
2604 int ctdb_ctrl_getcapabilities_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *capabilities)
2610 ret = ctdb_control_recv(ctdb, state, mem_ctx, &outdata, &res, NULL);
2611 if ( (ret != 0) || (res != 0) ) {
2612 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_getcapabilities_recv failed\n"));
2617 *capabilities = *((uint32_t *)outdata.dptr);
2623 int ctdb_ctrl_getcapabilities(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *capabilities)
2625 struct ctdb_client_control_state *state;
2626 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
2629 state = ctdb_ctrl_getcapabilities_send(ctdb, tmp_ctx, timeout, destnode);
2630 ret = ctdb_ctrl_getcapabilities_recv(ctdb, tmp_ctx, state, capabilities);
2631 talloc_free(tmp_ctx);
2636 * check whether a transaction is active on a given db on a given node
2638 int32_t ctdb_ctrl_transaction_active(struct ctdb_context *ctdb,
2646 indata.dptr = (uint8_t *)&db_id;
2647 indata.dsize = sizeof(db_id);
2649 ret = ctdb_control(ctdb, destnode, 0,
2650 CTDB_CONTROL_TRANS2_ACTIVE,
2651 0, indata, NULL, NULL, &status,
2655 DEBUG(DEBUG_ERR, (__location__ " ctdb control for transaction_active failed\n"));
2663 struct ctdb_transaction_handle {
2664 struct ctdb_db_context *ctdb_db;
2667 * we store the reads and writes done under a transaction:
2668 * - one list stores both reads and writes (m_all),
2669 * - the other just writes (m_write)
2671 struct ctdb_marshall_buffer *m_all;
2672 struct ctdb_marshall_buffer *m_write;
2675 /* start a transaction on a database */
2676 static int ctdb_transaction_destructor(struct ctdb_transaction_handle *h)
2678 tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
2682 /* start a transaction on a database */
2683 static int ctdb_transaction_fetch_start(struct ctdb_transaction_handle *h)
2685 struct ctdb_record_handle *rh;
2688 struct ctdb_ltdb_header header;
2689 TALLOC_CTX *tmp_ctx;
2690 const char *keyname = CTDB_TRANSACTION_LOCK_KEY;
2692 struct ctdb_db_context *ctdb_db = h->ctdb_db;
2696 key.dptr = discard_const(keyname);
2697 key.dsize = strlen(keyname);
2699 if (!ctdb_db->persistent) {
2700 DEBUG(DEBUG_ERR,(__location__ " Attempted transaction on non-persistent database\n"));
2705 tmp_ctx = talloc_new(h);
2707 rh = ctdb_fetch_lock(ctdb_db, tmp_ctx, key, NULL);
2709 DEBUG(DEBUG_ERR,(__location__ " Failed to fetch_lock database\n"));
2710 talloc_free(tmp_ctx);
2714 status = ctdb_ctrl_transaction_active(ctdb_db->ctdb,
2718 unsigned long int usec = (1000 + random()) % 100000;
2719 DEBUG(DEBUG_DEBUG, (__location__ " transaction is active "
2720 "on db_id[0x%08x]. waiting for %lu "
2722 ctdb_db->db_id, usec));
2723 talloc_free(tmp_ctx);
2729 * store the pid in the database:
2730 * it is not enough that the node is dmaster...
2733 data.dptr = (unsigned char *)&pid;
2734 data.dsize = sizeof(pid_t);
2736 rh->header.dmaster = ctdb_db->ctdb->pnn;
2737 ret = ctdb_ltdb_store(ctdb_db, key, &(rh->header), data);
2739 DEBUG(DEBUG_ERR, (__location__ " Failed to store pid in "
2740 "transaction record\n"));
2741 talloc_free(tmp_ctx);
2747 ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
2749 DEBUG(DEBUG_ERR,(__location__ " Failed to start tdb transaction\n"));
2750 talloc_free(tmp_ctx);
2754 ret = ctdb_ltdb_fetch(ctdb_db, key, &header, tmp_ctx, &data);
2756 DEBUG(DEBUG_ERR,(__location__ " Failed to re-fetch transaction "
2757 "lock record inside transaction\n"));
2758 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
2759 talloc_free(tmp_ctx);
2763 if (header.dmaster != ctdb_db->ctdb->pnn) {
2764 DEBUG(DEBUG_DEBUG,(__location__ " not dmaster any more on "
2765 "transaction lock record\n"));
2766 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
2767 talloc_free(tmp_ctx);
2771 if ((data.dsize != sizeof(pid_t)) || (*(pid_t *)(data.dptr) != pid)) {
2772 DEBUG(DEBUG_DEBUG, (__location__ " my pid is not stored in "
2773 "the transaction lock record\n"));
2774 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
2775 talloc_free(tmp_ctx);
2779 talloc_free(tmp_ctx);
2785 /* start a transaction on a database */
2786 struct ctdb_transaction_handle *ctdb_transaction_start(struct ctdb_db_context *ctdb_db,
2787 TALLOC_CTX *mem_ctx)
2789 struct ctdb_transaction_handle *h;
2792 h = talloc_zero(mem_ctx, struct ctdb_transaction_handle);
2794 DEBUG(DEBUG_ERR,(__location__ " oom for transaction handle\n"));
2798 h->ctdb_db = ctdb_db;
2800 ret = ctdb_transaction_fetch_start(h);
2806 talloc_set_destructor(h, ctdb_transaction_destructor);
2814 fetch a record inside a transaction
2816 int ctdb_transaction_fetch(struct ctdb_transaction_handle *h,
2817 TALLOC_CTX *mem_ctx,
2818 TDB_DATA key, TDB_DATA *data)
2820 struct ctdb_ltdb_header header;
2823 ZERO_STRUCT(header);
2825 ret = ctdb_ltdb_fetch(h->ctdb_db, key, &header, mem_ctx, data);
2826 if (ret == -1 && header.dmaster == (uint32_t)-1) {
2827 /* record doesn't exist yet */
2836 if (!h->in_replay) {
2837 h->m_all = ctdb_marshall_add(h, h->m_all, h->ctdb_db->db_id, 1, key, NULL, *data);
2838 if (h->m_all == NULL) {
2839 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
2848 stores a record inside a transaction
2850 int ctdb_transaction_store(struct ctdb_transaction_handle *h,
2851 TDB_DATA key, TDB_DATA data)
2853 TALLOC_CTX *tmp_ctx = talloc_new(h);
2854 struct ctdb_ltdb_header header;
2858 ZERO_STRUCT(header);
2860 /* we need the header so we can update the RSN */
2861 ret = ctdb_ltdb_fetch(h->ctdb_db, key, &header, tmp_ctx, &olddata);
2862 if (ret == -1 && header.dmaster == (uint32_t)-1) {
2863 /* the record doesn't exist - create one with us as dmaster.
2864 This is only safe because we are in a transaction and this
2865 is a persistent database */
2866 ZERO_STRUCT(header);
2867 } else if (ret != 0) {
2868 DEBUG(DEBUG_ERR,(__location__ " Failed to fetch record\n"));
2869 talloc_free(tmp_ctx);
2873 if (data.dsize == olddata.dsize &&
2874 memcmp(data.dptr, olddata.dptr, data.dsize) == 0) {
2875 /* save writing the same data */
2876 talloc_free(tmp_ctx);
2880 header.dmaster = h->ctdb_db->ctdb->pnn;
2883 if (!h->in_replay) {
2884 h->m_all = ctdb_marshall_add(h, h->m_all, h->ctdb_db->db_id, 0, key, NULL, data);
2885 if (h->m_all == NULL) {
2886 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
2887 talloc_free(tmp_ctx);
2892 h->m_write = ctdb_marshall_add(h, h->m_write, h->ctdb_db->db_id, 0, key, &header, data);
2893 if (h->m_write == NULL) {
2894 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
2895 talloc_free(tmp_ctx);
2899 ret = ctdb_ltdb_store(h->ctdb_db, key, &header, data);
2901 talloc_free(tmp_ctx);
2907 replay a transaction
2909 static int ctdb_replay_transaction(struct ctdb_transaction_handle *h)
2912 struct ctdb_rec_data *rec = NULL;
2914 h->in_replay = true;
2915 talloc_free(h->m_write);
2918 ret = ctdb_transaction_fetch_start(h);
2923 for (i=0;i<h->m_all->count;i++) {
2926 rec = ctdb_marshall_loop_next(h->m_all, rec, NULL, NULL, &key, &data);
2928 DEBUG(DEBUG_ERR, (__location__ " Out of records in ctdb_replay_transaction?\n"));
2932 if (rec->reqid == 0) {
2934 if (ctdb_transaction_store(h, key, data) != 0) {
2939 TALLOC_CTX *tmp_ctx = talloc_new(h);
2941 if (ctdb_transaction_fetch(h, tmp_ctx, key, &data2) != 0) {
2942 talloc_free(tmp_ctx);
2945 if (data2.dsize != data.dsize ||
2946 memcmp(data2.dptr, data.dptr, data.dsize) != 0) {
2947 /* the record has changed on us - we have to give up */
2948 talloc_free(tmp_ctx);
2951 talloc_free(tmp_ctx);
2958 tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
2964 commit a transaction
2966 int ctdb_transaction_commit(struct ctdb_transaction_handle *h)
2970 struct ctdb_context *ctdb = h->ctdb_db->ctdb;
2971 struct timeval timeout;
2972 enum ctdb_controls failure_control = CTDB_CONTROL_TRANS2_ERROR;
2974 talloc_set_destructor(h, NULL);
2976 /* our commit strategy is quite complex.
2978 - we first try to commit the changes to all other nodes
2980 - if that works, then we commit locally and we are done
2982 - if a commit on another node fails, then we need to cancel
2983 the transaction, then restart the transaction (thus
2984 opening a window of time for a pending recovery to
2985 complete), then replay the transaction, checking all the
2986 reads and writes (checking that reads give the same data,
2987 and writes succeed). Then we retry the transaction to the
2992 if (h->m_write == NULL) {
2993 /* no changes were made */
2994 tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
2999 /* tell ctdbd to commit to the other nodes */
3000 timeout = timeval_current_ofs(1, 0);
3001 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
3002 retries==0?CTDB_CONTROL_TRANS2_COMMIT:CTDB_CONTROL_TRANS2_COMMIT_RETRY, 0,
3003 ctdb_marshall_finish(h->m_write), NULL, NULL, &status,
3005 if (ret != 0 || status != 0) {
3006 tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
3007 DEBUG(DEBUG_NOTICE, (__location__ " transaction commit%s failed"
3008 ", retrying after 1 second...\n",
3009 (retries==0)?"":"retry "));
3013 failure_control = CTDB_CONTROL_TRANS2_ERROR;
3015 /* work out what error code we will give if we
3016 have to fail the operation */
3017 switch ((enum ctdb_trans2_commit_error)status) {
3018 case CTDB_TRANS2_COMMIT_SUCCESS:
3019 case CTDB_TRANS2_COMMIT_SOMEFAIL:
3020 case CTDB_TRANS2_COMMIT_TIMEOUT:
3021 failure_control = CTDB_CONTROL_TRANS2_ERROR;
3023 case CTDB_TRANS2_COMMIT_ALLFAIL:
3024 failure_control = CTDB_CONTROL_TRANS2_FINISHED;
3029 if (++retries == 100) {
3030 DEBUG(DEBUG_ERR,(__location__ " Giving up transaction on db 0x%08x after %d retries failure_control=%u\n",
3031 h->ctdb_db->db_id, retries, (unsigned)failure_control));
3032 ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
3033 failure_control, CTDB_CTRL_FLAG_NOREPLY,
3034 tdb_null, NULL, NULL, NULL, NULL, NULL);
3039 if (ctdb_replay_transaction(h) != 0) {
3040 DEBUG(DEBUG_ERR, (__location__ " Failed to replay "
3041 "transaction on db 0x%08x, "
3042 "failure control =%u\n",
3044 (unsigned)failure_control));
3045 ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
3046 failure_control, CTDB_CTRL_FLAG_NOREPLY,
3047 tdb_null, NULL, NULL, NULL, NULL, NULL);
3053 failure_control = CTDB_CONTROL_TRANS2_ERROR;
3056 /* do the real commit locally */
3057 ret = tdb_transaction_commit(h->ctdb_db->ltdb->tdb);
3059 DEBUG(DEBUG_ERR, (__location__ " Failed to commit transaction "
3060 "on db id 0x%08x locally, "
3061 "failure_control=%u\n",
3063 (unsigned)failure_control));
3064 ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
3065 failure_control, CTDB_CTRL_FLAG_NOREPLY,
3066 tdb_null, NULL, NULL, NULL, NULL, NULL);
3071 /* tell ctdbd that we are finished with our local commit */
3072 ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
3073 CTDB_CONTROL_TRANS2_FINISHED, CTDB_CTRL_FLAG_NOREPLY,
3074 tdb_null, NULL, NULL, NULL, NULL, NULL);
3080 recovery daemon ping to main daemon
3082 int ctdb_ctrl_recd_ping(struct ctdb_context *ctdb)
3087 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_RECD_PING, 0, tdb_null,
3088 ctdb, NULL, &res, NULL, NULL);
3089 if (ret != 0 || res != 0) {
3090 DEBUG(DEBUG_ERR,("Failed to send recd ping\n"));
3097 /* when forking the main daemon and the child process needs to connect back
3098 * to the daemon as a client process, this function can be used to change
3099 * the ctdb context from daemon into client mode
3101 int switch_from_server_to_client(struct ctdb_context *ctdb)
3105 /* shutdown the transport */
3106 if (ctdb->methods) {
3107 ctdb->methods->shutdown(ctdb);
3110 /* get a new event context */
3111 talloc_free(ctdb->ev);
3112 ctdb->ev = event_context_init(ctdb);
3114 close(ctdb->daemon.sd);
3115 ctdb->daemon.sd = -1;
3117 /* initialise ctdb */
3118 ret = ctdb_socket_connect(ctdb);
3120 DEBUG(DEBUG_ALERT, (__location__ " Failed to init ctdb client\n"));
3128 get the status of running the monitor eventscripts: NULL means never run.
3130 int ctdb_ctrl_getscriptstatus(struct ctdb_context *ctdb,
3131 struct timeval timeout, uint32_t destnode,
3132 TALLOC_CTX *mem_ctx, enum ctdb_eventscript_call type,
3133 struct ctdb_scripts_wire **script_status)
3136 TDB_DATA outdata, indata;
3138 uint32_t uinttype = type;
3140 indata.dptr = (uint8_t *)&uinttype;
3141 indata.dsize = sizeof(uinttype);
3143 ret = ctdb_control(ctdb, destnode, 0,
3144 CTDB_CONTROL_GET_EVENT_SCRIPT_STATUS, 0, indata,
3145 mem_ctx, &outdata, &res, &timeout, NULL);
3146 if (ret != 0 || res != 0) {
3147 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getscriptstatus failed ret:%d res:%d\n", ret, res));
3151 if (outdata.dsize == 0) {
3152 *script_status = NULL;
3154 *script_status = (struct ctdb_scripts_wire *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
3155 talloc_free(outdata.dptr);
3162 tell the main daemon how long it took to lock the reclock file
3164 int ctdb_ctrl_report_recd_lock_latency(struct ctdb_context *ctdb, struct timeval timeout, double latency)
3170 data.dptr = (uint8_t *)&latency;
3171 data.dsize = sizeof(latency);
3173 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_RECD_RECLOCK_LATENCY, 0, data,
3174 ctdb, NULL, &res, NULL, NULL);
3175 if (ret != 0 || res != 0) {
3176 DEBUG(DEBUG_ERR,("Failed to send recd reclock latency\n"));
3184 get the name of the reclock file
3186 int ctdb_ctrl_getreclock(struct ctdb_context *ctdb, struct timeval timeout,
3187 uint32_t destnode, TALLOC_CTX *mem_ctx,
3194 ret = ctdb_control(ctdb, destnode, 0,
3195 CTDB_CONTROL_GET_RECLOCK_FILE, 0, tdb_null,
3196 mem_ctx, &data, &res, &timeout, NULL);
3197 if (ret != 0 || res != 0) {
3201 if (data.dsize == 0) {
3204 *name = talloc_strdup(mem_ctx, discard_const(data.dptr));
3206 talloc_free(data.dptr);
3212 set the reclock filename for a node
3214 int ctdb_ctrl_setreclock(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, const char *reclock)
3220 if (reclock == NULL) {
3224 data.dsize = strlen(reclock) + 1;
3225 data.dptr = discard_const(reclock);
3228 ret = ctdb_control(ctdb, destnode, 0,
3229 CTDB_CONTROL_SET_RECLOCK_FILE, 0, data,
3230 NULL, NULL, &res, &timeout, NULL);
3231 if (ret != 0 || res != 0) {
3232 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setreclock failed\n"));
3242 int ctdb_ctrl_stop_node(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
3247 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_STOP_NODE, 0, tdb_null,
3248 ctdb, NULL, &res, &timeout, NULL);
3249 if (ret != 0 || res != 0) {
3250 DEBUG(DEBUG_ERR,("Failed to stop node\n"));
3260 int ctdb_ctrl_continue_node(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
3264 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_CONTINUE_NODE, 0, tdb_null,
3265 ctdb, NULL, NULL, &timeout, NULL);
3267 DEBUG(DEBUG_ERR,("Failed to continue node\n"));
3275 set the natgw state for a node
3277 int ctdb_ctrl_setnatgwstate(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t natgwstate)
3283 data.dsize = sizeof(natgwstate);
3284 data.dptr = (uint8_t *)&natgwstate;
3286 ret = ctdb_control(ctdb, destnode, 0,
3287 CTDB_CONTROL_SET_NATGWSTATE, 0, data,
3288 NULL, NULL, &res, &timeout, NULL);
3289 if (ret != 0 || res != 0) {
3290 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setnatgwstate failed\n"));
3298 set the lmaster role for a node
3300 int ctdb_ctrl_setlmasterrole(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t lmasterrole)
3306 data.dsize = sizeof(lmasterrole);
3307 data.dptr = (uint8_t *)&lmasterrole;
3309 ret = ctdb_control(ctdb, destnode, 0,
3310 CTDB_CONTROL_SET_LMASTERROLE, 0, data,
3311 NULL, NULL, &res, &timeout, NULL);
3312 if (ret != 0 || res != 0) {
3313 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setlmasterrole failed\n"));
3321 set the recmaster role for a node
3323 int ctdb_ctrl_setrecmasterrole(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmasterrole)
3329 data.dsize = sizeof(recmasterrole);
3330 data.dptr = (uint8_t *)&recmasterrole;
3332 ret = ctdb_control(ctdb, destnode, 0,
3333 CTDB_CONTROL_SET_RECMASTERROLE, 0, data,
3334 NULL, NULL, &res, &timeout, NULL);
3335 if (ret != 0 || res != 0) {
3336 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setrecmasterrole failed\n"));
3343 /* enable an eventscript
3345 int ctdb_ctrl_enablescript(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, const char *script)
3351 data.dsize = strlen(script) + 1;
3352 data.dptr = discard_const(script);
3354 ret = ctdb_control(ctdb, destnode, 0,
3355 CTDB_CONTROL_ENABLE_SCRIPT, 0, data,
3356 NULL, NULL, &res, &timeout, NULL);
3357 if (ret != 0 || res != 0) {
3358 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for enablescript failed\n"));
3365 /* disable an eventscript
3367 int ctdb_ctrl_disablescript(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, const char *script)
3373 data.dsize = strlen(script) + 1;
3374 data.dptr = discard_const(script);
3376 ret = ctdb_control(ctdb, destnode, 0,
3377 CTDB_CONTROL_DISABLE_SCRIPT, 0, data,
3378 NULL, NULL, &res, &timeout, NULL);
3379 if (ret != 0 || res != 0) {
3380 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for disablescript failed\n"));
3388 int ctdb_ctrl_set_ban(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, struct ctdb_ban_time *bantime)
3394 data.dsize = sizeof(*bantime);
3395 data.dptr = (uint8_t *)bantime;
3397 ret = ctdb_control(ctdb, destnode, 0,
3398 CTDB_CONTROL_SET_BAN_STATE, 0, data,
3399 NULL, NULL, &res, &timeout, NULL);
3400 if (ret != 0 || res != 0) {
3401 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set ban state failed\n"));
3409 int ctdb_ctrl_get_ban(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_ban_time **bantime)
3414 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
3416 ret = ctdb_control(ctdb, destnode, 0,
3417 CTDB_CONTROL_GET_BAN_STATE, 0, tdb_null,
3418 tmp_ctx, &outdata, &res, &timeout, NULL);
3419 if (ret != 0 || res != 0) {
3420 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set ban state failed\n"));
3421 talloc_free(tmp_ctx);
3425 *bantime = (struct ctdb_ban_time *)talloc_steal(mem_ctx, outdata.dptr);
3426 talloc_free(tmp_ctx);
3432 int ctdb_ctrl_set_db_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, struct ctdb_db_priority *db_prio)
3437 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
3439 data.dptr = (uint8_t*)db_prio;
3440 data.dsize = sizeof(*db_prio);
3442 ret = ctdb_control(ctdb, destnode, 0,
3443 CTDB_CONTROL_SET_DB_PRIORITY, 0, data,
3444 tmp_ctx, NULL, &res, &timeout, NULL);
3445 if (ret != 0 || res != 0) {
3446 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set_db_priority failed\n"));
3447 talloc_free(tmp_ctx);
3451 talloc_free(tmp_ctx);
3456 int ctdb_ctrl_get_db_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t db_id, uint32_t *priority)
3461 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
3463 data.dptr = (uint8_t*)&db_id;
3464 data.dsize = sizeof(db_id);
3466 ret = ctdb_control(ctdb, destnode, 0,
3467 CTDB_CONTROL_GET_DB_PRIORITY, 0, data,
3468 tmp_ctx, NULL, &res, &timeout, NULL);
3469 if (ret != 0 || res < 0) {
3470 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set_db_priority failed\n"));
3471 talloc_free(tmp_ctx);
3479 talloc_free(tmp_ctx);