dovecot: Added SQL connection pools.

dovecot at dovecot.org dovecot at dovecot.org
Sat Sep 22 19:40:52 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/e66bf9b9e011
changeset: 6479:e66bf9b9e011
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Sep 22 19:39:42 2007 +0300
description:
Added SQL connection pools.

diffstat:

3 files changed, 156 insertions(+), 2 deletions(-)
src/lib-sql/Makefile.am |    6 +-
src/lib-sql/sql-pool.c  |  139 +++++++++++++++++++++++++++++++++++++++++++++++
src/lib-sql/sql-pool.h  |   13 ++++

diffs (183 lines):

diff -r 1e07f47e5e1e -r e66bf9b9e011 src/lib-sql/Makefile.am
--- a/src/lib-sql/Makefile.am	Sat Sep 22 19:39:30 2007 +0300
+++ b/src/lib-sql/Makefile.am	Sat Sep 22 19:39:42 2007 +0300
@@ -32,7 +32,8 @@ AM_CPPFLAGS = \
 	$(SQL_CFLAGS)
 
 dist_sources = \
-	sql-api.c
+	sql-api.c \
+	sql-pool.c
 
 if ! SQL_PLUGINS
 driver_sources = \
@@ -65,7 +66,8 @@ endif
 
 headers = \
 	sql-api.h \
-	sql-api-private.h
+	sql-api-private.h \
+	sql-pool.h
 
 if INSTALL_HEADERS
   pkginc_libdir=$(pkgincludedir)/src/lib-sql
diff -r 1e07f47e5e1e -r e66bf9b9e011 src/lib-sql/sql-pool.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-sql/sql-pool.c	Sat Sep 22 19:39:42 2007 +0300
@@ -0,0 +1,139 @@
+/* Copyright (c) 2004-2007 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "hash.h"
+#include "sql-api-private.h"
+#include "sql-pool.h"
+
+#define SQL_POOL_CONTEXT(obj) \
+	MODULE_CONTEXT(obj, sql_pool_module)
+
+struct sql_pool_context {
+	union sql_db_module_context module_ctx;
+	struct sql_db *prev, *next; /* These are set while refcount=0 */
+
+	struct sql_pool *pool;
+	int refcount;
+	char *key;
+	void (*orig_deinit)(struct sql_db *db);
+};
+
+struct sql_pool {
+	struct hash_table *dbs;
+	unsigned int unused_count, max_unused_connections;
+	struct sql_db *unused_tail, *unused_head;
+};
+
+static MODULE_CONTEXT_DEFINE_INIT(sql_pool_module, &sql_db_module_register);
+
+static void sql_pool_db_deinit(struct sql_db *db)
+{
+	struct sql_pool_context *ctx = SQL_POOL_CONTEXT(db);
+	struct sql_pool_context *head_ctx;
+
+	if (--ctx->refcount > 0)
+		return;
+
+	ctx->pool->unused_count++;
+	if (ctx->pool->unused_tail == NULL)
+		ctx->pool->unused_tail = db;
+	else {
+		head_ctx = SQL_POOL_CONTEXT(ctx->pool->unused_head);
+		head_ctx->next = db;
+	}
+	ctx->prev = ctx->pool->unused_head;
+	ctx->pool->unused_head = db;
+}
+
+static void sql_pool_unlink(struct sql_pool_context *ctx)
+{
+	struct sql_pool_context *prev_ctx, *next_ctx;
+
+	i_assert(ctx->refcount == 0);
+
+	if (ctx->prev == NULL)
+		ctx->pool->unused_tail = ctx->next;
+	else {
+		prev_ctx = SQL_POOL_CONTEXT(ctx->prev);
+		prev_ctx->next = ctx->next;
+	}
+	if (ctx->next == NULL)
+		ctx->pool->unused_head = ctx->prev;
+	else {
+		next_ctx = SQL_POOL_CONTEXT(ctx->prev);
+		next_ctx->prev = ctx->prev;
+	}
+	ctx->pool->unused_count--;
+}
+
+static void sql_pool_drop_oldest(struct sql_pool *pool)
+{
+	struct sql_db *db;
+	struct sql_pool_context *ctx;
+
+	while (pool->unused_count >= pool->max_unused_connections) {
+		db = pool->unused_tail;
+		ctx = SQL_POOL_CONTEXT(db);
+		sql_pool_unlink(ctx);
+
+		i_free(ctx->key);
+		ctx->orig_deinit(db);
+	}
+}
+
+struct sql_db *sql_pool_new(struct sql_pool *pool,
+			    const char *db_driver, const char *connect_string)
+{
+	struct sql_pool_context *ctx;
+	struct sql_db *db;
+	const char *key;
+
+	t_push();
+	key = t_strdup_printf("%s\t%s", db_driver, connect_string);
+	db = hash_lookup(pool->dbs, key);
+	if (db != NULL) {
+		ctx = SQL_POOL_CONTEXT(db);
+		if (ctx->refcount == 0) {
+			sql_pool_unlink(ctx);
+			ctx->prev = ctx->next = NULL;
+		}
+	} else {
+		sql_pool_drop_oldest(pool);
+
+		ctx = i_new(struct sql_pool_context, 1);
+		ctx->pool = pool;
+		ctx->key = i_strdup(key);
+
+		db = sql_init(db_driver, connect_string);
+		ctx->orig_deinit = db->v.deinit;
+		db->v.deinit = sql_pool_db_deinit;
+
+		MODULE_CONTEXT_SET(db, sql_pool_module, ctx);
+		hash_insert(pool->dbs, ctx->key, db);
+	}
+	t_pop();
+
+	ctx->refcount++;
+	return db;
+}
+
+struct sql_pool *sql_pool_init(unsigned int max_unused_connections)
+{
+	struct sql_pool *pool;
+
+	pool = i_new(struct sql_pool, 1);
+	pool->dbs = hash_create(default_pool, default_pool, 0, str_hash,
+				(hash_cmp_callback_t *)strcmp);
+	pool->max_unused_connections = max_unused_connections;
+	return pool;
+}
+
+void sql_pool_deinit(struct sql_pool **_pool)
+{
+	struct sql_pool *pool = *_pool;
+
+	*_pool = NULL;
+	hash_destroy(&pool->dbs);
+	i_free(pool);
+}
diff -r 1e07f47e5e1e -r e66bf9b9e011 src/lib-sql/sql-pool.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-sql/sql-pool.h	Sat Sep 22 19:39:42 2007 +0300
@@ -0,0 +1,13 @@
+#ifndef SQL_POOL_H
+#define SQL_POOL_H
+
+struct sql_pool;
+
+/* Like sql_init(), but use a connection pool. */
+struct sql_db *sql_pool_new(struct sql_pool *pool,
+			    const char *db_driver, const char *connect_string);
+
+struct sql_pool *sql_pool_init(unsigned int max_unused_connections);
+void sql_pool_deinit(struct sql_pool **pool);
+
+#endif


More information about the dovecot-cvs mailing list