]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Fix #1253: Cache entries fail to be removed from Redis cachedb
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Fri, 21 Mar 2025 11:56:21 +0000 (12:56 +0100)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Fri, 21 Mar 2025 11:56:21 +0000 (12:56 +0100)
  backend with unbound-control flush* +c.

cachedb/redis.c
doc/Changelog

index 248a3d7b4d632f9d7d98d7ab250b079f9c440048..c38bcaa14f4ce113f2a0557791cb39f8ec8d454e 100644 (file)
@@ -61,7 +61,7 @@ struct redis_moddata {
        struct timeval command_timeout;  /* timeout for commands */
        struct timeval connect_timeout;  /* timeout for connect */
        int logical_db;         /* the redis logical database to use */
-       int setex_available;    /* if the SETEX command is supported */
+       int set_with_ex_available;    /* if the SET with EX command is supported */
 };
 
 static redisReply* redis_command(struct module_env*, struct cachedb_env*,
@@ -195,12 +195,12 @@ redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
                moddata->ctxs[env->alloc->thread_num] != NULL) {
                redisReply* rep = NULL;
                int redis_reply_type = 0;
-               /** check if setex command is supported */
+               /** check if set with ex command is supported */
                rep = redis_command(env, cachedb_env,
-                       "SETEX __UNBOUND_REDIS_CHECK__ 1 none", NULL, 0);
+                       "SET __UNBOUND_REDIS_CHECK__ none EX 1", NULL, 0);
                if(!rep) {
                        /** init failed, no response from redis server*/
-                       goto setex_fail;
+                       goto set_with_ex_fail;
                }
                redis_reply_type = rep->type;
                freeReplyObject(rep);
@@ -208,17 +208,17 @@ redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
                case REDIS_REPLY_STATUS:
                        break;
                default:
-                       /** init failed, setex command not supported */
-                       goto setex_fail;
+                       /** init failed, set_with_ex command not supported */
+                       goto set_with_ex_fail;
                }
-               moddata->setex_available = 1;
+               moddata->set_with_ex_available = 1;
        }
        return 1;
 
-setex_fail:
+set_with_ex_fail:
        log_err("redis_init: failure during redis_init, the "
-               "redis-expire-records option requires the SETEX command "
-               "(redis >= 2.0.0)");
+               "redis-expire-records option requires the SET with EX command "
+               "(redis >= 2.6.2)");
        return 1;
 fail:
        moddata_clean(&moddata);
@@ -352,12 +352,14 @@ redis_store(struct module_env* env, struct cachedb_env* cachedb_env,
        int n;
        struct redis_moddata* moddata = (struct redis_moddata*)
                cachedb_env->backend_data;
-       int set_ttl = (moddata->setex_available &&
+       int set_ttl = (moddata->set_with_ex_available &&
                env->cfg->redis_expire_records &&
                (!env->cfg->serve_expired || env->cfg->serve_expired_ttl > 0));
        /* Supported commands:
         * - "SET " + key + " %b"
-        * - "SETEX " + key + " " + ttl + " %b"
+        * - "SET " + key + " %b EX " + ttl
+        *   older redis 2.0.0 was "SETEX " + key + " " + ttl + " %b"
+        * - "EXPIRE " + key + " 0"
         */
        char cmdbuf[6+(CACHEDB_HASHSIZE/8)*2+11+3+1];
 
@@ -365,14 +367,21 @@ redis_store(struct module_env* env, struct cachedb_env* cachedb_env,
                verbose(VERB_ALGO, "redis_store %s (%d bytes)", key, (int)data_len);
                /* build command to set to a binary safe string */
                n = snprintf(cmdbuf, sizeof(cmdbuf), "SET %s %%b", key);
+       } else if(ttl == 0) {
+               /* use the EXPIRE command, SET with EX 0 is an invalid time. */
+               verbose(VERB_ALGO, "redis_store expire %s (%d bytes)",
+                       key, (int)data_len);
+               n = snprintf(cmdbuf, sizeof(cmdbuf), "EXPIRE %s 0", key);
+               data = NULL;
+               data_len = 0;
        } else {
                /* add expired ttl time to redis ttl to avoid premature eviction of key */
                ttl += env->cfg->serve_expired_ttl;
                verbose(VERB_ALGO, "redis_store %s (%d bytes) with ttl %u",
-                       key, (int)data_len, (uint32_t)ttl);
+                       key, (int)data_len, (unsigned)(uint32_t)ttl);
                /* build command to set to a binary safe string */
-               n = snprintf(cmdbuf, sizeof(cmdbuf), "SETEX %s %u %%b", key,
-                       (uint32_t)ttl);
+               n = snprintf(cmdbuf, sizeof(cmdbuf), "SET %s %%b EX %u", key,
+                       (unsigned)(uint32_t)ttl);
        }
 
 
index f6777a536ec04e1d3e8e678bf02ac28578181df8..7b98f440a5c5b0e59dd9723d0303dfefbed0c09d 100644 (file)
@@ -1,3 +1,7 @@
+21 March 2025: Wouter
+       - Fix #1253: Cache entries fail to be removed from Redis cachedb
+         backend with unbound-control flush* +c.
+
 20 March 2025: Wouter
        - Fix print of RR type NSAP-PTR, it is an unquoted string.