mirror of
https://github.com/facebook/rocksdb.git
synced 2026-11-06 11:02:36 -05:00
Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
33ce358130 | ||
|
|
351d212777 | ||
|
|
668067e0bf | ||
|
|
463f9fd9f2 | ||
|
|
ca5d60fd69 | ||
|
|
c50a2b68bb | ||
|
|
fe68fbcd7f | ||
|
|
57ff2b2492 | ||
|
|
551ba21e9b |
No files matched your search
@@ -182,7 +182,7 @@ jobs:
|
||||
- uses: actions/checkout@v4.1.0
|
||||
- uses: "./.github/actions/pre-steps"
|
||||
- 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
|
||||
- run: "./sst_dump --help | grep -E -q 'Supported compression types: kNoCompression$' # Verify no compiled in compression\n"
|
||||
- run: "./sst_dump --help | grep -E -q 'Supported built-in compression types: kNoCompression$' # Verify no compiled in compression\n"
|
||||
- uses: "./.github/actions/post-steps"
|
||||
# ======================== Linux No Test Runs ======================= #
|
||||
build-linux-release:
|
||||
|
||||
+16
@@ -1,6 +1,22 @@
|
||||
# Rocksdb Change Log
|
||||
> NOTE: Entries for next release do not go here. Follow instructions in `unreleased_history/README.txt`
|
||||
|
||||
## 10.5.0 (07/18/2025)
|
||||
### Public API Changes
|
||||
* DB option skip_checking_sst_file_sizes_on_db_open is deprecated, in favor of validating file size in parallel in a thread pool, when db is opened. When DB is opened, with paranoid check enabled, a file with the wrong size would fail the DB open. With paranoid check disabled, the DB open would succeed, the column family with the corrupted file would not be read or write, while the other healthy column families could be read and write normally. When max_open_files option is not set to -1, only a subset of the files will be opened and checked. The rest of the files will be opened and checked when they are accessed.
|
||||
|
||||
### Behavior Changes
|
||||
* PessimisticTransaction::GetWaitingTxns now returns waiting transaction information even if the current transaction has timed out. This allows the information to be surfaced to users for debugging purposes once it is known that the timeout has occured.
|
||||
* A new API GetFileSize is added to FSRandomAccessFile interface class. It uses fstat vs stat on the posix implementation which is more efficient. Caller could use it to get file size faster. This function might be required in the future for FileSystem implementation outside of the RocksDB code base.
|
||||
* RocksDB now triggers eligible compactions every 12 hours when periodic compaction is configured. This solves a limitation of the compaction trigger mechanism, which would only trigger compaction after specific events like flush, compaction, or SetOptions.
|
||||
|
||||
### Bug Fixes
|
||||
* Fix a bug in BackupEngine that can crash backup due to a null FSWritableFile passed to WritableFileWriter.
|
||||
* Fix DB::NewMultiScan iterator to respect the scan upper bound specified in ScanOptions
|
||||
|
||||
### Performance Improvements
|
||||
* Optimized MultiScan using BlockBasedTable to coalesce I/Os and prefetch all data blocks.
|
||||
|
||||
## 10.4.0 (06/20/2025)
|
||||
### New Features
|
||||
* Add a new CF option `memtable_avg_op_scan_flush_trigger` that supports triggering memtable flush when an iterator scans through an expensive range of keys, with the average number of skipped keys from the active memtable exceeding the threshold.
|
||||
|
||||
@@ -2492,7 +2492,7 @@ checkout_folly:
|
||||
fi
|
||||
@# Pin to a particular version for public CI, so that PR authors don't
|
||||
@# need to worry about folly breaking our integration. Update periodically
|
||||
cd third-party/folly && git reset --hard 5c626dd6a028a02e461edb5396694d48305e9284
|
||||
cd third-party/folly && git reset --hard e95383b7c8b5b1e46cf47acf2f317d54f93c8268
|
||||
@# Apparently missing include
|
||||
perl -pi -e 's/(#include <atomic>)/$$1\n#include <cstring>/' third-party/folly/folly/lang/Exception.h
|
||||
@# Warning-as-error on memcpy
|
||||
|
||||
@@ -2400,7 +2400,6 @@ class DataVisibilityTest : public DBBasicTestWithTimestampBase {
|
||||
}
|
||||
}
|
||||
};
|
||||
constexpr int DataVisibilityTest::kTestDataSize;
|
||||
|
||||
// Application specifies timestamp but not snapshot.
|
||||
// reader writer
|
||||
|
||||
@@ -156,10 +156,6 @@ Status ExternalSstFileIngestionJob::Prepare(
|
||||
// It is unsafe to assume application had sync the file and file
|
||||
// directory before ingest the file. For integrity of RocksDB we need
|
||||
// to sync the file.
|
||||
// Use FSRandomRWFile instead of FSWritableFile, as in encrypted file
|
||||
// system the FSWritableFile will append a new prefix to the end of the
|
||||
// file when the file exists, which causes file corruption. On the
|
||||
// contrary, FSRandomRWFile handles an existing file correctly.
|
||||
|
||||
// TODO(xingbo), We should in general be moving away from production
|
||||
// uses of ReuseWritableFile (except explicitly for WAL recycling),
|
||||
@@ -168,9 +164,9 @@ Status ExternalSstFileIngestionJob::Prepare(
|
||||
// re-open+sync+close combo but can (a) be reused easily, and (b) be
|
||||
// overridden to do that more cleanly, e.g. in EncryptedEnv.
|
||||
// https://github.com/facebook/rocksdb/issues/13741
|
||||
std::unique_ptr<FSRandomRWFile> file_to_sync;
|
||||
Status s = fs_->NewRandomRWFile(path_inside_db, env_options_,
|
||||
&file_to_sync, nullptr);
|
||||
std::unique_ptr<FSWritableFile> file_to_sync;
|
||||
Status s = fs_->ReopenWritableFile(path_inside_db, env_options_,
|
||||
&file_to_sync, nullptr);
|
||||
TEST_SYNC_POINT_CALLBACK("ExternalSstFileIngestionJob::Prepare:Reopen",
|
||||
&s);
|
||||
// Some file systems (especially remote/distributed) don't support
|
||||
|
||||
+66
-6
@@ -95,6 +95,8 @@ namespace ROCKSDB_NAMESPACE {
|
||||
|
||||
namespace {
|
||||
|
||||
using ScanOptionsMap = std::unordered_map<size_t, std::vector<ScanOptions>>;
|
||||
|
||||
// Find File in LevelFilesBrief data structure
|
||||
// Within an index range defined by left and right
|
||||
int FindFileInRange(const InternalKeyComparator& icmp,
|
||||
@@ -1100,9 +1102,47 @@ class LevelIterator final : public InternalIterator {
|
||||
}
|
||||
|
||||
void Prepare(const std::vector<ScanOptions>* scan_opts) override {
|
||||
// We assume here that scan_opts is sorted such that
|
||||
// scan_opts[0].range.start < scan_opts[1].range.start, and non overlapping
|
||||
scan_opts_ = scan_opts;
|
||||
if (file_iter_.iter()) {
|
||||
file_iter_.Prepare(scan_opts_);
|
||||
if (scan_opts_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
file_to_scan_opts_ = std::make_unique<ScanOptionsMap>();
|
||||
for (size_t k = 0; k < scan_opts_->size(); k++) {
|
||||
const ScanOptions& opt = scan_opts_->at(k);
|
||||
auto start = opt.range.start;
|
||||
auto end = opt.range.limit;
|
||||
|
||||
if (!start.has_value()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// We can capture this case in the future, but for now lets skip this.
|
||||
if (!end.has_value()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
InternalKey istart(start.value(), kMaxSequenceNumber, kValueTypeForSeek);
|
||||
InternalKey iend(end.value(), 0, kValueTypeForSeekForPrev);
|
||||
|
||||
// TODO: This needs to be optimized, right now we iterate twice, which
|
||||
// we dont need to. We can do this in N rather than 2N.
|
||||
size_t fstart = FindFile(icomparator_, *flevel_, istart.Encode());
|
||||
size_t fend = FindFile(icomparator_, *flevel_, iend.Encode());
|
||||
|
||||
// We need to check the relevant cases
|
||||
// Cases:
|
||||
// 1. [ S E ]
|
||||
// 2. [ S ] [ E ]
|
||||
// 3. [ S ] ...... [ E ]
|
||||
for (auto i = fstart; i <= fend; i++) {
|
||||
if (i < flevel_->num_files) {
|
||||
(*file_to_scan_opts_)[i].emplace_back(start.value(), end.value());
|
||||
(*file_to_scan_opts_)[i].back().property_bag = opt.property_bag;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1233,6 +1273,9 @@ class LevelIterator final : public InternalIterator {
|
||||
bool to_return_sentinel_ = false;
|
||||
const std::vector<ScanOptions>* scan_opts_;
|
||||
|
||||
// Our stored scan_opts for each prefix
|
||||
std::unique_ptr<ScanOptionsMap> file_to_scan_opts_ = nullptr;
|
||||
|
||||
// Sets flags for if we should return the sentinel key next.
|
||||
// The condition for returning sentinel is reaching the end of current
|
||||
// file_iter_: !Valid() && status.().ok().
|
||||
@@ -1494,7 +1537,18 @@ bool LevelIterator::SkipEmptyFileForward() {
|
||||
// LevelIterator::Seek*, it should also call Seek* into the corresponding
|
||||
// range tombstone iterator.
|
||||
if (file_iter_.iter() != nullptr) {
|
||||
file_iter_.SeekToFirst();
|
||||
// If we are doing prepared scan opts then we should seek to the values
|
||||
// specified by the scan opts
|
||||
if (scan_opts_ && (*file_to_scan_opts_)[file_index_].size()) {
|
||||
const ScanOptions& opts = file_to_scan_opts_->at(file_index_).front();
|
||||
if (opts.range.start.has_value()) {
|
||||
InternalKey target(*opts.range.start.AsPtr(), kMaxSequenceNumber,
|
||||
kValueTypeForSeek);
|
||||
file_iter_.Seek(target.Encode());
|
||||
}
|
||||
} else {
|
||||
file_iter_.SeekToFirst();
|
||||
}
|
||||
if (range_tombstone_iter_) {
|
||||
if (*range_tombstone_iter_) {
|
||||
(*range_tombstone_iter_)->SeekToFirst();
|
||||
@@ -1542,10 +1596,15 @@ void LevelIterator::SetFileIterator(InternalIterator* iter) {
|
||||
}
|
||||
|
||||
InternalIterator* old_iter = file_iter_.Set(iter);
|
||||
// Since this is a new table iterator, no need to call Prepare() if
|
||||
// scan_opts_ is null
|
||||
if (iter && scan_opts_) {
|
||||
file_iter_.Prepare(scan_opts_);
|
||||
if (file_to_scan_opts_.get() &&
|
||||
file_to_scan_opts_->find(file_index_) != file_to_scan_opts_->end()) {
|
||||
const std::vector<ScanOptions>& opts =
|
||||
file_to_scan_opts_->at(file_index_);
|
||||
file_iter_.Prepare(&opts);
|
||||
} else {
|
||||
file_iter_.Prepare(scan_opts_);
|
||||
}
|
||||
}
|
||||
|
||||
// Update the read pattern for PrefetchBuffer.
|
||||
@@ -1582,6 +1641,7 @@ void LevelIterator::InitFileIterator(size_t new_file_index) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
Status Version::GetTableProperties(const ReadOptions& read_options,
|
||||
|
||||
Vendored
+38
-3
@@ -665,17 +665,52 @@ class EncryptedFileSystemImpl : public EncryptedFileSystem {
|
||||
std::unique_ptr<FSWritableFile>* result,
|
||||
IODebugContext* dbg) override {
|
||||
result->reset();
|
||||
if (options.use_mmap_writes) {
|
||||
if (options.use_mmap_reads || options.use_mmap_writes) {
|
||||
return IOStatus::InvalidArgument();
|
||||
}
|
||||
|
||||
size_t prefix_length = 0;
|
||||
std::unique_ptr<BlockAccessCipherStream> stream;
|
||||
|
||||
// Open file using underlying Env implementation
|
||||
std::unique_ptr<FSWritableFile> underlying;
|
||||
IOStatus status =
|
||||
auto status =
|
||||
FileSystemWrapper::ReopenWritableFile(fname, options, &underlying, dbg);
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
}
|
||||
return CreateWritableEncryptedFile(fname, underlying, options, result, dbg);
|
||||
|
||||
if (underlying->GetFileSize(options.io_options, dbg) != 0) {
|
||||
// read the cipher stream from file for non-empty file
|
||||
std::unique_ptr<FSRandomAccessFile> underlying_file_reader;
|
||||
status = FileSystemWrapper::NewRandomAccessFile(
|
||||
fname, options, &underlying_file_reader, dbg);
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = CreateRandomReadCipherStream(
|
||||
fname, underlying_file_reader, options, &prefix_length, &stream, dbg);
|
||||
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
}
|
||||
} else {
|
||||
// create cipher stream for new or empty file
|
||||
status = CreateWritableCipherStream(fname, underlying, options,
|
||||
&prefix_length, &stream, dbg);
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
if (stream) {
|
||||
result->reset(new EncryptedWritableFile(
|
||||
std::move(underlying), std::move(stream), prefix_length));
|
||||
} else {
|
||||
result->reset(underlying.release());
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
IOStatus ReuseWritableFile(const std::string& fname,
|
||||
|
||||
@@ -63,6 +63,8 @@ class DBWithTTL : public StackableDB {
|
||||
|
||||
virtual void SetTtl(ColumnFamilyHandle* h, int32_t ttl) = 0;
|
||||
|
||||
virtual Status GetTtl(ColumnFamilyHandle* h, int32_t* ttl) = 0;
|
||||
|
||||
protected:
|
||||
explicit DBWithTTL(DB* db) : StackableDB(db) {}
|
||||
};
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// NOTE: in 'main' development branch, this should be the *next*
|
||||
// minor or major version number planned for release.
|
||||
#define ROCKSDB_MAJOR 10
|
||||
#define ROCKSDB_MINOR 5
|
||||
#define ROCKSDB_MINOR 6
|
||||
#define ROCKSDB_PATCH 0
|
||||
|
||||
// Do not use these. We made the mistake of declaring macros starting with
|
||||
|
||||
@@ -72,6 +72,9 @@ std::unique_ptr<Configurable> CFOptionsAsConfigurable(
|
||||
Status StringToMap(const std::string& opts_str,
|
||||
std::unordered_map<std::string, std::string>* opts_map);
|
||||
|
||||
Status GetStringFromCompressionType(std::string* compression_str,
|
||||
CompressionType compression_type);
|
||||
|
||||
struct OptionsHelper {
|
||||
static const std::string kCFOptionsName /*= "ColumnFamilyOptions"*/;
|
||||
static const std::string kDBOptionsName /*= "DBOptions" */;
|
||||
|
||||
@@ -260,16 +260,21 @@ Status SstFileDumper::CalculateCompressedTableSize(
|
||||
}
|
||||
|
||||
Status SstFileDumper::ShowAllCompressionSizes(
|
||||
size_t block_size,
|
||||
const std::vector<std::pair<CompressionType, const char*>>&
|
||||
compression_types,
|
||||
size_t block_size, const std::vector<CompressionType>& compression_types,
|
||||
int32_t compress_level_from, int32_t compress_level_to,
|
||||
uint32_t max_dict_bytes, uint32_t zstd_max_train_bytes,
|
||||
uint64_t max_dict_buffer_bytes, bool use_zstd_dict_trainer) {
|
||||
fprintf(stdout, "Block Size: %" ROCKSDB_PRIszt "\n", block_size);
|
||||
for (auto& i : compression_types) {
|
||||
if (CompressionTypeSupported(i.first)) {
|
||||
fprintf(stdout, "Compression: %-24s\n", i.second);
|
||||
for (CompressionType ctype : compression_types) {
|
||||
std::string cname;
|
||||
if (!GetStringFromCompressionType(&cname, ctype).ok()) {
|
||||
// Can produce names like "Reserved4F" for unrecognized values
|
||||
cname = CompressionTypeToString(ctype);
|
||||
}
|
||||
if (options_.compression_manager
|
||||
? options_.compression_manager->SupportsCompressionType(ctype)
|
||||
: CompressionTypeSupported(ctype)) {
|
||||
fprintf(stdout, "Compression: %-24s\n", cname.c_str());
|
||||
CompressionOptions compress_opt;
|
||||
compress_opt.max_dict_bytes = max_dict_bytes;
|
||||
compress_opt.zstd_max_train_bytes = zstd_max_train_bytes;
|
||||
@@ -278,13 +283,13 @@ Status SstFileDumper::ShowAllCompressionSizes(
|
||||
for (int32_t j = compress_level_from; j <= compress_level_to; j++) {
|
||||
fprintf(stdout, "Compression level: %d", j);
|
||||
compress_opt.level = j;
|
||||
Status s = ShowCompressionSize(block_size, i.first, compress_opt);
|
||||
Status s = ShowCompressionSize(block_size, ctype, compress_opt);
|
||||
if (!s.ok()) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fprintf(stdout, "Unsupported compression type: %s.\n", i.second);
|
||||
fprintf(stdout, "Unsupported compression type: %s.\n", cname.c_str());
|
||||
}
|
||||
}
|
||||
return Status::OK();
|
||||
|
||||
@@ -43,9 +43,7 @@ class SstFileDumper {
|
||||
Status getStatus() { return init_result_; }
|
||||
|
||||
Status ShowAllCompressionSizes(
|
||||
size_t block_size,
|
||||
const std::vector<std::pair<CompressionType, const char*>>&
|
||||
compression_types,
|
||||
size_t block_size, const std::vector<CompressionType>& compression_types,
|
||||
int32_t compress_level_from, int32_t compress_level_to,
|
||||
uint32_t max_dict_bytes, uint32_t zstd_max_train_bytes,
|
||||
uint64_t max_dict_buffer_bytes, bool use_zstd_dict_trainer);
|
||||
|
||||
@@ -137,7 +137,7 @@ EOF
|
||||
|
||||
# To check for DB forward compatibility with loading options (old version
|
||||
# reading data from new), as well as backward compatibility
|
||||
declare -a db_forward_with_options_refs=("8.6.fb" "8.7.fb" "8.8.fb" "8.9.fb" "8.10.fb" "8.11.fb" "9.0.fb" "9.1.fb" "9.2.fb" "9.3.fb" "9.4.fb" "9.5.fb" "9.6.fb" "9.7.fb" "9.8.fb" "9.9.fb" "9.10.fb" "9.11.fb" "10.0.fb" "10.1.fb" "10.2.fb" "10.3.fb" "10.4.fb")
|
||||
declare -a db_forward_with_options_refs=("8.6.fb" "8.7.fb" "8.8.fb" "8.9.fb" "8.10.fb" "8.11.fb" "9.0.fb" "9.1.fb" "9.2.fb" "9.3.fb" "9.4.fb" "9.5.fb" "9.6.fb" "9.7.fb" "9.8.fb" "9.9.fb" "9.10.fb" "9.11.fb" "10.0.fb" "10.1.fb" "10.2.fb" "10.3.fb" "10.4.fb" "10.5.fb")
|
||||
# To check for DB forward compatibility without loading options (in addition
|
||||
# to the "with loading options" set), as well as backward compatibility
|
||||
declare -a db_forward_no_options_refs=() # N/A at the moment
|
||||
|
||||
+71
-1
@@ -15,6 +15,7 @@
|
||||
#include "rocksdb/convenience.h"
|
||||
#include "rocksdb/filter_policy.h"
|
||||
#include "rocksdb/sst_dump_tool.h"
|
||||
#include "rocksdb/utilities/object_registry.h"
|
||||
#include "table/block_based/block_based_table_factory.h"
|
||||
#include "table/sst_file_dumper.h"
|
||||
#include "table/table_builder.h"
|
||||
@@ -176,7 +177,6 @@ class SSTDumpToolTest : public testing::Test {
|
||||
constexpr static int kNumKey = 1024;
|
||||
};
|
||||
|
||||
constexpr int SSTDumpToolTest::kNumKey;
|
||||
|
||||
TEST_F(SSTDumpToolTest, HelpAndVersion) {
|
||||
Options opts;
|
||||
@@ -346,6 +346,76 @@ TEST_F(SSTDumpToolTest, CompressedSizes) {
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
using Compressor8A = test::CompressorCustomAlg<kCustomCompression8A>;
|
||||
class MyManager : public CompressionManager {
|
||||
public:
|
||||
static constexpr const char* kCompatibilityName = "SSTDumpToolTest:MyManager";
|
||||
const char* Name() const override { return kCompatibilityName; }
|
||||
const char* CompatibilityName() const override { return kCompatibilityName; }
|
||||
|
||||
bool SupportsCompressionType(CompressionType type) const override {
|
||||
return type == kCustomCompression8A;
|
||||
}
|
||||
|
||||
std::unique_ptr<Compressor> GetCompressor(const CompressionOptions& /*opts*/,
|
||||
CompressionType type) override {
|
||||
switch (static_cast<unsigned char>(type)) {
|
||||
case kCustomCompression8A:
|
||||
return std::make_unique<Compressor8A>();
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Decompressor> GetDecompressor() override {
|
||||
return std::make_shared<test::DecompressorCustomAlg>();
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
TEST_F(SSTDumpToolTest, CompressionManager) {
|
||||
if (!Compressor8A::Supported()) {
|
||||
fprintf(stderr,
|
||||
"Prerequisite compression library not supported. Skipping\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Registery in ObjectLibrary to check that sst_dump can use named
|
||||
// CompressionManagers with dependency injection
|
||||
auto& library = *ObjectLibrary::Default();
|
||||
library.AddFactory<CompressionManager>(
|
||||
MyManager::kCompatibilityName,
|
||||
[](const std::string& /*uri*/, std::unique_ptr<CompressionManager>* guard,
|
||||
std::string* /*errmsg*/) {
|
||||
*guard = std::make_unique<MyManager>();
|
||||
return guard->get();
|
||||
});
|
||||
|
||||
Options opts;
|
||||
opts.env = env();
|
||||
BlockBasedTableOptions table_opts;
|
||||
table_opts.filter_policy.reset(
|
||||
ROCKSDB_NAMESPACE::NewBloomFilterPolicy(10, false));
|
||||
opts.table_factory.reset(new BlockBasedTableFactory(table_opts));
|
||||
std::string file_path = MakeFilePath("rocksdb_sst_test.sst");
|
||||
createSST(opts, file_path, 10);
|
||||
|
||||
char* usage[5];
|
||||
PopulateCommandArgs(file_path, "--command=recompress", usage);
|
||||
snprintf(usage[3], kOptLength, "--compression_manager=%s",
|
||||
MyManager::kCompatibilityName);
|
||||
snprintf(usage[4], kOptLength, "--compression_types=kCustomCompression8A");
|
||||
|
||||
ROCKSDB_NAMESPACE::SSTDumpTool tool;
|
||||
ASSERT_TRUE(!tool.Run(5, usage, opts));
|
||||
|
||||
cleanup(opts, file_path);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
delete[] usage[i];
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(SSTDumpToolTest, MemEnv) {
|
||||
std::unique_ptr<Env> mem_env(NewMemEnv(env()));
|
||||
Options opts;
|
||||
|
||||
+37
-22
@@ -17,17 +17,6 @@
|
||||
|
||||
namespace ROCKSDB_NAMESPACE {
|
||||
|
||||
static const std::vector<std::pair<CompressionType, const char*>>
|
||||
kCompressions = {
|
||||
{CompressionType::kNoCompression, "kNoCompression"},
|
||||
{CompressionType::kSnappyCompression, "kSnappyCompression"},
|
||||
{CompressionType::kZlibCompression, "kZlibCompression"},
|
||||
{CompressionType::kBZip2Compression, "kBZip2Compression"},
|
||||
{CompressionType::kLZ4Compression, "kLZ4Compression"},
|
||||
{CompressionType::kLZ4HCCompression, "kLZ4HCCompression"},
|
||||
{CompressionType::kXpressCompression, "kXpressCompression"},
|
||||
{CompressionType::kZSTD, "kZSTD"}};
|
||||
|
||||
namespace {
|
||||
|
||||
void print_help(bool to_stderr) {
|
||||
@@ -98,10 +87,15 @@ void print_help(bool to_stderr) {
|
||||
be used when trying different compression algorithms
|
||||
|
||||
--compression_types=<comma-separated list of CompressionType members, e.g.,
|
||||
kSnappyCompression>
|
||||
kSnappyCompression or kCustomCompressionC4>
|
||||
Can be combined with --command=recompress to run recompression for this
|
||||
list of compression types
|
||||
Supported compression types: %s
|
||||
Supported built-in compression types: %s
|
||||
|
||||
--compression_manager=<compression manager string>
|
||||
Used with --command=recompress to specify a compression manager to use
|
||||
instead of the built-in compression manager, which may support a
|
||||
different set of compression types.
|
||||
|
||||
--parse_internal_key=<0xKEY>
|
||||
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) {
|
||||
std::string compression_level_to_str;
|
||||
size_t block_size = 0;
|
||||
size_t readahead_size = 2 * 1024 * 1024;
|
||||
std::vector<std::pair<CompressionType, const char*>> compression_types;
|
||||
std::vector<CompressionType> compression_types;
|
||||
std::shared_ptr<CompressionManager> compression_manager;
|
||||
uint64_t total_num_files = 0;
|
||||
uint64_t total_num_data_blocks = 0;
|
||||
uint64_t total_data_block_size = 0;
|
||||
@@ -244,19 +239,36 @@ int SSTDumpTool::Run(int argc, char const* const* argv, Options options) {
|
||||
std::istringstream iss(compression_types_csv);
|
||||
std::string compression_type;
|
||||
has_specified_compression_types = true;
|
||||
|
||||
while (std::getline(iss, compression_type, ',')) {
|
||||
auto iter = std::find_if(
|
||||
kCompressions.begin(), kCompressions.end(),
|
||||
[&compression_type](std::pair<CompressionType, const char*> curr) {
|
||||
return curr.second == compression_type;
|
||||
});
|
||||
if (iter == kCompressions.end()) {
|
||||
auto iter =
|
||||
OptionsHelper::compression_type_string_map.find(compression_type);
|
||||
if (iter == OptionsHelper::compression_type_string_map.end()) {
|
||||
fprintf(stderr, "%s is not a valid CompressionType\n",
|
||||
compression_type.c_str());
|
||||
exit(1);
|
||||
}
|
||||
compression_types.emplace_back(*iter);
|
||||
compression_types.emplace_back(iter->second);
|
||||
}
|
||||
} else if (strncmp(argv[i], "--compression_manager=", 22) == 0) {
|
||||
std::string compression_manager_str = argv[i] + 22;
|
||||
ConfigOptions config_options;
|
||||
config_options.ignore_unsupported_options = false;
|
||||
Status s = CompressionManager::CreateFromString(
|
||||
config_options, compression_manager_str, &compression_manager);
|
||||
if (!s.ok()) {
|
||||
fprintf(stderr, "Failed to create compression manager: %s\n",
|
||||
s.ToString().c_str());
|
||||
exit(1);
|
||||
}
|
||||
if (compression_manager == nullptr) {
|
||||
fprintf(stderr, "No compression manager created: %s\n",
|
||||
compression_manager_str.c_str());
|
||||
exit(1);
|
||||
}
|
||||
options.compression_manager = compression_manager;
|
||||
printf("Using compression manager: %s\n",
|
||||
compression_manager->GetId().c_str());
|
||||
} else if (strncmp(argv[i], "--parse_internal_key=", 21) == 0) {
|
||||
std::string in_key(argv[i] + 21);
|
||||
try {
|
||||
@@ -450,9 +462,12 @@ int SSTDumpTool::Run(int argc, char const* const* argv, Options options) {
|
||||
}
|
||||
|
||||
if (command == "recompress") {
|
||||
// TODO: consider getting supported compressions from the compression
|
||||
// manager
|
||||
st = dumper.ShowAllCompressionSizes(
|
||||
set_block_size ? block_size : 16384,
|
||||
compression_types.empty() ? kCompressions : compression_types,
|
||||
compression_types.empty() ? GetSupportedCompressions()
|
||||
: compression_types,
|
||||
compress_level_from, compress_level_to, compression_max_dict_bytes,
|
||||
compression_zstd_max_train_bytes, compression_max_dict_buffer_bytes,
|
||||
!compression_use_zstd_finalize_dict);
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
* PessimisticTransaction::GetWaitingTxns now returns waiting transaction information even if the current transaction has timed out. This allows the information to be surfaced to users for debugging purposes once it is known that the timeout has occured.
|
||||
-1
@@ -1 +0,0 @@
|
||||
A new API GetFileSize is added to FSRandomAccessFile interface class. It uses fstat vs stat on the posix implementation which is more efficient. Caller could use it to get file size faster. This function might be required in the future for FileSystem implementation outside of the RocksDB code base.
|
||||
@@ -1 +0,0 @@
|
||||
* RocksDB now triggers eligible compactions every 12 hours when periodic compaction is configured. This solves a limitation of the compaction trigger mechanism, which would only trigger compaction after specific events like flush, compaction, or SetOptions.
|
||||
@@ -1 +0,0 @@
|
||||
* Fix a bug in BackupEngine that can crash backup due to a null FSWritableFile passed to WritableFileWriter.
|
||||
@@ -1 +0,0 @@
|
||||
Fix DB::NewMultiScan iterator to respect the scan upper bound specified in ScanOptions
|
||||
@@ -1 +0,0 @@
|
||||
* Optimized MultiScan using BlockBasedTable to coalesce I/Os and prefetch all data blocks.
|
||||
-1
@@ -1 +0,0 @@
|
||||
DB option skip_checking_sst_file_sizes_on_db_open is deprecated, in favor of validating file size in parallel in a thread pool, when db is opened. When DB is opened, with paranoid check enabled, a file with the wrong size would fail the DB open. With paranoid check disabled, the DB open would succeed, the column family with the corrupted file would not be read or write, while the other healthy column families could be read and write normally. When max_open_files option is not set to -1, only a subset of the files will be opened and checked. The rest of the files will be opened and checked when they are accessed.
|
||||
@@ -0,0 +1 @@
|
||||
GetTtl() API is now available in TTL DB
|
||||
@@ -322,9 +322,6 @@ Status PointLockManager::AcquireWithTimeout(
|
||||
// instead of exiting this while loop below.
|
||||
uint64_t now = env->NowMicros();
|
||||
if (static_cast<uint64_t>(cv_end_time) > now) {
|
||||
// This may be invoked multiple times since we divide
|
||||
// the time into smaller intervals.
|
||||
(void)ROCKSDB_THREAD_YIELD_CHECK_ABORT();
|
||||
result = stripe->stripe_cv->WaitFor(stripe->stripe_mutex,
|
||||
cv_end_time - now);
|
||||
cv_wait_fail = !result.ok() && !result.IsTimedOut();
|
||||
|
||||
@@ -635,4 +635,22 @@ void DBWithTTLImpl::SetTtl(ColumnFamilyHandle* h, int32_t ttl) {
|
||||
filter->SetTtl(ttl);
|
||||
}
|
||||
|
||||
Status DBWithTTLImpl::GetTtl(ColumnFamilyHandle* h, int32_t* ttl) {
|
||||
if (h == nullptr || ttl == nullptr) {
|
||||
return Status::InvalidArgument(
|
||||
"column family handle or ttl cannot be null");
|
||||
}
|
||||
std::shared_ptr<TtlCompactionFilterFactory> filter;
|
||||
Options opts;
|
||||
opts = GetOptions(h);
|
||||
filter = std::static_pointer_cast<TtlCompactionFilterFactory>(
|
||||
opts.compaction_filter_factory);
|
||||
if (!filter) {
|
||||
return Status::InvalidArgument(
|
||||
"TTLCompactionFilterFactory is not set for TTLDB");
|
||||
}
|
||||
*ttl = filter->GetTtl();
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
} // namespace ROCKSDB_NAMESPACE
|
||||
@@ -100,6 +100,8 @@ class DBWithTTLImpl : public DBWithTTL {
|
||||
|
||||
void SetTtl(ColumnFamilyHandle* h, int32_t ttl) override;
|
||||
|
||||
Status GetTtl(ColumnFamilyHandle* h, int32_t* ttl) override;
|
||||
|
||||
private:
|
||||
// remember whether the Close completes or not
|
||||
bool closed_;
|
||||
@@ -184,6 +186,7 @@ class TtlCompactionFilterFactory : public CompactionFilterFactory {
|
||||
std::unique_ptr<CompactionFilter> CreateCompactionFilter(
|
||||
const CompactionFilter::Context& context) override;
|
||||
void SetTtl(int32_t ttl) { ttl_ = ttl; }
|
||||
int32_t GetTtl() { return ttl_; }
|
||||
|
||||
const char* Name() const override { return kClassName(); }
|
||||
static const char* kClassName() { return "TtlCompactionFilterFactory"; }
|
||||
|
||||
@@ -720,6 +720,9 @@ TEST_F(TtlTest, ChangeTtlOnOpenDb) {
|
||||
|
||||
OpenTtl(1); // T=0:Open the db with ttl = 2
|
||||
SetTtl(3);
|
||||
int32_t ttl = 0;
|
||||
ASSERT_OK(db_ttl_->GetTtl(db_ttl_->DefaultColumnFamily(), &ttl));
|
||||
ASSERT_EQ(ttl, 3);
|
||||
PutValues(0, kSampleSize_); // T=0:Insert Set1. Delete at t=2
|
||||
SleepCompactCheck(2, 0, kSampleSize_, true); // T=2:Set1 should be there
|
||||
CloseTtl();
|
||||
|
||||
Reference in new issue
Block a user