mirror of
https://github.com/samba-team/samba.git
synced 2025-03-20 22:50:26 +03:00
merged from ronnie
(This used to be ctdb commit 77255f93d432829387dc328b0ae726cc9cba8d68)
This commit is contained in:
commit
0415881893
@ -147,7 +147,7 @@ XXX table for the daemons.
|
||||
exit(1);
|
||||
}
|
||||
ctdb->vnn_map->generation = 1;
|
||||
ctdb->vnn_map->size = 1024;
|
||||
ctdb->vnn_map->size = ctdb->num_nodes;
|
||||
ctdb->vnn_map->map = talloc_array(ctdb->vnn_map, uint32_t, ctdb->vnn_map->size);
|
||||
if (ctdb->vnn_map->map == NULL) {
|
||||
DEBUG(0,(__location__ " Unable to allocate vnn_map->map structure\n"));
|
||||
@ -192,7 +192,7 @@ struct ctdb_context *ctdb_cmdline_client(struct event_context *ev)
|
||||
}
|
||||
|
||||
/* get our config */
|
||||
ret = ctdb_get_config(ctdb);
|
||||
ret = ctdb_ctrl_get_config(ctdb);
|
||||
if (ret != 0) {
|
||||
DEBUG(0,(__location__ " Failed to get ctdb config\n"));
|
||||
talloc_free(ctdb);
|
||||
|
@ -255,6 +255,18 @@ void ctdb_recv_pkt(struct ctdb_context *ctdb, uint8_t *data, uint32_t length)
|
||||
hdr->generation));
|
||||
break;
|
||||
}
|
||||
/* if we are in recovery mode we discard all traffic
|
||||
until the cluster has recovered.
|
||||
*/
|
||||
if (ctdb->recovery_mode != CTDB_RECOVERY_NORMAL) {
|
||||
DEBUG(0,(__location__ " ctdb request %d of type"
|
||||
" %d length %d from node %d to %d"
|
||||
" while we are in recovery mode\n",
|
||||
hdr->reqid, hdr->operation, hdr->length,
|
||||
hdr->srcnode, hdr->destnode));
|
||||
break;
|
||||
}
|
||||
|
||||
ctdb->status.count.req_call++;
|
||||
ctdb_request_call(ctdb, hdr);
|
||||
break;
|
||||
@ -462,6 +474,7 @@ struct ctdb_context *ctdb_init(struct event_context *ev)
|
||||
|
||||
ctdb = talloc_zero(ev, struct ctdb_context);
|
||||
ctdb->ev = ev;
|
||||
ctdb->recovery_mode = CTDB_RECOVERY_NORMAL;
|
||||
ctdb->upcalls = &ctdb_upcalls;
|
||||
ctdb->idr = idr_init(ctdb);
|
||||
ctdb->max_lacount = CTDB_DEFAULT_MAX_LACOUNT;
|
||||
|
@ -461,7 +461,7 @@ void ctdb_connect_wait(struct ctdb_context *ctdb)
|
||||
ctdb_daemon_connect_wait(ctdb);
|
||||
|
||||
/* get other config variables */
|
||||
ctdb_get_config(ctdb);
|
||||
ctdb_ctrl_get_config(ctdb);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -716,7 +716,7 @@ int ctdb_control(struct ctdb_context *ctdb, uint32_t destnode, uint64_t srvid,
|
||||
/*
|
||||
a process exists call. Returns 0 if process exists, -1 otherwise
|
||||
*/
|
||||
int ctdb_process_exists(struct ctdb_context *ctdb, uint32_t destnode, pid_t pid)
|
||||
int ctdb_ctrl_process_exists(struct ctdb_context *ctdb, uint32_t destnode, pid_t pid)
|
||||
{
|
||||
int ret;
|
||||
TDB_DATA data;
|
||||
@ -739,7 +739,7 @@ int ctdb_process_exists(struct ctdb_context *ctdb, uint32_t destnode, pid_t pid)
|
||||
/*
|
||||
get remote status
|
||||
*/
|
||||
int ctdb_status(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_status *status)
|
||||
int ctdb_ctrl_status(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_status *status)
|
||||
{
|
||||
int ret;
|
||||
TDB_DATA data;
|
||||
@ -769,7 +769,7 @@ int ctdb_status(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_status
|
||||
/*
|
||||
get vnn map from a remote node
|
||||
*/
|
||||
int ctdb_getvnnmap(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_vnn_map *vnnmap)
|
||||
int ctdb_ctrl_getvnnmap(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_vnn_map *vnnmap)
|
||||
{
|
||||
int ret;
|
||||
TDB_DATA data, outdata;
|
||||
@ -798,10 +798,57 @@ int ctdb_getvnnmap(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_vnn
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
get the recovery mode of a remote node
|
||||
*/
|
||||
int ctdb_ctrl_getrecmode(struct ctdb_context *ctdb, uint32_t destnode, uint32_t *recmode)
|
||||
{
|
||||
int ret;
|
||||
TDB_DATA data, outdata;
|
||||
int32_t res;
|
||||
|
||||
ZERO_STRUCT(data);
|
||||
ret = ctdb_control(ctdb, destnode, 0,
|
||||
CTDB_CONTROL_GET_RECMODE, 0, data,
|
||||
ctdb, &outdata, &res);
|
||||
if (ret != 0 || res != 0) {
|
||||
DEBUG(0,(__location__ " ctdb_control for getrecmode failed\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
*recmode = ((uint32_t *)outdata.dptr)[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
set the recovery mode of a remote node
|
||||
*/
|
||||
int ctdb_ctrl_setrecmode(struct ctdb_context *ctdb, uint32_t destnode, uint32_t recmode)
|
||||
{
|
||||
int ret;
|
||||
TDB_DATA data, outdata;
|
||||
int32_t res;
|
||||
|
||||
ZERO_STRUCT(data);
|
||||
data.dsize = sizeof(uint32_t);
|
||||
data.dptr = (unsigned char *)&recmode;
|
||||
|
||||
ret = ctdb_control(ctdb, destnode, 0,
|
||||
CTDB_CONTROL_SET_RECMODE, 0, data,
|
||||
ctdb, &outdata, &res);
|
||||
if (ret != 0 || res != 0) {
|
||||
DEBUG(0,(__location__ " ctdb_control for getrecmode failed\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
get a list of databases off a remote node
|
||||
*/
|
||||
int ctdb_getdbmap(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_dbid_map *dbmap)
|
||||
int ctdb_ctrl_getdbmap(struct ctdb_context *ctdb, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_dbid_map *dbmap)
|
||||
{
|
||||
int ret;
|
||||
TDB_DATA data, outdata;
|
||||
@ -817,11 +864,7 @@ int ctdb_getdbmap(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_dbid
|
||||
}
|
||||
|
||||
dbmap->num = ((uint32_t *)outdata.dptr)[0];
|
||||
if (dbmap->dbids) {
|
||||
talloc_free(dbmap->dbids);
|
||||
dbmap->dbids=NULL;
|
||||
}
|
||||
dbmap->dbids=talloc_array(dbmap, uint32_t, dbmap->num);
|
||||
dbmap->dbids=talloc_array(mem_ctx, uint32_t, dbmap->num);
|
||||
if (!dbmap->dbids) {
|
||||
DEBUG(0,(__location__ " failed to talloc dbmap\n"));
|
||||
return -1;
|
||||
@ -837,7 +880,7 @@ int ctdb_getdbmap(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_dbid
|
||||
/*
|
||||
get a list of nodes (vnn and flags ) from a remote node
|
||||
*/
|
||||
int ctdb_getnodemap(struct ctdb_context *ctdb, uint32_t destnode,
|
||||
int ctdb_ctrl_getnodemap(struct ctdb_context *ctdb, uint32_t destnode,
|
||||
TALLOC_CTX *mem_ctx, struct ctdb_node_map *nodemap)
|
||||
{
|
||||
int ret;
|
||||
@ -869,13 +912,13 @@ int ctdb_getnodemap(struct ctdb_context *ctdb, uint32_t destnode,
|
||||
/*
|
||||
set vnn map on a node
|
||||
*/
|
||||
int ctdb_setvnnmap(struct ctdb_context *ctdb, uint32_t destnode, 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)
|
||||
{
|
||||
int ret;
|
||||
TDB_DATA *data, outdata;
|
||||
int32_t i, res;
|
||||
|
||||
data = talloc_zero(ctdb, TDB_DATA);
|
||||
data = talloc_zero(mem_ctx, TDB_DATA);
|
||||
data->dsize = (vnnmap->size+2)*sizeof(uint32_t);
|
||||
data->dptr = (unsigned char *)talloc_array(data, uint32_t, vnnmap->size+2);
|
||||
|
||||
@ -897,10 +940,161 @@ int ctdb_setvnnmap(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_vnn
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
get all keys and records for a specific database
|
||||
*/
|
||||
int ctdb_ctrl_pulldb(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid, uint32_t lmaster, TALLOC_CTX *mem_ctx, struct ctdb_key_list *keys)
|
||||
{
|
||||
int i, ret;
|
||||
TDB_DATA indata, outdata;
|
||||
int32_t res;
|
||||
unsigned char *ptr;
|
||||
|
||||
indata.dsize = 2*sizeof(uint32_t);
|
||||
indata.dptr = (unsigned char *)talloc_array(mem_ctx, uint32_t, 2);
|
||||
|
||||
((uint32_t *)(&indata.dptr[0]))[0] = dbid;
|
||||
((uint32_t *)(&indata.dptr[0]))[1] = lmaster;
|
||||
|
||||
ret = ctdb_control(ctdb, destnode, 0,
|
||||
CTDB_CONTROL_PULL_DB, 0, indata,
|
||||
mem_ctx, &outdata, &res);
|
||||
if (ret != 0 || res != 0) {
|
||||
DEBUG(0,(__location__ " ctdb_control for pulldb failed\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
keys->dbid = ((uint32_t *)(&outdata.dptr[0]))[0];
|
||||
keys->num = ((uint32_t *)(&outdata.dptr[0]))[1];
|
||||
keys->keys =talloc_array(mem_ctx, TDB_DATA, keys->num);
|
||||
keys->headers=talloc_array(mem_ctx, struct ctdb_ltdb_header, keys->num);
|
||||
keys->lmasters=talloc_array(mem_ctx, uint32_t, keys->num);
|
||||
keys->data=talloc_array(mem_ctx, TDB_DATA, keys->num);
|
||||
|
||||
/* loop over all key/data pairs */
|
||||
ptr=&outdata.dptr[8];
|
||||
for(i=0;i<keys->num;i++){
|
||||
uint32_t len;
|
||||
TDB_DATA *key, *data;
|
||||
|
||||
keys->lmasters[i]= *((uint32_t *)ptr);
|
||||
ptr+=4;
|
||||
|
||||
key=&keys->keys[i];
|
||||
key->dsize= *((uint32_t *)ptr);
|
||||
ptr+=4;
|
||||
key->dptr=talloc_size(mem_ctx, key->dsize);
|
||||
memcpy(key->dptr, ptr, key->dsize);
|
||||
len = (key->dsize+CTDB_DS_ALIGNMENT-1)& ~(CTDB_DS_ALIGNMENT-1);
|
||||
ptr+=len;
|
||||
|
||||
memcpy(&keys->headers[i], ptr, sizeof(struct ctdb_ltdb_header));
|
||||
len = (sizeof(struct ctdb_ltdb_header)+CTDB_DS_ALIGNMENT-1)& ~(CTDB_DS_ALIGNMENT-1);
|
||||
ptr+=len;
|
||||
|
||||
data=&keys->data[i];
|
||||
data->dsize= *((uint32_t *)ptr);
|
||||
ptr+=4;
|
||||
data->dptr=talloc_size(mem_ctx, data->dsize);
|
||||
memcpy(data->dptr, ptr, data->dsize);
|
||||
len = (data->dsize+CTDB_DS_ALIGNMENT-1)& ~(CTDB_DS_ALIGNMENT-1);
|
||||
ptr+=len;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
copy a tdb from one node to another node
|
||||
*/
|
||||
int ctdb_ctrl_copydb(struct ctdb_context *ctdb, uint32_t sourcenode, uint32_t destnode, uint32_t dbid, uint32_t lmaster, TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
int ret;
|
||||
TDB_DATA indata, outdata;
|
||||
int32_t res;
|
||||
|
||||
indata.dsize = 2*sizeof(uint32_t);
|
||||
indata.dptr = (unsigned char *)talloc_array(mem_ctx, uint32_t, 2);
|
||||
|
||||
((uint32_t *)(&indata.dptr[0]))[0] = dbid;
|
||||
((uint32_t *)(&indata.dptr[0]))[1] = lmaster;
|
||||
|
||||
ret = ctdb_control(ctdb, sourcenode, 0,
|
||||
CTDB_CONTROL_PULL_DB, 0, indata,
|
||||
mem_ctx, &outdata, &res);
|
||||
if (ret != 0 || res != 0) {
|
||||
DEBUG(0,(__location__ " ctdb_control for pulldb failed\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = ctdb_control(ctdb, destnode, 0,
|
||||
CTDB_CONTROL_PUSH_DB, 0, outdata,
|
||||
mem_ctx, NULL, &res);
|
||||
if (ret != 0 || res != 0) {
|
||||
DEBUG(0,(__location__ " ctdb_control for pushdb failed\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
change dmaster for all keys in the database to the new value
|
||||
*/
|
||||
int ctdb_ctrl_setdmaster(struct ctdb_context *ctdb, uint32_t destnode, TALLOC_CTX *mem_ctx, uint32_t dbid, uint32_t dmaster)
|
||||
{
|
||||
int ret;
|
||||
TDB_DATA indata, outdata;
|
||||
int32_t res;
|
||||
|
||||
indata.dsize = 2*sizeof(uint32_t);
|
||||
indata.dptr = (unsigned char *)talloc_array(mem_ctx, uint32_t, 2);
|
||||
|
||||
((uint32_t *)(&indata.dptr[0]))[0] = dbid;
|
||||
((uint32_t *)(&indata.dptr[0]))[1] = dmaster;
|
||||
|
||||
ret = ctdb_control(ctdb, destnode, 0,
|
||||
CTDB_CONTROL_SET_DMASTER, 0, indata,
|
||||
mem_ctx, &outdata, &res);
|
||||
if (ret != 0 || res != 0) {
|
||||
DEBUG(0,(__location__ " ctdb_control for setdmaster failed\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
delete all records from a tdb
|
||||
*/
|
||||
int ctdb_ctrl_cleardb(struct ctdb_context *ctdb, uint32_t destnode, TALLOC_CTX *mem_ctx, uint32_t dbid)
|
||||
{
|
||||
int ret;
|
||||
TDB_DATA indata, outdata;
|
||||
int32_t res;
|
||||
|
||||
indata.dsize = sizeof(uint32_t);
|
||||
indata.dptr = (unsigned char *)talloc_array(mem_ctx, uint32_t, 1);
|
||||
|
||||
((uint32_t *)(&indata.dptr[0]))[0] = dbid;
|
||||
|
||||
ret = ctdb_control(ctdb, destnode, 0,
|
||||
CTDB_CONTROL_CLEAR_DB, 0, indata,
|
||||
mem_ctx, &outdata, &res);
|
||||
if (ret != 0 || res != 0) {
|
||||
DEBUG(0,(__location__ " ctdb_control for cleardb failed\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
ping a node, return number of clients connected
|
||||
*/
|
||||
int ctdb_ping(struct ctdb_context *ctdb, uint32_t destnode)
|
||||
int ctdb_ctrl_ping(struct ctdb_context *ctdb, uint32_t destnode)
|
||||
{
|
||||
int ret;
|
||||
int32_t res;
|
||||
@ -918,7 +1112,7 @@ int ctdb_ping(struct ctdb_context *ctdb, uint32_t destnode)
|
||||
/*
|
||||
get ctdb config
|
||||
*/
|
||||
int ctdb_get_config(struct ctdb_context *ctdb)
|
||||
int ctdb_ctrl_get_config(struct ctdb_context *ctdb)
|
||||
{
|
||||
int ret;
|
||||
int32_t res;
|
||||
@ -950,7 +1144,7 @@ int ctdb_get_config(struct ctdb_context *ctdb)
|
||||
/*
|
||||
find the real path to a ltdb
|
||||
*/
|
||||
int ctdb_getdbpath(struct ctdb_context *ctdb, uint32_t dbid, TALLOC_CTX *mem_ctx,
|
||||
int ctdb_ctrl_getdbpath(struct ctdb_context *ctdb, uint32_t dbid, TALLOC_CTX *mem_ctx,
|
||||
const char **path)
|
||||
{
|
||||
int ret;
|
||||
@ -980,7 +1174,7 @@ int ctdb_getdbpath(struct ctdb_context *ctdb, uint32_t dbid, TALLOC_CTX *mem_ctx
|
||||
/*
|
||||
get debug level on a node
|
||||
*/
|
||||
int ctdb_get_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, uint32_t *level)
|
||||
int ctdb_ctrl_get_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, uint32_t *level)
|
||||
{
|
||||
int ret;
|
||||
int32_t res;
|
||||
@ -1005,7 +1199,7 @@ int ctdb_get_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, uint32_t *
|
||||
/*
|
||||
set debug level on a node
|
||||
*/
|
||||
int ctdb_set_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, uint32_t level)
|
||||
int ctdb_ctrl_set_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, uint32_t level)
|
||||
{
|
||||
int ret;
|
||||
int32_t res;
|
||||
@ -1038,7 +1232,7 @@ uint32_t *ctdb_get_connected_nodes(struct ctdb_context *ctdb, TALLOC_CTX *mem_ct
|
||||
map = talloc(mem_ctx, struct ctdb_node_map);
|
||||
CTDB_NO_MEMORY_VOID(ctdb, map);
|
||||
|
||||
ret = ctdb_getnodemap(ctdb, CTDB_CURRENT_NODE, map, map);
|
||||
ret = ctdb_ctrl_getnodemap(ctdb, CTDB_CURRENT_NODE, map, map);
|
||||
if (ret != 0) {
|
||||
talloc_free(map);
|
||||
return NULL;
|
||||
@ -1114,7 +1308,7 @@ struct ctdb_db_context *ctdb_attach(struct ctdb_context *ctdb, const char *name)
|
||||
|
||||
ctdb_db->db_id = *(uint32_t *)data.dptr;
|
||||
|
||||
ret = ctdb_getdbpath(ctdb, ctdb_db->db_id, ctdb_db, &ctdb_db->db_path);
|
||||
ret = ctdb_ctrl_getdbpath(ctdb, ctdb_db->db_id, ctdb_db, &ctdb_db->db_path);
|
||||
if (ret != 0) {
|
||||
DEBUG(0,("Failed to get dbpath for database '%s'\n", name));
|
||||
talloc_free(ctdb_db);
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "system/wait.h"
|
||||
#include "../include/ctdb_private.h"
|
||||
#include "lib/util/dlinklist.h"
|
||||
#include "db_wrap.h"
|
||||
|
||||
struct ctdb_control_state {
|
||||
struct ctdb_context *ctdb;
|
||||
@ -41,8 +42,96 @@ struct ctdb_control_state {
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static int traverse_cleardb(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *p)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
||||
ret = tdb_delete(tdb, key);
|
||||
if (ret) {
|
||||
DEBUG(0,(__location__ "failed to delete tdb record\n"));
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int traverse_setdmaster(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *p)
|
||||
{
|
||||
uint32_t *dmaster = (uint32_t *)p;
|
||||
struct ctdb_ltdb_header *header = (struct ctdb_ltdb_header *)data.dptr;
|
||||
int ret;
|
||||
|
||||
header->dmaster = *dmaster;
|
||||
|
||||
ret = tdb_store(tdb, key, data, TDB_REPLACE);
|
||||
if (ret) {
|
||||
DEBUG(0,(__location__ "failed to write tdb data back ret:%d\n",ret));
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct getkeys_params {
|
||||
struct ctdb_db_context *ctdb_db;
|
||||
TDB_DATA *outdata;
|
||||
uint32_t lmaster;
|
||||
};
|
||||
|
||||
static int traverse_getkeys(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *p)
|
||||
{
|
||||
struct getkeys_params *params = (struct getkeys_params *)p;
|
||||
TDB_DATA *outdata = talloc_get_type(params->outdata, TDB_DATA);
|
||||
struct ctdb_db_context *ctdb_db = talloc_get_type(params->ctdb_db, struct ctdb_db_context);
|
||||
unsigned char *ptr;
|
||||
int len;
|
||||
uint32_t lmaster;
|
||||
|
||||
lmaster = ctdb_lmaster(ctdb_db->ctdb, &key);
|
||||
|
||||
/* only include this record if the lmaster matches or if
|
||||
the wildcard lmaster (-1) was specified.
|
||||
*/
|
||||
if((lmaster!=CTDB_LMASTER_ANY)
|
||||
&& (lmaster!=params->lmaster) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
len=outdata->dsize;
|
||||
len+=4; /*lmaster*/
|
||||
len+=4; /*key len*/
|
||||
len+=key.dsize;
|
||||
len=(len+CTDB_DS_ALIGNMENT-1)& ~(CTDB_DS_ALIGNMENT-1);
|
||||
len+=sizeof(struct ctdb_ltdb_header);
|
||||
len=(len+CTDB_DS_ALIGNMENT-1)& ~(CTDB_DS_ALIGNMENT-1);
|
||||
len+=4; /*data len */
|
||||
len+=data.dsize;
|
||||
len=(len+CTDB_DS_ALIGNMENT-1)& ~(CTDB_DS_ALIGNMENT-1);
|
||||
|
||||
ptr=outdata->dptr=talloc_realloc_size(outdata, outdata->dptr, len);
|
||||
ptr+=outdata->dsize;
|
||||
outdata->dsize=len;
|
||||
/* number of records is stored as the second 4 bytes */
|
||||
((uint32_t *)(&outdata->dptr[0]))[1]++;
|
||||
|
||||
*((uint32_t *)ptr)=lmaster;
|
||||
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);
|
||||
|
||||
memcpy(ptr, data.dptr, sizeof(struct ctdb_ltdb_header));
|
||||
ptr+=(sizeof(struct ctdb_ltdb_header)+CTDB_DS_ALIGNMENT-1)& ~(CTDB_DS_ALIGNMENT-1);
|
||||
|
||||
*((uint32_t *)ptr)=data.dsize-sizeof(struct ctdb_ltdb_header);
|
||||
ptr+=4;
|
||||
memcpy(ptr, data.dptr+sizeof(struct ctdb_ltdb_header), data.dsize-sizeof(struct ctdb_ltdb_header));
|
||||
ptr+= (data.dsize-sizeof(struct ctdb_ltdb_header)+CTDB_DS_ALIGNMENT-1)& ~(CTDB_DS_ALIGNMENT-1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
process a control request
|
||||
*/
|
||||
@ -175,6 +264,154 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
|
||||
return 0;
|
||||
}
|
||||
|
||||
case CTDB_CONTROL_PULL_DB: {
|
||||
uint32_t dbid, lmaster;
|
||||
struct ctdb_db_context *ctdb_db;
|
||||
struct getkeys_params params;
|
||||
|
||||
dbid = ((uint32_t *)(&indata.dptr[0]))[0];
|
||||
ctdb_db = find_ctdb_db(ctdb, dbid);
|
||||
if (!ctdb_db) {
|
||||
DEBUG(0,(__location__ " Unknown db\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
lmaster = ((uint32_t *)(&indata.dptr[0]))[1];
|
||||
|
||||
outdata->dsize = 2* sizeof(uint32_t);
|
||||
outdata->dptr = (unsigned char *)talloc_array(outdata, uint32_t, 2);
|
||||
((uint32_t *)(&outdata->dptr[0]))[0]=dbid;
|
||||
((uint32_t *)(&outdata->dptr[0]))[1]=0;
|
||||
|
||||
params.ctdb_db = ctdb_db;
|
||||
params.outdata = outdata;
|
||||
params.lmaster = lmaster;
|
||||
tdb_traverse_read(ctdb_db->ltdb->tdb, traverse_getkeys, ¶ms);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
case CTDB_CONTROL_SET_DMASTER: {
|
||||
uint32_t dbid, dmaster;
|
||||
struct ctdb_db_context *ctdb_db;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
dmaster = ((uint32_t *)(&indata.dptr[0]))[1];
|
||||
|
||||
outdata->dsize = 0;
|
||||
outdata->dptr = NULL;
|
||||
|
||||
tdb_traverse(ctdb_db->ltdb->tdb, traverse_setdmaster, &dmaster);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
case CTDB_CONTROL_CLEAR_DB: {
|
||||
uint32_t dbid;
|
||||
struct ctdb_db_context *ctdb_db;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
outdata->dsize = 0;
|
||||
outdata->dptr = NULL;
|
||||
|
||||
tdb_traverse(ctdb_db->ltdb->tdb, traverse_cleardb, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
case CTDB_CONTROL_PUSH_DB: {
|
||||
uint32_t dbid, num;
|
||||
struct ctdb_db_context *ctdb_db;
|
||||
unsigned char *ptr;
|
||||
int i, ret;
|
||||
TDB_DATA key, data;
|
||||
struct ctdb_ltdb_header *hdr, header;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
num = ((uint32_t *)(&indata.dptr[0]))[1];
|
||||
|
||||
ptr=&indata.dptr[8];
|
||||
for(i=0;i<num;i++){
|
||||
/* skip the lmaster*/
|
||||
ptr+=4;
|
||||
|
||||
/* key */
|
||||
key.dsize=*((uint32_t *)ptr);
|
||||
ptr+=4;
|
||||
key.dptr=ptr;
|
||||
ptr+=(key.dsize+CTDB_DS_ALIGNMENT-1)& ~(CTDB_DS_ALIGNMENT-1);
|
||||
|
||||
/* header */
|
||||
hdr = (struct ctdb_ltdb_header *)ptr;
|
||||
ptr+=(sizeof(struct ctdb_ltdb_header)+CTDB_DS_ALIGNMENT-1)& ~(CTDB_DS_ALIGNMENT-1);
|
||||
|
||||
/* data */
|
||||
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;
|
||||
}
|
||||
if (header.rsn < hdr->rsn) {
|
||||
ret = ctdb_ltdb_store(ctdb_db, key, hdr, 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_SET_RECMODE: {
|
||||
ctdb->recovery_mode = ((uint32_t *)(&indata.dptr[0]))[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
case CTDB_CONTROL_GET_RECMODE: {
|
||||
outdata->dsize = sizeof(uint32_t);
|
||||
outdata->dptr = (unsigned char *)talloc_array(outdata, uint32_t, 1);
|
||||
*((uint32_t *)(&outdata->dptr[0])) = ctdb->recovery_mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
case CTDB_CONTROL_CONFIG: {
|
||||
CHECK_CONTROL_DATA_SIZE(0);
|
||||
outdata->dptr = (uint8_t *)ctdb;
|
||||
|
@ -653,7 +653,7 @@ int ctdb_start(struct ctdb_context *ctdb)
|
||||
close(fd[0]);
|
||||
close(ctdb->daemon.sd);
|
||||
ctdb->daemon.sd = -1;
|
||||
ctdb_get_config(ctdb);
|
||||
ctdb_ctrl_get_config(ctdb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -213,11 +213,11 @@ struct ctdb_db_context *find_ctdb_db(struct ctdb_context *ctdb, uint32_t id);
|
||||
struct ctdb_context *ctdb_cmdline_client(struct event_context *ev);
|
||||
|
||||
struct ctdb_status;
|
||||
int ctdb_status(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_status *status);
|
||||
int ctdb_ctrl_status(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_status *status);
|
||||
|
||||
struct ctdb_vnn_map;
|
||||
int ctdb_getvnnmap(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_vnn_map *vnnmap);
|
||||
int ctdb_setvnnmap(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_vnn_map *vnnmap);
|
||||
int ctdb_ctrl_getvnnmap(struct ctdb_context *ctdb, uint32_t destnode, 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
|
||||
*/
|
||||
@ -225,7 +225,7 @@ struct ctdb_dbid_map {
|
||||
uint32_t num;
|
||||
uint32_t *dbids;
|
||||
};
|
||||
int ctdb_getdbmap(struct ctdb_context *ctdb, uint32_t destnode, struct ctdb_dbid_map *dbmap);
|
||||
int ctdb_ctrl_getdbmap(struct ctdb_context *ctdb, uint32_t destnode, TALLOC_CTX *mem_ctx, struct ctdb_dbid_map *dbmap);
|
||||
|
||||
|
||||
/* table that contains a list of all nodes a ctdb knows about and their
|
||||
@ -239,19 +239,52 @@ struct ctdb_node_map {
|
||||
uint32_t num;
|
||||
struct ctdb_node_and_flags *nodes;
|
||||
};
|
||||
int ctdb_getnodemap(struct ctdb_context *ctdb, uint32_t destnode,
|
||||
int ctdb_ctrl_getnodemap(struct ctdb_context *ctdb, uint32_t destnode,
|
||||
TALLOC_CTX *mem_ctx, struct ctdb_node_map *nodemap);
|
||||
|
||||
int ctdb_getdbpath(struct ctdb_context *ctdb, uint32_t dbid, TALLOC_CTX *mem_ctx, const char **path);
|
||||
struct ctdb_key_list {
|
||||
uint32_t dbid;
|
||||
uint32_t num;
|
||||
TDB_DATA *keys;
|
||||
struct ctdb_ltdb_header *headers;
|
||||
uint32_t *lmasters;
|
||||
TDB_DATA *data;
|
||||
};
|
||||
int ctdb_ctrl_pulldb(struct ctdb_context *ctdb, uint32_t destnode, uint32_t dbid, uint32_t lmaster, TALLOC_CTX *mem_ctx, struct ctdb_key_list *keys);
|
||||
int ctdb_ctrl_copydb(struct ctdb_context *ctdb, uint32_t sourcenode, uint32_t destnode, uint32_t dbid, uint32_t lmaster, TALLOC_CTX *mem_ctx);
|
||||
|
||||
int ctdb_process_exists(struct ctdb_context *ctdb, uint32_t destnode, pid_t pid);
|
||||
int ctdb_ctrl_getdbpath(struct ctdb_context *ctdb, uint32_t dbid, TALLOC_CTX *mem_ctx, const char **path);
|
||||
|
||||
int ctdb_ping(struct ctdb_context *ctdb, uint32_t destnode);
|
||||
int ctdb_ctrl_process_exists(struct ctdb_context *ctdb, uint32_t destnode, pid_t pid);
|
||||
|
||||
int ctdb_get_config(struct ctdb_context *ctdb);
|
||||
int ctdb_ctrl_ping(struct ctdb_context *ctdb, uint32_t destnode);
|
||||
|
||||
int ctdb_get_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, uint32_t *level);
|
||||
int ctdb_set_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, uint32_t level);
|
||||
int ctdb_ctrl_get_config(struct ctdb_context *ctdb);
|
||||
|
||||
int ctdb_ctrl_get_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, uint32_t *level);
|
||||
int ctdb_ctrl_set_debuglevel(struct ctdb_context *ctdb, uint32_t destnode, uint32_t level);
|
||||
|
||||
/*
|
||||
change dmaster for all keys in the database to the new value
|
||||
*/
|
||||
int ctdb_ctrl_setdmaster(struct ctdb_context *ctdb, uint32_t destnode, TALLOC_CTX *mem_ctx, uint32_t dbid, uint32_t dmaster);
|
||||
|
||||
/*
|
||||
delete all records from a tdb
|
||||
*/
|
||||
int ctdb_ctrl_cleardb(struct ctdb_context *ctdb, uint32_t destnode, TALLOC_CTX *mem_ctx, uint32_t dbid);
|
||||
|
||||
|
||||
#define CTDB_RECOVERY_NORMAL 0
|
||||
#define CTDB_RECOVERY_ACTIVE 1
|
||||
/*
|
||||
get the recovery mode of a remote node
|
||||
*/
|
||||
int ctdb_ctrl_getrecmode(struct ctdb_context *ctdb, uint32_t destnode, uint32_t *recmode);
|
||||
/*
|
||||
set the recovery mode of a remote node
|
||||
*/
|
||||
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 *num_nodes);
|
||||
|
@ -174,6 +174,7 @@ struct ctdb_vnn_map {
|
||||
/* main state of the ctdb daemon */
|
||||
struct ctdb_context {
|
||||
struct event_context *ev;
|
||||
uint32_t recovery_mode;
|
||||
struct ctdb_address address;
|
||||
const char *name;
|
||||
const char *db_directory;
|
||||
@ -256,6 +257,12 @@ enum ctdb_controls {CTDB_CONTROL_PROCESS_EXISTS,
|
||||
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_STATUS_RESET,
|
||||
CTDB_CONTROL_DB_ATTACH,
|
||||
CTDB_CONTROL_SET_CALL};
|
||||
@ -269,9 +276,10 @@ struct ctdb_control_set_call {
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
|
||||
enum call_state {CTDB_CALL_WAIT, CTDB_CALL_DONE, CTDB_CALL_ERROR};
|
||||
|
||||
#define CTDB_LMASTER_ANY 0xffffffff
|
||||
|
||||
/*
|
||||
state of a in-progress ctdb call
|
||||
*/
|
||||
|
@ -23,7 +23,7 @@
|
||||
#ifndef __EVENTS_H__
|
||||
#define __EVENTS_H__
|
||||
|
||||
#include "talloc/talloc.h"
|
||||
#include "lib/talloc/talloc.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
struct event_context;
|
||||
|
@ -243,6 +243,10 @@ int main(int argc, const char *argv[])
|
||||
|
||||
printf("DATA:\n%s\n", (char *)call.reply_data.dptr);
|
||||
|
||||
#if 1
|
||||
/* to keep the cluster up so one can play with it using the controls */
|
||||
sleep(9999999);
|
||||
#endif
|
||||
/* go into a wait loop to allow other nodes to complete */
|
||||
ctdb_shutdown(ctdb);
|
||||
|
||||
|
@ -138,7 +138,7 @@ int main(int argc, const char *argv[])
|
||||
ctdb_connect_wait(ctdb);
|
||||
|
||||
/* find the full path to the database file */
|
||||
ctdb_getdbpath(ctdb, ctdb_db->db_id, ctdb_db, &path);
|
||||
ctdb_ctrl_getdbpath(ctdb, ctdb_db->db_id, ctdb_db, &path);
|
||||
printf("path to database:[%s]\n",path);
|
||||
|
||||
ZERO_STRUCT(call);
|
||||
|
@ -43,6 +43,13 @@ static void usage(void)
|
||||
printf(" setvnnmap <vnn> <generation> <numslots> <lmaster>*\n");
|
||||
printf(" getdbmap <vnn> lists databases on a node\n");
|
||||
printf(" getnodemap <vnn> lists nodes known to a ctdb daemon\n");
|
||||
printf(" catdb <vnn> <dbid> lists all keys in a remote tdb\n");
|
||||
printf(" cpdb <fromvnn> <tovnn> <dbid> lists all keys in a remote tdb\n");
|
||||
printf(" setdmaster <vnn> <dbid> <dmaster> sets new dmaster for all records in the database\n");
|
||||
printf(" cleardb <vnn> <dbid> deletes all records in a db\n");
|
||||
printf(" getrecmode <vnn> get recovery mode\n");
|
||||
printf(" setrecmode <vnn> <mode> set recovery mode\n");
|
||||
printf(" recover <vnn> recover the cluster\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -62,7 +69,7 @@ static int control_process_exists(struct ctdb_context *ctdb, int argc, const cha
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = ctdb_process_exists(ctdb, vnn, pid);
|
||||
ret = ctdb_ctrl_process_exists(ctdb, vnn, pid);
|
||||
if (ret == 0) {
|
||||
printf("%u:%u exists\n", vnn, pid);
|
||||
} else {
|
||||
@ -126,7 +133,7 @@ static int control_status_all(struct ctdb_context *ctdb)
|
||||
uint32_t *v2 = (uint32_t *)&status;
|
||||
uint32_t num_ints =
|
||||
offsetof(struct ctdb_status, __last_counter) / sizeof(uint32_t);
|
||||
ret = ctdb_status(ctdb, nodes[i], &s1);
|
||||
ret = ctdb_ctrl_status(ctdb, nodes[i], &s1);
|
||||
if (ret != 0) {
|
||||
printf("Unable to get status from node %u\n", nodes[i]);
|
||||
return ret;
|
||||
@ -165,7 +172,7 @@ static int control_status(struct ctdb_context *ctdb, int argc, const char **argv
|
||||
|
||||
vnn = strtoul(argv[0], NULL, 0);
|
||||
|
||||
ret = ctdb_status(ctdb, vnn, &status);
|
||||
ret = ctdb_ctrl_status(ctdb, vnn, &status);
|
||||
if (ret != 0) {
|
||||
printf("Unable to get status from node %u\n", vnn);
|
||||
return ret;
|
||||
@ -224,6 +231,195 @@ static int control_status_reset(struct ctdb_context *ctdb, int argc, const char
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
perform a samba3 style recovery
|
||||
*/
|
||||
static int control_recover(struct ctdb_context *ctdb, int argc, const char **argv)
|
||||
{
|
||||
uint32_t vnn, num_nodes, generation, dmaster;
|
||||
struct ctdb_vnn_map vnnmap;
|
||||
struct ctdb_node_map nodemap;
|
||||
int i, j, ret;
|
||||
struct ctdb_dbid_map dbmap;
|
||||
|
||||
if (argc < 1) {
|
||||
usage();
|
||||
}
|
||||
|
||||
|
||||
vnn = strtoul(argv[0], NULL, 0);
|
||||
|
||||
printf("recover ctdb from node %d\n", vnn);
|
||||
|
||||
/* 1: find a list of all nodes */
|
||||
printf("\n1: fetching list of nodes\n");
|
||||
ret = ctdb_ctrl_getnodemap(ctdb, vnn, ctdb, &nodemap);
|
||||
if (ret != 0) {
|
||||
printf("Unable to get nodemap from node %u\n", vnn);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* 2: count the active nodes */
|
||||
printf("\n2: count number of active nodes\n");
|
||||
num_nodes = 0;
|
||||
for (i=0; i<nodemap.num; i++) {
|
||||
if (nodemap.nodes[i].flags&NODE_FLAGS_CONNECTED) {
|
||||
num_nodes++;
|
||||
}
|
||||
}
|
||||
printf("number of active nodes:%d\n",num_nodes);
|
||||
|
||||
/* 3: go to all active nodes and activate recovery mode */
|
||||
printf("\n3: set recovery mode for all active nodes\n");
|
||||
for (j=0; j<nodemap.num; j++) {
|
||||
/* dont change it for nodes that are unavailable */
|
||||
if (!(nodemap.nodes[j].flags&NODE_FLAGS_CONNECTED)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("setting node %d to recovery mode\n",nodemap.nodes[j].vnn);
|
||||
ret = ctdb_ctrl_setrecmode(ctdb, nodemap.nodes[j].vnn, CTDB_RECOVERY_ACTIVE);
|
||||
if (ret != 0) {
|
||||
printf("Unable to set recmode on node %u\n", nodemap.nodes[j].vnn);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* 4: get a list of all databases */
|
||||
printf("\n4: getting list of databases to recover\n");
|
||||
ret = ctdb_ctrl_getdbmap(ctdb, vnn, ctdb, &dbmap);
|
||||
if (ret != 0) {
|
||||
printf("Unable to get dbids from node %u\n", vnn);
|
||||
return ret;
|
||||
}
|
||||
for (i=0;i<dbmap.num;i++) {
|
||||
const char *path;
|
||||
|
||||
ctdb_ctrl_getdbpath(ctdb, dbmap.dbids[i], ctdb, &path);
|
||||
printf("dbid:0x%08x path:%s\n", dbmap.dbids[i], path);
|
||||
}
|
||||
|
||||
/* 5: pull all records from all other nodes across to this node
|
||||
(this merges based on rsn internally)
|
||||
*/
|
||||
printf("\n5: merge all records from remote nodes\n");
|
||||
for (i=0;i<dbmap.num;i++) {
|
||||
printf("recovering database 0x%08x\n",dbmap.dbids[i]);
|
||||
for (j=0; j<nodemap.num; j++) {
|
||||
/* we dont need to merge with ourselves */
|
||||
if (nodemap.nodes[j].vnn == vnn) {
|
||||
continue;
|
||||
}
|
||||
/* dont merge from nodes that are unavailable */
|
||||
if (!(nodemap.nodes[j].flags&NODE_FLAGS_CONNECTED)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("merging all records from node %d for database 0x%08x\n", nodemap.nodes[j].vnn, dbmap.dbids[i]);
|
||||
ret = ctdb_ctrl_copydb(ctdb, nodemap.nodes[j].vnn, vnn, dbmap.dbids[i], CTDB_LMASTER_ANY, ctdb);
|
||||
if (ret != 0) {
|
||||
printf("Unable to copy db from node %u to node %u\n", nodemap.nodes[j].vnn, vnn);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 6: update dmaster to point to this node for all databases/nodes */
|
||||
printf("\n6: repoint dmaster to the recovery node\n");
|
||||
dmaster = vnn;
|
||||
printf("new dmaster is %d\n", dmaster);
|
||||
for (i=0;i<dbmap.num;i++) {
|
||||
for (j=0; j<nodemap.num; j++) {
|
||||
/* dont repoint nodes that are unavailable */
|
||||
if (!(nodemap.nodes[j].flags&NODE_FLAGS_CONNECTED)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("setting dmaster to %d for node %d db 0x%08x\n",dmaster,nodemap.nodes[j].vnn,dbmap.dbids[i]);
|
||||
ret = ctdb_ctrl_setdmaster(ctdb, nodemap.nodes[j].vnn, ctdb, dbmap.dbids[i], dmaster);
|
||||
if (ret != 0) {
|
||||
printf("Unable to set dmaster for node %u db:0x%08x\n", nodemap.nodes[j].vnn, dbmap.dbids[i]);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 7: push all records out to the nodes again */
|
||||
printf("\n7: push all records to remote nodes\n");
|
||||
for (i=0;i<dbmap.num;i++) {
|
||||
printf("distributing new database 0x%08x\n",dbmap.dbids[i]);
|
||||
for (j=0; j<nodemap.num; j++) {
|
||||
/* we dont need to push to ourselves */
|
||||
if (nodemap.nodes[j].vnn == vnn) {
|
||||
continue;
|
||||
}
|
||||
/* dont push to nodes that are unavailable */
|
||||
if (!(nodemap.nodes[j].flags&NODE_FLAGS_CONNECTED)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("pushing all records to node %d for database 0x%08x\n", nodemap.nodes[j].vnn, dbmap.dbids[i]);
|
||||
ret = ctdb_ctrl_copydb(ctdb, vnn, nodemap.nodes[j].vnn, dbmap.dbids[i], CTDB_LMASTER_ANY, ctdb);
|
||||
if (ret != 0) {
|
||||
printf("Unable to copy db from node %u to node %u\n", vnn, nodemap.nodes[j].vnn);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 8: build a new vnn map */
|
||||
printf("\n8: build a new vnn map with a new generation id\n");
|
||||
generation = random();
|
||||
vnnmap.generation = generation;
|
||||
vnnmap.size = num_nodes;
|
||||
vnnmap.map = talloc_array(ctdb, uint32_t, num_nodes);
|
||||
for (i=j=0;i<nodemap.num;i++) {
|
||||
if (nodemap.nodes[i].flags&NODE_FLAGS_CONNECTED) {
|
||||
vnnmap.map[j++]=nodemap.nodes[i].vnn;
|
||||
}
|
||||
}
|
||||
printf("Generation:%d\n",vnnmap.generation);
|
||||
printf("Size:%d\n",vnnmap.size);
|
||||
for(i=0;i<vnnmap.size;i++){
|
||||
printf("hash:%d lmaster:%d\n",i,vnnmap.map[i]);
|
||||
}
|
||||
|
||||
/* 9: push the new vnn map out to all the nodes */
|
||||
printf("\n9: distribute the new vnn map\n");
|
||||
for (j=0; j<nodemap.num; j++) {
|
||||
/* dont push to nodes that are unavailable */
|
||||
if (!(nodemap.nodes[j].flags&NODE_FLAGS_CONNECTED)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("setting new vnn map on node %d\n",nodemap.nodes[j].vnn);
|
||||
ret = ctdb_ctrl_setvnnmap(ctdb, nodemap.nodes[j].vnn, ctdb, &vnnmap);
|
||||
if (ret != 0) {
|
||||
printf("Unable to set vnnmap for node %u\n", vnn);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* 10: disable recovery mode */
|
||||
printf("\n10: restore recovery mode back to normal\n");
|
||||
for (j=0; j<nodemap.num; j++) {
|
||||
/* dont push to nodes that are unavailable */
|
||||
if (!(nodemap.nodes[j].flags&NODE_FLAGS_CONNECTED)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("changing recovery mode back to normal for node %d\n",nodemap.nodes[j].vnn);
|
||||
ret = ctdb_ctrl_setrecmode(ctdb, nodemap.nodes[j].vnn, CTDB_RECOVERY_NORMAL);
|
||||
if (ret != 0) {
|
||||
printf("Unable to set recmode on node %u\n", nodemap.nodes[j].vnn);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
display remote ctdb vnn map
|
||||
*/
|
||||
@ -239,7 +435,7 @@ static int control_getvnnmap(struct ctdb_context *ctdb, int argc, const char **a
|
||||
vnn = strtoul(argv[0], NULL, 0);
|
||||
|
||||
vnnmap = talloc_zero(ctdb, struct ctdb_vnn_map);
|
||||
ret = ctdb_getvnnmap(ctdb, vnn, vnnmap);
|
||||
ret = ctdb_ctrl_getvnnmap(ctdb, vnn, vnnmap);
|
||||
if (ret != 0) {
|
||||
printf("Unable to get vnnmap from node %u\n", vnn);
|
||||
return ret;
|
||||
@ -252,6 +448,125 @@ static int control_getvnnmap(struct ctdb_context *ctdb, int argc, const char **a
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
display recovery mode of a remote node
|
||||
*/
|
||||
static int control_getrecmode(struct ctdb_context *ctdb, int argc, const char **argv)
|
||||
{
|
||||
uint32_t vnn, recmode;
|
||||
int ret;
|
||||
|
||||
|
||||
if (argc < 1) {
|
||||
usage();
|
||||
}
|
||||
|
||||
vnn = strtoul(argv[0], NULL, 0);
|
||||
|
||||
ret = ctdb_ctrl_getrecmode(ctdb, vnn, &recmode);
|
||||
if (ret != 0) {
|
||||
printf("Unable to get recmode from node %u\n", vnn);
|
||||
return ret;
|
||||
}
|
||||
printf("Recovery mode:%s (%d)\n",recmode==CTDB_RECOVERY_NORMAL?"NORMAL":"RECOVERY",recmode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
set recovery mode of a remote node
|
||||
*/
|
||||
static int control_setrecmode(struct ctdb_context *ctdb, int argc, const char **argv)
|
||||
{
|
||||
uint32_t vnn, recmode;
|
||||
int ret;
|
||||
|
||||
|
||||
if (argc < 2) {
|
||||
usage();
|
||||
}
|
||||
|
||||
vnn = strtoul(argv[0], NULL, 0);
|
||||
recmode = strtoul(argv[0], NULL, 0);
|
||||
|
||||
ret = ctdb_ctrl_setrecmode(ctdb, vnn, recmode);
|
||||
if (ret != 0) {
|
||||
printf("Unable to set recmode on node %u\n", vnn);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
display remote list of keys for a tdb
|
||||
*/
|
||||
static int control_catdb(struct ctdb_context *ctdb, int argc, const char **argv)
|
||||
{
|
||||
uint32_t vnn, dbid;
|
||||
int i, j, ret;
|
||||
struct ctdb_key_list keys;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
|
||||
if (argc < 2) {
|
||||
usage();
|
||||
}
|
||||
|
||||
vnn = strtoul(argv[0], NULL, 0);
|
||||
dbid = strtoul(argv[1], NULL, 0);
|
||||
|
||||
mem_ctx = talloc_new(ctdb);
|
||||
ret = ctdb_ctrl_pulldb(ctdb, vnn, dbid, CTDB_LMASTER_ANY, mem_ctx, &keys);
|
||||
if (ret != 0) {
|
||||
printf("Unable to get keys from node %u\n", vnn);
|
||||
return ret;
|
||||
}
|
||||
printf("Number of keys:%d in dbid:0x%08x\n",keys.num,keys.dbid);
|
||||
for(i=0;i<keys.num;i++){
|
||||
printf("key:");
|
||||
for(j=0;j<keys.keys[i].dsize;j++){
|
||||
printf("%02x",keys.keys[i].dptr[j]);
|
||||
}
|
||||
printf(" lmaster:%d rsn:%llu dmaster:%d laccessor:%d lacount:%d",keys.lmasters[i],keys.headers[i].rsn,keys.headers[i].dmaster,keys.headers[i].laccessor,keys.headers[i].lacount);
|
||||
printf(" data:");
|
||||
for(j=0;j<keys.data[i].dsize;j++){
|
||||
printf("%02x",keys.data[i].dptr[j]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
copy a db from one node to another
|
||||
*/
|
||||
static int control_cpdb(struct ctdb_context *ctdb, int argc, const char **argv)
|
||||
{
|
||||
uint32_t fromvnn, tovnn, dbid;
|
||||
int ret;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
|
||||
if (argc < 3) {
|
||||
usage();
|
||||
}
|
||||
|
||||
fromvnn = strtoul(argv[0], NULL, 0);
|
||||
tovnn = strtoul(argv[1], NULL, 0);
|
||||
dbid = strtoul(argv[2], NULL, 0);
|
||||
|
||||
mem_ctx = talloc_new(ctdb);
|
||||
ret = ctdb_ctrl_copydb(ctdb, fromvnn, tovnn, dbid, CTDB_LMASTER_ANY, mem_ctx);
|
||||
if (ret != 0) {
|
||||
printf("Unable to copy db from node %u to node %u\n", fromvnn, tovnn);
|
||||
return ret;
|
||||
}
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
display a list of the databases on a remote ctdb
|
||||
*/
|
||||
@ -259,7 +574,7 @@ static int control_getdbmap(struct ctdb_context *ctdb, int argc, const char **ar
|
||||
{
|
||||
uint32_t vnn;
|
||||
int i, ret;
|
||||
struct ctdb_dbid_map *dbmap;
|
||||
struct ctdb_dbid_map dbmap;
|
||||
|
||||
if (argc < 1) {
|
||||
usage();
|
||||
@ -267,22 +582,20 @@ static int control_getdbmap(struct ctdb_context *ctdb, int argc, const char **ar
|
||||
|
||||
vnn = strtoul(argv[0], NULL, 0);
|
||||
|
||||
dbmap = talloc_zero(ctdb, struct ctdb_dbid_map);
|
||||
ret = ctdb_getdbmap(ctdb, vnn, dbmap);
|
||||
ret = ctdb_ctrl_getdbmap(ctdb, vnn, ctdb, &dbmap);
|
||||
if (ret != 0) {
|
||||
printf("Unable to get dbids from node %u\n", vnn);
|
||||
talloc_free(dbmap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
printf("Number of databases:%d\n", dbmap->num);
|
||||
for(i=0;i<dbmap->num;i++){
|
||||
printf("Number of databases:%d\n", dbmap.num);
|
||||
for(i=0;i<dbmap.num;i++){
|
||||
const char *path;
|
||||
|
||||
ctdb_getdbpath(ctdb, dbmap->dbids[i], dbmap, &path);
|
||||
printf("dbid:0x%08x path:%s\n", dbmap->dbids[i], path);
|
||||
ctdb_ctrl_getdbpath(ctdb, dbmap.dbids[i], ctdb, &path);
|
||||
printf("dbid:0x%08x path:%s\n", dbmap.dbids[i], path);
|
||||
}
|
||||
talloc_free(dbmap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -302,7 +615,7 @@ static int control_getnodemap(struct ctdb_context *ctdb, int argc, const char **
|
||||
vnn = strtoul(argv[0], NULL, 0);
|
||||
|
||||
nodemap = talloc_zero(ctdb, struct ctdb_node_map);
|
||||
ret = ctdb_getnodemap(ctdb, vnn, nodemap, nodemap);
|
||||
ret = ctdb_ctrl_getnodemap(ctdb, vnn, nodemap, nodemap);
|
||||
if (ret != 0) {
|
||||
printf("Unable to get nodemap from node %u\n", vnn);
|
||||
talloc_free(nodemap);
|
||||
@ -311,7 +624,10 @@ static int control_getnodemap(struct ctdb_context *ctdb, int argc, const char **
|
||||
|
||||
printf("Number of nodes:%d\n", nodemap->num);
|
||||
for(i=0;i<nodemap->num;i++){
|
||||
printf("vnn:%d %s\n", nodemap->nodes[i].vnn, nodemap->nodes[i].flags&NODE_FLAGS_CONNECTED?"UNAVAILABLE":"CONNECTED");
|
||||
printf("vnn:%d %s%s\n", nodemap->nodes[i].vnn,
|
||||
nodemap->nodes[i].flags&NODE_FLAGS_CONNECTED?
|
||||
"CONNECTED":"UNAVAILABLE",
|
||||
nodemap->nodes[i].vnn==vnn?" (THIS NODE)":"");
|
||||
}
|
||||
talloc_free(nodemap);
|
||||
return 0;
|
||||
@ -339,7 +655,7 @@ static int control_setvnnmap(struct ctdb_context *ctdb, int argc, const char **a
|
||||
vnnmap->map[i] = strtoul(argv[3+i], NULL, 0);
|
||||
}
|
||||
|
||||
ret = ctdb_setvnnmap(ctdb, vnn, vnnmap);
|
||||
ret = ctdb_ctrl_setvnnmap(ctdb, vnn, ctdb, vnnmap);
|
||||
if (ret != 0) {
|
||||
printf("Unable to set vnnmap for node %u\n", vnn);
|
||||
return ret;
|
||||
@ -347,6 +663,53 @@ static int control_setvnnmap(struct ctdb_context *ctdb, int argc, const char **a
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
set the dmaster for all records in a database
|
||||
*/
|
||||
static int control_setdmaster(struct ctdb_context *ctdb, int argc, const char **argv)
|
||||
{
|
||||
uint32_t vnn, dbid, dmaster;
|
||||
int ret;
|
||||
|
||||
if (argc < 3) {
|
||||
usage();
|
||||
}
|
||||
|
||||
vnn = strtoul(argv[0], NULL, 0);
|
||||
dbid = strtoul(argv[1], NULL, 0);
|
||||
dmaster = strtoul(argv[2], NULL, 0);
|
||||
|
||||
ret = ctdb_ctrl_setdmaster(ctdb, vnn, ctdb, dbid, dmaster);
|
||||
if (ret != 0) {
|
||||
printf("Unable to set dmaster for node %u db:0x%08x\n", vnn, dbid);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
clears a database
|
||||
*/
|
||||
static int control_cleardb(struct ctdb_context *ctdb, int argc, const char **argv)
|
||||
{
|
||||
uint32_t vnn, dbid;
|
||||
int ret;
|
||||
|
||||
if (argc < 2) {
|
||||
usage();
|
||||
}
|
||||
|
||||
vnn = strtoul(argv[0], NULL, 0);
|
||||
dbid = strtoul(argv[1], NULL, 0);
|
||||
|
||||
ret = ctdb_ctrl_cleardb(ctdb, vnn, ctdb, dbid);
|
||||
if (ret != 0) {
|
||||
printf("Unable to clear db for node %u db:0x%08x\n", vnn, dbid);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
ping all node
|
||||
*/
|
||||
@ -361,7 +724,7 @@ static int control_ping(struct ctdb_context *ctdb, int argc, const char **argv)
|
||||
|
||||
for (i=0;i<num_nodes;i++) {
|
||||
struct timeval tv = timeval_current();
|
||||
ret = ctdb_ping(ctdb, nodes[i]);
|
||||
ret = ctdb_ctrl_ping(ctdb, nodes[i]);
|
||||
if (ret == -1) {
|
||||
printf("Unable to get ping response from node %u\n", nodes[i]);
|
||||
} else {
|
||||
@ -388,7 +751,7 @@ static int control_debuglevel(struct ctdb_context *ctdb, int argc, const char **
|
||||
|
||||
for (i=0;i<num_nodes;i++) {
|
||||
uint32_t level;
|
||||
ret = ctdb_get_debuglevel(ctdb, nodes[i], &level);
|
||||
ret = ctdb_ctrl_get_debuglevel(ctdb, nodes[i], &level);
|
||||
if (ret != 0) {
|
||||
printf("Unable to get debuglevel response from node %u\n",
|
||||
nodes[i]);
|
||||
@ -418,7 +781,7 @@ static int control_debug(struct ctdb_context *ctdb, int argc, const char **argv)
|
||||
|
||||
if (strcmp(argv[0], "all") != 0) {
|
||||
vnn = strtoul(argv[0], NULL, 0);
|
||||
ret = ctdb_set_debuglevel(ctdb, vnn, level);
|
||||
ret = ctdb_ctrl_set_debuglevel(ctdb, vnn, level);
|
||||
if (ret != 0) {
|
||||
printf("Unable to set debug level on node %u\n", vnn);
|
||||
}
|
||||
@ -429,7 +792,7 @@ static int control_debug(struct ctdb_context *ctdb, int argc, const char **argv)
|
||||
nodes = ctdb_get_connected_nodes(ctdb, ctdb, &num_nodes);
|
||||
CTDB_NO_MEMORY(ctdb, nodes);
|
||||
for (i=0;i<num_nodes;i++) {
|
||||
ret = ctdb_set_debuglevel(ctdb, nodes[i], level);
|
||||
ret = ctdb_ctrl_set_debuglevel(ctdb, nodes[i], level);
|
||||
if (ret != 0) {
|
||||
printf("Unable to set debug level on node %u\n", nodes[i]);
|
||||
break;
|
||||
@ -525,14 +888,28 @@ int main(int argc, const char *argv[])
|
||||
ret = control_getdbmap(ctdb, extra_argc-1, extra_argv+1);
|
||||
} else if (strcmp(control, "getnodemap") == 0) {
|
||||
ret = control_getnodemap(ctdb, extra_argc-1, extra_argv+1);
|
||||
} else if (strcmp(control, "catdb") == 0) {
|
||||
ret = control_catdb(ctdb, extra_argc-1, extra_argv+1);
|
||||
} else if (strcmp(control, "cpdb") == 0) {
|
||||
ret = control_cpdb(ctdb, extra_argc-1, extra_argv+1);
|
||||
} else if (strcmp(control, "setvnnmap") == 0) {
|
||||
ret = control_setvnnmap(ctdb, extra_argc-1, extra_argv+1);
|
||||
} else if (strcmp(control, "setdmaster") == 0) {
|
||||
ret = control_setdmaster(ctdb, extra_argc-1, extra_argv+1);
|
||||
} else if (strcmp(control, "cleardb") == 0) {
|
||||
ret = control_cleardb(ctdb, extra_argc-1, extra_argv+1);
|
||||
} else if (strcmp(control, "getrecmode") == 0) {
|
||||
ret = control_getrecmode(ctdb, extra_argc-1, extra_argv+1);
|
||||
} else if (strcmp(control, "setrecmode") == 0) {
|
||||
ret = control_setrecmode(ctdb, extra_argc-1, extra_argv+1);
|
||||
} else if (strcmp(control, "ping") == 0) {
|
||||
ret = control_ping(ctdb, extra_argc-1, extra_argv+1);
|
||||
} else if (strcmp(control, "debug") == 0) {
|
||||
ret = control_debug(ctdb, extra_argc-1, extra_argv+1);
|
||||
} else if (strcmp(control, "debuglevel") == 0) {
|
||||
ret = control_debuglevel(ctdb, extra_argc-1, extra_argv+1);
|
||||
} else if (strcmp(control, "recover") == 0) {
|
||||
ret = control_recover(ctdb, extra_argc-1, extra_argv+1);
|
||||
} else if (strcmp(control, "attach") == 0) {
|
||||
ret = control_attach(ctdb, extra_argc-1, extra_argv+1);
|
||||
} else {
|
||||
|
Loading…
x
Reference in New Issue
Block a user