]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: cache: replace old object on store
authorWilly Tarreau <w@1wt.eu>
Fri, 22 Dec 2017 16:42:46 +0000 (17:42 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 22 Dec 2017 16:56:18 +0000 (17:56 +0100)
Currently the cache aborts a store operation if the object to store
already exists in the cache. This is used to avoid storing multiple
copies at the same time on concurrent accesses. It causes an issue
though, which is that existing unexpired objects cannot be updated.
This happens when any request criterion disables the retrieval from
the cache (eg: with max-age or any other cache-control condition).

For now, let's simply replace the previous existing entry by unlinking
it from the index. This could possibly be improved in the future if
needed.

This fix needs to be backported to 1.8.

src/cache.c

index 371ce20acd540c35432f84eb4d2d7c79932cfe8f..351276e4df89bac38dd1a1ab6d7e6a89b17902fe 100644 (file)
@@ -469,6 +469,7 @@ enum act_return http_action_store_cache(struct act_rule *rule, struct proxy *px,
                            filter->config->conf == rule->arg.act.p[0]) {
                                if (filter->ctx) {
                                        struct cache_st *cache_ctx = filter->ctx;
+                                       struct cache_entry *old;
 
                                        cache_ctx->first_block = first;
                                        object = (struct cache_entry *)first->data;
@@ -478,14 +479,11 @@ enum act_return http_action_store_cache(struct act_rule *rule, struct proxy *px,
                                        /* Insert the node later on caching success */
 
                                        shctx_lock(shctx);
-                                       if (entry_exist(cache, txn->cache_hash)) {
-                                               shctx_unlock(shctx);
-                                               if (filter->ctx) {
-                                                       object->eb.key = 0;
-                                                       pool_free(pool_head_cache_st, filter->ctx);
-                                                       filter->ctx = NULL;
-                                               }
-                                               goto out;
+
+                                       old = entry_exist(cache, txn->cache_hash);
+                                       if (old) {
+                                               eb32_delete(&old->eb);
+                                               old->eb.key = 0;
                                        }
                                        shctx_unlock(shctx);