From 124b41eb3946b5b9cbf80d94bcecf8d24616cd55 Mon Sep 17 00:00:00 2001 From: JayLiu <38887641+luky116@users.noreply.github.com> Date: Thu, 8 Aug 2024 16:51:32 +0800 Subject: [PATCH] fix: add basic.tcl, fixed some bugs (#403) * fix Rename and Renamenx bug * add basic.tcl --------- Co-authored-by: liuyuecai --- src/storage/src/redis_hashes.cc | 82 ++++++++++++--------- src/storage/src/redis_lists.cc | 80 +++++++++++--------- src/storage/src/redis_sets.cc | 91 +++++++++++++---------- src/storage/src/redis_strings.cc | 56 ++++++++------ src/storage/src/redis_zsets.cc | 88 ++++++++++++---------- src/storage/src/storage.cc | 122 +++++++++++++------------------ tests/test_helper.tcl | 2 +- tests/unit/basic.tcl | 102 +++++++++++++++----------- tests/unit/keys.tcl | 1 + 9 files changed, 340 insertions(+), 284 deletions(-) diff --git a/src/storage/src/redis_hashes.cc b/src/storage/src/redis_hashes.cc index 9fa83c033..850230040 100644 --- a/src/storage/src/redis_hashes.cc +++ b/src/storage/src/redis_hashes.cc @@ -1150,21 +1150,27 @@ Status Redis::HashesRename(const Slice& key, Redis* new_inst, const Slice& newke BaseMetaKey base_meta_key(key); BaseMetaKey base_meta_newkey(newkey); s = db_->Get(default_read_options_, handles_[kMetaCF], base_meta_key.Encode(), &meta_value); - if (s.ok()) { - if (IsStale(meta_value)) { - return Status::NotFound(); - } - // copy a new hash with newkey - ParsedHashesMetaValue parsed_hashes_meta_value(&meta_value); - statistic = parsed_hashes_meta_value.Count(); - s = new_inst->GetDB()->Put(default_write_options_, handles_[kMetaCF], base_meta_newkey.Encode(), meta_value); - new_inst->UpdateSpecificKeyStatistics(DataType::kHashes, newkey.ToString(), statistic); - - // HashesDel key - parsed_hashes_meta_value.InitialMetaValue(); - s = db_->Put(default_write_options_, handles_[kMetaCF], base_meta_key.Encode(), meta_value); - UpdateSpecificKeyStatistics(DataType::kHashes, key.ToString(), statistic); + if (!s.ok() || !ExpectedMetaValue(DataType::kHashes, meta_value)) { + return s; + } + if (key == newkey) { + return Status::OK(); } + + if (IsStale(meta_value)) { + return Status::NotFound(); + } + // copy a new hash with newkey + ParsedHashesMetaValue parsed_hashes_meta_value(&meta_value); + statistic = parsed_hashes_meta_value.Count(); + s = new_inst->GetDB()->Put(default_write_options_, handles_[kMetaCF], base_meta_newkey.Encode(), meta_value); + new_inst->UpdateSpecificKeyStatistics(DataType::kHashes, newkey.ToString(), statistic); + + // HashesDel key + parsed_hashes_meta_value.InitialMetaValue(); + s = db_->Put(default_write_options_, handles_[kMetaCF], base_meta_key.Encode(), meta_value); + UpdateSpecificKeyStatistics(DataType::kHashes, key.ToString(), statistic); + return s; } @@ -1178,30 +1184,36 @@ Status Redis::HashesRenamenx(const Slice& key, Redis* new_inst, const Slice& new BaseMetaKey base_meta_key(key); BaseMetaKey base_meta_newkey(newkey); s = db_->Get(default_read_options_, handles_[kMetaCF], base_meta_key.Encode(), &meta_value); + if (!s.ok() || !ExpectedMetaValue(DataType::kHashes, meta_value)) { + return s; + } + if (key == newkey) { + return Status::Corruption(); + } + + if (IsStale(meta_value)) { + return Status::NotFound(); + } + ParsedHashesMetaValue parsed_hashes_meta_value(&meta_value); + // check if newkey exists. + std::string new_meta_value; + s = new_inst->GetDB()->Get(default_read_options_, handles_[kMetaCF], base_meta_newkey.Encode(), &new_meta_value); if (s.ok()) { - if (IsStale(meta_value)) { - return Status::NotFound(); + if (!IsStale(new_meta_value)) { + return Status::Corruption(); // newkey already exists. } - ParsedHashesMetaValue parsed_hashes_meta_value(&meta_value); - // check if newkey exists. - std::string new_meta_value; - s = new_inst->GetDB()->Get(default_read_options_, handles_[kMetaCF], base_meta_newkey.Encode(), &new_meta_value); - if (s.ok()) { - if (!IsStale(new_meta_value)) { - return Status::Corruption(); // newkey already exists. - } - } - ParsedHashesMetaValue parsed_hashes_new_meta_value(&new_meta_value); - // copy a new hash with newkey - statistic = parsed_hashes_meta_value.Count(); - s = new_inst->GetDB()->Put(default_write_options_, handles_[kMetaCF], base_meta_newkey.Encode(), meta_value); - new_inst->UpdateSpecificKeyStatistics(DataType::kHashes, newkey.ToString(), statistic); - - // HashesDel key - parsed_hashes_meta_value.InitialMetaValue(); - s = db_->Put(default_write_options_, handles_[kMetaCF], base_meta_key.Encode(), meta_value); - UpdateSpecificKeyStatistics(DataType::kHashes, key.ToString(), statistic); } + ParsedHashesMetaValue parsed_hashes_new_meta_value(&new_meta_value); + // copy a new hash with newkey + statistic = parsed_hashes_meta_value.Count(); + s = new_inst->GetDB()->Put(default_write_options_, handles_[kMetaCF], base_meta_newkey.Encode(), meta_value); + new_inst->UpdateSpecificKeyStatistics(DataType::kHashes, newkey.ToString(), statistic); + + // HashesDel key + parsed_hashes_meta_value.InitialMetaValue(); + s = db_->Put(default_write_options_, handles_[kMetaCF], base_meta_key.Encode(), meta_value); + UpdateSpecificKeyStatistics(DataType::kHashes, key.ToString(), statistic); + return s; } diff --git a/src/storage/src/redis_lists.cc b/src/storage/src/redis_lists.cc index d6c6391a3..ca7187ea7 100644 --- a/src/storage/src/redis_lists.cc +++ b/src/storage/src/redis_lists.cc @@ -981,21 +981,27 @@ Status Redis::ListsRename(const Slice& key, Redis* new_inst, const Slice& newkey BaseMetaKey base_meta_key(key); BaseMetaKey base_meta_newkey(newkey); Status s = db_->Get(default_read_options_, handles_[kMetaCF], base_meta_key.Encode(), &meta_value); - if (s.ok()) { - if (IsStale(meta_value)) { - return Status::NotFound(); - } - // copy a new list with newkey - ParsedListsMetaValue parsed_lists_meta_value(&meta_value); - statistic = parsed_lists_meta_value.Count(); - s = new_inst->GetDB()->Put(default_write_options_, handles_[kMetaCF], base_meta_newkey.Encode(), meta_value); - new_inst->UpdateSpecificKeyStatistics(DataType::kLists, newkey.ToString(), statistic); + if (!s.ok() || !ExpectedMetaValue(DataType::kLists, meta_value)) { + return s; + } + if (key == newkey) { + return Status::OK(); + } - // ListsDel key - parsed_lists_meta_value.InitialMetaValue(); - s = db_->Put(default_write_options_, handles_[kMetaCF], base_meta_key.Encode(), meta_value); - UpdateSpecificKeyStatistics(DataType::kLists, key.ToString(), statistic); + if (IsStale(meta_value)) { + return Status::NotFound(); } + // copy a new list with newkey + ParsedListsMetaValue parsed_lists_meta_value(&meta_value); + statistic = parsed_lists_meta_value.Count(); + s = new_inst->GetDB()->Put(default_write_options_, handles_[kMetaCF], base_meta_newkey.Encode(), meta_value); + new_inst->UpdateSpecificKeyStatistics(DataType::kLists, newkey.ToString(), statistic); + + // ListsDel key + parsed_lists_meta_value.InitialMetaValue(); + s = db_->Put(default_write_options_, handles_[kMetaCF], base_meta_key.Encode(), meta_value); + UpdateSpecificKeyStatistics(DataType::kLists, key.ToString(), statistic); + return s; } @@ -1008,30 +1014,36 @@ Status Redis::ListsRenamenx(const Slice& key, Redis* new_inst, const Slice& newk BaseMetaKey base_meta_key(key); BaseMetaKey base_meta_newkey(newkey); Status s = db_->Get(default_read_options_, handles_[kMetaCF], base_meta_key.Encode(), &meta_value); + if (!s.ok() || !ExpectedMetaValue(DataType::kLists, meta_value)) { + return s; + } + if (key == newkey) { + return Status::Corruption(); + } + + if (IsStale(meta_value)) { + return Status::NotFound(); + } + // check if newkey exists. + std::string new_meta_value; + ParsedListsMetaValue parsed_lists_meta_value(&meta_value); + s = new_inst->GetDB()->Get(default_read_options_, handles_[kMetaCF], base_meta_newkey.Encode(), &new_meta_value); if (s.ok()) { - if (IsStale(meta_value)) { - return Status::NotFound(); - } - // check if newkey exists. - std::string new_meta_value; - ParsedListsMetaValue parsed_lists_meta_value(&meta_value); - s = new_inst->GetDB()->Get(default_read_options_, handles_[kMetaCF], base_meta_newkey.Encode(), &new_meta_value); - if (s.ok()) { - if (IsStale(new_meta_value)) { - return Status::Corruption(); // newkey already exists. - } + if (IsStale(new_meta_value)) { + return Status::Corruption(); // newkey already exists. } - ParsedSetsMetaValue parsed_lists_new_meta_value(&new_meta_value); - // copy a new list with newkey - statistic = parsed_lists_meta_value.Count(); - s = new_inst->GetDB()->Put(default_write_options_, handles_[kMetaCF], base_meta_newkey.Encode(), meta_value); - new_inst->UpdateSpecificKeyStatistics(DataType::kLists, newkey.ToString(), statistic); - - // ListsDel key - parsed_lists_meta_value.InitialMetaValue(); - s = db_->Put(default_write_options_, handles_[kMetaCF], base_meta_key.Encode(), meta_value); - UpdateSpecificKeyStatistics(DataType::kLists, key.ToString(), statistic); } + ParsedSetsMetaValue parsed_lists_new_meta_value(&new_meta_value); + // copy a new list with newkey + statistic = parsed_lists_meta_value.Count(); + s = new_inst->GetDB()->Put(default_write_options_, handles_[kMetaCF], base_meta_newkey.Encode(), meta_value); + new_inst->UpdateSpecificKeyStatistics(DataType::kLists, newkey.ToString(), statistic); + + // ListsDel key + parsed_lists_meta_value.InitialMetaValue(); + s = db_->Put(default_write_options_, handles_[kMetaCF], base_meta_key.Encode(), meta_value); + UpdateSpecificKeyStatistics(DataType::kLists, key.ToString(), statistic); + return s; } diff --git a/src/storage/src/redis_sets.cc b/src/storage/src/redis_sets.cc index dfa5ba8ab..ca2170ad1 100644 --- a/src/storage/src/redis_sets.cc +++ b/src/storage/src/redis_sets.cc @@ -1244,23 +1244,32 @@ Status Redis::SetsRename(const Slice& key, Redis* new_inst, const Slice& newkey) BaseMetaKey base_meta_key(key); BaseMetaKey base_meta_newkey(newkey); rocksdb::Status s = db_->Get(default_read_options_, handles_[kMetaCF], base_meta_key.Encode(), &meta_value); - if (s.ok()) { - ParsedSetsMetaValue parsed_sets_meta_value(&meta_value); - if (parsed_sets_meta_value.IsStale()) { - return rocksdb::Status::NotFound("Stale"); - } else if (parsed_sets_meta_value.Count() == 0) { - return rocksdb::Status::NotFound(); - } - // copy a new set with newkey - statistic = parsed_sets_meta_value.Count(); - s = new_inst->GetDB()->Put(default_write_options_, handles_[kMetaCF], base_meta_newkey.Encode(), meta_value); - new_inst->UpdateSpecificKeyStatistics(DataType::kSets, newkey.ToString(), statistic); + if (!s.ok()) { + return s; + } + if (!s.ok() || !ExpectedMetaValue(DataType::kSets, meta_value)) { + return s; + } + if (key == newkey) { + return Status::OK(); + } - // SetsDel key - parsed_sets_meta_value.InitialMetaValue(); - s = db_->Put(default_write_options_, handles_[kMetaCF], base_meta_key.Encode(), meta_value); - UpdateSpecificKeyStatistics(DataType::kSets, key.ToString(), statistic); + ParsedSetsMetaValue parsed_sets_meta_value(&meta_value); + if (parsed_sets_meta_value.IsStale()) { + return rocksdb::Status::NotFound("Stale"); + } else if (parsed_sets_meta_value.Count() == 0) { + return rocksdb::Status::NotFound(); } + // copy a new set with newkey + statistic = parsed_sets_meta_value.Count(); + s = new_inst->GetDB()->Put(default_write_options_, handles_[kMetaCF], base_meta_newkey.Encode(), meta_value); + new_inst->UpdateSpecificKeyStatistics(DataType::kSets, newkey.ToString(), statistic); + + // SetsDel key + parsed_sets_meta_value.InitialMetaValue(); + s = db_->Put(default_write_options_, handles_[kMetaCF], base_meta_key.Encode(), meta_value); + UpdateSpecificKeyStatistics(DataType::kSets, key.ToString(), statistic); + return s; } @@ -1273,33 +1282,39 @@ Status Redis::SetsRenamenx(const Slice& key, Redis* new_inst, const Slice& newke BaseMetaKey base_meta_key(key); BaseMetaKey base_meta_newkey(newkey); rocksdb::Status s = db_->Get(default_read_options_, handles_[kMetaCF], base_meta_key.Encode(), &meta_value); + if (!s.ok() || !ExpectedMetaValue(DataType::kSets, meta_value)) { + return s; + } + if (key == newkey) { + return Status::Corruption(); + } + + ParsedSetsMetaValue parsed_sets_meta_value(&meta_value); + if (parsed_sets_meta_value.IsStale()) { + return rocksdb::Status::NotFound("Stale"); + } else if (parsed_sets_meta_value.Count() == 0) { + return rocksdb::Status::NotFound(); + } + // check if newkey exists. + std::string new_meta_value; + s = new_inst->GetDB()->Get(default_read_options_, handles_[kMetaCF], base_meta_newkey.Encode(), &new_meta_value); if (s.ok()) { - ParsedSetsMetaValue parsed_sets_meta_value(&meta_value); - if (parsed_sets_meta_value.IsStale()) { - return rocksdb::Status::NotFound("Stale"); - } else if (parsed_sets_meta_value.Count() == 0) { - return rocksdb::Status::NotFound(); - } - // check if newkey exists. - std::string new_meta_value; - s = new_inst->GetDB()->Get(default_read_options_, handles_[kMetaCF], base_meta_newkey.Encode(), &new_meta_value); - if (s.ok()) { - ParsedSetsMetaValue parsed_sets_new_meta_value(&new_meta_value); - if (!parsed_sets_new_meta_value.IsStale() && parsed_sets_new_meta_value.Count() != 0) { - return Status::Corruption(); // newkey already exists. - } + ParsedSetsMetaValue parsed_sets_new_meta_value(&new_meta_value); + if (!parsed_sets_new_meta_value.IsStale() && parsed_sets_new_meta_value.Count() != 0) { + return Status::Corruption(); // newkey already exists. } + } - // copy a new set with newkey - statistic = parsed_sets_meta_value.Count(); - s = new_inst->GetDB()->Put(default_write_options_, handles_[kMetaCF], base_meta_newkey.Encode(), meta_value); - new_inst->UpdateSpecificKeyStatistics(DataType::kSets, newkey.ToString(), statistic); + // copy a new set with newkey + statistic = parsed_sets_meta_value.Count(); + s = new_inst->GetDB()->Put(default_write_options_, handles_[kMetaCF], base_meta_newkey.Encode(), meta_value); + new_inst->UpdateSpecificKeyStatistics(DataType::kSets, newkey.ToString(), statistic); + + // SetsDel key + parsed_sets_meta_value.InitialMetaValue(); + s = db_->Put(default_write_options_, handles_[kMetaCF], base_meta_key.Encode(), meta_value); + UpdateSpecificKeyStatistics(DataType::kSets, key.ToString(), statistic); - // SetsDel key - parsed_sets_meta_value.InitialMetaValue(); - s = db_->Put(default_write_options_, handles_[kMetaCF], base_meta_key.Encode(), meta_value); - UpdateSpecificKeyStatistics(DataType::kSets, key.ToString(), statistic); - } return s; } diff --git a/src/storage/src/redis_strings.cc b/src/storage/src/redis_strings.cc index 60c0bdfd9..5ea64c5f8 100644 --- a/src/storage/src/redis_strings.cc +++ b/src/storage/src/redis_strings.cc @@ -517,9 +517,9 @@ Status Redis::Incrby(const Slice& key, int64_t value, int64_t* ret) { StringsValue strings_value(buf); return db_->Put(default_write_options_, base_key.Encode(), strings_value.Encode()); } else if (!ExpectedMetaValue(DataType::kStrings, old_value)) { - return Status::InvalidArgument(fmt::format("WRONGTYPE, key: {}, expect type: {}, get type: {}", key.ToString(), - DataTypeStrings[static_cast(DataType::kStrings)], - DataTypeStrings[static_cast(GetMetaValueType(old_value))])); + return Status::NotSupported(fmt::format("WRONGTYPE, key: {}, expect type: {}, get type: {}", key.ToString(), + DataTypeStrings[static_cast(DataType::kStrings)], + DataTypeStrings[static_cast(GetMetaValueType(old_value))])); } else { ParsedStringsValue parsed_strings_value(&old_value); uint64_t timestamp = parsed_strings_value.Etime(); @@ -886,6 +886,9 @@ Status Redis::Setrange(const Slice& key, int64_t start_offset, const Slice& valu strings_value.SetEtime(timestamp); return db_->Put(default_write_options_, base_key.Encode(), strings_value.Encode()); } else if (s.IsNotFound()) { + if (value.empty()) { // ignore empty value + return Status::OK(); + } std::string tmp(start_offset, '\0'); new_value = tmp.append(value.data()); *ret = static_cast(new_value.length()); @@ -1129,13 +1132,18 @@ Status Redis::StringsRename(const Slice& key, Redis* new_inst, const Slice& newk BaseKey base_key(key); BaseKey base_newkey(newkey); s = db_->Get(default_read_options_, base_key.Encode(), &value); - if (s.ok()) { - if (IsStale(value)) { - return Status::NotFound("Stale"); - } - db_->Delete(default_write_options_, base_key.Encode()); - s = new_inst->GetDB()->Put(default_write_options_, base_newkey.Encode(), value); + if (!s.ok() || !ExpectedMetaValue(DataType::kStrings, value)) { + return s; + } + if (key == newkey) { + return Status::OK(); + } + + if (IsStale(value)) { + return Status::NotFound("Stale"); } + db_->Delete(default_write_options_, base_key.Encode()); + s = new_inst->GetDB()->Put(default_write_options_, base_newkey.Encode(), value); return s; } @@ -1148,20 +1156,26 @@ Status Redis::StringsRenamenx(const Slice& key, Redis* new_inst, const Slice& ne BaseKey base_key(key); BaseKey base_newkey(newkey); s = db_->Get(default_read_options_, base_key.Encode(), &value); + if (!s.ok() || !ExpectedMetaValue(DataType::kStrings, value)) { + return s; + } + if (key == newkey) { + return Status::Corruption(); + } + + if (IsStale(value)) { + return Status::NotFound("Stale"); + } + // check if newkey exists. + s = new_inst->GetDB()->Get(default_read_options_, base_newkey.Encode(), &value); if (s.ok()) { - if (IsStale(value)) { - return Status::NotFound("Stale"); + if (!IsStale(value)) { + return Status::Corruption(); // newkey already exists. } - // check if newkey exists. - s = new_inst->GetDB()->Get(default_read_options_, base_newkey.Encode(), &value); - if (s.ok()) { - if (!IsStale(value)) { - return Status::Corruption(); // newkey already exists. - } - } - db_->Delete(default_write_options_, base_key.Encode()); - s = new_inst->GetDB()->Put(default_write_options_, base_newkey.Encode(), value); } + db_->Delete(default_write_options_, base_key.Encode()); + s = new_inst->GetDB()->Put(default_write_options_, base_newkey.Encode(), value); + return s; } @@ -1596,7 +1610,7 @@ Status Redis::GetType(const Slice& key, enum DataType& type) { if (s.ok()) { type = static_cast(static_cast(meta_value[0])); } - return Status::OK(); + return s; } Status Redis::IsExist(const Slice& key) { diff --git a/src/storage/src/redis_zsets.cc b/src/storage/src/redis_zsets.cc index c12fed800..d70948baa 100644 --- a/src/storage/src/redis_zsets.cc +++ b/src/storage/src/redis_zsets.cc @@ -1576,23 +1576,29 @@ Status Redis::ZsetsRename(const Slice& key, Redis* new_inst, const Slice& newkey BaseMetaKey base_meta_key(key); BaseMetaKey base_meta_newkey(newkey); Status s = db_->Get(default_read_options_, handles_[kMetaCF], base_meta_key.Encode(), &meta_value); - if (s.ok()) { - ParsedZSetsMetaValue parsed_zsets_meta_value(&meta_value); - if (parsed_zsets_meta_value.IsStale()) { - return Status::NotFound("Stale"); - } else if (parsed_zsets_meta_value.Count() == 0) { - return Status::NotFound(); - } - // copy a new zset with newkey - statistic = parsed_zsets_meta_value.Count(); - s = new_inst->GetDB()->Put(default_write_options_, handles_[kMetaCF], base_meta_newkey.Encode(), meta_value); - new_inst->UpdateSpecificKeyStatistics(DataType::kZSets, newkey.ToString(), statistic); + if (!s.ok() || !ExpectedMetaValue(DataType::kZSets, meta_value)) { + return s; + } + if (key == newkey) { + return Status::OK(); + } - // ZsetsDel key - parsed_zsets_meta_value.InitialMetaValue(); - s = db_->Put(default_write_options_, handles_[kMetaCF], base_meta_key.Encode(), meta_value); - UpdateSpecificKeyStatistics(DataType::kZSets, key.ToString(), statistic); + ParsedZSetsMetaValue parsed_zsets_meta_value(&meta_value); + if (parsed_zsets_meta_value.IsStale()) { + return Status::NotFound("Stale"); + } else if (parsed_zsets_meta_value.Count() == 0) { + return Status::NotFound(); } + // copy a new zset with newkey + statistic = parsed_zsets_meta_value.Count(); + s = new_inst->GetDB()->Put(default_write_options_, handles_[kMetaCF], base_meta_newkey.Encode(), meta_value); + new_inst->UpdateSpecificKeyStatistics(DataType::kZSets, newkey.ToString(), statistic); + + // ZsetsDel key + parsed_zsets_meta_value.InitialMetaValue(); + s = db_->Put(default_write_options_, handles_[kMetaCF], base_meta_key.Encode(), meta_value); + UpdateSpecificKeyStatistics(DataType::kZSets, key.ToString(), statistic); + return s; } @@ -1605,33 +1611,39 @@ Status Redis::ZsetsRenamenx(const Slice& key, Redis* new_inst, const Slice& newk BaseMetaKey base_meta_key(key); BaseMetaKey base_meta_newkey(newkey); Status s = db_->Get(default_read_options_, handles_[kMetaCF], base_meta_key.Encode(), &meta_value); + if (!s.ok() || !ExpectedMetaValue(DataType::kZSets, meta_value)) { + return s; + } + if (key == newkey) { + return Status::Corruption(); + } + + ParsedZSetsMetaValue parsed_zsets_meta_value(&meta_value); + if (parsed_zsets_meta_value.IsStale()) { + return Status::NotFound("Stale"); + } else if (parsed_zsets_meta_value.Count() == 0) { + return Status::NotFound(); + } + // check if newkey exist. + std::string new_meta_value; + s = new_inst->GetDB()->Get(default_read_options_, handles_[kMetaCF], base_meta_newkey.Encode(), &new_meta_value); if (s.ok()) { - ParsedZSetsMetaValue parsed_zsets_meta_value(&meta_value); - if (parsed_zsets_meta_value.IsStale()) { - return Status::NotFound("Stale"); - } else if (parsed_zsets_meta_value.Count() == 0) { - return Status::NotFound(); - } - // check if newkey exist. - std::string new_meta_value; - s = new_inst->GetDB()->Get(default_read_options_, handles_[kMetaCF], base_meta_newkey.Encode(), &new_meta_value); - if (s.ok()) { - ParsedSetsMetaValue parsed_zsets_new_meta_value(&new_meta_value); - if (!parsed_zsets_new_meta_value.IsStale() && parsed_zsets_new_meta_value.Count() != 0) { - return Status::Corruption(); // newkey already exists. - } + ParsedSetsMetaValue parsed_zsets_new_meta_value(&new_meta_value); + if (!parsed_zsets_new_meta_value.IsStale() && parsed_zsets_new_meta_value.Count() != 0) { + return Status::Corruption(); // newkey already exists. } + } - // copy a new zset with newkey - statistic = parsed_zsets_meta_value.Count(); - s = new_inst->GetDB()->Put(default_write_options_, handles_[kMetaCF], base_meta_newkey.Encode(), meta_value); - new_inst->UpdateSpecificKeyStatistics(DataType::kZSets, newkey.ToString(), statistic); + // copy a new zset with newkey + statistic = parsed_zsets_meta_value.Count(); + s = new_inst->GetDB()->Put(default_write_options_, handles_[kMetaCF], base_meta_newkey.Encode(), meta_value); + new_inst->UpdateSpecificKeyStatistics(DataType::kZSets, newkey.ToString(), statistic); + + // ZsetsDel key + parsed_zsets_meta_value.InitialMetaValue(); + s = db_->Put(default_write_options_, handles_[kMetaCF], base_meta_key.Encode(), meta_value); + UpdateSpecificKeyStatistics(DataType::kZSets, key.ToString(), statistic); - // ZsetsDel key - parsed_zsets_meta_value.InitialMetaValue(); - s = db_->Put(default_write_options_, handles_[kMetaCF], base_meta_key.Encode(), meta_value); - UpdateSpecificKeyStatistics(DataType::kZSets, key.ToString(), statistic); - } return s; } diff --git a/src/storage/src/storage.cc b/src/storage/src/storage.cc index 619b87832..b8d48b2c1 100644 --- a/src/storage/src/storage.cc +++ b/src/storage/src/storage.cc @@ -1523,8 +1523,7 @@ int64_t Storage::TTL(const Slice& key) { Status Storage::GetType(const std::string& key, enum DataType& type) { auto& inst = GetDBInstance(key); - inst->GetType(key, type); - return Status::OK(); + return inst->GetType(key, type); } Status Storage::Keys(const DataType& data_type, const std::string& pattern, std::vector* keys) { @@ -1548,99 +1547,76 @@ Status Storage::Keys(const DataType& data_type, const std::string& pattern, std: } Status Storage::Rename(const std::string& key, const std::string& newkey) { - Status ret = Status::NotFound(); auto& inst = GetDBInstance(key); auto& new_inst = GetDBInstance(newkey); - // Strings - Status s = inst->StringsRename(key, new_inst.get(), newkey); - if (s.ok()) { - ret = Status::OK(); - } else if (!s.IsNotFound()) { - return s; - } - - // Hashes - s = inst->HashesRename(key, new_inst.get(), newkey); - if (s.ok()) { - ret = Status::OK(); - } else if (!s.IsNotFound()) { - return s; - } - - // Sets - s = inst->SetsRename(key, new_inst.get(), newkey); - if (s.ok()) { - ret = Status::OK(); - } else if (!s.IsNotFound()) { + DataType type; + Status s = GetType(key, type); + if (!s.ok()) { return s; } - - // Lists - s = inst->ListsRename(key, new_inst.get(), newkey); - if (s.ok()) { - ret = Status::OK(); - } else if (!s.IsNotFound()) { - return s; + if (key == newkey) { + return Status::OK(); } - // ZSets - s = inst->ZsetsRename(key, new_inst.get(), newkey); - if (s.ok()) { - ret = Status::OK(); - } else if (!s.IsNotFound()) { - return s; + switch (type) { + case DataType::kStrings: + s = inst->StringsRename(key, new_inst.get(), newkey); + break; + case DataType::kHashes: + s = inst->HashesRename(key, new_inst.get(), newkey); + break; + case DataType::kSets: + s = inst->SetsRename(key, new_inst.get(), newkey); + break; + case DataType::kZSets: + s = inst->ZsetsRename(key, new_inst.get(), newkey); + break; + case DataType::kLists: + s = inst->ListsRename(key, new_inst.get(), newkey); + break; + default: + return Status::NotFound(); } - return ret; + return s; } Status Storage::Renamenx(const std::string& key, const std::string& newkey) { - Status ret = Status::NotFound(); auto& inst = GetDBInstance(key); auto& new_inst = GetDBInstance(newkey); - // Strings - Status s = inst->StringsRenamenx(key, new_inst.get(), newkey); - if (s.ok()) { - ret = Status::OK(); - } else if (!s.IsNotFound()) { - return s; - } - - // Hashes - s = inst->HashesRenamenx(key, new_inst.get(), newkey); - if (s.ok()) { - ret = Status::OK(); - } else if (!s.IsNotFound()) { + DataType type; + Status s = GetType(key, type); + if (!s.ok()) { return s; } - // Sets - s = inst->SetsRenamenx(key, new_inst.get(), newkey); - if (s.ok()) { - ret = Status::OK(); - } else if (!s.IsNotFound()) { - return s; + if (key == newkey) { + return Status::Corruption(); } - // Lists - s = inst->ListsRenamenx(key, new_inst.get(), newkey); - if (s.ok()) { - ret = Status::OK(); - } else if (!s.IsNotFound()) { - return s; - } - - // ZSets - s = inst->ZsetsRenamenx(key, new_inst.get(), newkey); - if (s.ok()) { - ret = Status::OK(); - } else if (!s.IsNotFound()) { - return s; + switch (type) { + case DataType::kStrings: + s = inst->StringsRenamenx(key, new_inst.get(), newkey); + break; + case DataType::kHashes: + s = inst->HashesRenamenx(key, new_inst.get(), newkey); + break; + case DataType::kSets: + s = inst->SetsRenamenx(key, new_inst.get(), newkey); + break; + case DataType::kZSets: + s = inst->ZsetsRenamenx(key, new_inst.get(), newkey); + break; + case DataType::kLists: + s = inst->ListsRenamenx(key, new_inst.get(), newkey); + break; + default: + return Status::NotFound(); } - return ret; + return s; } void Storage::ScanDatabase(const DataType& type) { diff --git a/tests/test_helper.tcl b/tests/test_helper.tcl index aef0c4bf4..938edaeec 100644 --- a/tests/test_helper.tcl +++ b/tests/test_helper.tcl @@ -13,7 +13,7 @@ source tests/support/util.tcl set ::all_tests { # unit/printver - # unit/basic + unit/basic # unit/scan # unit/multi unit/quit diff --git a/tests/unit/basic.tcl b/tests/unit/basic.tcl index f9f29d22d..654b04461 100644 --- a/tests/unit/basic.tcl +++ b/tests/unit/basic.tcl @@ -1,5 +1,6 @@ start_server {tags {"basic"}} { +# Pikiwidb does not support the dbsize command # test {DEL all keys to start with a clean DB} { # foreach key [r keys *] {r del $key} # r dbsize @@ -38,12 +39,14 @@ start_server {tags {"basic"}} { lsort [r keys *] } {foo_a foo_b foo_c key_x key_y key_z} +# Pikiwidb does not support the dbsize command # test {DBSIZE} { # r info keyspace 1 # after 1000 # r dbsize # } {6} +# Pikiwidb does not support the dbsize command # test {DEL all keys} { # foreach key [r keys *] {r del $key} # r info keyspace 1 @@ -51,50 +54,51 @@ start_server {tags {"basic"}} { # r dbsize # } {0} -# test {Very big payload in GET/SET} { -# set buf [string repeat "abcd" 1000000] -# r set foo $buf -# r get foo -# } [string repeat "abcd" 1000000] - -# tags {"slow"} { -# test {Very big payload random access} { -# set err {} -# array set payload {} -# for {set j 0} {$j < 100} {incr j} { -# set size [expr 1+[randomInt 100000]] -# set buf [string repeat "pl-$j" $size] -# set payload($j) $buf -# r set bigpayload_$j $buf -# } -# for {set j 0} {$j < 1000} {incr j} { -# set index [randomInt 100] -# set buf [r get bigpayload_$index] -# if {$buf != $payload($index)} { -# set err "Values differ: I set '$payload($index)' but I read back '$buf'" -# break -# } -# } -# unset payload -# set _ $err -# } {} -# -# test {SET 10000 numeric keys and access all them in reverse order} { -# set err {} -# for {set x 0} {$x < 10000} {incr x} { -# r set $x $x -# } -# set sum 0 -# for {set x 9999} {$x >= 0} {incr x -1} { -# set val [r get $x] -# if {$val ne $x} { -# set err "Element at position $x is $val instead of $x" -# break -# } -# } -# set _ $err -# } {} - + test {Very big payload in GET/SET} { + set buf [string repeat "abcd" 1000000] + r set foo $buf + r get foo + } [string repeat "abcd" 1000000] + + tags {"slow"} { + test {Very big payload random access} { + set err {} + array set payload {} + for {set j 0} {$j < 100} {incr j} { + set size [expr 1+[randomInt 100000]] + set buf [string repeat "pl-$j" $size] + set payload($j) $buf + r set bigpayload_$j $buf + } + for {set j 0} {$j < 1000} {incr j} { + set index [randomInt 100] + set buf [r get bigpayload_$index] + if {$buf != $payload($index)} { + set err "Values differ: I set '$payload($index)' but I read back '$buf'" + break + } + } + unset payload + set _ $err + } {} + + test {SET 10000 numeric keys and access all them in reverse order} { + set err {} + for {set x 0} {$x < 10000} {incr x} { + r set $x $x + } + set sum 0 + for {set x 9999} {$x >= 0} {incr x -1} { + set val [r get $x] + if {$val ne $x} { + set err "Element at position $x is $val instead of $x" + break + } + } + set _ $err + } {} + +# Pikiwidb does not support the dbsize command # test {DBSIZE should be 10101 now} { # r info keyspace 1 # after 1000 @@ -127,6 +131,7 @@ start_server {tags {"basic"}} { r incrby novar 17179869184 } {34359738368} +# TODO 待讨论是否要兼容 # test {INCR fails against key with spaces (left)} { # r set novar " 11" # catch {r incr novar} err @@ -145,6 +150,7 @@ start_server {tags {"basic"}} { format $err } {ERR*} +# TODO wait util pikiwidb compatibled redis error code specification, ref issue: https://github.com/OpenAtomFoundation/pikiwidb/issues/382 # test {INCR fails against a key holding a list} { # r rpush mylist 1 # catch {r incr mylist} err @@ -201,6 +207,7 @@ start_server {tags {"basic"}} { format $err } {ERR*valid*} +# TODO wait util pikiwidb compatibled redis error code specification, ref issue: https://github.com/OpenAtomFoundation/pikiwidb/issues/382 # test {INCRBYFLOAT fails against a key holding a list} { # r del mylist # set err {} @@ -268,6 +275,7 @@ start_server {tags {"basic"}} { assert_equal 20 [r get x] } +# Pikiwidb does not support the set-active-expire command # test "DEL against expired key" { # r debug set-active-expire 0 # r setex keyExpire 1 valExpire @@ -292,6 +300,7 @@ start_server {tags {"basic"}} { append res [r exists emptykey] } {10} +# Pikiwidb does not support the read command # test {Commands pipelining} { # set fd [r channel] # puts -nonewline $fd "SET k1 xyzk\r\nGET k1\r\nPING\r\n" @@ -392,6 +401,7 @@ start_server {tags {"basic"}} { r ttl mykey2 } {-1} +# Pikiwidb does not support the dbsize command # test {DEL all keys again (DB 0)} { # foreach key [r keys *] { # r del $key @@ -399,6 +409,7 @@ start_server {tags {"basic"}} { # r dbsize # } {0} +# Pikiwidb does not support the dbsize command # test {DEL all keys again (DB 1)} { # r select 10 # foreach key [r keys *] { @@ -409,6 +420,7 @@ start_server {tags {"basic"}} { # format $res # } {0} +# Pikiwidb does not support the dbsize command # test {MOVE basic usage} { # r set mykey foobar # r move mykey 10 @@ -422,11 +434,13 @@ start_server {tags {"basic"}} { # format $res # } [list 0 0 foobar 1] +# Pikiwidb does not support the move command # test {MOVE against key existing in the target DB} { # r set mykey hello # r move mykey 10 # } {0} +# Pikiwidb does not support the move command # test {MOVE against non-integer DB (#1428)} { # r set mykey hello # catch {r move mykey notanumber} e diff --git a/tests/unit/keys.tcl b/tests/unit/keys.tcl index cb62444f3..9179e1b57 100644 --- a/tests/unit/keys.tcl +++ b/tests/unit/keys.tcl @@ -1,3 +1,4 @@ +# TODO all param is invalid start_server {tags {"keys"}} { test {KEYS with pattern} { foreach key {key_x key_y key_z foo_a foo_b foo_c} {