From: Remi Tricot-Le Breton Date: Thu, 10 Dec 2020 16:58:43 +0000 (+0100) Subject: MINOR: cache: Add a max-secondary-entries cache option X-Git-Tag: v2.4-dev4~26 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5853c0c0d527d406e5eb54dec9c21ff1478dc16e;p=thirdparty%2Fhaproxy.git MINOR: cache: Add a max-secondary-entries cache option This new option allows to tune the maximum number of simultaneous entries with the same primary key in the cache (secondary entries). When we try to store a response in the cache and there are already max-secondary-entries living entries in the cache, the storage will fail (but the response will still be sent to the client). It defaults to 10 and does not have a maximum number. --- diff --git a/doc/configuration.txt b/doc/configuration.txt index ec1f249988..e60e3428d9 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -14606,6 +14606,8 @@ The cache won't store and won't deliver objects in these cases: - If the response does not have an explicit expiration time (s-maxage or max-age Cache-Control directives or Expires header) or a validator (ETag or Last-Modified headers) +- If the process-vary option is enabled and there are already max-secondary-entries + entries with the same primary key as the current response - If the request is not a GET - If the HTTP version of the request is smaller than 1.1 @@ -14636,7 +14638,7 @@ max-object-size All objects with sizes larger than "max-object-size" will not be cached. max-age - Define the maximum expiration duration. The expiration is set has the lowest + Define the maximum expiration duration. The expiration is set as the lowest value between the s-maxage or max-age (in this order) directive in the Cache-Control response header and this value. The default value is 60 seconds, which means that you can't cache an object more than 60 seconds by @@ -14649,6 +14651,11 @@ process-vary <0 or 1> (which might come with a cpu cost) which will be used to build a secondary key for a given request (see RFC 7234#4.1). The default value is 0 (disabled). +max-secondary-entries + Define the maximum number of simultaneous secondary entries with the same primary + key in the cache. This needs the vary support to be enabled. Its default value is 10 + and should be passed a strictly positive integer. + 6.2.2. Proxy section --------------------- diff --git a/src/cache.c b/src/cache.c index 60946decdd..a833c044f2 100644 --- a/src/cache.c +++ b/src/cache.c @@ -49,6 +49,7 @@ struct cache { unsigned int maxage; /* max-age */ unsigned int maxblocks; unsigned int maxobjsz; /* max-object-size (in bytes) */ + unsigned int max_secondary_entries; /* maximum number of secondary entries with the same primary hash */ uint8_t vary_processing_enabled; /* boolean : manage Vary header (disabled by default) */ char id[33]; /* cache name */ }; @@ -104,7 +105,7 @@ struct cache_st { struct shared_block *first_block; }; -#define SECONDARY_ENTRY_MAX_COUNT 10 +#define DEFAULT_MAX_SECONDARY_ENTRY 10 struct cache_entry { unsigned int complete; /* An entry won't be valid until complete is not null. */ @@ -276,7 +277,7 @@ static struct eb32_node *insert_entry(struct cache *cache, struct cache_entry *n entry_count = entry->secondary_entries_count; last_clear_ts = entry->last_clear_ts; - if (entry_count >= SECONDARY_ENTRY_MAX_COUNT) { + if (entry_count >= cache->max_secondary_entries) { /* Some entries of the duplicate list might be expired so * we will iterate over all the items in order to free some * space. In order to avoid going over the same list too @@ -291,7 +292,7 @@ static struct eb32_node *insert_entry(struct cache *cache, struct cache_entry *n } entry_count = clear_expired_duplicates(&prev); - if (entry_count >= SECONDARY_ENTRY_MAX_COUNT) { + if (entry_count >= cache->max_secondary_entries) { /* Still too many entries for this primary key, delete * the newly inserted one. */ entry = container_of(prev, struct cache_entry, eb); @@ -1800,6 +1801,7 @@ int cfg_parse_cache(const char *file, int linenum, char **args, int kwm) tmp_cache_config->maxage = 60; tmp_cache_config->maxblocks = 0; tmp_cache_config->maxobjsz = 0; + tmp_cache_config->max_secondary_entries = DEFAULT_MAX_SECONDARY_ENTRY; } } else if (strcmp(args[0], "total-max-size") == 0) { unsigned long int maxsize; @@ -1877,6 +1879,29 @@ int cfg_parse_cache(const char *file, int linenum, char **args, int kwm) } tmp_cache_config->vary_processing_enabled = atoi(args[1]); + } else if (strcmp(args[0], "max-secondary-entries") == 0) { + unsigned int max_sec_entries; + char *err; + + if (alertif_too_many_args(1, file, linenum, args, &err_code)) { + err_code |= ERR_ABORT; + goto out; + } + + if (!*args[1]) { + ha_warning("parsing [%s:%d]: '%s' expects a strictly positive number.\n", + file, linenum, args[0]); + err_code |= ERR_WARN; + } + + max_sec_entries = strtoul(args[1], &err, 10); + if (err == args[1] || *err != '\0' || max_sec_entries == 0) { + ha_warning("parsing [%s:%d]: max-secondary-entries wrong value '%s'\n", + file, linenum, args[1]); + err_code |= ERR_ABORT; + goto out; + } + tmp_cache_config->max_secondary_entries = max_sec_entries; } else if (*args[0] != 0) { ha_alert("parsing [%s:%d] : unknown keyword '%s' in 'cache' section\n", file, linenum, args[0]);