1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-26 10:04:02 +03:00

merge from tridge

(This used to be ctdb commit 3bfede5d46dba5a3654dad9205534391bc339461)
This commit is contained in:
Ronnie Sahlberg 2007-06-04 20:10:53 +10:00
commit 1ee8989bd4
25 changed files with 560 additions and 692 deletions

View File

@ -17,3 +17,5 @@ ctdb-3
nodes.txt
TAGS
web/packages
rec.lock
test.db

View 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
@ -43,7 +44,7 @@ CTDB_OBJ = $(CTDB_COMMON_OBJ) $(CTDB_TAKEOVER_OBJ) $(CTDB_TCP_OBJ) $(POPT_OBJ)
OBJS = @TDB_OBJ@ @TALLOC_OBJ@ @LIBREPLACEOBJ@ @INFINIBAND_WRAPPER_OBJ@ $(EXTRA_OBJ) @EVENTS_OBJ@ $(CTDB_OBJ) $(UTIL_OBJ)
TEST_BINS=bin/ctdbd_test bin/ctdb_bench bin/ctdb_fetch @INFINIBAND_BINS@
TEST_BINS=bin/ctdb_bench bin/ctdb_fetch @INFINIBAND_BINS@
BINS = bin/ctdb
SBINS = bin/ctdbd
@ -72,10 +73,6 @@ bin/ctdb: $(OBJS) tools/ctdb_control.o
@echo Linking $@
@$(CC) $(CFLAGS) -o $@ tools/ctdb_control.o $(OBJS) $(LIB_FLAGS)
bin/ctdbd_test: $(OBJS) direct/ctdbd_test.o
@echo Linking $@
@$(CC) $(CFLAGS) -o $@ direct/ctdbd_test.o
bin/ctdb_bench: $(OBJS) tests/ctdb_bench.o
@echo Linking $@
@$(CC) $(CFLAGS) -o $@ tests/ctdb_bench.o $(OBJS) $(LIB_FLAGS)

View File

@ -86,14 +86,6 @@ void ctdb_clear_flags(struct ctdb_context *ctdb, unsigned flags)
ctdb->flags &= ~flags;
}
/*
set max acess count before a dmaster migration
*/
void ctdb_set_max_lacount(struct ctdb_context *ctdb, unsigned count)
{
ctdb->max_lacount = count;
}
/*
set the directory for the local databases
*/
@ -316,11 +308,6 @@ void ctdb_input_pkt(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
ctdb_request_message(ctdb, hdr);
break;
case CTDB_REQ_FINISHED:
ctdb->statistics.node.req_finished++;
ctdb_request_finished(ctdb, hdr);
break;
case CTDB_REQ_CONTROL:
ctdb->statistics.node.req_control++;
ctdb_request_control(ctdb, hdr);
@ -406,23 +393,6 @@ void ctdb_node_connected(struct ctdb_node *node)
node->ctdb->name, node->name, node->ctdb->num_connected));
}
/*
wait for all nodes to be connected
*/
void ctdb_daemon_connect_wait(struct ctdb_context *ctdb)
{
int expected = ctdb->num_nodes - 1;
if (ctdb->flags & CTDB_FLAG_SELF_CONNECT) {
expected++;
}
while (ctdb->num_connected != expected) {
DEBUG(3,("ctdb_connect_wait: waiting for %u nodes (have %u)\n",
expected, ctdb->num_connected));
event_loop_once(ctdb->ev);
}
DEBUG(3,("ctdb_connect_wait: got all %u nodes\n", expected));
}
struct queue_next {
struct ctdb_context *ctdb;
struct ctdb_req_header *hdr;
@ -550,11 +520,18 @@ struct ctdb_context *ctdb_init(struct event_context *ev)
ctdb->recovery_master = (uint32_t)-1;
ctdb->upcalls = &ctdb_upcalls;
ctdb->idr = idr_init(ctdb);
ctdb->max_lacount = CTDB_DEFAULT_MAX_LACOUNT;
ctdb->seqnum_frequency = CTDB_DEFAULT_SEQNUM_FREQUENCY;
ctdb->recovery_lock_fd = -1;
ctdb->monitoring_mode = CTDB_MONITORING_ACTIVE;
/* set default values for tunables */
ctdb->tunable.max_redirect_count = 3;
ctdb->tunable.seqnum_frequency = 1;
ctdb->tunable.control_timeout = 60;
ctdb->tunable.traverse_timeout = 20;
ctdb->tunable.monitoring_timeout = 2;
ctdb->tunable.monitoring_limit = 3;
ctdb->tunable.max_lacount = 7;
return ctdb;
}

View File

@ -180,7 +180,7 @@ static void ctdb_call_send_redirect(struct ctdb_context *ctdb,
uint32_t lmaster = ctdb_lmaster(ctdb, &key);
if (ctdb->vnn == lmaster) {
c->hdr.destnode = header->dmaster;
} else if ((c->hopcount % CTDB_MAX_REDIRECT_COUNT) == 0) {
} else if ((c->hopcount % ctdb->tunable.max_redirect_count) == 0) {
c->hdr.destnode = lmaster;
} else {
c->hdr.destnode = header->dmaster;
@ -476,8 +476,8 @@ void ctdb_request_call(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
*/
if ( c->hdr.srcnode != ctdb->vnn &&
((header.laccessor == c->hdr.srcnode
&& header.lacount >= ctdb->max_lacount)
|| (c->flags&CTDB_IMMEDIATE_MIGRATION)) ) {
&& header.lacount >= ctdb->tunable.max_lacount)
|| (c->flags & CTDB_IMMEDIATE_MIGRATION)) ) {
DEBUG(2,("vnn %u starting migration of %08x to %u\n",
ctdb->vnn, ctdb_hash(&call.key), c->hdr.srcnode));
ctdb_call_send_dmaster(ctdb_db, c, &header, &call.key, &data);

View File

@ -38,17 +38,6 @@ static int ctdb_client_queue_pkt(struct ctdb_context *ctdb, struct ctdb_req_head
}
/*
handle a connect wait reply packet
*/
static void ctdb_reply_connect_wait(struct ctdb_context *ctdb,
struct ctdb_req_header *hdr)
{
struct ctdb_reply_connect_wait *r = (struct ctdb_reply_connect_wait *)hdr;
ctdb->vnn = r->vnn;
ctdb->num_connected = r->num_connected;
}
/*
state of a in-progress ctdb call in client
*/
@ -143,10 +132,6 @@ static void ctdb_client_read_cb(uint8_t *data, size_t cnt, void *args)
ctdb_request_message(ctdb, hdr);
break;
case CTDB_REPLY_CONNECT_WAIT:
ctdb_reply_connect_wait(ctdb, hdr);
break;
case CTDB_REPLY_CONTROL:
ctdb_client_reply_control(ctdb, hdr);
break;
@ -437,38 +422,6 @@ int ctdb_send_message(struct ctdb_context *ctdb, uint32_t vnn,
return 0;
}
/*
wait for all nodes to be connected - from client
*/
void ctdb_connect_wait(struct ctdb_context *ctdb)
{
struct ctdb_req_connect_wait *r;
int res;
r = ctdbd_allocate_pkt(ctdb, ctdb, CTDB_REQ_CONNECT_WAIT, sizeof(*r),
struct ctdb_req_connect_wait);
CTDB_NO_MEMORY_VOID(ctdb, r);
DEBUG(3,("ctdb_connect_wait: sending to ctdbd\n"));
/* if the domain socket is not yet open, open it */
if (ctdb->daemon.sd==-1) {
ctdb_socket_connect(ctdb);
}
res = ctdb_queue_send(ctdb->daemon.queue, (uint8_t *)&r->hdr, r->hdr.length);
talloc_free(r);
if (res != 0) {
DEBUG(0,(__location__ " Failed to queue a connect wait request\n"));
return;
}
DEBUG(3,("ctdb_connect_wait: waiting\n"));
/* now we can go into the normal wait routine, as the reply packet
will update the ctdb->num_connected variable */
ctdb_daemon_connect_wait(ctdb);
}
/*
cancel a ctdb_fetch_lock operation, releasing the lock
@ -576,34 +529,6 @@ int ctdb_record_store(struct ctdb_record_handle *h, TDB_DATA data)
return ctdb_ltdb_store(h->ctdb_db, h->key, &h->header, data);
}
/*
wait until we're the only node left.
this function never returns
*/
void ctdb_shutdown(struct ctdb_context *ctdb)
{
struct ctdb_req_shutdown *r;
/* if the domain socket is not yet open, open it */
if (ctdb->daemon.sd==-1) {
ctdb_socket_connect(ctdb);
}
r = ctdbd_allocate_pkt(ctdb, ctdb, CTDB_REQ_SHUTDOWN, sizeof(*r),
struct ctdb_req_shutdown);
CTDB_NO_MEMORY_VOID(ctdb, r);
ctdb_client_queue_pkt(ctdb, &(r->hdr));
talloc_free(r);
/* this event loop will terminate once we receive the reply */
while (1) {
event_loop_once(ctdb->ev);
}
}
struct ctdb_client_control_state {
struct ctdb_context *ctdb;
uint32_t reqid;
@ -1870,3 +1795,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;
}

View File

@ -142,14 +142,6 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
case CTDB_CONTROL_GET_VNN:
return ctdb->vnn;
case CTDB_CONTROL_CONFIG: {
CHECK_CONTROL_DATA_SIZE(0);
ctdb->statistics.controls.get_config++;
outdata->dptr = (uint8_t *)ctdb;
outdata->dsize = sizeof(*ctdb);
return 0;
}
case CTDB_CONTROL_PING:
CHECK_CONTROL_DATA_SIZE(0);
ctdb->statistics.controls.ping++;
@ -224,11 +216,6 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
CHECK_CONTROL_DATA_SIZE(sizeof(uint32_t));
return ctdb_ltdb_update_seqnum(ctdb, *(uint32_t *)indata.dptr, srcnode);
case CTDB_CONTROL_SET_SEQNUM_FREQUENCY:
ctdb->statistics.controls.set_seqnum_frequency++;
CHECK_CONTROL_DATA_SIZE(sizeof(uint32_t));
return ctdb_ltdb_set_seqnum_frequency(ctdb, *(uint32_t *)indata.dptr);
case CTDB_CONTROL_FREEZE:
CHECK_CONTROL_DATA_SIZE(0);
return ctdb_control_freeze(ctdb, c, async_reply);
@ -292,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;
@ -489,10 +485,11 @@ int ctdb_daemon_send_control(struct ctdb_context *ctdb, uint32_t destnode,
return 0;
}
#if CTDB_CONTROL_TIMEOUT
event_add_timed(ctdb->ev, state, timeval_current_ofs(CTDB_CONTROL_TIMEOUT, 0),
ctdb_control_timeout, state);
#endif
if (ctdb->tunable.control_timeout) {
event_add_timed(ctdb->ev, state,
timeval_current_ofs(ctdb->tunable.control_timeout, 0),
ctdb_control_timeout, state);
}
talloc_free(c);
return 0;

View File

@ -191,82 +191,6 @@ int daemon_deregister_message_handler(struct ctdb_context *ctdb, uint32_t client
}
/*
called when the daemon gets a shutdown request from a client
*/
static void daemon_request_shutdown(struct ctdb_client *client,
struct ctdb_req_shutdown *f)
{
struct ctdb_context *ctdb = talloc_get_type(client->ctdb, struct ctdb_context);
int len;
uint32_t node;
/* we dont send to ourself so we can already count one daemon as
exiting */
ctdb->num_finished++;
/* loop over all nodes of the cluster */
for (node=0; node<ctdb->num_nodes;node++) {
struct ctdb_req_finished *rf;
/* dont send a message to ourself */
if (ctdb->vnn == node) {
continue;
}
len = sizeof(struct ctdb_req_finished);
rf = ctdb_transport_allocate(ctdb, ctdb, CTDB_REQ_FINISHED, len,
struct ctdb_req_finished);
CTDB_NO_MEMORY_FATAL(ctdb, rf);
rf->hdr.destnode = node;
ctdb_queue_packet(ctdb, &(rf->hdr));
talloc_free(rf);
}
/* wait until all nodes have are prepared to shutdown */
while (ctdb->num_finished != ctdb->num_nodes) {
event_loop_once(ctdb->ev);
}
/* all daemons have requested to finish - we now exit */
DEBUG(1,("All daemons finished - exiting\n"));
_exit(0);
}
/*
called when the daemon gets a connect wait request from a client
*/
static void daemon_request_connect_wait(struct ctdb_client *client,
struct ctdb_req_connect_wait *c)
{
struct ctdb_reply_connect_wait *r;
int res;
/* first wait - in the daemon */
ctdb_daemon_connect_wait(client->ctdb);
/* now send the reply */
r = ctdbd_allocate_pkt(client->ctdb, client, CTDB_REPLY_CONNECT_WAIT, sizeof(*r),
struct ctdb_reply_connect_wait);
CTDB_NO_MEMORY_VOID(client->ctdb, r);
r->vnn = ctdb_get_vnn(client->ctdb);
r->num_connected = client->ctdb->num_connected;
res = daemon_queue_send(client, &r->hdr);
talloc_free(r);
if (res != 0) {
DEBUG(0,(__location__ " Failed to queue a connect wait response\n"));
return;
}
}
/*
destroy a ctdb_client
*/
@ -495,16 +419,6 @@ static void daemon_incoming_packet(void *p, struct ctdb_req_header *hdr)
daemon_request_message_from_client(client, (struct ctdb_req_message *)hdr);
break;
case CTDB_REQ_CONNECT_WAIT:
ctdb->statistics.client.req_connect_wait++;
daemon_request_connect_wait(client, (struct ctdb_req_connect_wait *)hdr);
break;
case CTDB_REQ_SHUTDOWN:
ctdb->statistics.client.req_shutdown++;
daemon_request_shutdown(client, (struct ctdb_req_shutdown *)hdr);
break;
case CTDB_REQ_CONTROL:
ctdb->statistics.client.req_control++;
daemon_request_control_from_client(client, (struct ctdb_req_control *)hdr);
@ -862,15 +776,6 @@ struct ctdb_req_header *_ctdb_transport_allocate(struct ctdb_context *ctdb,
return hdr;
}
/*
called when a CTDB_REQ_FINISHED packet comes in
*/
void ctdb_request_finished(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
{
ctdb->num_finished++;
}
struct daemon_control_state {
struct daemon_control_state *next, *prev;
struct ctdb_client *client;

View File

@ -484,9 +484,10 @@ static void ctdb_ltdb_seqnum_check(struct event_context *ev, struct timed_event
ctdb_db->seqnum = new_seqnum;
/* setup a new timer */
ctdb_db->te = event_add_timed(ctdb->ev, ctdb_db,
timeval_current_ofs(ctdb->seqnum_frequency, 0),
ctdb_ltdb_seqnum_check, ctdb_db);
ctdb_db->te =
event_add_timed(ctdb->ev, ctdb_db,
timeval_current_ofs(ctdb->tunable.seqnum_frequency, 0),
ctdb_ltdb_seqnum_check, ctdb_db);
}
/*
@ -502,9 +503,10 @@ int32_t ctdb_ltdb_enable_seqnum(struct ctdb_context *ctdb, uint32_t db_id)
}
if (ctdb_db->te == NULL) {
ctdb_db->te = event_add_timed(ctdb->ev, ctdb_db,
timeval_current_ofs(ctdb->seqnum_frequency, 0),
ctdb_ltdb_seqnum_check, ctdb_db);
ctdb_db->te =
event_add_timed(ctdb->ev, ctdb_db,
timeval_current_ofs(ctdb->tunable.seqnum_frequency, 0),
ctdb_ltdb_seqnum_check, ctdb_db);
}
tdb_enable_seqnum(ctdb_db->ltdb->tdb);
@ -512,11 +514,3 @@ int32_t ctdb_ltdb_enable_seqnum(struct ctdb_context *ctdb, uint32_t db_id)
return 0;
}
/*
enable seqnum handling on this db
*/
int32_t ctdb_ltdb_set_seqnum_frequency(struct ctdb_context *ctdb, uint32_t frequency)
{
ctdb->seqnum_frequency = frequency;
return 0;
}

View File

@ -36,7 +36,7 @@ static void ctdb_check_for_dead_nodes(struct event_context *ev, struct timed_eve
if (ctdb->monitoring_mode==CTDB_MONITORING_DISABLED) {
event_add_timed(ctdb->ev, ctdb,
timeval_current_ofs(CTDB_MONITORING_TIMEOUT, 0),
timeval_current_ofs(ctdb->tunable.monitoring_timeout, 0),
ctdb_check_for_dead_nodes, ctdb);
return;
}
@ -65,7 +65,7 @@ static void ctdb_check_for_dead_nodes(struct event_context *ev, struct timed_eve
node->rx_cnt = 0;
if (node->dead_count >= CTDB_MONITORING_DEAD_COUNT) {
if (node->dead_count >= ctdb->tunable.monitoring_limit) {
DEBUG(0,("dead count reached for node %u\n", node->vnn));
ctdb_node_dead(node);
ctdb_send_keepalive(ctdb, node->vnn);
@ -84,7 +84,7 @@ static void ctdb_check_for_dead_nodes(struct event_context *ev, struct timed_eve
}
event_add_timed(ctdb->ev, ctdb,
timeval_current_ofs(CTDB_MONITORING_TIMEOUT, 0),
timeval_current_ofs(ctdb->tunable.monitoring_timeout, 0),
ctdb_check_for_dead_nodes, ctdb);
}
@ -94,7 +94,7 @@ static void ctdb_check_for_dead_nodes(struct event_context *ev, struct timed_eve
int ctdb_start_monitoring(struct ctdb_context *ctdb)
{
event_add_timed(ctdb->ev, ctdb,
timeval_current_ofs(CTDB_MONITORING_TIMEOUT, 0),
timeval_current_ofs(ctdb->tunable.monitoring_timeout, 0),
ctdb_check_for_dead_nodes, ctdb);
return 0;
}

View File

@ -256,7 +256,8 @@ struct ctdb_traverse_all_handle *ctdb_daemon_traverse_all(struct ctdb_db_context
}
/* timeout the traverse */
event_add_timed(ctdb->ev, state, timeval_current_ofs(CTDB_TRAVERSE_TIMEOUT, 0),
event_add_timed(ctdb->ev, state,
timeval_current_ofs(ctdb->tunable.traverse_timeout, 0),
ctdb_traverse_all_timeout, state);
return state;

142
ctdb/common/ctdb_tunables.c Normal file
View File

@ -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;
}

View File

@ -51,6 +51,14 @@
# the default is 0
# DEBUGLEVEL=0
# set any default tuning options for ctdb
# use CTDB_SET_XXXX=value where XXXX is the name of the tuning
# variable
# for example
# CTDB_SET_TRAVERSETIMEOUT=60
# you can get a list of variables using "ctdb listvars"
# any other options you might want. Run ctdbd --help for a list
# CTDB_OPTIONS=

View File

@ -21,6 +21,15 @@ case $cmd in
# make sure we have a blank state directory for the scripts to work with
/bin/rm -rf /etc/ctdb/state
/bin/mkdir -p /etc/ctdb/state
# set any tunables from the config file
set | grep ^CTDB_SET_ | cut -d_ -f3- |
while read v; do
varname=`echo $v | cut -d= -f1`
value=`echo $v | cut -d= -f2`
ctdb setvar $varname $value || exit 1
echo "`date` Set $varname to $value"
done
;;
esac

View File

@ -0,0 +1,4 @@
This directory is where you should put any local or application
specific event scripts for ctdb to call.

View File

@ -1,4 +0,0 @@
127.0.0.1
127.0.0.2
127.0.0.3
127.0.0.4

View File

@ -1,12 +0,0 @@
Run ./direct/ctdbd.sh to start a cluster with two ctdb nodes
They will listen for clients on the unix domain sockets
/tmp/ctdb.socket.127.0.0.1
/tmp/ctdb.socket.127.0.0.2
In order for this to work you must have an interface with the address 127.0.0.2 available.
Just create this as an alias for loopback.
Then run ./direct/ctdbd_test to connect a client to the ctdbd daemon on /tmp/ctdb.socket.127.0.0.1 and do some commands to it across the domain socket.

View File

@ -1,285 +0,0 @@
/*
test of messaging
Copyright (C) Andrew Tridgell 2006
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 "system/network.h"
#include "../include/ctdb.h"
#include "../include/ctdb_private.h"
#define CTDB_SOCKET "/tmp/ctdb.socket.127.0.0.1"
/*
connect to the unix domain socket
*/
static int ux_socket_connect(const char *name)
{
struct sockaddr_un addr;
int fd;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, name, sizeof(addr.sun_path));
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd == -1) {
return -1;
}
if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
close(fd);
return -1;
}
return fd;
}
/* send a command to the cluster to wait until all nodes are connected
and the cluster is fully operational
*/
int wait_for_cluster(int fd)
{
struct ctdb_req_connect_wait req;
struct ctdb_reply_connect_wait rep;
int cnt, tot;
/* send a connect wait command to the local node */
bzero(&req, sizeof(req));
req.hdr.length = sizeof(req);
req.hdr.ctdb_magic = CTDB_MAGIC;
req.hdr.ctdb_version = CTDB_VERSION;
req.hdr.generation = 1;
req.hdr.operation = CTDB_REQ_CONNECT_WAIT;
/* XXX must deal with partial writes here */
write(fd, &req, sizeof(req));
/* read the 4 bytes of length for the pdu */
cnt=0;
tot=4;
while(cnt!=tot){
int numread;
numread=read(fd, ((char *)&rep)+cnt, tot-cnt);
if(numread>0){
cnt+=numread;
}
}
/* read the rest of the pdu */
tot=rep.hdr.length;
while(cnt!=tot){
int numread;
numread=read(fd, ((char *)&rep)+cnt, tot-cnt);
if(numread>0){
cnt+=numread;
}
}
return rep.vnn;
}
int send_a_message(int fd, int ourvnn, int vnn, int pid, TDB_DATA data)
{
struct ctdb_req_message r;
int len, cnt;
len = offsetof(struct ctdb_req_message, data) + data.dsize;
r.hdr.length = len;
r.hdr.ctdb_magic = CTDB_MAGIC;
r.hdr.ctdb_version = CTDB_VERSION;
r.hdr.generation = 1;
r.hdr.operation = CTDB_REQ_MESSAGE;
r.hdr.destnode = vnn;
r.hdr.srcnode = ourvnn;
r.hdr.reqid = 0;
r.srvid = pid;
r.datalen = data.dsize;
/* write header */
cnt=write(fd, &r, offsetof(struct ctdb_req_message, data));
/* write data */
if(data.dsize){
cnt=write(fd, data.dptr, data.dsize);
}
return 0;
}
int receive_a_message(int fd, struct ctdb_req_message **preply)
{
int cnt,tot;
struct ctdb_req_message *rep;
uint32_t length;
/* read the 4 bytes of length for the pdu */
cnt=0;
tot=4;
while(cnt!=tot){
int numread;
numread=read(fd, ((char *)&length)+cnt, tot-cnt);
if(numread>0){
cnt+=numread;
}
}
/* read the rest of the pdu */
rep = malloc(length);
rep->hdr.length = length;
cnt = 0;
tot = length-4;
while(cnt!=tot){
int numread;
numread=read(fd, ((char *)rep)+cnt, tot-cnt);
if(numread>0){
cnt+=numread;
}
}
*preply = rep;
return 0;
}
/*
hash function for mapping data to a VNN - taken from tdb
*/
uint32_t ctdb_hash(const TDB_DATA *key)
{
uint32_t value; /* Used to compute the hash value. */
uint32_t i; /* Used to cycle through random values. */
/* Set the initial value from the key size. */
for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++)
value = (value + (key->dptr[i] << (i*5 % 24)));
return (1103515243 * value + 12345);
}
/* ask the daemon to migrate a record over so that the local node is the dmaster the client must not have the record locked when performing this call.
when the daemon has responded this node should be the dmaster (unless it has migrated off again)
*/
void fetch_record(int fd, uint32_t db_id, TDB_DATA key)
{
struct ctdb_req_call *req;
struct ctdb_reply_call *rep;
uint32_t length;
int len, cnt, tot;
len = offsetof(struct ctdb_req_call, data) + key.dsize;
req = malloc(len);
req->hdr.length = len;
req->hdr.ctdb_magic = CTDB_MAGIC;
req->hdr.ctdb_version = CTDB_VERSION;
req->hdr.generation = 1;
req->hdr.operation = CTDB_REQ_CALL;
req->hdr.reqid = 1;
req->flags = CTDB_IMMEDIATE_MIGRATION;
req->db_id = db_id;
req->callid = CTDB_NULL_FUNC;
req->keylen = key.dsize;
req->calldatalen = 0;
memcpy(&req->data[0], key.dptr, key.dsize);
cnt=write(fd, req, len);
/* wait fot the reply */
/* read the 4 bytes of length for the pdu */
cnt=0;
tot=4;
while(cnt!=tot){
int numread;
numread=read(fd, ((char *)&length)+cnt, tot-cnt);
if(numread>0){
cnt+=numread;
}
}
/* read the rest of the pdu */
rep = malloc(length);
tot=length;
while(cnt!=tot){
int numread;
numread=read(fd, ((char *)rep)+cnt, tot-cnt);
if(numread>0){
cnt+=numread;
}
}
printf("fetch record reply: operation:%d state:%d\n",rep->hdr.operation,rep->status);
}
int main(int argc, const char *argv[])
{
int fd, pid=0, vnn, dstvnn, dstpid;
TDB_DATA message;
struct ctdb_req_message *reply;
TDB_DATA dbname;
uint32_t db_id;
TDB_DATA key;
/* open the socket to talk to the local ctdb daemon */
fd=ux_socket_connect(CTDB_SOCKET);
if (fd==-1) {
printf("failed to open domain socket\n");
exit(10);
}
/* do a connect wait to ensure that all nodes in the cluster are up
and operational.
this also tells us the vnn of the local cluster.
If someone wants to send us a emssage they should send it to
this vnn and our pid
*/
vnn=wait_for_cluster(fd);
printf("our address is vnn:%d pid:%d if someone wants to send us a message!\n",vnn,pid);
/* send a message to ourself */
dstvnn=vnn;
dstpid=pid;
message.dptr=discard_const("Test message");
message.dsize=strlen((const char *)message.dptr)+1;
printf("sending test message [%s] to ourself\n", message.dptr);
send_a_message(fd, vnn, dstvnn, dstpid, message);
/* wait for the message to come back */
receive_a_message(fd, &reply);
printf("received message: [%s]\n",&reply->data[0]);
/* create the db id for "test.tdb" */
dbname.dptr = discard_const("test.tdb");
dbname.dsize = strlen((const char *)(dbname.dptr));
db_id = ctdb_hash(&dbname);
printf("the has for the database id is 0x%08x\n",db_id);
printf("\n");
/* send a request to migrate a record to the local node */
key.dptr=discard_const("TestKey");
key.dsize=strlen((const char *)(key.dptr));
printf("fetch the test key:[%s]\n",key.dptr);
fetch_record(fd, db_id, key);
printf("\n");
return 0;
}

View File

@ -1,2 +0,0 @@
127.0.0.1
127.0.0.2

View File

@ -162,11 +162,6 @@ int ctdb_set_call(struct ctdb_db_context *ctdb_db, ctdb_fn_t fn, uint32_t id);
*/
int ctdb_call(struct ctdb_db_context *ctdb_db, struct ctdb_call *call);
/*
wait for all nodes to be connected - useful for test code
*/
void ctdb_connect_wait(struct ctdb_context *ctdb);
/*
initiate an ordered ctdb cluster shutdown
this function will never return
@ -345,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

View File

@ -38,8 +38,16 @@
#define CTDB_NULL_FUNC 0xFF000001
#define CTDB_FETCH_FUNC 0xFF000002
#define CTDB_MAX_REDIRECT_COUNT 3
#define CTDB_DEFAULT_SEQNUM_FREQUENCY 1
/* all tunable variables go in here */
struct ctdb_tunable {
uint32_t max_redirect_count;
uint32_t seqnum_frequency;
uint32_t control_timeout;
uint32_t traverse_timeout;
uint32_t monitoring_timeout;
uint32_t monitoring_limit;
uint32_t max_lacount;
};
/*
an installed ctdb remote call
@ -181,16 +189,12 @@ struct ctdb_statistics {
uint32_t reply_dmaster;
uint32_t reply_error;
uint32_t req_message;
uint32_t req_finished;
uint32_t req_control;
uint32_t reply_control;
} node;
struct {
uint32_t req_call;
uint32_t req_message;
uint32_t req_finished;
uint32_t req_connect_wait;
uint32_t req_shutdown;
uint32_t req_control;
} client;
struct {
@ -271,6 +275,7 @@ struct ctdb_context {
struct event_context *ev;
uint32_t recovery_mode;
uint32_t monitoring_mode;
struct ctdb_tunable tunable;
enum ctdb_freeze_mode freeze_mode;
struct ctdb_freeze_handle *freeze_handle;
struct ctdb_address address;
@ -284,7 +289,6 @@ struct ctdb_context {
uint32_t vnn; /* our own vnn */
uint32_t num_nodes;
uint32_t num_connected;
uint32_t num_finished;
unsigned flags;
struct idr_context *idr;
uint16_t idr_cnt;
@ -293,14 +297,12 @@ struct ctdb_context {
const struct ctdb_methods *methods; /* transport methods */
const struct ctdb_upcalls *upcalls; /* transport upcalls */
void *private_data; /* private to transport */
unsigned max_lacount;
struct ctdb_db_context *db_list;
struct ctdb_message_list *message_list;
struct ctdb_daemon_data daemon;
struct ctdb_statistics statistics;
struct ctdb_vnn_map *vnn_map;
uint32_t num_clients;
uint32_t seqnum_frequency;
uint32_t recovery_master;
struct ctdb_call_state *pending_calls;
struct ctdb_takeover takeover;
@ -340,24 +342,6 @@ struct ctdb_db_context {
ctdb_fatal(ctdb, "Out of memory in " __location__ ); \
}} while (0)
/* maximum timeout for ctdb control calls */
#define CTDB_CONTROL_TIMEOUT 60
/* timeout for ctdb traverse calls. When this is reached we cut short
the traverse */
#define CTDB_TRAVERSE_TIMEOUT 20
/* timeout between dead-node monitoring events */
#define CTDB_MONITORING_TIMEOUT 2
/* number of monitoring timeouts before a node is considered dead */
#define CTDB_MONITORING_DEAD_COUNT 3
/* number of consecutive calls from the same node before we give them
the record */
#define CTDB_DEFAULT_MAX_LACOUNT 7
/*
the extended header for records in the ltdb
*/
@ -368,54 +352,57 @@ struct ctdb_ltdb_header {
uint32_t lacount;
};
enum ctdb_controls {CTDB_CONTROL_PROCESS_EXISTS,
CTDB_CONTROL_STATISTICS,
CTDB_CONTROL_CONFIG,
CTDB_CONTROL_PING,
CTDB_CONTROL_GETDBPATH,
CTDB_CONTROL_GETVNNMAP,
CTDB_CONTROL_SETVNNMAP,
CTDB_CONTROL_GET_DEBUG,
CTDB_CONTROL_SET_DEBUG,
CTDB_CONTROL_GET_DBMAP,
CTDB_CONTROL_GET_NODEMAP,
CTDB_CONTROL_SET_DMASTER,
CTDB_CONTROL_CLEAR_DB,
CTDB_CONTROL_PULL_DB,
CTDB_CONTROL_PUSH_DB,
CTDB_CONTROL_GET_RECMODE,
CTDB_CONTROL_SET_RECMODE,
CTDB_CONTROL_STATISTICS_RESET,
CTDB_CONTROL_DB_ATTACH,
CTDB_CONTROL_SET_CALL,
CTDB_CONTROL_TRAVERSE_START,
CTDB_CONTROL_TRAVERSE_ALL,
CTDB_CONTROL_TRAVERSE_DATA,
CTDB_CONTROL_REGISTER_SRVID,
CTDB_CONTROL_DEREGISTER_SRVID,
CTDB_CONTROL_GET_DBNAME,
CTDB_CONTROL_ENABLE_SEQNUM,
CTDB_CONTROL_UPDATE_SEQNUM,
CTDB_CONTROL_SET_SEQNUM_FREQUENCY,
CTDB_CONTROL_DUMP_MEMORY,
CTDB_CONTROL_GET_PID,
CTDB_CONTROL_GET_RECMASTER,
CTDB_CONTROL_SET_RECMASTER,
CTDB_CONTROL_FREEZE,
CTDB_CONTROL_THAW,
CTDB_CONTROL_GET_VNN,
CTDB_CONTROL_SHUTDOWN,
CTDB_CONTROL_GET_MONMODE,
CTDB_CONTROL_SET_MONMODE,
CTDB_CONTROL_MAX_RSN,
CTDB_CONTROL_SET_RSN_NONEMPTY,
CTDB_CONTROL_DELETE_LOW_RSN,
CTDB_CONTROL_TAKEOVER_IP,
CTDB_CONTROL_RELEASE_IP,
CTDB_CONTROL_TCP_CLIENT,
CTDB_CONTROL_TCP_ADD,
CTDB_CONTROL_TCP_REMOVE,
CTDB_CONTROL_STARTUP,
enum ctdb_controls {CTDB_CONTROL_PROCESS_EXISTS = 0,
CTDB_CONTROL_STATISTICS = 1,
/* #2 removed */
CTDB_CONTROL_PING = 3,
CTDB_CONTROL_GETDBPATH = 4,
CTDB_CONTROL_GETVNNMAP = 5,
CTDB_CONTROL_SETVNNMAP = 6,
CTDB_CONTROL_GET_DEBUG = 7,
CTDB_CONTROL_SET_DEBUG = 8,
CTDB_CONTROL_GET_DBMAP = 9,
CTDB_CONTROL_GET_NODEMAP = 10,
CTDB_CONTROL_SET_DMASTER = 11,
CTDB_CONTROL_CLEAR_DB = 12,
CTDB_CONTROL_PULL_DB = 13,
CTDB_CONTROL_PUSH_DB = 14,
CTDB_CONTROL_GET_RECMODE = 15,
CTDB_CONTROL_SET_RECMODE = 16,
CTDB_CONTROL_STATISTICS_RESET = 17,
CTDB_CONTROL_DB_ATTACH = 18,
CTDB_CONTROL_SET_CALL = 19,
CTDB_CONTROL_TRAVERSE_START = 20,
CTDB_CONTROL_TRAVERSE_ALL = 21,
CTDB_CONTROL_TRAVERSE_DATA = 22,
CTDB_CONTROL_REGISTER_SRVID = 23,
CTDB_CONTROL_DEREGISTER_SRVID = 24,
CTDB_CONTROL_GET_DBNAME = 25,
CTDB_CONTROL_ENABLE_SEQNUM = 26,
CTDB_CONTROL_UPDATE_SEQNUM = 27,
/* #28 removed */
CTDB_CONTROL_DUMP_MEMORY = 29,
CTDB_CONTROL_GET_PID = 30,
CTDB_CONTROL_GET_RECMASTER = 31,
CTDB_CONTROL_SET_RECMASTER = 32,
CTDB_CONTROL_FREEZE = 33,
CTDB_CONTROL_THAW = 34,
CTDB_CONTROL_GET_VNN = 35,
CTDB_CONTROL_SHUTDOWN = 36,
CTDB_CONTROL_GET_MONMODE = 37,
CTDB_CONTROL_SET_MONMODE = 38,
CTDB_CONTROL_MAX_RSN = 39,
CTDB_CONTROL_SET_RSN_NONEMPTY = 40,
CTDB_CONTROL_DELETE_LOW_RSN = 41,
CTDB_CONTROL_TAKEOVER_IP = 42,
CTDB_CONTROL_RELEASE_IP = 43,
CTDB_CONTROL_TCP_CLIENT = 44,
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,
};
/*
@ -496,20 +483,15 @@ struct ctdb_fetch_handle {
*/
enum ctdb_operation {
CTDB_REQ_CALL = 0,
CTDB_REPLY_CALL,
CTDB_REQ_DMASTER,
CTDB_REPLY_DMASTER,
CTDB_REPLY_ERROR,
CTDB_REQ_MESSAGE,
CTDB_REQ_FINISHED,
CTDB_REQ_CONTROL,
CTDB_REPLY_CONTROL,
CTDB_REQ_KEEPALIVE,
/* only used on the domain socket */
CTDB_REQ_CONNECT_WAIT = 1000,
CTDB_REPLY_CONNECT_WAIT,
CTDB_REQ_SHUTDOWN
CTDB_REPLY_CALL = 1,
CTDB_REQ_DMASTER = 2,
CTDB_REPLY_DMASTER = 3,
CTDB_REPLY_ERROR = 4,
CTDB_REQ_MESSAGE = 5,
/* #6 removed */
CTDB_REQ_CONTROL = 7,
CTDB_REPLY_CONTROL = 8,
CTDB_REQ_KEEPALIVE = 9,
};
#define CTDB_MAGIC 0x43544442 /* CTDB */
@ -580,24 +562,6 @@ struct ctdb_req_message {
uint8_t data[1];
};
struct ctdb_req_finished {
struct ctdb_req_header hdr;
};
struct ctdb_req_shutdown {
struct ctdb_req_header hdr;
};
struct ctdb_req_connect_wait {
struct ctdb_req_header hdr;
};
struct ctdb_reply_connect_wait {
struct ctdb_req_header hdr;
uint32_t vnn;
uint32_t num_connected;
};
struct ctdb_req_getdbpath {
struct ctdb_req_header hdr;
uint32_t db_id;
@ -757,12 +721,6 @@ int ctdb_daemon_send_message(struct ctdb_context *ctdb, uint32_t vnn,
uint64_t srvid, TDB_DATA data);
/*
wait for all nodes to be connected
*/
void ctdb_daemon_connect_wait(struct ctdb_context *ctdb);
struct lockwait_handle *ctdb_lockwait(struct ctdb_db_context *ctdb_db,
TDB_DATA key,
void (*callback)(void *), void *private_data);
@ -776,8 +734,6 @@ struct ctdb_call_state *ctdb_daemon_call_send_remote(struct ctdb_db_context *ctd
struct ctdb_call *call,
struct ctdb_ltdb_header *header);
void ctdb_request_finished(struct ctdb_context *ctdb, struct ctdb_req_header *hdr);
int ctdb_call_local(struct ctdb_db_context *ctdb_db, struct ctdb_call *call,
struct ctdb_ltdb_header *header, TALLOC_CTX *mem_ctx, TDB_DATA *data,
uint32_t caller);
@ -869,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
*/
@ -989,4 +972,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

View File

@ -12,10 +12,7 @@ for i in `seq 1 $NUMNODES`; do
echo 127.0.0.$i >> nodes.txt
done
echo "Trying $NUMNODES nodes"
for i in `seq 1 $NUMNODES`; do
$VALGRIND bin/ctdbd --reclock=rec.lock --nlist nodes.txt --event-script=tests/events --logfile=- --socket=sock.$i
done
tests/start_daemons.sh $NUMNODES nodes.txt || exit 1
killall -9 ctdb_bench
echo "Trying $NUMNODES nodes"

View File

@ -2,14 +2,7 @@
killall -q ctdbd
echo "Starting 2 ctdb daemons"
$VALGRIND bin/ctdbd --reclock=rec.lock --nlist direct/nodes.txt --event-script=tests/events --logfile=-
$VALGRIND bin/ctdbd --reclock=rec.lock --nlist direct/nodes.txt --event-script=tests/events --logfile=- --socket=sock.2
while bin/ctdb status | grep RECOVERY > /dev/null; do
echo "`date` Waiting for recovery"
sleep 1;
done
tests/start_daemons.sh 2 tests/nodes.txt || exit 1
echo "Testing ping"
$VALGRIND bin/ctdb ping || exit 1
@ -39,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"

View File

@ -10,11 +10,8 @@ for i in `seq 1 $NUMNODES`; do
echo 127.0.0.$i >> nodes.txt
done
killall -q ctdbd
echo "Trying $NUMNODES nodes"
for i in `seq 1 $NUMNODES`; do
$VALGRIND bin/ctdbd --reclock=rec.lock --nlist nodes.txt --event-script=tests/events --logfile=- --socket=sock.$i
done
tests/start_daemons.sh $NUMNODES nodes.txt || exit 1
killall -9 -q ctdb_fetch
for i in `seq 1 $NUMNODES`; do

21
ctdb/tests/start_daemons.sh Executable file
View File

@ -0,0 +1,21 @@
#!/bin/sh
NUMNODES="$1"
NODES=$2
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 $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

View File

@ -91,14 +91,10 @@ static void show_statistics(struct ctdb_statistics *s)
STATISTICS_FIELD(node.reply_dmaster),
STATISTICS_FIELD(node.reply_error),
STATISTICS_FIELD(node.req_message),
STATISTICS_FIELD(node.req_finished),
STATISTICS_FIELD(node.req_control),
STATISTICS_FIELD(node.reply_control),
STATISTICS_FIELD(client.req_call),
STATISTICS_FIELD(client.req_message),
STATISTICS_FIELD(client.req_finished),
STATISTICS_FIELD(client.req_connect_wait),
STATISTICS_FIELD(client.req_shutdown),
STATISTICS_FIELD(client.req_control),
STATISTICS_FIELD(controls.statistics),
STATISTICS_FIELD(controls.get_config),
@ -111,7 +107,6 @@ static void show_statistics(struct ctdb_statistics *s)
STATISTICS_FIELD(controls.traverse_data),
STATISTICS_FIELD(controls.update_seqnum),
STATISTICS_FIELD(controls.enable_seqnum),
STATISTICS_FIELD(controls.set_seqnum_frequency),
STATISTICS_FIELD(controls.register_srvid),
STATISTICS_FIELD(controls.deregister_srvid),
STATISTICS_FIELD(timeouts.call),
@ -522,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
*/
@ -707,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>"},