1
/* Copyright (c) 2004-2008 Dovecot authors, see the included COPYING file */
6
#include "sql-api-private.h"
9
#define SQL_POOL_CONTEXT(obj) \
10
MODULE_CONTEXT(obj, sql_pool_module)
12
struct sql_pool_context {
13
union sql_db_module_context module_ctx;
14
struct sql_db *prev, *next; /* These are set while refcount=0 */
16
struct sql_pool *pool;
19
void (*orig_deinit)(struct sql_db *db);
23
struct hash_table *dbs;
24
unsigned int unused_count, max_unused_connections;
25
struct sql_db *unused_tail, *unused_head;
28
static MODULE_CONTEXT_DEFINE_INIT(sql_pool_module, &sql_db_module_register);
30
static void sql_pool_db_deinit(struct sql_db *db)
32
struct sql_pool_context *ctx = SQL_POOL_CONTEXT(db);
33
struct sql_pool_context *head_ctx;
35
if (--ctx->refcount > 0)
38
ctx->pool->unused_count++;
39
if (ctx->pool->unused_tail == NULL)
40
ctx->pool->unused_tail = db;
42
head_ctx = SQL_POOL_CONTEXT(ctx->pool->unused_head);
45
ctx->prev = ctx->pool->unused_head;
46
ctx->pool->unused_head = db;
49
static void sql_pool_unlink(struct sql_pool_context *ctx)
51
struct sql_pool_context *prev_ctx, *next_ctx;
53
i_assert(ctx->refcount == 0);
55
if (ctx->prev == NULL)
56
ctx->pool->unused_tail = ctx->next;
58
prev_ctx = SQL_POOL_CONTEXT(ctx->prev);
59
prev_ctx->next = ctx->next;
61
if (ctx->next == NULL)
62
ctx->pool->unused_head = ctx->prev;
64
next_ctx = SQL_POOL_CONTEXT(ctx->prev);
65
next_ctx->prev = ctx->prev;
67
ctx->pool->unused_count--;
70
static void sql_pool_drop_oldest(struct sql_pool *pool)
73
struct sql_pool_context *ctx;
75
while (pool->unused_count >= pool->max_unused_connections) {
76
db = pool->unused_tail;
77
ctx = SQL_POOL_CONTEXT(db);
85
struct sql_db *sql_pool_new(struct sql_pool *pool,
86
const char *db_driver, const char *connect_string)
88
struct sql_pool_context *ctx;
92
key = i_strdup_printf("%s\t%s", db_driver, connect_string);
93
db = hash_lookup(pool->dbs, key);
95
ctx = SQL_POOL_CONTEXT(db);
96
if (ctx->refcount == 0) {
98
ctx->prev = ctx->next = NULL;
102
sql_pool_drop_oldest(pool);
104
ctx = i_new(struct sql_pool_context, 1);
108
db = sql_init(db_driver, connect_string);
109
ctx->orig_deinit = db->v.deinit;
110
db->v.deinit = sql_pool_db_deinit;
112
MODULE_CONTEXT_SET(db, sql_pool_module, ctx);
113
hash_insert(pool->dbs, ctx->key, db);
120
struct sql_pool *sql_pool_init(unsigned int max_unused_connections)
122
struct sql_pool *pool;
124
pool = i_new(struct sql_pool, 1);
125
pool->dbs = hash_create(default_pool, default_pool, 0, str_hash,
126
(hash_cmp_callback_t *)strcmp);
127
pool->max_unused_connections = max_unused_connections;
131
void sql_pool_deinit(struct sql_pool **_pool)
133
struct sql_pool *pool = *_pool;
136
hash_destroy(&pool->dbs);