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

Optimize RDB_TYPE_HASH_METADATA to keep relative expiration time (#13438)

Modify RDB_TYPE_HASH_METADATA layout to store expiration times relative
to the minimum expiration time, which is written at the start as absolute time.
parent 447ce11a
......@@ -699,7 +699,7 @@ int rdbSaveObjectType(rio *rdb, robj *o) {
else if (o->encoding == OBJ_ENCODING_LISTPACK_EX)
return rdbSaveType(rdb,RDB_TYPE_HASH_LISTPACK_EX);
else if (o->encoding == OBJ_ENCODING_HT) {
if (hashTypeGetMinExpire(o, 0) == EB_EXPIRE_TIME_INVALID)
if (hashTypeGetMinExpire(o, /*accurate*/ 1) == EB_EXPIRE_TIME_INVALID)
return rdbSaveType(rdb,RDB_TYPE_HASH);
else
return rdbSaveType(rdb,RDB_TYPE_HASH_METADATA);
......@@ -970,7 +970,7 @@ ssize_t rdbSaveObject(rio *rdb, robj *o, robj *key, int dbid) {
* RDB_TYPE_HASH_METADATA layout, including tuples of [ttl][field][value].
* Otherwise, use the standard RDB_TYPE_HASH layout containing only
* the tuples [field][value]. */
uint64_t minExpire = hashTypeGetMinExpire(o, 0);
uint64_t minExpire = hashTypeGetMinExpire(o, 1);
/* if RDB_TYPE_HASH_METADATA (Can have TTLs on fields) */
if (minExpire != EB_EXPIRE_TIME_INVALID) {
......@@ -996,9 +996,13 @@ ssize_t rdbSaveObject(rio *rdb, robj *o, robj *key, int dbid) {
/* save the TTL */
if (hashWithMeta) {
uint64_t ttl = hfieldGetExpireTime(field);
/* 0 is used to indicate no TTL is set for this field */
if (ttl == EB_EXPIRE_TIME_INVALID) ttl = 0;
uint64_t ttl, expiryTime= hfieldGetExpireTime(field);
/* Saved TTL value:
* - 0: Indicates no TTL. This is common case so we keep it small.
* - Otherwise: TTL is relative to minExpire (with +1 to avoid 0 that already taken)
*/
ttl = (expiryTime == EB_EXPIRE_TIME_INVALID) ? 0 : expiryTime - minExpire + 1;
if ((n = rdbSaveLen(rdb, ttl)) == -1) {
dictReleaseIterator(di);
return -1;
......@@ -2261,19 +2265,24 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, sds key, int dbid, int *error)
} else if (rdbtype == RDB_TYPE_HASH_METADATA || rdbtype == RDB_TYPE_HASH_METADATA_PRE_GA) {
sds value;
hfield field;
uint64_t expireAt;
uint64_t ttl, expireAt, minExpire = EB_EXPIRE_TIME_INVALID;
dict *dupSearchDict = NULL;
/* If hash with TTLs, load next/min expiration time */
/* If hash with TTLs, load next/min expiration time
*
* - This value is serialized for future use-case of streaming the object
* directly to FLASH (while keeping in mem its next expiration time).
* - It is also being used to keep only relative TTL for fields in RDB file.
*/
if (rdbtype == RDB_TYPE_HASH_METADATA) {
uint64_t minExpire = rdbLoadMillisecondTime(rdb, RDB_VERSION);
/* This value was serialized for future use-case of streaming the object
* directly to FLASH (while keeping in mem its next expiration time) */
UNUSED(minExpire);
minExpire = rdbLoadMillisecondTime(rdb, RDB_VERSION);
if (rioGetReadError(rdb)) {
rdbReportCorruptRDB("Hash failed loading minExpire");
return NULL;
}
if (minExpire > EB_EXPIRE_TIME_INVALID) {
rdbReportCorruptRDB("Hash read invalid minExpire value");
}
}
len = rdbLoadLen(rdb, NULL);
......@@ -2301,14 +2310,27 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, sds key, int dbid, int *error)
len--;
/* read the TTL */
if (rdbLoadLenByRef(rdb, NULL, &expireAt) == -1) {
if (rdbLoadLenByRef(rdb, NULL, &ttl) == -1) {
serverLog(LL_WARNING, "failed reading hash TTL");
decrRefCount(o);
if (dupSearchDict != NULL) dictRelease(dupSearchDict);
return NULL;
}
if (rdbtype == RDB_TYPE_HASH_METADATA) {
/* Loaded TTL value:
* - 0: Indicates no TTL. This is common case so we keep it small.
* - Otherwise: TTL is relative to minExpire (with +1 to avoid 0 that already taken)
*/
expireAt = (ttl != 0) ? (ttl + minExpire - 1) : 0;
} else { /* RDB_TYPE_HASH_METADATA_PRE_GA */
expireAt = ttl; /* Value is absolute */
}
if (expireAt > EB_EXPIRE_TIME_MAX) {
rdbReportCorruptRDB("invalid expireAt time: %llu", (unsigned long long)expireAt);
rdbReportCorruptRDB("invalid expireAt time: %llu",
(unsigned long long) expireAt);
decrRefCount(o);
return NULL;
}
......
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