JoverZhang commented on code in PR #1681:
URL: https://github.com/apache/kvrocks/pull/1681#discussion_r1298602908


##########
src/types/redis_list.cc:
##########
@@ -392,6 +392,67 @@ rocksdb::Status List::Range(const Slice &user_key, int 
start, int stop, std::vec
   return rocksdb::Status::OK();
 }
 
+rocksdb::Status List::Pos(const Slice &user_key, const Slice &elem, const 
PosSpec &spec,
+                          std::vector<int64_t> *indexes) {
+  assert(spec.rank != 0);
+  assert(!spec.count.has_value() || spec.count >= 0);
+  assert(spec.max_len >= 0);
+  indexes->clear();
+
+  std::string ns_key = AppendNamespacePrefix(user_key);
+  ListMetadata metadata(false);
+  rocksdb::Status s = GetMetadata(ns_key, &metadata);
+  if (!s.ok()) return s;
+
+  // A negative rank means start from the tail.
+  int64_t rank = spec.rank;
+  uint64_t start = metadata.head;
+  bool reversed = false;
+  if (rank < 0) {
+    rank = -rank;
+    start = metadata.tail - 1;
+    reversed = true;
+  }
+
+  std::string buf;
+  PutFixed64(&buf, start);
+  std::string start_key = InternalKey(ns_key, buf, metadata.version, 
storage_->IsSlotIdEncoded()).Encode();
+  std::string prefix = InternalKey(ns_key, "", metadata.version, 
storage_->IsSlotIdEncoded()).Encode();
+  std::string next_version_prefix = InternalKey(ns_key, "", metadata.version + 
1, storage_->IsSlotIdEncoded()).Encode();
+
+  std::vector<uint64_t> to_delete_indexes;
+  rocksdb::ReadOptions read_options = storage_->DefaultScanOptions();
+  LatestSnapShot ss(storage_);
+  read_options.snapshot = ss.GetSnapShot();
+  rocksdb::Slice upper_bound(next_version_prefix);
+  read_options.iterate_upper_bound = &upper_bound;
+  rocksdb::Slice lower_bound(prefix);
+  read_options.iterate_lower_bound = &lower_bound;
+
+  auto list_len = static_cast<int64_t>(metadata.size);
+  int64_t max_len = spec.max_len;
+  int64_t count = spec.count.value_or(-1);
+  int64_t index = 0, matches = 0;
+
+  auto iter = util::UniqueIterator(storage_, read_options);
+  iter->Seek(start_key);
+  while (iter->Valid() && iter->key().starts_with(prefix) && (max_len == 0 || 
index < max_len)) {
+    if (iter->value() == elem) {
+      matches++;
+      if (matches >= rank) {
+        int64_t pos = !reversed ? index : list_len - index - 1;
+        indexes->push_back(pos);
+        if (count && matches - rank + 1 >= count) {

Review Comment:
   Yeah, `count = -1 (by default)`. I took reference from Redis' implementation 
of `LPOS` here. I did try removing this "trick" before, but I was never 
successful, and it kinda feels flawless to me.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to