rocksdb/tools/ldb_cmd_impl.h
Jay Huh 59f4cbef8c 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
2024-01-24 11:35:12 -08:00

797 lines
21 KiB
C++

// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
#pragma once
#include <map>
#include <string>
#include <utility>
#include <vector>
#include "rocksdb/utilities/ldb_cmd.h"
namespace ROCKSDB_NAMESPACE {
class CompactorCommand : public LDBCommand {
public:
static std::string Name() { return "compact"; }
CompactorCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
static void Help(std::string& ret);
void DoCommand() override;
private:
bool null_from_;
std::string from_;
bool null_to_;
std::string to_;
};
class DBFileDumperCommand : public LDBCommand {
public:
static std::string Name() { return "dump_live_files"; }
DBFileDumperCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
static void Help(std::string& ret);
void DoCommand() override;
private:
bool decode_blob_index_;
bool dump_uncompressed_blobs_;
};
class DBLiveFilesMetadataDumperCommand : public LDBCommand {
public:
static std::string Name() { return "list_live_files_metadata"; }
DBLiveFilesMetadataDumperCommand(
const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
static void Help(std::string& ret);
void DoCommand() override;
private:
bool sort_by_filename_;
static const std::string ARG_SORT_BY_FILENAME;
};
class DBDumperCommand : public LDBCommand {
public:
static std::string Name() { return "dump"; }
DBDumperCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
static void Help(std::string& ret);
void DoCommand() override;
private:
/**
* Extract file name from the full path. We handle both the forward slash (/)
* and backslash (\) to make sure that different OS-s are supported.
*/
static std::string GetFileNameFromPath(const std::string& s) {
std::size_t n = s.find_last_of("/\\");
if (std::string::npos == n) {
return s;
} else {
return s.substr(n + 1);
}
}
void DoDumpCommand();
bool null_from_;
std::string from_;
bool null_to_;
std::string to_;
int max_keys_;
std::string delim_;
bool count_only_;
bool count_delim_;
bool print_stats_;
std::string path_;
bool decode_blob_index_;
bool dump_uncompressed_blobs_;
static const std::string ARG_COUNT_ONLY;
static const std::string ARG_COUNT_DELIM;
static const std::string ARG_STATS;
static const std::string ARG_TTL_BUCKET;
};
class InternalDumpCommand : public LDBCommand {
public:
static std::string Name() { return "idump"; }
InternalDumpCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
static void Help(std::string& ret);
void DoCommand() override;
private:
bool has_from_;
std::string from_;
bool has_to_;
std::string to_;
int max_keys_;
std::string delim_;
bool count_only_;
bool count_delim_;
bool print_stats_;
bool is_input_key_hex_;
bool decode_blob_index_;
static const std::string ARG_DELIM;
static const std::string ARG_COUNT_ONLY;
static const std::string ARG_COUNT_DELIM;
static const std::string ARG_STATS;
static const std::string ARG_INPUT_KEY_HEX;
};
class DBLoaderCommand : public LDBCommand {
public:
static std::string Name() { return "load"; }
DBLoaderCommand(std::string& db_name, std::vector<std::string>& args);
DBLoaderCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
static void Help(std::string& ret);
void DoCommand() override;
void OverrideBaseOptions() override;
private:
bool disable_wal_;
bool bulk_load_;
bool compact_;
static const std::string ARG_DISABLE_WAL;
static const std::string ARG_BULK_LOAD;
static const std::string ARG_COMPACT;
};
class ManifestDumpCommand : public LDBCommand {
public:
static std::string Name() { return "manifest_dump"; }
ManifestDumpCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
static void Help(std::string& ret);
void DoCommand() override;
bool NoDBOpen() override { return true; }
private:
bool verbose_;
bool json_;
std::string path_;
static const std::string ARG_VERBOSE;
static const std::string ARG_JSON;
static const std::string ARG_PATH;
};
class UpdateManifestCommand : public LDBCommand {
public:
static std::string Name() { return "update_manifest"; }
UpdateManifestCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
static void Help(std::string& ret);
virtual void DoCommand() override;
virtual bool NoDBOpen() override { return true; }
private:
bool verbose_;
bool update_temperatures_;
// TODO future: checksum_func for populating checksums
static const std::string ARG_VERBOSE;
static const std::string ARG_UPDATE_TEMPERATURES;
};
class FileChecksumDumpCommand : public LDBCommand {
public:
static std::string Name() { return "file_checksum_dump"; }
FileChecksumDumpCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
static void Help(std::string& ret);
void DoCommand() override;
bool NoDBOpen() override { return true; }
private:
std::string path_;
bool is_checksum_hex_;
static const std::string ARG_PATH;
};
class GetPropertyCommand : public LDBCommand {
public:
static std::string Name() { return "get_property"; }
GetPropertyCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
static void Help(std::string& ret);
void DoCommand() override;
private:
std::string property_;
};
class ListColumnFamiliesCommand : public LDBCommand {
public:
static std::string Name() { return "list_column_families"; }
ListColumnFamiliesCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
static void Help(std::string& ret);
void DoCommand() override;
bool NoDBOpen() override { return true; }
};
class CreateColumnFamilyCommand : public LDBCommand {
public:
static std::string Name() { return "create_column_family"; }
CreateColumnFamilyCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
static void Help(std::string& ret);
void DoCommand() override;
bool NoDBOpen() override { return false; }
private:
std::string new_cf_name_;
};
class DropColumnFamilyCommand : public LDBCommand {
public:
static std::string Name() { return "drop_column_family"; }
DropColumnFamilyCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
static void Help(std::string& ret);
void DoCommand() override;
bool NoDBOpen() override { return false; }
private:
std::string cf_name_to_drop_;
};
class ReduceDBLevelsCommand : public LDBCommand {
public:
static std::string Name() { return "reduce_levels"; }
ReduceDBLevelsCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
void OverrideBaseCFOptions(ColumnFamilyOptions* cf_opts) override;
void DoCommand() override;
bool NoDBOpen() override { return true; }
static void Help(std::string& msg);
static std::vector<std::string> PrepareArgs(const std::string& db_path,
int new_levels,
bool print_old_level = false);
private:
int old_levels_;
int new_levels_;
bool print_old_levels_;
static const std::string ARG_NEW_LEVELS;
static const std::string ARG_PRINT_OLD_LEVELS;
Status GetOldNumOfLevels(Options& opt, int* levels);
};
class ChangeCompactionStyleCommand : public LDBCommand {
public:
static std::string Name() { return "change_compaction_style"; }
ChangeCompactionStyleCommand(
const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
void OverrideBaseCFOptions(ColumnFamilyOptions* cf_opts) override;
void DoCommand() override;
static void Help(std::string& msg);
private:
int old_compaction_style_;
int new_compaction_style_;
static const std::string ARG_OLD_COMPACTION_STYLE;
static const std::string ARG_NEW_COMPACTION_STYLE;
};
class WALDumperCommand : public LDBCommand {
public:
static std::string Name() { return "dump_wal"; }
WALDumperCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
bool NoDBOpen() override { return true; }
static void Help(std::string& ret);
void DoCommand() override;
private:
bool print_header_;
std::string wal_file_;
bool print_values_;
bool is_write_committed_; // default will be set to true
static const std::string ARG_WAL_FILE;
static const std::string ARG_WRITE_COMMITTED;
static const std::string ARG_PRINT_HEADER;
static const std::string ARG_PRINT_VALUE;
};
class GetCommand : public LDBCommand {
public:
static std::string Name() { return "get"; }
GetCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
void DoCommand() override;
static void Help(std::string& ret);
private:
std::string key_;
};
class MultiGetCommand : public LDBCommand {
public:
static std::string Name() { return "multi_get"; }
MultiGetCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
void DoCommand() override;
static void Help(std::string& ret);
private:
std::vector<std::string> keys_;
};
class GetEntityCommand : public LDBCommand {
public:
static std::string Name() { return "get_entity"; }
GetEntityCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
void DoCommand() override;
static void Help(std::string& ret);
private:
std::string key_;
};
class ApproxSizeCommand : public LDBCommand {
public:
static std::string Name() { return "approxsize"; }
ApproxSizeCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
void DoCommand() override;
static void Help(std::string& ret);
private:
std::string start_key_;
std::string end_key_;
};
class BatchPutCommand : public LDBCommand {
public:
static std::string Name() { return "batchput"; }
BatchPutCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
void DoCommand() override;
static void Help(std::string& ret);
void OverrideBaseOptions() override;
private:
/**
* The key-values to be inserted.
*/
std::vector<std::pair<std::string, std::string>> key_values_;
};
class ScanCommand : public LDBCommand {
public:
static std::string Name() { return "scan"; }
ScanCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
void DoCommand() override;
static void Help(std::string& ret);
private:
std::string start_key_;
std::string end_key_;
bool start_key_specified_;
bool end_key_specified_;
int max_keys_scanned_;
bool no_value_;
};
class DeleteCommand : public LDBCommand {
public:
static std::string Name() { return "delete"; }
DeleteCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
void DoCommand() override;
static void Help(std::string& ret);
private:
std::string key_;
};
class SingleDeleteCommand : public LDBCommand {
public:
static std::string Name() { return "singledelete"; }
SingleDeleteCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
void DoCommand() override;
static void Help(std::string& ret);
private:
std::string key_;
};
class DeleteRangeCommand : public LDBCommand {
public:
static std::string Name() { return "deleterange"; }
DeleteRangeCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
void DoCommand() override;
static void Help(std::string& ret);
private:
std::string begin_key_;
std::string end_key_;
};
class PutCommand : public LDBCommand {
public:
static std::string Name() { return "put"; }
PutCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
void DoCommand() override;
static void Help(std::string& ret);
void OverrideBaseOptions() override;
private:
std::string key_;
std::string value_;
};
class PutEntityCommand : public LDBCommand {
public:
static std::string Name() { return "put_entity"; }
PutEntityCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
void DoCommand() override;
static void Help(std::string& ret);
void OverrideBaseOptions() override;
private:
std::string key_;
std::vector<std::string> column_names_;
std::vector<std::string> column_values_;
};
/**
* Command that starts up a REPL shell that allows
* get/put/delete.
*/
class DBQuerierCommand : public LDBCommand {
public:
static std::string Name() { return "query"; }
DBQuerierCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
static void Help(std::string& ret);
void DoCommand() override;
private:
static const char* HELP_CMD;
static const char* GET_CMD;
static const char* PUT_CMD;
static const char* DELETE_CMD;
};
class CheckConsistencyCommand : public LDBCommand {
public:
static std::string Name() { return "checkconsistency"; }
CheckConsistencyCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
void DoCommand() override;
bool NoDBOpen() override { return true; }
static void Help(std::string& ret);
};
class CheckPointCommand : public LDBCommand {
public:
static std::string Name() { return "checkpoint"; }
CheckPointCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
void DoCommand() override;
static void Help(std::string& ret);
std::string checkpoint_dir_;
private:
static const std::string ARG_CHECKPOINT_DIR;
};
class RepairCommand : public LDBCommand {
public:
static std::string Name() { return "repair"; }
RepairCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
void DoCommand() override;
bool NoDBOpen() override { return true; }
void OverrideBaseOptions() override;
static void Help(std::string& ret);
protected:
bool verbose_;
private:
static const std::string ARG_VERBOSE;
};
class BackupEngineCommand : public LDBCommand {
public:
BackupEngineCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
protected:
static void Help(const std::string& name, std::string& ret);
std::string backup_env_uri_;
std::string backup_fs_uri_;
std::string backup_dir_;
int num_threads_;
std::unique_ptr<Logger> logger_;
std::shared_ptr<Env> backup_env_guard_;
private:
static const std::string ARG_BACKUP_DIR;
static const std::string ARG_BACKUP_ENV_URI;
static const std::string ARG_BACKUP_FS_URI;
static const std::string ARG_NUM_THREADS;
static const std::string ARG_STDERR_LOG_LEVEL;
};
class BackupCommand : public BackupEngineCommand {
public:
static std::string Name() { return "backup"; }
BackupCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
void DoCommand() override;
static void Help(std::string& ret);
};
class RestoreCommand : public BackupEngineCommand {
public:
static std::string Name() { return "restore"; }
RestoreCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
void DoCommand() override;
bool NoDBOpen() override { return true; }
static void Help(std::string& ret);
};
class WriteExternalSstFilesCommand : public LDBCommand {
public:
static std::string Name() { return "write_extern_sst"; }
WriteExternalSstFilesCommand(
const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
void DoCommand() override;
bool NoDBOpen() override { return false; }
void OverrideBaseOptions() override;
static void Help(std::string& ret);
private:
std::string output_sst_path_;
};
class IngestExternalSstFilesCommand : public LDBCommand {
public:
static std::string Name() { return "ingest_extern_sst"; }
IngestExternalSstFilesCommand(
const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
void DoCommand() override;
bool NoDBOpen() override { return false; }
void OverrideBaseOptions() override;
static void Help(std::string& ret);
private:
std::string input_sst_path_;
bool move_files_;
bool snapshot_consistency_;
bool allow_global_seqno_;
bool allow_blocking_flush_;
bool ingest_behind_;
bool write_global_seqno_;
static const std::string ARG_MOVE_FILES;
static const std::string ARG_SNAPSHOT_CONSISTENCY;
static const std::string ARG_ALLOW_GLOBAL_SEQNO;
static const std::string ARG_ALLOW_BLOCKING_FLUSH;
static const std::string ARG_INGEST_BEHIND;
static const std::string ARG_WRITE_GLOBAL_SEQNO;
};
// Command that prints out range delete tombstones in SST files.
class ListFileRangeDeletesCommand : public LDBCommand {
public:
static std::string Name() { return "list_file_range_deletes"; }
ListFileRangeDeletesCommand(const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
void DoCommand() override;
static void Help(std::string& ret);
private:
int max_keys_ = 1000;
};
// Command that removes the SST file forcibly from the manifest.
class UnsafeRemoveSstFileCommand : public LDBCommand {
public:
static std::string Name() { return "unsafe_remove_sst_file"; }
UnsafeRemoveSstFileCommand(const std::vector<std::string>& params,
const std::map<std::string, std::string>& options,
const std::vector<std::string>& flags);
static void Help(std::string& ret);
void DoCommand() override;
bool NoDBOpen() override { return true; }
private:
uint64_t sst_file_number_;
};
} // namespace ROCKSDB_NAMESPACE