summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2007-06-04 19:53:19 +1000
committerAndrew Tridgell <tridge@samba.org>2007-06-04 19:53:19 +1000
commitdbb2ec43dda8287996dd110ff610364f0bfac712 (patch)
tree5716c432a8921e7b4862406fb0fc8c104949bfee
parentf1d81386e684c8adb6cadd2ae56aa166aef6b5f2 (diff)
downloadsamba-dbb2ec43dda8287996dd110ff610364f0bfac712.tar.gz
added tunables settable using ctdb command line tool
(This used to be ctdb commit 73d440f8cb19373cfad7a2f0f0ca4f963c57ff29)
-rw-r--r--ctdb/.bzrignore2
-rw-r--r--ctdb/Makefile.in3
-rw-r--r--ctdb/common/ctdb_client.c125
-rw-r--r--ctdb/common/ctdb_control.c9
-rw-r--r--ctdb/common/ctdb_tunables.c142
-rw-r--r--ctdb/config/events.d/README4
-rw-r--r--ctdb/include/ctdb.h18
-rw-r--r--ctdb/include/ctdb_private.h35
-rwxr-xr-xctdb/tests/ctdbd.sh6
-rwxr-xr-xctdb/tests/start_daemons.sh6
-rw-r--r--ctdb/tools/ctdb_control.c75
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>"},