[SCM] CTDB repository - branch master updated - 8734bd32809ad817ad28d96315a139674429c395

Ronnie Sahlberg sahlberg at samba.org
Fri Jun 13 04:14:31 GMT 2008


The branch, master has been updated
       via  8734bd32809ad817ad28d96315a139674429c395 (commit)
       via  de8f1bedc56da05c03cfd0e4780839771d94a58f (commit)
       via  b4e6d8e37c7f985f357af82b4a524959bb97ec4c (commit)
       via  7239d7ecd54037b11eddf47328a3129d281e7d4a (commit)
       via  dbe31581abf35fc4a32d3cbf487dd34e2b9c937a (commit)
       via  3a69fad0b1dee4a482461680c556358409e53c4d (commit)
       via  72f89bac13cbe8c3ca3e7a942469cd2ff25abba2 (commit)
       via  5444ebd0815e335a75ef4857546e23f490a22338 (commit)
      from  b87fab857bc9b3537527be93b7f68484502d6b84 (commit)

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


- Log -----------------------------------------------------------------
commit 8734bd32809ad817ad28d96315a139674429c395
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Fri Jun 13 13:53:05 2008 +1000

    it is 2008   not 2008 right now :-)

commit de8f1bedc56da05c03cfd0e4780839771d94a58f
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Fri Jun 13 13:50:28 2008 +1000

    update to 1.0.42

commit b4e6d8e37c7f985f357af82b4a524959bb97ec4c
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Fri Jun 13 13:45:23 2008 +1000

    ban the node after 3 failed scripts by default

commit 7239d7ecd54037b11eddf47328a3129d281e7d4a
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Fri Jun 13 13:18:06 2008 +1000

    if the event scripts hangs EventScriptsBanCount consecutive times in a row
    the node will ban itself for the default recovery ban period

commit dbe31581abf35fc4a32d3cbf487dd34e2b9c937a
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Fri Jun 13 12:18:00 2008 +1000

    when a eventscript has timed out, log the event options (i.e. "monitor" "takeip 1.2..." etc)
    to the log

commit 3a69fad0b1dee4a482461680c556358409e53c4d
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Fri Jun 13 11:47:42 2008 +1000

    make it possible to re-start a recovery without marking the current node as
    the culprit.

commit 72f89bac13cbe8c3ca3e7a942469cd2ff25abba2
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Thu Jun 12 16:53:36 2008 +1000

    add a callback for failed nodes to the async control helper.
    
    this callback is called for every node where the control failed (or timed out)
    
    when we issue the start recovery control from recovery master,
    set any node that fails as a culprit   so it will eventually be banned

commit 5444ebd0815e335a75ef4857546e23f490a22338
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Wed Jun 4 17:12:57 2008 +1000

    first cut to convert takeover_callback_state{}
    to use ctdb_sock_addr instead of sockaddr_in

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

Summary of changes:
 client/ctdb_client.c    |   17 +++++-
 common/ctdb_util.c      |   25 ++++++++-
 include/ctdb_private.h  |   14 ++++-
 packaging/RPM/ctdb.spec |    6 ++-
 server/ctdb_recoverd.c  |  144 +++++++++++++++++++++++++++++++----------------
 server/ctdb_takeover.c  |   65 ++++++++++-----------
 server/ctdb_tunables.c  |    1 +
 server/eventscript.c    |   61 +++++++++++++++-----
 tools/ctdb.c            |   11 ++--
 9 files changed, 234 insertions(+), 110 deletions(-)


Changeset truncated at 500 lines:

diff --git a/client/ctdb_client.c b/client/ctdb_client.c
index fd9003d..97fae50 100644
--- a/client/ctdb_client.c
+++ b/client/ctdb_client.c
@@ -2688,6 +2688,10 @@ static void async_callback(struct ctdb_client_control_state *state)
 			DEBUG(DEBUG_ERR,("Async operation failed with state %d\n", state->state));
 		}
 		data->fail_count++;
+		if (data->fail_callback) {
+			data->fail_callback(ctdb, destnode, res, outdata,
+					data->callback_data);
+		}
 		return;
 	}
 	
@@ -2699,9 +2703,14 @@ static void async_callback(struct ctdb_client_control_state *state)
 			DEBUG(DEBUG_ERR,("Async operation failed with ret=%d res=%d\n", ret, (int)res));
 		}
 		data->fail_count++;
+		if (data->fail_callback) {
+			data->fail_callback(ctdb, destnode, res, outdata,
+					data->callback_data);
+		}
 	}
 	if ((ret == 0) && (data->callback != NULL)) {
-		data->callback(ctdb, destnode, res, outdata);
+		data->callback(ctdb, destnode, res, outdata,
+					data->callback_data);
 	}
 }
 
@@ -2746,7 +2755,9 @@ int ctdb_client_async_control(struct ctdb_context *ctdb,
 				struct timeval timeout,
 				bool dont_log_errors,
 				TDB_DATA data,
-			        client_async_callback client_callback)
+				client_async_callback client_callback,
+			        client_async_callback fail_callback,
+				void *callback_data)
 {
 	struct client_async_data *async_data;
 	struct ctdb_client_control_state *state;
@@ -2756,6 +2767,8 @@ int ctdb_client_async_control(struct ctdb_context *ctdb,
 	CTDB_NO_MEMORY_FATAL(ctdb, async_data);
 	async_data->dont_log_errors = dont_log_errors;
 	async_data->callback = client_callback;
+	async_data->fail_callback = fail_callback;
+	async_data->callback_data = callback_data;
 
 	num_nodes = talloc_get_size(nodes) / sizeof(uint32_t);
 
diff --git a/common/ctdb_util.c b/common/ctdb_util.c
index a92a53f..6856c17 100644
--- a/common/ctdb_util.c
+++ b/common/ctdb_util.c
@@ -408,18 +408,39 @@ bool parse_ip_mask(const char *s, struct sockaddr_in *ip, unsigned *mask)
 /*
   compare two sockaddr_in structures - matching only on IP
  */
-bool ctdb_same_ip(const struct sockaddr_in *ip1, const struct sockaddr_in *ip2)
+bool ctdb_same_ipv4(const struct sockaddr_in *ip1, const struct sockaddr_in *ip2)
 {
 	return ip1->sin_family == ip2->sin_family &&
 		ip1->sin_addr.s_addr == ip2->sin_addr.s_addr;
 }
 
+bool ctdb_same_ip(ctdb_sock_addr *ip1, ctdb_sock_addr *ip2)
+{
+	if (ip1->sa.sa_family != ip2->sa.sa_family) {
+		return false;
+	}
+
+	switch (ip1->sa.sa_family) {
+	case AF_INET:
+		return ip1->ip.sin_addr.s_addr == ip2->ip.sin_addr.s_addr;
+	case AF_INET6:
+		return !memcmp(&ip1->ip6.sin6_addr.s6_addr[0],
+				&ip2->ip6.sin6_addr.s6_addr[0],
+				16);
+	default:
+		DEBUG(DEBUG_ERR, (__location__ " CRITICAL Can not compare sockaddr structures of type %u\n", ip1->sa.sa_family));
+		return false;
+	}
+
+	return true;
+}
+
 /*
   compare two sockaddr_in structures
  */
 bool ctdb_same_sockaddr(const struct sockaddr_in *ip1, const struct sockaddr_in *ip2)
 {
-	return ctdb_same_ip(ip1, ip2) && ip1->sin_port == ip2->sin_port;
+	return ctdb_same_ipv4(ip1, ip2) && ip1->sin_port == ip2->sin_port;
 }
 
 
diff --git a/include/ctdb_private.h b/include/ctdb_private.h
index 8127fd1..b19012f 100644
--- a/include/ctdb_private.h
+++ b/include/ctdb_private.h
@@ -52,6 +52,7 @@ struct rd_memdump_reply {
 typedef struct sockaddr_in ctdb_addr_in;
 typedef struct sockaddr_in6 ctdb_addr_in6;
 typedef union {
+	struct sockaddr sa;
 	ctdb_addr_in	ip;
 	ctdb_addr_in6	ip6;
 } ctdb_sock_addr;
@@ -101,6 +102,7 @@ struct ctdb_tunable {
 	uint32_t monitor_interval;
 	uint32_t tickle_update_interval;
 	uint32_t script_timeout;
+	uint32_t script_ban_count; /* ban after this many consec timeouts*/
 	uint32_t recovery_grace_period;
 	uint32_t recovery_ban_period;
 	uint32_t database_hash_size;
@@ -409,6 +411,7 @@ struct ctdb_context {
 	struct ctdb_monitor_state *monitor;
 	struct ctdb_log_state *log;
 	int start_as_disabled;
+	uint32_t event_script_timeouts; /* counting how many consecutive times an eventscript has timedout */
 	TALLOC_CTX *eventscripts_ctx; /* a context to hold data for the RUN_EVENTSCRIPTS control */
 };
 
@@ -786,7 +789,8 @@ bool parse_ip_mask(const char *s, struct sockaddr_in *ip, unsigned *mask);
 int ctdb_parse_address(struct ctdb_context *ctdb,
 		       TALLOC_CTX *mem_ctx, const char *str,
 		       struct ctdb_address *address);
-bool ctdb_same_ip(const struct sockaddr_in *ip1, const struct sockaddr_in *ip2);
+bool ctdb_same_ipv4(const struct sockaddr_in *ip1, const struct sockaddr_in *ip2);
+bool ctdb_same_ip(ctdb_sock_addr *ip1, ctdb_sock_addr *ip2);
 bool ctdb_same_sockaddr(const struct sockaddr_in *ip1, const struct sockaddr_in *ip2);
 uint32_t ctdb_hash(const TDB_DATA *key);
 uint32_t ctdb_hash_string(const char *str);
@@ -1306,13 +1310,15 @@ int32_t ctdb_monitoring_mode(struct ctdb_context *ctdb);
 int ctdb_set_child_logging(struct ctdb_context *ctdb);
 
 
-typedef void (*client_async_callback)(struct ctdb_context *ctdb, uint32_t node_pnn, int32_t res, TDB_DATA outdata);
+typedef void (*client_async_callback)(struct ctdb_context *ctdb, uint32_t node_pnn, int32_t res, TDB_DATA outdata, void *callback_data);
 
 struct client_async_data {
 	bool dont_log_errors;
 	uint32_t count;
 	uint32_t fail_count;
 	client_async_callback callback;
+	client_async_callback fail_callback;
+	void *callback_data;
 };
 void ctdb_client_async_add(struct client_async_data *data, struct ctdb_client_control_state *state);
 int ctdb_client_async_wait(struct ctdb_context *ctdb, struct client_async_data *data);
@@ -1322,7 +1328,9 @@ int ctdb_client_async_control(struct ctdb_context *ctdb,
 				struct timeval timeout,
 				bool dont_log_errors,
 				TDB_DATA data,
-			        client_async_callback client_callback);
+			      	client_async_callback client_callback,
+			        client_async_callback fail_callback,
+				void *callback_data);
 
 void ctdb_load_nodes_file(struct ctdb_context *ctdb);
 
diff --git a/packaging/RPM/ctdb.spec b/packaging/RPM/ctdb.spec
index fc1457d..023f3d8 100644
--- a/packaging/RPM/ctdb.spec
+++ b/packaging/RPM/ctdb.spec
@@ -5,7 +5,7 @@ Vendor: Samba Team
 Packager: Samba Team <samba at samba.org>
 Name: ctdb
 Version: 1.0
-Release: 41
+Release: 42
 Epoch: 0
 License: GNU GPL version 3
 Group: System Environment/Daemons
@@ -120,6 +120,10 @@ fi
 %{_includedir}/ctdb_private.h
 
 %changelog
+* Fri Jun 13 2008 : Version 1.0.42
+ - When event scripts have hung/timedout more than EventScriptBanCount times
+   in a row the node will ban itself.
+ - Many updates to persistent write tests and the test scripts.
 * Wed May 28 2008 : Version 1.0.41
  - Reactivate the safe writes to persistent databases and solve the
    locking issues. Locking issues are solved the only possible way,
diff --git a/server/ctdb_recoverd.c b/server/ctdb_recoverd.c
index 30b121c..affd139 100644
--- a/server/ctdb_recoverd.c
+++ b/server/ctdb_recoverd.c
@@ -206,13 +206,17 @@ enum monitor_result { MONITOR_OK, MONITOR_RECOVERY_NEEDED, MONITOR_ELECTION_NEED
 static int run_recovered_eventscript(struct ctdb_context *ctdb, struct ctdb_node_map *nodemap, const char *caller)
 {
 	TALLOC_CTX *tmp_ctx;
+	uint32_t *nodes;
 
 	tmp_ctx = talloc_new(ctdb);
 	CTDB_NO_MEMORY(ctdb, tmp_ctx);
 
+	nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
 	if (ctdb_client_async_control(ctdb, CTDB_CONTROL_END_RECOVERY,
-			list_of_active_nodes(ctdb, nodemap, tmp_ctx, true),
-			CONTROL_TIMEOUT(), false, tdb_null, NULL) != 0) {
+					nodes,
+					CONTROL_TIMEOUT(), false, tdb_null,
+					NULL, NULL,
+					NULL) != 0) {
 		DEBUG(DEBUG_ERR, (__location__ " Unable to run the 'recovered' event when called from %s\n", caller));
 
 		talloc_free(tmp_ctx);
@@ -224,18 +228,55 @@ static int run_recovered_eventscript(struct ctdb_context *ctdb, struct ctdb_node
 }
 
 /*
+  remember the trouble maker
+ */
+static void ctdb_set_culprit(struct ctdb_recoverd *rec, uint32_t culprit)
+{
+	struct ctdb_context *ctdb = rec->ctdb;
+
+	if (rec->last_culprit != culprit ||
+	    timeval_elapsed(&rec->first_recover_time) > ctdb->tunable.recovery_grace_period) {
+		DEBUG(DEBUG_NOTICE,("New recovery culprit %u\n", culprit));
+		/* either a new node is the culprit, or we've decided to forgive them */
+		rec->last_culprit = culprit;
+		rec->first_recover_time = timeval_current();
+		rec->culprit_counter = 0;
+	}
+	rec->culprit_counter++;
+}
+
+
+/* this callback is called for every node that failed to execute the
+   start recovery event
+*/
+static void startrecovery_fail_callback(struct ctdb_context *ctdb, uint32_t node_pnn, int32_t res, TDB_DATA outdata, void *callback_data)
+{
+	struct ctdb_recoverd *rec = talloc_get_type(callback_data, struct ctdb_recoverd);
+
+	DEBUG(DEBUG_ERR, (__location__ " Node %u failed the startrecovery event. Setting it as recovery fail culprit\n", node_pnn));
+
+	ctdb_set_culprit(rec, node_pnn);
+}
+
+/*
   run the "startrecovery" eventscript on all nodes
  */
-static int run_startrecovery_eventscript(struct ctdb_context *ctdb, struct ctdb_node_map *nodemap)
+static int run_startrecovery_eventscript(struct ctdb_recoverd *rec, struct ctdb_node_map *nodemap)
 {
 	TALLOC_CTX *tmp_ctx;
+	uint32_t *nodes;
+	struct ctdb_context *ctdb = rec->ctdb;
 
 	tmp_ctx = talloc_new(ctdb);
 	CTDB_NO_MEMORY(ctdb, tmp_ctx);
 
+	nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
 	if (ctdb_client_async_control(ctdb, CTDB_CONTROL_START_RECOVERY,
-			list_of_active_nodes(ctdb, nodemap, tmp_ctx, true),
-			CONTROL_TIMEOUT(), false, tdb_null, NULL) != 0) {
+					nodes,
+					CONTROL_TIMEOUT(), false, tdb_null,
+					NULL,
+					startrecovery_fail_callback,
+					rec) != 0) {
 		DEBUG(DEBUG_ERR, (__location__ " Unable to run the 'startrecovery' event. Recovery failed.\n"));
 		talloc_free(tmp_ctx);
 		return -1;
@@ -245,11 +286,10 @@ static int run_startrecovery_eventscript(struct ctdb_context *ctdb, struct ctdb_
 	return 0;
 }
 
-static void async_getcap_callback(struct ctdb_context *ctdb, uint32_t node_pnn, int32_t res, TDB_DATA outdata)
+static void async_getcap_callback(struct ctdb_context *ctdb, uint32_t node_pnn, int32_t res, TDB_DATA outdata, void *callback_data)
 {
 	if ( (outdata.dsize != sizeof(uint32_t)) || (outdata.dptr == NULL) ) {
-		DEBUG(DEBUG_ERR, (__location__ " Invalid lenght/pointer for getcap callback : %u %p\n", 
-				  (unsigned)outdata.dsize, outdata.dptr));
+		DEBUG(DEBUG_ERR, (__location__ " Invalid lenght/pointer for getcap callback : %u %p\n",  (unsigned)outdata.dsize, outdata.dptr));
 		return;
 	}
 	ctdb->nodes[node_pnn]->capabilities = *((uint32_t *)outdata.dptr);
@@ -267,10 +307,11 @@ static int update_capabilities(struct ctdb_context *ctdb, struct ctdb_node_map *
 	CTDB_NO_MEMORY(ctdb, tmp_ctx);
 
 	nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
-
 	if (ctdb_client_async_control(ctdb, CTDB_CONTROL_GET_CAPABILITIES,
 					nodes, CONTROL_TIMEOUT(),
-					false, tdb_null, async_getcap_callback) != 0) {
+					false, tdb_null,
+					async_getcap_callback, NULL,
+					NULL) != 0) {
 		DEBUG(DEBUG_ERR, (__location__ " Failed to read node capabilities.\n"));
 		talloc_free(tmp_ctx);
 		return -1;
@@ -292,13 +333,14 @@ static int set_recovery_mode(struct ctdb_context *ctdb, struct ctdb_node_map *no
 	tmp_ctx = talloc_new(ctdb);
 	CTDB_NO_MEMORY(ctdb, tmp_ctx);
 
-	nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
-
 	/* freeze all nodes */
+	nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
 	if (rec_mode == CTDB_RECOVERY_ACTIVE) {
 		if (ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
 						nodes, CONTROL_TIMEOUT(),
-						false, tdb_null, NULL) != 0) {
+						false, tdb_null,
+						NULL, NULL,
+						NULL) != 0) {
 			DEBUG(DEBUG_ERR, (__location__ " Unable to freeze nodes. Recovery failed.\n"));
 			talloc_free(tmp_ctx);
 			return -1;
@@ -311,7 +353,9 @@ static int set_recovery_mode(struct ctdb_context *ctdb, struct ctdb_node_map *no
 
 	if (ctdb_client_async_control(ctdb, CTDB_CONTROL_SET_RECMODE,
 					nodes, CONTROL_TIMEOUT(),
-					false, data, NULL) != 0) {
+					false, data,
+					NULL, NULL,
+					NULL) != 0) {
 		DEBUG(DEBUG_ERR, (__location__ " Unable to set recovery mode. Recovery failed.\n"));
 		talloc_free(tmp_ctx);
 		return -1;
@@ -320,7 +364,9 @@ static int set_recovery_mode(struct ctdb_context *ctdb, struct ctdb_node_map *no
 	if (rec_mode == CTDB_RECOVERY_NORMAL) {
 		if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
 						nodes, CONTROL_TIMEOUT(),
-						false, tdb_null, NULL) != 0) {
+						false, tdb_null,
+						NULL, NULL,
+						NULL) != 0) {
 			DEBUG(DEBUG_ERR, (__location__ " Unable to thaw nodes. Recovery failed.\n"));
 			talloc_free(tmp_ctx);
 			return -1;
@@ -338,6 +384,7 @@ static int set_recovery_master(struct ctdb_context *ctdb, struct ctdb_node_map *
 {
 	TDB_DATA data;
 	TALLOC_CTX *tmp_ctx;
+	uint32_t *nodes;
 
 	tmp_ctx = talloc_new(ctdb);
 	CTDB_NO_MEMORY(ctdb, tmp_ctx);
@@ -345,9 +392,12 @@ static int set_recovery_master(struct ctdb_context *ctdb, struct ctdb_node_map *
 	data.dsize = sizeof(uint32_t);
 	data.dptr = (unsigned char *)&pnn;
 
+	nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
 	if (ctdb_client_async_control(ctdb, CTDB_CONTROL_SET_RECMASTER,
-			list_of_active_nodes(ctdb, nodemap, tmp_ctx, true),
-			CONTROL_TIMEOUT(), false, data, NULL) != 0) {
+					nodes,
+					CONTROL_TIMEOUT(), false, data,
+					NULL, NULL,
+					NULL) != 0) {
 		DEBUG(DEBUG_ERR, (__location__ " Unable to set recmaster. Recovery failed.\n"));
 		talloc_free(tmp_ctx);
 		return -1;
@@ -944,24 +994,6 @@ static void ctdb_wait_election(struct ctdb_recoverd *rec)
 }
 
 /*
-  remember the trouble maker
- */
-static void ctdb_set_culprit(struct ctdb_recoverd *rec, uint32_t culprit)
-{
-	struct ctdb_context *ctdb = rec->ctdb;
-
-	if (rec->last_culprit != culprit ||
-	    timeval_elapsed(&rec->first_recover_time) > ctdb->tunable.recovery_grace_period) {
-		DEBUG(DEBUG_NOTICE,("New recovery culprit %u\n", culprit));
-		/* either a new node is the culprit, or we've decided to forgive them */
-		rec->last_culprit = culprit;
-		rec->first_recover_time = timeval_current();
-		rec->culprit_counter = 0;
-	}
-	rec->culprit_counter++;
-}
-
-/*
   Update our local flags from all remote connected nodes. 
   This is only run when we are or we belive we are the recovery master
  */
@@ -1143,6 +1175,7 @@ static int push_recdb_database(struct ctdb_context *ctdb, uint32_t dbid,
 	struct ctdb_control_pulldb_reply *recdata;
 	TDB_DATA outdata;
 	TALLOC_CTX *tmp_ctx;
+	uint32_t *nodes;
 
 	tmp_ctx = talloc_new(ctdb);
 	CTDB_NO_MEMORY(ctdb, tmp_ctx);
@@ -1176,9 +1209,12 @@ static int push_recdb_database(struct ctdb_context *ctdb, uint32_t dbid,
 	outdata.dptr = (void *)recdata;
 	outdata.dsize = params.len;
 
+	nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
 	if (ctdb_client_async_control(ctdb, CTDB_CONTROL_PUSH_DB,
-			list_of_active_nodes(ctdb, nodemap, tmp_ctx, true),
-			CONTROL_TIMEOUT(), false, outdata, NULL) != 0) {
+					nodes,
+					CONTROL_TIMEOUT(), false, outdata,
+					NULL, NULL,
+					NULL) != 0) {
 		DEBUG(DEBUG_ERR,(__location__ " Failed to push recdb records to nodes for db 0x%x\n", dbid));
 		talloc_free(recdata);
 		talloc_free(tmp_ctx);
@@ -1210,6 +1246,7 @@ static int recover_database(struct ctdb_recoverd *rec,
 	struct ctdb_context *ctdb = rec->ctdb;
 	TDB_DATA data;
 	struct ctdb_control_wipe_database w;
+	uint32_t *nodes;
 
 	recdb = create_recdb(ctdb, mem_ctx);
 	if (recdb == NULL) {
@@ -1232,9 +1269,12 @@ static int recover_database(struct ctdb_recoverd *rec,
 	data.dptr = (void *)&w;
 	data.dsize = sizeof(w);
 
+	nodes = list_of_active_nodes(ctdb, nodemap, recdb, true);
 	if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
-			list_of_active_nodes(ctdb, nodemap, recdb, true),
-			CONTROL_TIMEOUT(), false, data, NULL) != 0) {
+					nodes,
+					CONTROL_TIMEOUT(), false, data,
+					NULL, NULL,
+					NULL) != 0) {
 		DEBUG(DEBUG_ERR, (__location__ " Unable to wipe database. Recovery failed.\n"));
 		talloc_free(recdb);
 		return -1;
@@ -1261,20 +1301,23 @@ static int recover_database(struct ctdb_recoverd *rec,
 static int do_recovery(struct ctdb_recoverd *rec, 
 		       TALLOC_CTX *mem_ctx, uint32_t pnn,
 		       struct ctdb_node_map *nodemap, struct ctdb_vnn_map *vnnmap,
-		       uint32_t culprit)
+		       int32_t culprit)
 {
 	struct ctdb_context *ctdb = rec->ctdb;
 	int i, j, ret;
 	uint32_t generation;
 	struct ctdb_dbid_map *dbmap;
 	TDB_DATA data;
+	uint32_t *nodes;
 
 	DEBUG(DEBUG_NOTICE, (__location__ " Starting do_recovery\n"));
 
 	/* if recovery fails, force it again */
 	rec->need_recovery = true;
 
-	ctdb_set_culprit(rec, culprit);
+	if (culprit != -1) {
+		ctdb_set_culprit(rec, culprit);
+	}
 
 	if (rec->culprit_counter > 2*nodemap->num) {
 		DEBUG(DEBUG_NOTICE,("Node %u has caused %u recoveries in %.0f seconds - banning it for %u seconds\n",
@@ -1326,7 +1369,7 @@ static int do_recovery(struct ctdb_recoverd *rec,
 	}
 
 	/* execute the "startrecovery" event script on all nodes */
-	ret = run_startrecovery_eventscript(ctdb, nodemap);
+	ret = run_startrecovery_eventscript(rec, nodemap);
 	if (ret!=0) {
 		DEBUG(DEBUG_ERR, (__location__ " Unable to run the 'startrecovery' event on cluster\n"));
 		return -1;
@@ -1355,9 +1398,12 @@ static int do_recovery(struct ctdb_recoverd *rec,
 	data.dptr = (void *)&generation;
 	data.dsize = sizeof(uint32_t);
 
+	nodes = list_of_active_nodes(ctdb, nodemap, mem_ctx, true);
 	if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
-			list_of_active_nodes(ctdb, nodemap, mem_ctx, true),
-			CONTROL_TIMEOUT(), false, data, NULL) != 0) {
+					nodes,
+					CONTROL_TIMEOUT(), false, data,
+					NULL, NULL,
+					NULL) != 0) {
 		DEBUG(DEBUG_ERR, (__location__ " Unable to start transactions. Recovery failed.\n"));
 		return -1;
 	}
@@ -1375,8 +1421,10 @@ static int do_recovery(struct ctdb_recoverd *rec,
 
 	/* commit all the changes */
 	if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
-			list_of_active_nodes(ctdb, nodemap, mem_ctx, true),
-			CONTROL_TIMEOUT(), false, data, NULL) != 0) {
+					nodes,
+					CONTROL_TIMEOUT(), false, data,
+					NULL, NULL,
+					NULL) != 0) {
 		DEBUG(DEBUG_ERR, (__location__ " Unable to commit recovery changes. Recovery failed.\n"));
 		return -1;
 	}
@@ -2555,7 +2603,7 @@ again:
 
 	if (rec->need_recovery) {
 		/* a previous recovery didn't finish */
-		do_recovery(rec, mem_ctx, pnn, nodemap, vnnmap, ctdb->pnn);


-- 
CTDB repository


More information about the samba-cvs mailing list