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:
commit
1ee8989bd4
@ -17,3 +17,5 @@ ctdb-3
|
||||
nodes.txt
|
||||
TAGS
|
||||
web/packages
|
||||
rec.lock
|
||||
test.db
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
142
ctdb/common/ctdb_tunables.c
Normal 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;
|
||||
}
|
@ -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=
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
4
ctdb/config/events.d/README
Normal file
4
ctdb/config/events.d/README
Normal file
@ -0,0 +1,4 @@
|
||||
This directory is where you should put any local or application
|
||||
specific event scripts for ctdb to call.
|
||||
|
||||
|
@ -1,4 +0,0 @@
|
||||
127.0.0.1
|
||||
127.0.0.2
|
||||
127.0.0.3
|
||||
127.0.0.4
|
@ -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.
|
||||
|
||||
|
@ -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;
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
127.0.0.1
|
||||
127.0.0.2
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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
21
ctdb/tests/start_daemons.sh
Executable 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
|
@ -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>"},
|
||||
|
Loading…
x
Reference in New Issue
Block a user