diff --git a/src/commands/cmd_hash.cc b/src/commands/cmd_hash.cc index 2e24220022d..46789dd5aaa 100644 --- a/src/commands/cmd_hash.cc +++ b/src/commands/cmd_hash.cc @@ -356,7 +356,7 @@ class CommandHRangeByLex : public Commander { } private: - CommonRangeLexSpec spec_; + RangeLexSpec spec_; }; class CommandHScan : public CommandSubkeyScanBase { diff --git a/src/commands/cmd_zset.cc b/src/commands/cmd_zset.cc index c58fa0a7f8d..93261755836 100644 --- a/src/commands/cmd_zset.cc +++ b/src/commands/cmd_zset.cc @@ -146,7 +146,7 @@ class CommandZCount : public Commander { } private: - CommonRangeScoreSpec spec_; + RangeScoreSpec spec_; }; class CommandZCard : public Commander { @@ -215,7 +215,7 @@ class CommandZLexCount : public Commander { } private: - CommonRangeLexSpec spec_; + RangeLexSpec spec_; }; class CommandZPop : public Commander { @@ -356,58 +356,41 @@ class CommandZRangeGeneric : public Commander { } Status Execute(Server *svr, Connection *conn, std::string *output) override { - if (range_type_ == kZRangeAuto || range_type_ == kZRangeRank) { - redis::ZSet zset_db(svr->storage, conn->GetNamespace()); - std::vector member_scores; - auto s = zset_db.RangeByRank(args_[1], rank_spec_, &member_scores); - if (!s.ok()) { - return {Status::RedisExecErr, s.ToString()}; - } - - if (!with_scores_) { - output->append(redis::MultiLen(member_scores.size())); - } else { - output->append(redis::MultiLen(member_scores.size() * 2)); - } - - for (const auto &ms : member_scores) { - output->append(redis::BulkString(ms.member)); - if (with_scores_) output->append(redis::BulkString(util::Float2String(ms.score))); - } - - return Status::OK(); - } else if (range_type_ == kZRangeLex) { - int size = 0; - redis::ZSet zset_db(svr->storage, conn->GetNamespace()); - std::vector members; - auto s = zset_db.RangeByLex(args_[1], lex_spec_, &members, &size); - if (!s.ok()) { - return {Status::RedisExecErr, s.ToString()}; - } - - *output = redis::MultiBulkString(members, false); - return Status::OK(); - } else { // range_type == kZRangeScore - int size = 0; - redis::ZSet zset_db(svr->storage, conn->GetNamespace()); - std::vector member_scores; - auto s = zset_db.RangeByScore(args_[1], score_spec_, &member_scores, &size); - if (!s.ok()) { - return {Status::RedisExecErr, s.ToString()}; - } + redis::ZSet zset_db(svr->storage, conn->GetNamespace()); - if (!with_scores_) { - output->append(redis::MultiLen(member_scores.size())); - } else { - output->append(redis::MultiLen(member_scores.size() * 2)); - } + std::vector member_scores; + std::vector members; - for (const auto &ms : member_scores) { - output->append(redis::BulkString(ms.member)); - if (with_scores_) output->append(redis::BulkString(util::Float2String(ms.score))); - } + rocksdb::Status s; + switch (range_type_) { + case kZRangeAuto: + case kZRangeRank: + s = zset_db.RangeByRank(key_, rank_spec_, &member_scores, nullptr); + break; + case kZRangeScore: + s = zset_db.RangeByScore(key_, score_spec_, &member_scores, nullptr); + break; + case kZRangeLex: + s = zset_db.RangeByLex(key_, lex_spec_, &members, nullptr); + break; + } + if (!s.ok()) { + return {Status::RedisExecErr, s.ToString()}; + } - return Status::OK(); + switch (range_type_) { + case kZRangeLex: + output->append(redis::MultiBulkString(members, false)); + return Status::OK(); + case kZRangeAuto: + case kZRangeRank: + case kZRangeScore: + output->append(redis::MultiLen(member_scores.size() * (with_scores_ ? 2 : 1))); + for (const auto &ms : member_scores) { + output->append(redis::BulkString(ms.member)); + if (with_scores_) output->append(redis::BulkString(util::Float2String(ms.score))); + } + return Status::OK(); } } @@ -417,9 +400,9 @@ class CommandZRangeGeneric : public Commander { ZRangeDirection direction_; bool with_scores_ = false; - CommonRangeRankSpec rank_spec_; - CommonRangeLexSpec lex_spec_; - CommonRangeScoreSpec score_spec_; + RangeRankSpec rank_spec_; + RangeLexSpec lex_spec_; + RangeScoreSpec score_spec_; }; class CommandZRange : public CommandZRangeGeneric { @@ -509,27 +492,29 @@ class CommandZRemRangeByRank : public Commander { return {Status::RedisParseErr, errValueNotInteger}; } - start_ = *parse_start; - stop_ = *parse_stop; + spec_.start = *parse_start; + spec_.stop = *parse_stop; return Commander::Parse(args); } Status Execute(Server *svr, Connection *conn, std::string *output) override { - int ret = 0; redis::ZSet zset_db(svr->storage, conn->GetNamespace()); - auto s = zset_db.RemoveRangeByRank(args_[1], start_, stop_, &ret); + + int cnt = 0; + spec_.with_deletion = true; + + auto s = zset_db.RangeByRank(args_[1], spec_, nullptr, &cnt); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } - *output = redis::Integer(ret); + *output = redis::Integer(cnt); return Status::OK(); } private: - int start_ = 0; - int stop_ = 0; + RangeRankSpec spec_; }; class CommandZRemRangeByScore : public Commander { @@ -543,19 +528,22 @@ class CommandZRemRangeByScore : public Commander { } Status Execute(Server *svr, Connection *conn, std::string *output) override { - int size = 0; redis::ZSet zset_db(svr->storage, conn->GetNamespace()); - auto s = zset_db.RemoveRangeByScore(args_[1], spec_, &size); + + int cnt = 0; + spec_.with_deletion = true; + + auto s = zset_db.RangeByScore(args_[1], spec_, nullptr, &cnt); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } - *output = redis::Integer(size); + *output = redis::Integer(cnt); return Status::OK(); } private: - CommonRangeScoreSpec spec_; + RangeScoreSpec spec_; }; class CommandZRemRangeByLex : public Commander { @@ -569,19 +557,22 @@ class CommandZRemRangeByLex : public Commander { } Status Execute(Server *svr, Connection *conn, std::string *output) override { - int size = 0; redis::ZSet zset_db(svr->storage, conn->GetNamespace()); - auto s = zset_db.RemoveRangeByLex(args_[1], spec_, &size); + + int cnt = 0; + spec_.with_deletion = true; + + auto s = zset_db.RangeByLex(args_[1], spec_, nullptr, &cnt); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } - *output = redis::Integer(size); + *output = redis::Integer(cnt); return Status::OK(); } private: - CommonRangeLexSpec spec_; + RangeLexSpec spec_; }; class CommandZScore : public Commander { diff --git a/src/common/range_spec.cc b/src/common/range_spec.cc index 505f4d843cb..c18b1c85a6c 100644 --- a/src/common/range_spec.cc +++ b/src/common/range_spec.cc @@ -23,7 +23,7 @@ #include "commands/error_constants.h" #include "parse_util.h" -Status ParseRangeLexSpec(const std::string &min, const std::string &max, CommonRangeLexSpec *spec) { +Status ParseRangeLexSpec(const std::string &min, const std::string &max, RangeLexSpec *spec) { if (min == "+" || max == "-") { return {Status::NotOK, "min > max"}; } @@ -56,7 +56,7 @@ Status ParseRangeLexSpec(const std::string &min, const std::string &max, CommonR return Status::OK(); } -Status ParseRangeRankSpec(const std::string &min, const std::string &max, CommonRangeRankSpec *spec) { +Status ParseRangeRankSpec(const std::string &min, const std::string &max, RangeRankSpec *spec) { auto parse_start = ParseInt(min, 10); auto parse_stop = ParseInt(max, 10); if (!parse_start || !parse_stop) { @@ -67,7 +67,7 @@ Status ParseRangeRankSpec(const std::string &min, const std::string &max, Common return Status::OK(); } -Status ParseRangeScoreSpec(const std::string &min, const std::string &max, CommonRangeScoreSpec *spec) { +Status ParseRangeScoreSpec(const std::string &min, const std::string &max, RangeScoreSpec *spec) { char *eptr = nullptr; if (min == "+inf" || max == "-inf") { diff --git a/src/common/range_spec.h b/src/common/range_spec.h index 6bf99521454..1adab476b75 100644 --- a/src/common/range_spec.h +++ b/src/common/range_spec.h @@ -24,36 +24,36 @@ #include "status.h" -struct CommonRangeLexSpec { +struct RangeLexSpec { std::string min, max; bool minex = false, maxex = false; /* are min or max exclusive */ bool max_infinite = false; /* are max infinite */ int64_t offset = -1, count = -1; - bool removed = false, reversed = false; - explicit CommonRangeLexSpec() = default; + bool with_deletion = false, reversed = false; + explicit RangeLexSpec() = default; }; -Status ParseRangeLexSpec(const std::string &min, const std::string &max, CommonRangeLexSpec *spec); +Status ParseRangeLexSpec(const std::string &min, const std::string &max, RangeLexSpec *spec); -struct CommonRangeRankSpec { - int start, stop; - bool removed = false, reversed = false; - explicit CommonRangeRankSpec() = default; +struct RangeRankSpec { + int start = 0, stop = -1; + bool with_deletion = false, reversed = false; + explicit RangeRankSpec() = default; }; -Status ParseRangeRankSpec(const std::string &min, const std::string &max, CommonRangeRankSpec *spec); +Status ParseRangeRankSpec(const std::string &min, const std::string &max, RangeRankSpec *spec); const double kMinScore = (std::numeric_limits::is_iec559 ? -std::numeric_limits::infinity() : std::numeric_limits::lowest()); const double kMaxScore = (std::numeric_limits::is_iec559 ? std::numeric_limits::infinity() : std::numeric_limits::max()); -struct CommonRangeScoreSpec { +struct RangeScoreSpec { double min = kMinScore, max = kMaxScore; bool minex = false, maxex = false; /* are min or max exclusive */ int64_t offset = -1, count = -1; - bool removed = false, reversed = false; - explicit CommonRangeScoreSpec() = default; + bool with_deletion = false, reversed = false; + explicit RangeScoreSpec() = default; }; -Status ParseRangeScoreSpec(const std::string &min, const std::string &max, CommonRangeScoreSpec *spec); +Status ParseRangeScoreSpec(const std::string &min, const std::string &max, RangeScoreSpec *spec); diff --git a/src/types/redis_geo.cc b/src/types/redis_geo.cc index 888c05c6707..106b57c488a 100644 --- a/src/types/redis_geo.cc +++ b/src/types/redis_geo.cc @@ -301,7 +301,7 @@ int Geo::getPointsInRange(const Slice &user_key, double min, double max, double std::vector *geo_points) { /* include min in range; exclude max in range */ /* That's: min <= val < max */ - CommonRangeScoreSpec spec; + RangeScoreSpec spec; spec.min = min; spec.max = max; spec.maxex = true; diff --git a/src/types/redis_hash.cc b/src/types/redis_hash.cc index 99d83606ef5..389b8e19626 100644 --- a/src/types/redis_hash.cc +++ b/src/types/redis_hash.cc @@ -273,7 +273,7 @@ rocksdb::Status Hash::MSet(const Slice &user_key, const std::vector return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status Hash::RangeByLex(const Slice &user_key, const CommonRangeLexSpec &spec, +rocksdb::Status Hash::RangeByLex(const Slice &user_key, const RangeLexSpec &spec, std::vector *field_values) { field_values->clear(); if (spec.count == 0) { diff --git a/src/types/redis_hash.h b/src/types/redis_hash.h index f1203a979de..fede0ab050e 100644 --- a/src/types/redis_hash.h +++ b/src/types/redis_hash.h @@ -52,8 +52,7 @@ class Hash : public SubKeyScanner { rocksdb::Status IncrBy(const Slice &user_key, const Slice &field, int64_t increment, int64_t *ret); rocksdb::Status IncrByFloat(const Slice &user_key, const Slice &field, double increment, double *ret); rocksdb::Status MSet(const Slice &user_key, const std::vector &field_values, bool nx, int *ret); - rocksdb::Status RangeByLex(const Slice &user_key, const CommonRangeLexSpec &spec, - std::vector *field_values); + rocksdb::Status RangeByLex(const Slice &user_key, const RangeLexSpec &spec, std::vector *field_values); rocksdb::Status MGet(const Slice &user_key, const std::vector &fields, std::vector *values, std::vector *statuses); rocksdb::Status GetAll(const Slice &user_key, std::vector *field_values, diff --git a/src/types/redis_zset.cc b/src/types/redis_zset.cc index 1a35bf60426..e181654a044 100644 --- a/src/types/redis_zset.cc +++ b/src/types/redis_zset.cc @@ -34,7 +34,7 @@ rocksdb::Status ZSet::GetMetadata(const Slice &ns_key, ZSetMetadata *metadata) { return Database::GetMetadata(kRedisZSet, ns_key, metadata); } -rocksdb::Status ZSet::Add(const Slice &user_key, ZAddFlags flags, std::vector *mscores, int *ret) { +rocksdb::Status ZSet::Add(const Slice &user_key, ZAddFlags flags, MemberScores *mscores, int *ret) { *ret = 0; std::string ns_key; @@ -144,8 +144,7 @@ rocksdb::Status ZSet::Card(const Slice &user_key, int *ret) { return rocksdb::Status::OK(); } -rocksdb::Status ZSet::Count(const Slice &user_key, const CommonRangeScoreSpec &spec, int *ret) { - *ret = 0; +rocksdb::Status ZSet::Count(const Slice &user_key, const RangeScoreSpec &spec, int *ret) { return RangeByScore(user_key, spec, nullptr, ret); } @@ -159,7 +158,7 @@ rocksdb::Status ZSet::IncrBy(const Slice &user_key, const Slice &member, double return rocksdb::Status::OK(); } -rocksdb::Status ZSet::Pop(const Slice &user_key, int count, bool min, std::vector *mscores) { +rocksdb::Status ZSet::Pop(const Slice &user_key, int count, bool min, MemberScores *mscores) { mscores->clear(); std::string ns_key; @@ -220,15 +219,18 @@ rocksdb::Status ZSet::Pop(const Slice &user_key, int count, bool min, std::vecto return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status ZSet::RangeByRank(const Slice &user_key, const CommonRangeRankSpec &spec, - std::vector *mscores) { - mscores->clear(); +rocksdb::Status ZSet::RangeByRank(const Slice &user_key, const RangeRankSpec &spec, MemberScores *mscores, int *ret) { + if (mscores) mscores->clear(); + + int cnt = 0; + if (!ret) ret = &cnt; + *ret = 0; std::string ns_key; AppendNamespacePrefix(user_key, &ns_key); std::unique_ptr lock_guard; - if (spec.removed) lock_guard = std::make_unique(storage_->GetLockManager(), ns_key); + if (spec.with_deletion) lock_guard = std::make_unique(storage_->GetLockManager(), ns_key); ZSetMetadata metadata(false); rocksdb::Status s = GetMetadata(ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; @@ -251,7 +253,6 @@ rocksdb::Status ZSet::RangeByRank(const Slice &user_key, const CommonRangeRankSp InternalKey(ns_key, "", metadata.version, storage_->IsSlotIdEncoded()).Encode(&prefix_key); InternalKey(ns_key, "", metadata.version + 1, storage_->IsSlotIdEncoded()).Encode(&next_verison_prefix_key); - int count = 0; int removed_subkey = 0; rocksdb::ReadOptions read_options; LatestSnapShot ss(storage_); @@ -270,19 +271,22 @@ rocksdb::Status ZSet::RangeByRank(const Slice &user_key, const CommonRangeRankSp iter->SeekForPrev(start_key); } + int count = 0; for (; iter->Valid() && iter->key().starts_with(prefix_key); !(spec.reversed) ? iter->Next() : iter->Prev()) { InternalKey ikey(iter->key(), storage_->IsSlotIdEncoded()); Slice score_key = ikey.GetSubKey(); GetDouble(&score_key, &score); if (count >= start) { - if (spec.removed) { + if (spec.with_deletion) { std::string sub_key; InternalKey(ns_key, score_key, metadata.version, storage_->IsSlotIdEncoded()).Encode(&sub_key); batch->Delete(sub_key); batch->Delete(score_cf_handle_, iter->key()); removed_subkey++; + } else { + if (mscores) mscores->emplace_back(MemberScore{score_key.ToString(), score}); } - mscores->emplace_back(MemberScore{score_key.ToString(), score}); + *ret += 1; } if (count++ >= stop) break; } @@ -297,16 +301,18 @@ rocksdb::Status ZSet::RangeByRank(const Slice &user_key, const CommonRangeRankSp return rocksdb::Status::OK(); } -rocksdb::Status ZSet::RangeByScore(const Slice &user_key, const CommonRangeScoreSpec &spec, - std::vector *mscores, int *size) { - if (size) *size = 0; +rocksdb::Status ZSet::RangeByScore(const Slice &user_key, const RangeScoreSpec &spec, MemberScores *mscores, int *ret) { if (mscores) mscores->clear(); + int cnt = 0; + if (!ret) ret = &cnt; + *ret = 0; + std::string ns_key; AppendNamespacePrefix(user_key, &ns_key); std::unique_ptr lock_guard; - if (spec.removed) lock_guard = std::make_unique(storage_->GetLockManager(), ns_key); + if (spec.with_deletion) lock_guard = std::make_unique(storage_->GetLockManager(), ns_key); ZSetMetadata metadata(false); rocksdb::Status s = GetMetadata(ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; @@ -350,15 +356,15 @@ rocksdb::Status ZSet::RangeByScore(const Slice &user_key, const CommonRangeScore std::string start_score_bytes; PutDouble(&start_score_bytes, spec.reversed ? (spec.maxex ? spec.max : max_next_score) : spec.min); - std::string start_key, prefix_key, next_verison_prefix_key; + std::string start_key, prefix_key, next_version_prefix_key; InternalKey(ns_key, start_score_bytes, metadata.version, storage_->IsSlotIdEncoded()).Encode(&start_key); InternalKey(ns_key, "", metadata.version, storage_->IsSlotIdEncoded()).Encode(&prefix_key); - InternalKey(ns_key, "", metadata.version + 1, storage_->IsSlotIdEncoded()).Encode(&next_verison_prefix_key); + InternalKey(ns_key, "", metadata.version + 1, storage_->IsSlotIdEncoded()).Encode(&next_version_prefix_key); rocksdb::ReadOptions read_options; LatestSnapShot ss(storage_); read_options.snapshot = ss.GetSnapShot(); - rocksdb::Slice upper_bound(next_verison_prefix_key); + rocksdb::Slice upper_bound(next_version_prefix_key); read_options.iterate_upper_bound = &upper_bound; rocksdb::Slice lower_bound(prefix_key); read_options.iterate_lower_bound = &lower_bound; @@ -391,7 +397,7 @@ rocksdb::Status ZSet::RangeByScore(const Slice &user_key, const CommonRangeScore if ((spec.maxex && score == spec.max) || score > spec.max) break; } if (spec.offset >= 0 && pos++ < spec.offset) continue; - if (spec.removed) { + if (spec.with_deletion) { std::string sub_key; InternalKey(ns_key, score_key, metadata.version, storage_->IsSlotIdEncoded()).Encode(&sub_key); batch->Delete(sub_key); @@ -399,12 +405,12 @@ rocksdb::Status ZSet::RangeByScore(const Slice &user_key, const CommonRangeScore } else { if (mscores) mscores->emplace_back(MemberScore{score_key.ToString(), score}); } - if (size) *size += 1; + *ret += 1; if (spec.count > 0 && mscores && mscores->size() >= static_cast(spec.count)) break; } - if (spec.removed && *size > 0) { - metadata.size -= *size; + if (spec.with_deletion && *ret > 0) { + metadata.size -= *ret; std::string bytes; metadata.Encode(&bytes); batch->Put(metadata_cf_handle_, ns_key, bytes); @@ -413,10 +419,13 @@ rocksdb::Status ZSet::RangeByScore(const Slice &user_key, const CommonRangeScore return rocksdb::Status::OK(); } -rocksdb::Status ZSet::RangeByLex(const Slice &user_key, const CommonRangeLexSpec &spec, - std::vector *members, int *size) { - if (size) *size = 0; +rocksdb::Status ZSet::RangeByLex(const Slice &user_key, const RangeLexSpec &spec, Members *members, int *ret) { if (members) members->clear(); + + int cnt = 0; + if (!ret) ret = &cnt; + *ret = 0; + if (spec.offset > -1 && spec.count == 0) { return rocksdb::Status::OK(); } @@ -425,7 +434,7 @@ rocksdb::Status ZSet::RangeByLex(const Slice &user_key, const CommonRangeLexSpec AppendNamespacePrefix(user_key, &ns_key); std::unique_ptr lock_guard; - if (spec.removed) { + if (spec.with_deletion) { lock_guard = std::make_unique(storage_->GetLockManager(), ns_key); } ZSetMetadata metadata(false); @@ -478,7 +487,7 @@ rocksdb::Status ZSet::RangeByLex(const Slice &user_key, const CommonRangeLexSpec if ((spec.maxex && member == spec.max) || (!spec.max_infinite && member.ToString() > spec.max)) break; } if (spec.offset >= 0 && pos++ < spec.offset) continue; - if (spec.removed) { + if (spec.with_deletion) { std::string score_bytes = iter->value().ToString(); score_bytes.append(member.data(), member.size()); std::string score_key; @@ -488,12 +497,12 @@ rocksdb::Status ZSet::RangeByLex(const Slice &user_key, const CommonRangeLexSpec } else { if (members) members->emplace_back(member.ToString()); } - if (size) *size += 1; + *ret += 1; if (spec.count > 0 && members && members->size() >= static_cast(spec.count)) break; } - if (spec.removed && size && *size > 0) { - metadata.size -= *size; + if (spec.with_deletion && *ret > 0) { + metadata.size -= *ret; std::string bytes; metadata.Encode(&bytes); batch->Put(metadata_cf_handle_, ns_key, bytes); @@ -558,27 +567,6 @@ rocksdb::Status ZSet::Remove(const Slice &user_key, const std::vector &me return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status ZSet::RemoveRangeByScore(const Slice &user_key, CommonRangeScoreSpec &spec, int *ret) { - spec.removed = true; - return RangeByScore(user_key, spec, nullptr, ret); -} - -rocksdb::Status ZSet::RemoveRangeByLex(const Slice &user_key, CommonRangeLexSpec spec, int *ret) { - spec.removed = true; - return RangeByLex(user_key, spec, nullptr, ret); -} - -rocksdb::Status ZSet::RemoveRangeByRank(const Slice &user_key, int start, int stop, int *ret) { - CommonRangeRankSpec rank_spec; - rank_spec.start = start; - rank_spec.stop = stop; - rank_spec.removed = true; - std::vector mscores; - rocksdb::Status s = RangeByRank(user_key, rank_spec, &mscores); - *ret = static_cast(mscores.size()); - return s; -} - rocksdb::Status ZSet::Rank(const Slice &user_key, const Slice &member, bool reversed, int *ret) { *ret = -1; @@ -630,7 +618,7 @@ rocksdb::Status ZSet::Rank(const Slice &user_key, const Slice &member, bool reve return rocksdb::Status::OK(); } -rocksdb::Status ZSet::Overwrite(const Slice &user_key, const std::vector &mscores) { +rocksdb::Status ZSet::Overwrite(const Slice &user_key, const MemberScores &mscores) { std::string ns_key; AppendNamespacePrefix(user_key, &ns_key); @@ -663,7 +651,7 @@ rocksdb::Status ZSet::InterStore(const Slice &dst, const std::vector std::map member_counters; std::vector target_mscores; int target_size = 0; - CommonRangeScoreSpec spec; + RangeScoreSpec spec; auto s = RangeByScore(keys_weights[0].key, spec, &target_mscores, &target_size); if (!s.ok() || target_mscores.empty()) return s; @@ -723,7 +711,7 @@ rocksdb::Status ZSet::UnionStore(const Slice &dst, const std::vector std::map dst_zset; std::vector target_mscores; int target_size = 0; - CommonRangeScoreSpec spec; + RangeScoreSpec spec; for (const auto &key_weight : keys_weights) { // get all member auto s = RangeByScore(key_weight.key, spec, &target_mscores, &target_size); diff --git a/src/types/redis_zset.h b/src/types/redis_zset.h index 905ed58735a..118177545d5 100644 --- a/src/types/redis_zset.h +++ b/src/types/redis_zset.h @@ -91,36 +91,33 @@ class ZSet : public SubKeyScanner { public: explicit ZSet(engine::Storage *storage, const std::string &ns) : SubKeyScanner(storage, ns), score_cf_handle_(storage->GetCFHandle("zset_score")) {} - rocksdb::Status Add(const Slice &user_key, ZAddFlags flags, std::vector *mscores, int *ret); + + using Members = std::vector; + using MemberScores = std::vector; + + rocksdb::Status Add(const Slice &user_key, ZAddFlags flags, MemberScores *mscores, int *ret); rocksdb::Status Card(const Slice &user_key, int *ret); - rocksdb::Status Count(const Slice &user_key, const CommonRangeScoreSpec &spec, int *ret); rocksdb::Status IncrBy(const Slice &user_key, const Slice &member, double increment, double *score); - rocksdb::Status RangeByRank(const Slice &user_key, const CommonRangeRankSpec &spec, - std::vector *mscores); - rocksdb::Status RangeByScore(const Slice &user_key, const CommonRangeScoreSpec &spec, - std::vector *mscores, int *size); - rocksdb::Status RangeByLex(const Slice &user_key, const CommonRangeLexSpec &spec, std::vector *members, - int *size); rocksdb::Status Rank(const Slice &user_key, const Slice &member, bool reversed, int *ret); rocksdb::Status Remove(const Slice &user_key, const std::vector &members, int *ret); - rocksdb::Status RemoveRangeByScore(const Slice &user_key, CommonRangeScoreSpec &spec, int *ret); - rocksdb::Status RemoveRangeByLex(const Slice &user_key, CommonRangeLexSpec spec, int *ret); - rocksdb::Status RemoveRangeByRank(const Slice &user_key, int start, int stop, int *ret); - rocksdb::Status Pop(const Slice &user_key, int count, bool min, std::vector *mscores); + rocksdb::Status Pop(const Slice &user_key, int count, bool min, MemberScores *mscores); rocksdb::Status Score(const Slice &user_key, const Slice &member, double *score); rocksdb::Status Scan(const Slice &user_key, const std::string &cursor, uint64_t limit, const std::string &member_prefix, std::vector *members, std::vector *scores = nullptr); - rocksdb::Status Overwrite(const Slice &user_key, const std::vector &mscores); + rocksdb::Status Overwrite(const Slice &user_key, const MemberScores &mscores); rocksdb::Status InterStore(const Slice &dst, const std::vector &keys_weights, AggregateMethod aggregate_method, int *size); rocksdb::Status UnionStore(const Slice &dst, const std::vector &keys_weights, AggregateMethod aggregate_method, int *size); - rocksdb::Status MGet(const Slice &user_key, const std::vector &members, - std::map *mscores); - + rocksdb::Status MGet(const Slice &user_key, const std::vector &members, std::map *scores); rocksdb::Status GetMetadata(const Slice &ns_key, ZSetMetadata *metadata); + rocksdb::Status Count(const Slice &user_key, const RangeScoreSpec &spec, int *ret); + rocksdb::Status RangeByRank(const Slice &user_key, const RangeRankSpec &spec, MemberScores *mscores, int *ret); + rocksdb::Status RangeByScore(const Slice &user_key, const RangeScoreSpec &spec, MemberScores *mscores, int *ret); + rocksdb::Status RangeByLex(const Slice &user_key, const RangeLexSpec &spec, Members *members, int *ret); + private: rocksdb::ColumnFamilyHandle *score_cf_handle_; }; diff --git a/tests/cppunit/types/hash_test.cc b/tests/cppunit/types/hash_test.cc index 1a24f0235ff..a24aff85dba 100644 --- a/tests/cppunit/types/hash_test.cc +++ b/tests/cppunit/types/hash_test.cc @@ -221,7 +221,7 @@ TEST_F(RedisHashTest, HRangeByLex) { EXPECT_TRUE(s.ok()); EXPECT_EQ(ret, 0); std::vector result; - CommonRangeLexSpec spec; + RangeLexSpec spec; spec.offset = 0; spec.count = INT_MAX; spec.min = "key0"; @@ -240,7 +240,7 @@ TEST_F(RedisHashTest, HRangeByLex) { EXPECT_TRUE(s.ok() && static_cast(tmp.size()) == ret); // use offset and count std::vector result; - CommonRangeLexSpec spec; + RangeLexSpec spec; spec.offset = 0; spec.count = INT_MAX; spec.min = "key0"; @@ -322,7 +322,7 @@ TEST_F(RedisHashTest, HRangeByLex) { TEST_F(RedisHashTest, HRangeByLexNonExistingKey) { std::vector result; - CommonRangeLexSpec spec; + RangeLexSpec spec; spec.offset = 0; spec.count = INT_MAX; spec.min = "any-start-key"; diff --git a/tests/cppunit/types/zset_test.cc b/tests/cppunit/types/zset_test.cc index fc06090e999..e408812fcdc 100644 --- a/tests/cppunit/types/zset_test.cc +++ b/tests/cppunit/types/zset_test.cc @@ -103,10 +103,10 @@ TEST_F(RedisZSetTest, Range) { int count = static_cast(mscores.size() - 1); zset_->Add(key_, ZAddFlags::Default(), &mscores, &ret); EXPECT_EQ(fields_.size(), ret); - CommonRangeRankSpec rank_spec; + RangeRankSpec rank_spec; rank_spec.start = 0; rank_spec.stop = -2; - zset_->RangeByRank(key_, rank_spec, &mscores); + zset_->RangeByRank(key_, rank_spec, &mscores, nullptr); EXPECT_EQ(mscores.size(), count); for (size_t i = 0; i < mscores.size(); i++) { EXPECT_EQ(mscores[i].member, fields_[i].ToString()); @@ -124,11 +124,11 @@ TEST_F(RedisZSetTest, RevRange) { int count = static_cast(mscores.size() - 1); zset_->Add(key_, ZAddFlags::Default(), &mscores, &ret); EXPECT_EQ(static_cast(fields_.size()), ret); - CommonRangeRankSpec rank_spec; + RangeRankSpec rank_spec; rank_spec.start = 0; rank_spec.stop = -2; rank_spec.reversed = true; - zset_->RangeByRank(key_, rank_spec, &mscores); + zset_->RangeByRank(key_, rank_spec, &mscores, nullptr); EXPECT_EQ(mscores.size(), count); for (size_t i = 0; i < mscores.size(); i++) { EXPECT_EQ(mscores[i].member, fields_[count - i].ToString()); @@ -182,7 +182,7 @@ TEST_F(RedisZSetTest, RangeByLex) { zset_->Add(key_, ZAddFlags::Default(), &mscores, &ret); EXPECT_EQ(fields_.size(), ret); - CommonRangeLexSpec spec; + RangeLexSpec spec; spec.min = fields_[0].ToString(); spec.max = fields_[fields_.size() - 1].ToString(); std::vector members; @@ -239,7 +239,7 @@ TEST_F(RedisZSetTest, RangeByScore) { EXPECT_EQ(fields_.size(), ret); // test case: inclusive the min and max score - CommonRangeScoreSpec spec; + RangeScoreSpec spec; spec.min = scores_[0]; spec.max = scores_[scores_.size() - 2]; zset_->RangeByScore(key_, spec, &mscores, nullptr); @@ -286,7 +286,7 @@ TEST_F(RedisZSetTest, RangeByScoreWithLimit) { zset_->Add(key_, ZAddFlags::Default(), &mscores, &ret); EXPECT_EQ(fields_.size(), ret); - CommonRangeScoreSpec spec; + RangeScoreSpec spec; spec.offset = 1; spec.count = 2; zset_->RangeByScore(key_, spec, &mscores, nullptr); @@ -306,14 +306,17 @@ TEST_F(RedisZSetTest, RemRangeByScore) { } zset_->Add(key_, ZAddFlags::Default(), &mscores, &ret); EXPECT_EQ(fields_.size(), ret); - CommonRangeScoreSpec spec; + RangeScoreSpec spec; + spec.with_deletion = true; + spec.min = scores_[0]; spec.max = scores_[scores_.size() - 2]; - zset_->RemoveRangeByScore(key_, spec, &ret); + zset_->RangeByScore(key_, spec, nullptr, &ret); EXPECT_EQ(scores_.size() - 1, ret); + spec.min = scores_[scores_.size() - 1]; spec.max = spec.min; - zset_->RemoveRangeByScore(key_, spec, &ret); + zset_->RangeByScore(key_, spec, nullptr, &ret); EXPECT_EQ(1, ret); } @@ -325,9 +328,18 @@ TEST_F(RedisZSetTest, RemoveRangeByRank) { } zset_->Add(key_, ZAddFlags::Default(), &mscores, &ret); EXPECT_EQ(fields_.size(), ret); - zset_->RemoveRangeByRank(key_, 0, static_cast(fields_.size() - 2), &ret); + + RangeRankSpec spec; + spec.with_deletion = true; + + spec.start = 0; + spec.stop = static_cast(fields_.size() - 2); + zset_->RangeByRank(key_, spec, nullptr, &ret); EXPECT_EQ(fields_.size() - 1, ret); - zset_->RemoveRangeByRank(key_, 0, 2, &ret); + + spec.start = 0; + spec.stop = 2; + zset_->RangeByRank(key_, spec, nullptr, &ret); EXPECT_EQ(1, ret); } @@ -339,9 +351,18 @@ TEST_F(RedisZSetTest, RemoveRevRangeByRank) { } zset_->Add(key_, ZAddFlags::Default(), &mscores, &ret); EXPECT_EQ(fields_.size(), ret); - zset_->RemoveRangeByRank(key_, 0, static_cast(fields_.size() - 2), &ret); - EXPECT_EQ(static_cast(fields_.size() - 1), ret); - zset_->RemoveRangeByRank(key_, 0, 2, &ret); + + RangeRankSpec spec; + spec.with_deletion = true; + + spec.start = 0; + spec.stop = static_cast(fields_.size() - 2); + zset_->RangeByRank(key_, spec, nullptr, &ret); + EXPECT_EQ(fields_.size() - 1, ret); + + spec.start = 0; + spec.stop = 2; + zset_->RangeByRank(key_, spec, nullptr, &ret); EXPECT_EQ(1, ret); }