dovecot-2.1: lib-sql: If mysql/pgsql commit fails due to server ...
dovecot at dovecot.org
dovecot at dovecot.org
Thu Dec 8 07:02:12 EET 2011
details: http://hg.dovecot.org/dovecot-2.1/rev/782f09d13ece
changeset: 13821:782f09d13ece
user: Timo Sirainen <tss at iki.fi>
date: Thu Dec 08 07:02:03 2011 +0200
description:
lib-sql: If mysql/pgsql commit fails due to server disconnection, reconnect and retry.
diffstat:
src/lib-sql/driver-mysql.c | 47 ++++++++++++++++++++++++++++++++++-----------
src/lib-sql/driver-pgsql.c | 41 +++++++++++++++++++++++++++++----------
2 files changed, 65 insertions(+), 23 deletions(-)
diffs (133 lines):
diff -r 3b70254e0596 -r 782f09d13ece src/lib-sql/driver-mysql.c
--- a/src/lib-sql/driver-mysql.c Thu Dec 08 06:11:03 2011 +0200
+++ b/src/lib-sql/driver-mysql.c Thu Dec 08 07:02:03 2011 +0200
@@ -506,31 +506,54 @@
return ret;
}
+static int driver_mysql_try_commit_s(struct mysql_transaction_context *ctx)
+{
+ struct sql_transaction_context *_ctx = &ctx->ctx;
+
+ /* try to use a transaction in any case,
+ even if it's not actually functional. */
+ if (transaction_send_query(ctx, "BEGIN", NULL) < 0) {
+ if (_ctx->db->state != SQL_DB_STATE_DISCONNECTED)
+ return -1;
+ /* we got disconnected, retry */
+ return 0;
+ }
+ while (_ctx->head != NULL) {
+ if (transaction_send_query(ctx, _ctx->head->query,
+ _ctx->head->affected_rows) < 0)
+ return -1;
+ _ctx->head = _ctx->head->next;
+ }
+ if (transaction_send_query(ctx, "COMMIT", NULL) < 0)
+ return -1;
+ return 1;
+}
+
static int
driver_mysql_transaction_commit_s(struct sql_transaction_context *_ctx,
const char **error_r)
{
struct mysql_transaction_context *ctx =
(struct mysql_transaction_context *)_ctx;
- int ret = 0;
+ struct mysql_db *db = (struct mysql_db *)_ctx->db;
+ int ret = 1;
*error_r = NULL;
if (_ctx->head != NULL) {
- /* try to use a transaction in any case,
- even if it doesn't work. */
- (void)transaction_send_query(ctx, "BEGIN", NULL);
- while (_ctx->head != NULL) {
- if (transaction_send_query(ctx, _ctx->head->query,
- _ctx->head->affected_rows) < 0)
- break;
- _ctx->head = _ctx->head->next;
+ ret = driver_mysql_try_commit_s(ctx);
+ *error_r = t_strdup(ctx->error);
+ if (ret == 0) {
+ i_info("%s: Disconnected from database, "
+ "retrying commit", db->dbname);
+ if (sql_connect(_ctx->db) >= 0) {
+ ctx->failed = FALSE;
+ ret = driver_mysql_try_commit_s(ctx);
+ }
}
- ret = transaction_send_query(ctx, "COMMIT", NULL);
- *error_r = ctx->error;
}
sql_transaction_rollback(&_ctx);
- return ret;
+ return ret <= 0 ? -1 : 0;
}
static void
diff -r 3b70254e0596 -r 782f09d13ece src/lib-sql/driver-pgsql.c
--- a/src/lib-sql/driver-pgsql.c Thu Dec 08 06:11:03 2011 +0200
+++ b/src/lib-sql/driver-pgsql.c Thu Dec 08 07:02:03 2011 +0200
@@ -956,22 +956,16 @@
"ROLLBACK" : "COMMIT");
}
-static int
-driver_pgsql_transaction_commit_s(struct sql_transaction_context *_ctx,
- const char **error_r)
+static void
+driver_pgsql_try_commit_s(struct pgsql_transaction_context *ctx,
+ const char **error_r)
{
- struct pgsql_transaction_context *ctx =
- (struct pgsql_transaction_context *)_ctx;
+ struct sql_transaction_context *_ctx = &ctx->ctx;
struct pgsql_db *db = (struct pgsql_db *)_ctx->db;
struct sql_transaction_query *single_query = NULL;
struct sql_result *result;
- *error_r = NULL;
-
- if (ctx->failed || _ctx->head == NULL) {
- /* nothing to be done */
- result = NULL;
- } else if (_ctx->head->next == NULL) {
+ if (_ctx->head->next == NULL) {
/* just a single query, send it */
single_query = _ctx->head;
result = sql_query_s(_ctx->db, single_query->query);
@@ -999,6 +993,31 @@
}
if (result != NULL)
sql_result_unref(result);
+}
+
+static int
+driver_pgsql_transaction_commit_s(struct sql_transaction_context *_ctx,
+ const char **error_r)
+{
+ struct pgsql_transaction_context *ctx =
+ (struct pgsql_transaction_context *)_ctx;
+ struct pgsql_db *db = (struct pgsql_db *)_ctx->db;
+
+ *error_r = NULL;
+
+ if (_ctx->head != NULL) {
+ driver_pgsql_try_commit_s(ctx, error_r);
+ if (_ctx->db->state == SQL_DB_STATE_DISCONNECTED) {
+ *error_r = t_strdup(*error_r);
+ i_info("%s: Disconnected from database, "
+ "retrying commit", pgsql_prefix(db));
+ if (sql_connect(_ctx->db) >= 0) {
+ ctx->failed = FALSE;
+ *error_r = NULL;
+ driver_pgsql_try_commit_s(ctx, error_r);
+ }
+ }
+ }
i_assert(ctx->refcount == 1);
driver_pgsql_transaction_unref(ctx);
More information about the dovecot-cvs
mailing list