driver-sqlpool.c revision 2d20d46069fa0d4b98790779552dd778d1749d1c
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2010-2011 Dovecot authors, see the included COPYING file */
6f2e601fa36133320aa88258106be46a175a0e53Timo Sirainen /* all connections from all hosts */
6f2e601fa36133320aa88258106be46a175a0e53Timo Sirainen ARRAY_DEFINE(all_connections, struct sqlpool_connection);
6f2e601fa36133320aa88258106be46a175a0e53Timo Sirainen /* index of last connection in all_connections that was used to
6f2e601fa36133320aa88258106be46a175a0e53Timo Sirainen send a query. */
6f2e601fa36133320aa88258106be46a175a0e53Timo Sirainen /* queued requests */
6f2e601fa36133320aa88258106be46a175a0e53Timo Sirainen struct sqlpool_request *requests_head, *requests_tail;
8846e6eed6177a39b662f4f1ebf9b84ad1f0b7ecTimo Sirainen /* requests are a) queries */
8846e6eed6177a39b662f4f1ebf9b84ad1f0b7ecTimo Sirainen /* b) transaction waiters */
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainensqlpool_add_connection(struct sqlpool_db *db, struct sqlpool_host *host,
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen unsigned int host_idx);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainendriver_sqlpool_query_callback(struct sql_result *result,
f9ef36afc131626754716d6f4874a2ad04da0ac4Timo Sirainendriver_sqlpool_commit_callback(const char *error,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainensqlpool_request_new(struct sqlpool_db *db, const char *query)
573731df7d9b2ebb9028311a6c33b338dd2dd34dTimo Sirainensqlpool_request_free(struct sqlpool_request **_request)
01758d8aaa05940397c8210af52d7f45a5b676aeTimo Sirainen i_assert(request->prev == NULL && request->next == NULL);
573731df7d9b2ebb9028311a6c33b338dd2dd34dTimo Sirainensqlpool_request_abort(struct sqlpool_request **_request)
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen request->callback(&sql_not_connected_result, request->context);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainendriver_sqlpool_new_conn_trans(struct sqlpool_transaction_context *trans,
573731df7d9b2ebb9028311a6c33b338dd2dd34dTimo Sirainen /* backend will use our queries list (we might still append more
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen queries to the list) */
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainensqlpool_request_handle_transaction(struct sql_db *conndb,
573731df7d9b2ebb9028311a6c33b338dd2dd34dTimo Sirainen conn_trans = driver_sqlpool_new_conn_trans(trans, conndb);
573731df7d9b2ebb9028311a6c33b338dd2dd34dTimo Sirainensqlpool_request_send_next(struct sqlpool_db *db, struct sql_db *conndb)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if (db->requests_head == NULL || !SQL_DB_IS_READY(conndb))
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen DLLIST2_REMOVE(&db->requests_head, &db->requests_tail, request);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen sqlpool_request_handle_transaction(conndb, request->trans);
573731df7d9b2ebb9028311a6c33b338dd2dd34dTimo Sirainenstatic void sqlpool_reconnect(struct sql_db *conndb)
573731df7d9b2ebb9028311a6c33b338dd2dd34dTimo Sirainensqlpool_find_host_with_least_connections(struct sqlpool_db *db,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen unsigned int *host_idx_r)
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen unsigned int i, count;
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen hosts = array_get_modifiable(&db->hosts, &count);
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen if (min->connection_count > hosts[i].connection_count) {
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainenstatic bool sqlpool_have_successful_connections(struct sqlpool_db *db)
124e615e2949883473e30950a15a563feef26406Timo Sirainensqlpool_handle_connect_failed(struct sqlpool_db *db, struct sql_db *conndb)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen /* increase delay between reconnections to this
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if (conndb->connect_delay > SQL_CONNECT_MAX_DELAY)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen conndb->connect_delay = SQL_CONNECT_MAX_DELAY;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen /* reconnect after the delay */
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen conndb->to_reconnect = timeout_add(conndb->connect_delay * 1000,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen /* if we have zero successful hosts and there still are hosts
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen without connections, connect to one of them. */
53dff078a5f49e9d28d6c81d3437755e27526e3eTimo Sirainen if (!sqlpool_have_successful_connections(db)) {
124e615e2949883473e30950a15a563feef26406Timo Sirainen host = sqlpool_find_host_with_least_connections(db, &host_idx);
53dff078a5f49e9d28d6c81d3437755e27526e3eTimo Sirainen (void)sqlpool_add_connection(db, host, host_idx);
124e615e2949883473e30950a15a563feef26406Timo Sirainensqlpool_state_changed(struct sql_db *conndb, enum sql_db_state prev_state,
124e615e2949883473e30950a15a563feef26406Timo Sirainen conndb->connect_delay = SQL_CONNECT_MIN_DELAY;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainensqlpool_add_connection(struct sqlpool_db *db, struct sqlpool_host *host,
573731df7d9b2ebb9028311a6c33b338dd2dd34dTimo Sirainen conndb = db->driver->v.init(host->connect_string);
124e615e2949883473e30950a15a563feef26406Timo Sirainen conndb->state_change_callback = sqlpool_state_changed;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen conndb->connect_delay = SQL_CONNECT_MIN_DELAY;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen conn = array_append_space(&db->all_connections);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainensqlpool_add_new_connection(struct sqlpool_db *db)
548f87789cf9865572b7b86f7be5a9bbfa132f3fTimo Sirainen host = sqlpool_find_host_with_least_connections(db, &host_idx);
return NULL;
static const struct sqlpool_connection *
unsigned int unwanted_host_idx,
bool *all_disconnected_r)
unsigned int i, count;
for (i = 0; i < count; i++) {
return NULL;
unsigned int unwanted_host_idx,
unsigned int i, count;
bool all_disconnected;
for (i = 0; i < count; i++) {
return FALSE;
return TRUE;
unsigned int i, count;
return TRUE;
for (i = 0; i < count; i++) {
return TRUE;
return FALSE;
value++;
value);
struct sql_db *
T_BEGIN {
} T_END;
if (ret2 > 0)
if (ret2 == 0)
ret = 0;
return ret;
unsigned int i, count;
for (i = 0; i < count; i++) {
request);
static struct sql_result *
return &sql_not_connected_result;
return result;
return result;
static struct sql_transaction_context *
void *context)
const char **error_r)
int ret;
return ret;
unsigned int *affected_rows)
NULL,