Unverified Commit f01fdc39 authored by Moti Cohen's avatar Moti Cohen Committed by GitHub
Browse files

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.
parent ce121b92
......@@ -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)" {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment