#include "istream.h"
#include "str.h"
#include "sql-api-private.h"
-#include "sql-pool.h"
+#include "sql-db-cache.h"
#include "dict-private.h"
#include "dict-sql-settings.h"
#include "dict-sql.h"
unsigned int changed:1;
};
-static struct sql_pool *dict_sql_pool;
+static struct sql_db_cache *dict_sql_db_cache;
static void sql_dict_prev_inc_flush(struct sql_dict_transaction_context *ctx);
/* currently pgsql and sqlite don't support "ON DUPLICATE KEY" */
dict->has_on_duplicate_key = strcmp(driver->name, "mysql") == 0;
- dict->db = sql_pool_new(dict_sql_pool, driver->name,
- dict->set->connect);
+ dict->db = sql_db_cache_new(dict_sql_db_cache, driver->name,
+ dict->set->connect);
return &dict->dict;
}
const struct sql_db *const *drivers;
unsigned int i, count;
- dict_sql_pool = sql_pool_init(DICT_SQL_MAX_UNUSED_CONNECTIONS);
+ dict_sql_db_cache = sql_db_cache_init(DICT_SQL_MAX_UNUSED_CONNECTIONS);
/* @UNSAFE */
drivers = array_get(&sql_drivers, &count);
for (i = 0; dict_sql_drivers[i].name != NULL; i++)
dict_driver_unregister(&dict_sql_drivers[i]);
i_free(dict_sql_drivers);
- sql_pool_deinit(&dict_sql_pool);
+ sql_db_cache_deinit(&dict_sql_db_cache);
}
dist_sources = \
sql-api.c \
- sql-pool.c
+ sql-db-cache.c
if ! SQL_PLUGINS
driver_sources = \
headers = \
sql-api.h \
sql-api-private.h \
- sql-pool.h
+ sql-db-cache.h
pkginc_libdir=$(pkgincludedir)
pkginc_lib_HEADERS = $(headers)
--- /dev/null
+/* Copyright (c) 2004-2010 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "hash.h"
+#include "sql-api-private.h"
+#include "sql-db-cache.h"
+
+#define SQL_DB_CACHE_CONTEXT(obj) \
+ MODULE_CONTEXT(obj, sql_db_cache_module)
+
+struct sql_db_cache_context {
+ union sql_db_module_context module_ctx;
+ struct sql_db *prev, *next; /* These are set while refcount=0 */
+
+ struct sql_db_cache *cache;
+ int refcount;
+ char *key;
+ void (*orig_deinit)(struct sql_db *db);
+};
+
+struct sql_db_cache {
+ struct hash_table *dbs;
+ unsigned int unused_count, max_unused_connections;
+ struct sql_db *unused_tail, *unused_head;
+};
+
+static MODULE_CONTEXT_DEFINE_INIT(sql_db_cache_module, &sql_db_module_register);
+
+static void sql_db_cache_db_deinit(struct sql_db *db)
+{
+ struct sql_db_cache_context *ctx = SQL_DB_CACHE_CONTEXT(db);
+ struct sql_db_cache_context *head_ctx;
+
+ if (--ctx->refcount > 0)
+ return;
+
+ ctx->cache->unused_count++;
+ if (ctx->cache->unused_tail == NULL)
+ ctx->cache->unused_tail = db;
+ else {
+ head_ctx = SQL_DB_CACHE_CONTEXT(ctx->cache->unused_head);
+ head_ctx->next = db;
+ }
+ ctx->prev = ctx->cache->unused_head;
+ ctx->cache->unused_head = db;
+}
+
+static void sql_db_cache_unlink(struct sql_db_cache_context *ctx)
+{
+ struct sql_db_cache_context *prev_ctx, *next_ctx;
+
+ i_assert(ctx->refcount == 0);
+
+ if (ctx->prev == NULL)
+ ctx->cache->unused_tail = ctx->next;
+ else {
+ prev_ctx = SQL_DB_CACHE_CONTEXT(ctx->prev);
+ prev_ctx->next = ctx->next;
+ }
+ if (ctx->next == NULL)
+ ctx->cache->unused_head = ctx->prev;
+ else {
+ next_ctx = SQL_DB_CACHE_CONTEXT(ctx->next);
+ next_ctx->prev = ctx->prev;
+ }
+ ctx->cache->unused_count--;
+}
+
+static void sql_db_cache_drop_oldest(struct sql_db_cache *cache)
+{
+ struct sql_db *db;
+ struct sql_db_cache_context *ctx;
+
+ while (cache->unused_count >= cache->max_unused_connections) {
+ db = cache->unused_tail;
+ ctx = SQL_DB_CACHE_CONTEXT(db);
+ sql_db_cache_unlink(ctx);
+
+ i_free(ctx->key);
+ ctx->orig_deinit(db);
+ }
+}
+
+struct sql_db *
+sql_db_cache_new(struct sql_db_cache *cache,
+ const char *db_driver, const char *connect_string)
+{
+ struct sql_db_cache_context *ctx;
+ struct sql_db *db;
+ char *key;
+
+ key = i_strdup_printf("%s\t%s", db_driver, connect_string);
+ db = hash_table_lookup(cache->dbs, key);
+ if (db != NULL) {
+ ctx = SQL_DB_CACHE_CONTEXT(db);
+ if (ctx->refcount == 0) {
+ sql_db_cache_unlink(ctx);
+ ctx->prev = ctx->next = NULL;
+ }
+ i_free(key);
+ } else {
+ sql_db_cache_drop_oldest(cache);
+
+ ctx = i_new(struct sql_db_cache_context, 1);
+ ctx->cache = cache;
+ ctx->key = key;
+
+ db = sql_init(db_driver, connect_string);
+ ctx->orig_deinit = db->v.deinit;
+ db->v.deinit = sql_db_cache_db_deinit;
+
+ MODULE_CONTEXT_SET(db, sql_db_cache_module, ctx);
+ hash_table_insert(cache->dbs, ctx->key, db);
+ }
+
+ ctx->refcount++;
+ return db;
+}
+
+struct sql_db_cache *sql_db_cache_init(unsigned int max_unused_connections)
+{
+ struct sql_db_cache *cache;
+
+ cache = i_new(struct sql_db_cache, 1);
+ cache->dbs = hash_table_create(default_pool, default_pool, 0, str_hash,
+ (hash_cmp_callback_t *)strcmp);
+ cache->max_unused_connections = max_unused_connections;
+ return cache;
+}
+
+void sql_db_cache_deinit(struct sql_db_cache **_cache)
+{
+ struct sql_db_cache *cache = *_cache;
+
+ *_cache = NULL;
+ hash_table_destroy(&cache->dbs);
+ i_free(cache);
+}
--- /dev/null
+#ifndef SQL_DB_CACHE_H
+#define SQL_DB_CACHE_H
+
+struct sql_db_cache;
+
+/* Like sql_init(), but use a connection pool. */
+struct sql_db *
+sql_db_cache_new(struct sql_db_cache *cache,
+ const char *db_driver, const char *connect_string);
+
+struct sql_db_cache *sql_db_cache_init(unsigned int max_unused_connections);
+void sql_db_cache_deinit(struct sql_db_cache **cache);
+
+#endif
+++ /dev/null
-/* Copyright (c) 2004-2010 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->next);
- 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;
- char *key;
-
- key = i_strdup_printf("%s\t%s", db_driver, connect_string);
- db = hash_table_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;
- }
- i_free(key);
- } else {
- sql_pool_drop_oldest(pool);
-
- ctx = i_new(struct sql_pool_context, 1);
- ctx->pool = pool;
- ctx->key = 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_table_insert(pool->dbs, ctx->key, db);
- }
-
- 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_table_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_table_destroy(&pool->dbs);
- i_free(pool);
-}
+++ /dev/null
-#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