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 {
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;
ret = ctdb_ctrl_get_public_ips_flags(ctdb,
TAKEOVER_TIMEOUT(),
j,
- ctdb->nodes,
+ ipalloc_state->known_public_ips,
0,
&ipalloc_state->known_public_ips[j]);
if (ret != 0) {
ret = ctdb_ctrl_get_public_ips_flags(ctdb,
TAKEOVER_TIMEOUT(),
j,
- ctdb->nodes,
+ ipalloc_state->available_public_ips,
CTDB_PUBLIC_IP_FLAGS_ONLY_AVAILABLE,
&ipalloc_state->available_public_ips[j]);
if (ret != 0) {
/* 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 *t;
/* loop over all ip's and find a physical node to cover for
each unassigned ip.
*/
- for (t = all_ips; t != NULL; t = t->next) {
+ for (t = ipalloc_state->all_ips; t != NULL; t = t->next) {
if (t->pnn == -1) {
- if (find_takeover_node(ipalloc_state,
- t, all_ips)) {
+ if (find_takeover_node(ipalloc_state, t)) {
DEBUG(DEBUG_WARNING,
("Failed to find node to cover ip %s\n",
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;
serving the most and the node serving the least ip's are
not greater than 1.
*/
- for (t = all_ips; t != NULL; t = t->next) {
+ for (t = ipalloc_state->all_ips; t != NULL; t = t->next) {
if (t->pnn == -1) {
continue;
}
continue;
}
- num = node_ip_coverage(i, all_ips);
+ num = node_ip_coverage(i, ipalloc_state->all_ips);
if (maxnode == -1) {
maxnode = i;
maxnum = num;
struct public_ip_list *tt;
/* Reassign one of maxnode's VNNs */
- for (tt = all_ips; tt != NULL; tt = tt->next) {
+ for (tt = ipalloc_state->all_ips; tt != NULL; tt = tt->next) {
if (tt->pnn == maxnode) {
(void)find_takeover_node(ipalloc_state,
- tt,
- 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)
{
}
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 (t = all_ips; t != NULL; t = t->next) {
+ 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 *t;
minip = NULL;
/* loop over each unassigned ip. */
- for (t = all_ips; t != NULL ; t = t->next) {
+ for (t = ipalloc_state->all_ips; t != NULL ; t = t->next) {
if (t->pnn != -1) {
continue;
}
continue;
}
- dstdsum = ip_distance_2_sum(&(t->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",
/* There might be a better way but at least this is clear. */
have_unassigned = false;
- for (t = all_ips; t != NULL; t = t->next) {
+ for (t = ipalloc_state->all_ips; t != NULL; t = t->next) {
if (t->pnn == -1) {
have_unassigned = true;
}
* well optimise.
*/
if (have_unassigned) {
- for (t = all_ips; t != NULL; t = t->next) {
+ 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",
* 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)
DEBUG(DEBUG_DEBUG,(" CONSIDERING MOVES FROM %d [%d]\n",
srcnode, lcp2_imbalances[srcnode]));
- for (t = all_ips; t != NULL; t = t->next) {
+ for (t = ipalloc_state->all_ips; t != NULL; t = t->next) {
/* Only consider addresses on srcnode. */
if (t->pnn != srcnode) {
continue;
}
/* What is this IP address costing the source node? */
- srcdsum = ip_distance_2_sum(&(t->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
continue;
}
- dstdsum = ip_distance_2_sum(&(t->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,
* 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)
{
}
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 *t;
/* verify that the assigned nodes can serve that public ip
and set it to -1 if not
*/
- for (t = all_ips; t != NULL; t = t->next) {
+ for (t = ipalloc_state->all_ips; t != NULL; t = t->next) {
if (t->pnn == -1) {
continue;
}
}
}
-static bool ip_alloc_deterministic_ips(struct ipalloc_state *ipalloc_state,
- struct public_ip_list *all_ips)
+static bool ipalloc_deterministic(struct ipalloc_state *ipalloc_state)
{
struct public_ip_list *t;
int i, numnodes;
* available/unavailable nodes.
*/
- for (i = 0, t = all_ips; t!= NULL; t = t->next, i++) {
+ for (i = 0, t = ipalloc_state->all_ips; t!= NULL; t = t->next, i++) {
t->pnn = i % numnodes;
}
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 ipalloc_nondeterministic(struct ipalloc_state *ipalloc_state)
{
/* This should be pushed down into basic_failback. */
struct public_ip_list *t;
int num_ips = 0;
- for (t = all_ips; t != NULL; t = t->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 ipalloc_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 = ipalloc_lcp2(ipalloc_state);
break;
case IPALLOC_DETERMINISTIC:
- ret = ip_alloc_deterministic_ips(ipalloc_state, all_ips);
+ ret = ipalloc_deterministic(ipalloc_state);
break;
case IPALLOC_NONDETERMINISTIC:
- ret = ip_alloc_nondeterministic_ips(ipalloc_state, all_ips);
+ ret = ipalloc_nondeterministic(ipalloc_state);
break;
}
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