From 65a8cd5c2b3a30f3c7bfc5bc91bd2fab01824b55 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 23 Apr 2024 23:55:03 +0800 Subject: [PATCH] add scan_false_limit in all scan --- .gitignore | 4 +- src/commands/cmd_hash.cc | 8 ++- src/commands/cmd_server.cc | 3 +- src/commands/cmd_set.cc | 5 +- src/commands/cmd_zset.cc | 6 +- src/commands/scan_base.h | 33 +++++------ src/config/config.cc | 2 + src/config/config.h | 1 + src/storage/redis_db.cc | 111 +++++++++++++++++++++++------------ src/storage/redis_db.h | 15 +++-- src/storage/redis_metadata.h | 6 ++ src/types/redis_hash.cc | 11 ++-- src/types/redis_hash.h | 7 ++- src/types/redis_set.cc | 9 ++- src/types/redis_set.h | 5 +- src/types/redis_zset.cc | 14 +++-- src/types/redis_zset.h | 6 +- 17 files changed, 153 insertions(+), 93 deletions(-) diff --git a/.gitignore b/.gitignore index d4b47f191c4..924a3bbc773 100644 --- a/.gitignore +++ b/.gitignore @@ -40,11 +40,13 @@ version.h .idea .vscode .cache +.gitignore compactdb +test testdb build cmake-build-* debug-build -test \ No newline at end of file +test diff --git a/src/commands/cmd_hash.cc b/src/commands/cmd_hash.cc index 45b1c3de0c5..ca7f7ffa766 100644 --- a/src/commands/cmd_hash.cc +++ b/src/commands/cmd_hash.cc @@ -18,6 +18,8 @@ * */ +#include + #include "commander.h" #include "commands/command_parser.h" #include "error_constants.h" @@ -367,12 +369,12 @@ class CommandHScan : public CommandSubkeyScanBase { std::vector fields; std::vector values; auto key_name = srv->GetKeyNameFromCursor(cursor_, CursorType::kTypeHash); - auto s = hash_db.Scan(key_, key_name, limit_, prefix_, &fields, &values, pm_); + auto s = hash_db.Scan(key_, key_name, limit_, srv->GetConfig()->max_scan_num, prefix_, &fields, &values); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } - - auto cursor = GetNextCursor(srv, fields, CursorType::kTypeHash); + auto &end_cursor = hash_db.end_cursor; + const auto &cursor = srv->GenerateCursorFromKeyName(end_cursor, CursorType::kTypeHash); std::vector entries; entries.reserve(2 * fields.size()); for (size_t i = 0; i < fields.size(); i++) { diff --git a/src/commands/cmd_server.cc b/src/commands/cmd_server.cc index 4ae83388459..22ec0074e2a 100644 --- a/src/commands/cmd_server.cc +++ b/src/commands/cmd_server.cc @@ -840,7 +840,8 @@ class CommandScan : public CommandScanBase { std::vector keys; std::string end_key; - auto s = redis_db.Scan(key_name, limit_, prefix_, &keys, &end_key, type_, pm_); + auto s = + redis_db.Scan(key_name, limit_, srv->GetConfig()->max_scan_num, prefix_, &keys, &end_key, type_, match_mode_); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } diff --git a/src/commands/cmd_set.cc b/src/commands/cmd_set.cc index 213a6768279..dce232fed0a 100644 --- a/src/commands/cmd_set.cc +++ b/src/commands/cmd_set.cc @@ -427,12 +427,11 @@ class CommandSScan : public CommandSubkeyScanBase { redis::Set set_db(srv->storage, conn->GetNamespace()); std::vector members; auto key_name = srv->GetKeyNameFromCursor(cursor_, CursorType::kTypeSet); - auto s = set_db.Scan(key_, key_name, limit_, prefix_, &members); + auto s = set_db.Scan(key_, key_name, limit_, srv->GetConfig()->max_scan_num, prefix_, &members, match_mode_); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } - - *output = CommandScanBase::GenerateOutput(srv, conn, members, CursorType::kTypeSet); + *output = CommandScanBase::GenerateOutput(srv, conn, members, set_db.end_cursor); return Status::OK(); } }; diff --git a/src/commands/cmd_zset.cc b/src/commands/cmd_zset.cc index 05dd3c47208..8da4eb26b67 100644 --- a/src/commands/cmd_zset.cc +++ b/src/commands/cmd_zset.cc @@ -1350,12 +1350,12 @@ class CommandZScan : public CommandSubkeyScanBase { std::vector members; std::vector scores; auto key_name = srv->GetKeyNameFromCursor(cursor_, CursorType::kTypeZSet); - auto s = zset_db.Scan(key_, key_name, limit_, prefix_, &members, &scores, pm_); + auto s = + zset_db.Scan(key_, key_name, limit_, srv->GetConfig()->max_scan_num, prefix_, &members, &scores, match_mode_); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } - - auto cursor = GetNextCursor(srv, members, CursorType::kTypeZSet); + auto cursor = srv->GenerateCursorFromKeyName(zset_db.end_cursor, CursorType::kTypeZSet); std::vector entries; entries.reserve(2 * members.size()); for (size_t i = 0; i < members.size(); i++) { diff --git a/src/commands/scan_base.h b/src/commands/scan_base.h index 1c8716ea17f..fba71040c50 100644 --- a/src/commands/scan_base.h +++ b/src/commands/scan_base.h @@ -20,6 +20,8 @@ #pragma once +#include + #include "commander.h" #include "commands/command_parser.h" #include "error_constants.h" @@ -44,17 +46,16 @@ class CommandScanBase : public Commander { while (parser.Good()) { if (parser.EatEqICase("match")) { prefix_ = GET_OR_RET(parser.TakeStr()); - if(prefix_.size()>=2&&prefix_.front() == '*'&&prefix_.back() =='*'){ - prefix_ = prefix_.substr(1,prefix_.size()-2); - pm_ = 2; - }else if (!prefix_.empty() && prefix_.back() == '*') { + if (prefix_.size() >= 2 && prefix_.front() == '*' && prefix_.back() == '*') { + prefix_ = prefix_.substr(1, prefix_.size() - 2); + match_mode_ = MatchType::SUBSTRING; + } else if (!prefix_.empty() && prefix_.back() == '*') { prefix_ = prefix_.substr(0, prefix_.size() - 1); - pm_ = 0; - } else if(!prefix_.empty()&& prefix_.front()=='*'){ + match_mode_ = MatchType::PREFIX; + } else if (!prefix_.empty() && prefix_.front() == '*') { prefix_ = prefix_.substr(1, prefix_.size() - 1); - pm_ = 1; - } - else { + match_mode_ = MatchType::SUBSTRING; + } else { return {Status::RedisParseErr, "currently only key prefix matching is supported"}; } } else if (parser.EatEqICase("count")) { @@ -87,16 +88,10 @@ class CommandScanBase : public Commander { } } - std::string GenerateOutput(Server *srv, const Connection *conn, const std::vector &keys, - CursorType cursor_type) const { + static std::string GenerateOutput(Server *srv, const Connection *conn, const std::vector &keys, + const std::string &end_cursor) { std::vector list; - if (keys.size() == static_cast(limit_)) { - auto end_cursor = srv->GenerateCursorFromKeyName(keys.back(), cursor_type); - list.emplace_back(redis::BulkString(end_cursor)); - } else { - list.emplace_back(redis::BulkString("0")); - } - + list.emplace_back(end_cursor); list.emplace_back(ArrayOfBulkStrings(keys)); return redis::Array(list); @@ -107,7 +102,7 @@ class CommandScanBase : public Commander { std::string prefix_; int limit_ = 20; RedisType type_ = kRedisNone; - int pm_ = 0; + MatchType match_mode_; }; class CommandSubkeyScanBase : public CommandScanBase { diff --git a/src/config/config.cc b/src/config/config.cc index 500ac717008..c0301b76631 100644 --- a/src/config/config.cc +++ b/src/config/config.cc @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -152,6 +153,7 @@ Config::Config() { {"pidfile", true, new StringField(&pidfile, kDefaultPidfile)}, {"max-io-mb", false, new IntField(&max_io_mb, 0, 0, INT_MAX)}, {"max-bitmap-to-string-mb", false, new IntField(&max_bitmap_to_string_mb, 16, 0, INT_MAX)}, + {"max-scan-num", false, new IntField(&max_scan_num, 2, 0, INT_MAX)}, {"max-db-size", false, new IntField(&max_db_size, 0, 0, INT_MAX)}, {"max-replication-mb", false, new IntField(&max_replication_mb, 0, 0, INT_MAX)}, {"supervised", true, new EnumField(&supervised_mode, supervised_modes, kSupervisedNone)}, diff --git a/src/config/config.h b/src/config/config.h index c4bc705b006..88d57c7e609 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -114,6 +114,7 @@ struct Config { int max_replication_mb = 0; int max_io_mb = 0; int max_bitmap_to_string_mb = 16; + int max_scan_num = 2; bool master_use_repl_port = false; bool purge_backup_on_fullsync = false; bool auto_resize_block_and_sst = true; diff --git a/src/storage/redis_db.cc b/src/storage/redis_db.cc index b514c65f3b2..10370c2e583 100644 --- a/src/storage/redis_db.cc +++ b/src/storage/redis_db.cc @@ -21,6 +21,7 @@ #include "redis_db.h" #include +#include #include #include #include @@ -28,6 +29,7 @@ #include "cluster/redis_slot.h" #include "common/scope_exit.h" +#include "config/config.h" #include "db_util.h" #include "parse_util.h" #include "rocksdb/iterator.h" @@ -312,10 +314,12 @@ rocksdb::Status Database::Keys(const std::string &prefix, std::vector *keys, std::string *end_cursor, RedisType type, const int pm) { +rocksdb::Status Database::Scan(const std::string &cursor, uint64_t scan_success_limit, uint64_t scan_false_limit, + const std::string &match_str, std::vector *keys, std::string *end_cursor, + RedisType type, const MatchType match_mode) { end_cursor->clear(); - uint64_t cnt = 0; + uint64_t cnt_success = 0; + uint64_t cnt_false = 0; uint16_t slot_start = 0; std::string ns_prefix; std::string user_key; @@ -329,11 +333,11 @@ rocksdb::Status Database::Scan(const std::string &cursor, uint64_t limit, const ns_prefix = ComposeNamespaceKey(namespace_, "", false); if (storage_->IsSlotIdEncoded()) { slot_start = cursor.empty() ? 0 : GetSlotIdFromKey(cursor); - if (!fix.empty()) { + if (!match_str.empty()) { PutFixed16(&ns_prefix, slot_start); } } - if (pm == 0) ns_prefix.append(fix); + if (match_mode == MatchType::PREFIX) ns_prefix.append(match_str); if (!cursor.empty()) { iter->Seek(ns_cursor); if (iter->Valid()) { @@ -346,17 +350,36 @@ rocksdb::Status Database::Scan(const std::string &cursor, uint64_t limit, const } uint16_t slot_id = slot_start; + + auto scan_match_check = [&]() -> bool { + if (ns_prefix.empty()) { + return true; + } + if (!iter->key().starts_with(ns_prefix)) { + return false; + } + auto key_view = iter->key().ToStringView(); + auto sub_key_view = static_cast(key_view.substr(ns_prefix.size(), key_view.size() - ns_prefix.size())); + if (match_mode == MatchType::SUFFIX && !sub_key_view.ends_with(match_str)) { + return false; + } else if (match_mode == MatchType::SUBSTRING && sub_key_view.ToStringView().find(match_str) == std::string::npos) { + return false; + } + return true; + }; + while (true) { - for (; iter->Valid() && cnt < limit; iter->Next()) { - if (!ns_prefix.empty()) { - if (!iter->key().starts_with(ns_prefix)) break; - auto key_view = iter->key().ToStringView(); - auto sub_key_view = static_cast(key_view.substr(ns_prefix.size(), key_view.size() - ns_prefix.size())); - if (pm == 1 && !sub_key_view.ends_with(fix)) - continue; - else if (pm == 2 && sub_key_view.ToStringView().find(fix) == std::string::npos) + for (; iter->Valid() && cnt_success < scan_success_limit; iter->Next()) { + if (!scan_match_check()) { + cnt_false++; + if (cnt_false < scan_false_limit) { continue; + } else { + break; + } } + // The user_key must be updated either when the scan is successful, or when the number of consecutive failures + // reaches its limit Metadata metadata(kRedisNone, false); auto s = metadata.Decode(iter->value()); if (!s.ok()) continue; @@ -366,16 +389,19 @@ rocksdb::Status Database::Scan(const std::string &cursor, uint64_t limit, const if (metadata.Expired()) continue; std::tie(std::ignore, user_key) = ExtractNamespaceKey(iter->key(), storage_->IsSlotIdEncoded()); keys->emplace_back(user_key); - cnt++; + cnt_success++; } - if (!storage_->IsSlotIdEncoded() || fix.empty()) { - if (!keys->empty() && cnt >= limit) { + if (!storage_->IsSlotIdEncoded() || match_str.empty()) { + if (!keys->empty() && (cnt_success >= scan_success_limit)) { + end_cursor->append(user_key); + } + if (cnt_false >= scan_false_limit) { end_cursor->append(user_key); } break; } - if (cnt >= limit) { + if (cnt_success >= scan_success_limit || cnt_false >= scan_false_limit) { end_cursor->append(user_key); break; } @@ -388,8 +414,8 @@ rocksdb::Status Database::Scan(const std::string &cursor, uint64_t limit, const if (keys->empty()) { if (iter->Valid()) { std::tie(std::ignore, user_key) = ExtractNamespaceKey(iter->key(), storage_->IsSlotIdEncoded()); - auto res = std::mismatch(fix.begin(), fix.end(), user_key.begin()); - if (res.first == fix.end()) { + auto res = std::mismatch(match_str.begin(), match_str.end(), user_key.begin()); + if (res.first == match_str.end()) { keys->emplace_back(user_key); } @@ -402,7 +428,7 @@ rocksdb::Status Database::Scan(const std::string &cursor, uint64_t limit, const ns_prefix = ComposeNamespaceKey(namespace_, "", false); PutFixed16(&ns_prefix, slot_id); - if (pm == 0) ns_prefix.append(fix); + if (match_mode == MatchType::PREFIX) ns_prefix.append(match_str); iter->Seek(ns_prefix); } return rocksdb::Status::OK(); @@ -413,13 +439,13 @@ rocksdb::Status Database::RandomKey(const std::string &cursor, std::string *key) std::string end_cursor; std::vector keys; - auto s = Scan(cursor, RANDOM_KEY_SCAN_LIMIT, "", &keys, &end_cursor); + auto s = Scan(cursor, RANDOM_KEY_SCAN_LIMIT, 1, "", &keys, &end_cursor); if (!s.ok()) { return s; } if (keys.empty() && !cursor.empty()) { // if reach the end, restart from beginning - s = Scan("", RANDOM_KEY_SCAN_LIMIT, "", &keys, &end_cursor); + s = Scan("", RANDOM_KEY_SCAN_LIMIT, 1, "", &keys, &end_cursor); if (!s.ok()) { return s; } @@ -606,10 +632,13 @@ rocksdb::Status Database::KeyExist(const std::string &key) { return rocksdb::Status::OK(); } -rocksdb::Status SubKeyScanner::Scan(RedisType type, const Slice &user_key, const std::string &cursor, uint64_t limit, - const std::string &subkey_fix, std::vector *keys, - std::vector *values, const int pm) { - uint64_t cnt = 0; +rocksdb::Status SubKeyScanner::Scan(RedisType type, const Slice &user_key, const std::string &cursor, + uint64_t scan_success_limit, uint64_t scan_false_limit, + const std::string &match_string, std::vector *keys, + std::vector *values, const MatchType match_mode) { + end_cursor = "0"; + uint64_t success_cnt = 0; + uint64_t false_cnt = 0; std::string ns_key = AppendNamespacePrefix(user_key); Metadata metadata(type, false); LatestSnapShot ss(storage_); @@ -618,8 +647,9 @@ rocksdb::Status SubKeyScanner::Scan(RedisType type, const Slice &user_key, const rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); auto iter = util::UniqueIterator(storage_, read_options); - std::string match_prefix_key = - InternalKey(ns_key, pm == 0 ? subkey_fix : "", metadata.version, storage_->IsSlotIdEncoded()).Encode(); + std::string match_prefix_key = InternalKey(ns_key, match_mode == MatchType::PREFIX ? match_string : "", + metadata.version, storage_->IsSlotIdEncoded()) + .Encode(); std::string start_key; if (!cursor.empty()) { @@ -633,23 +663,30 @@ rocksdb::Status SubKeyScanner::Scan(RedisType type, const Slice &user_key, const // because we already return that key in the last scan continue; } - if (pm == 0 && !iter->key().starts_with(match_prefix_key)) { - std::cout << iter->key() << " " << match_prefix_key << "\n"; - continue; - } InternalKey ikey(iter->key(), storage_->IsSlotIdEncoded()); auto sub_key = ikey.GetSubKey(); - if (pm == 1 && !sub_key.ends_with(subkey_fix)) { + if (scan_false_limit > 0 && false_cnt >= scan_false_limit) { + end_cursor = sub_key.ToString(); + break; + } + if (match_mode == MatchType::PREFIX && !sub_key.starts_with(match_prefix_key)) { + false_cnt++; + break; + } + if (match_mode == MatchType::SUFFIX && !sub_key.ends_with(match_string)) { + false_cnt++; continue; - } else if (pm == 2 && sub_key.ToString().find(subkey_fix) == std::string::npos) { + } else if (match_mode == MatchType::SUBSTRING && sub_key.ToString().find(match_string) == std::string::npos) { + false_cnt++; continue; } - keys->emplace_back(ikey.GetSubKey().ToString()); + keys->emplace_back(sub_key.ToString()); if (values != nullptr) { values->emplace_back(iter->value().ToString()); } - cnt++; - if (limit > 0 && cnt >= limit) { + success_cnt++; + if (scan_success_limit > 0 && success_cnt >= scan_success_limit) { + end_cursor = sub_key.ToString(); break; } } diff --git a/src/storage/redis_db.h b/src/storage/redis_db.h index 83f8290fc3f..b24543f12d4 100644 --- a/src/storage/redis_db.h +++ b/src/storage/redis_db.h @@ -20,6 +20,7 @@ #pragma once +#include #include #include #include @@ -92,9 +93,10 @@ class Database { [[nodiscard]] rocksdb::Status GetKeyNumStats(const std::string &prefix, KeyNumStats *stats); [[nodiscard]] rocksdb::Status Keys(const std::string &prefix, std::vector *keys = nullptr, KeyNumStats *stats = nullptr); - [[nodiscard]] rocksdb::Status Scan(const std::string &cursor, uint64_t limit, const std::string &prefix, - std::vector *keys, std::string *end_cursor = nullptr, - RedisType type = kRedisNone, int pm = 0); + [[nodiscard]] rocksdb::Status Scan(const std::string &cursor, uint64_t scan_success_limit, uint64_t scan_false_limit, + const std::string &match_str, std::vector *keys, + std::string *end_cursor = nullptr, RedisType type = kRedisNone, + MatchType match_mode = MatchType::PREFIX); [[nodiscard]] rocksdb::Status RandomKey(const std::string &cursor, std::string *key); std::string AppendNamespacePrefix(const Slice &user_key); [[nodiscard]] rocksdb::Status FindKeyRangeWithPrefix(const std::string &prefix, const std::string &prefix_end, @@ -137,9 +139,10 @@ class LatestSnapShot { class SubKeyScanner : public redis::Database { public: explicit SubKeyScanner(engine::Storage *storage, const std::string &ns) : Database(storage, ns) {} - rocksdb::Status Scan(RedisType type, const Slice &user_key, const std::string &cursor, uint64_t limit, - const std::string &subkey_prefix, std::vector *keys, - std::vector *values = nullptr, int pm = 0); + rocksdb::Status Scan(RedisType type, const Slice &user_key, const std::string &cursor, uint64_t scan_success_limit, + uint64_t scan_false_limt, const std::string &match_string, std::vector *keys, + std::vector *values = nullptr, MatchType match_mode = MatchType::PREFIX); + std::string end_cursor; }; class WriteBatchLogData { diff --git a/src/storage/redis_metadata.h b/src/storage/redis_metadata.h index 531a880355b..40da9e0d729 100644 --- a/src/storage/redis_metadata.h +++ b/src/storage/redis_metadata.h @@ -37,6 +37,12 @@ constexpr bool USE_64BIT_COMMON_FIELD_DEFAULT = METADATA_ENCODING_VERSION != 0; // explicitly since it cannot be changed once confirmed // Note that if you want to add a new redis type in `RedisType` // you should also add a type name to the `RedisTypeNames` below + +enum class MatchType { + PREFIX, + SUFFIX, + SUBSTRING, +}; enum RedisType : uint8_t { kRedisNone = 0, kRedisString = 1, diff --git a/src/types/redis_hash.cc b/src/types/redis_hash.cc index 529e26fdb13..7d8038eaf76 100644 --- a/src/types/redis_hash.cc +++ b/src/types/redis_hash.cc @@ -31,6 +31,8 @@ #include "db_util.h" #include "parse_util.h" #include "sample_helper.h" +#include "storage/redis_db.h" +#include "storage/redis_metadata.h" namespace redis { @@ -374,10 +376,11 @@ rocksdb::Status Hash::GetAll(const Slice &user_key, std::vector *fie return rocksdb::Status::OK(); } -rocksdb::Status Hash::Scan(const Slice &user_key, const std::string &cursor, uint64_t limit, - const std::string &field_prefix, std::vector *fields, - std::vector *values, const int pm) { - return SubKeyScanner::Scan(kRedisHash, user_key, cursor, limit, field_prefix, fields, values, pm); +rocksdb::Status Hash::Scan(const Slice &user_key, const std::string &cursor, uint64_t scan_success_limit, + uint64_t scan_false_limit, const std::string &match_str, std::vector *fields, + std::vector *values, const MatchType match_mode) { + return SubKeyScanner::Scan(kRedisHash, user_key, cursor, scan_success_limit, scan_false_limit, match_str, fields, + values, match_mode); } rocksdb::Status Hash::RandField(const Slice &user_key, int64_t command_count, std::vector *field_values, diff --git a/src/types/redis_hash.h b/src/types/redis_hash.h index 3544c481972..19ba3272e8d 100644 --- a/src/types/redis_hash.h +++ b/src/types/redis_hash.h @@ -22,6 +22,7 @@ #include +#include #include #include @@ -58,9 +59,9 @@ class Hash : public SubKeyScanner { std::vector *statuses); rocksdb::Status GetAll(const Slice &user_key, std::vector *field_values, HashFetchType type = HashFetchType::kAll); - rocksdb::Status Scan(const Slice &user_key, const std::string &cursor, uint64_t limit, - const std::string &field_prefix, std::vector *fields, - std::vector *values = nullptr, int pm = 0); + rocksdb::Status Scan(const Slice &user_key, const std::string &cursor, uint64_t scan_success_limit, + uint64_t scan_false_limt, const std::string &match_str, std::vector *fields, + std::vector *values = nullptr, MatchType match_mode = MatchType::PREFIX); rocksdb::Status RandField(const Slice &user_key, int64_t command_count, std::vector *field_values, HashFetchType type = HashFetchType::kOnlyKey); diff --git a/src/types/redis_set.cc b/src/types/redis_set.cc index 0c7e4009b28..835ee6bf483 100644 --- a/src/types/redis_set.cc +++ b/src/types/redis_set.cc @@ -26,6 +26,7 @@ #include "db_util.h" #include "sample_helper.h" +#include "storage/redis_metadata.h" namespace redis { @@ -264,9 +265,11 @@ rocksdb::Status Set::Move(const Slice &src, const Slice &dst, const Slice &membe return s; } -rocksdb::Status Set::Scan(const Slice &user_key, const std::string &cursor, uint64_t limit, - const std::string &member_prefix, std::vector *members) { - return SubKeyScanner::Scan(kRedisSet, user_key, cursor, limit, member_prefix, members); +rocksdb::Status Set::Scan(const Slice &user_key, const std::string &cursor, uint64_t scan_success_limit, + uint64_t scan_false_limit, const std::string &member_match, std::vector *members, + const MatchType match_mode) { + return SubKeyScanner::Scan(kRedisSet, user_key, cursor, scan_success_limit, scan_false_limit, member_match, members, + nullptr, match_mode); } /* diff --git a/src/types/redis_set.h b/src/types/redis_set.h index bfd8bd3c7aa..fdac2d73804 100644 --- a/src/types/redis_set.h +++ b/src/types/redis_set.h @@ -20,6 +20,7 @@ #pragma once +#include #include #include @@ -48,8 +49,8 @@ class Set : public SubKeyScanner { rocksdb::Status DiffStore(const Slice &dst, const std::vector &keys, uint64_t *saved_cnt); rocksdb::Status UnionStore(const Slice &dst, const std::vector &keys, uint64_t *save_cnt); rocksdb::Status InterStore(const Slice &dst, const std::vector &keys, uint64_t *saved_cnt); - rocksdb::Status Scan(const Slice &user_key, const std::string &cursor, uint64_t limit, - const std::string &member_prefix, std::vector *members); + rocksdb::Status Scan(const Slice &user_key, const std::string &cursor, uint64_t succes_limit, uint64_t false_limit, + const std::string &member_match, std::vector *members, MatchType match_mode); private: rocksdb::Status GetMetadata(Database::GetOptions options, const Slice &ns_key, SetMetadata *metadata); diff --git a/src/types/redis_zset.cc b/src/types/redis_zset.cc index 25c9f1c53dc..4fc72b412cc 100644 --- a/src/types/redis_zset.cc +++ b/src/types/redis_zset.cc @@ -21,6 +21,7 @@ #include "redis_zset.h" #include +#include #include #include #include @@ -29,6 +30,7 @@ #include "db_util.h" #include "sample_helper.h" +#include "storage/redis_metadata.h" namespace redis { @@ -808,12 +810,13 @@ rocksdb::Status ZSet::Union(const std::vector &keys_weights, Aggregat return rocksdb::Status::OK(); } -rocksdb::Status ZSet::Scan(const Slice &user_key, const std::string &cursor, uint64_t limit, - const std::string &member_prefix, std::vector *members, - std::vector *scores, const int pm) { +rocksdb::Status ZSet::Scan(const Slice &user_key, const std::string &cursor, uint64_t scan_success_limit, + uint64_t scan_false_limit, const std::string &match_str, std::vector *members, + std::vector *scores, MatchType match_mode) { if (scores != nullptr) { std::vector values; - auto s = SubKeyScanner::Scan(kRedisZSet, user_key, cursor, limit, member_prefix, members, &values, pm); + auto s = SubKeyScanner::Scan(kRedisZSet, user_key, cursor, scan_success_limit, scan_false_limit, match_str, members, + &values, match_mode); if (!s.ok()) return s; for (const auto &value : values) { @@ -822,7 +825,8 @@ rocksdb::Status ZSet::Scan(const Slice &user_key, const std::string &cursor, uin } return s; } - return SubKeyScanner::Scan(kRedisZSet, user_key, cursor, limit, member_prefix, members, nullptr, pm); + return SubKeyScanner::Scan(kRedisZSet, user_key, cursor, scan_success_limit, scan_false_limit, match_str, members, + nullptr, match_mode); } rocksdb::Status ZSet::MGet(const Slice &user_key, const std::vector &members, diff --git a/src/types/redis_zset.h b/src/types/redis_zset.h index 6b28e002095..b07437a63af 100644 --- a/src/types/redis_zset.h +++ b/src/types/redis_zset.h @@ -103,9 +103,9 @@ class ZSet : public SubKeyScanner { rocksdb::Status Remove(const Slice &user_key, const std::vector &members, uint64_t *removed_cnt); 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, int pm = 0); + rocksdb::Status Scan(const Slice &user_key, const std::string &cursor, uint64_t scan_success_limit, + uint64_t scan_false_limit, const std::string &match_str, std::vector *members, + std::vector *scores = nullptr, MatchType match_mode = MatchType::PREFIX); rocksdb::Status Overwrite(const Slice &user_key, const MemberScores &mscores); rocksdb::Status InterStore(const Slice &dst, const std::vector &keys_weights, AggregateMethod aggregate_method, uint64_t *saved_cnt);