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 if (state != NULL && timeout && !timeval_is_zero(timeout)) {
259 event_add_timed(ctdb->ev, state, *timeout, ctdb_control_timeout_func, state);
262 return ctdb_control_recv(ctdb, state, mem_ctx, outdata, status,
270 a process exists call. Returns 0 if process exists, -1 otherwise
272 int ctdb_ctrl_process_exists(struct ctdb_context *ctdb, uint32_t destnode, pid_t pid)
278 data.dptr = (uint8_t*)&pid;
279 data.dsize = sizeof(pid);
281 ret = ctdb_control(ctdb, destnode, 0,
282 CTDB_CONTROL_PROCESS_EXISTS, 0, data,
283 NULL, NULL, &status, NULL, NULL);
285 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for process_exists failed\n"));
293 get remote statistics
295 int ctdb_ctrl_statistics(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_statistics *status)
301 ret = ctdb_control(ctdb, destnode, 0,
302 CTDB_CONTROL_STATISTICS, 0, tdb_null,
303 ctdb, &data, &res, NULL, NULL);
304 if (ret != 0 || res != 0) {
305 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for statistics failed\n"));
309 if (data.dsize != sizeof(struct ctdb_statistics)) {
310 DEBUG(DEBUG_ERR,(__location__ " Wrong statistics size %u - expected %u\n",
311 (unsigned)data.dsize, (unsigned)sizeof(struct ctdb_statistics)));
315 *status = *(struct ctdb_statistics *)data.dptr;
316 talloc_free(data.dptr);
322 shutdown a remote ctdb node
324 int ctdb_ctrl_shutdown(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
326 struct ctdb_client_control_state *state;
328 state = ctdb_control_send(ctdb, destnode, 0,
329 CTDB_CONTROL_SHUTDOWN, 0, tdb_null,
332 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for shutdown failed\n"));
335 if (!timeval_is_zero(&timeout)) {
336 event_add_timed(ctdb->ev, state, timeout, ctdb_control_timeout_func, state);
343 get vnn map from a remote node
345 int ctdb_ctrl_getvnnmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_vnn_map **vnnmap)
350 struct ctdb_vnn_map_wire *map;
352 ret = ctdb_control(ctdb, destnode, 0,
353 CTDB_CONTROL_GETVNNMAP, 0, tdb_null,
354 mem_ctx, &outdata, &res, &timeout, NULL);
355 if (ret != 0 || res != 0) {
356 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getvnnmap failed\n"));
360 map = (struct ctdb_vnn_map_wire *)outdata.dptr;
361 if (outdata.dsize < offsetof(struct ctdb_vnn_map_wire, map) ||
362 outdata.dsize != map->size*sizeof(uint32_t) + offsetof(struct ctdb_vnn_map_wire, map)) {
363 DEBUG(DEBUG_ERR,("Bad vnn map size received in ctdb_ctrl_getvnnmap\n"));
367 (*vnnmap) = talloc(mem_ctx, struct ctdb_vnn_map);
368 CTDB_NO_MEMORY(ctdb, *vnnmap);
369 (*vnnmap)->generation = map->generation;
370 (*vnnmap)->size = map->size;
371 (*vnnmap)->map = talloc_array(*vnnmap, uint32_t, map->size);
373 CTDB_NO_MEMORY(ctdb, (*vnnmap)->map);
374 memcpy((*vnnmap)->map, map->map, sizeof(uint32_t)*map->size);
375 talloc_free(outdata.dptr);
382 get the recovery mode of a remote node
384 struct ctdb_client_control_state *
385 ctdb_ctrl_getrecmode_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode)
387 struct ctdb_client_control_state *state;
389 state = ctdb_control_send(ctdb, destnode, 0,
390 CTDB_CONTROL_GET_RECMODE, 0, tdb_null,
393 if (state != NULL && !timeval_is_zero(&timeout)) {
394 event_add_timed(ctdb->ev, state, timeout, ctdb_control_timeout_func, state);
400 int ctdb_ctrl_getrecmode_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *recmode)
405 ret = ctdb_control_recv(ctdb, state, mem_ctx, NULL, &res, NULL);
407 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_getrecmode_recv failed\n"));
412 *recmode = (uint32_t)res;
418 int ctdb_ctrl_getrecmode(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, uint32_t *recmode)
420 struct ctdb_client_control_state *state;
422 state = ctdb_ctrl_getrecmode_send(ctdb, mem_ctx, timeout, destnode);
423 return ctdb_ctrl_getrecmode_recv(ctdb, mem_ctx, state, recmode);
430 set the recovery mode of a remote node
432 int ctdb_ctrl_setrecmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmode)
438 data.dsize = sizeof(uint32_t);
439 data.dptr = (unsigned char *)&recmode;
441 ret = ctdb_control(ctdb, destnode, 0,
442 CTDB_CONTROL_SET_RECMODE, 0, data,
443 NULL, NULL, &res, &timeout, NULL);
444 if (ret != 0 || res != 0) {
445 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setrecmode failed\n"));
455 get the recovery master of a remote node
457 struct ctdb_client_control_state *
458 ctdb_ctrl_getrecmaster_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx,
459 struct timeval timeout, uint32_t destnode)
461 struct ctdb_client_control_state *state;
463 state = ctdb_control_send(ctdb, destnode, 0,
464 CTDB_CONTROL_GET_RECMASTER, 0, tdb_null,
466 if (state != NULL && !timeval_is_zero(&timeout)) {
467 event_add_timed(ctdb->ev, state, timeout, ctdb_control_timeout_func, state);
473 int ctdb_ctrl_getrecmaster_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *recmaster)
478 ret = ctdb_control_recv(ctdb, state, mem_ctx, NULL, &res, NULL);
480 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_getrecmaster_recv failed\n"));
485 *recmaster = (uint32_t)res;
491 int ctdb_ctrl_getrecmaster(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, uint32_t *recmaster)
493 struct ctdb_client_control_state *state;
495 state = ctdb_ctrl_getrecmaster_send(ctdb, mem_ctx, timeout, destnode);
496 return ctdb_ctrl_getrecmaster_recv(ctdb, mem_ctx, state, recmaster);
501 set the recovery master of a remote node
503 int ctdb_ctrl_setrecmaster(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmaster)
510 data.dsize = sizeof(uint32_t);
511 data.dptr = (unsigned char *)&recmaster;
513 ret = ctdb_control(ctdb, destnode, 0,
514 CTDB_CONTROL_SET_RECMASTER, 0, data,
515 NULL, NULL, &res, &timeout, NULL);
516 if (ret != 0 || res != 0) {
517 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setrecmaster failed\n"));
526 get a list of databases off a remote node
528 int ctdb_ctrl_getdbmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
529 TALLOC_CTX *mem_ctx, struct ctdb_dbid_map **dbmap)
535 ret = ctdb_control(ctdb, destnode, 0,
536 CTDB_CONTROL_GET_DBMAP, 0, tdb_null,
537 mem_ctx, &outdata, &res, &timeout, NULL);
538 if (ret != 0 || res != 0) {
539 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getdbmap failed ret:%d res:%d\n", ret, res));
543 *dbmap = (struct ctdb_dbid_map *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
544 talloc_free(outdata.dptr);
550 get a list of nodes (vnn and flags ) from a remote node
552 int ctdb_ctrl_getnodemap(struct ctdb_context *ctdb,
553 struct timeval timeout, uint32_t destnode,
554 TALLOC_CTX *mem_ctx, struct ctdb_node_map **nodemap)
560 ret = ctdb_control(ctdb, destnode, 0,
561 CTDB_CONTROL_GET_NODEMAP, 0, tdb_null,
562 mem_ctx, &outdata, &res, &timeout, NULL);
563 if (ret == 0 && res == -1 && outdata.dsize == 0) {
564 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getnodes failed, falling back to ipv4-only control\n"));
565 return ctdb_ctrl_getnodemapv4(ctdb, timeout, destnode, mem_ctx, nodemap);
567 if (ret != 0 || res != 0 || outdata.dsize == 0) {
568 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getnodes failed ret:%d res:%d\n", ret, res));
572 *nodemap = (struct ctdb_node_map *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
573 talloc_free(outdata.dptr);
579 old style ipv4-only get a list of nodes (vnn and flags ) from a remote node
581 int ctdb_ctrl_getnodemapv4(struct ctdb_context *ctdb,
582 struct timeval timeout, uint32_t destnode,
583 TALLOC_CTX *mem_ctx, struct ctdb_node_map **nodemap)
587 struct ctdb_node_mapv4 *nodemapv4;
590 ret = ctdb_control(ctdb, destnode, 0,
591 CTDB_CONTROL_GET_NODEMAPv4, 0, tdb_null,
592 mem_ctx, &outdata, &res, &timeout, NULL);
593 if (ret != 0 || res != 0 || outdata.dsize == 0) {
594 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getnodesv4 failed ret:%d res:%d\n", ret, res));
598 nodemapv4 = (struct ctdb_node_mapv4 *)outdata.dptr;
600 len = offsetof(struct ctdb_node_map, nodes) + nodemapv4->num*sizeof(struct ctdb_node_and_flags);
601 (*nodemap) = talloc_zero_size(mem_ctx, len);
602 CTDB_NO_MEMORY(ctdb, (*nodemap));
604 (*nodemap)->num = nodemapv4->num;
605 for (i=0; i<nodemapv4->num; i++) {
606 (*nodemap)->nodes[i].pnn = nodemapv4->nodes[i].pnn;
607 (*nodemap)->nodes[i].flags = nodemapv4->nodes[i].flags;
608 (*nodemap)->nodes[i].addr.ip = nodemapv4->nodes[i].sin;
609 (*nodemap)->nodes[i].addr.sa.sa_family = AF_INET;
612 talloc_free(outdata.dptr);
618 drop the transport, reload the nodes file and restart the transport
620 int ctdb_ctrl_reload_nodes_file(struct ctdb_context *ctdb,
621 struct timeval timeout, uint32_t destnode)
626 ret = ctdb_control(ctdb, destnode, 0,
627 CTDB_CONTROL_RELOAD_NODES_FILE, 0, tdb_null,
628 NULL, NULL, &res, &timeout, NULL);
629 if (ret != 0 || res != 0) {
630 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for reloadnodesfile failed\n"));
639 set vnn map on a node
641 int ctdb_ctrl_setvnnmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
642 TALLOC_CTX *mem_ctx, struct ctdb_vnn_map *vnnmap)
647 struct ctdb_vnn_map_wire *map;
650 len = offsetof(struct ctdb_vnn_map_wire, map) + sizeof(uint32_t)*vnnmap->size;
651 map = talloc_size(mem_ctx, len);
652 CTDB_NO_MEMORY(ctdb, map);
654 map->generation = vnnmap->generation;
655 map->size = vnnmap->size;
656 memcpy(map->map, vnnmap->map, sizeof(uint32_t)*map->size);
659 data.dptr = (uint8_t *)map;
661 ret = ctdb_control(ctdb, destnode, 0,
662 CTDB_CONTROL_SETVNNMAP, 0, data,
663 NULL, NULL, &res, &timeout, NULL);
664 if (ret != 0 || res != 0) {
665 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setvnnmap failed\n"));
676 async send for pull database
678 struct ctdb_client_control_state *ctdb_ctrl_pulldb_send(
679 struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid,
680 uint32_t lmaster, TALLOC_CTX *mem_ctx, struct timeval timeout)
683 struct ctdb_control_pulldb *pull;
684 struct ctdb_client_control_state *state;
686 pull = talloc(mem_ctx, struct ctdb_control_pulldb);
687 CTDB_NO_MEMORY_NULL(ctdb, pull);
690 pull->lmaster = lmaster;
692 indata.dsize = sizeof(struct ctdb_control_pulldb);
693 indata.dptr = (unsigned char *)pull;
695 state = ctdb_control_send(ctdb, destnode, 0,
696 CTDB_CONTROL_PULL_DB, 0, indata,
698 if (state != NULL && !timeval_is_zero(&timeout)) {
699 event_add_timed(ctdb->ev, state, timeout, ctdb_control_timeout_func, state);
708 async recv for pull database
710 int ctdb_ctrl_pulldb_recv(
711 struct ctdb_context *ctdb,
712 TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state,
718 ret = ctdb_control_recv(ctdb, state, mem_ctx, outdata, &res, NULL);
719 if ( (ret != 0) || (res != 0) ){
720 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_pulldb_recv failed\n"));
728 pull all keys and records for a specific database on a node
730 int ctdb_ctrl_pulldb(struct ctdb_context *ctdb, uint32_t destnode,
731 uint32_t dbid, uint32_t lmaster,
732 TALLOC_CTX *mem_ctx, struct timeval timeout,
735 struct ctdb_client_control_state *state;
737 state = ctdb_ctrl_pulldb_send(ctdb, destnode, dbid, lmaster, mem_ctx,
740 return ctdb_ctrl_pulldb_recv(ctdb, mem_ctx, state, outdata);
745 change dmaster for all keys in the database to the new value
747 int ctdb_ctrl_setdmaster(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
748 TALLOC_CTX *mem_ctx, uint32_t dbid, uint32_t dmaster)
754 indata.dsize = 2*sizeof(uint32_t);
755 indata.dptr = (unsigned char *)talloc_array(mem_ctx, uint32_t, 2);
757 ((uint32_t *)(&indata.dptr[0]))[0] = dbid;
758 ((uint32_t *)(&indata.dptr[0]))[1] = dmaster;
760 ret = ctdb_control(ctdb, destnode, 0,
761 CTDB_CONTROL_SET_DMASTER, 0, indata,
762 NULL, NULL, &res, &timeout, NULL);
763 if (ret != 0 || res != 0) {
764 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setdmaster failed\n"));
772 ping a node, return number of clients connected
774 int ctdb_ctrl_ping(struct ctdb_context *ctdb, uint32_t destnode)
779 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_PING, 0,
780 tdb_null, NULL, NULL, &res, NULL, NULL);
788 find the real path to a ltdb
790 int ctdb_ctrl_getdbpath(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t dbid, TALLOC_CTX *mem_ctx,
797 data.dptr = (uint8_t *)&dbid;
798 data.dsize = sizeof(dbid);
800 ret = ctdb_control(ctdb, destnode, 0,
801 CTDB_CONTROL_GETDBPATH, 0, data,
802 mem_ctx, &data, &res, &timeout, NULL);
803 if (ret != 0 || res != 0) {
807 (*path) = talloc_strndup(mem_ctx, (const char *)data.dptr, data.dsize);
808 if ((*path) == NULL) {
812 talloc_free(data.dptr);
818 find the name of a db
820 int ctdb_ctrl_getdbname(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t dbid, TALLOC_CTX *mem_ctx,
827 data.dptr = (uint8_t *)&dbid;
828 data.dsize = sizeof(dbid);
830 ret = ctdb_control(ctdb, destnode, 0,
831 CTDB_CONTROL_GET_DBNAME, 0, data,
832 mem_ctx, &data, &res, &timeout, NULL);
833 if (ret != 0 || res != 0) {
837 (*name) = talloc_strndup(mem_ctx, (const char *)data.dptr, data.dsize);
838 if ((*name) == NULL) {
842 talloc_free(data.dptr);
848 get the health status of a db
850 int ctdb_ctrl_getdbhealth(struct ctdb_context *ctdb,
851 struct timeval timeout,
853 uint32_t dbid, TALLOC_CTX *mem_ctx,
860 data.dptr = (uint8_t *)&dbid;
861 data.dsize = sizeof(dbid);
863 ret = ctdb_control(ctdb, destnode, 0,
864 CTDB_CONTROL_DB_GET_HEALTH, 0, data,
865 mem_ctx, &data, &res, &timeout, NULL);
866 if (ret != 0 || res != 0) {
870 if (data.dsize == 0) {
875 (*reason) = talloc_strndup(mem_ctx, (const char *)data.dptr, data.dsize);
876 if ((*reason) == NULL) {
880 talloc_free(data.dptr);
888 int ctdb_ctrl_createdb(struct ctdb_context *ctdb, struct timeval timeout,
890 const char *name, bool persistent)
895 handle = ctdb_createdb_send(ctdb, destnode, name, persistent, 0, NULL, NULL);
896 if (handle == NULL) {
897 DEBUG(DEBUG_ERR, (__location__ " Failed to send createdb control\n"));
901 if (!timeval_is_zero(&timeout)) {
902 event_add_timed(ctdb->ev, handle, timeout, ctdb_control_timeout_func, handle);
905 ret = ctdb_createdb_recv(ctdb, handle, NULL);
907 DEBUG(DEBUG_ERR,(__location__ " ctdb control for createdb failed\n"));
915 get debug level on a node
917 int ctdb_ctrl_get_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, int32_t *level)
923 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_DEBUG, 0, tdb_null,
924 ctdb, &data, &res, NULL, NULL);
925 if (ret != 0 || res != 0) {
928 if (data.dsize != sizeof(int32_t)) {
929 DEBUG(DEBUG_ERR,("Bad control reply size in ctdb_get_debuglevel (got %u)\n",
930 (unsigned)data.dsize));
933 *level = *(int32_t *)data.dptr;
934 talloc_free(data.dptr);
939 set debug level on a node
941 int ctdb_ctrl_set_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, int32_t level)
947 data.dptr = (uint8_t *)&level;
948 data.dsize = sizeof(level);
950 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SET_DEBUG, 0, data,
951 NULL, NULL, &res, NULL, NULL);
952 if (ret != 0 || res != 0) {
960 get a list of connected nodes
962 uint32_t *ctdb_get_connected_nodes(struct ctdb_context *ctdb,
963 struct timeval timeout,
967 struct ctdb_node_map *map=NULL;
973 ret = ctdb_ctrl_getnodemap(ctdb, timeout, CTDB_CURRENT_NODE, mem_ctx, &map);
978 nodes = talloc_array(mem_ctx, uint32_t, map->num);
983 for (i=0;i<map->num;i++) {
984 if (!(map->nodes[i].flags & NODE_FLAGS_DISCONNECTED)) {
985 nodes[*num_nodes] = map->nodes[i].pnn;
997 int ctdb_statistics_reset(struct ctdb_context *ctdb, uint32_t destnode)
1002 ret = ctdb_control(ctdb, destnode, 0,
1003 CTDB_CONTROL_STATISTICS_RESET, 0, tdb_null,
1004 NULL, NULL, &res, NULL, NULL);
1005 if (ret != 0 || res != 0) {
1006 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for reset statistics failed\n"));
1013 this is the dummy null procedure that all databases support
1015 static int ctdb_null_func(struct ctdb_call_info *call)
1021 this is a plain fetch procedure that all databases support
1023 static int ctdb_fetch_func(struct ctdb_call_info *call)
1025 call->reply_data = &call->record_data;
1030 attach to a specific database - client call
1032 struct ctdb_db_context *ctdb_attach(struct ctdb_context *ctdb, const char *name, bool persistent, uint32_t tdb_flags)
1034 struct ctdb_db_context *ctdb_db;
1039 ctdb_db = ctdb_db_handle(ctdb, name);
1044 ctdb_db = talloc_zero(ctdb, struct ctdb_db_context);
1045 CTDB_NO_MEMORY_NULL(ctdb, ctdb_db);
1047 ctdb_db->ctdb = ctdb;
1048 ctdb_db->db_name = talloc_strdup(ctdb_db, name);
1049 CTDB_NO_MEMORY_NULL(ctdb, ctdb_db->db_name);
1051 data.dptr = discard_const(name);
1052 data.dsize = strlen(name)+1;
1054 /* tell ctdb daemon to attach */
1055 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, tdb_flags,
1056 persistent?CTDB_CONTROL_DB_ATTACH_PERSISTENT:CTDB_CONTROL_DB_ATTACH,
1057 0, data, ctdb_db, &data, &res, NULL, NULL);
1058 if (ret != 0 || res != 0 || data.dsize != sizeof(uint32_t)) {
1059 DEBUG(DEBUG_ERR,("Failed to attach to database '%s'\n", name));
1060 talloc_free(ctdb_db);
1064 ctdb_db->db_id = *(uint32_t *)data.dptr;
1065 talloc_free(data.dptr);
1067 ret = ctdb_ctrl_getdbpath(ctdb, timeval_current_ofs(2, 0), CTDB_CURRENT_NODE, ctdb_db->db_id, ctdb_db, &ctdb_db->db_path);
1069 DEBUG(DEBUG_ERR,("Failed to get dbpath for database '%s'\n", name));
1070 talloc_free(ctdb_db);
1074 tdb_flags = persistent?TDB_DEFAULT:TDB_NOSYNC;
1075 if (ctdb->valgrinding) {
1076 tdb_flags |= TDB_NOMMAP;
1078 tdb_flags |= TDB_DISALLOW_NESTING;
1080 ctdb_db->ltdb = tdb_wrap_open(ctdb, ctdb_db->db_path, 0, tdb_flags, O_RDWR, 0);
1081 if (ctdb_db->ltdb == NULL) {
1082 ctdb_set_error(ctdb, "Failed to open tdb '%s'\n", ctdb_db->db_path);
1083 talloc_free(ctdb_db);
1087 ctdb_db->persistent = persistent;
1089 DLIST_ADD(ctdb->db_list, ctdb_db);
1091 /* add well known functions */
1092 ctdb_set_call(ctdb_db, ctdb_null_func, CTDB_NULL_FUNC);
1093 ctdb_set_call(ctdb_db, ctdb_fetch_func, CTDB_FETCH_FUNC);
1100 setup a call for a database
1102 int ctdb_set_call(struct ctdb_db_context *ctdb_db, ctdb_fn_t fn, uint32_t id)
1104 struct ctdb_registered_call *call;
1109 struct ctdb_control_set_call c;
1112 /* this is no longer valid with the separate daemon architecture */
1113 c.db_id = ctdb_db->db_id;
1117 data.dptr = (uint8_t *)&c;
1118 data.dsize = sizeof(c);
1120 ret = ctdb_control(ctdb_db->ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_SET_CALL, 0,
1121 data, NULL, NULL, &status, NULL, NULL);
1122 if (ret != 0 || status != 0) {
1123 DEBUG(DEBUG_ERR,("ctdb_set_call failed for call %u\n", id));
1128 /* also register locally */
1129 call = talloc(ctdb_db, struct ctdb_registered_call);
1133 DLIST_ADD(ctdb_db->calls, call);
1138 struct traverse_state {
1141 ctdb_traverse_func fn;
1146 called on each key during a ctdb_traverse
1148 static void traverse_handler(struct ctdb_context *ctdb, uint64_t srvid, TDB_DATA data, void *p)
1150 struct traverse_state *state = (struct traverse_state *)p;
1151 struct ctdb_rec_data *d = (struct ctdb_rec_data *)data.dptr;
1154 if (data.dsize < sizeof(uint32_t) ||
1155 d->length != data.dsize) {
1156 DEBUG(DEBUG_ERR,("Bad data size %u in traverse_handler\n", (unsigned)data.dsize));
1161 key.dsize = d->keylen;
1162 key.dptr = &d->data[0];
1163 data.dsize = d->datalen;
1164 data.dptr = &d->data[d->keylen];
1166 if (key.dsize == 0 && data.dsize == 0) {
1167 /* end of traverse */
1172 if (data.dsize == sizeof(struct ctdb_ltdb_header)) {
1173 /* empty records are deleted records in ctdb */
1177 if (state->fn(ctdb, key, data, state->private_data) != 0) {
1186 start a cluster wide traverse, calling the supplied fn on each record
1187 return the number of records traversed, or -1 on error
1189 int ctdb_traverse(struct ctdb_db_context *ctdb_db, ctdb_traverse_func fn, void *private_data)
1192 struct ctdb_traverse_start t;
1195 uint64_t srvid = (getpid() | 0xFLL<<60);
1196 struct traverse_state state;
1200 state.private_data = private_data;
1203 ret = ctdb_set_message_handler(ctdb_db->ctdb, srvid, traverse_handler, &state);
1205 DEBUG(DEBUG_ERR,("Failed to setup traverse handler\n"));
1209 t.db_id = ctdb_db->db_id;
1213 data.dptr = (uint8_t *)&t;
1214 data.dsize = sizeof(t);
1216 ret = ctdb_control(ctdb_db->ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_TRAVERSE_START, 0,
1217 data, NULL, NULL, &status, NULL, NULL);
1218 if (ret != 0 || status != 0) {
1219 DEBUG(DEBUG_ERR,("ctdb_traverse_all failed\n"));
1220 ctdb_remove_message_handler(ctdb_db->ctdb, srvid);
1224 while (!state.done) {
1225 event_loop_once(ctdb_db->ctdb->ev);
1228 ret = ctdb_remove_message_handler(ctdb_db->ctdb, srvid);
1230 DEBUG(DEBUG_ERR,("Failed to remove ctdb_traverse handler\n"));
1237 #define ISASCII(x) ((x>31)&&(x<128))
1239 called on each key during a catdb
1241 int ctdb_dumpdb_record(struct ctdb_context *ctdb, TDB_DATA key, TDB_DATA data, void *p)
1244 FILE *f = (FILE *)p;
1245 struct ctdb_ltdb_header *h = (struct ctdb_ltdb_header *)data.dptr;
1247 fprintf(f, "key(%u) = \"", (unsigned)key.dsize);
1248 for (i=0;i<key.dsize;i++) {
1249 if (ISASCII(key.dptr[i])) {
1250 fprintf(f, "%c", key.dptr[i]);
1252 fprintf(f, "\\%02X", key.dptr[i]);
1257 fprintf(f, "dmaster: %u\n", h->dmaster);
1258 fprintf(f, "rsn: %llu\n", (unsigned long long)h->rsn);
1260 fprintf(f, "data(%u) = \"", (unsigned)(data.dsize - sizeof(*h)));
1261 for (i=sizeof(*h);i<data.dsize;i++) {
1262 if (ISASCII(data.dptr[i])) {
1263 fprintf(f, "%c", data.dptr[i]);
1265 fprintf(f, "\\%02X", data.dptr[i]);
1276 convenience function to list all keys to stdout
1278 int ctdb_dump_db(struct ctdb_db_context *ctdb_db, FILE *f)
1280 return ctdb_traverse(ctdb_db, ctdb_dumpdb_record, f);
1284 get the pid of a ctdb daemon
1286 int ctdb_ctrl_getpid(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *pid)
1291 ret = ctdb_control(ctdb, destnode, 0,
1292 CTDB_CONTROL_GET_PID, 0, tdb_null,
1293 NULL, NULL, &res, &timeout, NULL);
1295 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getpid failed\n"));
1306 async freeze send control
1308 struct ctdb_client_control_state *
1309 ctdb_ctrl_freeze_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, uint32_t priority)
1311 struct ctdb_client_control_state *state;
1313 state = ctdb_control_send(ctdb, destnode, priority,
1314 CTDB_CONTROL_FREEZE, 0, tdb_null,
1316 if (state != NULL && !timeval_is_zero(&timeout)) {
1317 event_add_timed(ctdb->ev, state, timeout, ctdb_control_timeout_func, state);
1324 async freeze recv control
1326 int ctdb_ctrl_freeze_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state)
1331 ret = ctdb_control_recv(ctdb, state, mem_ctx, NULL, &res, NULL);
1332 if ( (ret != 0) || (res != 0) ){
1333 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_freeze_recv failed\n"));
1341 freeze databases of a certain priority
1343 int ctdb_ctrl_freeze_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t priority)
1345 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1346 struct ctdb_client_control_state *state;
1349 state = ctdb_ctrl_freeze_send(ctdb, tmp_ctx, timeout, destnode, priority);
1350 ret = ctdb_ctrl_freeze_recv(ctdb, tmp_ctx, state);
1351 talloc_free(tmp_ctx);
1356 /* Freeze all databases */
1357 int ctdb_ctrl_freeze(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
1361 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
1362 if (ctdb_ctrl_freeze_priority(ctdb, timeout, destnode, i) != 0) {
1370 thaw databases of a certain priority
1372 int ctdb_ctrl_thaw_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t priority)
1377 ret = ctdb_control(ctdb, destnode, priority,
1378 CTDB_CONTROL_THAW, 0, tdb_null,
1379 NULL, NULL, &res, &timeout, NULL);
1380 if (ret != 0 || res != 0) {
1381 DEBUG(DEBUG_ERR,(__location__ " ctdb_control thaw failed\n"));
1388 /* thaw all databases */
1389 int ctdb_ctrl_thaw(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
1391 return ctdb_ctrl_thaw_priority(ctdb, timeout, destnode, 0);
1395 get pnn of a node, or -1
1397 int ctdb_ctrl_getpnn(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
1401 ctdb_handle *handle;
1403 handle = ctdb_getpnn_send(ctdb, destnode, NULL, NULL);
1404 if (handle == NULL) {
1405 DEBUG(DEBUG_ERR, (__location__ " Failed to send getpnn control\n"));
1409 if (!timeval_is_zero(&timeout)) {
1410 event_add_timed(ctdb->ev, handle, timeout, ctdb_control_timeout_func, handle);
1413 ret = ctdb_getpnn_recv(ctdb, handle, &pnn);
1415 DEBUG(DEBUG_ERR,(__location__ " ctdb control for getpnn failed\n"));
1423 get the monitoring mode of a remote node
1425 int ctdb_ctrl_getmonmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *monmode)
1430 ret = ctdb_control(ctdb, destnode, 0,
1431 CTDB_CONTROL_GET_MONMODE, 0, tdb_null,
1432 NULL, NULL, &res, &timeout, NULL);
1434 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getmonmode failed\n"));
1445 set the monitoring mode of a remote node to active
1447 int ctdb_ctrl_enable_monmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
1452 ret = ctdb_control(ctdb, destnode, 0,
1453 CTDB_CONTROL_ENABLE_MONITOR, 0, tdb_null,
1454 NULL, NULL,NULL, &timeout, NULL);
1456 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for enable_monitor failed\n"));
1466 set the monitoring mode of a remote node to disable
1468 int ctdb_ctrl_disable_monmode(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
1473 ret = ctdb_control(ctdb, destnode, 0,
1474 CTDB_CONTROL_DISABLE_MONITOR, 0, tdb_null,
1475 NULL, NULL, NULL, &timeout, NULL);
1477 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for disable_monitor failed\n"));
1489 sent to a node to make it take over an ip address
1491 int ctdb_ctrl_takeover_ip(struct ctdb_context *ctdb, struct timeval timeout,
1492 uint32_t destnode, struct ctdb_public_ip *ip)
1495 struct ctdb_public_ipv4 ipv4;
1499 if (ip->addr.sa.sa_family == AF_INET) {
1501 ipv4.sin = ip->addr.ip;
1503 data.dsize = sizeof(ipv4);
1504 data.dptr = (uint8_t *)&ipv4;
1506 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_TAKEOVER_IPv4, 0, data, NULL,
1507 NULL, &res, &timeout, NULL);
1509 data.dsize = sizeof(*ip);
1510 data.dptr = (uint8_t *)ip;
1512 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_TAKEOVER_IP, 0, data, NULL,
1513 NULL, &res, &timeout, NULL);
1516 if (ret != 0 || res != 0) {
1517 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for takeover_ip failed\n"));
1526 sent to a node to make it release an ip address
1528 int ctdb_ctrl_release_ip(struct ctdb_context *ctdb, struct timeval timeout,
1529 uint32_t destnode, struct ctdb_public_ip *ip)
1532 struct ctdb_public_ipv4 ipv4;
1536 if (ip->addr.sa.sa_family == AF_INET) {
1538 ipv4.sin = ip->addr.ip;
1540 data.dsize = sizeof(ipv4);
1541 data.dptr = (uint8_t *)&ipv4;
1543 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_RELEASE_IPv4, 0, data, NULL,
1544 NULL, &res, &timeout, NULL);
1546 data.dsize = sizeof(*ip);
1547 data.dptr = (uint8_t *)ip;
1549 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_RELEASE_IP, 0, data, NULL,
1550 NULL, &res, &timeout, NULL);
1553 if (ret != 0 || res != 0) {
1554 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for release_ip failed\n"));
1565 int ctdb_ctrl_get_tunable(struct ctdb_context *ctdb,
1566 struct timeval timeout,
1568 const char *name, uint32_t *value)
1570 struct ctdb_control_get_tunable *t;
1571 TDB_DATA data, outdata;
1575 data.dsize = offsetof(struct ctdb_control_get_tunable, name) + strlen(name) + 1;
1576 data.dptr = talloc_size(ctdb, data.dsize);
1577 CTDB_NO_MEMORY(ctdb, data.dptr);
1579 t = (struct ctdb_control_get_tunable *)data.dptr;
1580 t->length = strlen(name)+1;
1581 memcpy(t->name, name, t->length);
1583 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_TUNABLE, 0, data, ctdb,
1584 &outdata, &res, &timeout, NULL);
1585 talloc_free(data.dptr);
1586 if (ret != 0 || res != 0) {
1587 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get_tunable failed\n"));
1591 if (outdata.dsize != sizeof(uint32_t)) {
1592 DEBUG(DEBUG_ERR,("Invalid return data in get_tunable\n"));
1593 talloc_free(outdata.dptr);
1597 *value = *(uint32_t *)outdata.dptr;
1598 talloc_free(outdata.dptr);
1606 int ctdb_ctrl_set_tunable(struct ctdb_context *ctdb,
1607 struct timeval timeout,
1609 const char *name, uint32_t value)
1611 struct ctdb_control_set_tunable *t;
1616 data.dsize = offsetof(struct ctdb_control_set_tunable, name) + strlen(name) + 1;
1617 data.dptr = talloc_size(ctdb, data.dsize);
1618 CTDB_NO_MEMORY(ctdb, data.dptr);
1620 t = (struct ctdb_control_set_tunable *)data.dptr;
1621 t->length = strlen(name)+1;
1622 memcpy(t->name, name, t->length);
1625 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SET_TUNABLE, 0, data, NULL,
1626 NULL, &res, &timeout, NULL);
1627 talloc_free(data.dptr);
1628 if (ret != 0 || res != 0) {
1629 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set_tunable failed\n"));
1639 int ctdb_ctrl_list_tunables(struct ctdb_context *ctdb,
1640 struct timeval timeout,
1642 TALLOC_CTX *mem_ctx,
1643 const char ***list, uint32_t *count)
1648 struct ctdb_control_list_tunable *t;
1651 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_LIST_TUNABLES, 0, tdb_null,
1652 mem_ctx, &outdata, &res, &timeout, NULL);
1653 if (ret != 0 || res != 0) {
1654 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for list_tunables failed\n"));
1658 t = (struct ctdb_control_list_tunable *)outdata.dptr;
1659 if (outdata.dsize < offsetof(struct ctdb_control_list_tunable, data) ||
1660 t->length > outdata.dsize-offsetof(struct ctdb_control_list_tunable, data)) {
1661 DEBUG(DEBUG_ERR,("Invalid data in list_tunables reply\n"));
1662 talloc_free(outdata.dptr);
1666 p = talloc_strndup(mem_ctx, (char *)t->data, t->length);
1667 CTDB_NO_MEMORY(ctdb, p);
1669 talloc_free(outdata.dptr);
1674 for (s=strtok_r(p, ":", &ptr); s; s=strtok_r(NULL, ":", &ptr)) {
1675 (*list) = talloc_realloc(mem_ctx, *list, const char *, 1+(*count));
1676 CTDB_NO_MEMORY(ctdb, *list);
1677 (*list)[*count] = talloc_strdup(*list, s);
1678 CTDB_NO_MEMORY(ctdb, (*list)[*count]);
1688 int ctdb_ctrl_get_public_ips_flags(struct ctdb_context *ctdb,
1689 struct timeval timeout, uint32_t destnode,
1690 TALLOC_CTX *mem_ctx,
1692 struct ctdb_all_public_ips **ips)
1698 ret = ctdb_control(ctdb, destnode, 0,
1699 CTDB_CONTROL_GET_PUBLIC_IPS, flags, tdb_null,
1700 mem_ctx, &outdata, &res, &timeout, NULL);
1701 if (ret == 0 && res == -1) {
1702 DEBUG(DEBUG_ERR,(__location__ " ctdb_control to get public ips failed, falling back to ipv4-only version\n"));
1703 return ctdb_ctrl_get_public_ipsv4(ctdb, timeout, destnode, mem_ctx, ips);
1705 if (ret != 0 || res != 0) {
1706 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getpublicips failed ret:%d res:%d\n", ret, res));
1710 *ips = (struct ctdb_all_public_ips *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
1711 talloc_free(outdata.dptr);
1716 int ctdb_ctrl_get_public_ips(struct ctdb_context *ctdb,
1717 struct timeval timeout, uint32_t destnode,
1718 TALLOC_CTX *mem_ctx,
1719 struct ctdb_all_public_ips **ips)
1721 return ctdb_ctrl_get_public_ips_flags(ctdb, timeout,
1726 int ctdb_ctrl_get_public_ipsv4(struct ctdb_context *ctdb,
1727 struct timeval timeout, uint32_t destnode,
1728 TALLOC_CTX *mem_ctx, struct ctdb_all_public_ips **ips)
1733 struct ctdb_all_public_ipsv4 *ipsv4;
1735 ret = ctdb_control(ctdb, destnode, 0,
1736 CTDB_CONTROL_GET_PUBLIC_IPSv4, 0, tdb_null,
1737 mem_ctx, &outdata, &res, &timeout, NULL);
1738 if (ret != 0 || res != 0) {
1739 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getpublicips failed\n"));
1743 ipsv4 = (struct ctdb_all_public_ipsv4 *)outdata.dptr;
1744 len = offsetof(struct ctdb_all_public_ips, ips) +
1745 ipsv4->num*sizeof(struct ctdb_public_ip);
1746 *ips = talloc_zero_size(mem_ctx, len);
1747 CTDB_NO_MEMORY(ctdb, *ips);
1748 (*ips)->num = ipsv4->num;
1749 for (i=0; i<ipsv4->num; i++) {
1750 (*ips)->ips[i].pnn = ipsv4->ips[i].pnn;
1751 (*ips)->ips[i].addr.ip = ipsv4->ips[i].sin;
1754 talloc_free(outdata.dptr);
1759 int ctdb_ctrl_get_public_ip_info(struct ctdb_context *ctdb,
1760 struct timeval timeout, uint32_t destnode,
1761 TALLOC_CTX *mem_ctx,
1762 const ctdb_sock_addr *addr,
1763 struct ctdb_control_public_ip_info **_info)
1769 struct ctdb_control_public_ip_info *info;
1773 indata.dptr = discard_const_p(uint8_t, addr);
1774 indata.dsize = sizeof(*addr);
1776 ret = ctdb_control(ctdb, destnode, 0,
1777 CTDB_CONTROL_GET_PUBLIC_IP_INFO, 0, indata,
1778 mem_ctx, &outdata, &res, &timeout, NULL);
1779 if (ret != 0 || res != 0) {
1780 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
1781 "failed ret:%d res:%d\n",
1786 len = offsetof(struct ctdb_control_public_ip_info, ifaces);
1787 if (len > outdata.dsize) {
1788 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
1789 "returned invalid data with size %u > %u\n",
1790 (unsigned int)outdata.dsize,
1791 (unsigned int)len));
1792 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
1796 info = (struct ctdb_control_public_ip_info *)outdata.dptr;
1797 len += info->num*sizeof(struct ctdb_control_iface_info);
1799 if (len > outdata.dsize) {
1800 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
1801 "returned invalid data with size %u > %u\n",
1802 (unsigned int)outdata.dsize,
1803 (unsigned int)len));
1804 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
1808 /* make sure we null terminate the returned strings */
1809 for (i=0; i < info->num; i++) {
1810 info->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
1813 *_info = (struct ctdb_control_public_ip_info *)talloc_memdup(mem_ctx,
1816 talloc_free(outdata.dptr);
1817 if (*_info == NULL) {
1818 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get public ip info "
1819 "talloc_memdup size %u failed\n",
1820 (unsigned int)outdata.dsize));
1827 int ctdb_ctrl_get_ifaces(struct ctdb_context *ctdb,
1828 struct timeval timeout, uint32_t destnode,
1829 TALLOC_CTX *mem_ctx,
1830 struct ctdb_control_get_ifaces **_ifaces)
1835 struct ctdb_control_get_ifaces *ifaces;
1839 ret = ctdb_control(ctdb, destnode, 0,
1840 CTDB_CONTROL_GET_IFACES, 0, tdb_null,
1841 mem_ctx, &outdata, &res, &timeout, NULL);
1842 if (ret != 0 || res != 0) {
1843 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
1844 "failed ret:%d res:%d\n",
1849 len = offsetof(struct ctdb_control_get_ifaces, ifaces);
1850 if (len > outdata.dsize) {
1851 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
1852 "returned invalid data with size %u > %u\n",
1853 (unsigned int)outdata.dsize,
1854 (unsigned int)len));
1855 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
1859 ifaces = (struct ctdb_control_get_ifaces *)outdata.dptr;
1860 len += ifaces->num*sizeof(struct ctdb_control_iface_info);
1862 if (len > outdata.dsize) {
1863 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
1864 "returned invalid data with size %u > %u\n",
1865 (unsigned int)outdata.dsize,
1866 (unsigned int)len));
1867 dump_data(DEBUG_DEBUG, outdata.dptr, outdata.dsize);
1871 /* make sure we null terminate the returned strings */
1872 for (i=0; i < ifaces->num; i++) {
1873 ifaces->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
1876 *_ifaces = (struct ctdb_control_get_ifaces *)talloc_memdup(mem_ctx,
1879 talloc_free(outdata.dptr);
1880 if (*_ifaces == NULL) {
1881 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get ifaces "
1882 "talloc_memdup size %u failed\n",
1883 (unsigned int)outdata.dsize));
1890 int ctdb_ctrl_set_iface_link(struct ctdb_context *ctdb,
1891 struct timeval timeout, uint32_t destnode,
1892 TALLOC_CTX *mem_ctx,
1893 const struct ctdb_control_iface_info *info)
1899 indata.dptr = discard_const_p(uint8_t, info);
1900 indata.dsize = sizeof(*info);
1902 ret = ctdb_control(ctdb, destnode, 0,
1903 CTDB_CONTROL_SET_IFACE_LINK_STATE, 0, indata,
1904 mem_ctx, NULL, &res, &timeout, NULL);
1905 if (ret != 0 || res != 0) {
1906 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set iface link "
1907 "failed ret:%d res:%d\n",
1916 set/clear the permanent disabled bit on a remote node
1918 int ctdb_ctrl_modflags(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode,
1919 uint32_t set, uint32_t clear)
1923 struct ctdb_node_map *nodemap=NULL;
1924 struct ctdb_node_flag_change c;
1925 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1930 /* find the recovery master */
1931 ret = ctdb_ctrl_getrecmaster(ctdb, tmp_ctx, timeout, CTDB_CURRENT_NODE, &recmaster);
1933 DEBUG(DEBUG_ERR, (__location__ " Unable to get recmaster from local node\n"));
1934 talloc_free(tmp_ctx);
1939 /* read the node flags from the recmaster */
1940 ret = ctdb_ctrl_getnodemap(ctdb, timeout, recmaster, tmp_ctx, &nodemap);
1942 DEBUG(DEBUG_ERR, (__location__ " Unable to get nodemap from node %u\n", destnode));
1943 talloc_free(tmp_ctx);
1946 if (destnode >= nodemap->num) {
1947 DEBUG(DEBUG_ERR,(__location__ " Nodemap from recmaster does not contain node %d\n", destnode));
1948 talloc_free(tmp_ctx);
1953 c.old_flags = nodemap->nodes[destnode].flags;
1954 c.new_flags = c.old_flags;
1956 c.new_flags &= ~clear;
1958 data.dsize = sizeof(c);
1959 data.dptr = (unsigned char *)&c;
1961 /* send the flags update to all connected nodes */
1962 nodes = list_of_connected_nodes(ctdb, nodemap, tmp_ctx, true);
1964 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_MODIFY_FLAGS,
1966 timeout, false, data,
1969 DEBUG(DEBUG_ERR, (__location__ " Unable to update nodeflags on remote nodes\n"));
1971 talloc_free(tmp_ctx);
1975 talloc_free(tmp_ctx);
1983 int ctdb_ctrl_get_all_tunables(struct ctdb_context *ctdb,
1984 struct timeval timeout,
1986 struct ctdb_tunable *tunables)
1992 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_ALL_TUNABLES, 0, tdb_null, ctdb,
1993 &outdata, &res, &timeout, NULL);
1994 if (ret != 0 || res != 0) {
1995 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get all tunables failed\n"));
1999 if (outdata.dsize != sizeof(*tunables)) {
2000 DEBUG(DEBUG_ERR,(__location__ " bad data size %u in ctdb_ctrl_get_all_tunables should be %u\n",
2001 (unsigned)outdata.dsize, (unsigned)sizeof(*tunables)));
2005 *tunables = *(struct ctdb_tunable *)outdata.dptr;
2006 talloc_free(outdata.dptr);
2011 add a public address to a node
2013 int ctdb_ctrl_add_public_ip(struct ctdb_context *ctdb,
2014 struct timeval timeout,
2016 struct ctdb_control_ip_iface *pub)
2022 data.dsize = offsetof(struct ctdb_control_ip_iface, iface) + pub->len;
2023 data.dptr = (unsigned char *)pub;
2025 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_ADD_PUBLIC_IP, 0, data, NULL,
2026 NULL, &res, &timeout, NULL);
2027 if (ret != 0 || res != 0) {
2028 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for add_public_ip failed\n"));
2036 delete a public address from a node
2038 int ctdb_ctrl_del_public_ip(struct ctdb_context *ctdb,
2039 struct timeval timeout,
2041 struct ctdb_control_ip_iface *pub)
2047 data.dsize = offsetof(struct ctdb_control_ip_iface, iface) + pub->len;
2048 data.dptr = (unsigned char *)pub;
2050 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_DEL_PUBLIC_IP, 0, data, NULL,
2051 NULL, &res, &timeout, NULL);
2052 if (ret != 0 || res != 0) {
2053 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for del_public_ip failed\n"));
2061 kill a tcp connection
2063 int ctdb_ctrl_killtcp(struct ctdb_context *ctdb,
2064 struct timeval timeout,
2066 struct ctdb_control_killtcp *killtcp)
2072 data.dsize = sizeof(struct ctdb_control_killtcp);
2073 data.dptr = (unsigned char *)killtcp;
2075 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_KILL_TCP, 0, data, NULL,
2076 NULL, &res, &timeout, NULL);
2077 if (ret != 0 || res != 0) {
2078 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for killtcp failed\n"));
2088 int ctdb_ctrl_gratious_arp(struct ctdb_context *ctdb,
2089 struct timeval timeout,
2091 ctdb_sock_addr *addr,
2097 struct ctdb_control_gratious_arp *gratious_arp;
2098 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2101 len = strlen(ifname)+1;
2102 gratious_arp = talloc_size(tmp_ctx,
2103 offsetof(struct ctdb_control_gratious_arp, iface) + len);
2104 CTDB_NO_MEMORY(ctdb, gratious_arp);
2106 gratious_arp->addr = *addr;
2107 gratious_arp->len = len;
2108 memcpy(&gratious_arp->iface[0], ifname, len);
2111 data.dsize = offsetof(struct ctdb_control_gratious_arp, iface) + len;
2112 data.dptr = (unsigned char *)gratious_arp;
2114 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SEND_GRATIOUS_ARP, 0, data, NULL,
2115 NULL, &res, &timeout, NULL);
2116 if (ret != 0 || res != 0) {
2117 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for gratious_arp failed\n"));
2118 talloc_free(tmp_ctx);
2122 talloc_free(tmp_ctx);
2127 get a list of all tcp tickles that a node knows about for a particular vnn
2129 int ctdb_ctrl_get_tcp_tickles(struct ctdb_context *ctdb,
2130 struct timeval timeout, uint32_t destnode,
2131 TALLOC_CTX *mem_ctx,
2132 ctdb_sock_addr *addr,
2133 struct ctdb_control_tcp_tickle_list **list)
2136 TDB_DATA data, outdata;
2139 data.dptr = (uint8_t*)addr;
2140 data.dsize = sizeof(ctdb_sock_addr);
2142 ret = ctdb_control(ctdb, destnode, 0,
2143 CTDB_CONTROL_GET_TCP_TICKLE_LIST, 0, data,
2144 mem_ctx, &outdata, &status, NULL, NULL);
2145 if (ret != 0 || status != 0) {
2146 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get tcp tickles failed\n"));
2150 *list = (struct ctdb_control_tcp_tickle_list *)outdata.dptr;
2156 register a server id
2158 int ctdb_ctrl_register_server_id(struct ctdb_context *ctdb,
2159 struct timeval timeout,
2160 struct ctdb_server_id *id)
2166 data.dsize = sizeof(struct ctdb_server_id);
2167 data.dptr = (unsigned char *)id;
2169 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0,
2170 CTDB_CONTROL_REGISTER_SERVER_ID,
2172 NULL, &res, &timeout, NULL);
2173 if (ret != 0 || res != 0) {
2174 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for register server id failed\n"));
2182 unregister a server id
2184 int ctdb_ctrl_unregister_server_id(struct ctdb_context *ctdb,
2185 struct timeval timeout,
2186 struct ctdb_server_id *id)
2192 data.dsize = sizeof(struct ctdb_server_id);
2193 data.dptr = (unsigned char *)id;
2195 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0,
2196 CTDB_CONTROL_UNREGISTER_SERVER_ID,
2198 NULL, &res, &timeout, NULL);
2199 if (ret != 0 || res != 0) {
2200 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for unregister server id failed\n"));
2209 check if a server id exists
2211 if a server id does exist, return *status == 1, otherwise *status == 0
2213 int ctdb_ctrl_check_server_id(struct ctdb_context *ctdb,
2214 struct timeval timeout,
2216 struct ctdb_server_id *id,
2223 data.dsize = sizeof(struct ctdb_server_id);
2224 data.dptr = (unsigned char *)id;
2226 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_CHECK_SERVER_ID,
2228 NULL, &res, &timeout, NULL);
2230 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for check server id failed\n"));
2244 get the list of server ids that are registered on a node
2246 int ctdb_ctrl_get_server_id_list(struct ctdb_context *ctdb,
2247 TALLOC_CTX *mem_ctx,
2248 struct timeval timeout, uint32_t destnode,
2249 struct ctdb_server_id_list **svid_list)
2255 ret = ctdb_control(ctdb, destnode, 0,
2256 CTDB_CONTROL_GET_SERVER_ID_LIST, 0, tdb_null,
2257 mem_ctx, &outdata, &res, &timeout, NULL);
2258 if (ret != 0 || res != 0) {
2259 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for get_server_id_list failed\n"));
2263 *svid_list = (struct ctdb_server_id_list *)talloc_steal(mem_ctx, outdata.dptr);
2271 void ctdb_set_flags(struct ctdb_context *ctdb, unsigned flags)
2273 ctdb->flags |= flags;
2278 return the pnn of this node
2280 uint32_t ctdb_get_pnn(struct ctdb_context *ctdb)
2287 get the uptime of a remote node
2289 struct ctdb_client_control_state *
2290 ctdb_ctrl_uptime_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode)
2292 struct ctdb_client_control_state *state;
2294 state = ctdb_control_send(ctdb, destnode, 0,
2295 CTDB_CONTROL_UPTIME, 0, tdb_null,
2297 if (state != NULL && !timeval_is_zero(&timeout)) {
2298 event_add_timed(ctdb->ev, state, timeout, ctdb_control_timeout_func, state);
2304 int ctdb_ctrl_uptime_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, struct ctdb_uptime **uptime)
2310 ret = ctdb_control_recv(ctdb, state, mem_ctx, &outdata, &res, NULL);
2311 if (ret != 0 || res != 0) {
2312 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_uptime_recv failed\n"));
2316 *uptime = (struct ctdb_uptime *)talloc_steal(mem_ctx, outdata.dptr);
2321 int ctdb_ctrl_uptime(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode, struct ctdb_uptime **uptime)
2323 struct ctdb_client_control_state *state;
2325 state = ctdb_ctrl_uptime_send(ctdb, mem_ctx, timeout, destnode);
2326 return ctdb_ctrl_uptime_recv(ctdb, mem_ctx, state, uptime);
2330 send a control to execute the "recovered" event script on a node
2332 int ctdb_ctrl_end_recovery(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
2337 ret = ctdb_control(ctdb, destnode, 0,
2338 CTDB_CONTROL_END_RECOVERY, 0, tdb_null,
2339 NULL, NULL, &status, &timeout, NULL);
2340 if (ret != 0 || status != 0) {
2341 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for end_recovery failed\n"));
2349 callback for the async helpers used when sending the same control
2350 to multiple nodes in parallell.
2352 static void async_callback(struct ctdb_client_control_state *state)
2354 struct client_async_data *data = talloc_get_type(state->async.private_data, struct client_async_data);
2355 struct ctdb_context *ctdb = talloc_get_type(state->ctdb, struct ctdb_context);
2359 uint32_t destnode = state->c->hdr.destnode;
2361 /* one more node has responded with recmode data */
2364 /* if we failed to push the db, then return an error and let
2365 the main loop try again.
2367 if (state->state != CTDB_CONTROL_DONE) {
2368 if ( !data->dont_log_errors) {
2369 DEBUG(DEBUG_ERR,("Async operation failed with state %d, opcode:%u\n", state->state, data->opcode));
2372 if (data->fail_callback) {
2373 data->fail_callback(ctdb, destnode, res, outdata,
2374 data->callback_data);
2379 state->async.fn = NULL;
2381 ret = ctdb_control_recv(ctdb, state, data, &outdata, &res, NULL);
2382 if ((ret != 0) || (res != 0)) {
2383 if ( !data->dont_log_errors) {
2384 DEBUG(DEBUG_ERR,("Async operation failed with ret=%d res=%d opcode=%u\n", ret, (int)res, data->opcode));
2387 if (data->fail_callback) {
2388 data->fail_callback(ctdb, destnode, res, outdata,
2389 data->callback_data);
2392 if ((ret == 0) && (data->callback != NULL)) {
2393 data->callback(ctdb, destnode, res, outdata,
2394 data->callback_data);
2399 void ctdb_client_async_add(struct client_async_data *data, struct ctdb_client_control_state *state)
2401 /* set up the callback functions */
2402 state->async.fn = async_callback;
2403 state->async.private_data = data;
2405 /* one more control to wait for to complete */
2410 /* wait for up to the maximum number of seconds allowed
2411 or until all nodes we expect a response from has replied
2413 int ctdb_client_async_wait(struct ctdb_context *ctdb, struct client_async_data *data)
2415 while (data->count > 0) {
2416 event_loop_once(ctdb->ev);
2418 if (data->fail_count != 0) {
2419 if (!data->dont_log_errors) {
2420 DEBUG(DEBUG_ERR,("Async wait failed - fail_count=%u\n",
2430 perform a simple control on the listed nodes
2431 The control cannot return data
2433 int ctdb_client_async_control(struct ctdb_context *ctdb,
2434 enum ctdb_controls opcode,
2437 struct timeval timeout,
2438 bool dont_log_errors,
2440 client_async_callback client_callback,
2441 client_async_callback fail_callback,
2442 void *callback_data)
2444 struct client_async_data *async_data;
2445 struct ctdb_client_control_state *state;
2448 async_data = talloc_zero(ctdb, struct client_async_data);
2449 CTDB_NO_MEMORY_FATAL(ctdb, async_data);
2450 async_data->dont_log_errors = dont_log_errors;
2451 async_data->callback = client_callback;
2452 async_data->fail_callback = fail_callback;
2453 async_data->callback_data = callback_data;
2454 async_data->opcode = opcode;
2456 num_nodes = talloc_get_size(nodes) / sizeof(uint32_t);
2458 /* loop over all nodes and send an async control to each of them */
2459 for (j=0; j<num_nodes; j++) {
2460 uint32_t pnn = nodes[j];
2462 state = ctdb_control_send(ctdb, pnn, srvid, opcode,
2463 0, data, async_data, NULL);
2464 if (state == NULL) {
2465 DEBUG(DEBUG_ERR,(__location__ " Failed to call async control %u\n", (unsigned)opcode));
2466 talloc_free(async_data);
2469 if (!timeval_is_zero(&timeout)) {
2470 event_add_timed(ctdb->ev, state, timeout, ctdb_control_timeout_func, state);
2473 ctdb_client_async_add(async_data, state);
2476 if (ctdb_client_async_wait(ctdb, async_data) != 0) {
2477 talloc_free(async_data);
2481 talloc_free(async_data);
2485 uint32_t *list_of_vnnmap_nodes(struct ctdb_context *ctdb,
2486 struct ctdb_vnn_map *vnn_map,
2487 TALLOC_CTX *mem_ctx,
2490 int i, j, num_nodes;
2493 for (i=num_nodes=0;i<vnn_map->size;i++) {
2494 if (vnn_map->map[i] == ctdb->pnn && !include_self) {
2500 nodes = talloc_array(mem_ctx, uint32_t, num_nodes);
2501 CTDB_NO_MEMORY_FATAL(ctdb, nodes);
2503 for (i=j=0;i<vnn_map->size;i++) {
2504 if (vnn_map->map[i] == ctdb->pnn && !include_self) {
2507 nodes[j++] = vnn_map->map[i];
2513 uint32_t *list_of_active_nodes(struct ctdb_context *ctdb,
2514 struct ctdb_node_map *node_map,
2515 TALLOC_CTX *mem_ctx,
2518 int i, j, num_nodes;
2521 for (i=num_nodes=0;i<node_map->num;i++) {
2522 if (node_map->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2525 if (node_map->nodes[i].pnn == ctdb->pnn && !include_self) {
2531 nodes = talloc_array(mem_ctx, uint32_t, num_nodes);
2532 CTDB_NO_MEMORY_FATAL(ctdb, nodes);
2534 for (i=j=0;i<node_map->num;i++) {
2535 if (node_map->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2538 if (node_map->nodes[i].pnn == ctdb->pnn && !include_self) {
2541 nodes[j++] = node_map->nodes[i].pnn;
2547 uint32_t *list_of_active_nodes_except_pnn(struct ctdb_context *ctdb,
2548 struct ctdb_node_map *node_map,
2549 TALLOC_CTX *mem_ctx,
2552 int i, j, num_nodes;
2555 for (i=num_nodes=0;i<node_map->num;i++) {
2556 if (node_map->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2559 if (node_map->nodes[i].pnn == pnn) {
2565 nodes = talloc_array(mem_ctx, uint32_t, num_nodes);
2566 CTDB_NO_MEMORY_FATAL(ctdb, nodes);
2568 for (i=j=0;i<node_map->num;i++) {
2569 if (node_map->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2572 if (node_map->nodes[i].pnn == pnn) {
2575 nodes[j++] = node_map->nodes[i].pnn;
2581 uint32_t *list_of_connected_nodes(struct ctdb_context *ctdb,
2582 struct ctdb_node_map *node_map,
2583 TALLOC_CTX *mem_ctx,
2586 int i, j, num_nodes;
2589 for (i=num_nodes=0;i<node_map->num;i++) {
2590 if (node_map->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
2593 if (node_map->nodes[i].pnn == ctdb->pnn && !include_self) {
2599 nodes = talloc_array(mem_ctx, uint32_t, num_nodes);
2600 CTDB_NO_MEMORY_FATAL(ctdb, nodes);
2602 for (i=j=0;i<node_map->num;i++) {
2603 if (node_map->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
2606 if (node_map->nodes[i].pnn == ctdb->pnn && !include_self) {
2609 nodes[j++] = node_map->nodes[i].pnn;
2616 this is used to test if a pnn lock exists and if it exists will return
2617 the number of connections that pnn has reported or -1 if that recovery
2618 daemon is not running.
2621 ctdb_read_pnn_lock(int fd, int32_t pnn)
2626 lock.l_type = F_WRLCK;
2627 lock.l_whence = SEEK_SET;
2632 if (fcntl(fd, F_GETLK, &lock) != 0) {
2633 DEBUG(DEBUG_ERR, (__location__ " F_GETLK failed with %s\n", strerror(errno)));
2637 if (lock.l_type == F_UNLCK) {
2641 if (pread(fd, &c, 1, pnn) == -1) {
2642 DEBUG(DEBUG_CRIT,(__location__ " failed read pnn count - %s\n", strerror(errno)));
2650 get capabilities of a remote node
2652 struct ctdb_client_control_state *
2653 ctdb_ctrl_getcapabilities_send(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct timeval timeout, uint32_t destnode)
2655 struct ctdb_client_control_state *state;
2657 state = ctdb_control_send(ctdb, destnode, 0,
2658 CTDB_CONTROL_GET_CAPABILITIES, 0, tdb_null,
2660 if (state != NULL && !timeval_is_zero(&timeout)) {
2661 event_add_timed(ctdb->ev, state, timeout, ctdb_control_timeout_func, state);
2667 int ctdb_ctrl_getcapabilities_recv(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, struct ctdb_client_control_state *state, uint32_t *capabilities)
2673 ret = ctdb_control_recv(ctdb, state, mem_ctx, &outdata, &res, NULL);
2674 if ( (ret != 0) || (res != 0) ) {
2675 DEBUG(DEBUG_ERR,(__location__ " ctdb_ctrl_getcapabilities_recv failed\n"));
2680 *capabilities = *((uint32_t *)outdata.dptr);
2686 int ctdb_ctrl_getcapabilities(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t *capabilities)
2688 struct ctdb_client_control_state *state;
2689 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
2692 state = ctdb_ctrl_getcapabilities_send(ctdb, tmp_ctx, timeout, destnode);
2693 ret = ctdb_ctrl_getcapabilities_recv(ctdb, tmp_ctx, state, capabilities);
2694 talloc_free(tmp_ctx);
2699 * check whether a transaction is active on a given db on a given node
2701 int32_t ctdb_ctrl_transaction_active(struct ctdb_context *ctdb,
2709 indata.dptr = (uint8_t *)&db_id;
2710 indata.dsize = sizeof(db_id);
2712 ret = ctdb_control(ctdb, destnode, 0,
2713 CTDB_CONTROL_TRANS2_ACTIVE,
2714 0, indata, NULL, NULL, &status,
2718 DEBUG(DEBUG_ERR, (__location__ " ctdb control for transaction_active failed\n"));
2726 struct ctdb_transaction_handle {
2727 struct ctdb_db_context *ctdb_db;
2730 * we store the reads and writes done under a transaction:
2731 * - one list stores both reads and writes (m_all),
2732 * - the other just writes (m_write)
2734 struct ctdb_marshall_buffer *m_all;
2735 struct ctdb_marshall_buffer *m_write;
2738 /* start a transaction on a database */
2739 static int ctdb_transaction_destructor(struct ctdb_transaction_handle *h)
2741 tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
2745 /* start a transaction on a database */
2746 static int ctdb_transaction_fetch_start(struct ctdb_transaction_handle *h)
2748 struct ctdb_record_handle *rh;
2751 struct ctdb_ltdb_header header;
2752 TALLOC_CTX *tmp_ctx;
2753 const char *keyname = CTDB_TRANSACTION_LOCK_KEY;
2755 struct ctdb_db_context *ctdb_db = h->ctdb_db;
2759 key.dptr = discard_const(keyname);
2760 key.dsize = strlen(keyname);
2762 if (!ctdb_db->persistent) {
2763 DEBUG(DEBUG_ERR,(__location__ " Attempted transaction on non-persistent database\n"));
2768 tmp_ctx = talloc_new(h);
2770 rh = ctdb_fetch_lock(ctdb_db, tmp_ctx, key, NULL);
2772 DEBUG(DEBUG_ERR,(__location__ " Failed to fetch_lock database\n"));
2773 talloc_free(tmp_ctx);
2777 status = ctdb_ctrl_transaction_active(ctdb_db->ctdb,
2781 unsigned long int usec = (1000 + random()) % 100000;
2782 DEBUG(DEBUG_DEBUG, (__location__ " transaction is active "
2783 "on db_id[0x%08x]. waiting for %lu "
2785 ctdb_db->db_id, usec));
2786 talloc_free(tmp_ctx);
2792 * store the pid in the database:
2793 * it is not enough that the node is dmaster...
2796 data.dptr = (unsigned char *)&pid;
2797 data.dsize = sizeof(pid_t);
2799 rh->header.dmaster = ctdb_db->ctdb->pnn;
2800 ret = ctdb_ltdb_store(ctdb_db, key, &(rh->header), data);
2802 DEBUG(DEBUG_ERR, (__location__ " Failed to store pid in "
2803 "transaction record\n"));
2804 talloc_free(tmp_ctx);
2810 ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
2812 DEBUG(DEBUG_ERR,(__location__ " Failed to start tdb transaction\n"));
2813 talloc_free(tmp_ctx);
2817 ret = ctdb_ltdb_fetch(ctdb_db, key, &header, tmp_ctx, &data);
2819 DEBUG(DEBUG_ERR,(__location__ " Failed to re-fetch transaction "
2820 "lock record inside transaction\n"));
2821 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
2822 talloc_free(tmp_ctx);
2826 if (header.dmaster != ctdb_db->ctdb->pnn) {
2827 DEBUG(DEBUG_DEBUG,(__location__ " not dmaster any more on "
2828 "transaction lock record\n"));
2829 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
2830 talloc_free(tmp_ctx);
2834 if ((data.dsize != sizeof(pid_t)) || (*(pid_t *)(data.dptr) != pid)) {
2835 DEBUG(DEBUG_DEBUG, (__location__ " my pid is not stored in "
2836 "the transaction lock record\n"));
2837 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
2838 talloc_free(tmp_ctx);
2842 talloc_free(tmp_ctx);
2848 /* start a transaction on a database */
2849 struct ctdb_transaction_handle *ctdb_transaction_start(struct ctdb_db_context *ctdb_db,
2850 TALLOC_CTX *mem_ctx)
2852 struct ctdb_transaction_handle *h;
2855 h = talloc_zero(mem_ctx, struct ctdb_transaction_handle);
2857 DEBUG(DEBUG_ERR,(__location__ " oom for transaction handle\n"));
2861 h->ctdb_db = ctdb_db;
2863 ret = ctdb_transaction_fetch_start(h);
2869 talloc_set_destructor(h, ctdb_transaction_destructor);
2877 fetch a record inside a transaction
2879 int ctdb_transaction_fetch(struct ctdb_transaction_handle *h,
2880 TALLOC_CTX *mem_ctx,
2881 TDB_DATA key, TDB_DATA *data)
2883 struct ctdb_ltdb_header header;
2886 ZERO_STRUCT(header);
2888 ret = ctdb_ltdb_fetch(h->ctdb_db, key, &header, mem_ctx, data);
2889 if (ret == -1 && header.dmaster == (uint32_t)-1) {
2890 /* record doesn't exist yet */
2899 if (!h->in_replay) {
2900 h->m_all = ctdb_marshall_add(h, h->m_all, h->ctdb_db->db_id, 1, key, NULL, *data);
2901 if (h->m_all == NULL) {
2902 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
2911 stores a record inside a transaction
2913 int ctdb_transaction_store(struct ctdb_transaction_handle *h,
2914 TDB_DATA key, TDB_DATA data)
2916 TALLOC_CTX *tmp_ctx = talloc_new(h);
2917 struct ctdb_ltdb_header header;
2921 ZERO_STRUCT(header);
2923 /* we need the header so we can update the RSN */
2924 ret = ctdb_ltdb_fetch(h->ctdb_db, key, &header, tmp_ctx, &olddata);
2925 if (ret == -1 && header.dmaster == (uint32_t)-1) {
2926 /* the record doesn't exist - create one with us as dmaster.
2927 This is only safe because we are in a transaction and this
2928 is a persistent database */
2929 ZERO_STRUCT(header);
2930 } else if (ret != 0) {
2931 DEBUG(DEBUG_ERR,(__location__ " Failed to fetch record\n"));
2932 talloc_free(tmp_ctx);
2936 if (data.dsize == olddata.dsize &&
2937 memcmp(data.dptr, olddata.dptr, data.dsize) == 0) {
2938 /* save writing the same data */
2939 talloc_free(tmp_ctx);
2943 header.dmaster = h->ctdb_db->ctdb->pnn;
2946 if (!h->in_replay) {
2947 h->m_all = ctdb_marshall_add(h, h->m_all, h->ctdb_db->db_id, 0, key, NULL, data);
2948 if (h->m_all == NULL) {
2949 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
2950 talloc_free(tmp_ctx);
2955 h->m_write = ctdb_marshall_add(h, h->m_write, h->ctdb_db->db_id, 0, key, &header, data);
2956 if (h->m_write == NULL) {
2957 DEBUG(DEBUG_ERR,(__location__ " Failed to add to marshalling record\n"));
2958 talloc_free(tmp_ctx);
2962 ret = ctdb_ltdb_store(h->ctdb_db, key, &header, data);
2964 talloc_free(tmp_ctx);
2970 replay a transaction
2972 static int ctdb_replay_transaction(struct ctdb_transaction_handle *h)
2975 struct ctdb_rec_data *rec = NULL;
2977 h->in_replay = true;
2978 talloc_free(h->m_write);
2981 ret = ctdb_transaction_fetch_start(h);
2986 for (i=0;i<h->m_all->count;i++) {
2989 rec = ctdb_marshall_loop_next(h->m_all, rec, NULL, NULL, &key, &data);
2991 DEBUG(DEBUG_ERR, (__location__ " Out of records in ctdb_replay_transaction?\n"));
2995 if (rec->reqid == 0) {
2997 if (ctdb_transaction_store(h, key, data) != 0) {
3002 TALLOC_CTX *tmp_ctx = talloc_new(h);
3004 if (ctdb_transaction_fetch(h, tmp_ctx, key, &data2) != 0) {
3005 talloc_free(tmp_ctx);
3008 if (data2.dsize != data.dsize ||
3009 memcmp(data2.dptr, data.dptr, data.dsize) != 0) {
3010 /* the record has changed on us - we have to give up */
3011 talloc_free(tmp_ctx);
3014 talloc_free(tmp_ctx);
3021 tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
3027 commit a transaction
3029 int ctdb_transaction_commit(struct ctdb_transaction_handle *h)
3033 struct ctdb_context *ctdb = h->ctdb_db->ctdb;
3034 struct timeval timeout;
3035 enum ctdb_controls failure_control = CTDB_CONTROL_TRANS2_ERROR;
3037 talloc_set_destructor(h, NULL);
3039 /* our commit strategy is quite complex.
3041 - we first try to commit the changes to all other nodes
3043 - if that works, then we commit locally and we are done
3045 - if a commit on another node fails, then we need to cancel
3046 the transaction, then restart the transaction (thus
3047 opening a window of time for a pending recovery to
3048 complete), then replay the transaction, checking all the
3049 reads and writes (checking that reads give the same data,
3050 and writes succeed). Then we retry the transaction to the
3055 if (h->m_write == NULL) {
3056 /* no changes were made */
3057 tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
3062 /* tell ctdbd to commit to the other nodes */
3063 timeout = timeval_current_ofs(1, 0);
3064 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
3065 retries==0?CTDB_CONTROL_TRANS2_COMMIT:CTDB_CONTROL_TRANS2_COMMIT_RETRY, 0,
3066 ctdb_marshall_finish(h->m_write), NULL, NULL, &status,
3068 if (ret != 0 || status != 0) {
3069 tdb_transaction_cancel(h->ctdb_db->ltdb->tdb);
3070 DEBUG(DEBUG_NOTICE, (__location__ " transaction commit%s failed"
3071 ", retrying after 1 second...\n",
3072 (retries==0)?"":"retry "));
3076 failure_control = CTDB_CONTROL_TRANS2_ERROR;
3078 /* work out what error code we will give if we
3079 have to fail the operation */
3080 switch ((enum ctdb_trans2_commit_error)status) {
3081 case CTDB_TRANS2_COMMIT_SUCCESS:
3082 case CTDB_TRANS2_COMMIT_SOMEFAIL:
3083 case CTDB_TRANS2_COMMIT_TIMEOUT:
3084 failure_control = CTDB_CONTROL_TRANS2_ERROR;
3086 case CTDB_TRANS2_COMMIT_ALLFAIL:
3087 failure_control = CTDB_CONTROL_TRANS2_FINISHED;
3092 if (++retries == 100) {
3093 DEBUG(DEBUG_ERR,(__location__ " Giving up transaction on db 0x%08x after %d retries failure_control=%u\n",
3094 h->ctdb_db->db_id, retries, (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 if (ctdb_replay_transaction(h) != 0) {
3103 DEBUG(DEBUG_ERR, (__location__ " Failed to replay "
3104 "transaction on db 0x%08x, "
3105 "failure control =%u\n",
3107 (unsigned)failure_control));
3108 ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
3109 failure_control, CTDB_CTRL_FLAG_NOREPLY,
3110 tdb_null, NULL, NULL, NULL, NULL, NULL);
3116 failure_control = CTDB_CONTROL_TRANS2_ERROR;
3119 /* do the real commit locally */
3120 ret = tdb_transaction_commit(h->ctdb_db->ltdb->tdb);
3122 DEBUG(DEBUG_ERR, (__location__ " Failed to commit transaction "
3123 "on db id 0x%08x locally, "
3124 "failure_control=%u\n",
3126 (unsigned)failure_control));
3127 ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
3128 failure_control, CTDB_CTRL_FLAG_NOREPLY,
3129 tdb_null, NULL, NULL, NULL, NULL, NULL);
3134 /* tell ctdbd that we are finished with our local commit */
3135 ctdb_control(ctdb, CTDB_CURRENT_NODE, h->ctdb_db->db_id,
3136 CTDB_CONTROL_TRANS2_FINISHED, CTDB_CTRL_FLAG_NOREPLY,
3137 tdb_null, NULL, NULL, NULL, NULL, NULL);
3143 recovery daemon ping to main daemon
3145 int ctdb_ctrl_recd_ping(struct ctdb_context *ctdb)
3150 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_RECD_PING, 0, tdb_null,
3151 ctdb, NULL, &res, NULL, NULL);
3152 if (ret != 0 || res != 0) {
3153 DEBUG(DEBUG_ERR,("Failed to send recd ping\n"));
3160 /* when forking the main daemon and the child process needs to connect back
3161 * to the daemon as a client process, this function can be used to change
3162 * the ctdb context from daemon into client mode
3164 int switch_from_server_to_client(struct ctdb_context *ctdb)
3168 /* shutdown the transport */
3169 if (ctdb->methods) {
3170 ctdb->methods->shutdown(ctdb);
3173 /* get a new event context */
3174 talloc_free(ctdb->ev);
3175 ctdb->ev = event_context_init(ctdb);
3177 close(ctdb->daemon.sd);
3178 ctdb->daemon.sd = -1;
3180 /* initialise ctdb */
3181 ret = ctdb_socket_connect(ctdb);
3183 DEBUG(DEBUG_ALERT, (__location__ " Failed to init ctdb client\n"));
3191 get the status of running the monitor eventscripts: NULL means never run.
3193 int ctdb_ctrl_getscriptstatus(struct ctdb_context *ctdb,
3194 struct timeval timeout, uint32_t destnode,
3195 TALLOC_CTX *mem_ctx, enum ctdb_eventscript_call type,
3196 struct ctdb_scripts_wire **script_status)
3199 TDB_DATA outdata, indata;
3201 uint32_t uinttype = type;
3203 indata.dptr = (uint8_t *)&uinttype;
3204 indata.dsize = sizeof(uinttype);
3206 ret = ctdb_control(ctdb, destnode, 0,
3207 CTDB_CONTROL_GET_EVENT_SCRIPT_STATUS, 0, indata,
3208 mem_ctx, &outdata, &res, &timeout, NULL);
3209 if (ret != 0 || res != 0) {
3210 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for getscriptstatus failed ret:%d res:%d\n", ret, res));
3214 if (outdata.dsize == 0) {
3215 *script_status = NULL;
3217 *script_status = (struct ctdb_scripts_wire *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
3218 talloc_free(outdata.dptr);
3225 tell the main daemon how long it took to lock the reclock file
3227 int ctdb_ctrl_report_recd_lock_latency(struct ctdb_context *ctdb, struct timeval timeout, double latency)
3233 data.dptr = (uint8_t *)&latency;
3234 data.dsize = sizeof(latency);
3236 ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_RECD_RECLOCK_LATENCY, 0, data,
3237 ctdb, NULL, &res, NULL, NULL);
3238 if (ret != 0 || res != 0) {
3239 DEBUG(DEBUG_ERR,("Failed to send recd reclock latency\n"));
3247 get the name of the reclock file
3249 int ctdb_ctrl_getreclock(struct ctdb_context *ctdb, struct timeval timeout,
3250 uint32_t destnode, TALLOC_CTX *mem_ctx,
3257 ret = ctdb_control(ctdb, destnode, 0,
3258 CTDB_CONTROL_GET_RECLOCK_FILE, 0, tdb_null,
3259 mem_ctx, &data, &res, &timeout, NULL);
3260 if (ret != 0 || res != 0) {
3264 if (data.dsize == 0) {
3267 *name = talloc_strdup(mem_ctx, discard_const(data.dptr));
3269 talloc_free(data.dptr);
3275 set the reclock filename for a node
3277 int ctdb_ctrl_setreclock(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, const char *reclock)
3283 if (reclock == NULL) {
3287 data.dsize = strlen(reclock) + 1;
3288 data.dptr = discard_const(reclock);
3291 ret = ctdb_control(ctdb, destnode, 0,
3292 CTDB_CONTROL_SET_RECLOCK_FILE, 0, data,
3293 NULL, NULL, &res, &timeout, NULL);
3294 if (ret != 0 || res != 0) {
3295 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setreclock failed\n"));
3305 int ctdb_ctrl_stop_node(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
3310 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_STOP_NODE, 0, tdb_null,
3311 ctdb, NULL, &res, &timeout, NULL);
3312 if (ret != 0 || res != 0) {
3313 DEBUG(DEBUG_ERR,("Failed to stop node\n"));
3323 int ctdb_ctrl_continue_node(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode)
3327 ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_CONTINUE_NODE, 0, tdb_null,
3328 ctdb, NULL, NULL, &timeout, NULL);
3330 DEBUG(DEBUG_ERR,("Failed to continue node\n"));
3338 set the natgw state for a node
3340 int ctdb_ctrl_setnatgwstate(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t natgwstate)
3346 data.dsize = sizeof(natgwstate);
3347 data.dptr = (uint8_t *)&natgwstate;
3349 ret = ctdb_control(ctdb, destnode, 0,
3350 CTDB_CONTROL_SET_NATGWSTATE, 0, data,
3351 NULL, NULL, &res, &timeout, NULL);
3352 if (ret != 0 || res != 0) {
3353 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setnatgwstate failed\n"));
3361 set the lmaster role for a node
3363 int ctdb_ctrl_setlmasterrole(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t lmasterrole)
3369 data.dsize = sizeof(lmasterrole);
3370 data.dptr = (uint8_t *)&lmasterrole;
3372 ret = ctdb_control(ctdb, destnode, 0,
3373 CTDB_CONTROL_SET_LMASTERROLE, 0, data,
3374 NULL, NULL, &res, &timeout, NULL);
3375 if (ret != 0 || res != 0) {
3376 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setlmasterrole failed\n"));
3384 set the recmaster role for a node
3386 int ctdb_ctrl_setrecmasterrole(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t recmasterrole)
3392 data.dsize = sizeof(recmasterrole);
3393 data.dptr = (uint8_t *)&recmasterrole;
3395 ret = ctdb_control(ctdb, destnode, 0,
3396 CTDB_CONTROL_SET_RECMASTERROLE, 0, data,
3397 NULL, NULL, &res, &timeout, NULL);
3398 if (ret != 0 || res != 0) {
3399 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for setrecmasterrole failed\n"));
3406 /* enable an eventscript
3408 int ctdb_ctrl_enablescript(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, const char *script)
3414 data.dsize = strlen(script) + 1;
3415 data.dptr = discard_const(script);
3417 ret = ctdb_control(ctdb, destnode, 0,
3418 CTDB_CONTROL_ENABLE_SCRIPT, 0, data,
3419 NULL, NULL, &res, &timeout, NULL);
3420 if (ret != 0 || res != 0) {
3421 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for enablescript failed\n"));
3428 /* disable an eventscript
3430 int ctdb_ctrl_disablescript(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, const char *script)
3436 data.dsize = strlen(script) + 1;
3437 data.dptr = discard_const(script);
3439 ret = ctdb_control(ctdb, destnode, 0,
3440 CTDB_CONTROL_DISABLE_SCRIPT, 0, data,
3441 NULL, NULL, &res, &timeout, NULL);
3442 if (ret != 0 || res != 0) {
3443 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for disablescript failed\n"));
3451 int ctdb_ctrl_set_ban(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, struct ctdb_ban_time *bantime)
3457 data.dsize = sizeof(*bantime);
3458 data.dptr = (uint8_t *)bantime;
3460 ret = ctdb_control(ctdb, destnode, 0,
3461 CTDB_CONTROL_SET_BAN_STATE, 0, data,
3462 NULL, NULL, &res, &timeout, NULL);
3463 if (ret != 0 || res != 0) {
3464 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set ban state failed\n"));
3472 int ctdb_ctrl_get_ban(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_ban_time **bantime)
3477 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
3479 ret = ctdb_control(ctdb, destnode, 0,
3480 CTDB_CONTROL_GET_BAN_STATE, 0, tdb_null,
3481 tmp_ctx, &outdata, &res, &timeout, NULL);
3482 if (ret != 0 || res != 0) {
3483 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set ban state failed\n"));
3484 talloc_free(tmp_ctx);
3488 *bantime = (struct ctdb_ban_time *)talloc_steal(mem_ctx, outdata.dptr);
3489 talloc_free(tmp_ctx);
3495 int ctdb_ctrl_set_db_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, struct ctdb_db_priority *db_prio)
3500 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
3502 data.dptr = (uint8_t*)db_prio;
3503 data.dsize = sizeof(*db_prio);
3505 ret = ctdb_control(ctdb, destnode, 0,
3506 CTDB_CONTROL_SET_DB_PRIORITY, 0, data,
3507 tmp_ctx, NULL, &res, &timeout, NULL);
3508 if (ret != 0 || res != 0) {
3509 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set_db_priority failed\n"));
3510 talloc_free(tmp_ctx);
3514 talloc_free(tmp_ctx);
3519 int ctdb_ctrl_get_db_priority(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, uint32_t db_id, uint32_t *priority)
3524 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
3526 data.dptr = (uint8_t*)&db_id;
3527 data.dsize = sizeof(db_id);
3529 ret = ctdb_control(ctdb, destnode, 0,
3530 CTDB_CONTROL_GET_DB_PRIORITY, 0, data,
3531 tmp_ctx, NULL, &res, &timeout, NULL);
3532 if (ret != 0 || res < 0) {
3533 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set_db_priority failed\n"));
3534 talloc_free(tmp_ctx);
3542 talloc_free(tmp_ctx);
3547 /* time out handler for ctdb_control */
3548 void ctdb_control_timeout_func(struct event_context *ev, struct timed_event *te,
3549 struct timeval t, void *private_data)
3551 struct ctdb_client_control_state *state = talloc_get_type(private_data, struct ctdb_client_control_state);
3553 DEBUG(DEBUG_ERR,(__location__ " control timed out. reqid:%u opcode:%u "
3554 "dstnode:%u\n", state->reqid, state->c->opcode,
3555 state->c->hdr.destnode));
3557 state->state = CTDB_CONTROL_TIMEOUT;
3559 /* if we had a callback registered for this control, pull the response
3560 and call the callback.
3562 if (state->async.fn) {
3563 event_add_timed(state->ctdb->ev, state, timeval_zero(), ctdb_invoke_control_callback, state);