From f84e1eeac83bb1829e7fcc93e731b79a246f34b8 Mon Sep 17 00:00:00 2001 From: Roman Gershman Date: Tue, 26 Nov 2024 16:11:18 +0200 Subject: [PATCH] fix: debug object encoding names (#4188) Signed-off-by: Roman Gershman --- src/redis/redis_aux.c | 20 --------------- src/redis/redis_aux.h | 3 --- src/server/debugcmd.cc | 49 +++++++++++++++++++++++++++++++++++- src/server/dragonfly_test.cc | 19 ++++++++++++++ src/server/zset_family.cc | 32 ++++++++++++----------- 5 files changed, 85 insertions(+), 38 deletions(-) diff --git a/src/redis/redis_aux.c b/src/redis/redis_aux.c index bad6f9532..aa5629565 100644 --- a/src/redis/redis_aux.c +++ b/src/redis/redis_aux.c @@ -26,26 +26,6 @@ void InitRedisTables() { server.stream_node_max_entries = 100; } - -const char *strEncoding(int encoding) { - switch(encoding) { - case OBJ_ENCODING_RAW: return "raw"; - case OBJ_ENCODING_INT: return "int"; - case OBJ_ENCODING_HT: return "hashtable"; - case OBJ_ENCODING_ZIPMAP: return "zipmap"; - case OBJ_ENCODING_LINKEDLIST: return "linkedlist"; - case OBJ_ENCODING_ZIPLIST: return "ziplist"; - case OBJ_ENCODING_INTSET: return "intset"; - case OBJ_ENCODING_SKIPLIST: return "skiplist"; - case OBJ_ENCODING_EMBSTR: return "embstr"; - case OBJ_ENCODING_QUICKLIST: return "quicklist"; - case OBJ_ENCODING_STREAM: return "stream"; - case OBJ_ENCODING_LISTPACK: return "listpack"; - case OBJ_ENCODING_COMPRESS_INTERNAL: return "compress_internal"; - default: return "unknown"; - } -} - /* Toggle the 64 bit unsigned integer pointed by *p from little endian to * big endian */ void memrev64(void* p) { diff --git a/src/redis/redis_aux.h b/src/redis/redis_aux.h index 80e3cf8ac..8ec55263e 100644 --- a/src/redis/redis_aux.h +++ b/src/redis/redis_aux.h @@ -28,9 +28,6 @@ extern Server server; void InitRedisTables(); -const char *strEncoding(int encoding); - - /* The actual Redis Object */ #define OBJ_STRING 0U /* String object. */ #define OBJ_LIST 1U /* List object. */ diff --git a/src/server/debugcmd.cc b/src/server/debugcmd.cc index 4d7d158bf..166e3f8da 100644 --- a/src/server/debugcmd.cc +++ b/src/server/debugcmd.cc @@ -57,6 +57,7 @@ struct PopulateBatch { }; struct ObjInfo { + unsigned type = 0; unsigned encoding; unsigned bucket_id = 0; unsigned slot_id = 0; @@ -309,6 +310,7 @@ ObjInfo InspectOp(ConnectionContext* cntx, string_view key) { const PrimeValue& pv = it->second; oinfo.found = true; + oinfo.type = pv.ObjType(); oinfo.encoding = pv.Encoding(); oinfo.bucket_id = it.bucket_id(); oinfo.slot_id = it.slot_id(); @@ -365,6 +367,50 @@ OpResult EstimateCompression(ConnectionContext* cntx, string_ return info; }; +const char* EncodingName(unsigned obj_type, unsigned encoding) { + switch (obj_type) { + case OBJ_STRING: + return "raw"; + case OBJ_LIST: + switch (encoding) { + case kEncodingQL2: + case OBJ_ENCODING_QUICKLIST: + return "quicklist"; + } + break; + case OBJ_SET: + ABSL_FALLTHROUGH_INTENDED; + case OBJ_ZSET: + ABSL_FALLTHROUGH_INTENDED; + case OBJ_HASH: + switch (encoding) { + case kEncodingIntSet: + return "intset"; + case kEncodingStrMap2: + return "dense_set"; + case OBJ_ENCODING_SKIPLIST: // we kept the old enum for zset + return "btree"; + case OBJ_ENCODING_LISTPACK: + ABSL_FALLTHROUGH_INTENDED; + case kEncodingListPack: + return "listpack"; + } + break; + case OBJ_JSON: + switch (encoding) { + case kEncodingJsonCons: + return "jsoncons"; + case kEncodingJsonFlat: + return "jsonflat"; + } + break; + case OBJ_STREAM: + return "stream"; + default:; + } + return "unknown"; +} + } // namespace DebugCmd::DebugCmd(ServerFamily* owner, cluster::ClusterFamily* cf, ConnectionContext* cntx) @@ -818,7 +864,8 @@ void DebugCmd::Inspect(string_view key, CmdArgList args, facade::SinkReplyBuilde return; } - StrAppend(&resp, "encoding:", strEncoding(res.encoding), " bucket_id:", res.bucket_id); + StrAppend(&resp, "encoding:", EncodingName(res.type, res.encoding), + " bucket_id:", res.bucket_id); StrAppend(&resp, " slot:", res.slot_id, " shard:", sid); if (res.ttl != INT64_MAX) { diff --git a/src/server/dragonfly_test.cc b/src/server/dragonfly_test.cc index d2c97af93..276bcd87b 100644 --- a/src/server/dragonfly_test.cc +++ b/src/server/dragonfly_test.cc @@ -783,6 +783,25 @@ TEST_F(DflyEngineTest, MemoryUsage) { EXPECT_GT(*resp.GetInt(), 100000); } +TEST_F(DflyEngineTest, DebugObject) { + Run({"set", "key", "value"}); + Run({"lpush", "l1", "a", "b"}); + Run({"sadd", "s1", "1", "2", "3"}); + Run({"sadd", "s2", "a", "b", "c"}); + Run({"zadd", "z1", "1", "a", "2", "b", "3", "c"}); + Run({"hset", "h1", "a", "1", "b", "2", "c", "3"}); + auto resp = Run({"debug", "object", "key"}); + EXPECT_THAT(resp.GetString(), HasSubstr("encoding:raw")); + resp = Run({"debug", "object", "l1"}); + EXPECT_THAT(resp.GetString(), HasSubstr("encoding:quicklist")); + resp = Run({"debug", "object", "s1"}); + EXPECT_THAT(resp.GetString(), HasSubstr("encoding:intset")); + resp = Run({"debug", "object", "s2"}); + EXPECT_THAT(resp.GetString(), HasSubstr("encoding:dense_set")); + resp = Run({"debug", "object", "z1"}); + EXPECT_THAT(resp.GetString(), HasSubstr("encoding:listpack")); +} + // TODO: to test transactions with a single shard since then all transactions become local. // To consider having a parameter in dragonfly engine controlling number of shards // unconditionally from number of cpus. TO TEST BLPOP under multi for single/multi argument case. diff --git a/src/server/zset_family.cc b/src/server/zset_family.cc index fecf99b93..77c5aaf0d 100644 --- a/src/server/zset_family.cc +++ b/src/server/zset_family.cc @@ -129,13 +129,17 @@ zlexrangespec GetLexRange(bool reverse, const ZSetFamily::LexInterval& li) { return range; } +bool IsListPack(const detail::RobjWrapper* robj_wrapper) { + return robj_wrapper->encoding() == OBJ_ENCODING_LISTPACK; +} + /* Delete the element 'ele' from the sorted set, returning 1 if the element * existed and was deleted, 0 otherwise (the element was not there). * taken from t_zset.c */ int ZsetDel(detail::RobjWrapper* robj_wrapper, sds ele) { - if (robj_wrapper->encoding() == OBJ_ENCODING_LISTPACK) { + if (IsListPack(robj_wrapper)) { unsigned char* eptr; uint8_t* lp = (uint8_t*)robj_wrapper->inner_obj(); if ((eptr = zzlFind(lp, ele, NULL)) != NULL) { @@ -153,7 +157,7 @@ int ZsetDel(detail::RobjWrapper* robj_wrapper, sds ele) { // taken from t_zset.c std::optional GetZsetScore(const detail::RobjWrapper* robj_wrapper, sds member) { - if (robj_wrapper->encoding() == OBJ_ENCODING_LISTPACK) { + if (IsListPack(robj_wrapper)) { double score; if (zzlFind((uint8_t*)robj_wrapper->inner_obj(), member, &score) == NULL) return std::nullopt; @@ -429,7 +433,7 @@ void IntervalVisitor::ActionRange(unsigned start, unsigned end) { } void IntervalVisitor::ActionRange(const zrangespec& range) { - if (robj_wrapper_->encoding() == OBJ_ENCODING_LISTPACK) { + if (IsListPack(robj_wrapper_)) { ExtractListPack(range); } else { CHECK_EQ(robj_wrapper_->encoding(), OBJ_ENCODING_SKIPLIST); @@ -438,7 +442,7 @@ void IntervalVisitor::ActionRange(const zrangespec& range) { } void IntervalVisitor::ActionRange(const zlexrangespec& range) { - if (robj_wrapper_->encoding() == OBJ_ENCODING_LISTPACK) { + if (IsListPack(robj_wrapper_)) { ExtractListPack(range); } else { CHECK_EQ(robj_wrapper_->encoding(), OBJ_ENCODING_SKIPLIST); @@ -447,7 +451,7 @@ void IntervalVisitor::ActionRange(const zlexrangespec& range) { } void IntervalVisitor::ActionRem(unsigned start, unsigned end) { - if (robj_wrapper_->encoding() == OBJ_ENCODING_LISTPACK) { + if (IsListPack(robj_wrapper_)) { uint8_t* zl = (uint8_t*)robj_wrapper_->inner_obj(); removed_ = (end - start) + 1; @@ -461,7 +465,7 @@ void IntervalVisitor::ActionRem(unsigned start, unsigned end) { } void IntervalVisitor::ActionRem(const zrangespec& range) { - if (robj_wrapper_->encoding() == OBJ_ENCODING_LISTPACK) { + if (IsListPack(robj_wrapper_)) { uint8_t* zl = (uint8_t*)robj_wrapper_->inner_obj(); unsigned long deleted = 0; zl = zzlDeleteRangeByScore(zl, &range, &deleted); @@ -475,7 +479,7 @@ void IntervalVisitor::ActionRem(const zrangespec& range) { } void IntervalVisitor::ActionRem(const zlexrangespec& range) { - if (robj_wrapper_->encoding() == OBJ_ENCODING_LISTPACK) { + if (IsListPack(robj_wrapper_)) { uint8_t* zl = (uint8_t*)robj_wrapper_->inner_obj(); unsigned long deleted = 0; zl = zzlDeleteRangeByLex(zl, &range, &deleted); @@ -490,7 +494,7 @@ void IntervalVisitor::ActionRem(const zlexrangespec& range) { void IntervalVisitor::ActionPop(ZSetFamily::TopNScored sc) { if (sc > 0) { - if (robj_wrapper_->encoding() == OBJ_ENCODING_LISTPACK) { + if (IsListPack(robj_wrapper_)) { PopListPack(sc); } else { CHECK_EQ(robj_wrapper_->encoding(), OBJ_ENCODING_SKIPLIST); @@ -984,7 +988,7 @@ OpResult OpAdd(const OpArgs& op_args, const ZParams& zparams, string_ OpStatus op_status = OpStatus::OK; AddResult aresult; detail::RobjWrapper* robj_wrapper = res_it->it->second.GetRobjWrapper(); - bool is_list_pack = robj_wrapper->encoding() == OBJ_ENCODING_LISTPACK; + bool is_list_pack = IsListPack(robj_wrapper); // opportunistically reserve space if multiple entries are about to be added. if ((zparams.flags & ZADD_IN_XX) == 0 && members.size() > 2) { @@ -1027,7 +1031,7 @@ OpResult OpAdd(const OpArgs& op_args, const ZParams& zparams, string_ } // if we migrated to skip_list - update listpack stats. - if (is_list_pack && robj_wrapper->encoding() != OBJ_ENCODING_LISTPACK) { + if (is_list_pack && !IsListPack(robj_wrapper)) { DbTableStats* stats = db_slice.MutableStats(op_args.db_cntx.db_index); --stats->listpack_blob_cnt; } @@ -1399,7 +1403,7 @@ OpResult OpRank(const OpArgs& op_args, string_view key, string_view return res_it.status(); const detail::RobjWrapper* robj_wrapper = res_it.value()->second.GetRobjWrapper(); - if (robj_wrapper->encoding() == OBJ_ENCODING_LISTPACK) { + if (IsListPack(robj_wrapper)) { unsigned char* zl = (uint8_t*)robj_wrapper->inner_obj(); unsigned char *eptr, *sptr; @@ -1462,7 +1466,7 @@ OpResult OpCount(const OpArgs& op_args, std::string_view key, zrangespec range = GetZrangeSpec(false, interval); unsigned count = 0; - if (robj_wrapper->encoding() == OBJ_ENCODING_LISTPACK) { + if (IsListPack(robj_wrapper)) { uint8_t* zl = (uint8_t*)robj_wrapper->inner_obj(); uint8_t *eptr, *sptr; double score; @@ -1512,7 +1516,7 @@ OpResult OpLexCount(const OpArgs& op_args, string_view key, unsigned count = 0; const detail::RobjWrapper* robj_wrapper = res_it.value()->second.GetRobjWrapper(); - if (robj_wrapper->encoding() == OBJ_ENCODING_LISTPACK) { + if (IsListPack(robj_wrapper)) { uint8_t* zl = (uint8_t*)robj_wrapper->inner_obj(); uint8_t *eptr, *sptr; @@ -1614,7 +1618,7 @@ OpResult OpScan(const OpArgs& op_args, std::string_view key, uint64_t StringVec res; char buf[128]; - if (pv.Encoding() == OBJ_ENCODING_LISTPACK) { + if (IsListPack(pv.GetRobjWrapper())) { ZSetFamily::RangeParams params; params.with_scores = true; IntervalVisitor iv{Action::RANGE, params, const_cast(&pv)};