From: Timo Sirainen Date: Tue, 29 Nov 2022 16:59:53 +0000 (+0200) Subject: lib-master: Remove master-service-settings-cache API X-Git-Tag: 2.4.0~3086 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0f0d8d8091b1d5d67fb542bd60b90feb52040f41;p=thirdparty%2Fdovecot%2Fcore.git lib-master: Remove master-service-settings-cache API --- diff --git a/src/lib-master/Makefile.am b/src/lib-master/Makefile.am index d7d75c5c09..20a7f052aa 100644 --- a/src/lib-master/Makefile.am +++ b/src/lib-master/Makefile.am @@ -22,7 +22,6 @@ libmaster_la_SOURCES = \ master-service.c \ master-service-haproxy.c \ master-service-settings.c \ - master-service-settings-cache.c \ master-service-ssl.c \ master-service-ssl-settings.c \ stats-client.c \ @@ -37,7 +36,6 @@ headers = \ master-service.h \ master-service-private.h \ master-service-settings.h \ - master-service-settings-cache.h \ master-service-ssl.h \ master-service-ssl-settings.h \ service-settings.h \ @@ -48,7 +46,6 @@ pkginc_libdir=$(pkgincludedir) pkginc_lib_HEADERS = $(headers) test_programs = \ - test-master-service-settings-cache \ test-event-stats noinst_PROGRAMS = $(test_programs) @@ -63,10 +60,6 @@ test_event_stats_libs = \ test_deps = $(noinst_LTLIBRARIES) $(test_libs) -test_master_service_settings_cache_SOURCES = test-master-service-settings-cache.c -test_master_service_settings_cache_LDADD = master-service-settings-cache.lo ../lib-settings/libsettings.la $(test_libs) -test_master_service_settings_cache_DEPENDENCIES = $(test_deps) ../lib-settings/libsettings.la - test_event_stats_SOURCES = test-event-stats.c test_event_stats_LDADD = $(test_event_stats_libs) $(test_libs) test_event_stats_DEPENDENCIES = $(test_deps) diff --git a/src/lib-master/master-service-settings-cache.c b/src/lib-master/master-service-settings-cache.c deleted file mode 100644 index c63e30abd8..0000000000 --- a/src/lib-master/master-service-settings-cache.c +++ /dev/null @@ -1,406 +0,0 @@ -/* Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "wildcard-match.h" -#include "hash.h" -#include "llist.h" -#include "settings-parser.h" -#include "dns-util.h" -#include "strescape.h" -#include "master-service-private.h" -#include "master-service-settings.h" -#include "master-service-settings-cache.h" - -/* we start with just a guess. it's updated later. */ -#define CACHE_INITIAL_ENTRY_POOL_SIZE (1024*16) -#define CACHE_ADD_ENTRY_POOL_SIZE 1024 - -struct config_filter { - struct config_filter *prev, *next; - - const char *local_name; - struct ip_addr local_ip, remote_ip; - unsigned int local_bits, remote_bits; -}; - -struct settings_entry { - struct settings_entry *prev, *next; - - pool_t pool; - const char *local_name; - struct ip_addr local_ip; - - struct setting_parser_context *parser; -}; - -struct master_service_settings_cache { - pool_t pool; - - struct master_service *service; - const char *module; - const char *service_name; - size_t max_cache_size; - - /* global settings for this service (after they've been read) */ - struct setting_parser_context *global_parser; - - /* cache for other settings (local_ip/local_name set) */ - struct settings_entry *oldest, *newest; - /* separate list for entries whose parser=global_parser */ - struct settings_entry *oldest_global, *newest_global; - /* local_name, local_ip => struct settings_entry */ - HASH_TABLE(char *, struct settings_entry *) local_name_hash; - HASH_TABLE(struct ip_addr *, struct settings_entry *) local_ip_hash; - - struct config_filter *filters; - - /* Initial size for new settings entry pools */ - size_t approx_entry_pool_size; - /* number of bytes malloced by cached settings entries - (doesn't count memory used by hash table or global sets) */ - size_t cache_malloc_size; - - bool done_initial_lookup:1; - bool service_uses_local:1; - bool service_uses_remote:1; -}; - -struct master_service_settings_cache * -master_service_settings_cache_init(struct master_service *service, - const char *module, const char *service_name) -{ - struct master_service_settings_cache *cache; - pool_t pool; - - pool = pool_alloconly_create(MEMPOOL_GROWING"master service settings cache", - 1024*12); - cache = p_new(pool, struct master_service_settings_cache, 1); - cache->pool = pool; - cache->service = service; - cache->module = p_strdup(pool, module); - cache->service_name = p_strdup(pool, service_name); - cache->max_cache_size = SIZE_MAX; - return cache; -} - -int master_service_settings_cache_init_filter(struct master_service_settings_cache *cache) -{ - const char *const *filters; - const char *value, *error; - - if (cache->filters != NULL) - return 0; - if (master_service_settings_get_filters(cache->service, &filters, &error) < 0) { - e_error(cache->service->event, - "master-service: cannot get filters: %s", error); - return -1; - } - - /* parse filters */ - while(*filters != NULL) { - const char *const *keys = t_strsplit_tabescaped(*filters); - struct config_filter *filter = - p_new(cache->pool, struct config_filter, 1); - while(*keys != NULL) { - if (str_begins(*keys, "local-net=", &value)) { - (void)net_parse_range(value, - &filter->local_ip, &filter->local_bits); - } else if (str_begins(*keys, "remote-net=", &value)) { - (void)net_parse_range(value, - &filter->remote_ip, &filter->remote_bits); - } else if (str_begins(*keys, "local-name=", &value)) { - filter->local_name = p_strdup(cache->pool, value); - } - keys++; - } - DLLIST_PREPEND(&cache->filters, filter); - filters++; - } - return 0; -} - -static bool -match_local_name(const char *local_name, - const char *filter_local_name) -{ - /* Handle multiple names separated by spaces in local_name - * Ex: local_name "mail.domain.tld domain.tld mx.domain.tld" { ... } */ - const char *ptr; - while((ptr = strchr(filter_local_name, ' ')) != NULL) { - if (dns_match_wildcard(local_name, - t_strdup_until(filter_local_name, ptr)) == 0) - return TRUE; - filter_local_name = ptr+1; - } - return dns_match_wildcard(local_name, filter_local_name) == 0; -} - -/* Remove any elements which there is no filter for */ -static void -master_service_settings_cache_fix_input(struct master_service_settings_cache *cache, - const struct master_service_settings_input *input, - struct master_service_settings_input *new_input) -{ - bool found_lip, found_rip, found_local_name; - - found_lip = found_rip = found_local_name = FALSE; - - struct config_filter *filter = cache->filters; - while(filter != NULL) { - if (filter->local_bits > 0 && - net_is_in_network(&input->local_ip, &filter->local_ip, - filter->local_bits)) - found_lip = TRUE; - if (filter->remote_bits > 0 && - net_is_in_network(&input->remote_ip, &filter->remote_ip, - filter->remote_bits)) - found_rip = TRUE; - if (input->local_name != NULL && filter->local_name != NULL && - match_local_name(input->local_name, filter->local_name)) - found_local_name = TRUE; - filter = filter->next; - }; - - *new_input = *input; - - if (!found_lip) - i_zero(&new_input->local_ip); - if (!found_rip) - i_zero(&new_input->remote_ip); - if (!found_local_name) - new_input->local_name = NULL; -} - - -void master_service_settings_cache_deinit(struct master_service_settings_cache **_cache) -{ - struct master_service_settings_cache *cache = *_cache; - struct settings_entry *entry, *next; - - /* parsers need to be deinitialized, because they reference the pool */ - for (entry = cache->oldest_global; entry != NULL; entry = next) { - next = entry->next; - i_assert(entry->parser == cache->global_parser); - pool_unref(&entry->pool); - } - for (entry = cache->oldest; entry != NULL; entry = next) { - next = entry->next; - i_assert(entry->parser != cache->global_parser); - settings_parser_unref(&entry->parser); - pool_unref(&entry->pool); - } - hash_table_destroy(&cache->local_name_hash); - hash_table_destroy(&cache->local_ip_hash); - if (cache->global_parser != NULL) - settings_parser_unref(&cache->global_parser); - pool_unref(&cache->pool); -} - -static bool -cache_can_return_global(struct master_service_settings_cache *cache, - const struct master_service_settings_input *input) -{ - if (cache->service_uses_local) { - if (input->local_name != NULL || input->local_ip.family != 0) - return FALSE; - } - if (cache->service_uses_remote) { - if (input->remote_ip.family != 0) - return FALSE; - } - return TRUE; -} - -static bool -cache_find(struct master_service_settings_cache *cache, - const struct master_service_settings_input *input, - struct setting_parser_context **parser_r) -{ - struct settings_entry *entry = NULL; - - if (!cache->done_initial_lookup) - return FALSE; - - if (cache_can_return_global(cache, input)) { - if (cache->global_parser != NULL) { - *parser_r = cache->global_parser; - return TRUE; - } - return FALSE; - } - - if (cache->service_uses_remote) - return FALSE; - - /* see if we have it already in cache. if local_name is specified, - don't even try to use local_ip (even though we have it), because - there may be different settings specifically for local_name */ - if (input->local_name != NULL) { - if (hash_table_is_created(cache->local_name_hash)) { - entry = hash_table_lookup(cache->local_name_hash, - input->local_name); - } - } else if (hash_table_is_created(cache->local_ip_hash) && - input->local_ip.family != 0) { - entry = hash_table_lookup(cache->local_ip_hash, - &input->local_ip); - } - - if (entry != NULL) { - if (entry->parser != cache->global_parser) { - DLLIST2_REMOVE(&cache->oldest, &cache->newest, entry); - DLLIST2_APPEND(&cache->oldest, &cache->newest, entry); - } - *parser_r = entry->parser; - return TRUE; - } - return FALSE; -} - -static void -setting_entry_detach(struct master_service_settings_cache *cache, - struct settings_entry *entry) -{ - DLLIST2_REMOVE(&cache->oldest, &cache->newest, entry); - cache->cache_malloc_size -= - pool_alloconly_get_total_alloc_size(entry->pool); - - if (entry->local_name != NULL) - hash_table_remove(cache->local_name_hash, entry->local_name); - else if (entry->local_ip.family != 0) - hash_table_remove(cache->local_ip_hash, &entry->local_ip); - settings_parser_unref(&entry->parser); -} - -static struct setting_parser_context * -cache_add(struct master_service_settings_cache *cache, - const struct master_service_settings_input *input, - const struct master_service_settings_output *output, - struct setting_parser_context *parser) -{ - struct settings_entry *entry; - pool_t pool; - size_t pool_size; - char *entry_local_name; - - if (!output->used_local && !output->used_remote) { - /* these are same as global settings */ - if (cache->global_parser == NULL) { - cache->global_parser = - settings_parser_dup(parser, cache->pool); - } - } - if (cache->service_uses_remote) { - /* for now we don't try to handle caching remote IPs */ - return parser; - } - - if (input->local_name == NULL && input->local_ip.family == 0) - return parser; - - if (!output->used_local) { - /* use global settings, but add local_ip/host to hash tables - so we'll find them */ - pool = pool_alloconly_create("settings global entry", 256); - } else if (cache->cache_malloc_size >= cache->max_cache_size) { - /* free the oldest and reuse its pool */ - pool = cache->oldest->pool; - setting_entry_detach(cache, cache->oldest); - p_clear(pool); /* note: frees also entry */ - } else { - pool_size = cache->approx_entry_pool_size != 0 ? - cache->approx_entry_pool_size : - CACHE_INITIAL_ENTRY_POOL_SIZE; - pool = pool_alloconly_create("settings entry", pool_size); - } - entry = p_new(pool, struct settings_entry, 1); - entry->pool = pool; - entry_local_name = p_strdup(pool, input->local_name); - entry->local_name = entry_local_name; - entry->local_ip = input->local_ip; - if (!output->used_local) { - entry->parser = cache->global_parser; - DLLIST2_APPEND(&cache->oldest_global, &cache->newest_global, - entry); - } else { - entry->parser = settings_parser_dup(parser, entry->pool); - DLLIST2_APPEND(&cache->oldest, &cache->newest, entry); - - pool_size = pool_alloconly_get_total_used_size(pool); - if (pool_size > cache->approx_entry_pool_size) { - cache->approx_entry_pool_size = pool_size + - CACHE_ADD_ENTRY_POOL_SIZE; - } - } - cache->cache_malloc_size += pool_alloconly_get_total_alloc_size(pool); - - if (input->local_name != NULL) { - if (!hash_table_is_created(cache->local_name_hash)) { - hash_table_create(&cache->local_name_hash, - cache->pool, 0, str_hash, strcmp); - } - i_assert(hash_table_lookup(cache->local_name_hash, - entry_local_name) == NULL); - hash_table_insert(cache->local_name_hash, - entry_local_name, entry); - } else if (input->local_ip.family != 0) { - if (!hash_table_is_created(cache->local_ip_hash)) { - hash_table_create(&cache->local_ip_hash, cache->pool, 0, - net_ip_hash, net_ip_cmp); - } - i_assert(hash_table_lookup(cache->local_ip_hash, - &entry->local_ip) == NULL); - hash_table_insert(cache->local_ip_hash, - &entry->local_ip, entry); - } - return entry->parser; -} - -int master_service_settings_cache_read(struct master_service_settings_cache *cache, - const struct master_service_settings_input *input, - struct setting_parser_context **parser_r, - const char **error_r) -{ - struct master_service_settings_output output; - struct master_service_settings_input new_input; - const struct master_service_settings *set; - - i_assert(null_strcmp(input->module, cache->module) == 0); - i_assert(null_strcmp(input->service, cache->service_name) == 0); - - if (cache_find(cache, input, parser_r)) - return 0; - - new_input = *input; - if (cache->filters != NULL) { - master_service_settings_cache_fix_input(cache, input, &new_input); - if (cache_find(cache, &new_input, parser_r)) - return 0; - } - - if (master_service_settings_read(cache->service, &new_input, - &output, error_r) < 0) - return -1; - - if (!cache->done_initial_lookup) { - cache->done_initial_lookup = TRUE; - cache->service_uses_local = output.service_uses_local; - cache->service_uses_remote = output.service_uses_remote; - - set = master_service_settings_get(cache->service); - cache->max_cache_size = set->config_cache_size; - } - - if (output.used_local && !cache->service_uses_local) { - *error_r = "BUG: config unexpectedly returned local settings"; - return -1; - } - if (output.used_remote && !cache->service_uses_remote) { - *error_r = "BUG: config unexpectedly returned remote settings"; - return -1; - } - - *parser_r = cache_add(cache, &new_input, &output, - cache->service->set_parser); - return 0; -} diff --git a/src/lib-master/master-service-settings-cache.h b/src/lib-master/master-service-settings-cache.h deleted file mode 100644 index 973d1d24cb..0000000000 --- a/src/lib-master/master-service-settings-cache.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef MASTER_SERVICE_SETTINGS_CACHE_H -#define MASTER_SERVICE_SETTINGS_CACHE_H - -struct master_service_settings_cache * -master_service_settings_cache_init(struct master_service *service, - const char *module, - const char *service_name); -void master_service_settings_cache_deinit(struct master_service_settings_cache **cache); -int master_service_settings_cache_init_filter(struct master_service_settings_cache *cache); -int master_service_settings_cache_read(struct master_service_settings_cache *cache, - const struct master_service_settings_input *input, - struct setting_parser_context **parser_r, - const char **error_r) ATTR_NULL(3); - -#endif diff --git a/src/lib-master/test-master-service-settings-cache.c b/src/lib-master/test-master-service-settings-cache.c deleted file mode 100644 index 0b988acc1c..0000000000 --- a/src/lib-master/test-master-service-settings-cache.c +++ /dev/null @@ -1,125 +0,0 @@ -/* Copyright (c) 2014-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "test-common.h" -#include "settings-parser.h" -#include "master-service-private.h" -#include "master-service-settings.h" -#include "master-service-settings-cache.h" - - -struct master_service *master_service; - -static struct master_service test_master_service; -static struct master_service_settings set; -static struct master_service_settings_input input; -static struct master_service_settings_output output; -static struct master_service_settings_cache *cache; - -struct test_service_settings { - const char *foo; -}; - -#undef DEF -#define DEF(type, name) \ - SETTING_DEFINE_STRUCT_##type(#name, name, struct test_service_settings) - -static const struct setting_define test_setting_defines[] = { - DEF(STR, foo), - SETTING_DEFINE_LIST_END -}; - -static const struct test_service_settings test_default_settings = { - .foo = "" -}; - -static const struct setting_parser_info test_setting_parser_info = { - .module_name = "module", - .defines = test_setting_defines, - .defaults = &test_default_settings, - - .type_offset = SIZE_MAX, - .struct_size = sizeof(struct test_service_settings), - - .parent_offset = SIZE_MAX -}; - -int master_service_settings_read(struct master_service *service ATTR_UNUSED, - const struct master_service_settings_input *input ATTR_UNUSED, - struct master_service_settings_output *output_r, - const char **error_r ATTR_UNUSED) -{ - *output_r = output; - return 0; -} - -int master_service_settings_get_filters(struct master_service *service ATTR_UNUSED, - const char *const **filters ATTR_UNUSED, - const char **error_r ATTR_UNUSED) -{ - return -1; -} - - -const struct master_service_settings * -master_service_settings_get(struct master_service *service ATTR_UNUSED) -{ - return &set; -} - -static void test_master_service_settings_cache_once(void) -{ - struct setting_parser_context *parser; - const char *error; - - output.used_local = output.service_uses_local && i_rand_limit(2) != 0; - if (output.used_local) { - input.local_ip.family = AF_INET; - input.local_ip.u.ip4.s_addr = i_rand_minmax(100, 199); - } - output.used_remote = output.service_uses_remote && i_rand_limit(2) != 0; - if (output.used_remote) { - input.remote_ip.family = AF_INET; - input.remote_ip.u.ip4.s_addr = i_rand_minmax(100, 199); - } - test_assert(master_service_settings_cache_read(cache, &input, &parser, &error) == 0); -} - -static void test_master_service_settings_cache(void) -{ - int i, j; - - for (i = 1; i < 4; i++) { - cache = master_service_settings_cache_init(master_service, - "module", "service_name"); - output.service_uses_local = (i & 1) != 0; - output.service_uses_remote = (i & 2) != 0; - for (j = 0; j < 1000; j++) - test_master_service_settings_cache_once(); - master_service_settings_cache_deinit(&cache); - } -} - -int main(void) -{ - static void (*const test_functions[])(void) = { - test_master_service_settings_cache, - NULL - }; - pool_t pool; - int ret; - - i_zero(&input); - input.module = "module"; - input.service = "service_name"; - - set.config_cache_size = 1024*4; - pool = pool_alloconly_create("set pool", 1024); - test_master_service.set_parser = - settings_parser_init(pool, &test_setting_parser_info, 0); - master_service = &test_master_service; - ret = test_run(test_functions); - settings_parser_unref(&test_master_service.set_parser); - pool_unref(&pool); - return ret; -}