Пример #1
0
/* search the node lists list for a node to takeover this ip.
   pick the node that currently are serving the least number of ips
   so that the ips get spread out evenly.
*/
int find_takeover_node(struct ipalloc_state *ipalloc_state,
		       struct public_ip_list *ip)
{
	int pnn, min=0, num;
	int i, numnodes;

	numnodes = ipalloc_state->num;
	pnn    = -1;
	for (i=0; i<numnodes; i++) {
		/* verify that this node can serve this ip */
		if (!can_node_takeover_ip(ipalloc_state, i, ip)) {
			/* no it couldnt   so skip to the next node */
			continue;
		}

		num = node_ip_coverage(i, ipalloc_state->all_ips);
		/* was this the first node we checked ? */
		if (pnn == -1) {
			pnn = i;
			min  = num;
		} else {
			if (num < min) {
				pnn = i;
				min  = num;
			}
		}
	}
	if (pnn == -1) {
		DEBUG(DEBUG_WARNING,(__location__ " Could not find node to take over public address '%s'\n",
				     ctdb_sock_addr_to_string(ipalloc_state,
							      &ip->addr)));

		return -1;
	}

	ip->pnn = pnn;
	return 0;
}
Пример #2
0
/* LCP2 algorithm for rebalancing the cluster.  Given a candidate node
 * to move IPs from, determines the best IP/destination node
 * combination to move from the source node.
 */
static bool lcp2_failback_candidate(struct ipalloc_state *ipalloc_state,
				    int srcnode,
				    uint32_t *lcp2_imbalances,
				    bool *rebalance_candidates)
{
	int dstnode, mindstnode, numnodes;
	uint32_t srcimbl, srcdsum, dstimbl, dstdsum;
	uint32_t minsrcimbl, mindstimbl;
	struct public_ip_list *minip;
	struct public_ip_list *t;

	/* Find an IP and destination node that best reduces imbalance. */
	srcimbl = 0;
	minip = NULL;
	minsrcimbl = 0;
	mindstnode = -1;
	mindstimbl = 0;

	numnodes = ipalloc_state->num;

	DEBUG(DEBUG_DEBUG,(" ----------------------------------------\n"));
	DEBUG(DEBUG_DEBUG,(" CONSIDERING MOVES FROM %d [%d]\n",
			   srcnode, lcp2_imbalances[srcnode]));

	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),
					    ipalloc_state->all_ips,
					    srcnode);
		srcimbl = lcp2_imbalances[srcnode] - srcdsum;

		/* Consider this IP address would cost each potential
		 * destination node.  Destination nodes are limited to
		 * those that are newly healthy, since we don't want
		 * to do gratuitous failover of IPs just to make minor
		 * balance improvements.
		 */
		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,
						  t)) {
				/* no it couldnt   so skip to the next node */
				continue;
			}

			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_sock_addr_to_string(
						   ipalloc_state, &(t->addr)),
					   dstnode, dstdsum));

			if ((dstimbl < lcp2_imbalances[srcnode]) &&
			    (dstdsum < srcdsum) &&			\
			    ((mindstnode == -1) ||				\
			     ((srcimbl + dstimbl) < (minsrcimbl + mindstimbl)))) {

				minip = t;
				minsrcimbl = srcimbl;
				mindstnode = dstnode;
				mindstimbl = dstimbl;
			}
		}
	}
	DEBUG(DEBUG_DEBUG,(" ----------------------------------------\n"));

        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_sock_addr_to_string(ipalloc_state, &(minip->addr)),
		       mindstnode, mindstimbl - lcp2_imbalances[mindstnode]));


		lcp2_imbalances[srcnode] = minsrcimbl;
		lcp2_imbalances[mindstnode] = mindstimbl;
		minip->pnn = mindstnode;

		return true;
	}

        return false;
}
Пример #3
0
/* Allocate any unassigned addresses using the LCP2 algorithm to find
 * the IP/node combination that will cost the least.
 */
static void lcp2_allocate_unassigned(struct ipalloc_state *ipalloc_state,
				     uint32_t *lcp2_imbalances)
{
	struct public_ip_list *t;
	int dstnode, numnodes;

	int minnode;
	uint32_t mindsum, dstdsum, dstimbl;
	uint32_t minimbl = 0;
	struct public_ip_list *minip;

	bool should_loop = true;
	bool have_unassigned = true;

	numnodes = ipalloc_state->num;

	while (have_unassigned && should_loop) {
		should_loop = false;

		DEBUG(DEBUG_DEBUG,(" ----------------------------------------\n"));
		DEBUG(DEBUG_DEBUG,(" CONSIDERING MOVES (UNASSIGNED)\n"));

		minnode = -1;
		mindsum = 0;
		minip = NULL;

		/* loop over each unassigned ip. */
		for (t = ipalloc_state->all_ips; t != NULL ; t = t->next) {
			if (t->pnn != -1) {
				continue;
			}

			for (dstnode = 0; dstnode < numnodes; dstnode++) {
				/* only check nodes that can actually takeover this ip */
				if (!can_node_takeover_ip(ipalloc_state,
							  dstnode,
							  t)) {
					/* no it couldnt   so skip to the next node */
					continue;
				}

				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_sock_addr_to_string(ipalloc_state,
								&(t->addr)),
				       dstnode,
				       dstimbl - lcp2_imbalances[dstnode]));


				if ((minnode == -1) || (dstdsum < mindsum)) {
					minnode = dstnode;
					minimbl = dstimbl;
					mindsum = dstdsum;
					minip = t;
					should_loop = true;
				}
			}
		}

		DEBUG(DEBUG_DEBUG,(" ----------------------------------------\n"));

		/* If we found one then assign it to the given node. */
		if (minnode != -1) {
			minip->pnn = minnode;
			lcp2_imbalances[minnode] = minimbl;
			DEBUG(DEBUG_INFO,(" %s -> %d [+%d]\n",
					  ctdb_sock_addr_to_string(
						  ipalloc_state,
						  &(minip->addr)),
					  minnode,
					  mindsum));
		}

		/* There might be a better way but at least this is clear. */
		have_unassigned = false;
		for (t = ipalloc_state->all_ips; t != NULL; t = t->next) {
			if (t->pnn == -1) {
				have_unassigned = true;
			}
		}
	}

	/* We know if we have an unassigned addresses so we might as
	 * well optimise.
	 */
	if (have_unassigned) {
		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_sock_addr_to_string(ipalloc_state,
								&t->addr)));
			}
		}
	}
}