Skip to content

Commit d709f2a

Browse files
authored
chore: improve compatibility of EXPIRE functions with Redis (#2696)
* chore: improve compatibility of EXPIRE functions with Redis Also, provide a module name if stumbled upon module data that can not be loaded by dragonfly. --------- Signed-off-by: Roman Gershman <[email protected]>
1 parent 4a9f816 commit d709f2a

File tree

5 files changed

+60
-20
lines changed

5 files changed

+60
-20
lines changed

src/server/common.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ namespace dfly {
2323
enum class ListDir : uint8_t { LEFT, RIGHT };
2424

2525
// Dependent on ExpirePeriod representation of the value.
26-
constexpr int64_t kMaxExpireDeadlineSec = (1u << 28) - 1;
26+
constexpr int64_t kMaxExpireDeadlineSec = (1u << 28) - 1; // 8.5 years
27+
constexpr int64_t kMaxExpireDeadlineMs = kMaxExpireDeadlineSec * 1000;
2728

2829
using DbIndex = uint16_t;
2930
using ShardId = uint16_t;

src/server/generic_family.cc

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ class RestoreArgs {
178178
[[nodiscard]] bool RestoreArgs::UpdateExpiration(int64_t now_msec) {
179179
if (HasExpiration()) {
180180
int64_t ttl = abs_time_ ? expiration_ - now_msec : expiration_;
181-
if (ttl > kMaxExpireDeadlineSec * 1000)
181+
if (ttl > kMaxExpireDeadlineMs)
182182
return false;
183183

184184
expiration_ = ttl < 0 ? -1 : ttl + now_msec;
@@ -743,11 +743,13 @@ void GenericFamily::Expire(CmdArgList args, ConnectionContext* cntx) {
743743
return cntx->SendError(kInvalidIntErr);
744744
}
745745

746-
if (int_arg > kMaxExpireDeadlineSec || int_arg < -kMaxExpireDeadlineSec) {
747-
return cntx->SendError(InvalidExpireTime(cntx->cid->name()));
746+
int_arg = std::max<int64_t>(int_arg, -1);
747+
748+
// silently cap the expire time to kMaxExpireDeadlineSec which is more than 8 years.
749+
if (int_arg > kMaxExpireDeadlineSec) {
750+
int_arg = kMaxExpireDeadlineSec;
748751
}
749752

750-
int_arg = std::max<int64_t>(int_arg, -1);
751753
auto expire_options = ParseExpireOptionsOrReply(args.subspan(2), cntx);
752754
if (!expire_options) {
753755
return;
@@ -851,7 +853,13 @@ void GenericFamily::Pexpire(CmdArgList args, ConnectionContext* cntx) {
851853
if (!absl::SimpleAtoi(msec, &int_arg)) {
852854
return cntx->SendError(kInvalidIntErr);
853855
}
854-
int_arg = std::max<int64_t>(int_arg, 0L);
856+
int_arg = std::max<int64_t>(int_arg, -1);
857+
858+
// to be more compatible with redis, we silently cap the expire time to kMaxExpireDeadlineSec
859+
if (int_arg > kMaxExpireDeadlineMs) {
860+
int_arg = kMaxExpireDeadlineMs;
861+
}
862+
855863
auto expire_options = ParseExpireOptionsOrReply(args.subspan(2), cntx);
856864
if (!expire_options) {
857865
return;

src/server/rdb_load.cc

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,25 @@ int ziplistPairsConvertAndValidateIntegrity(const uint8_t* zl, size_t size, unsi
203203
return ret;
204204
}
205205

206+
string ModuleTypeName(uint64_t module_id) {
207+
static const char ModuleNameSet[] =
208+
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
209+
"abcdefghijklmnopqrstuvwxyz"
210+
"0123456789-_";
211+
212+
char name[10];
213+
214+
name[9] = '\0';
215+
char* p = name + 8;
216+
module_id >>= 10;
217+
for (int j = 0; j < 9; j++) {
218+
*p-- = ModuleNameSet[module_id & 63];
219+
module_id >>= 6;
220+
}
221+
222+
return string{name};
223+
}
224+
206225
} // namespace
207226

208227
class DecompressImpl {
@@ -1978,7 +1997,11 @@ error_code RdbLoader::Load(io::Source* src) {
19781997
}
19791998

19801999
if (type == RDB_OPCODE_MODULE_AUX) {
1981-
LOG(ERROR) << "Modules are not supported";
2000+
uint64_t module_id;
2001+
SET_OR_RETURN(LoadLen(nullptr), module_id);
2002+
string module_name = ModuleTypeName(module_id);
2003+
2004+
LOG(ERROR) << "Modules are not supported, error loading module " << module_name;
19822005
return RdbError(errc::feature_not_supported);
19832006
}
19842007

src/server/string_family.cc

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -739,16 +739,16 @@ void StringFamily::Set(CmdArgList args, ConnectionContext* cntx) {
739739
return builder->SendStored();
740740
}
741741
}
742-
if (!is_ms && int_arg >= kMaxExpireDeadlineSec) {
743-
return builder->SendError(InvalidExpireTime("set"));
744-
}
745-
746-
if (!is_ms) {
742+
if (is_ms) {
743+
if (int_arg > kMaxExpireDeadlineMs) {
744+
int_arg = kMaxExpireDeadlineMs;
745+
}
746+
} else {
747+
if (int_arg > kMaxExpireDeadlineSec) {
748+
int_arg = kMaxExpireDeadlineSec;
749+
}
747750
int_arg *= 1000;
748751
}
749-
if (int_arg >= kMaxExpireDeadlineSec * 1000) {
750-
return builder->SendError(InvalidExpireTime("set"));
751-
}
752752
sparams.expire_after_ms = int_arg;
753753
} else if (cur_arg == "NX" && !(sparams.flags & SetCmd::SET_IF_EXISTS)) {
754754
sparams.flags |= SetCmd::SET_IF_NOTEXIST;
@@ -1147,22 +1147,29 @@ void StringFamily::SetExGeneric(bool seconds, CmdArgList args, ConnectionContext
11471147
string_view key = ArgS(args, 0);
11481148
string_view ex = ArgS(args, 1);
11491149
string_view value = ArgS(args, 2);
1150-
int32_t unit_vals;
1150+
int64_t unit_vals;
11511151

11521152
if (!absl::SimpleAtoi(ex, &unit_vals)) {
11531153
return cntx->SendError(kInvalidIntErr);
11541154
}
11551155

1156-
if (unit_vals < 1 || unit_vals >= kMaxExpireDeadlineSec) {
1156+
if (unit_vals < 1) {
11571157
return cntx->SendError(InvalidExpireTime(cntx->cid->name()));
11581158
}
11591159

11601160
SetCmd::SetParams sparams;
11611161
sparams.flags |= SetCmd::SET_EXPIRE_AFTER_MS;
1162-
if (seconds)
1162+
if (seconds) {
1163+
if (unit_vals > kMaxExpireDeadlineSec) {
1164+
unit_vals = kMaxExpireDeadlineSec;
1165+
}
11631166
sparams.expire_after_ms = uint64_t(unit_vals) * 1000;
1164-
else
1167+
} else {
1168+
if (unit_vals > kMaxExpireDeadlineMs) {
1169+
unit_vals = kMaxExpireDeadlineMs;
1170+
}
11651171
sparams.expire_after_ms = unit_vals;
1172+
}
11661173

11671174
auto cb = [&](Transaction* t, EngineShard* shard) {
11681175
SetCmd sg(t->GetOpArgs(shard), true);

src/server/string_family_test.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,8 @@ TEST_F(StringFamilyTest, SetEx) {
451451
ASSERT_THAT(Run({"ttl", "key"}), IntArg(10));
452452
ASSERT_THAT(Run({"setex", "key", "0", "val"}), ErrArg("invalid expire time"));
453453
ASSERT_EQ(Run({"setex", "key", StrCat(5 * 365 * 24 * 3600), "val"}), "OK");
454-
ASSERT_THAT(Run({"setex", "key", StrCat(1 << 30), "val"}), ErrArg("invalid expire time"));
454+
ASSERT_THAT(Run({"setex", "key", StrCat(1 << 30), "val"}), "OK");
455+
ASSERT_THAT(Run({"ttl", "key"}), IntArg(kMaxExpireDeadlineSec));
455456
}
456457

457458
TEST_F(StringFamilyTest, Range) {

0 commit comments

Comments
 (0)