X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=src%2Fsrc%2Fsearch.c;h=ccad25021675a412a5cf58220c5ad0cc5f0607d0;hb=ecc5f51aca286f528e46dade1cf50776e8e38d02;hp=8a3f928efe6479d7e5bf452ceb6f0ad1b95fd0a4;hpb=55414b25bee9f0195ccd1e47f3d3b5cba766e099;p=exim.git diff --git a/src/src/search.c b/src/src/search.c index 8a3f928ef..ccad25021 100644 --- a/src/src/search.c +++ b/src/src/search.c @@ -2,7 +2,7 @@ * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2009 */ +/* Copyright (c) University of Cambridge 1995 - 2015 */ /* See the file NOTICE for conditions of use and distribution. */ /* A set of functions to search databases in various formats. An open @@ -466,6 +466,7 @@ internal_search_find(void *handle, uschar *filename, uschar *keystring) { tree_node *t = (tree_node *)handle; search_cache *c = (search_cache *)(t->data.ptr); +expiring_data *e; uschar *data = NULL; int search_type = t->name[0] - '0'; int old_pool = store_pool; @@ -491,18 +492,27 @@ store_pool = POOL_SEARCH; /* Look up the data for the key, unless it is already in the cache for this file. No need to check c->item_cache for NULL, tree_search will do so. */ -if ((t = tree_search(c->item_cache, keystring)) == NULL) +if ( (t = tree_search(c->item_cache, keystring)) + && (!(e = t->data.ptr)->expiry || e->expiry > time(NULL)) + ) + { /* Data was in the cache already; set the pointer from the tree node */ + data = e->ptr; + DEBUG(D_lookup) debug_printf("cached data used for lookup of %s%s%s\n", + keystring, + filename ? US"\n in " : US"", filename ? filename : US""); + } +else { - BOOL do_cache = TRUE; + uint do_cache = UINT_MAX; int keylength = Ustrlen(keystring); DEBUG(D_lookup) { - if (filename != NULL) - debug_printf("file lookup required for %s\n in %s\n", - keystring, filename); - else - debug_printf("database lookup required for %s\n", keystring); + if (t) debug_printf("cached data found but past valid time; "); + debug_printf("%s lookup required for %s%s%s\n", + filename ? US"file" : US"database", + keystring, + filename ? US"\n in " : US"", filename ? filename : US""); } /* Call the code for the different kinds of search. DEFER is handled @@ -511,9 +521,7 @@ if ((t = tree_search(c->item_cache, keystring)) == NULL) if (lookup_list[search_type]->find(c->handle, filename, keystring, keylength, &data, &search_error_message, &do_cache) == DEFER) - { search_find_defer = TRUE; - } /* A record that has been found is now in data, which is either NULL or points to a bit of dynamic store. Cache the result of the lookup if @@ -524,10 +532,22 @@ if ((t = tree_search(c->item_cache, keystring)) == NULL) else if (do_cache) { int len = keylength + 1; - t = store_get(sizeof(tree_node) + len); - memcpy(t->name, keystring, len); - t->data.ptr = data; - tree_insertnode(&c->item_cache, t); + + if (t) /* Previous, out-of-date cache entry. Update with the */ + { /* new result and forget the old one */ + e->expiry = do_cache == UINT_MAX ? 0 : time(NULL)+do_cache; + e->ptr = data; + } + else + { + e = store_get(sizeof(expiring_data) + sizeof(tree_node) + len); + e->expiry = do_cache == UINT_MAX ? 0 : time(NULL)+do_cache; + e->ptr = data; + t = (tree_node *)(e+1); + memcpy(t->name, keystring, len); + t->data.ptr = e; + tree_insertnode(&c->item_cache, t); + } } /* If caching was disabled, empty the cache tree. We just set the cache @@ -540,34 +560,19 @@ if ((t = tree_search(c->item_cache, keystring)) == NULL) } } -/* Data was in the cache already; set the pointer from the tree node */ - -else - { - data = US t->data.ptr; - DEBUG(D_lookup) debug_printf("cached data used for lookup of %s%s%s\n", - keystring, - (filename == NULL)? US"" : US"\n in ", - (filename == NULL)? US"" : filename); - } - -/* Debug: output the answer */ - DEBUG(D_lookup) { - if (data == NULL) - { - if (search_find_defer) debug_printf("lookup deferred: %s\n", - search_error_message); - else debug_printf("lookup failed\n"); - } - else debug_printf("lookup yielded: %s\n", data); + if (data) + debug_printf("lookup yielded: %s\n", data); + else if (search_find_defer) + debug_printf("lookup deferred: %s\n", search_error_message); + else debug_printf("lookup failed\n"); } /* Return it in new dynamic store in the regular pool */ store_pool = old_pool; -return (data == NULL)? NULL : string_copy(data); +return data ? string_copy(data) : NULL; }