[SCM] CTDB repository - branch 1.2 updated - ctdb-1.9.1-328-g486ec95

Ronnie Sahlberg sahlberg at samba.org
Thu Feb 24 15:27:09 MST 2011


The branch, 1.2 has been updated
       via  486ec95ae5852979d5f5a67f19e5d126136cc299 (commit)
       via  e4567b85b6f03af9a022681d8a4baac6b92b5198 (commit)
       via  d35f63369d0124ed295de6a7a287b425176f2333 (commit)
       via  8656023f4153a6b5c4bf512c8b8dbd640fd9aa55 (commit)
       via  bbcfb7e468f5b3d0e71e95393675fdb55831aaca (commit)
       via  c74a75eb7b2f2de9da32b9c8d6fa9e3a89abedd7 (commit)
       via  903a0904617cccb852aa07bd4d765e1407a3c883 (commit)
       via  a1cb6cff0f8196ccbba36cd9342cf2e36c5c38a8 (commit)
       via  e82e25abf2ca62e994fd445af86dff851ec8782e (commit)
       via  e7d4571cbf2ec2e571634a5ce8d11b803dd31fe9 (commit)
       via  66add4d45c5fc295e2cdce13aa957e3bf5ba9646 (commit)
       via  1306312e80453a64fd27ad762d5898f00bdd4000 (commit)
       via  922d787a469fbb6cb5108919a9059ce905d217b5 (commit)
       via  39f40257a4b7b3acc7fdec230dc0859c455ccaf5 (commit)
       via  43ca24fa0f449b605ea0d95f82a4f234a378e741 (commit)
      from  5ef6a403bf99f9b805b9a996bd64d406b0cf893f (commit)

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


- Log -----------------------------------------------------------------
commit 486ec95ae5852979d5f5a67f19e5d126136cc299
Author: Michael Adam <obnox at samba.org>
Date:   Mon Feb 21 15:55:16 2011 +1100

    New version 1.2.22.

commit e4567b85b6f03af9a022681d8a4baac6b92b5198
Author: Michael Adam <obnox at samba.org>
Date:   Wed Feb 23 17:39:57 2011 +0100

    recover: finish pending trans3 commits when a recovery is finished.
    
    When the end_recovery control is received, pending trans3 commits are
    finished. During the recovery, all the actions like persistent_callback
    and persistent_store_timeout had been disabled to let the recovery do
    its job. After the recover is completed, send the reply to the waiting
    clients.

commit d35f63369d0124ed295de6a7a287b425176f2333
Author: Michael Adam <obnox at samba.org>
Date:   Wed Feb 23 17:38:40 2011 +0100

    persistent: add ctdb_persistent_finish_trans3_commits().
    
    This function walks all databases and checks for running trans3 commits.
    It sends replies to all of them (with error code) and ends them.
    To be called when a recovery finishes.

commit 8656023f4153a6b5c4bf512c8b8dbd640fd9aa55
Author: Michael Adam <obnox at samba.org>
Date:   Wed Feb 23 17:37:42 2011 +0100

    daemon: correctly end a running trans3_commit if the client disconnects.

commit bbcfb7e468f5b3d0e71e95393675fdb55831aaca
Author: Michael Adam <obnox at samba.org>
Date:   Wed Feb 23 17:35:27 2011 +0100

    persistent: add a client context to the persistent_stat and track the db_id
    
    The db_id is tracked in the client context as an indication that a
    transaction commit is in progress. This is cleared in the persistent_state
    talloc destructor.
    
    This is in order to properly treat running trans3_commits if the client
    disconnects.

commit c74a75eb7b2f2de9da32b9c8d6fa9e3a89abedd7
Author: Michael Adam <obnox at samba.org>
Date:   Wed Feb 23 00:03:07 2011 +0100

    persistent: reject trans3_control when a commit is already active.
    
    This should actually never happen.

commit 903a0904617cccb852aa07bd4d765e1407a3c883
Author: Michael Adam <obnox at samba.org>
Date:   Wed Feb 23 00:01:13 2011 +0100

    persistent: allocate the persistent state in the ctdb_db struct in trans3_commit
    
    Make sure that ctdb_db->persistent_state is correctly NULL-ed when
    the state is freed. This way, we can use ctdb_db->persistent_state
    as an indication for whether a transaction commit is currently
    running.

commit a1cb6cff0f8196ccbba36cd9342cf2e36c5c38a8
Author: Michael Adam <obnox at samba.org>
Date:   Wed Feb 23 00:23:18 2011 +0100

    persistent: add a ctdb_db context to the ctdb_persistent_state struct.

commit e82e25abf2ca62e994fd445af86dff851ec8782e
Author: Michael Adam <obnox at samba.org>
Date:   Wed Feb 23 00:00:04 2011 +0100

    persistent: add a ctdb_persistent_state member to the ctdb_db context.
    
    To be used for tracking running transaction commits through recoveries.

commit e7d4571cbf2ec2e571634a5ce8d11b803dd31fe9
Author: Michael Adam <obnox at samba.org>
Date:   Tue Feb 22 22:49:52 2011 +0100

    persistent_callback: print "no error message given" instead of "(null)"

commit 66add4d45c5fc295e2cdce13aa957e3bf5ba9646
Author: Michael Adam <obnox at samba.org>
Date:   Tue Feb 22 22:47:30 2011 +0100

    persistent: reduce indentation for the finishing moves in ctdb_persistent_callback

commit 1306312e80453a64fd27ad762d5898f00bdd4000
Author: Michael Adam <obnox at samba.org>
Date:   Tue Feb 22 22:44:16 2011 +0100

    persistent: if a node failed to update_record, trigger a recovery
    
    and stop processing of the update_record replies in order to let
    the recovery finish the trans3_commit control.

commit 922d787a469fbb6cb5108919a9059ce905d217b5
Author: Michael Adam <obnox at samba.org>
Date:   Tue Feb 22 22:24:50 2011 +0100

    persistent_store_timout: do not really time out the trans3_commit control in recovery
    
    If a recovery was started, then all further processing of the update_record
    controls sent by the trans3_commit control and timing them out is disabled.
    The recovery should trigger sending the reply for the update record control
    when finished.

commit 39f40257a4b7b3acc7fdec230dc0859c455ccaf5
Author: Michael Adam <obnox at samba.org>
Date:   Tue Feb 22 22:24:50 2011 +0100

    persistent_callback: ignore the update-recordreturn code of remote node in recovery
    
    If a recovery was started, then all further processing of the update_record
    controls sent by the trans3_commit control is disabled. The recovery should
    trigger sending the reply for the update record control when finished.

commit 43ca24fa0f449b605ea0d95f82a4f234a378e741
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Wed Feb 23 15:46:36 2011 +1100

    Deferred attach : at early startup, defer any db attach calls until we are out of recovery.

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

Summary of changes:
 include/ctdb_private.h     |   14 ++++-
 packaging/RPM/ctdb.spec.in |    4 +-
 server/ctdb_control.c      |    4 +-
 server/ctdb_daemon.c       |    9 +++
 server/ctdb_ltdb_server.c  |  106 ++++++++++++++++++++++++++++++----
 server/ctdb_persistent.c   |  137 +++++++++++++++++++++++++++++++++++++------
 server/ctdb_recover.c      |   12 ++++
 server/ctdb_tunables.c     |    3 +-
 8 files changed, 254 insertions(+), 35 deletions(-)


Changeset truncated at 500 lines:

diff --git a/include/ctdb_private.h b/include/ctdb_private.h
index 4dcf9a5..447d40c 100644
--- a/include/ctdb_private.h
+++ b/include/ctdb_private.h
@@ -118,6 +118,7 @@ struct ctdb_tunable {
 	uint32_t use_status_events_for_monitoring;
 	uint32_t allow_unhealthy_db_read;
 	uint32_t stat_history_interval;
+	uint32_t deferred_attach_timeout;
 };
 
 /*
@@ -488,6 +489,9 @@ struct ctdb_context {
 
 	/* used in the recovery daemon to remember the ip allocation */
 	struct trbt_tree *ip_tree;
+
+	/* Used to defer db attach requests while in recovery mode */
+	struct ctdb_deferred_attach_context *deferred_attach;
 };
 
 struct ctdb_db_context {
@@ -509,6 +513,7 @@ struct ctdb_db_context {
 	int pending_requests;
 	struct lockwait_handle *lockwait_active;
 	struct lockwait_handle *lockwait_overflow;
+	struct ctdb_persistent_state *persistent_state;
 };
 
 
@@ -799,7 +804,10 @@ int ctdb_daemon_send_control(struct ctdb_context *ctdb, uint32_t destnode,
 			     void *private_data);
 
 int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata, 
-			       TDB_DATA *outdata, uint64_t tdb_flags, bool persistent);
+			       TDB_DATA *outdata, uint64_t tdb_flags,
+			       bool persistent, uint32_t client_id,
+			       struct ctdb_req_control *c,
+			       bool *async_reply);
 
 int ctdb_daemon_set_call(struct ctdb_context *ctdb, uint32_t db_id,
 			 ctdb_fn_t fn, int id);
@@ -1215,6 +1223,8 @@ int32_t ctdb_control_trans3_commit(struct ctdb_context *ctdb,
 				   struct ctdb_req_control *c,
 				   TDB_DATA recdata, bool *async_reply);
 
+void ctdb_persistent_finish_trans3_commits(struct ctdb_context *ctdb);
+
 int32_t ctdb_control_transaction_start(struct ctdb_context *ctdb, uint32_t id);
 int32_t ctdb_control_transaction_commit(struct ctdb_context *ctdb, uint32_t id);
 int32_t ctdb_control_transaction_cancel(struct ctdb_context *ctdb);
@@ -1362,4 +1372,6 @@ int32_t ctdb_control_get_stat_history(struct ctdb_context *ctdb,
 
 int ctdb_deferred_drop_all_ips(struct ctdb_context *ctdb);
 
+int ctdb_process_deferred_attach(struct ctdb_context *ctdb);
+
 #endif
diff --git a/packaging/RPM/ctdb.spec.in b/packaging/RPM/ctdb.spec.in
index f7a0871..4841844 100644
--- a/packaging/RPM/ctdb.spec.in
+++ b/packaging/RPM/ctdb.spec.in
@@ -3,7 +3,7 @@ Name: ctdb
 Summary: Clustered TDB
 Vendor: Samba Team
 Packager: Samba Team <samba at samba.org>
-Version: 1.2.21
+Version: 1.2.22
 Release: 1GITHASH
 Epoch: 0
 License: GNU GPL version 3
@@ -143,6 +143,8 @@ development libraries for ctdb
 %{_libdir}/libctdb.a
 
 %changelog
+* Wed Feb 23 2011 : Version 1.2.22
+ - Fix transaction errors that especially happened during startup.
 * Mon Feb 21 2011 : Version 1.2.21
  - fix for CQ 1022004
 * Tue Feb 8 2011 : Version 1.2.20
diff --git a/server/ctdb_control.c b/server/ctdb_control.c
index 90900c9..69724e3 100644
--- a/server/ctdb_control.c
+++ b/server/ctdb_control.c
@@ -221,10 +221,10 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
 	}
 
 	case CTDB_CONTROL_DB_ATTACH:
-		return ctdb_control_db_attach(ctdb, indata, outdata, srvid, false);
+	  return ctdb_control_db_attach(ctdb, indata, outdata, srvid, false, client_id, c, async_reply);
 
 	case CTDB_CONTROL_DB_ATTACH_PERSISTENT:
-		return ctdb_control_db_attach(ctdb, indata, outdata, srvid, true);
+	  return ctdb_control_db_attach(ctdb, indata, outdata, srvid, true, client_id, c, async_reply);
 
 	case CTDB_CONTROL_SET_CALL: {
 		struct ctdb_control_set_call *sc = 
diff --git a/server/ctdb_daemon.c b/server/ctdb_daemon.c
index 362f1ce..9c650a0 100644
--- a/server/ctdb_daemon.c
+++ b/server/ctdb_daemon.c
@@ -225,7 +225,16 @@ static int ctdb_client_destructor(struct ctdb_client *client)
 		DEBUG(DEBUG_ERR, (__location__ " client exit while transaction "
 				  "commit active. Forcing recovery.\n"));
 		client->ctdb->recovery_mode = CTDB_RECOVERY_ACTIVE;
+
+		/* legacy trans2 transaction state: */
 		ctdb_db->transaction_active = false;
+
+		/*
+		 * trans3 transaction state:
+		 *
+		 * The destructor sets the pointer to NULL.
+		 */
+		talloc_free(ctdb_db->persistent_state);
 	}
 
 	return 0;
diff --git a/server/ctdb_ltdb_server.c b/server/ctdb_ltdb_server.c
index ba2a9cb..3e90b2d 100644
--- a/server/ctdb_ltdb_server.c
+++ b/server/ctdb_ltdb_server.c
@@ -745,33 +745,117 @@ again:
 }
 
 
+struct ctdb_deferred_attach_context {
+	struct ctdb_deferred_attach_context *next, *prev;
+	struct ctdb_context *ctdb;
+	struct ctdb_req_control *c;
+};
+
+
+static int ctdb_deferred_attach_destructor(struct ctdb_deferred_attach_context *da_ctx)
+{
+	DLIST_REMOVE(da_ctx->ctdb->deferred_attach, da_ctx);
+
+	return 0;
+}
+
+static void ctdb_deferred_attach_timeout(struct event_context *ev, struct timed_event *te, struct timeval t, void *private_data)
+{
+	struct ctdb_deferred_attach_context *da_ctx = talloc_get_type(private_data, struct ctdb_deferred_attach_context);
+	struct ctdb_context *ctdb = da_ctx->ctdb;
+
+	ctdb_request_control_reply(ctdb, da_ctx->c, NULL, -1, NULL);
+	talloc_free(da_ctx);
+}
+
+static void ctdb_deferred_attach_callback(struct event_context *ev, struct timed_event *te, struct timeval t, void *private_data)
+{
+	struct ctdb_deferred_attach_context *da_ctx = talloc_get_type(private_data, struct ctdb_deferred_attach_context);
+	struct ctdb_context *ctdb = da_ctx->ctdb;
+
+	/* This talloc-steals the packet ->c */
+	ctdb_input_pkt(ctdb, (struct ctdb_req_header *)da_ctx->c);
+	talloc_free(da_ctx);
+}
+
+int ctdb_process_deferred_attach(struct ctdb_context *ctdb)
+{
+	struct ctdb_deferred_attach_context *da_ctx;
+
+	/* call it from the main event loop as soon as the current event 
+	   finishes.
+	 */
+	while ((da_ctx = ctdb->deferred_attach) != NULL) {
+		DLIST_REMOVE(ctdb->deferred_attach, da_ctx);
+		event_add_timed(ctdb->ev, ctdb, timeval_current_ofs(1,0), ctdb_deferred_attach_callback, da_ctx);
+	}
+
+	return 0;
+}
+
 /*
   a client has asked to attach a new database
  */
 int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata,
 			       TDB_DATA *outdata, uint64_t tdb_flags, 
-			       bool persistent)
+			       bool persistent, uint32_t client_id,
+			       struct ctdb_req_control *c,
+			       bool *async_reply)
 {
 	const char *db_name = (const char *)indata.dptr;
 	struct ctdb_db_context *db;
 	struct ctdb_node *node = ctdb->nodes[ctdb->pnn];
 
+	/* dont allow any local clients to attach while we are in recovery mode
+	 * except for the recovery daemon.
+	 * allow all attach from the network since these are always from remote
+	 * recovery daemons.
+	 */
+	if (client_id != 0) {
+		struct ctdb_client *client = ctdb_reqid_find(ctdb, client_id, struct ctdb_client);
+
+		if (client == NULL) {
+			DEBUG(DEBUG_ERR,("DB Attach to database %s refused. Can not match clientid:%d to a client structure.\n", db_name, client_id));
+			return -1;
+		}
+
+		/* If the node is inactive it is not part of the cluster
+		   and we should not allow clients to attach to any
+		   databases
+		*/
+		if (node->flags & NODE_FLAGS_INACTIVE) {
+			DEBUG(DEBUG_ERR,("DB Attach to database %s refused since node is inactive (disconnected or banned)\n", db_name));
+			return -1;
+		}
+
+		if (ctdb->recovery_mode == CTDB_RECOVERY_ACTIVE
+		 && client->pid != ctdb->recoverd_pid) {
+			struct ctdb_deferred_attach_context *da_ctx = talloc(client, struct ctdb_deferred_attach_context);
+
+			if (da_ctx == NULL) {
+				DEBUG(DEBUG_ERR,("DB Attach to database %s deferral for client with pid:%d failed due to OOM.\n", db_name, client->pid));
+				return -1;
+			}
+
+			da_ctx->ctdb = ctdb;
+			da_ctx->c = talloc_steal(da_ctx, c);
+			talloc_set_destructor(da_ctx, ctdb_deferred_attach_destructor);
+			DLIST_ADD(ctdb->deferred_attach, da_ctx);
+
+			event_add_timed(ctdb->ev, da_ctx, timeval_current_ofs(ctdb->tunable.deferred_attach_timeout, 0), ctdb_deferred_attach_timeout, da_ctx);
+
+			DEBUG(DEBUG_ERR,("DB Attach to database %s deferred for client with pid:%d since node is in recovery mode.\n", db_name, client->pid));
+			*async_reply = true;
+			return 0;
+		}
+	}
+
 	/* the client can optionally pass additional tdb flags, but we
 	   only allow a subset of those on the database in ctdb. Note
 	   that tdb_flags is passed in via the (otherwise unused)
 	   srvid to the attach control */
 	tdb_flags &= (TDB_NOSYNC|TDB_INCOMPATIBLE_HASH);
 
-	/* If the node is inactive it is not part of the cluster
-	   and we should not allow clients to attach to any
-	   databases
-	*/
-	if (node->flags & NODE_FLAGS_INACTIVE) {
-		DEBUG(DEBUG_ERR,("DB Attach to database %s refused since node is inactive (disconnected or banned)\n", db_name));
-		return -1;
-	}
-
-
 	/* see if we already have this name */
 	db = ctdb_db_handle(ctdb, db_name);
 	if (db) {
diff --git a/server/ctdb_persistent.c b/server/ctdb_persistent.c
index f9a2051..b95f456 100644
--- a/server/ctdb_persistent.c
+++ b/server/ctdb_persistent.c
@@ -28,6 +28,8 @@
 
 struct ctdb_persistent_state {
 	struct ctdb_context *ctdb;
+	struct ctdb_db_context *ctdb_db; /* used by trans3_commit */
+	struct ctdb_client *client; /* used by trans3_commit */
 	struct ctdb_req_control *c;
 	const char *errormsg;
 	uint32_t num_pending;
@@ -52,27 +54,48 @@ static void ctdb_persistent_callback(struct ctdb_context *ctdb,
 {
 	struct ctdb_persistent_state *state = talloc_get_type(private_data, 
 							      struct ctdb_persistent_state);
+	enum ctdb_trans2_commit_error etype;
+
+	if (ctdb->recovery_mode != CTDB_RECOVERY_NORMAL) {
+		DEBUG(DEBUG_INFO, ("ctdb_persistent_callback: ignoring reply "
+				   "during recovery\n"));
+		return;
+	}
 
 	if (status != 0) {
 		DEBUG(DEBUG_ERR,("ctdb_persistent_callback failed with status %d (%s)\n",
-			 status, errormsg));
+			 status, errormsg?errormsg:"no error message given"));
 		state->status = status;
 		state->errormsg = errormsg;
 		state->num_failed++;
+
+		/*
+		 * If a node failed to complete the update_record control,
+		 * then either a recovery is already running or something
+		 * bad is going on. So trigger a recovery and let the
+		 * recovery finish the transaction, sending back the reply
+		 * for the trans3_commit control to the client.
+		 */
+		ctdb->recovery_mode = CTDB_RECOVERY_ACTIVE;
+		return;
 	}
+
 	state->num_pending--;
-	if (state->num_pending == 0) {
-		enum ctdb_trans2_commit_error etype;
-		if (state->num_failed == state->num_sent) {
-			etype = CTDB_TRANS2_COMMIT_ALLFAIL;
-		} else if (state->num_failed != 0) {
-			etype = CTDB_TRANS2_COMMIT_SOMEFAIL;
-		} else {
-			etype = CTDB_TRANS2_COMMIT_SUCCESS;
-		}
-		ctdb_request_control_reply(state->ctdb, state->c, NULL, etype, state->errormsg);
-		talloc_free(state);
+
+	if (state->num_pending != 0) {
+		return;
+	}
+
+	if (state->num_failed == state->num_sent) {
+		etype = CTDB_TRANS2_COMMIT_ALLFAIL;
+	} else if (state->num_failed != 0) {
+		etype = CTDB_TRANS2_COMMIT_SOMEFAIL;
+	} else {
+		etype = CTDB_TRANS2_COMMIT_SUCCESS;
 	}
+
+	ctdb_request_control_reply(state->ctdb, state->c, NULL, etype, state->errormsg);
+	talloc_free(state);
 }
 
 /*
@@ -82,13 +105,53 @@ static void ctdb_persistent_store_timeout(struct event_context *ev, struct timed
 					 struct timeval t, void *private_data)
 {
 	struct ctdb_persistent_state *state = talloc_get_type(private_data, struct ctdb_persistent_state);
-	
+
+	if (state->ctdb->recovery_mode != CTDB_RECOVERY_NORMAL) {
+		DEBUG(DEBUG_INFO, ("ctdb_persistent_store_timeout: ignoring "
+				   "timeout during recovery\n"));
+		return;
+	}
+
 	ctdb_request_control_reply(state->ctdb, state->c, NULL, CTDB_TRANS2_COMMIT_TIMEOUT, 
 				   "timeout in ctdb_persistent_state");
 
 	talloc_free(state);
 }
 
+/**
+ * Finish pending trans3 commit controls, i.e. send
+ * reply to the client. This is called by the end-recovery
+ * control to fix the situation when a recovery interrupts
+ * the usual porgress of a transaction.
+ */
+void ctdb_persistent_finish_trans3_commits(struct ctdb_context *ctdb)
+{
+	struct ctdb_db_context *ctdb_db;
+
+	if (ctdb->recovery_mode != CTDB_RECOVERY_NORMAL) {
+		DEBUG(DEBUG_INFO, ("ctdb_persistent_store_timeout: ignoring "
+				   "timeout during recovery\n"));
+		return;
+	}
+
+	for (ctdb_db = ctdb->db_list; ctdb_db; ctdb_db = ctdb_db->next) {
+		struct ctdb_persistent_state *state;
+
+		if (ctdb_db->persistent_state == NULL) {
+			continue;
+		}
+
+		state = ctdb_db->persistent_state;
+
+		ctdb_request_control_reply(ctdb, state->c, NULL,
+					   CTDB_TRANS2_COMMIT_SOMEFAIL,
+					   "trans3 commit ended by recovery");
+
+		/* The destructor sets ctdb_db->persistent_state to NULL. */
+		talloc_free(state);
+	}
+}
+
 /*
   store a set of persistent records - called from a ctdb client when it has updated
   some records in a persistent database. The client will have the record
@@ -247,6 +310,18 @@ int32_t ctdb_control_trans2_commit(struct ctdb_context *ctdb,
 	return 0;
 }
 
+static int ctdb_persistent_state_destructor(struct ctdb_persistent_state *state)
+{
+	if (state->client != NULL) {
+		state->client->db_id = 0;
+	}
+
+	if (state->ctdb_db != NULL) {
+		state->ctdb_db->persistent_state = NULL;
+	}
+
+	return 0;
+}
 
 /*
  * Store a set of persistent records.
@@ -267,6 +342,21 @@ int32_t ctdb_control_trans3_commit(struct ctdb_context *ctdb,
 		return -1;
 	}
 
+	client = ctdb_reqid_find(ctdb, c->client_id, struct ctdb_client);
+	if (client == NULL) {
+		DEBUG(DEBUG_ERR,(__location__ " can not match persistent_store "
+				 "to a client. Returning error\n"));
+		return -1;
+	}
+
+	if (client->db_id != 0) {
+		DEBUG(DEBUG_ERR,(__location__ " ERROR: trans3_commit: "
+				 "client-db_id[0x%08x] != 0 "
+				 "(client_id[0x%08x]): trans3_commit active?\n",
+				 client->db_id, client->client_id));
+		return -1;
+	}
+
 	ctdb_db = find_ctdb_db(ctdb, m->db_id);
 	if (ctdb_db == NULL) {
 		DEBUG(DEBUG_ERR,(__location__ " ctdb_control_trans3_commit: "
@@ -274,18 +364,27 @@ int32_t ctdb_control_trans3_commit(struct ctdb_context *ctdb,
 		return -1;
 	}
 
-	client = ctdb_reqid_find(ctdb, c->client_id, struct ctdb_client);
-	if (client == NULL) {
-		DEBUG(DEBUG_ERR,(__location__ " can not match persistent_store "
-				 "to a client. Returning error\n"));
+	if (ctdb_db->persistent_state != NULL) {
+		DEBUG(DEBUG_ERR, (__location__ " Error: "
+				  "ctdb_control_trans3_commit "
+				  "called while a transaction commit is "
+				  "active. db_id[0x%08x]\n", m->db_id));
 		return -1;
 	}
 
-	state = talloc_zero(ctdb, struct ctdb_persistent_state);
-	CTDB_NO_MEMORY(ctdb, state);
+	ctdb_db->persistent_state = talloc_zero(ctdb_db,
+						struct ctdb_persistent_state);
+	CTDB_NO_MEMORY(ctdb, ctdb_db->persistent_state);
 
+	client->db_id = m->db_id;
+
+	state = ctdb_db->persistent_state;
 	state->ctdb = ctdb;
+	state->ctdb_db = ctdb_db;
 	state->c    = c;
+	state->client = client;
+
+	talloc_set_destructor(state, ctdb_persistent_state_destructor);
 
 	for (i = 0; i < ctdb->vnn_map->size; i++) {
 		struct ctdb_node *node = ctdb->nodes[ctdb->vnn_map->map[i]];
diff --git a/server/ctdb_recover.c b/server/ctdb_recover.c
index 4db4d97..0cbd7dc 100644
--- a/server/ctdb_recover.c
+++ b/server/ctdb_recover.c
@@ -630,6 +630,11 @@ static void set_recmode_handler(struct event_context *ev, struct fd_event *fde,
 
 	state->ctdb->recovery_mode = state->recmode;
 
+	/* release any deferred attach calls from clients */
+	if (state->recmode == CTDB_RECOVERY_NORMAL) {
+		ctdb_process_deferred_attach(state->ctdb);
+	}
+
 	ctdb_request_control_reply(state->ctdb, state->c, NULL, 0, NULL);
 	talloc_free(state);
 	return;
@@ -716,6 +721,11 @@ int32_t ctdb_control_set_recmode(struct ctdb_context *ctdb,
 	state->fd[0] = -1;
 	state->fd[1] = -1;
 
+	/* release any deferred attach calls from clients */
+	if (recmode == CTDB_RECOVERY_NORMAL) {
+		ctdb_process_deferred_attach(ctdb);
+	}
+
 	if (ctdb->tunable.verify_recovery_lock == 0) {
 		/* dont need to verify the reclock file */
 		ctdb->recovery_mode = recmode;
@@ -988,6 +998,8 @@ int32_t ctdb_control_end_recovery(struct ctdb_context *ctdb,
 
 	DEBUG(DEBUG_NOTICE,("Recovery has finished\n"));
 
+	ctdb_persistent_finish_trans3_commits(ctdb);
+
 	state = talloc(ctdb, struct recovery_callback_state);
 	CTDB_NO_MEMORY(ctdb, state);
 
diff --git a/server/ctdb_tunables.c b/server/ctdb_tunables.c
index 4cd1b45..0f8d7c8 100644
--- a/server/ctdb_tunables.c
+++ b/server/ctdb_tunables.c
@@ -65,7 +65,8 @@ static const struct {
 	{ "MaxQueueDropMsg",  1000000, offsetof(struct ctdb_tunable, max_queue_depth_drop_msg) },
 	{ "UseStatusEvents",     0,  offsetof(struct ctdb_tunable, use_status_events_for_monitoring) },
 	{ "AllowUnhealthyDBRead", 0,  offsetof(struct ctdb_tunable, allow_unhealthy_db_read) },


-- 
CTDB repository


More information about the samba-cvs mailing list