From 59f4cbef8c3ada628c47ff7868a93c7d01e02fd7 Mon Sep 17 00:00:00 2001 From: Jay Huh Date: Wed, 24 Jan 2024 11:35:12 -0800 Subject: [PATCH] MultiGet support in ldb (#12283) Summary: While investigating test failures due to the inconsistency between `Get()` and `MultiGet()`, I realized that LDB currently doesn't support `MultiGet()`. This PR introduces the `MultiGet()` support in LDB. Tested the command manually. Unit test will follow in a separate PR. Pull Request resolved: https://github.com/facebook/rocksdb/pull/12283 Test Plan: When key not found ``` $> ./ldb --db=/data/users/jewoongh/rocksdb_test/T173992396/rocksdb_crashtest_blackbox --hex multi_get 0x0000000000000009000000000000012B00000000000002AB Status for key 0x0000000000000009000000000000012B00000000000002AB: NotFound: ``` Compare the same key with get ``` $> ./ldb --db=/data/users/jewoongh/rocksdb_test/T173992396/rocksdb_crashtest_blackbox --hex get 0x0000000000000009000000000000012B00000000000002AB Failed: Get failed: NotFound: ``` Multiple keys not found ``` $> ./ldb --db=/data/users/jewoongh/rocksdb_test/T173992396/rocksdb_crashtest_blackbox --hex multi_get 0x0000000000000009000000000000012B00000000000002AB 0x0000000000000009000000000000012B00000000000002AC Status for key 0x0000000000000009000000000000012B00000000000002AB: NotFound: Status for key 0x0000000000000009000000000000012B00000000000002AC: NotFound: ``` One of the keys found ``` $> ./ldb --db=/data/users/jewoongh/rocksdb_test/T173992396/rocksdb_crashtest_blackbox --hex multi_get 0x0000000000000009000000000000012B00000000000002AB 0x00000000000000090000000000000026787878787878 Status for key 0x0000000000000009000000000000012B00000000000002AB: NotFound: 0x22000000262724252A2B28292E2F2C2D32333031363734353A3B38393E3F3C3D02030001060704050A0B08090E0F0C0D12131011161714151A1B18191E1F1C1D ``` All of the keys found ``` $> ./ldb --db=/data/users/jewoongh/rocksdb_test/T173992396/rocksdb_crashtest_blackbox --hex multi_get 0x0000000000000009000000000000012B00000000000000D8 0x00000000000000090000000000000026787878787878 15:57:03 0x47000000434241404F4E4D4C4B4A494857565554535251505F5E5D5C5B5A595867666564636261606F6E6D6C6B6A696877767574737271707F7E7D7C7B7A797807060504030201000F0E0D0C0B0A090817161514131211101F1E1D1C1B1A1918 0x22000000262724252A2B28292E2F2C2D32333031363734353A3B38393E3F3C3D02030001060704050A0B08090E0F0C0D12131011161714151A1B18191E1F1C1D ``` Reviewed By: hx235 Differential Revision: D53048519 Pulled By: jaykorean fbshipit-source-id: a6217905464c5f460a222e2b883bdff47b9dd9c7 --- tools/ldb_cmd.cc | 63 ++++++++++++++++++++++++++++++++++++++++++++ tools/ldb_cmd_impl.h | 16 +++++++++++ 2 files changed, 79 insertions(+) diff --git a/tools/ldb_cmd.cc b/tools/ldb_cmd.cc index 90b7886eea1..e7933f42cc4 100644 --- a/tools/ldb_cmd.cc +++ b/tools/ldb_cmd.cc @@ -208,6 +208,9 @@ LDBCommand* LDBCommand::SelectCommand(const ParsedParams& parsed_params) { if (parsed_params.cmd == GetCommand::Name()) { return new GetCommand(parsed_params.cmd_params, parsed_params.option_map, parsed_params.flags); + } else if (parsed_params.cmd == MultiGetCommand::Name()) { + return new MultiGetCommand(parsed_params.cmd_params, + parsed_params.option_map, parsed_params.flags); } else if (parsed_params.cmd == GetEntityCommand::Name()) { return new GetEntityCommand(parsed_params.cmd_params, parsed_params.option_map, parsed_params.flags); @@ -2872,6 +2875,66 @@ void GetCommand::DoCommand() { // ---------------------------------------------------------------------------- +MultiGetCommand::MultiGetCommand( + const std::vector& params, + const std::map& options, + const std::vector& flags) + : LDBCommand(options, flags, true, + BuildCmdLineOptions({ARG_HEX, ARG_KEY_HEX, ARG_VALUE_HEX})) { + if (params.size() < 1) { + exec_state_ = LDBCommandExecuteResult::Failed( + "At least one must be specified for multi_get."); + } else { + for (size_t i = 0; i < params.size(); ++i) { + std::string key = params.at(i); + keys_.emplace_back(is_key_hex_ ? HexToString(key) : key); + } + } +} + +void MultiGetCommand::Help(std::string& ret) { + ret.append(" "); + ret.append(MultiGetCommand::Name()); + ret.append(" ..."); + ret.append(" [--" + ARG_TTL + "]"); + ret.append("\n"); +} + +void MultiGetCommand::DoCommand() { + if (!db_) { + assert(GetExecuteState().IsFailed()); + return; + } + size_t num_keys = keys_.size(); + std::vector key_slices; + std::vector values(num_keys); + std::vector statuses(num_keys); + for (const std::string& key : keys_) { + key_slices.emplace_back(key); + } + db_->MultiGet(ReadOptions(), GetCfHandle(), num_keys, key_slices.data(), + values.data(), statuses.data()); + + bool failed = false; + for (size_t i = 0; i < num_keys; ++i) { + if (statuses[i].ok()) { + fprintf(stdout, is_value_hex_ ? "0x%s\n" : "%s\n", + values[i].ToString(is_value_hex_).c_str()); + } else { + fprintf(stderr, "Status for key %s: %s\n", + (is_key_hex_ ? StringToHex(keys_[i]) : keys_[i]).c_str(), + statuses[i].ToString().c_str()); + failed = false; + } + } + if (failed) { + exec_state_ = + LDBCommandExecuteResult::Failed("one or more keys had non-okay status"); + } +} + +// ---------------------------------------------------------------------------- + GetEntityCommand::GetEntityCommand( const std::vector& params, const std::map& options, diff --git a/tools/ldb_cmd_impl.h b/tools/ldb_cmd_impl.h index 2a396754dcb..30384eba7bf 100644 --- a/tools/ldb_cmd_impl.h +++ b/tools/ldb_cmd_impl.h @@ -403,6 +403,22 @@ class GetCommand : public LDBCommand { std::string key_; }; +class MultiGetCommand : public LDBCommand { + public: + static std::string Name() { return "multi_get"; } + + MultiGetCommand(const std::vector& params, + const std::map& options, + const std::vector& flags); + + void DoCommand() override; + + static void Help(std::string& ret); + + private: + std::vector keys_; +}; + class GetEntityCommand : public LDBCommand { public: static std::string Name() { return "get_entity"; }