dovecot-2.0: lib-sql: Connect earlier to fallback host when usin...
dovecot at dovecot.org
dovecot at dovecot.org
Wed Nov 17 18:56:00 EET 2010
details: http://hg.dovecot.org/dovecot-2.0/rev/990abbb6d3dd
changeset: 12434:990abbb6d3dd
user: Timo Sirainen <tss at iki.fi>
date: Wed Nov 17 16:55:44 2010 +0000
description:
lib-sql: Connect earlier to fallback host when using multiple hosts and primary fails.
diffstat:
src/lib-sql/driver-sqlpool.c | 121 ++++++++++++++++++++++++++-------------
1 files changed, 80 insertions(+), 41 deletions(-)
diffs (170 lines):
diff -r 2456cd0917d3 -r 990abbb6d3dd src/lib-sql/driver-sqlpool.c
--- a/src/lib-sql/driver-sqlpool.c Wed Nov 17 14:33:46 2010 +0000
+++ b/src/lib-sql/driver-sqlpool.c Wed Nov 17 16:55:44 2010 +0000
@@ -70,6 +70,9 @@
extern struct sql_db driver_sqlpool_db;
+static struct sqlpool_connection *
+sqlpool_add_connection(struct sqlpool_db *db, struct sqlpool_host *host,
+ unsigned int host_idx);
static void
driver_sqlpool_query_callback(struct sql_result *result,
struct sqlpool_request *request);
@@ -172,39 +175,6 @@
(void)sql_connect(conndb);
}
-static void
-sqlpool_state_changed(struct sql_db *conndb, enum sql_db_state prev_state,
- void *context)
-{
- struct sqlpool_db *db = context;
-
- if (conndb->state == SQL_DB_STATE_IDLE) {
- conndb->connect_failure_count = 0;
- conndb->connect_delay = SQL_CONNECT_MIN_DELAY;
- sqlpool_request_send_next(db, conndb);
- }
-
- if (prev_state == SQL_DB_STATE_CONNECTING &&
- conndb->state == SQL_DB_STATE_DISCONNECTED &&
- !conndb->no_reconnect) {
- /* connect failed */
- if (conndb->connect_failure_count > 0) {
- /* increase delay between reconnections to this
- server */
- conndb->connect_delay *= 5;
- if (conndb->connect_delay > SQL_CONNECT_MAX_DELAY)
- conndb->connect_delay = SQL_CONNECT_MAX_DELAY;
- }
- conndb->connect_failure_count++;
-
- /* reconnect after the delay */
- if (conndb->to_reconnect != NULL)
- timeout_remove(&conndb->to_reconnect);
- conndb->to_reconnect = timeout_add(conndb->connect_delay * 1000,
- sqlpool_reconnect, conndb);
- }
-}
-
static struct sqlpool_host *
sqlpool_find_host_with_least_connections(struct sqlpool_db *db,
unsigned int *host_idx_r)
@@ -227,16 +197,72 @@
return min;
}
-static struct sqlpool_connection *sqlpool_add_connection(struct sqlpool_db *db)
+static bool sqlpool_have_successful_connections(struct sqlpool_db *db)
+{
+ const struct sqlpool_connection *conn;
+
+ array_foreach(&db->all_connections, conn) {
+ if (conn->db->state >= SQL_DB_STATE_IDLE)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void
+sqlpool_handle_connect_failed(struct sqlpool_db *db, struct sql_db *conndb)
+{
+ struct sqlpool_host *host;
+ unsigned int host_idx;
+
+ if (conndb->connect_failure_count > 0) {
+ /* increase delay between reconnections to this
+ server */
+ conndb->connect_delay *= 5;
+ if (conndb->connect_delay > SQL_CONNECT_MAX_DELAY)
+ conndb->connect_delay = SQL_CONNECT_MAX_DELAY;
+ }
+ conndb->connect_failure_count++;
+
+ /* reconnect after the delay */
+ if (conndb->to_reconnect != NULL)
+ timeout_remove(&conndb->to_reconnect);
+ conndb->to_reconnect = timeout_add(conndb->connect_delay * 1000,
+ sqlpool_reconnect, conndb);
+
+ /* if we have zero successful hosts and there still are hosts
+ without connections, connect to one of them. */
+ if (!sqlpool_have_successful_connections(db)) {
+ host = sqlpool_find_host_with_least_connections(db, &host_idx);
+ if (host->connection_count == 0)
+ (void)sqlpool_add_connection(db, host, host_idx);
+ }
+}
+
+static void
+sqlpool_state_changed(struct sql_db *conndb, enum sql_db_state prev_state,
+ void *context)
+{
+ struct sqlpool_db *db = context;
+
+ if (conndb->state == SQL_DB_STATE_IDLE) {
+ conndb->connect_failure_count = 0;
+ conndb->connect_delay = SQL_CONNECT_MIN_DELAY;
+ sqlpool_request_send_next(db, conndb);
+ }
+
+ if (prev_state == SQL_DB_STATE_CONNECTING &&
+ conndb->state == SQL_DB_STATE_DISCONNECTED &&
+ !conndb->no_reconnect)
+ sqlpool_handle_connect_failed(db, conndb);
+}
+
+static struct sqlpool_connection *
+sqlpool_add_connection(struct sqlpool_db *db, struct sqlpool_host *host,
+ unsigned int host_idx)
{
struct sql_db *conndb;
- struct sqlpool_host *host;
struct sqlpool_connection *conn;
- unsigned int host_idx;
- host = sqlpool_find_host_with_least_connections(db, &host_idx);
- if (host->connection_count >= db->connection_limit)
- return NULL;
host->connection_count++;
conndb = db->driver->v.init(host->connect_string);
@@ -252,6 +278,19 @@
return conn;
}
+static struct sqlpool_connection *
+sqlpool_add_new_connection(struct sqlpool_db *db)
+{
+ struct sqlpool_host *host;
+ unsigned int host_idx;
+
+ host = sqlpool_find_host_with_least_connections(db, &host_idx);
+ if (host->connection_count >= db->connection_limit)
+ return NULL;
+ else
+ return sqlpool_add_connection(db, host, host_idx);
+}
+
static const struct sqlpool_connection *
sqlpool_find_available_connection(struct sqlpool_db *db,
unsigned int unwanted_host_idx,
@@ -316,7 +355,7 @@
}
if (conn == NULL) {
/* still nothing. try creating new connections */
- conn = sqlpool_add_connection(db);
+ conn = sqlpool_add_new_connection(db);
if (conn == NULL || !SQL_DB_IS_READY(conn->db))
return FALSE;
}
@@ -425,7 +464,7 @@
i_array_init(&db->all_connections, 16);
/* always have at least one backend connection initialized */
- (void)sqlpool_add_connection(db);
+ (void)sqlpool_add_new_connection(db);
return &db->api;
}
More information about the dovecot-cvs
mailing list