#define CTDB_ARP_REPEAT 3
/* Flags used in IP allocation algorithms. */
-struct ctdb_ipflags {
- bool noiptakeover;
- bool noiphost;
-};
-
enum ipalloc_algorithm {
IPALLOC_DETERMINISTIC,
IPALLOC_NONDETERMINISTIC,
/* Arrays with data for each node */
struct ctdb_public_ip_list_old **known_public_ips;
struct ctdb_public_ip_list_old **available_public_ips;
- struct ctdb_ipflags *ipflags;
+ bool *noiptakeover;
+ bool *noiphost;
+ struct public_ip_list *all_ips;
enum ipalloc_algorithm algorithm;
uint32_t no_ip_failback;
+ uint32_t *force_rebalance_nodes;
};
struct ctdb_interface {
struct ctdb_public_ip_list_old *public_ips;
int i;
- if (ipalloc_state->ipflags[pnn].noiphost) {
+ if (ipalloc_state->noiphost[pnn]) {
return false;
}
int32_t pnn,
struct public_ip_list *ip)
{
- if (ipalloc_state->ipflags[pnn].noiptakeover) {
+ if (ipalloc_state->noiptakeover[pnn]) {
return false;
}
so that the ips get spread out evenly.
*/
static int find_takeover_node(struct ipalloc_state *ipalloc_state,
- struct public_ip_list *ip,
- struct public_ip_list *all_ips)
+ struct public_ip_list *ip)
{
int pnn, min=0, num;
int i, numnodes;
continue;
}
- num = node_ip_coverage(i, all_ips);
+ num = node_ip_coverage(i, ipalloc_state->all_ips);
/* was this the first node we checked ? */
if (pnn == -1) {
pnn = i;
uint32_t sum = 0;
- for (t=ips; t != NULL; t=t->next) {
+ for (t = ips; t != NULL; t = t->next) {
if (t->pnn != pnn) {
continue;
}
uint32_t imbalance = 0;
- for (t=all_ips; t!=NULL; t=t->next) {
+ for (t = all_ips; t != NULL; t = t->next) {
if (t->pnn != pnn) {
continue;
}
/* Allocate any unassigned IPs just by looping through the IPs and
* finding the best node for each.
*/
-static void basic_allocate_unassigned(struct ipalloc_state *ipalloc_state,
- struct public_ip_list *all_ips)
+static void basic_allocate_unassigned(struct ipalloc_state *ipalloc_state)
{
- struct public_ip_list *tmp_ip;
+ struct public_ip_list *t;
/* loop over all ip's and find a physical node to cover for
each unassigned ip.
*/
- for (tmp_ip=all_ips;tmp_ip;tmp_ip=tmp_ip->next) {
- if (tmp_ip->pnn == -1) {
- if (find_takeover_node(ipalloc_state,
- tmp_ip, all_ips)) {
+ for (t = ipalloc_state->all_ips; t != NULL; t = t->next) {
+ if (t->pnn == -1) {
+ if (find_takeover_node(ipalloc_state, t)) {
DEBUG(DEBUG_WARNING,
("Failed to find node to cover ip %s\n",
- ctdb_addr_to_str(&tmp_ip->addr)));
+ ctdb_addr_to_str(&t->addr)));
}
}
}
/* Basic non-deterministic rebalancing algorithm.
*/
static void basic_failback(struct ipalloc_state *ipalloc_state,
- struct public_ip_list *all_ips,
int num_ips)
{
int i, numnodes;
int maxnode, maxnum, minnode, minnum, num, retries;
- struct public_ip_list *tmp_ip;
+ struct public_ip_list *t;
numnodes = ipalloc_state->num;
retries = 0;
serving the most and the node serving the least ip's are
not greater than 1.
*/
- for (tmp_ip=all_ips;tmp_ip;tmp_ip=tmp_ip->next) {
- if (tmp_ip->pnn == -1) {
+ for (t = ipalloc_state->all_ips; t != NULL; t = t->next) {
+ if (t->pnn == -1) {
continue;
}
for (i=0; i<numnodes; i++) {
/* only check nodes that can actually serve this ip */
if (!can_node_takeover_ip(ipalloc_state, i,
- tmp_ip)) {
+ t)) {
/* no it couldnt so skip to the next node */
continue;
}
- num = node_ip_coverage(i, all_ips);
+ num = node_ip_coverage(i, ipalloc_state->all_ips);
if (maxnode == -1) {
maxnode = i;
maxnum = num;
}
}
if (maxnode == -1) {
- DEBUG(DEBUG_WARNING,(__location__ " Could not find maxnode. May not be able to serve ip '%s'\n",
- ctdb_addr_to_str(&tmp_ip->addr)));
+ DEBUG(DEBUG_WARNING,
+ (__location__ " Could not find maxnode. May not be able to serve ip '%s'\n",
+ ctdb_addr_to_str(&t->addr)));
continue;
}
try to do this a limited number of times since we dont
want to spend too much time balancing the ip coverage.
*/
- if ( (maxnum > minnum+1)
- && (retries < (num_ips + 5)) ){
- struct public_ip_list *tmp;
+ if ((maxnum > minnum+1) &&
+ (retries < (num_ips + 5))){
+ struct public_ip_list *tt;
/* Reassign one of maxnode's VNNs */
- for (tmp=all_ips;tmp;tmp=tmp->next) {
- if (tmp->pnn == maxnode) {
+ for (tt = ipalloc_state->all_ips; tt != NULL; tt = tt->next) {
+ if (tt->pnn == maxnode) {
(void)find_takeover_node(ipalloc_state,
- tmp,
- all_ips);
+ tt);
retries++;
goto try_again;;
}
}
static bool lcp2_init(struct ipalloc_state *ipalloc_state,
- struct public_ip_list *all_ips,
- uint32_t *force_rebalance_nodes,
uint32_t **lcp2_imbalances,
bool **rebalance_candidates)
{
int i, numnodes;
- struct public_ip_list *tmp_ip;
+ struct public_ip_list *t;
numnodes = ipalloc_state->num;
}
for (i=0; i<numnodes; i++) {
- (*lcp2_imbalances)[i] = lcp2_imbalance(all_ips, i);
+ (*lcp2_imbalances)[i] =
+ lcp2_imbalance(ipalloc_state->all_ips, i);
/* First step: assume all nodes are candidates */
(*rebalance_candidates)[i] = true;
}
* keep state and invalidate it every time the recovery master
* changes.
*/
- for (tmp_ip=all_ips;tmp_ip;tmp_ip=tmp_ip->next) {
- if (tmp_ip->pnn != -1) {
- (*rebalance_candidates)[tmp_ip->pnn] = false;
+ for (t = ipalloc_state->all_ips; t != NULL; t = t->next) {
+ if (t->pnn != -1) {
+ (*rebalance_candidates)[t->pnn] = false;
}
}
/* 3rd step: if a node is forced to re-balance then
we allow failback onto the node */
- if (force_rebalance_nodes == NULL) {
+ if (ipalloc_state->force_rebalance_nodes == NULL) {
return true;
}
- for (i = 0; i < talloc_array_length(force_rebalance_nodes); i++) {
- uint32_t pnn = force_rebalance_nodes[i];
+ for (i = 0;
+ i < talloc_array_length(ipalloc_state->force_rebalance_nodes);
+ i++) {
+ uint32_t pnn = ipalloc_state->force_rebalance_nodes[i];
if (pnn >= numnodes) {
DEBUG(DEBUG_ERR,
(__location__ "unknown node %u\n", pnn));
* the IP/node combination that will cost the least.
*/
static void lcp2_allocate_unassigned(struct ipalloc_state *ipalloc_state,
- struct public_ip_list *all_ips,
uint32_t *lcp2_imbalances)
{
- struct public_ip_list *tmp_ip;
+ struct public_ip_list *t;
int dstnode, numnodes;
int minnode;
minip = NULL;
/* loop over each unassigned ip. */
- for (tmp_ip=all_ips;tmp_ip;tmp_ip=tmp_ip->next) {
- if (tmp_ip->pnn != -1) {
+ for (t = ipalloc_state->all_ips; t != NULL ; t = t->next) {
+ if (t->pnn != -1) {
continue;
}
- for (dstnode=0; dstnode<numnodes; dstnode++) {
+ for (dstnode = 0; dstnode < numnodes; dstnode++) {
/* only check nodes that can actually takeover this ip */
if (!can_node_takeover_ip(ipalloc_state,
dstnode,
- tmp_ip)) {
+ t)) {
/* no it couldnt so skip to the next node */
continue;
}
- dstdsum = ip_distance_2_sum(&(tmp_ip->addr), all_ips, dstnode);
+ dstdsum = ip_distance_2_sum(&(t->addr),
+ ipalloc_state->all_ips,
+ dstnode);
dstimbl = lcp2_imbalances[dstnode] + dstdsum;
- DEBUG(DEBUG_DEBUG,(" %s -> %d [+%d]\n",
- ctdb_addr_to_str(&(tmp_ip->addr)),
- dstnode,
- dstimbl - lcp2_imbalances[dstnode]));
+ DEBUG(DEBUG_DEBUG,
+ (" %s -> %d [+%d]\n",
+ ctdb_addr_to_str(&(t->addr)),
+ dstnode,
+ dstimbl - lcp2_imbalances[dstnode]));
if ((minnode == -1) || (dstdsum < mindsum)) {
minnode = dstnode;
minimbl = dstimbl;
mindsum = dstdsum;
- minip = tmp_ip;
+ minip = t;
should_loop = true;
}
}
/* There might be a better way but at least this is clear. */
have_unassigned = false;
- for (tmp_ip=all_ips;tmp_ip;tmp_ip=tmp_ip->next) {
- if (tmp_ip->pnn == -1) {
+ for (t = ipalloc_state->all_ips; t != NULL; t = t->next) {
+ if (t->pnn == -1) {
have_unassigned = true;
}
}
* well optimise.
*/
if (have_unassigned) {
- for (tmp_ip=all_ips;tmp_ip;tmp_ip=tmp_ip->next) {
- if (tmp_ip->pnn == -1) {
- DEBUG(DEBUG_WARNING,("Failed to find node to cover ip %s\n",
- ctdb_addr_to_str(&tmp_ip->addr)));
+ for (t = ipalloc_state->all_ips; t != NULL; t = t->next) {
+ if (t->pnn == -1) {
+ DEBUG(DEBUG_WARNING,
+ ("Failed to find node to cover ip %s\n",
+ ctdb_addr_to_str(&t->addr)));
}
}
}
* combination to move from the source node.
*/
static bool lcp2_failback_candidate(struct ipalloc_state *ipalloc_state,
- struct public_ip_list *all_ips,
int srcnode,
uint32_t *lcp2_imbalances,
bool *rebalance_candidates)
uint32_t srcimbl, srcdsum, dstimbl, dstdsum;
uint32_t minsrcimbl, mindstimbl;
struct public_ip_list *minip;
- struct public_ip_list *tmp_ip;
+ struct public_ip_list *t;
/* Find an IP and destination node that best reduces imbalance. */
srcimbl = 0;
DEBUG(DEBUG_DEBUG,(" CONSIDERING MOVES FROM %d [%d]\n",
srcnode, lcp2_imbalances[srcnode]));
- for (tmp_ip=all_ips; tmp_ip; tmp_ip=tmp_ip->next) {
+ for (t = ipalloc_state->all_ips; t != NULL; t = t->next) {
/* Only consider addresses on srcnode. */
- if (tmp_ip->pnn != srcnode) {
+ if (t->pnn != srcnode) {
continue;
}
/* What is this IP address costing the source node? */
- srcdsum = ip_distance_2_sum(&(tmp_ip->addr), all_ips, srcnode);
+ srcdsum = ip_distance_2_sum(&(t->addr),
+ ipalloc_state->all_ips,
+ srcnode);
srcimbl = lcp2_imbalances[srcnode] - srcdsum;
/* Consider this IP address would cost each potential
* to do gratuitous failover of IPs just to make minor
* balance improvements.
*/
- for (dstnode=0; dstnode<numnodes; dstnode++) {
+ for (dstnode = 0; dstnode < numnodes; dstnode++) {
if (!rebalance_candidates[dstnode]) {
continue;
}
/* only check nodes that can actually takeover this ip */
if (!can_node_takeover_ip(ipalloc_state, dstnode,
- tmp_ip)) {
+ t)) {
/* no it couldnt so skip to the next node */
continue;
}
- dstdsum = ip_distance_2_sum(&(tmp_ip->addr), all_ips, dstnode);
+ dstdsum = ip_distance_2_sum(&(t->addr),
+ ipalloc_state->all_ips,
+ dstnode);
dstimbl = lcp2_imbalances[dstnode] + dstdsum;
DEBUG(DEBUG_DEBUG,(" %d [%d] -> %s -> %d [+%d]\n",
srcnode, -srcdsum,
- ctdb_addr_to_str(&(tmp_ip->addr)),
+ ctdb_addr_to_str(&(t->addr)),
dstnode, dstdsum));
if ((dstimbl < lcp2_imbalances[srcnode]) &&
((mindstnode == -1) || \
((srcimbl + dstimbl) < (minsrcimbl + mindstimbl)))) {
- minip = tmp_ip;
+ minip = t;
minsrcimbl = srcimbl;
mindstnode = dstnode;
mindstimbl = dstimbl;
if (mindstnode != -1) {
/* We found a move that makes things better... */
- DEBUG(DEBUG_INFO,("%d [%d] -> %s -> %d [+%d]\n",
- srcnode, minsrcimbl - lcp2_imbalances[srcnode],
- ctdb_addr_to_str(&(minip->addr)),
- mindstnode, mindstimbl - lcp2_imbalances[mindstnode]));
+ DEBUG(DEBUG_INFO,
+ ("%d [%d] -> %s -> %d [+%d]\n",
+ srcnode, minsrcimbl - lcp2_imbalances[srcnode],
+ ctdb_addr_to_str(&(minip->addr)),
+ mindstnode, mindstimbl - lcp2_imbalances[mindstnode]));
lcp2_imbalances[srcnode] = minsrcimbl;
* IP/destination node combination to move from the source node.
*/
static void lcp2_failback(struct ipalloc_state *ipalloc_state,
- struct public_ip_list *all_ips,
uint32_t *lcp2_imbalances,
bool *rebalance_candidates)
{
DEBUG(DEBUG_DEBUG,("+++++++++++++++++++++++++++++++++++++++++\n"));
DEBUG(DEBUG_DEBUG,("Selecting most imbalanced node from:\n"));
lips = talloc_array(ipalloc_state, struct lcp2_imbalance_pnn, numnodes);
- for (i=0; i<numnodes; i++) {
+ for (i = 0; i < numnodes; i++) {
lips[i].imbalance = lcp2_imbalances[i];
lips[i].pnn = i;
DEBUG(DEBUG_DEBUG,(" %d [%d]\n", i, lcp2_imbalances[i]));
lcp2_cmp_imbalance_pnn);
again = false;
- for (i=0; i<numnodes; i++) {
+ for (i = 0; i < numnodes; i++) {
/* This means that all nodes had 0 or 1 addresses, so
* can't be imbalanced.
*/
}
if (lcp2_failback_candidate(ipalloc_state,
- all_ips,
lips[i].pnn,
lcp2_imbalances,
rebalance_candidates)) {
}
}
-static void unassign_unsuitable_ips(struct ipalloc_state *ipalloc_state,
- struct public_ip_list *all_ips)
+static void unassign_unsuitable_ips(struct ipalloc_state *ipalloc_state)
{
- struct public_ip_list *tmp_ip;
+ struct public_ip_list *t;
/* verify that the assigned nodes can serve that public ip
and set it to -1 if not
*/
- for (tmp_ip=all_ips;tmp_ip;tmp_ip=tmp_ip->next) {
- if (tmp_ip->pnn == -1) {
+ for (t = ipalloc_state->all_ips; t != NULL; t = t->next) {
+ if (t->pnn == -1) {
continue;
}
- if (!can_node_host_ip(ipalloc_state, tmp_ip->pnn,
- tmp_ip) != 0) {
+ if (!can_node_host_ip(ipalloc_state, t->pnn, t) != 0) {
/* this node can not serve this ip. */
DEBUG(DEBUG_DEBUG,("Unassign IP: %s from %d\n",
- ctdb_addr_to_str(&(tmp_ip->addr)),
- tmp_ip->pnn));
- tmp_ip->pnn = -1;
+ ctdb_addr_to_str(&(t->addr)),
+ t->pnn));
+ t->pnn = -1;
}
}
}
-static bool ip_alloc_deterministic_ips(struct ipalloc_state *ipalloc_state,
- struct public_ip_list *all_ips)
+static bool ip_alloc_deterministic_ips(struct ipalloc_state *ipalloc_state)
{
- struct public_ip_list *tmp_ip;
+ struct public_ip_list *t;
int i, numnodes;
numnodes = ipalloc_state->num;
* available/unavailable nodes.
*/
- for (i=0,tmp_ip=all_ips;tmp_ip;tmp_ip=tmp_ip->next,i++) {
- tmp_ip->pnn = i % numnodes;
+ for (i = 0, t = ipalloc_state->all_ips; t!= NULL; t = t->next, i++) {
+ t->pnn = i % numnodes;
}
/* IP failback doesn't make sense with deterministic
DEBUG(DEBUG_WARNING, ("WARNING: 'NoIPFailback' set but ignored - incompatible with 'DeterministicIPs\n"));
}
- unassign_unsuitable_ips(ipalloc_state, all_ips);
+ unassign_unsuitable_ips(ipalloc_state);
- basic_allocate_unassigned(ipalloc_state, all_ips);
+ basic_allocate_unassigned(ipalloc_state);
/* No failback here! */
return true;
}
-static bool ip_alloc_nondeterministic_ips(struct ipalloc_state *ipalloc_state,
- struct public_ip_list *all_ips)
+static bool ip_alloc_nondeterministic_ips(struct ipalloc_state *ipalloc_state)
{
/* This should be pushed down into basic_failback. */
- struct public_ip_list *tmp_ip;
+ struct public_ip_list *t;
int num_ips = 0;
- for (tmp_ip=all_ips;tmp_ip;tmp_ip=tmp_ip->next) {
+ for (t = ipalloc_state->all_ips; t != NULL; t = t->next) {
num_ips++;
}
- unassign_unsuitable_ips(ipalloc_state, all_ips);
+ unassign_unsuitable_ips(ipalloc_state);
- basic_allocate_unassigned(ipalloc_state, all_ips);
+ basic_allocate_unassigned(ipalloc_state);
/* If we don't want IPs to fail back then don't rebalance IPs. */
if (1 == ipalloc_state->no_ip_failback) {
/* Now, try to make sure the ip adresses are evenly distributed
across the nodes.
*/
- basic_failback(ipalloc_state, all_ips, num_ips);
+ basic_failback(ipalloc_state, num_ips);
return true;
}
-static bool ip_alloc_lcp2(struct ipalloc_state *ipalloc_state,
- struct public_ip_list *all_ips,
- uint32_t *force_rebalance_nodes)
+static bool ip_alloc_lcp2(struct ipalloc_state *ipalloc_state)
{
uint32_t *lcp2_imbalances;
bool *rebalance_candidates;
int numnodes, num_rebalance_candidates, i;
bool ret = true;
- unassign_unsuitable_ips(ipalloc_state, all_ips);
+ unassign_unsuitable_ips(ipalloc_state);
- if (!lcp2_init(ipalloc_state, all_ips,force_rebalance_nodes,
+ if (!lcp2_init(ipalloc_state,
&lcp2_imbalances, &rebalance_candidates)) {
ret = false;
goto finished;
}
- lcp2_allocate_unassigned(ipalloc_state, all_ips, lcp2_imbalances);
+ lcp2_allocate_unassigned(ipalloc_state, lcp2_imbalances);
/* If we don't want IPs to fail back then don't rebalance IPs. */
if (1 == ipalloc_state->no_ip_failback) {
/* Now, try to make sure the ip adresses are evenly distributed
across the nodes.
*/
- lcp2_failback(ipalloc_state, all_ips,
- lcp2_imbalances, rebalance_candidates);
+ lcp2_failback(ipalloc_state, lcp2_imbalances, rebalance_candidates);
finished:
return ret;
}
/* The calculation part of the IP allocation algorithm. */
-static bool ctdb_takeover_run_core(struct ipalloc_state *ipalloc_state,
- struct public_ip_list *all_ips,
- uint32_t *force_rebalance_nodes)
+static bool ipalloc(struct ipalloc_state *ipalloc_state)
{
bool ret;
switch (ipalloc_state->algorithm) {
case IPALLOC_LCP2:
- ret = ip_alloc_lcp2(ipalloc_state, all_ips,
- force_rebalance_nodes);
+ ret = ip_alloc_lcp2(ipalloc_state);
break;
case IPALLOC_DETERMINISTIC:
- ret = ip_alloc_deterministic_ips(ipalloc_state, all_ips);
+ ret = ip_alloc_deterministic_ips(ipalloc_state);
break;
case IPALLOC_NONDETERMINISTIC:
- ret = ip_alloc_nondeterministic_ips(ipalloc_state, all_ips);
+ ret = ip_alloc_nondeterministic_ips(ipalloc_state);
break;
}
* else
* Set NOIPHOST ip flags for disabled nodes
*/
-static bool set_ipflags_internal(struct ipalloc_state *ipalloc_state,
+static void set_ipflags_internal(struct ipalloc_state *ipalloc_state,
struct ctdb_node_map_old *nodemap,
uint32_t *tval_noiptakeover,
uint32_t *tval_noiphostonalldisabled)
{
int i;
- /* Clear IP flags - implicit due to talloc_zero */
- ipalloc_state->ipflags =
- talloc_zero_array(ipalloc_state, struct ctdb_ipflags, nodemap->num);
- if (ipalloc_state->ipflags == NULL) {
- DEBUG(DEBUG_ERR, (__location__ " out of memory\n"));
- return false;
- }
-
for (i=0;i<nodemap->num;i++) {
/* Can not take IPs on node with NoIPTakeover set */
if (tval_noiptakeover[i] != 0) {
- ipalloc_state->ipflags[i].noiptakeover = true;
+ ipalloc_state->noiptakeover[i] = true;
}
/* Can not host IPs on INACTIVE node */
if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
- ipalloc_state->ipflags[i].noiphost = true;
+ ipalloc_state->noiphost[i] = true;
}
}
*/
for (i=0;i<nodemap->num;i++) {
if (tval_noiphostonalldisabled[i] != 0) {
- ipalloc_state->ipflags[i].noiphost = true;
+ ipalloc_state->noiphost[i] = true;
}
}
} else {
*/
for (i=0;i<nodemap->num;i++) {
if (nodemap->nodes[i].flags & NODE_FLAGS_DISABLED) {
- ipalloc_state->ipflags[i].noiphost = true;
+ ipalloc_state->noiphost[i] = true;
}
}
}
-
- return true;
}
static bool set_ipflags(struct ctdb_context *ctdb,
{
uint32_t *tval_noiptakeover;
uint32_t *tval_noiphostonalldisabled;
- bool ret;
tval_noiptakeover = get_tunable_from_nodes(ctdb, ipalloc_state, nodemap,
"NoIPTakeover", 0);
return false;
}
- ret = set_ipflags_internal(ipalloc_state, nodemap,
- tval_noiptakeover,
- tval_noiphostonalldisabled);
+ set_ipflags_internal(ipalloc_state, nodemap,
+ tval_noiptakeover,
+ tval_noiphostonalldisabled);
talloc_free(tval_noiptakeover);
talloc_free(tval_noiphostonalldisabled);
- return ret;
+ return true;
}
static struct ipalloc_state * ipalloc_state_init(struct ctdb_context *ctdb,
talloc_free(ipalloc_state);
return NULL;
}
+ ipalloc_state->noiptakeover =
+ talloc_zero_array(ipalloc_state,
+ bool,
+ ipalloc_state->num);
+ if (ipalloc_state->noiptakeover == NULL) {
+ DEBUG(DEBUG_ERR, (__location__ " Out of memory\n"));
+ talloc_free(ipalloc_state);
+ return NULL;
+ }
+ ipalloc_state->noiphost =
+ talloc_zero_array(ipalloc_state,
+ bool,
+ ipalloc_state->num);
+ if (ipalloc_state->noiphost == NULL) {
+ DEBUG(DEBUG_ERR, (__location__ " Out of memory\n"));
+ talloc_free(ipalloc_state);
+ return NULL;
+ }
if (1 == ctdb->tunable.lcp2_public_ip_assignment) {
ipalloc_state->algorithm = IPALLOC_LCP2;
keep the tree of ips around as ctdb->ip_tree
*/
all_ips = create_merged_ip_list(ctdb, ipalloc_state);
+ ipalloc_state->all_ips = all_ips;
+
+ ipalloc_state->force_rebalance_nodes = force_rebalance_nodes;
/* Do the IP reassignment calculations */
- ctdb_takeover_run_core(ipalloc_state,
- all_ips, force_rebalance_nodes);
+ ipalloc(ipalloc_state);
/* Now tell all nodes to release any public IPs should not
* host. This will be a NOOP on nodes that don't currently
}
-/*
- called by a daemon to inform us of a TCP connection that one of its
- clients managing that should tickled with an ACK when IP takeover is
- done
- */
-static void ctdb_remove_connection(struct ctdb_context *ctdb, struct ctdb_connection *conn)
+static void ctdb_remove_connection(struct ctdb_vnn *vnn, struct ctdb_connection *conn)
{
struct ctdb_connection *tcpp;
- struct ctdb_vnn *vnn = find_public_ip_vnn(ctdb, &conn->dst);
if (vnn == NULL) {
- DEBUG(DEBUG_ERR,(__location__ " unable to find public address %s\n",
- ctdb_addr_to_str(&conn->dst)));
return;
}
*/
int32_t ctdb_control_tcp_remove(struct ctdb_context *ctdb, TDB_DATA indata)
{
+ struct ctdb_vnn *vnn;
struct ctdb_connection *conn = (struct ctdb_connection *)indata.dptr;
/* If we don't have public IPs, tickles are useless */
return 0;
}
- ctdb_remove_connection(ctdb, conn);
+ vnn = find_public_ip_vnn(ctdb, &conn->dst);
+ if (vnn == NULL) {
+ DEBUG(DEBUG_ERR,
+ (__location__ " unable to find public address %s\n",
+ ctdb_addr_to_str(&conn->dst)));
+ return 0;
+ }
+
+ ctdb_remove_connection(vnn, conn);
return 0;
}
void ctdb_takeover_client_destructor_hook(struct ctdb_client *client)
{
while (client->tcp_list) {
+ struct ctdb_vnn *vnn;
struct ctdb_tcp_list *tcp = client->tcp_list;
+ struct ctdb_connection *conn = &tcp->connection;
+
DLIST_REMOVE(client->tcp_list, tcp);
- ctdb_remove_connection(client->ctdb, &tcp->connection);
+
+ vnn = find_public_ip_vnn(client->ctdb,
+ &conn->dst);
+ if (vnn == NULL) {
+ DEBUG(DEBUG_ERR,
+ (__location__ " unable to find public address %s\n",
+ ctdb_addr_to_str(&conn->dst)));
+ continue;
+ }
+
+ /* If the IP address is hosted on this node then
+ * remove the connection. */
+ if (vnn->pnn == client->ctdb->pnn) {
+ ctdb_remove_connection(vnn, conn);
+ }
+
+ /* Otherwise this function has been called because the
+ * server IP address has been released to another node
+ * and the client has exited. This means that we
+ * should not delete the connection information. The
+ * takeover node processes connections too. */
}
}
return 1;
}
+ if (vnn->pnn == ctdb->pnn) {
+ DEBUG(DEBUG_INFO,
+ ("Ignoring redundant set tcp tickle list, this node hosts '%s'\n",
+ ctdb_addr_to_str(&list->addr)));
+ return 0;
+ }
+
/* remove any old ticklelist we might have */
talloc_free(vnn->tcp_array);
vnn->tcp_array = NULL;