1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-24 21:34:56 +03:00

merge from ronnie

(This used to be ctdb commit e0f1c1acb1188500674626d631e1a1b8726e72ad)
This commit is contained in:
Andrew Tridgell 2007-08-22 17:31:29 +10:00
commit d95476fa38
11 changed files with 143 additions and 41 deletions

View File

@ -265,6 +265,8 @@ struct ctdb_statistics {
double max_lockwait_latency;
};
#define INVALID_GENERATION 1
/* table that contains the mapping between a hash value and lmaster
*/
struct ctdb_vnn_map {
@ -506,7 +508,8 @@ struct ctdb_control_tcp_vnn {
*/
struct ctdb_node_flag_change {
uint32_t vnn;
uint32_t flags;
uint32_t new_flags;
uint32_t old_flags;
};
/*

View File

@ -230,7 +230,7 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
ctdb_release_all_ips(ctdb);
ctdb->methods->shutdown(ctdb);
ctdb_event_script(ctdb, "shutdown");
DEBUG(0,("shutting down\n"));
DEBUG(0,("Received SHUTDOWN command. Stopping CTDB daemon.\n"));
exit(0);
case CTDB_CONTROL_MAX_RSN:

View File

@ -51,7 +51,7 @@ static void flag_change_handler(struct ctdb_context *ctdb, uint64_t srvid,
/* don't get the disconnected flag from the other node */
ctdb->nodes[c->vnn]->flags =
(ctdb->nodes[c->vnn]->flags&NODE_FLAGS_DISCONNECTED)
| (c->flags & ~NODE_FLAGS_DISCONNECTED);
| (c->new_flags & ~NODE_FLAGS_DISCONNECTED);
DEBUG(2,("Node flags for node %u are now 0x%x\n", c->vnn, ctdb->nodes[c->vnn]->flags));
/* make sure we don't hold any IPs when we shouldn't */
@ -218,7 +218,7 @@ int daemon_register_message_handler(struct ctdb_context *ctdb, uint32_t client_i
if ((srvid & 0xFFFFFFFF) == srvid &&
kill(srvid, 0) == 0) {
client->pid = srvid;
DEBUG(0,(__location__ " Registered PID %u for client %u\n",
DEBUG(3,(__location__ " Registered PID %u for client %u\n",
(unsigned)client->pid, client_id));
}
return res;
@ -616,6 +616,10 @@ static int unlink_destructor(const char *name)
return 0;
}
static void print_exit_message(void)
{
DEBUG(0,("CTDB daemon shutting down\n"));
}
/*
start the protocol going as a daemon
@ -640,6 +644,9 @@ int ctdb_start_daemon(struct ctdb_context *ctdb, bool do_fork)
return 0;
}
/* Make sure we log something when the daemon terminates */
atexit(print_exit_message);
tdb_reopen_all(False);
if (do_fork) {

View File

@ -194,8 +194,19 @@ int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata,
{
const char *db_name = (const char *)indata.dptr;
struct ctdb_db_context *ctdb_db, *tmp_db;
struct ctdb_node *node = ctdb->nodes[ctdb->vnn];
int ret;
/* If the node is inactive it is not part of the cluster
and we should not allow clients to attach to any
databases
*/
if (node->flags & NODE_FLAGS_INACTIVE) {
DEBUG(0,("DB Attach to database %s refused since node is inactive (disconnected or banned)\n", db_name));
return -1;
}
/* see if we already have this name */
for (tmp_db=ctdb->db_list;tmp_db;tmp_db=tmp_db->next) {
if (strcmp(db_name, tmp_db->db_name) == 0) {

View File

@ -103,6 +103,9 @@ static void ctdb_health_callback(struct ctdb_context *ctdb, int status, void *p)
timeval_current_ofs(ctdb->tunable.monitor_interval, 0),
ctdb_check_health, ctdb);
c.vnn = ctdb->vnn;
c.old_flags = node->flags;
if (status != 0 && !(node->flags & NODE_FLAGS_UNHEALTHY)) {
DEBUG(0,("monitor event failed - disabling node\n"));
node->flags |= NODE_FLAGS_UNHEALTHY;
@ -114,8 +117,7 @@ static void ctdb_health_callback(struct ctdb_context *ctdb, int status, void *p)
return;
}
c.vnn = ctdb->vnn;
c.flags = node->flags;
c.new_flags = node->flags;
data.dptr = (uint8_t *)&c;
data.dsize = sizeof(c);
@ -206,7 +208,8 @@ int32_t ctdb_control_modflags(struct ctdb_context *ctdb, TDB_DATA indata)
/* if we have been banned, go into recovery mode */
c.vnn = ctdb->vnn;
c.flags = node->flags;
c.old_flags = old_flags;
c.new_flags = node->flags;
data.dptr = (uint8_t *)&c;
data.dsize = sizeof(c);
@ -218,6 +221,13 @@ int32_t ctdb_control_modflags(struct ctdb_context *ctdb, TDB_DATA indata)
if ((node->flags & NODE_FLAGS_BANNED) && !(old_flags & NODE_FLAGS_BANNED)) {
/* make sure we are frozen */
DEBUG(0,("This node has been banned - forcing freeze and recovery\n"));
/* Reset the generation id to 1 to make us ignore any
REQ/REPLY CALL/DMASTER someone sends to us.
We are now banned so we shouldnt service database calls
anymore.
*/
ctdb->vnn_map->generation = INVALID_GENERATION;
ctdb_start_freeze(ctdb);
ctdb_release_all_ips(ctdb);
ctdb->recovery_mode = CTDB_RECOVERY_ACTIVE;

View File

@ -386,7 +386,8 @@ static int update_flags_on_all_nodes(struct ctdb_context *ctdb, struct ctdb_node
TDB_DATA data;
c.vnn = nodemap->nodes[i].vnn;
c.flags = nodemap->nodes[i].flags;
c.old_flags = nodemap->nodes[i].flags;
c.new_flags = nodemap->nodes[i].flags;
data.dptr = (uint8_t *)&c;
data.dsize = sizeof(c);
@ -610,6 +611,24 @@ static void ctdb_wait_timeout(struct ctdb_context *ctdb, uint32_t secs)
}
}
/* Create a new random generation ip.
The generation id can not be the INVALID_GENERATION id
*/
static uint32_t new_generation(void)
{
uint32_t generation;
while (1) {
generation = random();
if (generation != INVALID_GENERATION) {
break;
}
}
return generation;
}
/*
we are the recmaster, and recovery is needed - start a recovery run
*/
@ -654,7 +673,7 @@ static int do_recovery(struct ctdb_recoverd *rec,
DEBUG(0, (__location__ " Recovery initiated due to problem with node %u\n", culprit));
/* pick a new generation number */
generation = random();
generation = new_generation();
/* change the vnnmap on this node to use the new generation
number but not on any other nodes.
@ -728,7 +747,7 @@ static int do_recovery(struct ctdb_recoverd *rec,
/* build a new vnn map with all the currently active and
unbanned nodes */
generation = random();
generation = new_generation();
vnnmap = talloc(mem_ctx, struct ctdb_vnn_map);
CTDB_NO_MEMORY(ctdb, vnnmap);
vnnmap->generation = generation;
@ -815,7 +834,7 @@ static int do_recovery(struct ctdb_recoverd *rec,
/* send a message to all clients telling them that the cluster
has been reconfigured */
ctdb_send_message(ctdb, CTDB_BROADCAST_ALL, CTDB_SRVID_RECONFIGURE, tdb_null);
ctdb_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_RECONFIGURE, tdb_null);
DEBUG(0, (__location__ " Recovery complete\n"));
@ -1045,6 +1064,7 @@ static void monitor_handler(struct ctdb_context *ctdb, uint64_t srvid,
struct ctdb_node_flag_change *c = (struct ctdb_node_flag_change *)data.dptr;
struct ctdb_node_map *nodemap=NULL;
TALLOC_CTX *tmp_ctx;
uint32_t changed_flags;
int i;
if (data.dsize != sizeof(*c)) {
@ -1067,20 +1087,22 @@ static void monitor_handler(struct ctdb_context *ctdb, uint64_t srvid,
return;
}
changed_flags = c->old_flags ^ c->new_flags;
/* Dont let messages from remote nodes change the DISCONNECTED flag.
This flag is handled locally based on whether the local node
can communicate with the node or not.
*/
c->flags &= ~NODE_FLAGS_DISCONNECTED;
c->new_flags &= ~NODE_FLAGS_DISCONNECTED;
if (nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED) {
c->flags |= NODE_FLAGS_DISCONNECTED;
c->new_flags |= NODE_FLAGS_DISCONNECTED;
}
if (nodemap->nodes[i].flags != c->flags) {
DEBUG(0,("Node %u has changed flags - now 0x%x\n", c->vnn, c->flags));
if (nodemap->nodes[i].flags != c->new_flags) {
DEBUG(0,("Node %u has changed flags - now 0x%x was 0x%x\n", c->vnn, c->new_flags, c->old_flags));
}
nodemap->nodes[i].flags = c->flags;
nodemap->nodes[i].flags = c->new_flags;
ret = ctdb_ctrl_getrecmaster(ctdb, CONTROL_TIMEOUT(),
CTDB_CURRENT_NODE, &ctdb->recovery_master);
@ -1094,9 +1116,21 @@ static void monitor_handler(struct ctdb_context *ctdb, uint64_t srvid,
ctdb->recovery_master == ctdb->vnn &&
ctdb->recovery_mode == CTDB_RECOVERY_NORMAL &&
ctdb->takeover.enabled) {
ret = ctdb_takeover_run(ctdb, nodemap);
if (ret != 0) {
DEBUG(0, (__location__ " Unable to setup public takeover addresses\n"));
/* Only do the takeover run if the perm disabled or unhealthy
flags changed since these will cause an ip failover but not
a recovery.
If the node became disconnected or banned this will also
lead to an ip address failover but that is handled
during recovery
*/
if (changed_flags & NODE_FLAGS_DISABLED) {
ret = ctdb_takeover_run(ctdb, nodemap);
if (ret != 0) {
DEBUG(0, (__location__ " Unable to setup public takeover addresses\n"));
}
/* send a message to all clients telling them that the
cluster has been reconfigured */
ctdb_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_RECONFIGURE, tdb_null);
}
}

View File

@ -151,17 +151,10 @@ int ctdb_set_nlist(struct ctdb_context *ctdb, const char *nlist)
}
/* initialize the vnn mapping table now that we have num_nodes setup */
/*
XXX we currently initialize it to the maximum number of nodes to
XXX make it behave the same way as previously.
XXX Once we have recovery working we should initialize this always to
XXX generation==0 (==invalid) and let the recovery tool populate this
XXX table for the daemons.
*/
ctdb->vnn_map = talloc(ctdb, struct ctdb_vnn_map);
CTDB_NO_MEMORY(ctdb, ctdb->vnn_map);
ctdb->vnn_map->generation = 1;
ctdb->vnn_map->generation = INVALID_GENERATION;
ctdb->vnn_map->size = ctdb->num_nodes;
ctdb->vnn_map->map = talloc_array(ctdb->vnn_map, uint32_t, ctdb->vnn_map->size);
CTDB_NO_MEMORY(ctdb, ctdb->vnn_map->map);
@ -232,6 +225,18 @@ void ctdb_input_pkt(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
case CTDB_REPLY_CALL:
case CTDB_REQ_DMASTER:
case CTDB_REPLY_DMASTER:
/* we dont allow these calls when banned */
if (ctdb->nodes[ctdb->vnn]->flags & NODE_FLAGS_BANNED) {
DEBUG(0,(__location__ " ctdb operation %u"
" request %u"
" length %u from node %u to %u while node"
" is banned\n",
hdr->operation, hdr->reqid,
hdr->length,
hdr->srcnode, hdr->destnode));
goto done;
}
/* for ctdb_call inter-node operations verify that the
remote node that sent us the call is running in the
same generation instance as this node

View File

@ -524,6 +524,19 @@ int ctdb_takeover_run(struct ctdb_context *ctdb, struct ctdb_node_map *nodemap)
if (!(nodemap->nodes[i].flags & (NODE_FLAGS_INACTIVE|NODE_FLAGS_DISABLED))) {
ctdb->nodes[i]->takeover_vnn = nodemap->nodes[i].vnn;
} else {
uint32_t takeover_vnn;
/* If this public address has already been taken over
by a node and that node is still healthy, then
leave the public address at that node.
*/
takeover_vnn = ctdb->nodes[i]->takeover_vnn;
if ( ctdb_validate_vnn(ctdb, takeover_vnn)
&& (!(nodemap->nodes[takeover_vnn].flags & (NODE_FLAGS_INACTIVE|NODE_FLAGS_DISABLED))) ) {
continue;
}
ctdb->nodes[i]->takeover_vnn = (uint32_t)-1;
ctdb_takeover_find_node(ctdb, nodemap, i, NODE_FLAGS_INACTIVE|NODE_FLAGS_DISABLED);

View File

@ -147,6 +147,14 @@ int main(int argc, const char *argv[])
ctdb = ctdb_cmdline_init(ev);
ret = ctdb_set_logfile(ctdb, options.logfile);
if (ret == -1) {
printf("ctdb_set_logfile to %s failed - %s\n", options.logfile, ctdb_errstr(ctdb));
exit(1);
}
DEBUG(0,("Starting CTDB daemon\n"));
ctdb->recovery_mode = CTDB_RECOVERY_NORMAL;
ctdb->recovery_master = (uint32_t)-1;
ctdb->upcalls = &ctdb_upcalls;
@ -158,13 +166,13 @@ int main(int argc, const char *argv[])
ret = ctdb_set_recovery_lock_file(ctdb, options.recovery_lock_file);
if (ret == -1) {
printf("ctdb_set_recovery_lock_file failed - %s\n", ctdb_errstr(ctdb));
DEBUG(0,("ctdb_set_recovery_lock_file failed - %s\n", ctdb_errstr(ctdb)));
exit(1);
}
ret = ctdb_set_transport(ctdb, options.transport);
if (ret == -1) {
printf("ctdb_set_transport failed - %s\n", ctdb_errstr(ctdb));
DEBUG(0,("ctdb_set_transport failed - %s\n", ctdb_errstr(ctdb)));
exit(1);
}
@ -172,7 +180,7 @@ int main(int argc, const char *argv[])
if (options.myaddress) {
ret = ctdb_set_address(ctdb, options.myaddress);
if (ret == -1) {
printf("ctdb_set_address failed - %s\n", ctdb_errstr(ctdb));
DEBUG(0,("ctdb_set_address failed - %s\n", ctdb_errstr(ctdb)));
exit(1);
}
}
@ -180,24 +188,18 @@ int main(int argc, const char *argv[])
/* tell ctdb what nodes are available */
ret = ctdb_set_nlist(ctdb, options.nlist);
if (ret == -1) {
printf("ctdb_set_nlist failed - %s\n", ctdb_errstr(ctdb));
DEBUG(0,("ctdb_set_nlist failed - %s\n", ctdb_errstr(ctdb)));
exit(1);
}
if (options.db_dir) {
ret = ctdb_set_tdb_dir(ctdb, options.db_dir);
if (ret == -1) {
printf("ctdb_set_tdb_dir failed - %s\n", ctdb_errstr(ctdb));
DEBUG(0,("ctdb_set_tdb_dir failed - %s\n", ctdb_errstr(ctdb)));
exit(1);
}
}
ret = ctdb_set_logfile(ctdb, options.logfile);
if (ret == -1) {
printf("ctdb_set_logfile to %s failed - %s\n", options.logfile, ctdb_errstr(ctdb));
exit(1);
}
if (options.public_interface) {
ctdb->takeover.interface = talloc_strdup(ctdb, options.public_interface);
CTDB_NO_MEMORY(ctdb, ctdb->takeover.interface);
@ -206,7 +208,7 @@ int main(int argc, const char *argv[])
if (options.public_address_list) {
ret = ctdb_set_public_addresses(ctdb, options.public_address_list);
if (ret == -1) {
printf("Unable to setup public address list\n");
DEBUG(0,("Unable to setup public address list\n"));
exit(1);
}
ctdb->takeover.enabled = true;
@ -214,7 +216,7 @@ int main(int argc, const char *argv[])
ret = ctdb_set_event_script_dir(ctdb, options.event_script_dir);
if (ret == -1) {
printf("Unable to setup event script directory\n");
DEBUG(0,("Unable to setup event script directory\n"));
exit(1);
}

View File

@ -98,6 +98,7 @@ static int ctdb_event_script_v(struct ctdb_context *ctdb, const char *fmt, va_li
while ((de=readdir(dir)) != NULL) {
int namlen;
unsigned num;
char *str;
namlen = strlen(de->d_name);
@ -117,6 +118,18 @@ static int ctdb_event_script_v(struct ctdb_context *ctdb, const char *fmt, va_li
if (sscanf(de->d_name, "%02u.", &num) != 1) {
continue;
}
/* Make sure the event script is executable */
str = talloc_asprintf(tree, "%s/%s", ctdb->takeover.event_script_dir, de->d_name);
if (stat(str, &st) != 0) {
DEBUG(0,("Could not stat event script %s. Ignoring this event script\n", str));
continue;
}
if (!(st.st_mode & S_IXUSR)) {
DEBUG(0,("Event script %s is not executable. Ignoring this event script\n", str));
continue;
}
/* store the event script in the tree */
script = trbt_insert32(tree, num, talloc_strdup(tree, de->d_name));

View File

@ -282,7 +282,11 @@ static int control_status(struct ctdb_context *ctdb, int argc, const char **argv
DEBUG(0, ("Unable to get vnnmap from node %u\n", options.vnn));
return ret;
}
printf("Generation:%d\n",vnnmap->generation);
if (vnnmap->generation == INVALID_GENERATION) {
printf("Generation:INVALID\n");
} else {
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]);