]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
dict-sql: Cache reading settings files.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 11 May 2016 20:58:59 +0000 (16:58 -0400)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 11 May 2016 20:58:59 +0000 (16:58 -0400)
The settings were read for every dict init, which was done for every new
dict connection. This was using a lot of CPU. There are usually only a
couple dict-sql settings files, so we cache all of the ones we read.

src/lib-dict/dict-sql-settings.c
src/lib-dict/dict-sql-settings.h
src/lib-dict/dict-sql.c

index 8e5614633f810ce921b2059fc7d29f35de7116ef..5b090061edd1860d82fbe88950dfaa8eeb200204 100644 (file)
@@ -3,6 +3,7 @@
 #include "lib.h"
 #include "array.h"
 #include "str.h"
+#include "hash.h"
 #include "settings.h"
 #include "dict-sql-settings.h"
 
@@ -42,6 +43,14 @@ static const struct setting_def dict_sql_map_setting_defs[] = {
        { 0, NULL, 0 }
 };
 
+struct dict_sql_settings_cache {
+       pool_t pool;
+       const char *path;
+       struct dict_sql_settings *set;
+};
+
+static HASH_TABLE(const char *, struct dict_sql_settings_cache *) dict_sql_settings_cache;
+
 static const char *pattern_read_name(const char **pattern)
 {
        const char *p = *pattern, *name;
@@ -235,9 +244,20 @@ parse_section(const char *type, const char *name ATTR_UNUSED,
 }
 
 struct dict_sql_settings *
-dict_sql_settings_read(pool_t pool, const char *path, const char **error_r)
+dict_sql_settings_read(const char *path, const char **error_r)
 {
        struct setting_parser_ctx ctx;
+       struct dict_sql_settings_cache *cache;
+       pool_t pool = pool_alloconly_create("dict sql settings", 1024);
+
+       if (!hash_table_is_created(dict_sql_settings_cache)) {
+               hash_table_create(&dict_sql_settings_cache, default_pool, 0,
+                                 str_hash, strcmp);
+       }
+
+       cache = hash_table_lookup(dict_sql_settings_cache, path);
+       if (cache != NULL)
+               return cache->set;
 
        memset(&ctx, 0, sizeof(ctx));
        ctx.pool = pool;
@@ -246,14 +266,39 @@ dict_sql_settings_read(pool_t pool, const char *path, const char **error_r)
        p_array_init(&ctx.set->maps, pool, 8);
 
        if (!settings_read(path, NULL, parse_setting, parse_section,
-                          &ctx, error_r))
+                          &ctx, error_r)) {
+               pool_unref(&pool);
                return NULL;
+       }
 
        if (ctx.set->connect == NULL) {
                *error_r = t_strdup_printf("Error in configuration file %s: "
                                           "Missing connect setting", path);
+               pool_unref(&pool);
                return NULL;
        }
 
+       cache = p_new(pool, struct dict_sql_settings_cache, 1);
+       cache->pool = pool;
+       cache->path = p_strdup(pool, path);
+       cache->set = ctx.set;
+
+       hash_table_insert(dict_sql_settings_cache, cache->path, cache);
        return ctx.set;
 }
+
+void dict_sql_settings_deinit(void)
+{
+       struct hash_iterate_context *iter;
+       struct dict_sql_settings_cache *cache;
+       const char *key;
+
+       if (!hash_table_is_created(dict_sql_settings_cache))
+               return;
+
+       iter = hash_table_iterate_init(dict_sql_settings_cache);
+       while (hash_table_iterate(iter, dict_sql_settings_cache, &key, &cache))
+               pool_unref(&cache->pool);
+       hash_table_iterate_deinit(&iter);
+       hash_table_destroy(&dict_sql_settings_cache);
+}
index 62aff2ec17f55dce8adf94776959ddd0d315f3f3..dd9537237bbf29eb119edbfc1e016fbf33b5becd 100644 (file)
@@ -33,6 +33,8 @@ struct dict_sql_settings {
 };
 
 struct dict_sql_settings *
-dict_sql_settings_read(pool_t pool, const char *path, const char **error_r);
+dict_sql_settings_read(const char *path, const char **error_r);
+
+void dict_sql_settings_deinit(void);
 
 #endif
index 840e35492fa7369d3170dff3d63aa076aee678d6..4798facb119b0e85e0ba19a767f217120bd6e07f 100644 (file)
@@ -88,7 +88,7 @@ sql_dict_init(struct dict *driver, const char *uri,
        dict->pool = pool;
        dict->dict = *driver;
        dict->username = p_strdup(pool, set->username);
-       dict->set = dict_sql_settings_read(pool, uri, error_r);
+       dict->set = dict_sql_settings_read(uri, error_r);
        if (dict->set == NULL) {
                pool_unref(&pool);
                return -1;
@@ -1266,4 +1266,5 @@ void dict_sql_unregister(void)
                dict_driver_unregister(&dict_sql_drivers[i]);
        i_free(dict_sql_drivers);
        sql_db_cache_deinit(&dict_sql_db_cache);
+       dict_sql_settings_deinit();
 }