dovecot-1.2: pgsql: If query failed because connection was lost,...
dovecot at dovecot.org
dovecot at dovecot.org
Mon Jan 12 20:26:40 EET 2009
details: http://hg.dovecot.org/dovecot-1.2/rev/e3fd1a6467f2
changeset: 8617:e3fd1a6467f2
user: Timo Sirainen <tss at iki.fi>
date: Mon Jan 12 13:26:24 2009 -0500
description:
pgsql: If query failed because connection was lost, retry it automatically.
diffstat:
1 file changed, 64 insertions(+), 20 deletions(-)
src/lib-sql/driver-pgsql.c | 84 +++++++++++++++++++++++++++++++++-----------
diffs (186 lines):
diff -r e50c8c44ab28 -r e3fd1a6467f2 src/lib-sql/driver-pgsql.c
--- a/src/lib-sql/driver-pgsql.c Mon Jan 12 12:23:19 2009 -0500
+++ b/src/lib-sql/driver-pgsql.c Mon Jan 12 13:26:24 2009 -0500
@@ -46,6 +46,7 @@ struct pgsql_result {
struct sql_result api;
PGresult *pgres;
+ char *query;
unsigned int rownum, rows;
unsigned int fields_count;
const char **fields;
@@ -55,6 +56,8 @@ struct pgsql_result {
sql_query_callback_t *callback;
void *context;
+
+ unsigned int retry_query:1;
};
struct pgsql_queue {
@@ -80,6 +83,10 @@ extern struct sql_db driver_pgsql_db;
extern struct sql_db driver_pgsql_db;
extern struct sql_result driver_pgsql_result;
+static void
+driver_pgsql_query_full(struct sql_db *db, const char *query,
+ sql_query_callback_t *callback, void *context,
+ bool retry_query);
static void queue_send_next(struct pgsql_db *db);
static void result_finish(struct pgsql_result *result);
@@ -280,6 +287,7 @@ static void driver_pgsql_result_free(str
i_free(result->fields);
i_free(result->values);
+ i_free(result->query);
i_free(result);
if (db->queue != NULL && !db->querying && db->connected)
@@ -289,9 +297,15 @@ static void result_finish(struct pgsql_r
static void result_finish(struct pgsql_result *result)
{
struct pgsql_db *db = (struct pgsql_db *)result->api.db;
- bool free_result = TRUE;
-
- if (result->callback != NULL) {
+ bool free_result = TRUE, retry = FALSE;
+ bool disconnected;
+
+ disconnected = PQstatus(db->pg) == CONNECTION_BAD;
+ if (disconnected && result->pgres == NULL && result->retry_query) {
+ /* retry the query */
+ i_error("pgsql: Query failed, retrying: %s", last_error(db));
+ retry = TRUE;
+ } else if (result->callback != NULL) {
result->api.callback = TRUE;
T_BEGIN {
result->callback(&result->api, result->context);
@@ -299,13 +313,20 @@ static void result_finish(struct pgsql_r
result->api.callback = FALSE;
free_result = db->sync_result != &result->api;
}
+
+ if (disconnected) {
+ /* disconnected */
+ driver_pgsql_close(db);
+
+ if (retry) {
+ /* retry the query */
+ driver_pgsql_query_full(&db->api, result->query,
+ result->callback,
+ result->context, FALSE);
+ }
+ }
if (free_result)
driver_pgsql_result_free(&result->api);
-
- if (PQstatus(db->pg) == CONNECTION_BAD) {
- /* disconnected */
- driver_pgsql_close(db);
- }
}
static void get_result(struct pgsql_result *result)
@@ -495,10 +516,10 @@ static void do_query(struct pgsql_result
}
}
-static void exec_callback(struct sql_result *result,
+static void exec_callback(struct sql_result *_result,
void *context ATTR_UNUSED)
{
- struct pgsql_db *db = (struct pgsql_db *)result->db;
+ struct pgsql_db *db = (struct pgsql_db *)_result->db;
i_error("pgsql: sql_exec() failed: %s", last_error(db));
}
@@ -525,7 +546,8 @@ driver_pgsql_escape_string(struct sql_db
return to;
}
-static void driver_pgsql_exec(struct sql_db *db, const char *query)
+static void driver_pgsql_exec_full(struct sql_db *db, const char *query,
+ bool retry_query)
{
struct pgsql_result *result;
@@ -533,12 +555,22 @@ static void driver_pgsql_exec(struct sql
result->api = driver_pgsql_result;
result->api.db = db;
result->callback = exec_callback;
-
+ if (retry_query) {
+ result->query = i_strdup(query);
+ result->retry_query = TRUE;
+ }
do_query(result, query);
}
-static void driver_pgsql_query(struct sql_db *db, const char *query,
- sql_query_callback_t *callback, void *context)
+static void driver_pgsql_exec(struct sql_db *db, const char *query)
+{
+ driver_pgsql_exec_full(db, query, TRUE);
+}
+
+static void
+driver_pgsql_query_full(struct sql_db *db, const char *query,
+ sql_query_callback_t *callback, void *context,
+ bool retry_query)
{
struct pgsql_result *result;
@@ -547,8 +579,17 @@ static void driver_pgsql_query(struct sq
result->api.db = db;
result->callback = callback;
result->context = context;
-
+ if (retry_query) {
+ result->query = i_strdup(query);
+ result->retry_query = TRUE;
+ }
do_query(result, query);
+}
+
+static void driver_pgsql_query(struct sql_db *db, const char *query,
+ sql_query_callback_t *callback, void *context)
+{
+ driver_pgsql_query_full(db, query, callback, context, TRUE);
}
static void pgsql_query_s_callback(struct sql_result *result, void *context)
@@ -840,7 +881,8 @@ driver_pgsql_transaction_commit(struct s
ctx->callback = callback;
ctx->context = context;
- sql_query(_ctx->db, "COMMIT", transaction_commit_callback, ctx);
+ driver_pgsql_query_full(_ctx->db, "COMMIT",
+ transaction_commit_callback, ctx, FALSE);
}
static int
@@ -884,9 +926,10 @@ driver_pgsql_transaction_rollback(struct
}
static void
-transaction_update_callback(struct sql_result *result,
- struct pgsql_transaction_context *ctx)
-{
+transaction_update_callback(struct sql_result *result, void *context)
+{
+ struct pgsql_transaction_context *ctx = context;
+
if (sql_result_next_row(result) < 0) {
ctx->failed = TRUE;
ctx->error = sql_result_get_error(result);
@@ -907,7 +950,8 @@ driver_pgsql_update(struct sql_transacti
sql_query(_ctx->db, "BEGIN", transaction_update_callback, ctx);
}
- sql_query(_ctx->db, query, transaction_update_callback, ctx);
+ driver_pgsql_query_full(_ctx->db, query,
+ transaction_update_callback, ctx, FALSE);
}
struct sql_db driver_pgsql_db = {
More information about the dovecot-cvs
mailing list