dovecot-2.0: sql pool: Delay creating a transaction until commit...

dovecot at dovecot.org dovecot at dovecot.org
Tue Sep 7 21:50:52 EEST 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/902f008f17cf
changeset: 12084:902f008f17cf
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Sep 07 19:50:48 2010 +0100
description:
sql pool: Delay creating a transaction until commit is called.
Otherwise sql connection is reserved for the duration of the transaction.

diffstat:

 src/lib-sql/driver-sqlpool.c |  89 ++++++++++++++++++--------------------------
 1 files changed, 36 insertions(+), 53 deletions(-)

diffs (176 lines):

diff -r d72b4a74a992 -r 902f008f17cf src/lib-sql/driver-sqlpool.c
--- a/src/lib-sql/driver-sqlpool.c	Tue Sep 07 17:19:40 2010 +0100
+++ b/src/lib-sql/driver-sqlpool.c	Tue Sep 07 19:50:48 2010 +0100
@@ -64,10 +64,8 @@
 	sql_commit_callback_t *callback;
 	void *context;
 
+	pool_t query_pool;
 	struct sqlpool_request *commit_request;
-	struct sql_transaction_context *conn_trans;
-
-	pool_t query_pool;
 };
 
 extern struct sql_db driver_sqlpool_db;
@@ -120,31 +118,30 @@
 	sqlpool_request_free(&request);
 }
 
-static void
+static struct sql_transaction_context *
 driver_sqlpool_new_conn_trans(struct sqlpool_transaction_context *trans,
 			      struct sql_db *conndb)
 {
-	trans->conn_trans = sql_transaction_begin(conndb);
+	struct sql_transaction_context *conn_trans;
+
+	conn_trans = sql_transaction_begin(conndb);
 	/* backend will use our queries list (we might still append more
 	   queries to the list) */
-	trans->conn_trans->head = trans->ctx.head;
-	trans->conn_trans->tail = trans->ctx.tail;
+	conn_trans->head = trans->ctx.head;
+	conn_trans->tail = trans->ctx.tail;
+	return conn_trans;
 }
 
 static void
 sqlpool_request_handle_transaction(struct sql_db *conndb,
 				   struct sqlpool_transaction_context *trans)
 {
-	i_assert(trans->conn_trans == NULL);
+	struct sql_transaction_context *conn_trans;
 
 	sqlpool_request_free(&trans->commit_request);
-	driver_sqlpool_new_conn_trans(trans, conndb);
-
-	if (trans->callback != NULL) {
-		/* commit() already called, finish it */
-		sql_transaction_commit(&trans->conn_trans,
-				       driver_sqlpool_commit_callback, trans);
-	}
+	conn_trans = driver_sqlpool_new_conn_trans(trans, conndb);
+	sql_transaction_commit(&conn_trans,
+			       driver_sqlpool_commit_callback, trans);
 }
 
 static void
@@ -630,31 +627,21 @@
 static struct sql_transaction_context *
 driver_sqlpool_transaction_begin(struct sql_db *_db)
 {
-        struct sqlpool_db *db = (struct sqlpool_db *)_db;
 	struct sqlpool_transaction_context *ctx;
-	const struct sqlpool_connection *conn;
 
 	ctx = i_new(struct sqlpool_transaction_context, 1);
 	ctx->ctx.db = _db;
 
-	if (driver_sqlpool_get_connection(db, -1U, &conn))
-		ctx->conn_trans = sql_transaction_begin(conn->db);
-	else {
-		/* queue changes until we get a connection */
-		ctx->commit_request = sqlpool_request_new(db, NULL);
-		ctx->commit_request->trans = ctx;
-		ctx->query_pool = pool_alloconly_create("sqlpool transaction",
-							1024);
-		driver_sqlpool_append_request(db, ctx->commit_request);
-	}
+	/* queue changes until commit. even if we did have a free connection
+	   now, don't use it or multiple open transactions could tie up all
+	   connections. */
+	ctx->query_pool = pool_alloconly_create("sqlpool transaction", 1024);
 	return &ctx->ctx;
 }
 
 static void
 driver_sqlpool_transaction_free(struct sqlpool_transaction_context *ctx)
 {
-	i_assert(ctx->conn_trans == NULL);
-
 	if (ctx->commit_request != NULL)
 		sqlpool_request_abort(&ctx->commit_request);
 	if (ctx->query_pool != NULL)
@@ -677,14 +664,19 @@
 {
 	struct sqlpool_transaction_context *ctx =
 		(struct sqlpool_transaction_context *)_ctx;
+	struct sqlpool_db *db = (struct sqlpool_db *)_ctx->db;
+	const struct sqlpool_connection *conn;
 
 	ctx->callback = callback;
 	ctx->context = context;
 
-	if (ctx->conn_trans != NULL) {
-		sql_transaction_commit(&ctx->conn_trans,
-				       driver_sqlpool_commit_callback, ctx);
-	}
+	ctx->commit_request = sqlpool_request_new(db, NULL);
+	ctx->commit_request->trans = ctx;
+
+	if (driver_sqlpool_get_connection(db, -1U, &conn))
+		sqlpool_request_handle_transaction(conn->db, ctx);
+	else
+		driver_sqlpool_append_request(db, ctx->commit_request);
 }
 
 static int
@@ -695,22 +687,19 @@
 		(struct sqlpool_transaction_context *)_ctx;
         struct sqlpool_db *db = (struct sqlpool_db *)_ctx->db;
 	const struct sqlpool_connection *conn;
+	struct sql_transaction_context *conn_trans;
 	int ret;
 
 	*error_r = NULL;
 
-	if (ctx->conn_trans == NULL) {
-		if (driver_sqlpool_get_sync_connection(db, &conn))
-			driver_sqlpool_new_conn_trans(ctx, conn->db);
-		else {
-			*error_r = SQL_ERRSTR_NOT_CONNECTED;
-			driver_sqlpool_transaction_free(ctx);
-			return -1;
-		}
-		sqlpool_request_abort(&ctx->commit_request);
+	if (!driver_sqlpool_get_sync_connection(db, &conn)) {
+		*error_r = SQL_ERRSTR_NOT_CONNECTED;
+		driver_sqlpool_transaction_free(ctx);
+		return -1;
 	}
 
-	ret = sql_transaction_commit_s(&ctx->conn_trans, error_r);
+	conn_trans = driver_sqlpool_new_conn_trans(ctx, conn->db);
+	ret = sql_transaction_commit_s(&conn_trans, error_r);
 	driver_sqlpool_transaction_free(ctx);
 	return ret;
 }
@@ -721,8 +710,6 @@
 	struct sqlpool_transaction_context *ctx =
 		(struct sqlpool_transaction_context *)_ctx;
 
-	if (ctx->conn_trans != NULL)
-		sql_transaction_rollback(&ctx->conn_trans);
 	driver_sqlpool_transaction_free(ctx);
 }
 
@@ -733,14 +720,10 @@
 	struct sqlpool_transaction_context *ctx =
 		(struct sqlpool_transaction_context *)_ctx;
 
-	if (ctx->conn_trans != NULL && ctx->ctx.head == NULL)
-		sql_update_get_rows(ctx->conn_trans, query, affected_rows);
-	else {
-		/* we didn't get a connection for transaction immediately.
-		   queue updates until commit transfers all of these */
-		sql_transaction_add_query(&ctx->ctx, ctx->query_pool,
-					  query, affected_rows);
-	}
+	/* we didn't get a connection for transaction immediately.
+	   queue updates until commit transfers all of these */
+	sql_transaction_add_query(&ctx->ctx, ctx->query_pool,
+				  query, affected_rows);
 }
 
 struct sql_db driver_sqlpool_db = {


More information about the dovecot-cvs mailing list