Mercurial > dovecot > original-hg > dovecot-1.2
changeset 6479:e66bf9b9e011 HEAD
Added SQL connection pools.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sat, 22 Sep 2007 19:39:42 +0300 |
parents | 1e07f47e5e1e |
children | 7596339a9452 |
files | src/lib-sql/Makefile.am src/lib-sql/sql-pool.c src/lib-sql/sql-pool.h |
diffstat | 3 files changed, 156 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- 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 @@ $(SQL_CFLAGS) dist_sources = \ - sql-api.c + sql-api.c \ + sql-pool.c if ! SQL_PLUGINS driver_sources = \ @@ -65,7 +66,8 @@ headers = \ sql-api.h \ - sql-api-private.h + sql-api-private.h \ + sql-pool.h if INSTALL_HEADERS pkginc_libdir=$(pkgincludedir)/src/lib-sql
--- /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); +}
--- /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