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 38c36e1e Unify the way of parsing metadata (#1964)
38c36e1e is described below

commit 38c36e1e9082b6bc2f8af12a0080e507a2684786
Author: hulk <[email protected]>
AuthorDate: Sun Dec 24 12:59:00 2023 +0800

    Unify the way of parsing metadata (#1964)
---
 src/storage/redis_db.cc   | 23 +++++++--------
 src/storage/redis_db.h    |  4 +--
 src/types/redis_bitmap.cc | 21 ++------------
 src/types/redis_json.cc   | 73 ++++++++++++++++-------------------------------
 src/types/redis_json.h    |  3 +-
 5 files changed, 40 insertions(+), 84 deletions(-)

diff --git a/src/storage/redis_db.cc b/src/storage/redis_db.cc
index 29dc277f..e58c1f6f 100644
--- a/src/storage/redis_db.cc
+++ b/src/storage/redis_db.cc
@@ -38,7 +38,9 @@ Database::Database(engine::Storage *storage, std::string ns) 
: storage_(storage)
   metadata_cf_handle_ = storage->GetCFHandle("metadata");
 }
 
-rocksdb::Status Database::ParseMetadata(RedisType type, Slice *bytes, Metadata 
*metadata) {
+// Some data types may support reading multiple types of metadata.
+// For example, bitmap supports reading string metadata and bitmap metadata.
+rocksdb::Status Database::ParseMetadata(const std::vector<RedisType> &types, 
Slice *bytes, Metadata *metadata) {
   std::string old_metadata;
   metadata->Encode(&old_metadata);
 
@@ -50,7 +52,10 @@ rocksdb::Status Database::ParseMetadata(RedisType type, 
Slice *bytes, Metadata *
     auto _ [[maybe_unused]] = metadata->Decode(old_metadata);
     return rocksdb::Status::NotFound(kErrMsgKeyExpired);
   }
-  if (metadata->Type() != type && (metadata->size > 0 || 
metadata->IsEmptyableType())) {
+
+  bool is_type_matched = std::find(types.begin(), types.end(), 
metadata->Type()) != types.end();
+  // if type is not matched, we still need to check if the metadata is valid.
+  if (!is_type_matched && (metadata->size > 0 || metadata->IsEmptyableType())) 
{
     // error discarded here since it already failed
     auto _ [[maybe_unused]] = metadata->Decode(old_metadata);
     return rocksdb::Status::InvalidArgument(kErrMsgWrongType);
@@ -64,11 +69,9 @@ rocksdb::Status Database::ParseMetadata(RedisType type, 
Slice *bytes, Metadata *
 }
 
 rocksdb::Status Database::GetMetadata(RedisType type, const Slice &ns_key, 
Metadata *metadata) {
-  std::string bytes;
-  auto s = GetRawMetadata(ns_key, &bytes);
-  if (!s.ok()) return s;
-  Slice bytes_slice(bytes);
-  return ParseMetadata(type, &bytes_slice, metadata);
+  std::string raw_value;
+  Slice rest;
+  return GetMetadata(type, ns_key, &raw_value, metadata, &rest);
 }
 
 rocksdb::Status Database::GetMetadata(RedisType type, const Slice &ns_key, 
std::string *raw_value, Metadata *metadata,
@@ -76,7 +79,7 @@ rocksdb::Status Database::GetMetadata(RedisType type, const 
Slice &ns_key, std::
   auto s = GetRawMetadata(ns_key, raw_value);
   *rest = *raw_value;
   if (!s.ok()) return s;
-  return ParseMetadata(type, rest, metadata);
+  return ParseMetadata({type}, rest, metadata);
 }
 
 rocksdb::Status Database::GetRawMetadata(const Slice &ns_key, std::string 
*bytes) {
@@ -86,10 +89,6 @@ rocksdb::Status Database::GetRawMetadata(const Slice 
&ns_key, std::string *bytes
   return storage_->Get(read_options, metadata_cf_handle_, ns_key, bytes);
 }
 
-rocksdb::Status Database::GetRawMetadataByUserKey(const Slice &user_key, 
std::string *bytes) {
-  return GetRawMetadata(AppendNamespacePrefix(user_key), bytes);
-}
-
 rocksdb::Status Database::Expire(const Slice &user_key, uint64_t timestamp) {
   std::string ns_key = AppendNamespacePrefix(user_key);
 
diff --git a/src/storage/redis_db.h b/src/storage/redis_db.h
index c77135df..252e5d30 100644
--- a/src/storage/redis_db.h
+++ b/src/storage/redis_db.h
@@ -34,12 +34,12 @@ class Database {
   static constexpr uint64_t RANDOM_KEY_SCAN_LIMIT = 60;
 
   explicit Database(engine::Storage *storage, std::string ns = "");
-  [[nodiscard]] static rocksdb::Status ParseMetadata(RedisType type, Slice 
*bytes, Metadata *metadata);
+  [[nodiscard]] static rocksdb::Status ParseMetadata(const 
std::vector<RedisType> &types, Slice *bytes,
+                                                     Metadata *metadata);
   [[nodiscard]] rocksdb::Status GetMetadata(RedisType type, const Slice 
&ns_key, Metadata *metadata);
   [[nodiscard]] rocksdb::Status GetMetadata(RedisType type, const Slice 
&ns_key, std::string *raw_value,
                                             Metadata *metadata, Slice *rest);
   [[nodiscard]] rocksdb::Status GetRawMetadata(const Slice &ns_key, 
std::string *bytes);
-  [[nodiscard]] rocksdb::Status GetRawMetadataByUserKey(const Slice &user_key, 
std::string *bytes);
   [[nodiscard]] rocksdb::Status Expire(const Slice &user_key, uint64_t 
timestamp);
   [[nodiscard]] rocksdb::Status Del(const Slice &user_key);
   [[nodiscard]] rocksdb::Status MDel(const std::vector<Slice> &keys, uint64_t 
*deleted_cnt);
diff --git a/src/types/redis_bitmap.cc b/src/types/redis_bitmap.cc
index b0fc65f6..37fcc0e3 100644
--- a/src/types/redis_bitmap.cc
+++ b/src/types/redis_bitmap.cc
@@ -58,28 +58,11 @@ void ExpandBitmapSegment(std::string *segment, size_t 
min_bytes) {
 }
 
 rocksdb::Status Bitmap::GetMetadata(const Slice &ns_key, BitmapMetadata 
*metadata, std::string *raw_value) {
-  std::string old_metadata;
-  metadata->Encode(&old_metadata);
   auto s = GetRawMetadata(ns_key, raw_value);
   if (!s.ok()) return s;
-  s = metadata->Decode(*raw_value);
-  if (!s.ok()) return s;
 
-  if (metadata->Expired()) {
-    // error discarded here since it already failed
-    auto _ [[maybe_unused]] = metadata->Decode(old_metadata);
-    return rocksdb::Status::NotFound(kErrMsgKeyExpired);
-  }
-  if (metadata->Type() == kRedisString) return s;
-  if (metadata->Type() != kRedisBitmap && metadata->size > 0) {
-    auto _ [[maybe_unused]] = metadata->Decode(old_metadata);
-    return rocksdb::Status::InvalidArgument(kErrMsgWrongType);
-  }
-  if (metadata->size == 0) {
-    auto _ [[maybe_unused]] = metadata->Decode(old_metadata);
-    return rocksdb::Status::NotFound("no elements");
-  }
-  return s;
+  Slice slice = *raw_value;
+  return ParseMetadata({kRedisBitmap, kRedisString}, &slice, metadata);
 }
 
 rocksdb::Status Bitmap::GetBit(const Slice &user_key, uint32_t offset, bool 
*bit) {
diff --git a/src/types/redis_json.cc b/src/types/redis_json.cc
index b1755e3a..b7c0d4c4 100644
--- a/src/types/redis_json.cc
+++ b/src/types/redis_json.cc
@@ -54,6 +54,22 @@ rocksdb::Status Json::write(Slice ns_key, JsonMetadata 
*metadata, const JsonValu
   return storage_->Write(storage_->DefaultWriteOptions(), 
batch->GetWriteBatch());
 }
 
+rocksdb::Status Json::parse(const JsonMetadata &metadata, const Slice 
&json_bytes, JsonValue *value) {
+  if (metadata.format == JsonStorageFormat::JSON) {
+    auto res = JsonValue::FromString(json_bytes.ToStringView());
+    if (!res) return rocksdb::Status::Corruption(res.Msg());
+    *value = *std::move(res);
+  } else if (metadata.format == JsonStorageFormat::CBOR) {
+    auto res = JsonValue::FromCBOR(json_bytes.ToStringView());
+    if (!res) return rocksdb::Status::Corruption(res.Msg());
+    *value = *std::move(res);
+  } else {
+    return rocksdb::Status::NotSupported("JSON storage format not supported");
+  }
+
+  return rocksdb::Status::OK();
+}
+
 rocksdb::Status Json::read(const Slice &ns_key, JsonMetadata *metadata, 
JsonValue *value) {
   std::string bytes;
   Slice rest;
@@ -61,19 +77,7 @@ rocksdb::Status Json::read(const Slice &ns_key, JsonMetadata 
*metadata, JsonValu
   auto s = GetMetadata(kRedisJson, ns_key, &bytes, metadata, &rest);
   if (!s.ok()) return s;
 
-  if (metadata->format == JsonStorageFormat::JSON) {
-    auto origin_res = JsonValue::FromString(rest.ToStringView());
-    if (!origin_res) return rocksdb::Status::Corruption(origin_res.Msg());
-    *value = *std::move(origin_res);
-  } else if (metadata->format == JsonStorageFormat::CBOR) {
-    auto origin_res = JsonValue::FromCBOR(rest.ToStringView());
-    if (!origin_res) return rocksdb::Status::Corruption(origin_res.Msg());
-    *value = *std::move(origin_res);
-  } else {
-    return rocksdb::Status::NotSupported("JSON storage format not supported");
-  }
-
-  return rocksdb::Status::OK();
+  return parse(*metadata, rest, value);
 }
 
 rocksdb::Status Json::create(const std::string &ns_key, JsonMetadata 
&metadata, const std::string &value) {
@@ -545,52 +549,23 @@ std::vector<rocksdb::Status> Json::MGet(const 
std::vector<std::string> &user_key
 }
 
 std::vector<rocksdb::Status> Json::readMulti(const std::vector<Slice> 
&ns_keys, std::vector<JsonValue> &values) {
-  std::vector<std::string> raw_values;
-  std::vector<JsonMetadata> meta_data;
-  raw_values.resize(ns_keys.size());
-  meta_data.resize(ns_keys.size());
-
-  auto statuses = getRawMetaData(ns_keys, meta_data, &raw_values);
-  for (size_t i = 0; i < ns_keys.size(); i++) {
-    if (!statuses[i].ok()) continue;
-    if (meta_data[i].format == JsonStorageFormat::JSON) {
-      auto res = JsonValue::FromString(raw_values[i]);
-      if (!res) {
-        statuses[i] = rocksdb::Status::Corruption(res.Msg());
-        continue;
-      }
-      values[i] = *std::move(res);
-    } else if (meta_data[i].format == JsonStorageFormat::CBOR) {
-      auto res = JsonValue::FromCBOR(raw_values[i]);
-      if (!res) {
-        statuses[i] = rocksdb::Status::Corruption(res.Msg());
-        continue;
-      }
-      values[i] = *std::move(res);
-    } else {
-      statuses[i] = rocksdb::Status::NotSupported("JSON storage format not 
supported");
-    }
-  }
-  return statuses;
-}
-
-std::vector<rocksdb::Status> Json::getRawMetaData(const std::vector<Slice> 
&ns_keys,
-                                                  std::vector<JsonMetadata> 
&metadatas,
-                                                  std::vector<std::string> 
*raw_values) {
   rocksdb::ReadOptions read_options = storage_->DefaultMultiGetOptions();
   LatestSnapShot ss(storage_);
   read_options.snapshot = ss.GetSnapShot();
-  raw_values->resize(ns_keys.size());
+
   std::vector<rocksdb::Status> statuses(ns_keys.size());
   std::vector<rocksdb::PinnableSlice> pin_values(ns_keys.size());
   storage_->MultiGet(read_options, metadata_cf_handle_, ns_keys.size(), 
ns_keys.data(), pin_values.data(),
                      statuses.data());
   for (size_t i = 0; i < ns_keys.size(); i++) {
     if (!statuses[i].ok()) continue;
-    Slice slice(pin_values[i].data(), pin_values[i].size());
-    statuses[i] = ParseMetadata(kRedisJson, &slice, &metadatas[i]);
+    Slice rest(pin_values[i].data(), pin_values[i].size());
+    JsonMetadata metadata;
+    statuses[i] = ParseMetadata({kRedisJson}, &rest, &metadata);
+    if (!statuses[i].ok()) continue;
+
+    statuses[i] = parse(metadata, rest, &values[i]);
     if (!statuses[i].ok()) continue;
-    (*raw_values)[i].assign(slice.data(), slice.size());
   }
   return statuses;
 }
diff --git a/src/types/redis_json.h b/src/types/redis_json.h
index a3993786..a2135b75 100644
--- a/src/types/redis_json.h
+++ b/src/types/redis_json.h
@@ -70,13 +70,12 @@ class Json : public Database {
  private:
   rocksdb::Status write(Slice ns_key, JsonMetadata *metadata, const JsonValue 
&json_val);
   rocksdb::Status read(const Slice &ns_key, JsonMetadata *metadata, JsonValue 
*value);
+  static rocksdb::Status parse(const JsonMetadata &metadata, const Slice 
&json_byt, JsonValue *value);
   rocksdb::Status create(const std::string &ns_key, JsonMetadata &metadata, 
const std::string &value);
   rocksdb::Status del(const Slice &ns_key);
   rocksdb::Status numop(JsonValue::NumOpEnum op, const std::string &user_key, 
const std::string &path,
                         const std::string &value, JsonValue *result);
   std::vector<rocksdb::Status> readMulti(const std::vector<Slice> &ns_keys, 
std::vector<JsonValue> &values);
-  std::vector<rocksdb::Status> getRawMetaData(const std::vector<Slice> 
&ns_keys, std::vector<JsonMetadata> &metadatas,
-                                              std::vector<std::string> 
*raw_values);
 };
 
 }  // namespace redis

Reply via email to