diff options
author | Andrew Tridgell <tridge@samba.org> | 2007-06-04 19:53:19 +1000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2007-06-04 19:53:19 +1000 |
commit | dbb2ec43dda8287996dd110ff610364f0bfac712 (patch) | |
tree | 5716c432a8921e7b4862406fb0fc8c104949bfee | |
parent | f1d81386e684c8adb6cadd2ae56aa166aef6b5f2 (diff) | |
download | samba-dbb2ec43dda8287996dd110ff610364f0bfac712.tar.gz |
added tunables settable using ctdb command line tool
(This used to be ctdb commit 73d440f8cb19373cfad7a2f0f0ca4f963c57ff29)
-rw-r--r-- | ctdb/.bzrignore | 2 | ||||
-rw-r--r-- | ctdb/Makefile.in | 3 | ||||
-rw-r--r-- | ctdb/common/ctdb_client.c | 125 | ||||
-rw-r--r-- | ctdb/common/ctdb_control.c | 9 | ||||
-rw-r--r-- | ctdb/common/ctdb_tunables.c | 142 | ||||
-rw-r--r-- | ctdb/config/events.d/README | 4 | ||||
-rw-r--r-- | ctdb/include/ctdb.h | 18 | ||||
-rw-r--r-- | ctdb/include/ctdb_private.h | 35 | ||||
-rwxr-xr-x | ctdb/tests/ctdbd.sh | 6 | ||||
-rwxr-xr-x | ctdb/tests/start_daemons.sh | 6 | ||||
-rw-r--r-- | ctdb/tools/ctdb_control.c | 75 |
11 files changed, 422 insertions, 3 deletions
diff --git a/ctdb/.bzrignore b/ctdb/.bzrignore index 9ec7f5dd7b7..6d05088146e 100644 --- a/ctdb/.bzrignore +++ b/ctdb/.bzrignore @@ -17,3 +17,5 @@ ctdb-3 nodes.txt TAGS web/packages +rec.lock +test.db diff --git a/ctdb/Makefile.in b/ctdb/Makefile.in index 7d1cee1e429..56c3391927e 100644 --- a/ctdb/Makefile.in +++ b/ctdb/Makefile.in @@ -33,7 +33,8 @@ CTDB_COMMON_OBJ = common/ctdb.o common/ctdb_daemon.o common/ctdb_client.o \ common/ctdb_call.o common/ctdb_ltdb.o common/ctdb_lockwait.o \ common/ctdb_message.o common/cmdline.o common/ctdb_control.o \ lib/util/debug.o common/ctdb_recover.o common/ctdb_recoverd.o \ - common/ctdb_freeze.o common/ctdb_traverse.o common/ctdb_monitor.o + common/ctdb_freeze.o common/ctdb_traverse.o common/ctdb_monitor.o \ + common/ctdb_tunables.o CTDB_TAKEOVER_OBJ = takeover/system.o takeover/ctdb_takeover.o diff --git a/ctdb/common/ctdb_client.c b/ctdb/common/ctdb_client.c index afc968d81cc..b1abadc21c4 100644 --- a/ctdb/common/ctdb_client.c +++ b/ctdb/common/ctdb_client.c @@ -1813,3 +1813,128 @@ int ctdb_ctrl_release_ip(struct ctdb_context *ctdb, struct timeval timeout, return 0; } + +/* + get a tunable + */ +int ctdb_ctrl_get_tunable(struct ctdb_context *ctdb, + struct timeval timeout, + uint32_t destnode, + const char *name, uint32_t *value) +{ + struct ctdb_control_get_tunable *t; + TDB_DATA data, outdata; + int32_t res; + int ret; + + data.dsize = offsetof(struct ctdb_control_get_tunable, name) + strlen(name) + 1; + data.dptr = talloc_size(ctdb, data.dsize); + CTDB_NO_MEMORY(ctdb, data.dptr); + + t = (struct ctdb_control_get_tunable *)data.dptr; + t->length = strlen(name)+1; + memcpy(t->name, name, t->length); + + ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_TUNABLE, 0, data, ctdb, + &outdata, &res, &timeout, NULL); + talloc_free(data.dptr); + if (ret != 0 || res != 0) { + DEBUG(0,(__location__ " ctdb_control for get_tunable failed\n")); + return -1; + } + + if (outdata.dsize != sizeof(uint32_t)) { + DEBUG(0,("Invalid return data in get_tunable\n")); + talloc_free(outdata.dptr); + return -1; + } + + *value = *(uint32_t *)outdata.dptr; + talloc_free(outdata.dptr); + + return 0; +} + +/* + set a tunable + */ +int ctdb_ctrl_set_tunable(struct ctdb_context *ctdb, + struct timeval timeout, + uint32_t destnode, + const char *name, uint32_t value) +{ + struct ctdb_control_set_tunable *t; + TDB_DATA data; + int32_t res; + int ret; + + data.dsize = offsetof(struct ctdb_control_set_tunable, name) + strlen(name) + 1; + data.dptr = talloc_size(ctdb, data.dsize); + CTDB_NO_MEMORY(ctdb, data.dptr); + + t = (struct ctdb_control_set_tunable *)data.dptr; + t->length = strlen(name)+1; + memcpy(t->name, name, t->length); + t->value = value; + + ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SET_TUNABLE, 0, data, NULL, + NULL, &res, &timeout, NULL); + talloc_free(data.dptr); + if (ret != 0 || res != 0) { + DEBUG(0,(__location__ " ctdb_control for set_tunable failed\n")); + return -1; + } + + return 0; +} + +/* + list tunables + */ +int ctdb_ctrl_list_tunables(struct ctdb_context *ctdb, + struct timeval timeout, + uint32_t destnode, + TALLOC_CTX *mem_ctx, + const char ***list, uint32_t *count) +{ + TDB_DATA outdata; + int32_t res; + int ret; + struct ctdb_control_list_tunable *t; + char *p, *s, *ptr; + + ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_LIST_TUNABLES, 0, tdb_null, + mem_ctx, &outdata, &res, &timeout, NULL); + if (ret != 0 || res != 0) { + DEBUG(0,(__location__ " ctdb_control for list_tunables failed\n")); + return -1; + } + + t = (struct ctdb_control_list_tunable *)outdata.dptr; + if (outdata.dsize < offsetof(struct ctdb_control_list_tunable, data) || + t->length > outdata.dsize-offsetof(struct ctdb_control_list_tunable, data)) { + DEBUG(0,("Invalid data in list_tunables reply\n")); + talloc_free(outdata.dptr); + return -1; + } + + p = talloc_strndup(mem_ctx, (char *)t->data, t->length); + CTDB_NO_MEMORY(ctdb, p); + + talloc_free(outdata.dptr); + + (*list) = NULL; + (*count) = 0; + + for (s=strtok_r(p, ":", &ptr); s; s=strtok_r(NULL, ":", &ptr)) { + (*list) = talloc_realloc(mem_ctx, *list, const char *, 1+(*count)); + CTDB_NO_MEMORY(ctdb, *list); + (*list)[*count] = talloc_strdup(*list, s); + CTDB_NO_MEMORY(ctdb, (*list)[*count]); + (*count)++; + } + + talloc_free(p); + + return 0; +} diff --git a/ctdb/common/ctdb_control.c b/ctdb/common/ctdb_control.c index 7d2af014b12..188ebd77191 100644 --- a/ctdb/common/ctdb_control.c +++ b/ctdb/common/ctdb_control.c @@ -279,6 +279,15 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb, CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_control_tcp_vnn)); return ctdb_control_tcp_remove(ctdb, indata); + case CTDB_CONTROL_SET_TUNABLE: + return ctdb_control_set_tunable(ctdb, indata); + + case CTDB_CONTROL_GET_TUNABLE: + return ctdb_control_get_tunable(ctdb, indata, outdata); + + case CTDB_CONTROL_LIST_TUNABLES: + return ctdb_control_list_tunables(ctdb, outdata); + default: DEBUG(0,(__location__ " Unknown CTDB control opcode %u\n", opcode)); return -1; diff --git a/ctdb/common/ctdb_tunables.c b/ctdb/common/ctdb_tunables.c new file mode 100644 index 00000000000..912d12a4a44 --- /dev/null +++ b/ctdb/common/ctdb_tunables.c @@ -0,0 +1,142 @@ +/* + ctdb tunables code + + Copyright (C) Andrew Tridgell 2007 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#include "includes.h" +#include "../include/ctdb_private.h" + +static const struct { + const char *name; + size_t offset; +} tunable_map[] = { + { "MaxRedirectCount", offsetof(struct ctdb_tunable, max_redirect_count) }, + { "SeqnumFrequency", offsetof(struct ctdb_tunable, seqnum_frequency) }, + { "ControlTimeout", offsetof(struct ctdb_tunable, control_timeout) }, + { "TraverseTimeout", offsetof(struct ctdb_tunable, traverse_timeout) }, + { "MonitoringTimeout", offsetof(struct ctdb_tunable, monitoring_timeout) }, + { "MonitoringLimit", offsetof(struct ctdb_tunable, monitoring_limit) }, + { "MaxLACount", offsetof(struct ctdb_tunable, max_lacount) }, +}; + + +/* + get a tunable + */ +int32_t ctdb_control_get_tunable(struct ctdb_context *ctdb, TDB_DATA indata, + TDB_DATA *outdata) +{ + struct ctdb_control_get_tunable *t = + (struct ctdb_control_get_tunable *)indata.dptr; + char *name; + uint32_t val; + int i; + + if (indata.dsize < sizeof(*t) || + t->length > indata.dsize - offsetof(struct ctdb_control_get_tunable, name)) { + DEBUG(0,("Bad indata in ctdb_control_get_tunable\n")); + return -1; + } + + name = talloc_strndup(ctdb, (char*)t->name, t->length); + CTDB_NO_MEMORY(ctdb, name); + + for (i=0;i<ARRAY_SIZE(tunable_map);i++) { + if (strcasecmp(name, tunable_map[i].name) == 0) break; + } + talloc_free(name); + + if (i == ARRAY_SIZE(tunable_map)) { + return -1; + } + + val = *(uint32_t *)(tunable_map[i].offset + (uint8_t*)&ctdb->tunable); + + outdata->dptr = (uint8_t *)talloc(outdata, uint32_t); + CTDB_NO_MEMORY(ctdb, outdata->dptr); + + *(uint32_t *)outdata->dptr = val; + outdata->dsize = sizeof(uint32_t); + + return 0; +} + + +/* + set a tunable + */ +int32_t ctdb_control_set_tunable(struct ctdb_context *ctdb, TDB_DATA indata) +{ + struct ctdb_control_set_tunable *t = + (struct ctdb_control_set_tunable *)indata.dptr; + char *name; + int i; + + if (indata.dsize < sizeof(*t) || + t->length > indata.dsize - offsetof(struct ctdb_control_set_tunable, name)) { + DEBUG(0,("Bad indata in ctdb_control_set_tunable\n")); + return -1; + } + + name = talloc_strndup(ctdb, (char *)t->name, t->length); + CTDB_NO_MEMORY(ctdb, name); + + for (i=0;i<ARRAY_SIZE(tunable_map);i++) { + if (strcasecmp(name, tunable_map[i].name) == 0) break; + } + + talloc_free(name); + + if (i == ARRAY_SIZE(tunable_map)) { + return -1; + } + + *(uint32_t *)(tunable_map[i].offset + (uint8_t*)&ctdb->tunable) = t->value; + + return 0; +} + +/* + list tunables + */ +int32_t ctdb_control_list_tunables(struct ctdb_context *ctdb, TDB_DATA *outdata) +{ + char *list = NULL; + int i; + struct ctdb_control_list_tunable *t; + + list = talloc_strdup(outdata, tunable_map[0].name); + CTDB_NO_MEMORY(ctdb, list); + + for (i=1;i<ARRAY_SIZE(tunable_map);i++) { + list = talloc_asprintf_append(list, ":%s", tunable_map[i].name); + CTDB_NO_MEMORY(ctdb, list); + } + + outdata->dsize = offsetof(struct ctdb_control_list_tunable, data) + + strlen(list) + 1; + outdata->dptr = talloc_size(outdata, outdata->dsize); + CTDB_NO_MEMORY(ctdb, outdata->dptr); + + t = (struct ctdb_control_list_tunable *)outdata->dptr; + t->length = strlen(list)+1; + + memcpy(t->data, list, t->length); + talloc_free(list); + + return 0; +} diff --git a/ctdb/config/events.d/README b/ctdb/config/events.d/README new file mode 100644 index 00000000000..531e6453db9 --- /dev/null +++ b/ctdb/config/events.d/README @@ -0,0 +1,4 @@ +This directory is where you should put any local or application +specific event scripts for ctdb to call. + + diff --git a/ctdb/include/ctdb.h b/ctdb/include/ctdb.h index d8e32161d27..74039420fa6 100644 --- a/ctdb/include/ctdb.h +++ b/ctdb/include/ctdb.h @@ -340,4 +340,22 @@ int ctdb_ctrl_thaw(struct ctdb_context *ctdb, struct timeval timeout, uint32_t d int ctdb_ctrl_getvnn(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode); +int ctdb_ctrl_get_tunable(struct ctdb_context *ctdb, + struct timeval timeout, + uint32_t destnode, + const char *name, uint32_t *value); + +int ctdb_ctrl_set_tunable(struct ctdb_context *ctdb, + struct timeval timeout, + uint32_t destnode, + const char *name, uint32_t value); + +int ctdb_ctrl_list_tunables(struct ctdb_context *ctdb, + struct timeval timeout, + uint32_t destnode, + TALLOC_CTX *mem_ctx, + const char ***list, uint32_t *count); + + + #endif diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h index d7f2b32cea5..75126b21153 100644 --- a/ctdb/include/ctdb_private.h +++ b/ctdb/include/ctdb_private.h @@ -400,6 +400,9 @@ enum ctdb_controls {CTDB_CONTROL_PROCESS_EXISTS = 0, CTDB_CONTROL_TCP_ADD = 45, CTDB_CONTROL_TCP_REMOVE = 46, CTDB_CONTROL_STARTUP = 47, + CTDB_CONTROL_SET_TUNABLE = 48, + CTDB_CONTROL_GET_TUNABLE = 49, + CTDB_CONTROL_LIST_TUNABLES = 50, }; /* @@ -822,6 +825,33 @@ struct ctdb_control_set_dmaster { uint32_t dmaster; }; +/* + structure for setting a tunable + */ +struct ctdb_control_set_tunable { + uint32_t value; + uint32_t length; + uint8_t name[1]; +}; + +/* + structure for getting a tunable + */ +struct ctdb_control_get_tunable { + uint32_t length; + uint8_t name[1]; +}; + +/* + structure for listing tunables + */ +struct ctdb_control_list_tunable { + uint32_t length; + /* returns a : separated list of tunable names */ + uint8_t data[1]; +}; + + /* table that contains a list of all nodes a ctdb knows about and their status */ @@ -936,4 +966,9 @@ bool ctdb_recovery_lock(struct ctdb_context *ctdb, bool keep); int ctdb_set_recovery_lock_file(struct ctdb_context *ctdb, const char *file); +int32_t ctdb_control_get_tunable(struct ctdb_context *ctdb, TDB_DATA indata, + TDB_DATA *outdata); +int32_t ctdb_control_set_tunable(struct ctdb_context *ctdb, TDB_DATA indata); +int32_t ctdb_control_list_tunables(struct ctdb_context *ctdb, TDB_DATA *outdata); + #endif diff --git a/ctdb/tests/ctdbd.sh b/ctdb/tests/ctdbd.sh index 29777516bdf..4a1e9976b20 100755 --- a/ctdb/tests/ctdbd.sh +++ b/ctdb/tests/ctdbd.sh @@ -32,6 +32,12 @@ $VALGRIND bin/ctdb getdbmap || exit 1 echo "Testing status" $VALGRIND bin/ctdb status || exit 1 +echo "Testing variables" +$VALGRIND bin/ctdb listvars || exit 1 +$VALGRIND bin/ctdb getvar TraverseTimeout || exit 1 +$VALGRIND bin/ctdb setvar TraverseTimeout 10 || exit 1 +$VALGRIND bin/ctdb getvar TraverseTimeout || exit 1 + sleep 1 echo "Testing shutdown" diff --git a/ctdb/tests/start_daemons.sh b/ctdb/tests/start_daemons.sh index e902ae45f48..fcc53cecc10 100755 --- a/ctdb/tests/start_daemons.sh +++ b/ctdb/tests/start_daemons.sh @@ -3,17 +3,19 @@ NUMNODES="$1" NODES=$2 -pkill -f ctdbd +killall -q ctdbd echo "Starting $NUMNODES ctdb daemons" for i in `seq 1 $NUMNODES`; do $VALGRIND bin/ctdbd --reclock=rec.lock --nlist $NODES --event-script=tests/events --logfile=- --socket=sock.$i --dbdir=test.db || exit 1 done -ln -sf sock.1 /tmp/ctdb.socket || exit 1 +ln -sf $PWD/sock.1 /tmp/ctdb.socket || exit 1 while bin/ctdb status | grep RECOVERY > /dev/null; do echo "`date` Waiting for recovery" sleep 1; done +echo "$NUMNODES daemons started" + exit 0 diff --git a/ctdb/tools/ctdb_control.c b/ctdb/tools/ctdb_control.c index 34080bc50b5..ec23ccac185 100644 --- a/ctdb/tools/ctdb_control.c +++ b/ctdb/tools/ctdb_control.c @@ -518,6 +518,78 @@ static int control_ping(struct ctdb_context *ctdb, int argc, const char **argv) /* + get a tunable + */ +static int control_getvar(struct ctdb_context *ctdb, int argc, const char **argv) +{ + const char *name; + uint32_t value; + int ret; + + if (argc < 1) { + usage(); + } + + name = argv[0]; + ret = ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.vnn, name, &value); + if (ret == -1) { + printf("Unable to get tunable variable '%s'\n", name); + return -1; + } + + printf("%-17s = %u\n", name, value); + return 0; +} + +/* + set a tunable + */ +static int control_setvar(struct ctdb_context *ctdb, int argc, const char **argv) +{ + const char *name; + uint32_t value; + int ret; + + if (argc < 2) { + usage(); + } + + name = argv[0]; + value = strtoul(argv[1], NULL, 0); + + ret = ctdb_ctrl_set_tunable(ctdb, TIMELIMIT(), options.vnn, name, value); + if (ret == -1) { + printf("Unable to set tunable variable '%s'\n", name); + return -1; + } + return 0; +} + +/* + list all tunables + */ +static int control_listvars(struct ctdb_context *ctdb, int argc, const char **argv) +{ + uint32_t count; + const char **list; + int ret, i; + + ret = ctdb_ctrl_list_tunables(ctdb, TIMELIMIT(), options.vnn, ctdb, &list, &count); + if (ret == -1) { + printf("Unable to list tunable variables\n"); + return -1; + } + + for (i=0;i<count;i++) { + control_getvar(ctdb, 1, &list[i]); + } + + talloc_free(list); + + return 0; +} + +/* display debug level on a node */ static int control_getdebug(struct ctdb_context *ctdb, int argc, const char **argv) @@ -702,6 +774,9 @@ static const struct { } ctdb_commands[] = { { "status", control_status, "show node status" }, { "ping", control_ping, "ping all nodes" }, + { "getvar", control_getvar, "get a tunable variable", "<name>"}, + { "setvar", control_setvar, "set a tunable variable", "<name> <value>"}, + { "listvars", control_listvars, "list tunable variables"}, { "statistics", control_statistics, "show statistics" }, { "statisticsreset", control_statistics_reset, "reset statistics"}, { "process-exists", control_process_exists, "check if a process exists on a node", "<pid>"}, |