This is an automated email from the ASF dual-hosted git repository.

hulk pushed a commit to branch unstable
in repository https://gitbox.apache.org/repos/asf/kvrocks.git


The following commit(s) were added to refs/heads/unstable by this push:
     new 667c1458 Fix rand member didn't work in the command SRANDMEMBER (#2032)
667c1458 is described below

commit 667c1458c23db6938cb2a001bbc67c78eb21485e
Author: Lee <[email protected]>
AuthorDate: Tue Jan 23 14:48:06 2024 +0800

    Fix rand member didn't work in the command SRANDMEMBER (#2032)
---
 src/types/redis_set.cc | 28 +++++++++++++++++++++++-----
 1 file changed, 23 insertions(+), 5 deletions(-)

diff --git a/src/types/redis_set.cc b/src/types/redis_set.cc
index 32c06ef9..98677e27 100644
--- a/src/types/redis_set.cc
+++ b/src/types/redis_set.cc
@@ -23,6 +23,7 @@
 #include <map>
 #include <memory>
 #include <optional>
+#include <random>
 
 #include "db_util.h"
 
@@ -222,15 +223,32 @@ rocksdb::Status Set::Take(const Slice &user_key, 
std::vector<std::string> *membe
   rocksdb::Slice upper_bound(next_version_prefix);
   read_options.iterate_upper_bound = &upper_bound;
 
+  std::vector<std::string> iter_keys;
+  iter_keys.reserve(count);
+  std::random_device rd;
+  std::mt19937 gen(rd());
   auto iter = util::UniqueIterator(storage_, read_options);
   for (iter->Seek(prefix); iter->Valid() && iter->key().starts_with(prefix); 
iter->Next()) {
-    InternalKey ikey(iter->key(), storage_->IsSlotIdEncoded());
+    ++n;
+    if (n <= count) {
+      iter_keys.push_back(iter->key().ToString());
+    } else {  // n > count
+      std::uniform_int_distribution<> distrib(0, n - 1);
+      int random = distrib(gen);  // [0,n-1]
+      if (random < count) {
+        iter_keys[random] = iter->key().ToString();
+      }
+    }
+  }
+  for (Slice key : iter_keys) {
+    InternalKey ikey(key, storage_->IsSlotIdEncoded());
     members->emplace_back(ikey.GetSubKey().ToString());
-    if (pop) batch->Delete(iter->key());
-    if (++n >= count) break;
+    if (pop) {
+      batch->Delete(key);
+    }
   }
-  if (pop && n > 0) {
-    metadata.size -= n;
+  if (pop && !iter_keys.empty()) {
+    metadata.size -= iter_keys.size();
     std::string bytes;
     metadata.Encode(&bytes);
     batch->Put(metadata_cf_handle_, ns_key, bytes);

Reply via email to