提交 36a9f229 编写于 作者: Y Yi Wu 提交者: Facebook Github Bot

Blob DB: blob_dump to show uncompressed values

Summary:
Make blob_dump tool able to show uncompressed values if the blob file is compressed. Also show total compressed vs. raw size at the end if --show_summary is provided.
Closes https://github.com/facebook/rocksdb/pull/3633

Differential Revision: D7348926

Pulled By: yiwu-arbug

fbshipit-source-id: ca709cb4ed5cf6a550ff2987df8033df81516f8e
上级 c827b2dc
...@@ -27,9 +27,13 @@ int main(int argc, char** argv) { ...@@ -27,9 +27,13 @@ int main(int argc, char** argv) {
{"file", required_argument, nullptr, 'f'}, {"file", required_argument, nullptr, 'f'},
{"show_key", optional_argument, nullptr, 'k'}, {"show_key", optional_argument, nullptr, 'k'},
{"show_blob", optional_argument, nullptr, 'b'}, {"show_blob", optional_argument, nullptr, 'b'},
{"show_uncompressed_blob", optional_argument, nullptr, 'r'},
{"show_summary", optional_argument, nullptr, 's'},
}; };
DisplayType show_key = DisplayType::kRaw; DisplayType show_key = DisplayType::kRaw;
DisplayType show_blob = DisplayType::kNone; DisplayType show_blob = DisplayType::kNone;
DisplayType show_uncompressed_blob = DisplayType::kNone;
bool show_summary = false;
std::string file; std::string file;
while (true) { while (true) {
int c = getopt_long(argc, argv, "hk::b::f:", options, nullptr); int c = getopt_long(argc, argv, "hk::b::f:", options, nullptr);
...@@ -42,7 +46,9 @@ int main(int argc, char** argv) { ...@@ -42,7 +46,9 @@ int main(int argc, char** argv) {
fprintf(stdout, fprintf(stdout,
"Usage: blob_dump --file=filename " "Usage: blob_dump --file=filename "
"[--show_key[=none|raw|hex|detail]] " "[--show_key[=none|raw|hex|detail]] "
"[--show_blob[=none|raw|hex|detail]]\n"); "[--show_blob[=none|raw|hex|detail]] "
"[--show_uncompressed_blob[=none|raw|hex|detail]] "
"[--show_summary]\n");
return 0; return 0;
case 'f': case 'f':
file = optarg; file = optarg;
...@@ -64,16 +70,31 @@ int main(int argc, char** argv) { ...@@ -64,16 +70,31 @@ int main(int argc, char** argv) {
} }
show_blob = display_types.at(arg_str); show_blob = display_types.at(arg_str);
} else { } else {
show_blob = DisplayType::kDetail; show_blob = DisplayType::kHex;
} }
break; break;
case 'r':
if (optarg) {
if (display_types.count(arg_str) == 0) {
fprintf(stderr, "Unrecognized blob display type.\n");
return -1;
}
show_uncompressed_blob = display_types.at(arg_str);
} else {
show_uncompressed_blob = DisplayType::kHex;
}
break;
case 's':
show_summary = true;
break;
default: default:
fprintf(stderr, "Unrecognized option.\n"); fprintf(stderr, "Unrecognized option.\n");
return -1; return -1;
} }
} }
BlobDumpTool tool; BlobDumpTool tool;
Status s = tool.Run(file, show_key, show_blob); Status s =
tool.Run(file, show_key, show_blob, show_uncompressed_blob, show_summary);
if (!s.ok()) { if (!s.ok()) {
fprintf(stderr, "Failed: %s\n", s.ToString().c_str()); fprintf(stderr, "Failed: %s\n", s.ToString().c_str());
return -1; return -1;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "port/port.h" #include "port/port.h"
#include "rocksdb/convenience.h" #include "rocksdb/convenience.h"
#include "rocksdb/env.h" #include "rocksdb/env.h"
#include "table/format.h"
#include "util/coding.h" #include "util/coding.h"
#include "util/string_util.h" #include "util/string_util.h"
...@@ -27,7 +28,9 @@ BlobDumpTool::BlobDumpTool() ...@@ -27,7 +28,9 @@ BlobDumpTool::BlobDumpTool()
: reader_(nullptr), buffer_(nullptr), buffer_size_(0) {} : reader_(nullptr), buffer_(nullptr), buffer_size_(0) {}
Status BlobDumpTool::Run(const std::string& filename, DisplayType show_key, Status BlobDumpTool::Run(const std::string& filename, DisplayType show_key,
DisplayType show_blob) { DisplayType show_blob,
DisplayType show_uncompressed_blob,
bool show_summary) {
Status s; Status s;
Env* env = Env::Default(); Env* env = Env::Default();
s = env->FileExists(filename); s = env->FileExists(filename);
...@@ -50,7 +53,8 @@ Status BlobDumpTool::Run(const std::string& filename, DisplayType show_key, ...@@ -50,7 +53,8 @@ Status BlobDumpTool::Run(const std::string& filename, DisplayType show_key,
reader_.reset(new RandomAccessFileReader(std::move(file), filename)); reader_.reset(new RandomAccessFileReader(std::move(file), filename));
uint64_t offset = 0; uint64_t offset = 0;
uint64_t footer_offset = 0; uint64_t footer_offset = 0;
s = DumpBlobLogHeader(&offset); CompressionType compression = kNoCompression;
s = DumpBlobLogHeader(&offset, &compression);
if (!s.ok()) { if (!s.ok()) {
return s; return s;
} }
...@@ -58,14 +62,30 @@ Status BlobDumpTool::Run(const std::string& filename, DisplayType show_key, ...@@ -58,14 +62,30 @@ Status BlobDumpTool::Run(const std::string& filename, DisplayType show_key,
if (!s.ok()) { if (!s.ok()) {
return s; return s;
} }
if (show_key != DisplayType::kNone) { uint64_t total_records = 0;
uint64_t total_key_size = 0;
uint64_t total_blob_size = 0;
uint64_t total_uncompressed_blob_size = 0;
if (show_key != DisplayType::kNone || show_summary) {
while (offset < footer_offset) { while (offset < footer_offset) {
s = DumpRecord(show_key, show_blob, &offset); s = DumpRecord(show_key, show_blob, show_uncompressed_blob, show_summary,
compression, &offset, &total_records, &total_key_size,
&total_blob_size, &total_uncompressed_blob_size);
if (!s.ok()) { if (!s.ok()) {
return s; break;
} }
} }
} }
if (show_summary) {
fprintf(stdout, "Summary:\n");
fprintf(stdout, " total records: %" PRIu64 "\n", total_records);
fprintf(stdout, " total key size: %" PRIu64 "\n", total_key_size);
fprintf(stdout, " total blob size: %" PRIu64 "\n", total_blob_size);
if (compression != kNoCompression) {
fprintf(stdout, " total raw blob size: %" PRIu64 "\n",
total_uncompressed_blob_size);
}
}
return s; return s;
} }
...@@ -89,7 +109,8 @@ Status BlobDumpTool::Read(uint64_t offset, size_t size, Slice* result) { ...@@ -89,7 +109,8 @@ Status BlobDumpTool::Read(uint64_t offset, size_t size, Slice* result) {
return s; return s;
} }
Status BlobDumpTool::DumpBlobLogHeader(uint64_t* offset) { Status BlobDumpTool::DumpBlobLogHeader(uint64_t* offset,
CompressionType* compression) {
Slice slice; Slice slice;
Status s = Read(0, BlobLogHeader::kSize, &slice); Status s = Read(0, BlobLogHeader::kSize, &slice);
if (!s.ok()) { if (!s.ok()) {
...@@ -114,6 +135,7 @@ Status BlobDumpTool::DumpBlobLogHeader(uint64_t* offset) { ...@@ -114,6 +135,7 @@ Status BlobDumpTool::DumpBlobLogHeader(uint64_t* offset) {
fprintf(stdout, " Expiration range : %s\n", fprintf(stdout, " Expiration range : %s\n",
GetString(header.expiration_range).c_str()); GetString(header.expiration_range).c_str());
*offset = BlobLogHeader::kSize; *offset = BlobLogHeader::kSize;
*compression = header.compression;
return s; return s;
} }
...@@ -136,7 +158,7 @@ Status BlobDumpTool::DumpBlobLogFooter(uint64_t file_size, ...@@ -136,7 +158,7 @@ Status BlobDumpTool::DumpBlobLogFooter(uint64_t file_size,
BlobLogFooter footer; BlobLogFooter footer;
s = footer.DecodeFrom(slice); s = footer.DecodeFrom(slice);
if (!s.ok()) { if (!s.ok()) {
return s; return no_footer();
} }
fprintf(stdout, "Blob log footer:\n"); fprintf(stdout, "Blob log footer:\n");
fprintf(stdout, " Blob count : %" PRIu64 "\n", footer.blob_count); fprintf(stdout, " Blob count : %" PRIu64 "\n", footer.blob_count);
...@@ -146,9 +168,16 @@ Status BlobDumpTool::DumpBlobLogFooter(uint64_t file_size, ...@@ -146,9 +168,16 @@ Status BlobDumpTool::DumpBlobLogFooter(uint64_t file_size,
} }
Status BlobDumpTool::DumpRecord(DisplayType show_key, DisplayType show_blob, Status BlobDumpTool::DumpRecord(DisplayType show_key, DisplayType show_blob,
uint64_t* offset) { DisplayType show_uncompressed_blob,
fprintf(stdout, "Read record with offset 0x%" PRIx64 " (%" PRIu64 "):\n", bool show_summary, CompressionType compression,
*offset, *offset); uint64_t* offset, uint64_t* total_records,
uint64_t* total_key_size,
uint64_t* total_blob_size,
uint64_t* total_uncompressed_blob_size) {
if (show_key != DisplayType::kNone) {
fprintf(stdout, "Read record with offset 0x%" PRIx64 " (%" PRIu64 "):\n",
*offset, *offset);
}
Slice slice; Slice slice;
Status s = Read(*offset, BlobLogRecord::kHeaderSize, &slice); Status s = Read(*offset, BlobLogRecord::kHeaderSize, &slice);
if (!s.ok()) { if (!s.ok()) {
...@@ -161,14 +190,30 @@ Status BlobDumpTool::DumpRecord(DisplayType show_key, DisplayType show_blob, ...@@ -161,14 +190,30 @@ Status BlobDumpTool::DumpRecord(DisplayType show_key, DisplayType show_blob,
} }
uint64_t key_size = record.key_size; uint64_t key_size = record.key_size;
uint64_t value_size = record.value_size; uint64_t value_size = record.value_size;
fprintf(stdout, " key size : %" PRIu64 "\n", key_size); if (show_key != DisplayType::kNone) {
fprintf(stdout, " value size : %" PRIu64 "\n", value_size); fprintf(stdout, " key size : %" PRIu64 "\n", key_size);
fprintf(stdout, " expiration : %" PRIu64 "\n", record.expiration); fprintf(stdout, " value size : %" PRIu64 "\n", value_size);
fprintf(stdout, " expiration : %" PRIu64 "\n", record.expiration);
}
*offset += BlobLogRecord::kHeaderSize; *offset += BlobLogRecord::kHeaderSize;
s = Read(*offset, key_size + value_size, &slice); s = Read(*offset, key_size + value_size, &slice);
if (!s.ok()) { if (!s.ok()) {
return s; return s;
} }
// Decompress value
std::string uncompressed_value;
if (compression != kNoCompression &&
(show_uncompressed_blob != DisplayType::kNone || show_summary)) {
BlockContents contents;
s = UncompressBlockContentsForCompressionType(
slice.data() + key_size, value_size, &contents,
2 /*compress_format_version*/, Slice(), compression,
ImmutableCFOptions(Options()));
if (!s.ok()) {
return s;
}
uncompressed_value = contents.data.ToString();
}
if (show_key != DisplayType::kNone) { if (show_key != DisplayType::kNone) {
fprintf(stdout, " key : "); fprintf(stdout, " key : ");
DumpSlice(Slice(slice.data(), key_size), show_key); DumpSlice(Slice(slice.data(), key_size), show_key);
...@@ -176,8 +221,16 @@ Status BlobDumpTool::DumpRecord(DisplayType show_key, DisplayType show_blob, ...@@ -176,8 +221,16 @@ Status BlobDumpTool::DumpRecord(DisplayType show_key, DisplayType show_blob,
fprintf(stdout, " blob : "); fprintf(stdout, " blob : ");
DumpSlice(Slice(slice.data() + key_size, value_size), show_blob); DumpSlice(Slice(slice.data() + key_size, value_size), show_blob);
} }
if (show_uncompressed_blob != DisplayType::kNone) {
fprintf(stdout, " raw blob : ");
DumpSlice(Slice(uncompressed_value), show_uncompressed_blob);
}
} }
*offset += key_size + value_size; *offset += key_size + value_size;
*total_records += 1;
*total_key_size += key_size;
*total_blob_size += value_size;
*total_uncompressed_blob_size += uncompressed_value.size();
return s; return s;
} }
......
...@@ -27,8 +27,9 @@ class BlobDumpTool { ...@@ -27,8 +27,9 @@ class BlobDumpTool {
BlobDumpTool(); BlobDumpTool();
Status Run(const std::string& filename, DisplayType key_type, Status Run(const std::string& filename, DisplayType show_key,
DisplayType blob_type); DisplayType show_blob, DisplayType show_uncompressed_blob,
bool show_summary);
private: private:
std::unique_ptr<RandomAccessFileReader> reader_; std::unique_ptr<RandomAccessFileReader> reader_;
...@@ -36,10 +37,14 @@ class BlobDumpTool { ...@@ -36,10 +37,14 @@ class BlobDumpTool {
size_t buffer_size_; size_t buffer_size_;
Status Read(uint64_t offset, size_t size, Slice* result); Status Read(uint64_t offset, size_t size, Slice* result);
Status DumpBlobLogHeader(uint64_t* offset); Status DumpBlobLogHeader(uint64_t* offset, CompressionType* compression);
Status DumpBlobLogFooter(uint64_t file_size, uint64_t* footer_offset); Status DumpBlobLogFooter(uint64_t file_size, uint64_t* footer_offset);
Status DumpRecord(DisplayType show_key, DisplayType show_blob, Status DumpRecord(DisplayType show_key, DisplayType show_blob,
uint64_t* offset); DisplayType show_uncompressed_blob, bool show_summary,
CompressionType compression, uint64_t* offset,
uint64_t* total_records, uint64_t* total_key_size,
uint64_t* total_blob_size,
uint64_t* total_uncompressed_blob_size);
void DumpSlice(const Slice s, DisplayType type); void DumpSlice(const Slice s, DisplayType type);
template <class T> template <class T>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册