mirror of https://mirror.osredm.com/root/redis.git
Reserve 2 bits out of EB_EXPIRE_TIME_MAX for possible future use (#13331)
Reserve 2 bits out of hash-field expiration time (`EB_EXPIRE_TIME_MAX`) for possible future lightweight indexing/categorizing of fields. It can be achieved by hacking HFE as follows: ``` HPEXPIREAT key [ 2^47 + USER_INDEX ] FIELDS numfields field [field …] ``` Redis will also need to expose kind of `HEXPIRESCAN` and `HEXPIRECOUNT` for this idea. Yet to be better defined. `HFE_MAX_ABS_TIME_MSEC` constraint must be enforced only at API level. Internally, the expiration time can be up to `EB_EXPIRE_TIME_MAX` for future readiness.
This commit is contained in:
parent
ce121b9261
commit
f01fdc3960
36
src/t_hash.c
36
src/t_hash.c
|
@ -14,13 +14,23 @@
|
|||
* update the expiration time of the hash object in global HFE DS. */
|
||||
#define HASH_NEW_EXPIRE_DIFF_THRESHOLD max(4000, 1<<EB_BUCKET_KEY_PRECISION)
|
||||
|
||||
/* Returned by hashTypeGetValue() */
|
||||
/* Reserve 2 bits out of hash-field expiration time for possible future lightweight
|
||||
* indexing/categorizing of fields. It can be achieved by hacking HFE as follows:
|
||||
*
|
||||
* HPEXPIREAT key [ 2^47 + USER_INDEX ] FIELDS numfields field [field …]
|
||||
*
|
||||
* Redis will also need to expose kind of HEXPIRESCAN and HEXPIRECOUNT for this
|
||||
* idea. Yet to be better defined.
|
||||
*
|
||||
* HFE_MAX_ABS_TIME_MSEC constraint must be enforced only at API level. Internally,
|
||||
* the expiration time can be up to EB_EXPIRE_TIME_MAX for future readiness.
|
||||
*/
|
||||
#define HFE_MAX_ABS_TIME_MSEC (EB_EXPIRE_TIME_MAX >> 2)
|
||||
|
||||
typedef enum GetFieldRes {
|
||||
/* common (Used by hashTypeGet* value family) */
|
||||
GETF_OK = 0,
|
||||
GETF_OK = 0, /* The field was found. */
|
||||
GETF_NOT_FOUND, /* The field was not found. */
|
||||
|
||||
/* used only by hashTypeGetValue() */
|
||||
GETF_EXPIRED, /* Logically expired (Might be lazy deleted or not) */
|
||||
GETF_EXPIRED_HASH, /* Delete hash since retrieved field was expired and
|
||||
* it was the last field in the hash. */
|
||||
|
@ -168,10 +178,7 @@ static inline int isDictWithMetaHFE(dict *d) {
|
|||
|
||||
/* Returned value of hashTypeSetEx() */
|
||||
typedef enum SetExRes {
|
||||
/* Common res from hashTypeSetEx() */
|
||||
HSETEX_OK = 1, /* Expiration time set/updated as expected */
|
||||
|
||||
/* If provided HashTypeSetEx struct to hashTypeSetEx() */
|
||||
HSETEX_NO_FIELD = -2, /* No such hash-field */
|
||||
HSETEX_NO_CONDITION_MET = 0, /* Specified NX | XX | GT | LT condition not met */
|
||||
HSETEX_DELETED = 2, /* Field deleted because the specified time is in the past */
|
||||
|
@ -183,12 +190,6 @@ typedef enum GetExpireTimeRes {
|
|||
HFE_GET_NO_TTL = -1, /* No TTL attached to the field */
|
||||
} GetExpireTimeRes;
|
||||
|
||||
typedef enum FieldGet { /* TBD */
|
||||
FIELD_GET_NONE = 0,
|
||||
FIELD_GET_NEW = 1,
|
||||
FIELD_GET_OLD = 2
|
||||
} FieldGet;
|
||||
|
||||
typedef enum ExpireSetCond {
|
||||
HFE_NX = 1<<0,
|
||||
HFE_XX = 1<<1,
|
||||
|
@ -196,11 +197,6 @@ typedef enum ExpireSetCond {
|
|||
HFE_LT = 1<<3
|
||||
} ExpireSetCond;
|
||||
|
||||
typedef struct HashTypeSet {
|
||||
sds value;
|
||||
int flags;
|
||||
} HashTypeSet;
|
||||
|
||||
/* Used by hashTypeSetEx() for setting fields or their expiry */
|
||||
typedef struct HashTypeSetEx {
|
||||
|
||||
|
@ -2933,7 +2929,7 @@ static void hexpireGenericCommand(client *c, const char *cmd, long long basetime
|
|||
}
|
||||
|
||||
if (unit == UNIT_SECONDS) {
|
||||
if (expire > (long long) EB_EXPIRE_TIME_MAX / 1000) {
|
||||
if (expire > (long long) HFE_MAX_ABS_TIME_MSEC / 1000) {
|
||||
addReplyErrorExpireTime(c);
|
||||
return;
|
||||
}
|
||||
|
@ -2941,7 +2937,7 @@ static void hexpireGenericCommand(client *c, const char *cmd, long long basetime
|
|||
}
|
||||
|
||||
/* Ensure that the final absolute Unix timestamp does not exceed EB_EXPIRE_TIME_MAX. */
|
||||
if (expire > (long long) EB_EXPIRE_TIME_MAX - basetime) {
|
||||
if (expire > (long long) HFE_MAX_ABS_TIME_MSEC - basetime) {
|
||||
addReplyErrorExpireTime(c);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -429,8 +429,8 @@ start_server [list overrides [list "dir" $server_path]] {
|
|||
r HMSET key a 1 b 2 c 3 d 4 e 5
|
||||
# expected to be expired long after restart
|
||||
r HEXPIREAT key 2524600800 FIELDS 1 a
|
||||
# expected long TTL value (6 bytes) is saved and loaded correctly
|
||||
r HPEXPIREAT key 188900976391764 FIELDS 1 b
|
||||
# expected long TTL value (46 bits) is saved and loaded correctly
|
||||
r HPEXPIREAT key 65755674080852 FIELDS 1 b
|
||||
# expected to be already expired after restart
|
||||
r HPEXPIRE key 80 FIELDS 1 d
|
||||
# expected to be expired soon after restart
|
||||
|
@ -443,7 +443,7 @@ start_server [list overrides [list "dir" $server_path]] {
|
|||
wait_done_loading r
|
||||
|
||||
assert_equal [lsort [r hgetall key]] "1 2 3 a b c"
|
||||
assert_equal [r hpexpiretime key FIELDS 3 a b c] {2524600800000 188900976391764 -1}
|
||||
assert_equal [r hpexpiretime key FIELDS 3 a b c] {2524600800000 65755674080852 -1}
|
||||
assert_equal [s rdb_last_load_keys_loaded] 1
|
||||
|
||||
# wait until expired_hash_fields equals 2
|
||||
|
|
|
@ -208,12 +208,12 @@ start_server {tags {"external:skip needs:debug"}} {
|
|||
assert_error {*Parameter `numFields` is more than number of arguments} {r hpexpire myhash 1000 NX FIELDS 4 f1 f2 f3}
|
||||
}
|
||||
|
||||
test "HPEXPIRE - parameter expire-time near limit of 2^48 ($type)" {
|
||||
test "HPEXPIRE - parameter expire-time near limit of 2^46 ($type)" {
|
||||
r del myhash
|
||||
r hset myhash f1 v1
|
||||
# below & above
|
||||
assert_equal [r hpexpire myhash [expr (1<<48) - [clock milliseconds] - 1000 ] FIELDS 1 f1] [list $E_OK]
|
||||
assert_error {*invalid expire time*} {r hpexpire myhash [expr (1<<48) - [clock milliseconds] + 100 ] FIELDS 1 f1}
|
||||
assert_equal [r hpexpire myhash [expr (1<<46) - [clock milliseconds] - 1000 ] FIELDS 1 f1] [list $E_OK]
|
||||
assert_error {*invalid expire time*} {r hpexpire myhash [expr (1<<46) - [clock milliseconds] + 100 ] FIELDS 1 f1}
|
||||
}
|
||||
|
||||
test "Lazy Expire - fields are lazy deleted ($type)" {
|
||||
|
|
Loading…
Reference in New Issue