]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
added tunables settable using ctdb command line tool
authorAndrew Tridgell <tridge@samba.org>
Mon, 4 Jun 2007 09:53:19 +0000 (19:53 +1000)
committerAndrew Tridgell <tridge@samba.org>
Mon, 4 Jun 2007 09:53:19 +0000 (19:53 +1000)
(This used to be ctdb commit 73d440f8cb19373cfad7a2f0f0ca4f963c57ff29)

ctdb/.bzrignore
ctdb/Makefile.in
ctdb/common/ctdb_client.c
ctdb/common/ctdb_control.c
ctdb/common/ctdb_tunables.c [new file with mode: 0644]
ctdb/config/events.d/README [new file with mode: 0644]
ctdb/include/ctdb.h
ctdb/include/ctdb_private.h
ctdb/tests/ctdbd.sh
ctdb/tests/start_daemons.sh
ctdb/tools/ctdb_control.c

index 9ec7f5dd7b7bacebd3d605ba47242bd7dc945460..6d05088146eb73f36918e6abc9125e2f53bd2e98 100644 (file)
@@ -17,3 +17,5 @@ ctdb-3
 nodes.txt
 TAGS
 web/packages
+rec.lock
+test.db
index 7d1cee1e429c5380d58369c022ce412a6bd4e3c2..56c3391927ed50bc59152f868cc351ded5c694b2 100644 (file)
@@ -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
 
index afc968d81cc6004f29aeda2f5f11c1e5a4fc9ff5..b1abadc21c459b0d13ce54c5d4a8e53a48de8204 100644 (file)
@@ -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;
+}
index 7d2af014b125e4e10bb2a9c576b7770ab3eb7fd8..188ebd77191a2599aa99857c60736cc0f4c95c12 100644 (file)
@@ -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 (file)
index 0000000..912d12a
--- /dev/null
@@ -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 (file)
index 0000000..531e645
--- /dev/null
@@ -0,0 +1,4 @@
+This directory is where you should put any local or application
+specific event scripts for ctdb to call.
+
+
index d8e32161d27c8e74810651103e96ea3877de52c2..74039420fa61f08ffee8d60107641a398e987e01 100644 (file)
@@ -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
index d7f2b32cea5d0371d4a66c13d101e57a5e0d504a..75126b211532032146e989ac44821ac73346f485 100644 (file)
@@ -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
index 29777516bdf29dca0acdd452b832c06bdbad4c61..4a1e9976b20083112fc3affac3a0f778973baf29 100755 (executable)
@@ -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"
index e902ae45f486d995d2f39bd0e5ff258c63792cc2..fcc53cecc104dd2b1a4faa64c294181d6a1c3c2e 100755 (executable)
@@ -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
index 34080bc50b53b4b198b6433bb28700b6856fc357..ec23ccac185720ecbdc89404a989b5d3d0ba2b53 100644 (file)
@@ -517,6 +517,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
  */
@@ -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>"},