bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file */
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen#include "lib.h"
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen#include "hash.h"
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen#include "llist.h"
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen#include "settings-parser.h"
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen#include "master-service-private.h"
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen#include "master-service-settings.h"
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen#include "master-service-settings-cache.h"
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen/* we start with just a guess. it's updated later. */
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen#define CACHE_INITIAL_ENTRY_POOL_SIZE (1024*16)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen#define CACHE_ADD_ENTRY_POOL_SIZE 1024
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainenstruct settings_entry {
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen struct settings_entry *prev, *next;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen pool_t pool;
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen const char *local_name;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen struct ip_addr local_ip;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen struct setting_parser_context *parser;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen};
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainenstruct master_service_settings_cache {
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen pool_t pool;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen struct master_service *service;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen const char *module;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen const char *service_name;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen size_t max_cache_size;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen /* global settings for this service (after they've been read) */
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen struct setting_parser_context *global_parser;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen /* cache for other settings (local_ip/local_name set) */
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen struct settings_entry *oldest, *newest;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen /* separate list for entries whose parser=global_parser */
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen struct settings_entry *oldest_global, *newest_global;
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen /* local_name, local_ip => struct settings_entry */
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen HASH_TABLE(char *, struct settings_entry *) local_name_hash;
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen HASH_TABLE(struct ip_addr *, struct settings_entry *) local_ip_hash;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen /* Initial size for new settings entry pools */
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen size_t approx_entry_pool_size;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen /* number of bytes malloced by cached settings entries
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen (doesn't count memory used by hash table or global sets) */
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen size_t cache_malloc_size;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool done_initial_lookup:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool service_uses_local:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool service_uses_remote:1;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen};
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainenstruct master_service_settings_cache *
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainenmaster_service_settings_cache_init(struct master_service *service,
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen const char *module, const char *service_name)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen{
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen struct master_service_settings_cache *cache;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen pool_t pool;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
1439ac8e653ae5566e6f27f789e7fcded5524a7fTimo Sirainen pool = pool_alloconly_create(MEMPOOL_GROWING"master service settings cache",
1439ac8e653ae5566e6f27f789e7fcded5524a7fTimo Sirainen 1024*12);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen cache = p_new(pool, struct master_service_settings_cache, 1);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen cache->pool = pool;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen cache->service = service;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen cache->module = p_strdup(pool, module);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen cache->service_name = p_strdup(pool, service_name);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen cache->max_cache_size = (size_t)-1;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen return cache;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen}
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainenvoid master_service_settings_cache_deinit(struct master_service_settings_cache **_cache)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen{
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen struct master_service_settings_cache *cache = *_cache;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen struct settings_entry *entry, *next;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
878a83a906e1be6354b563ead096955a22ad5fbeTimo Sirainen /* parsers need to be deinitialized, because they reference the pool */
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen for (entry = cache->oldest_global; entry != NULL; entry = next) {
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen next = entry->next;
325f97b5e691a3b4d4abaf8153d07f869e9ca6b2Timo Sirainen i_assert(entry->parser == cache->global_parser);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen pool_unref(&entry->pool);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen }
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen for (entry = cache->oldest; entry != NULL; entry = next) {
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen next = entry->next;
0b617d3e072174036da356c620c2b20563a2d87fTimo Sirainen i_assert(entry->parser != cache->global_parser);
878a83a906e1be6354b563ead096955a22ad5fbeTimo Sirainen settings_parser_deinit(&entry->parser);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen pool_unref(&entry->pool);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen }
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen if (hash_table_is_created(cache->local_name_hash))
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen hash_table_destroy(&cache->local_name_hash);
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen if (hash_table_is_created(cache->local_ip_hash))
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen hash_table_destroy(&cache->local_ip_hash);
878a83a906e1be6354b563ead096955a22ad5fbeTimo Sirainen if (cache->global_parser != NULL)
878a83a906e1be6354b563ead096955a22ad5fbeTimo Sirainen settings_parser_deinit(&cache->global_parser);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen pool_unref(&cache->pool);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen}
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainenstatic bool
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainencache_can_return_global(struct master_service_settings_cache *cache,
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen const struct master_service_settings_input *input)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen{
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (cache->service_uses_local) {
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen if (input->local_name != NULL || input->local_ip.family != 0)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen return FALSE;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen }
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (cache->service_uses_remote) {
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen if (input->remote_ip.family != 0)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen return FALSE;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen }
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen return TRUE;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen}
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainenstatic bool
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainencache_find(struct master_service_settings_cache *cache,
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen const struct master_service_settings_input *input,
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen const struct setting_parser_context **parser_r)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen{
eafe35b9b0e3fd12bf6e9ccec4b21df8d946280dTimo Sirainen struct settings_entry *entry = NULL;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (!cache->done_initial_lookup)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen return FALSE;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (cache_can_return_global(cache, input)) {
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (cache->global_parser != NULL) {
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen *parser_r = cache->global_parser;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen return TRUE;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen }
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen return FALSE;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen }
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (cache->service_uses_remote)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen return FALSE;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen /* see if we have it already in cache. if local_name is specified,
eafe35b9b0e3fd12bf6e9ccec4b21df8d946280dTimo Sirainen don't even try to use local_ip (even though we have it), because
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen there may be different settings specifically for local_name */
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen if (input->local_name != NULL) {
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen if (hash_table_is_created(cache->local_name_hash)) {
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen entry = hash_table_lookup(cache->local_name_hash,
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen input->local_name);
eafe35b9b0e3fd12bf6e9ccec4b21df8d946280dTimo Sirainen }
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen } else if (hash_table_is_created(cache->local_ip_hash) &&
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen input->local_ip.family != 0) {
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen entry = hash_table_lookup(cache->local_ip_hash,
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen &input->local_ip);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen }
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (entry != NULL) {
0b617d3e072174036da356c620c2b20563a2d87fTimo Sirainen if (entry->parser != cache->global_parser) {
0b617d3e072174036da356c620c2b20563a2d87fTimo Sirainen DLLIST2_REMOVE(&cache->oldest, &cache->newest, entry);
0b617d3e072174036da356c620c2b20563a2d87fTimo Sirainen DLLIST2_APPEND(&cache->oldest, &cache->newest, entry);
0b617d3e072174036da356c620c2b20563a2d87fTimo Sirainen }
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen *parser_r = entry->parser;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen return TRUE;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen }
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen return FALSE;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen}
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainenstatic void
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainensetting_entry_detach(struct master_service_settings_cache *cache,
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen struct settings_entry *entry)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen{
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen DLLIST2_REMOVE(&cache->oldest, &cache->newest, entry);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen cache->cache_malloc_size -=
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen pool_alloconly_get_total_alloc_size(entry->pool);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen if (entry->local_name != NULL)
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen hash_table_remove(cache->local_name_hash, entry->local_name);
788a914ed09ca9a6605d66ef6707c3ca1175c153Timo Sirainen else if (entry->local_ip.family != 0)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen hash_table_remove(cache->local_ip_hash, &entry->local_ip);
878a83a906e1be6354b563ead096955a22ad5fbeTimo Sirainen settings_parser_deinit(&entry->parser);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen}
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
f098053b982e7ac1385ef7de97df9c06eb3d2ee0Timo Sirainenstatic struct setting_parser_context *
f098053b982e7ac1385ef7de97df9c06eb3d2ee0Timo Sirainencache_add(struct master_service_settings_cache *cache,
f098053b982e7ac1385ef7de97df9c06eb3d2ee0Timo Sirainen const struct master_service_settings_input *input,
f098053b982e7ac1385ef7de97df9c06eb3d2ee0Timo Sirainen const struct master_service_settings_output *output,
f098053b982e7ac1385ef7de97df9c06eb3d2ee0Timo Sirainen struct setting_parser_context *parser)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen{
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen struct settings_entry *entry;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen pool_t pool;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen size_t pool_size;
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen char *entry_local_name;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (!output->used_local && !output->used_remote) {
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen /* these are same as global settings */
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (cache->global_parser == NULL) {
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen cache->global_parser =
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen settings_parser_dup(parser, cache->pool);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen }
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen }
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (cache->service_uses_remote) {
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen /* for now we don't try to handle caching remote IPs */
f098053b982e7ac1385ef7de97df9c06eb3d2ee0Timo Sirainen return parser;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen }
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen if (input->local_name == NULL && input->local_ip.family == 0)
f098053b982e7ac1385ef7de97df9c06eb3d2ee0Timo Sirainen return parser;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (!output->used_local) {
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen /* use global settings, but add local_ip/host to hash tables
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen so we'll find them */
4af888b784e6b1a9d6ea8a624d6c6d2fc07f5642Timo Sirainen pool = pool_alloconly_create("settings global entry", 256);
2df335f17abb2964544dda7b88c321381a35ea2eTimo Sirainen } else if (cache->cache_malloc_size >= cache->max_cache_size) {
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen /* free the oldest and reuse its pool */
dbeedaef53c23e765126c875e1100729e52b5b0dTimo Sirainen pool = cache->oldest->pool;
dbeedaef53c23e765126c875e1100729e52b5b0dTimo Sirainen setting_entry_detach(cache, cache->oldest);
dbeedaef53c23e765126c875e1100729e52b5b0dTimo Sirainen p_clear(pool); /* note: frees also entry */
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen } else {
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen pool_size = cache->approx_entry_pool_size != 0 ?
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen cache->approx_entry_pool_size :
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen CACHE_INITIAL_ENTRY_POOL_SIZE;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen pool = pool_alloconly_create("settings entry", pool_size);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen }
dbeedaef53c23e765126c875e1100729e52b5b0dTimo Sirainen entry = p_new(pool, struct settings_entry, 1);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen entry->pool = pool;
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen entry_local_name = p_strdup(pool, input->local_name);
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen entry->local_name = entry_local_name;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen entry->local_ip = input->local_ip;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (!output->used_local) {
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen entry->parser = cache->global_parser;
dbeedaef53c23e765126c875e1100729e52b5b0dTimo Sirainen DLLIST2_APPEND(&cache->oldest_global, &cache->newest_global,
dbeedaef53c23e765126c875e1100729e52b5b0dTimo Sirainen entry);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen } else {
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen entry->parser = settings_parser_dup(parser, entry->pool);
dbeedaef53c23e765126c875e1100729e52b5b0dTimo Sirainen DLLIST2_APPEND(&cache->oldest, &cache->newest, entry);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen pool_size = pool_alloconly_get_total_used_size(pool);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (pool_size > cache->approx_entry_pool_size) {
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen cache->approx_entry_pool_size = pool_size +
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen CACHE_ADD_ENTRY_POOL_SIZE;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen }
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen }
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen cache->cache_malloc_size += pool_alloconly_get_total_alloc_size(pool);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen if (input->local_name != NULL) {
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen if (!hash_table_is_created(cache->local_name_hash)) {
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen hash_table_create(&cache->local_name_hash,
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen cache->pool, 0, str_hash, strcmp);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen }
788a914ed09ca9a6605d66ef6707c3ca1175c153Timo Sirainen i_assert(hash_table_lookup(cache->local_name_hash,
788a914ed09ca9a6605d66ef6707c3ca1175c153Timo Sirainen entry_local_name) == NULL);
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen hash_table_insert(cache->local_name_hash,
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen entry_local_name, entry);
788a914ed09ca9a6605d66ef6707c3ca1175c153Timo Sirainen } else if (input->local_ip.family != 0) {
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen if (!hash_table_is_created(cache->local_ip_hash)) {
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen hash_table_create(&cache->local_ip_hash, cache->pool, 0,
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen net_ip_hash, net_ip_cmp);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen }
788a914ed09ca9a6605d66ef6707c3ca1175c153Timo Sirainen i_assert(hash_table_lookup(cache->local_ip_hash,
788a914ed09ca9a6605d66ef6707c3ca1175c153Timo Sirainen &entry->local_ip) == NULL);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen hash_table_insert(cache->local_ip_hash,
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen &entry->local_ip, entry);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen }
f098053b982e7ac1385ef7de97df9c06eb3d2ee0Timo Sirainen return entry->parser;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen}
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainenint master_service_settings_cache_read(struct master_service_settings_cache *cache,
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen const struct master_service_settings_input *input,
9b78c0d5e13141f4df6c6e483f854e5acb861288Timo Sirainen const struct dynamic_settings_parser *dyn_parsers,
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen const struct setting_parser_context **parser_r,
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen const char **error_r)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen{
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen struct master_service_settings_output output;
9b78c0d5e13141f4df6c6e483f854e5acb861288Timo Sirainen struct master_service_settings_input new_input;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen const struct master_service_settings *set;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
84fd5bbb0d852ff0ead6ca9c49d3e1a107fb5826Timo Sirainen i_assert(null_strcmp(input->module, cache->module) == 0);
84fd5bbb0d852ff0ead6ca9c49d3e1a107fb5826Timo Sirainen i_assert(null_strcmp(input->service, cache->service_name) == 0);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (cache_find(cache, input, parser_r))
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen return 0;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
9b78c0d5e13141f4df6c6e483f854e5acb861288Timo Sirainen new_input = *input;
9b78c0d5e13141f4df6c6e483f854e5acb861288Timo Sirainen if (dyn_parsers != NULL) {
9b78c0d5e13141f4df6c6e483f854e5acb861288Timo Sirainen settings_parser_dyn_update(cache->pool, &new_input.roots,
9b78c0d5e13141f4df6c6e483f854e5acb861288Timo Sirainen dyn_parsers);
9b78c0d5e13141f4df6c6e483f854e5acb861288Timo Sirainen }
9b78c0d5e13141f4df6c6e483f854e5acb861288Timo Sirainen if (master_service_settings_read(cache->service, &new_input,
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen &output, error_r) < 0)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen return -1;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (!cache->done_initial_lookup) {
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen cache->done_initial_lookup = TRUE;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen cache->service_uses_local = output.service_uses_local;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen cache->service_uses_remote = output.service_uses_remote;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen set = master_service_settings_get(cache->service);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen cache->max_cache_size = set->config_cache_size;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen }
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (output.used_local && !cache->service_uses_local) {
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen *error_r = "BUG: config unexpectedly returned local settings";
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen return -1;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen }
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (output.used_remote && !cache->service_uses_remote) {
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen *error_r = "BUG: config unexpectedly returned remote settings";
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen return -1;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen }
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
f098053b982e7ac1385ef7de97df9c06eb3d2ee0Timo Sirainen *parser_r = cache_add(cache, &new_input, &output,
f098053b982e7ac1385ef7de97df9c06eb3d2ee0Timo Sirainen cache->service->set_parser);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen return 0;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen}