Skip to content

Commit 11a61ca

Browse files
pdillingerarchang19
authored andcommitted
Support recompress-with-CompressionManager in sst_dump (facebook#13783)
Summary: So that we can use --command=recompress with a custom CompressionManager. (It's not required for reading files using a custom CompressionManager because those can already use ObjectLibrary for dependency injection.) Suggested follow-up: * These tests should not be using C arrays, snprintf, manual delete, etc. except for thin compatibility with argc/argv. Pull Request resolved: facebook#13783 Test Plan: unit test added, some manual testing Reviewed By: archang19 Differential Revision: D78574434 Pulled By: pdillinger fbshipit-source-id: 609e6c6439090e6b7e9b63fbd4c2d3f04b104fcf
1 parent 462388a commit 11a61ca

6 files changed

Lines changed: 126 additions & 34 deletions

File tree

.github/workflows/pr-jobs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ jobs:
182182
- uses: actions/checkout@v4.1.0
183183
- uses: "./.github/actions/pre-steps"
184184
- run: ENCRYPTED_ENV=1 ROCKSDB_DISABLE_SNAPPY=1 ROCKSDB_DISABLE_ZLIB=1 ROCKSDB_DISABLE_BZIP=1 ROCKSDB_DISABLE_LZ4=1 ROCKSDB_DISABLE_ZSTD=1 make V=1 J=32 -j32 check
185-
- run: "./sst_dump --help | grep -E -q 'Supported compression types: kNoCompression$' # Verify no compiled in compression\n"
185+
- run: "./sst_dump --help | grep -E -q 'Supported built-in compression types: kNoCompression$' # Verify no compiled in compression\n"
186186
- uses: "./.github/actions/post-steps"
187187
# ======================== Linux No Test Runs ======================= #
188188
build-linux-release:

options/options_helper.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ std::unique_ptr<Configurable> CFOptionsAsConfigurable(
7272
Status StringToMap(const std::string& opts_str,
7373
std::unordered_map<std::string, std::string>* opts_map);
7474

75+
Status GetStringFromCompressionType(std::string* compression_str,
76+
CompressionType compression_type);
77+
7578
struct OptionsHelper {
7679
static const std::string kCFOptionsName /*= "ColumnFamilyOptions"*/;
7780
static const std::string kDBOptionsName /*= "DBOptions" */;

table/sst_file_dumper.cc

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -260,16 +260,21 @@ Status SstFileDumper::CalculateCompressedTableSize(
260260
}
261261

262262
Status SstFileDumper::ShowAllCompressionSizes(
263-
size_t block_size,
264-
const std::vector<std::pair<CompressionType, const char*>>&
265-
compression_types,
263+
size_t block_size, const std::vector<CompressionType>& compression_types,
266264
int32_t compress_level_from, int32_t compress_level_to,
267265
uint32_t max_dict_bytes, uint32_t zstd_max_train_bytes,
268266
uint64_t max_dict_buffer_bytes, bool use_zstd_dict_trainer) {
269267
fprintf(stdout, "Block Size: %" ROCKSDB_PRIszt "\n", block_size);
270-
for (auto& i : compression_types) {
271-
if (CompressionTypeSupported(i.first)) {
272-
fprintf(stdout, "Compression: %-24s\n", i.second);
268+
for (CompressionType ctype : compression_types) {
269+
std::string cname;
270+
if (!GetStringFromCompressionType(&cname, ctype).ok()) {
271+
// Can produce names like "Reserved4F" for unrecognized values
272+
cname = CompressionTypeToString(ctype);
273+
}
274+
if (options_.compression_manager
275+
? options_.compression_manager->SupportsCompressionType(ctype)
276+
: CompressionTypeSupported(ctype)) {
277+
fprintf(stdout, "Compression: %-24s\n", cname.c_str());
273278
CompressionOptions compress_opt;
274279
compress_opt.max_dict_bytes = max_dict_bytes;
275280
compress_opt.zstd_max_train_bytes = zstd_max_train_bytes;
@@ -278,13 +283,13 @@ Status SstFileDumper::ShowAllCompressionSizes(
278283
for (int32_t j = compress_level_from; j <= compress_level_to; j++) {
279284
fprintf(stdout, "Compression level: %d", j);
280285
compress_opt.level = j;
281-
Status s = ShowCompressionSize(block_size, i.first, compress_opt);
286+
Status s = ShowCompressionSize(block_size, ctype, compress_opt);
282287
if (!s.ok()) {
283288
return s;
284289
}
285290
}
286291
} else {
287-
fprintf(stdout, "Unsupported compression type: %s.\n", i.second);
292+
fprintf(stdout, "Unsupported compression type: %s.\n", cname.c_str());
288293
}
289294
}
290295
return Status::OK();

table/sst_file_dumper.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,7 @@ class SstFileDumper {
4343
Status getStatus() { return init_result_; }
4444

4545
Status ShowAllCompressionSizes(
46-
size_t block_size,
47-
const std::vector<std::pair<CompressionType, const char*>>&
48-
compression_types,
46+
size_t block_size, const std::vector<CompressionType>& compression_types,
4947
int32_t compress_level_from, int32_t compress_level_to,
5048
uint32_t max_dict_bytes, uint32_t zstd_max_train_bytes,
5149
uint64_t max_dict_buffer_bytes, bool use_zstd_dict_trainer);

tools/sst_dump_test.cc

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "rocksdb/convenience.h"
1616
#include "rocksdb/filter_policy.h"
1717
#include "rocksdb/sst_dump_tool.h"
18+
#include "rocksdb/utilities/object_registry.h"
1819
#include "table/block_based/block_based_table_factory.h"
1920
#include "table/sst_file_dumper.h"
2021
#include "table/table_builder.h"
@@ -346,6 +347,76 @@ TEST_F(SSTDumpToolTest, CompressedSizes) {
346347
}
347348
}
348349

350+
namespace {
351+
using Compressor8A = test::CompressorCustomAlg<kCustomCompression8A>;
352+
class MyManager : public CompressionManager {
353+
public:
354+
static constexpr const char* kCompatibilityName = "SSTDumpToolTest:MyManager";
355+
const char* Name() const override { return kCompatibilityName; }
356+
const char* CompatibilityName() const override { return kCompatibilityName; }
357+
358+
bool SupportsCompressionType(CompressionType type) const override {
359+
return type == kCustomCompression8A;
360+
}
361+
362+
std::unique_ptr<Compressor> GetCompressor(const CompressionOptions& /*opts*/,
363+
CompressionType type) override {
364+
switch (static_cast<unsigned char>(type)) {
365+
case kCustomCompression8A:
366+
return std::make_unique<Compressor8A>();
367+
default:
368+
return nullptr;
369+
}
370+
}
371+
372+
std::shared_ptr<Decompressor> GetDecompressor() override {
373+
return std::make_shared<test::DecompressorCustomAlg>();
374+
}
375+
};
376+
} // namespace
377+
378+
TEST_F(SSTDumpToolTest, CompressionManager) {
379+
if (!Compressor8A::Supported()) {
380+
fprintf(stderr,
381+
"Prerequisite compression library not supported. Skipping\n");
382+
return;
383+
}
384+
385+
// Registery in ObjectLibrary to check that sst_dump can use named
386+
// CompressionManagers with dependency injection
387+
auto& library = *ObjectLibrary::Default();
388+
library.AddFactory<CompressionManager>(
389+
MyManager::kCompatibilityName,
390+
[](const std::string& /*uri*/, std::unique_ptr<CompressionManager>* guard,
391+
std::string* /*errmsg*/) {
392+
*guard = std::make_unique<MyManager>();
393+
return guard->get();
394+
});
395+
396+
Options opts;
397+
opts.env = env();
398+
BlockBasedTableOptions table_opts;
399+
table_opts.filter_policy.reset(
400+
ROCKSDB_NAMESPACE::NewBloomFilterPolicy(10, false));
401+
opts.table_factory.reset(new BlockBasedTableFactory(table_opts));
402+
std::string file_path = MakeFilePath("rocksdb_sst_test.sst");
403+
createSST(opts, file_path, 10);
404+
405+
char* usage[5];
406+
PopulateCommandArgs(file_path, "--command=recompress", usage);
407+
snprintf(usage[3], kOptLength, "--compression_manager=%s",
408+
MyManager::kCompatibilityName);
409+
snprintf(usage[4], kOptLength, "--compression_types=kCustomCompression8A");
410+
411+
ROCKSDB_NAMESPACE::SSTDumpTool tool;
412+
ASSERT_TRUE(!tool.Run(5, usage, opts));
413+
414+
cleanup(opts, file_path);
415+
for (int i = 0; i < 5; i++) {
416+
delete[] usage[i];
417+
}
418+
}
419+
349420
TEST_F(SSTDumpToolTest, MemEnv) {
350421
std::unique_ptr<Env> mem_env(NewMemEnv(env()));
351422
Options opts;

tools/sst_dump_tool.cc

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,6 @@
1717

1818
namespace ROCKSDB_NAMESPACE {
1919

20-
static const std::vector<std::pair<CompressionType, const char*>>
21-
kCompressions = {
22-
{CompressionType::kNoCompression, "kNoCompression"},
23-
{CompressionType::kSnappyCompression, "kSnappyCompression"},
24-
{CompressionType::kZlibCompression, "kZlibCompression"},
25-
{CompressionType::kBZip2Compression, "kBZip2Compression"},
26-
{CompressionType::kLZ4Compression, "kLZ4Compression"},
27-
{CompressionType::kLZ4HCCompression, "kLZ4HCCompression"},
28-
{CompressionType::kXpressCompression, "kXpressCompression"},
29-
{CompressionType::kZSTD, "kZSTD"}};
30-
3120
namespace {
3221

3322
void print_help(bool to_stderr) {
@@ -98,10 +87,15 @@ void print_help(bool to_stderr) {
9887
be used when trying different compression algorithms
9988
10089
--compression_types=<comma-separated list of CompressionType members, e.g.,
101-
kSnappyCompression>
90+
kSnappyCompression or kCustomCompressionC4>
10291
Can be combined with --command=recompress to run recompression for this
10392
list of compression types
104-
Supported compression types: %s
93+
Supported built-in compression types: %s
94+
95+
--compression_manager=<compression manager string>
96+
Used with --command=recompress to specify a compression manager to use
97+
instead of the built-in compression manager, which may support a
98+
different set of compression types.
10599
106100
--parse_internal_key=<0xKEY>
107101
Convenience option to parse an internal key on the command line. Dumps the
@@ -178,7 +172,8 @@ int SSTDumpTool::Run(int argc, char const* const* argv, Options options) {
178172
std::string compression_level_to_str;
179173
size_t block_size = 0;
180174
size_t readahead_size = 2 * 1024 * 1024;
181-
std::vector<std::pair<CompressionType, const char*>> compression_types;
175+
std::vector<CompressionType> compression_types;
176+
std::shared_ptr<CompressionManager> compression_manager;
182177
uint64_t total_num_files = 0;
183178
uint64_t total_num_data_blocks = 0;
184179
uint64_t total_data_block_size = 0;
@@ -244,19 +239,36 @@ int SSTDumpTool::Run(int argc, char const* const* argv, Options options) {
244239
std::istringstream iss(compression_types_csv);
245240
std::string compression_type;
246241
has_specified_compression_types = true;
242+
247243
while (std::getline(iss, compression_type, ',')) {
248-
auto iter = std::find_if(
249-
kCompressions.begin(), kCompressions.end(),
250-
[&compression_type](std::pair<CompressionType, const char*> curr) {
251-
return curr.second == compression_type;
252-
});
253-
if (iter == kCompressions.end()) {
244+
auto iter =
245+
OptionsHelper::compression_type_string_map.find(compression_type);
246+
if (iter == OptionsHelper::compression_type_string_map.end()) {
254247
fprintf(stderr, "%s is not a valid CompressionType\n",
255248
compression_type.c_str());
256249
exit(1);
257250
}
258-
compression_types.emplace_back(*iter);
251+
compression_types.emplace_back(iter->second);
252+
}
253+
} else if (strncmp(argv[i], "--compression_manager=", 22) == 0) {
254+
std::string compression_manager_str = argv[i] + 22;
255+
ConfigOptions config_options;
256+
config_options.ignore_unsupported_options = false;
257+
Status s = CompressionManager::CreateFromString(
258+
config_options, compression_manager_str, &compression_manager);
259+
if (!s.ok()) {
260+
fprintf(stderr, "Failed to create compression manager: %s\n",
261+
s.ToString().c_str());
262+
exit(1);
263+
}
264+
if (compression_manager == nullptr) {
265+
fprintf(stderr, "No compression manager created: %s\n",
266+
compression_manager_str.c_str());
267+
exit(1);
259268
}
269+
options.compression_manager = compression_manager;
270+
printf("Using compression manager: %s\n",
271+
compression_manager->GetId().c_str());
260272
} else if (strncmp(argv[i], "--parse_internal_key=", 21) == 0) {
261273
std::string in_key(argv[i] + 21);
262274
try {
@@ -450,9 +462,12 @@ int SSTDumpTool::Run(int argc, char const* const* argv, Options options) {
450462
}
451463

452464
if (command == "recompress") {
465+
// TODO: consider getting supported compressions from the compression
466+
// manager
453467
st = dumper.ShowAllCompressionSizes(
454468
set_block_size ? block_size : 16384,
455-
compression_types.empty() ? kCompressions : compression_types,
469+
compression_types.empty() ? GetSupportedCompressions()
470+
: compression_types,
456471
compress_level_from, compress_level_to, compression_max_dict_bytes,
457472
compression_zstd_max_train_bytes, compression_max_dict_buffer_bytes,
458473
!compression_use_zstd_finalize_dict);

0 commit comments

Comments
 (0)