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