[SCM] CTDB repository - branch 1.2 updated - ctdb-1.9.1-492-g85206ee

Ronnie Sahlberg sahlberg at samba.org
Thu Nov 17 18:54:38 MST 2011


The branch, 1.2 has been updated
       via  85206ee924d8245091264984669abfe99f6e82b9 (commit)
       via  09577a797103c5a91fe816a3b9f385382e1791ca (commit)
       via  d595c57e7602a662055192297817849a15c6128b (commit)
      from  6568feec47b705a39c404bb1a5ff35db265aea6a (commit)

http://gitweb.samba.org/?p=ctdb.git;a=shortlog;h=1.2


- Log -----------------------------------------------------------------
commit 85206ee924d8245091264984669abfe99f6e82b9
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Thu Nov 17 13:34:29 2011 +1100

    Eventscripts: Add special -ECANCELED status for monitor events that are cancelled
    
    When a monitor event is canceled by a higher priority script, make sure we return
    status -ECANCELED to the callback in ctdB_monitor.c
    Also treat -ECANCELED as a simple "try monitor event again" and skip modifying any HEALTHY/UNHEALTHY flags when this happens

commit 09577a797103c5a91fe816a3b9f385382e1791ca
Author: Martin Schwenke <martin at meltin.net>
Date:   Tue Nov 1 20:52:57 2011 +1100

    LCP IP allocation algorithm - try harder to find a candidate source node
    
    There's a bug in LCP2.  Selecting the node with the highest imbalance
    doesn't always work.  Some nodes can have a high imbalance metric
    because they have a lot of IPs.  However, these nodes can be part of a
    group that is perfectly balanced.  Nodes in another group with less
    IPs might actually be imbalanced.
    
    Instead of just trying the source node with the highest imbalance this
    tries them in descending order of imbalance until it finds one where
    an IP can be moved to another node.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>

commit d595c57e7602a662055192297817849a15c6128b
Author: Martin Schwenke <martin at meltin.net>
Date:   Tue Nov 1 19:49:38 2011 +1100

    LCP IP allocation algorithm - new function lcp2_failback_candidate()
    
    There's a bug in LCP2.  Selecting the node with the highest imbalance
    doesn't always work.  Some nodes can have a high imbalance metric
    because they have a lot of IPs.  However, these nodes can be part of a
    group that is perfectly balanced.  Nodes in another group with less
    IPs might actually be imbalanced.
    
    Factor out the code from lcp2_failback() that actually takes a node
    and decides which address should be moved to which node.
    
    This is the first step in fixing the above bug.
    
    Signed-off-by: Martin Schwenke <martin at meltin.net>

-----------------------------------------------------------------------

Summary of changes:
 server/ctdb_monitor.c  |    5 ++
 server/ctdb_takeover.c |  150 +++++++++++++++++++++++++++++++++---------------
 server/eventscript.c   |   10 +++-
 3 files changed, 117 insertions(+), 48 deletions(-)


Changeset truncated at 500 lines:

diff --git a/server/ctdb_monitor.c b/server/ctdb_monitor.c
index f4fbaf4..e897452 100644
--- a/server/ctdb_monitor.c
+++ b/server/ctdb_monitor.c
@@ -124,6 +124,11 @@ static void ctdb_health_callback(struct ctdb_context *ctdb, int status, void *p)
 	rddata.dptr = (uint8_t *)&rd;
 	rddata.dsize = sizeof(rd);
 
+	if (status == -ECANCELED) {
+		DEBUG(DEBUG_ERR,("Monitoring event was cancelled\n"));
+		goto after_change_status;
+	}
+
 	if (status == -ETIME) {
 		ctdb->event_script_timeouts++;
 
diff --git a/server/ctdb_takeover.c b/server/ctdb_takeover.c
index 5865a17..b2e1a8d 100644
--- a/server/ctdb_takeover.c
+++ b/server/ctdb_takeover.c
@@ -1607,57 +1607,26 @@ void lcp2_allocate_unassigned(struct ctdb_context *ctdb,
 	}
 }
 
-/* LCP2 algorithm for rebalancing the cluster.  This finds the source
- * node with the highest LCP2 imbalance, and then determines the best
- * IP/destination node combination to move from the source node.
+/* 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.
  *
  * Not static, so we can easily link it into a unit test.
  */
-bool lcp2_failback(struct ctdb_context *ctdb,
-		   struct ctdb_node_map *nodemap,
-		   uint32_t mask,
-		   struct ctdb_public_ip_list *all_ips,
-		   uint32_t *lcp2_imbalances,
-		   bool *newly_healthy)
-{
-	int srcnode, dstnode, mindstnode, i, num_newly_healthy;
-	uint32_t srcimbl, srcdsum, maximbl, dstimbl, dstdsum;
-	uint32_t minsrcimbl, mindstimbl, b;
+bool lcp2_failback_candidate(struct ctdb_context *ctdb,
+			     struct ctdb_node_map *nodemap,
+			     struct ctdb_public_ip_list *all_ips,
+			     int srcnode,
+			     uint32_t candimbl,
+			     uint32_t *lcp2_imbalances,
+			     bool *newly_healthy)
+{
+	int dstnode, mindstnode;
+	uint32_t srcimbl, srcdsum, dstimbl, dstdsum;
+	uint32_t minsrcimbl, mindstimbl;
 	struct ctdb_public_ip_list *minip;
 	struct ctdb_public_ip_list *tmp_ip;
 
-	/* It is only worth continuing if we have suitable target
-	 * nodes to transfer IPs to.  This check is much cheaper than
-	 * continuing on...
-	 */
-	num_newly_healthy = 0;
-	for (i = 0; i < nodemap->num; i++) {
-		if (newly_healthy[i]) {
-			num_newly_healthy++;
-		}
-	}
-	if (num_newly_healthy == 0) {
-		return false;
-	}
-
-        /* Get the node with the highest imbalance metric. */
-        srcnode = -1;
-        maximbl = 0;
-	for (i=0; i < nodemap->num; i++) {
-		b = lcp2_imbalances[i];
-		if ((srcnode == -1) || (b > maximbl)) {
-			srcnode = i;
-			maximbl = b;
-		}
-	}
-
-        /* This means that all nodes had 0 or 1 addresses, so can't be
-	 * imbalanced.
-	 */
-        if (maximbl == 0) {
-		return false;
-	}
-
 	/* Find an IP and destination node that best reduces imbalance. */
 	minip = NULL;
 	minsrcimbl = 0;
@@ -1665,7 +1634,7 @@ bool lcp2_failback(struct ctdb_context *ctdb,
 	mindstimbl = 0;
 
 	DEBUG(DEBUG_DEBUG,(" ----------------------------------------\n"));
-	DEBUG(DEBUG_DEBUG,(" CONSIDERING MOVES FROM %d [%d]\n", srcnode, maximbl));
+	DEBUG(DEBUG_DEBUG,(" CONSIDERING MOVES FROM %d [%d]\n", srcnode, candimbl));
 
 	for (tmp_ip=all_ips; tmp_ip; tmp_ip=tmp_ip->next) {
 		/* Only consider addresses on srcnode. */
@@ -1675,7 +1644,7 @@ bool lcp2_failback(struct ctdb_context *ctdb,
 
 		/* What is this IP address costing the source node? */
 		srcdsum = ip_distance_2_sum(&(tmp_ip->addr), all_ips, srcnode);
-		srcimbl = maximbl - srcdsum;
+		srcimbl = candimbl - srcdsum;
 
 		/* Consider this IP address would cost each potential
 		 * destination node.  Destination nodes are limited to
@@ -1700,7 +1669,7 @@ bool lcp2_failback(struct ctdb_context *ctdb,
 					   ctdb_addr_to_str(&(tmp_ip->addr)),
 					   dstnode, dstimbl - lcp2_imbalances[dstnode]));
 
-			if ((dstimbl < maximbl) && (dstdsum < srcdsum) && \
+			if ((dstimbl < candimbl) && (dstdsum < srcdsum) && \
 			    ((mindstnode == -1) ||				\
 			     ((srcimbl + dstimbl) < (minsrcimbl + mindstimbl)))) {
 
@@ -1732,6 +1701,93 @@ bool lcp2_failback(struct ctdb_context *ctdb,
 	
 }
 
+struct lcp2_imbalance_pnn {
+	uint32_t imbalance;
+	int pnn;
+};
+
+int lcp2_cmp_imbalance_pnn(const void * a, const void * b)
+{
+	const struct lcp2_imbalance_pnn * lipa = (const struct lcp2_imbalance_pnn *) a;
+	const struct lcp2_imbalance_pnn * lipb = (const struct lcp2_imbalance_pnn *) b;
+
+	if (lipa->imbalance > lipb->imbalance) {
+		return -1;
+	} else if (lipa->imbalance == lipb->imbalance) {
+		return 0;
+	} else {
+		return 1;
+	}
+}
+
+/* LCP2 algorithm for rebalancing the cluster.  This finds the source
+ * node with the highest LCP2 imbalance, and then determines the best
+ * IP/destination node combination to move from the source node.
+ *
+ * Not static, so we can easily link it into a unit test.
+ */
+bool lcp2_failback(struct ctdb_context *ctdb,
+		   struct ctdb_node_map *nodemap,
+		   uint32_t mask,
+		   struct ctdb_public_ip_list *all_ips,
+		   uint32_t *lcp2_imbalances,
+		   bool *newly_healthy)
+{
+	int i, num_newly_healthy;
+	struct lcp2_imbalance_pnn * lips;
+	bool ret;
+
+	/* It is only worth continuing if we have suitable target
+	 * nodes to transfer IPs to.  This check is much cheaper than
+	 * continuing on...
+	 */
+	num_newly_healthy = 0;
+	for (i = 0; i < nodemap->num; i++) {
+		if (newly_healthy[i]) {
+			num_newly_healthy++;
+		}
+	}
+	if (num_newly_healthy == 0) {
+		return false;
+	}
+
+	/* Put the imbalances and nodes into an array, sort them and
+	 * iterate through candidates.  Usually the 1st one will be
+	 * used, so this doesn't cost much...
+	 */
+	lips = talloc_array(ctdb, struct lcp2_imbalance_pnn, nodemap->num);
+	for (i = 0; i < nodemap->num; i++) {
+		lips[i].imbalance = lcp2_imbalances[i];
+		lips[i].pnn = i;
+	}
+	qsort(lips, nodemap->num, sizeof(struct lcp2_imbalance_pnn),
+	      lcp2_cmp_imbalance_pnn);
+
+	ret = false;
+	for (i = 0; i < nodemap->num; i++) {
+		/* This means that all nodes had 0 or 1 addresses, so
+		 * can't be imbalanced.
+		 */
+		if (lips[i].imbalance == 0) {
+			break;
+		}
+
+		if (lcp2_failback_candidate(ctdb,
+					    nodemap,
+					    all_ips,
+					    lips[i].pnn,
+					    lips[i].imbalance,
+					    lcp2_imbalances,
+					    newly_healthy)) {
+			ret = true;
+			break;
+		}
+	}
+
+	talloc_free(lips);
+	return ret;
+}
+
 /* The calculation part of the IP allocation algorithm.
  * Not static, so we can easily link it into a unit test.
  */
diff --git a/server/eventscript.c b/server/eventscript.c
index eb5c2da..17cc3d4 100644
--- a/server/eventscript.c
+++ b/server/eventscript.c
@@ -58,7 +58,7 @@ struct ctdb_event_script_state {
 	enum ctdb_eventscript_call call;
 	const char *options;
 	struct timeval timeout;
-
+	
 	unsigned int current;
 	struct ctdb_scripts_wire *scripts;
 };
@@ -742,6 +742,14 @@ static int ctdb_event_script_callback_v(struct ctdb_context *ctdb,
 
 	/* Kill off any running monitor events to run this event. */
 	if (ctdb->current_monitor) {
+		struct ctdb_event_script_state *ms = talloc_get_type(ctdb->current_monitor, struct ctdb_event_script_state);
+
+		/* cancel it */
+		if (ms->callback != NULL) {
+			ms->callback->fn(ctdb, -ECANCELED, ms->callback->private_data);
+			talloc_free(ms->callback);
+		}
+
 		/* Discard script status so we don't save to last_status */
 		talloc_free(ctdb->current_monitor->scripts);
 		ctdb->current_monitor->scripts = NULL;


-- 
CTDB repository


More information about the samba-cvs mailing list