38
38
/* separate list for entries whose parser=global_parser */
39
39
struct settings_entry *oldest_global, *newest_global;
40
40
/* local_name, local_ip => struct settings_entry */
41
struct hash_table *local_name_hash;
42
struct hash_table *local_ip_hash;
41
HASH_TABLE(char *, struct settings_entry *) local_name_hash;
42
HASH_TABLE(struct ip_addr *, struct settings_entry *) local_ip_hash;
44
44
/* Initial size for new settings entry pools */
45
45
size_t approx_entry_pool_size;
59
59
struct master_service_settings_cache *cache;
62
pool = pool_alloconly_create("master service settings cache", 1024*32);
62
pool = pool_alloconly_create(MEMPOOL_GROWING"master service settings cache",
63
64
cache = p_new(pool, struct master_service_settings_cache, 1);
64
65
cache->pool = pool;
65
66
cache->service = service;
83
84
for (entry = cache->oldest; entry != NULL; entry = next) {
84
85
next = entry->next;
86
i_assert(entry->parser != cache->global_parser);
85
87
settings_parser_deinit(&entry->parser);
86
88
pool_unref(&entry->pool);
88
if (cache->local_name_hash != NULL)
90
if (hash_table_is_created(cache->local_name_hash))
89
91
hash_table_destroy(&cache->local_name_hash);
90
if (cache->local_ip_hash != NULL)
92
if (hash_table_is_created(cache->local_ip_hash))
91
93
hash_table_destroy(&cache->local_ip_hash);
92
94
if (cache->global_parser != NULL)
93
95
settings_parser_deinit(&cache->global_parser);
134
136
don't even try to use local_ip (even though we have it), because
135
137
there may be different settings specifically for local_name */
136
138
if (input->local_name != NULL) {
137
if (cache->local_name_hash != NULL) {
139
if (hash_table_is_created(cache->local_name_hash)) {
138
140
entry = hash_table_lookup(cache->local_name_hash,
139
141
input->local_name);
141
} else if (cache->local_ip_hash != NULL &&
143
} else if (hash_table_is_created(cache->local_ip_hash) &&
142
144
input->local_ip.family != 0) {
143
145
entry = hash_table_lookup(cache->local_ip_hash,
144
146
&input->local_ip);
147
149
if (entry != NULL) {
150
if (entry->parser != cache->global_parser) {
151
DLLIST2_REMOVE(&cache->oldest, &cache->newest, entry);
152
DLLIST2_APPEND(&cache->oldest, &cache->newest, entry);
148
154
*parser_r = entry->parser;
166
172
settings_parser_deinit(&entry->parser);
169
static void cache_add(struct master_service_settings_cache *cache,
170
const struct master_service_settings_input *input,
171
const struct master_service_settings_output *output,
172
struct setting_parser_context *parser)
175
static struct setting_parser_context *
176
cache_add(struct master_service_settings_cache *cache,
177
const struct master_service_settings_input *input,
178
const struct master_service_settings_output *output,
179
struct setting_parser_context *parser)
174
181
struct settings_entry *entry;
186
193
if (cache->service_uses_remote) {
187
194
/* for now we don't try to handle caching remote IPs */
191
198
if (input->local_name == NULL && input->local_ip.family == 0)
194
201
if (!output->used_local) {
195
202
/* use global settings, but add local_ip/host to hash tables
196
203
so we'll find them */
197
204
pool = pool_alloconly_create("settings global entry", 256);
198
entry = p_new(pool, struct settings_entry, 1);
199
205
} else if (cache->cache_malloc_size >= cache->max_cache_size) {
200
206
/* free the oldest and reuse its pool */
201
entry = cache->oldest;
203
setting_entry_detach(cache, entry);
207
pool = cache->oldest->pool;
208
setting_entry_detach(cache, cache->oldest);
209
p_clear(pool); /* note: frees also entry */
206
211
pool_size = cache->approx_entry_pool_size != 0 ?
207
212
cache->approx_entry_pool_size :
208
213
CACHE_INITIAL_ENTRY_POOL_SIZE;
209
214
pool = pool_alloconly_create("settings entry", pool_size);
210
entry = p_new(pool, struct settings_entry, 1);
216
entry = p_new(pool, struct settings_entry, 1);
212
217
entry->pool = pool;
213
218
entry_local_name = p_strdup(pool, input->local_name);
214
219
entry->local_name = entry_local_name;
215
220
entry->local_ip = input->local_ip;
216
221
if (!output->used_local) {
217
222
entry->parser = cache->global_parser;
218
DLLIST2_PREPEND(&cache->oldest_global, &cache->newest_global,
223
DLLIST2_APPEND(&cache->oldest_global, &cache->newest_global,
221
226
entry->parser = settings_parser_dup(parser, entry->pool);
222
DLLIST2_PREPEND(&cache->oldest, &cache->newest, entry);
227
DLLIST2_APPEND(&cache->oldest, &cache->newest, entry);
224
229
pool_size = pool_alloconly_get_total_used_size(pool);
225
230
if (pool_size > cache->approx_entry_pool_size) {
230
235
cache->cache_malloc_size += pool_alloconly_get_total_alloc_size(pool);
232
237
if (input->local_name != NULL) {
233
if (cache->local_name_hash == NULL) {
234
cache->local_name_hash =
235
hash_table_create(default_pool, cache->pool, 0,
237
(hash_cmp_callback_t *)strcmp);
238
if (!hash_table_is_created(cache->local_name_hash)) {
239
hash_table_create(&cache->local_name_hash,
240
cache->pool, 0, str_hash, strcmp);
239
242
hash_table_insert(cache->local_name_hash,
240
243
entry_local_name, entry);
242
245
if (input->local_ip.family != 0) {
243
if (cache->local_ip_hash == NULL) {
244
cache->local_ip_hash =
245
hash_table_create(default_pool, cache->pool, 0,
246
(hash_callback_t *)net_ip_hash,
247
(hash_cmp_callback_t *)net_ip_cmp);
246
if (!hash_table_is_created(cache->local_ip_hash)) {
247
hash_table_create(&cache->local_ip_hash, cache->pool, 0,
248
net_ip_hash, net_ip_cmp);
249
250
hash_table_insert(cache->local_ip_hash,
250
251
&entry->local_ip, entry);
253
return entry->parser;
254
256
int master_service_settings_cache_read(struct master_service_settings_cache *cache,
297
cache_add(cache, &new_input, &output, cache->service->set_parser);
298
*parser_r = cache->service->set_parser;
299
*parser_r = cache_add(cache, &new_input, &output,
300
cache->service->set_parser);