1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-19 18:50:24 +03:00

merge from ronnie

(This used to be ctdb commit cf23175526d8fde1ef145605fb545584384b6cec)
This commit is contained in:
Andrew Tridgell 2007-05-04 10:43:39 +10:00
commit 648e3835b3
9 changed files with 447 additions and 141 deletions

View File

@ -40,7 +40,7 @@ CTDB_OBJ = $(CTDB_COMMON_OBJ) $(CTDB_TCP_OBJ) $(POPT_OBJ)
OBJS = @TDB_OBJ@ @TALLOC_OBJ@ @LIBREPLACEOBJ@ @INFINIBAND_WRAPPER_OBJ@ $(EXTRA_OBJ) $(EVENTS_OBJ) $(CTDB_OBJ) $(UTIL_OBJ)
BINS = bin/ctdbd bin/ctdbd_test bin/ctdb_test bin/ctdb_bench bin/ctdb_messaging bin/ctdb_fetch bin/ctdb_fetch1 bin/lockwait bin/ctdb_control bin/ctdb_dump @INFINIBAND_BINS@
BINS = bin/ctdbd bin/ctdbd_test bin/ctdb_test bin/ctdb_bench bin/ctdb_messaging bin/ctdb_fetch bin/ctdb_fetch1 bin/lockwait bin/ctdb_control bin/ctdb_dump bin/recoverd @INFINIBAND_BINS@
DIRS = lib bin
@ -75,6 +75,10 @@ bin/ctdb_dump: $(OBJS) tools/ctdb_dump.o
@echo Linking $@
@$(CC) $(CFLAGS) -o $@ tools/ctdb_dump.o $(OBJS) $(LIB_FLAGS)
bin/recoverd: $(OBJS) direct/recoverd.o
@echo Linking $@
@$(CC) $(CFLAGS) -o $@ direct/recoverd.o $(OBJS) $(LIB_FLAGS)
bin/ctdbd_test: $(OBJS) direct/ctdbd_test.o
@echo Linking $@
@$(CC) $(CFLAGS) -o $@ direct/ctdbd_test.o

View File

@ -644,17 +644,30 @@ static void ctdb_client_reply_control(struct ctdb_context *ctdb,
}
/* time out handler for ctdb_control */
static void timeout_func(struct event_context *ev, struct timed_event *te,
struct timeval t, void *private_data)
{
uint32_t *timed_out = (uint32_t *)private_data;
*timed_out = 1;
}
/*
send a ctdb control message
timeout specifies how long we should wait for a reply.
if timeout is NULL we wait indefinitely
*/
int ctdb_control(struct ctdb_context *ctdb, uint32_t destnode, uint64_t srvid,
uint32_t opcode, uint32_t flags, TDB_DATA data,
TALLOC_CTX *mem_ctx, TDB_DATA *outdata, int32_t *status)
TALLOC_CTX *mem_ctx, TDB_DATA *outdata, int32_t *status,
struct timeval *timeout)
{
struct ctdb_client_control_state *state;
struct ctdb_req_control *c;
size_t len;
int ret;
uint32_t timed_out;
/* if the domain socket is not yet open, open it */
if (ctdb->daemon.sd==-1) {
@ -695,10 +708,19 @@ int ctdb_control(struct ctdb_context *ctdb, uint32_t destnode, uint64_t srvid,
}
/* semi-async operation */
while (state->state == CTDB_CALL_WAIT) {
timed_out = 0;
if (timeout) {
event_add_timed(ctdb->ev, mem_ctx, *timeout, timeout_func, &timed_out);
}
while ((state->state == CTDB_CALL_WAIT)
&& (timed_out == 0) ){
event_loop_once(ctdb->ev);
}
if (timed_out) {
talloc_free(state);
return -1;
}
if (outdata) {
*outdata = state->outdata;
outdata->dptr = talloc_memdup(mem_ctx, outdata->dptr, outdata->dsize);
@ -727,7 +749,7 @@ int ctdb_ctrl_process_exists(struct ctdb_context *ctdb, uint32_t destnode, pid_t
ret = ctdb_control(ctdb, destnode, 0,
CTDB_CONTROL_PROCESS_EXISTS, 0, data,
NULL, NULL, &status);
NULL, NULL, &status, NULL);
if (ret != 0) {
DEBUG(0,(__location__ " ctdb_control for process_exists failed\n"));
return -1;
@ -748,7 +770,7 @@ int ctdb_ctrl_status(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_s
ZERO_STRUCT(data);
ret = ctdb_control(ctdb, destnode, 0,
CTDB_CONTROL_STATUS, 0, data,
ctdb, &data, &res);
ctdb, &data, &res, NULL);
if (ret != 0 || res != 0) {
DEBUG(0,(__location__ " ctdb_control for status failed\n"));
return -1;
@ -769,7 +791,7 @@ int ctdb_ctrl_status(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_s
/*
get vnn map from a remote node
*/
int ctdb_ctrl_getvnnmap(struct ctdb_context *ctdb, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_vnn_map **vnnmap)
int ctdb_ctrl_getvnnmap(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_vnn_map **vnnmap)
{
int ret;
TDB_DATA data, outdata;
@ -778,16 +800,12 @@ int ctdb_ctrl_getvnnmap(struct ctdb_context *ctdb, uint32_t destnode, TALLOC_CTX
ZERO_STRUCT(data);
ret = ctdb_control(ctdb, destnode, 0,
CTDB_CONTROL_GETVNNMAP, 0, data,
ctdb, &outdata, &res);
ctdb, &outdata, &res, &timeout);
if (ret != 0 || res != 0) {
DEBUG(0,(__location__ " ctdb_control for getvnnmap failed\n"));
return -1;
}
if (*vnnmap) {
talloc_free(*vnnmap);
*vnnmap=NULL;
}
*vnnmap = (struct ctdb_vnn_map *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
return 0;
@ -805,7 +823,7 @@ int ctdb_ctrl_getrecmode(struct ctdb_context *ctdb, uint32_t destnode, uint32_t
ZERO_STRUCT(data);
ret = ctdb_control(ctdb, destnode, 0,
CTDB_CONTROL_GET_RECMODE, 0, data,
ctdb, &outdata, &res);
ctdb, &outdata, &res, NULL);
if (ret != 0 || res != 0) {
DEBUG(0,(__location__ " ctdb_control for getrecmode failed\n"));
return -1;
@ -831,7 +849,7 @@ int ctdb_ctrl_setrecmode(struct ctdb_context *ctdb, uint32_t destnode, uint32_t
ret = ctdb_control(ctdb, destnode, 0,
CTDB_CONTROL_SET_RECMODE, 0, data,
ctdb, &outdata, &res);
ctdb, &outdata, &res, NULL);
if (ret != 0 || res != 0) {
DEBUG(0,(__location__ " ctdb_control for getrecmode failed\n"));
return -1;
@ -852,7 +870,7 @@ int ctdb_ctrl_getdbmap(struct ctdb_context *ctdb, uint32_t destnode, TALLOC_CTX
ZERO_STRUCT(data);
ret = ctdb_control(ctdb, destnode, 0,
CTDB_CONTROL_GET_DBMAP, 0, data,
ctdb, &outdata, &res);
ctdb, &outdata, &res, NULL);
if (ret != 0 || res != 0) {
DEBUG(0,(__location__ " ctdb_control for getdbmap failed\n"));
return -1;
@ -871,8 +889,9 @@ int ctdb_ctrl_getdbmap(struct ctdb_context *ctdb, uint32_t destnode, TALLOC_CTX
/*
get a list of nodes (vnn and flags ) from a remote node
*/
int ctdb_ctrl_getnodemap(struct ctdb_context *ctdb, uint32_t destnode,
TALLOC_CTX *mem_ctx, struct ctdb_node_map **nodemap)
int ctdb_ctrl_getnodemap(struct ctdb_context *ctdb,
struct timeval timeout, uint32_t destnode,
TALLOC_CTX *mem_ctx, struct ctdb_node_map **nodemap)
{
int ret;
TDB_DATA data, outdata;
@ -881,16 +900,12 @@ int ctdb_ctrl_getnodemap(struct ctdb_context *ctdb, uint32_t destnode,
ZERO_STRUCT(data);
ret = ctdb_control(ctdb, destnode, 0,
CTDB_CONTROL_GET_NODEMAP, 0, data,
ctdb, &outdata, &res);
ctdb, &outdata, &res, &timeout);
if (ret != 0 || res != 0) {
DEBUG(0,(__location__ " ctdb_control for getnodes failed\n"));
return -1;
}
if (*nodemap) {
talloc_free(*nodemap);
*nodemap = NULL;
}
*nodemap = (struct ctdb_node_map *)talloc_memdup(mem_ctx, outdata.dptr, outdata.dsize);
return 0;
@ -910,7 +925,7 @@ int ctdb_ctrl_setvnnmap(struct ctdb_context *ctdb, uint32_t destnode, TALLOC_CTX
ret = ctdb_control(ctdb, destnode, 0,
CTDB_CONTROL_SETVNNMAP, 0, data,
ctdb, &outdata, &res);
ctdb, &outdata, &res, NULL);
if (ret != 0 || res != 0) {
DEBUG(0,(__location__ " ctdb_control for setvnnmap failed\n"));
return -1;
@ -937,7 +952,7 @@ int ctdb_ctrl_pulldb(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid
ret = ctdb_control(ctdb, destnode, 0,
CTDB_CONTROL_PULL_DB, 0, indata,
mem_ctx, &outdata, &res);
mem_ctx, &outdata, &res, NULL);
if (ret != 0 || res != 0) {
DEBUG(0,(__location__ " ctdb_control for pulldb failed\n"));
return -1;
@ -1004,7 +1019,7 @@ int ctdb_ctrl_copydb(struct ctdb_context *ctdb, uint32_t sourcenode, uint32_t de
ret = ctdb_control(ctdb, sourcenode, 0,
CTDB_CONTROL_PULL_DB, 0, indata,
mem_ctx, &outdata, &res);
mem_ctx, &outdata, &res, NULL);
if (ret != 0 || res != 0) {
DEBUG(0,(__location__ " ctdb_control for pulldb failed\n"));
return -1;
@ -1012,7 +1027,7 @@ int ctdb_ctrl_copydb(struct ctdb_context *ctdb, uint32_t sourcenode, uint32_t de
ret = ctdb_control(ctdb, destnode, 0,
CTDB_CONTROL_PUSH_DB, 0, outdata,
mem_ctx, NULL, &res);
mem_ctx, NULL, &res, NULL);
if (ret != 0 || res != 0) {
DEBUG(0,(__location__ " ctdb_control for pushdb failed\n"));
return -1;
@ -1038,7 +1053,7 @@ int ctdb_ctrl_setdmaster(struct ctdb_context *ctdb, uint32_t destnode, TALLOC_CT
ret = ctdb_control(ctdb, destnode, 0,
CTDB_CONTROL_SET_DMASTER, 0, indata,
mem_ctx, &outdata, &res);
mem_ctx, &outdata, &res, NULL);
if (ret != 0 || res != 0) {
DEBUG(0,(__location__ " ctdb_control for setdmaster failed\n"));
return -1;
@ -1063,7 +1078,7 @@ int ctdb_ctrl_cleardb(struct ctdb_context *ctdb, uint32_t destnode, TALLOC_CTX *
ret = ctdb_control(ctdb, destnode, 0,
CTDB_CONTROL_CLEAR_DB, 0, indata,
mem_ctx, &outdata, &res);
mem_ctx, &outdata, &res, NULL);
if (ret != 0 || res != 0) {
DEBUG(0,(__location__ " ctdb_control for cleardb failed\n"));
return -1;
@ -1074,36 +1089,26 @@ int ctdb_ctrl_cleardb(struct ctdb_context *ctdb, uint32_t destnode, TALLOC_CTX *
int ctdb_ctrl_write_record(struct ctdb_context *ctdb, uint32_t destnode, TALLOC_CTX *mem_ctx, uint32_t dbid, TDB_DATA key, TDB_DATA data)
{
int ret, len;
struct ctdb_write_record *wr;
TDB_DATA indata, outdata;
int32_t res;
unsigned char *ptr;
int ret, len;
len = offsetof(struct ctdb_write_record, blob)+key.dsize+data.dsize;
wr = (struct ctdb_write_record *)talloc_zero_size(mem_ctx, len);
wr->dbid = dbid;
wr->keylen = key.dsize;
wr->datalen = data.dsize;
memcpy(&wr->blob[0], &key.dptr[0], key.dsize);
memcpy(&wr->blob[key.dsize], &data.dptr[0], data.dsize);
len = 4; /* dbid */
len += 4; /* keylen */
len += (key.dsize+CTDB_DS_ALIGNMENT-1)& ~(CTDB_DS_ALIGNMENT-1);
len += 4; /* datalen */
len += (data.dsize+CTDB_DS_ALIGNMENT-1)& ~(CTDB_DS_ALIGNMENT-1);
indata.dsize = len;
indata.dptr = (unsigned char *)talloc_array(mem_ctx, uint8_t, len);
ptr = indata.dptr;
*((uint32_t *)ptr) = dbid;
ptr += 4;
*((uint32_t *)ptr) = key.dsize;
ptr += 4;
memcpy(ptr, key.dptr, key.dsize);
ptr += (key.dsize+CTDB_DS_ALIGNMENT-1)& ~(CTDB_DS_ALIGNMENT-1);
*((uint32_t *)ptr) = data.dsize;
ptr += 4;
memcpy(ptr, data.dptr, data.dsize);
ptr += (data.dsize+CTDB_DS_ALIGNMENT-1)& ~(CTDB_DS_ALIGNMENT-1);
indata.dptr = (unsigned char *)wr;
ret = ctdb_control(ctdb, destnode, 0,
CTDB_CONTROL_WRITE_RECORD, 0, indata,
mem_ctx, &outdata, &res);
mem_ctx, &outdata, &res, NULL);
if (ret != 0 || res != 0) {
DEBUG(0,(__location__ " ctdb_control for write record failed\n"));
return -1;
@ -1123,7 +1128,7 @@ int ctdb_ctrl_ping(struct ctdb_context *ctdb, uint32_t destnode)
ZERO_STRUCT(data);
ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_PING, 0,
data, NULL, NULL, &res);
data, NULL, NULL, &res, NULL);
if (ret != 0) {
return -1;
}
@ -1142,7 +1147,7 @@ int ctdb_ctrl_get_config(struct ctdb_context *ctdb)
ZERO_STRUCT(data);
ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_CONFIG, 0,
data, ctdb, &data, &res);
data, ctdb, &data, &res, NULL);
if (ret != 0 || res != 0) {
return -1;
}
@ -1177,7 +1182,7 @@ int ctdb_ctrl_getdbpath(struct ctdb_context *ctdb, uint32_t dbid, TALLOC_CTX *me
ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0,
CTDB_CONTROL_GETDBPATH, 0, data,
mem_ctx, &data, &res);
mem_ctx, &data, &res, NULL);
if (ret != 0 || res != 0) {
return -1;
}
@ -1203,7 +1208,7 @@ int ctdb_ctrl_get_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, uint3
ZERO_STRUCT(data);
ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_DEBUG, 0, data,
ctdb, &data, &res);
ctdb, &data, &res, NULL);
if (ret != 0 || res != 0) {
return -1;
}
@ -1230,7 +1235,7 @@ int ctdb_ctrl_set_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, uint3
data.dsize = sizeof(level);
ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SET_DEBUG, 0, data,
NULL, NULL, &res);
NULL, NULL, &res, NULL);
if (ret != 0 || res != 0) {
return -1;
}
@ -1241,8 +1246,10 @@ int ctdb_ctrl_set_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, uint3
/*
get a list of connected nodes
*/
uint32_t *ctdb_get_connected_nodes(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx,
uint32_t *num_nodes)
uint32_t *ctdb_get_connected_nodes(struct ctdb_context *ctdb,
struct timeval timeout,
TALLOC_CTX *mem_ctx,
uint32_t *num_nodes)
{
struct ctdb_node_map *map=NULL;
int ret, i;
@ -1250,7 +1257,7 @@ uint32_t *ctdb_get_connected_nodes(struct ctdb_context *ctdb, TALLOC_CTX *mem_ct
*num_nodes = 0;
ret = ctdb_ctrl_getnodemap(ctdb, CTDB_CURRENT_NODE, mem_ctx, &map);
ret = ctdb_ctrl_getnodemap(ctdb, timeout, CTDB_CURRENT_NODE, mem_ctx, &map);
if (ret != 0) {
return NULL;
}
@ -1283,7 +1290,7 @@ int ctdb_status_reset(struct ctdb_context *ctdb, uint32_t destnode)
ZERO_STRUCT(data);
ret = ctdb_control(ctdb, destnode, 0,
CTDB_CONTROL_STATUS_RESET, 0, data,
NULL, NULL, &res);
NULL, NULL, &res, NULL);
if (ret != 0 || res != 0) {
DEBUG(0,(__location__ " ctdb_control for reset status failed\n"));
return -1;
@ -1314,7 +1321,7 @@ struct ctdb_db_context *ctdb_attach(struct ctdb_context *ctdb, const char *name)
/* tell ctdb daemon to attach */
ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_DB_ATTACH,
0, data, ctdb_db, &data, &res);
0, data, ctdb_db, &data, &res, NULL);
if (ret != 0 || res != 0 || data.dsize != sizeof(uint32_t)) {
DEBUG(0,("Failed to attach to database '%s'\n", name));
talloc_free(ctdb_db);
@ -1362,7 +1369,7 @@ int ctdb_set_call(struct ctdb_db_context *ctdb_db, ctdb_fn_t fn, uint32_t id)
data.dsize = sizeof(c);
ret = ctdb_control(ctdb_db->ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_SET_CALL, 0,
data, NULL, NULL, &status);
data, NULL, NULL, &status, NULL);
if (ret != 0 || status != 0) {
DEBUG(0,("ctdb_set_call failed for call %u\n", id));
return -1;
@ -1397,7 +1404,7 @@ int ctdb_traverse_all(struct ctdb_db_context *ctdb_db, uint64_t srvid)
data.dsize = sizeof(t);
ret = ctdb_control(ctdb_db->ctdb, CTDB_CURRENT_NODE, 0, CTDB_CONTROL_TRAVERSE_START, 0,
data, NULL, NULL, &status);
data, NULL, NULL, &status, NULL);
if (ret != 0 || status != 0) {
DEBUG(0,("ctdb_traverse_all failed\n"));
return -1;

View File

@ -326,59 +326,8 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
return 0;
}
case CTDB_CONTROL_WRITE_RECORD: {
uint32_t dbid;
struct ctdb_db_context *ctdb_db;
unsigned char *ptr;
TDB_DATA key, data;
struct ctdb_ltdb_header header;
int ret;
outdata->dsize = 0;
outdata->dptr = NULL;
dbid = ((uint32_t *)(&indata.dptr[0]))[0];
ctdb_db = find_ctdb_db(ctdb, dbid);
if (!ctdb_db) {
DEBUG(0,(__location__ " Unknown db 0x%08x\n",dbid));
return -1;
}
ptr = &indata.dptr[4];
key.dsize = *((uint32_t *)(ptr));
ptr += 4;
key.dptr = ptr;
ptr += (key.dsize+CTDB_DS_ALIGNMENT-1)& ~(CTDB_DS_ALIGNMENT-1);
data.dsize = *((uint32_t *)(ptr));
ptr += 4;
data.dptr = ptr;
ptr += (data.dsize+CTDB_DS_ALIGNMENT-1)& ~(CTDB_DS_ALIGNMENT-1);
ret = ctdb_ltdb_lock(ctdb_db, key);
if (ret != 0) {
DEBUG(0, (__location__ "Unable to lock db\n"));
return -1;
}
ret = ctdb_ltdb_fetch(ctdb_db, key, &header, outdata, NULL);
if (ret != 0) {
DEBUG(0, (__location__ "Unable to fetch record\n"));
ctdb_ltdb_unlock(ctdb_db, key);
return -1;
}
header.rsn++;
ret = ctdb_ltdb_store(ctdb_db, key, &header, data);
if (ret != 0) {
DEBUG(0, (__location__ "Unable to store record\n"));
ctdb_ltdb_unlock(ctdb_db, key);
return -1;
}
ctdb_ltdb_unlock(ctdb_db, key);
return 0;
}
case CTDB_CONTROL_WRITE_RECORD:
return ctdb_control_writerecord(ctdb, opcode, indata, outdata);
case CTDB_CONTROL_SET_RECMODE: {
ctdb->recovery_mode = ((uint32_t *)(&indata.dptr[0]))[0];

View File

@ -109,3 +109,54 @@ ctdb_control_getnodemap(struct ctdb_context *ctdb, uint32_t opcode, TDB_DATA ind
return 0;
}
int
ctdb_control_writerecord(struct ctdb_context *ctdb, uint32_t opcode, TDB_DATA indata, TDB_DATA *outdata)
{
struct ctdb_write_record *wr;
struct ctdb_db_context *ctdb_db;
struct ctdb_ltdb_header header;
TDB_DATA key, data;
int ret;
outdata->dsize = 0;
outdata->dptr = NULL;
wr = (struct ctdb_write_record *)indata.dptr;
ctdb_db = find_ctdb_db(ctdb, wr->dbid);
if (!ctdb_db) {
DEBUG(0,(__location__ " Unknown db 0x%08x\n", wr->dbid));
return -1;
}
key.dsize = wr->keylen;
key.dptr = (unsigned char *)talloc_memdup(outdata, &wr->blob[0], wr->keylen);
data.dsize = wr->datalen;
data.dptr = (unsigned char *)talloc_memdup(outdata, &wr->blob[wr->keylen], wr->datalen);
ret = ctdb_ltdb_lock(ctdb_db, key);
if (ret != 0) {
DEBUG(0, (__location__ "Unable to lock db\n"));
return -1;
}
ret = ctdb_ltdb_fetch(ctdb_db, key, &header, outdata, NULL);
if (ret != 0) {
DEBUG(0, (__location__ "Unable to fetch record\n"));
ctdb_ltdb_unlock(ctdb_db, key);
return -1;
}
header.rsn++;
ret = ctdb_ltdb_store(ctdb_db, key, &header, data);
if (ret != 0) {
DEBUG(0, (__location__ "Unable to store record\n"));
ctdb_ltdb_unlock(ctdb_db, key);
return -1;
}
ctdb_ltdb_unlock(ctdb_db, key);
return 0;
}

275
ctdb/direct/recoverd.c Normal file
View File

@ -0,0 +1,275 @@
/*
ctdb recovery daemon
Copyright (C) Ronnie Sahlberg 2007
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "includes.h"
#include "lib/events/events.h"
#include "system/filesys.h"
#include "popt.h"
#include "cmdline.h"
#include "../include/ctdb.h"
#include "../include/ctdb_private.h"
static int timed_out = 0;
/*
show usage message
*/
static void usage(void)
{
printf(
"Usage: recoverd\n"
);
exit(1);
}
void timeout_func(struct event_context *ev, struct timed_event *te,
struct timeval t, void *private_data)
{
timed_out = 1;
}
void do_recovery(struct ctdb_context *ctdb, struct event_context *ev)
{
printf("we need to do recovery !!!\n");
}
void recoverd(struct ctdb_context *ctdb, struct event_context *ev)
{
uint32_t vnn, num_active;
TALLOC_CTX *mem_ctx=NULL;
struct ctdb_node_map *nodemap=NULL;
struct ctdb_node_map *remote_nodemap=NULL;
struct ctdb_vnn_map *vnnmap=NULL;
struct ctdb_vnn_map *remote_vnnmap=NULL;
int i, j, ret;
again:
printf("check if we need to do recovery\n");
if (mem_ctx) {
talloc_free(mem_ctx);
mem_ctx = NULL;
}
mem_ctx = talloc_new(ctdb);
if (!mem_ctx) {
DEBUG(0,("Failed to create temporary context\n"));
exit(-1);
}
/* we only check for recovery once every second */
timed_out = 0;
event_add_timed(ctdb->ev, mem_ctx, timeval_current_ofs(1, 0), timeout_func, ctdb);
while (!timed_out) {
event_loop_once(ev);
}
/* get our vnn number */
vnn = ctdb_get_vnn(ctdb);
/* get number of nodes */
ret = ctdb_ctrl_getnodemap(ctdb, timeval_current_ofs(1, 0), vnn, mem_ctx, &nodemap);
if (ret != 0) {
printf("Unable to get nodemap from node %u\n", vnn);
goto again;
}
/* count how many active nodes there are */
num_active = 0;
for (i=0; i<nodemap->num; i++) {
if (nodemap->nodes[i].flags&NODE_FLAGS_CONNECTED) {
num_active++;
}
}
/* get the nodemap for all active remote nodes and verify
they are the same as for this node
*/
for (j=0; j<nodemap->num; j++) {
if (!(nodemap->nodes[j].flags&NODE_FLAGS_CONNECTED)) {
continue;
}
if (nodemap->nodes[j].vnn == vnn) {
continue;
}
ret = ctdb_ctrl_getnodemap(ctdb, timeval_current_ofs(1, 0), nodemap->nodes[j].vnn, mem_ctx, &remote_nodemap);
if (ret != 0) {
printf("Unable to get nodemap from remote node %u\n", nodemap->nodes[j].vnn);
goto again;
}
/* if the nodes disagree on how many nodes there are
then this is a good reason to try recovery
*/
if (remote_nodemap->num != nodemap->num) {
printf("Remote node:%d has different node count. %d vs %d of the local node\n", nodemap->nodes[j].vnn, remote_nodemap->num, nodemap->num);
do_recovery(ctdb, ev);
goto again;
}
/* if the nodes disagree on which nodes exist and are
active, then that is also a good reason to do recovery
*/
for (i=0;i<nodemap->num;i++) {
if ((remote_nodemap->nodes[i].vnn != nodemap->nodes[i].vnn)
|| (remote_nodemap->nodes[i].flags != nodemap->nodes[i].flags)) {
printf("Remote node:%d has different nodemap.\n", nodemap->nodes[j].vnn);
do_recovery(ctdb, ev);
goto again;
}
}
}
/* get the vnnmap */
ret = ctdb_ctrl_getvnnmap(ctdb, timeval_current_ofs(1, 0), vnn, mem_ctx, &vnnmap);
if (ret != 0) {
printf("Unable to get vnnmap from node %u\n", vnn);
goto again;
}
/* there better be the same number of lmasters in the vnn map
as there are active nodes or well have to do a recovery
*/
if (vnnmap->size != num_active) {
printf("The vnnmap count is different from the number of active nodes. %d vs %d\n", vnnmap->size, num_active);
do_recovery(ctdb, ev);
goto again;
}
/* verify that all active nodes in the nodemap also exist in
the vnnmap.
*/
for (j=0; j<nodemap->num; j++) {
if (!(nodemap->nodes[j].flags&NODE_FLAGS_CONNECTED)) {
continue;
}
if (nodemap->nodes[j].vnn == vnn) {
continue;
}
for (i=0; i<vnnmap->size; i++) {
if (vnnmap->map[i] == nodemap->nodes[j].vnn) {
break;
}
}
if (i==vnnmap->size) {
printf("Node %d is active in the nodemap but did not exist in the vnnmap\n", nodemap->nodes[j].vnn);
do_recovery(ctdb, ev);
goto again;
}
}
/* verify that all other nodes have the same vnnmap */
for (j=0; j<nodemap->num; j++) {
if (!(nodemap->nodes[j].flags&NODE_FLAGS_CONNECTED)) {
continue;
}
if (nodemap->nodes[j].vnn == vnn) {
continue;
}
ret = ctdb_ctrl_getvnnmap(ctdb, timeval_current_ofs(1, 0), nodemap->nodes[j].vnn, mem_ctx, &remote_vnnmap);
if (ret != 0) {
printf("Unable to get vnnmap from remote node %u\n", nodemap->nodes[j].vnn);
goto again;
}
/* verify the vnnmap size is the same */
if (vnnmap->size != remote_vnnmap->size) {
printf("Remote node %d has different size of vnnmap. %d vs %d (ours)\n", nodemap->nodes[j].vnn, remote_vnnmap->size, vnnmap->size);
do_recovery(ctdb, ev);
goto again;
}
/* verify the vnnmap is the same */
for (i=0;i<vnnmap->size;i++) {
if (remote_vnnmap->map[i] != vnnmap->map[i]) {
printf("Remote node %d has different vnnmap.\n", nodemap->nodes[j].vnn);
do_recovery(ctdb, ev);
goto again;
}
}
}
printf("no we did not need to do recovery\n");
goto again;
}
/*
main program
*/
int main(int argc, const char *argv[])
{
struct ctdb_context *ctdb;
struct poptOption popt_options[] = {
POPT_AUTOHELP
POPT_CTDB_CMDLINE
POPT_TABLEEND
};
int opt;
const char **extra_argv;
int extra_argc = 0;
int ret;
poptContext pc;
struct event_context *ev;
pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
while ((opt = poptGetNextOpt(pc)) != -1) {
switch (opt) {
default:
fprintf(stderr, "Invalid option %s: %s\n",
poptBadOption(pc, 0), poptStrerror(opt));
exit(1);
}
}
/* setup the remaining options for the main program to use */
extra_argv = poptGetArgs(pc);
if (extra_argv) {
extra_argv++;
while (extra_argv[extra_argc]) extra_argc++;
}
#if 0
if (extra_argc < 1) {
usage();
}
#endif
ev = event_context_init(NULL);
/* initialise ctdb */
ctdb = ctdb_cmdline_client(ev);
if (ctdb == NULL) {
printf("Failed to init ctdb\n");
exit(1);
}
recoverd(ctdb, ev);
return ret;
}

View File

@ -201,7 +201,9 @@ struct ctdb_status;
int ctdb_ctrl_status(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_status *status);
struct ctdb_vnn_map;
int ctdb_ctrl_getvnnmap(struct ctdb_context *ctdb, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_vnn_map **vnnmap);
int ctdb_ctrl_getvnnmap(struct ctdb_context *ctdb,
struct timeval timeout, uint32_t destnode,
TALLOC_CTX *mem_ctx, struct ctdb_vnn_map **vnnmap);
int ctdb_ctrl_setvnnmap(struct ctdb_context *ctdb, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_vnn_map *vnnmap);
/* table that contains a list of all dbids on a node
@ -224,7 +226,8 @@ struct ctdb_node_map {
uint32_t num;
struct ctdb_node_and_flags nodes[1];
};
int ctdb_ctrl_getnodemap(struct ctdb_context *ctdb, uint32_t destnode,
int ctdb_ctrl_getnodemap(struct ctdb_context *ctdb,
struct timeval timeout, uint32_t destnode,
TALLOC_CTX *mem_ctx, struct ctdb_node_map **nodemap);
struct ctdb_key_list {
@ -275,7 +278,9 @@ int ctdb_ctrl_getrecmode(struct ctdb_context *ctdb, uint32_t destnode, uint32_t
*/
int ctdb_ctrl_setrecmode(struct ctdb_context *ctdb, uint32_t destnode, uint32_t recmode);
uint32_t *ctdb_get_connected_nodes(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx,
uint32_t *ctdb_get_connected_nodes(struct ctdb_context *ctdb,
struct timeval timeout,
TALLOC_CTX *mem_ctx,
uint32_t *num_nodes);
int ctdb_status_reset(struct ctdb_context *ctdb, uint32_t destnode);

View File

@ -173,6 +173,16 @@ struct ctdb_vnn_map {
uint32_t map[1];
};
/* a structure that contains the elements required for the write record
control
*/
struct ctdb_write_record {
uint32_t dbid;
uint32_t keylen;
uint32_t datalen;
unsigned char blob[1];
};
/* main state of the ctdb daemon */
struct ctdb_context {
struct event_context *ev;
@ -632,7 +642,8 @@ int ctdb_daemon_set_call(struct ctdb_context *ctdb, uint32_t db_id,
int ctdb_control(struct ctdb_context *ctdb, uint32_t destnode, uint64_t srvid,
uint32_t opcode, uint32_t flags, TDB_DATA data,
TALLOC_CTX *mem_ctx, TDB_DATA *outdata, int32_t *status);
TALLOC_CTX *mem_ctx, TDB_DATA *outdata, int32_t *status,
struct timeval *timeout);
@ -649,6 +660,7 @@ int ctdb_control_getvnnmap(struct ctdb_context *ctdb, uint32_t opcode, TDB_DATA
int ctdb_control_setvnnmap(struct ctdb_context *ctdb, uint32_t opcode, TDB_DATA indata, TDB_DATA *outdata);
int ctdb_control_getdbmap(struct ctdb_context *ctdb, uint32_t opcode, TDB_DATA indata, TDB_DATA *outdata);
int ctdb_control_getnodemap(struct ctdb_context *ctdb, uint32_t opcode, TDB_DATA indata, TDB_DATA *outdata);
int ctdb_control_writerecord(struct ctdb_context *ctdb, uint32_t opcode, TDB_DATA indata, TDB_DATA *outdata);
struct ctdb_traverse_start {

View File

@ -3,32 +3,32 @@
killall -q ctdbd
echo "Starting 2 ctdb daemons"
bin/ctdbd --nlist direct/nodes.txt
bin/ctdbd --nlist direct/nodes.txt
$VALGRIND bin/ctdbd --nlist direct/nodes.txt
$VALGRIND bin/ctdbd --nlist direct/nodes.txt
echo "Testing ping"
bin/ctdb_control ping || exit 1
$VALGRIND bin/ctdb_control ping || exit 1
echo "Testing status"
bin/ctdb_control status all || exit 1
$VALGRIND bin/ctdb_control status all || exit 1
echo "Testing statusreset"
bin/ctdb_control statusreset all || exit 1
$VALGRIND bin/ctdb_control statusreset all || exit 1
echo "Testing debug"
bin/ctdb_control debug all 5 || exit 1
bin/ctdb_control debuglevel || exit 1
bin/ctdb_control debug all 0 || exit 1
bin/ctdb_control debuglevel || exit 1
$VALGRIND bin/ctdb_control debug all 5 || exit 1
$VALGRIND bin/ctdb_control debuglevel || exit 1
$VALGRIND bin/ctdb_control debug all 0 || exit 1
$VALGRIND bin/ctdb_control debuglevel || exit 1
echo "Testing map calls"
bin/ctdb_control getvnnmap 0 || exit 1
$VALGRIND bin/ctdb_control getvnnmap 0 || exit 1
echo "Attaching to some databases"
bin/ctdb_control attach test1.tdb || exit 1
bin/ctdb_control attach test2.tdb || exit 1
$VALGRIND bin/ctdb_control attach test1.tdb || exit 1
$VALGRIND bin/ctdb_control attach test2.tdb || exit 1
echo "Testing getdbmap"
bin/ctdb_control getdbmap 0 || exit 1
$VALGRIND bin/ctdb_control getdbmap 0 || exit 1
killall -q ctdbd

View File

@ -127,7 +127,7 @@ static int control_status_all(struct ctdb_context *ctdb)
uint32_t *nodes;
uint32_t num_nodes;
nodes = ctdb_get_connected_nodes(ctdb, ctdb, &num_nodes);
nodes = ctdb_get_connected_nodes(ctdb, timeval_current_ofs(1, 0), ctdb, &num_nodes);
CTDB_NO_MEMORY(ctdb, nodes);
ZERO_STRUCT(status);
@ -197,7 +197,7 @@ static int control_status_reset_all(struct ctdb_context *ctdb)
uint32_t *nodes;
uint32_t num_nodes;
nodes = ctdb_get_connected_nodes(ctdb, ctdb, &num_nodes);
nodes = ctdb_get_connected_nodes(ctdb, timeval_current_ofs(1, 0), ctdb, &num_nodes);
CTDB_NO_MEMORY(ctdb, nodes);
for (i=0;i<num_nodes;i++) {
@ -260,7 +260,7 @@ static int control_recover(struct ctdb_context *ctdb, int argc, const char **arg
/* 1: find a list of all nodes */
printf("\n1: fetching list of nodes\n");
ret = ctdb_ctrl_getnodemap(ctdb, vnn, ctdb, &nodemap);
ret = ctdb_ctrl_getnodemap(ctdb, timeval_current_ofs(1, 0), vnn, ctdb, &nodemap);
if (ret != 0) {
printf("Unable to get nodemap from node %u\n", vnn);
return ret;
@ -445,7 +445,7 @@ static int control_getvnnmap(struct ctdb_context *ctdb, int argc, const char **a
vnn = strtoul(argv[0], NULL, 0);
ret = ctdb_ctrl_getvnnmap(ctdb, vnn, ctdb, &vnnmap);
ret = ctdb_ctrl_getvnnmap(ctdb, timeval_current_ofs(1, 0), vnn, ctdb, &vnnmap);
if (ret != 0) {
printf("Unable to get vnnmap from node %u\n", vnn);
return ret;
@ -624,7 +624,7 @@ static int control_getnodemap(struct ctdb_context *ctdb, int argc, const char **
vnn = strtoul(argv[0], NULL, 0);
ret = ctdb_ctrl_getnodemap(ctdb, vnn, ctdb, &nodemap);
ret = ctdb_ctrl_getnodemap(ctdb, timeval_current_ofs(1, 0), vnn, ctdb, &nodemap);
if (ret != 0) {
printf("Unable to get nodemap from node %u\n", vnn);
return ret;
@ -762,6 +762,7 @@ static int control_createdb(struct ctdb_context *ctdb, int argc, const char **ar
int ret;
int32_t res;
TDB_DATA data;
struct timeval timeout;
if (argc < 2) {
usage();
@ -773,8 +774,10 @@ static int control_createdb(struct ctdb_context *ctdb, int argc, const char **ar
/* tell ctdb daemon to attach */
data.dptr = discard_const(dbname);
data.dsize = strlen(dbname)+1;
timeout = timeval_current_ofs(1, 0);
ret = ctdb_control(ctdb, vnn, 0, CTDB_CONTROL_DB_ATTACH,
0, data, ctdb, &data, &res);
0, data, ctdb, &data, &res,
&timeout);
if (ret != 0 || res != 0 || data.dsize != sizeof(uint32_t)) {
DEBUG(0,("Failed to attach to database '%s'\n", dbname));
return -1;
@ -792,7 +795,7 @@ static int control_ping(struct ctdb_context *ctdb, int argc, const char **argv)
uint32_t *nodes;
uint32_t num_nodes;
nodes = ctdb_get_connected_nodes(ctdb, ctdb, &num_nodes);
nodes = ctdb_get_connected_nodes(ctdb, timeval_current_ofs(1, 0), ctdb, &num_nodes);
CTDB_NO_MEMORY(ctdb, nodes);
for (i=0;i<num_nodes;i++) {
@ -819,7 +822,7 @@ static int control_debuglevel(struct ctdb_context *ctdb, int argc, const char **
uint32_t *nodes;
uint32_t num_nodes;
nodes = ctdb_get_connected_nodes(ctdb, ctdb, &num_nodes);
nodes = ctdb_get_connected_nodes(ctdb, timeval_current_ofs(1, 0), ctdb, &num_nodes);
CTDB_NO_MEMORY(ctdb, nodes);
for (i=0;i<num_nodes;i++) {
@ -862,7 +865,7 @@ static int control_debug(struct ctdb_context *ctdb, int argc, const char **argv)
return 0;
}
nodes = ctdb_get_connected_nodes(ctdb, ctdb, &num_nodes);
nodes = ctdb_get_connected_nodes(ctdb, timeval_current_ofs(1, 0), ctdb, &num_nodes);
CTDB_NO_MEMORY(ctdb, nodes);
for (i=0;i<num_nodes;i++) {
ret = ctdb_ctrl_set_debuglevel(ctdb, nodes[i], level);