mirror of
https://github.com/dragonflydb/dragonfly.git
synced 2025-05-11 02:15:45 +02:00
Passover cleanups.
1. Add ttl with reload test. 2. Removed several LOG(FATAL) messages and replaced them with error propagation. 3. Added scan test for all the options.
This commit is contained in:
parent
997d2dcb69
commit
6e5de7ac59
10 changed files with 77 additions and 35 deletions
|
@ -20,7 +20,7 @@ class RespExpr {
|
||||||
|
|
||||||
using Vec = std::vector<RespExpr>;
|
using Vec = std::vector<RespExpr>;
|
||||||
Type type;
|
Type type;
|
||||||
bool has_support; // whether pointers in this item are supported by external storage.
|
bool has_support; // whether pointers in this item are supported by the external storage.
|
||||||
|
|
||||||
std::variant<int64_t, Buffer, Vec*> u;
|
std::variant<int64_t, Buffer, Vec*> u;
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace rdb {
|
||||||
enum errc {
|
enum errc {
|
||||||
wrong_signature = 1,
|
wrong_signature = 1,
|
||||||
bad_version = 2,
|
bad_version = 2,
|
||||||
module_not_supported = 3,
|
feature_not_supported = 3,
|
||||||
duplicate_key = 4,
|
duplicate_key = 4,
|
||||||
rdb_file_corrupted = 5,
|
rdb_file_corrupted = 5,
|
||||||
bad_checksum = 6,
|
bad_checksum = 6,
|
||||||
|
|
|
@ -153,4 +153,33 @@ TEST_F(GenericFamilyTest, RenameBinary) {
|
||||||
EXPECT_THAT(Run({"get", kKey2}), RespEq("bar"));
|
EXPECT_THAT(Run({"get", kKey2}), RespEq("bar"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using testing::Each;
|
||||||
|
using testing::StartsWith;
|
||||||
|
using testing::AnyOf;
|
||||||
|
|
||||||
|
TEST_F(GenericFamilyTest, Scan) {
|
||||||
|
for (unsigned i = 0; i < 10; ++i)
|
||||||
|
Run({"set", absl::StrCat("key", i), "bar"});
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < 10; ++i)
|
||||||
|
Run({"set", absl::StrCat("str", i), "bar"});
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < 10; ++i)
|
||||||
|
Run({"sadd", absl::StrCat("set", i), "bar"});
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < 10; ++i)
|
||||||
|
Run({"zadd", absl::StrCat("zset", i), "0", "bar"});
|
||||||
|
|
||||||
|
auto resp = Run({"scan", "0", "count", "20", "type", "string"});
|
||||||
|
EXPECT_EQ(2, resp.size());
|
||||||
|
auto vec = StrArray(resp[1]);
|
||||||
|
EXPECT_GT(vec.size(), 10);
|
||||||
|
EXPECT_THAT(vec, Each(AnyOf(StartsWith("str"), StartsWith("key"))));
|
||||||
|
|
||||||
|
resp = Run({"scan", "0", "count", "20", "match", "zset*"});
|
||||||
|
vec = StrArray(resp[1]);
|
||||||
|
EXPECT_EQ(10, vec.size());
|
||||||
|
EXPECT_THAT(vec, Each(StartsWith("zset")));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dfly
|
} // namespace dfly
|
||||||
|
|
|
@ -380,23 +380,24 @@ void ListFamily::BPopGeneric(ListDir dir, CmdArgList args, ConnectionContext* cn
|
||||||
BPopper popper(dir);
|
BPopper popper(dir);
|
||||||
OpStatus result = popper.Run(transaction, unsigned(timeout * 1000));
|
OpStatus result = popper.Run(transaction, unsigned(timeout * 1000));
|
||||||
|
|
||||||
|
if (result == OpStatus::OK) {
|
||||||
|
CHECK(popper.found());
|
||||||
|
VLOG(1) << "BLPop returned ";
|
||||||
|
|
||||||
|
auto res = popper.result();
|
||||||
|
std::string_view str_arr[2] = {res.first, res.second};
|
||||||
|
return (*cntx)->SendStringArr(str_arr);
|
||||||
|
}
|
||||||
|
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case OpStatus::WRONG_TYPE:
|
case OpStatus::WRONG_TYPE:
|
||||||
return (*cntx)->SendError(kWrongTypeErr);
|
return (*cntx)->SendError(kWrongTypeErr);
|
||||||
case OpStatus::OK:
|
|
||||||
break;
|
|
||||||
case OpStatus::TIMED_OUT:
|
case OpStatus::TIMED_OUT:
|
||||||
return (*cntx)->SendNullArray();
|
return (*cntx)->SendNullArray();
|
||||||
default:
|
default:
|
||||||
LOG(FATAL) << "Unexpected error " << result;
|
LOG(ERROR) << "Unexpected error " << result;
|
||||||
}
|
}
|
||||||
|
return (*cntx)->SendNullArray();
|
||||||
CHECK(popper.found());
|
|
||||||
VLOG(1) << "BLPop returned ";
|
|
||||||
|
|
||||||
auto res = popper.result();
|
|
||||||
std::string_view str_arr[2] = {res.first, res.second};
|
|
||||||
return (*cntx)->SendStringArr(str_arr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListFamily::PushGeneric(ListDir dir, bool skip_notexists, CmdArgList args,
|
void ListFamily::PushGeneric(ListDir dir, bool skip_notexists, CmdArgList args,
|
||||||
|
|
|
@ -332,7 +332,8 @@ error_code RdbLoader::Load(io::Source* src) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == RDB_OPCODE_MODULE_AUX) {
|
if (type == RDB_OPCODE_MODULE_AUX) {
|
||||||
return RdbError(errc::module_not_supported);
|
LOG(ERROR) << "Modules are not supported";
|
||||||
|
return RdbError(errc::feature_not_supported);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rdbIsObjectType(type)) {
|
if (!rdbIsObjectType(type)) {
|
||||||
|
@ -416,7 +417,8 @@ auto RdbLoader::LoadLen(bool* is_encoded) -> io::Result<uint64_t> {
|
||||||
res = absl::big_endian::Load64(mem_buf_.InputBuffer().data());
|
res = absl::big_endian::Load64(mem_buf_.InputBuffer().data());
|
||||||
mem_buf_.ConsumeInput(8);
|
mem_buf_.ConsumeInput(8);
|
||||||
} else {
|
} else {
|
||||||
LOG(FATAL) << "Unknown length encoding " << type << " in rdbLoadLen()";
|
LOG(ERROR) << "Bad length encoding " << type << " in rdbLoadLen()";
|
||||||
|
return Unexpected(errc::rdb_file_corrupted);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -501,7 +503,8 @@ error_code RdbLoader::HandleAux() {
|
||||||
} else if (!strcasecmp((char*)auxkey->ptr, "repl-offset")) {
|
} else if (!strcasecmp((char*)auxkey->ptr, "repl-offset")) {
|
||||||
// TODO
|
// TODO
|
||||||
} else if (!strcasecmp((char*)auxkey->ptr, "lua")) {
|
} else if (!strcasecmp((char*)auxkey->ptr, "lua")) {
|
||||||
LOG(FATAL) << "Lua scripts are not supported";
|
LOG(ERROR) << "Lua scripts are not supported";
|
||||||
|
return RdbError(errc::feature_not_supported);
|
||||||
} else if (!strcasecmp((char*)auxkey->ptr, "redis-ver")) {
|
} else if (!strcasecmp((char*)auxkey->ptr, "redis-ver")) {
|
||||||
LOG(INFO) << "Loading RDB produced by version " << (char*)auxval->ptr;
|
LOG(INFO) << "Loading RDB produced by version " << (char*)auxval->ptr;
|
||||||
} else if (!strcasecmp((char*)auxkey->ptr, "ctime")) {
|
} else if (!strcasecmp((char*)auxkey->ptr, "ctime")) {
|
||||||
|
@ -575,7 +578,8 @@ auto RdbLoader::FetchGenericString(int flags) -> io::Result<OpaqueBuf> {
|
||||||
case RDB_ENC_LZF:
|
case RDB_ENC_LZF:
|
||||||
return FetchLzfStringObject(flags);
|
return FetchLzfStringObject(flags);
|
||||||
default:
|
default:
|
||||||
LOG(FATAL) << "Unknown RDB string encoding type " << len;
|
LOG(ERROR) << "Unknown RDB string encoding len " << len;
|
||||||
|
return Unexpected(errc::rdb_file_corrupted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -216,8 +216,8 @@ error_code RdbSerializer::SaveObject(const PrimeValue& pv) {
|
||||||
return SaveZSetObject(pv.AsRObj());
|
return SaveZSetObject(pv.AsRObj());
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(FATAL) << "Not implemented " << obj_type;
|
LOG(ERROR) << "Not implemented " << obj_type;
|
||||||
return error_code{};
|
return make_error_code(errc::function_not_supported);
|
||||||
}
|
}
|
||||||
|
|
||||||
error_code RdbSerializer::SaveListObject(const robj* obj) {
|
error_code RdbSerializer::SaveListObject(const robj* obj) {
|
||||||
|
|
|
@ -83,7 +83,7 @@ TEST_F(RdbTest, LoadSmall6) {
|
||||||
auto ec = loader.Load(&fs);
|
auto ec = loader.Load(&fs);
|
||||||
CHECK(!ec);
|
CHECK(!ec);
|
||||||
auto resp = Run({"scan", "0"});
|
auto resp = Run({"scan", "0"});
|
||||||
EXPECT_THAT(Array(resp[1]),
|
EXPECT_THAT(StrArray(resp[1]),
|
||||||
UnorderedElementsAre("list1", "hset_zl", "list2", "zset_sl", "intset", "set1",
|
UnorderedElementsAre("list1", "hset_zl", "list2", "zset_sl", "intset", "set1",
|
||||||
"zset_zl", "hset_ht", "intkey", "strkey"));
|
"zset_zl", "hset_ht", "intkey", "strkey"));
|
||||||
resp = Run({"smembers", "intset"});
|
resp = Run({"smembers", "intset"});
|
||||||
|
@ -125,4 +125,11 @@ TEST_F(RdbTest, Reload) {
|
||||||
EXPECT_EQ(2, CheckedInt({"ZCARD", "zs2"}));
|
EXPECT_EQ(2, CheckedInt({"ZCARD", "zs2"}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(RdbTest, ReloadTtl) {
|
||||||
|
Run({"set", "key", "val"});
|
||||||
|
Run({"expire", "key", "1000"});
|
||||||
|
Run({"debug", "reload"});
|
||||||
|
EXPECT_LT(990, CheckedInt({"ttl", "key"}));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dfly
|
} // namespace dfly
|
||||||
|
|
|
@ -287,13 +287,18 @@ auto BaseFamilyTest::AddFindConn(Protocol proto, std::string_view id) -> TestCon
|
||||||
return it->second.get();
|
return it->second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
RespVec BaseFamilyTest::Array(const RespExpr& expr) {
|
vector<string> BaseFamilyTest::StrArray(const RespExpr& expr) {
|
||||||
CHECK(expr.type == RespExpr::ARRAY || expr.type == RespExpr::NIL_ARRAY);
|
CHECK(expr.type == RespExpr::ARRAY || expr.type == RespExpr::NIL_ARRAY);
|
||||||
if (expr.type == RespExpr::NIL_ARRAY)
|
if (expr.type == RespExpr::NIL_ARRAY)
|
||||||
return RespVec{};
|
return vector<string>{};
|
||||||
|
|
||||||
const RespVec* src = get<RespVec*>(expr.u);
|
const RespVec* src = get<RespVec*>(expr.u);
|
||||||
return *src;
|
vector<string> res(src->size());
|
||||||
|
for (size_t i = 0; i < src->size(); ++i) {
|
||||||
|
res[i] = ToSV(src->at(i).GetBuf());
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace dfly
|
} // namespace dfly
|
||||||
|
|
|
@ -66,7 +66,7 @@ class BaseFamilyTest : public ::testing::Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
TestConnWrapper* AddFindConn(Protocol proto, std::string_view id);
|
TestConnWrapper* AddFindConn(Protocol proto, std::string_view id);
|
||||||
static RespVec Array(const RespExpr& expr);
|
static std::vector<std::string> StrArray(const RespExpr& expr);
|
||||||
|
|
||||||
// ts is ms
|
// ts is ms
|
||||||
void UpdateTime(uint64_t ms);
|
void UpdateTime(uint64_t ms);
|
||||||
|
|
|
@ -193,7 +193,8 @@ void IntervalVisitor::ActionRange(unsigned start, unsigned end) {
|
||||||
|
|
||||||
Next(zl, &eptr, &sptr);
|
Next(zl, &eptr, &sptr);
|
||||||
}
|
}
|
||||||
} else if (zobj_->encoding == OBJ_ENCODING_SKIPLIST) {
|
} else {
|
||||||
|
CHECK_EQ(zobj_->encoding, OBJ_ENCODING_SKIPLIST);
|
||||||
zset* zs = (zset*)zobj_->ptr;
|
zset* zs = (zset*)zobj_->ptr;
|
||||||
zskiplist* zsl = zs->zsl;
|
zskiplist* zsl = zs->zsl;
|
||||||
zskiplistNode* ln;
|
zskiplistNode* ln;
|
||||||
|
@ -216,18 +217,15 @@ void IntervalVisitor::ActionRange(unsigned start, unsigned end) {
|
||||||
result_.emplace_back(string(ele, sdslen(ele)), ln->score);
|
result_.emplace_back(string(ele, sdslen(ele)), ln->score);
|
||||||
ln = params_.reverse ? ln->backward : ln->level[0].forward;
|
ln = params_.reverse ? ln->backward : ln->level[0].forward;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
LOG(FATAL) << "Unknown sorted set encoding" << zobj_->encoding;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntervalVisitor::ActionRange(const zrangespec& range) {
|
void IntervalVisitor::ActionRange(const zrangespec& range) {
|
||||||
if (zobj_->encoding == OBJ_ENCODING_LISTPACK) {
|
if (zobj_->encoding == OBJ_ENCODING_LISTPACK) {
|
||||||
ExtractListPack(range);
|
ExtractListPack(range);
|
||||||
} else if (zobj_->encoding == OBJ_ENCODING_SKIPLIST) {
|
|
||||||
ExtractSkipList(range);
|
|
||||||
} else {
|
} else {
|
||||||
LOG(FATAL) << "Unknown sorted set encoding " << zobj_->encoding;
|
CHECK_EQ(zobj_->encoding, OBJ_ENCODING_SKIPLIST);
|
||||||
|
ExtractSkipList(range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,11 +236,10 @@ void IntervalVisitor::ActionRem(unsigned start, unsigned end) {
|
||||||
removed_ = (end - start) + 1;
|
removed_ = (end - start) + 1;
|
||||||
zl = lpDeleteRange(zl, 2 * start, 2 * removed_);
|
zl = lpDeleteRange(zl, 2 * start, 2 * removed_);
|
||||||
zobj_->ptr = zl;
|
zobj_->ptr = zl;
|
||||||
} else if (zobj_->encoding == OBJ_ENCODING_SKIPLIST) {
|
} else {
|
||||||
|
CHECK_EQ(OBJ_ENCODING_SKIPLIST, zobj_->encoding);
|
||||||
zset* zs = (zset*)zobj_->ptr;
|
zset* zs = (zset*)zobj_->ptr;
|
||||||
removed_ = zslDeleteRangeByRank(zs->zsl, start + 1, end + 1, zs->dict);
|
removed_ = zslDeleteRangeByRank(zs->zsl, start + 1, end + 1, zs->dict);
|
||||||
} else {
|
|
||||||
LOG(FATAL) << "Unknown sorted set encoding" << zobj_->encoding;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,11 +250,10 @@ void IntervalVisitor::ActionRem(const zrangespec& range) {
|
||||||
zl = zzlDeleteRangeByScore(zl, &range, &deleted);
|
zl = zzlDeleteRangeByScore(zl, &range, &deleted);
|
||||||
zobj_->ptr = zl;
|
zobj_->ptr = zl;
|
||||||
removed_ = deleted;
|
removed_ = deleted;
|
||||||
} else if (zobj_->encoding == OBJ_ENCODING_SKIPLIST) {
|
} else {
|
||||||
|
CHECK_EQ(OBJ_ENCODING_SKIPLIST, zobj_->encoding);
|
||||||
zset* zs = (zset*)zobj_->ptr;
|
zset* zs = (zset*)zobj_->ptr;
|
||||||
removed_ = zslDeleteRangeByScore(zs->zsl, &range, zs->dict);
|
removed_ = zslDeleteRangeByScore(zs->zsl, &range, zs->dict);
|
||||||
} else {
|
|
||||||
LOG(FATAL) << "Unknown sorted set encoding" << zobj_->encoding;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue