mirror of
https://github.com/facebook/rocksdb.git
synced 2026-11-06 02:52:35 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8b5e4a6b7 | ||
|
|
a59ca8d5da | ||
|
|
740240e3b1 | ||
|
|
633631ac79 | ||
|
|
e7d28965ce | ||
|
|
c1b29dfe70 | ||
|
|
a116092ee6 | ||
|
|
f90d89ea52 | ||
|
|
cf149842a2 | ||
|
|
f2d64341f5 | ||
|
|
9c7f4946bb | ||
|
|
9885ced363 | ||
|
|
cda1e40498 | ||
|
|
0c3f08008a | ||
|
|
77af042413 | ||
|
|
acab405fc1 | ||
|
|
9a9a403a89 | ||
|
|
83026c7db2 | ||
|
|
06d4f569a8 | ||
|
|
b42bf48310 | ||
|
|
024194420c | ||
|
|
7c9b580681 | ||
|
|
fc2cf7ead2 | ||
|
|
df7a3a7168 | ||
|
|
2a0886b9a7 | ||
|
|
9c4b94b9e7 | ||
|
|
35e1c6c402 | ||
|
|
8cb2bfa233 | ||
|
|
0e3e349369 | ||
|
|
0102b1769b | ||
|
|
ef67339175 | ||
|
|
36600d8fa0 | ||
|
|
13d865f6f1 | ||
|
|
947a63400f | ||
|
|
f49d76b7ad | ||
|
|
1428e950bd | ||
|
|
e3b7dd7b56 | ||
|
|
9d1a071194 | ||
|
|
72c3887167 | ||
|
|
b2815b6b46 | ||
|
|
6c0e55a2a9 | ||
|
|
0560544e86 | ||
|
|
613e1a9a38 | ||
|
|
bcda3bda04 | ||
|
|
9998478c64 | ||
|
|
c368c6afe8 | ||
|
|
1614345a52 | ||
|
|
c237022831 |
No files matched your search
@@ -38,7 +38,7 @@ runs:
|
||||
$env:Path = $env:JAVA_HOME + ";" + $env:Path
|
||||
mkdir build
|
||||
cd build
|
||||
& cmake -G "$Env:CMAKE_GENERATOR" -DCMAKE_BUILD_TYPE=Debug -DOPTDBG=1 -DPORTABLE="$Env:CMAKE_PORTABLE" -DSNAPPY=1 -DJNI=1 ..
|
||||
& cmake -G "$Env:CMAKE_GENERATOR" -DCMAKE_BUILD_TYPE=Debug -DOPTDBG=1 -DPORTABLE="$Env:CMAKE_PORTABLE" -DSNAPPY=1 -DXPRESS=1 -DJNI=1 ..
|
||||
if(!$?) { Exit $LASTEXITCODE }
|
||||
cd ..
|
||||
echo "Building with VS version: $Env:CMAKE_GENERATOR"
|
||||
|
||||
+57
@@ -1,6 +1,63 @@
|
||||
# Rocksdb Change Log
|
||||
> NOTE: Entries for next release do not go here. Follow instructions in `unreleased_history/README.txt`
|
||||
|
||||
## 10.3.4 (06/17/2025)
|
||||
### Public API Changes
|
||||
* Change NewExternalTableFactory to return a unique_ptr instead of shared_ptr.
|
||||
|
||||
## 10.3.3 (06/04/2025)
|
||||
### Bug Fixes
|
||||
* Fix iterator operations returning NotImplemented status if disallow_memtable_writes and paranoid_memory_checks CF options are both set.
|
||||
* Fix Windows-only XPRESS compression
|
||||
* Fix newer gtest compatibility
|
||||
|
||||
## 10.3.2 (05/30/2025)
|
||||
### Behavior Changes
|
||||
* In Remote Compactions, instead of using FileSystem::GetFileSize() for each CompactionOutputFile, use the file size that is being tracked internally as part of the output file's metadata. FileSize is now part of CompactionServiceOutputFile and serialized in the CompactionServiceResult
|
||||
|
||||
## 10.3.1 (05/22/2025)
|
||||
### New Features
|
||||
* Add new experimental `TransactionOptions::large_txn_commit_optimize_byte_threshold` to enable optimizations for large transaction commit by transaction batch data size.
|
||||
|
||||
### Behavior Changes
|
||||
* `TransactionOptions::large_txn_commit_optimize_threshold` now has default value 0 for disabled. `TransactionDBOptions::txn_commit_bypass_memtable_threshold` now has no effect on transactions.
|
||||
|
||||
## 10.3.0 (05/17/2025)
|
||||
### New Features
|
||||
* Add new experimental `CompactionOptionsFIFO::allow_trivial_copy_when_change_temperature` along with `CompactionOptionsFIFO::trivial_copy_buffer_size` to allow optimizing FIFO compactions with tiering when kChangeTemperature to move files from source tier FileSystem to another tier FileSystem via trivial and direct copying raw sst file instead of reading thru the content of the SST file then rebuilding the table files.
|
||||
* Add a new field to Compaction Stats in LOG files for the pre-compression size written to each level.
|
||||
* Add new experimental `TransactionOptions::large_txn_commit_optimize_threshold` to enable optimizations for large transaction commit with per transaction threshold. `TransactionDBOptions::txn_commit_bypass_memtable_threshold` is deprecated in favor of this transaction option.
|
||||
* [internal team use only] Allow an application-defined `request_id` to be passed to RocksDB and propagated to the filesystem via IODebugContext
|
||||
|
||||
### Bug Fixes
|
||||
* Fix a bug where transaction lock upgrade can incorrectly fail with a Deadlock status. This happens when a transaction has a non-zero timeout and tries to upgrade a shared lock that is also held by another transaction.
|
||||
* Pass wrapped WritableFileWriter pointer to ExternalTableBuilder so that the file checksum can be correctly calculated and returned by SstFileWriter for external table files.
|
||||
* Fix an infinite-loop bug in transaction locking. This can happen if a transaction reaches lock limit and its time out expires before it attempts to wait for it.
|
||||
* Fixed a potential data race with `CompressionOptions::parallel_threads > 1` and a `TablePropertiesCollector` overriding `BlockAdd()`.
|
||||
|
||||
## 10.2.0 (04/21/2025)
|
||||
### New Features
|
||||
* Provide histogram stats `COMPACTION_PREFETCH_BYTES` to measure number of bytes for RocksDB's prefetching (as opposed to file
|
||||
system's prefetch) on SST file during compaction read
|
||||
* A new API DB::GetNewestUserDefinedTimestamp is added to return the newest user defined timestamp seen in a column family
|
||||
* Introduce API `IngestWriteBatchWithIndex()` for ingesting updates into DB while bypassing memtable writes. This improves performance when writing a large write batch to the DB.
|
||||
* Add a new CF option `memtable_op_scan_flush_trigger` that triggers a flush of the memtable if an iterator's Seek()/Next() scans over a certain number of invisible entries from the memtable.
|
||||
|
||||
### Public API Changes
|
||||
* AdvancedColumnFamilyOptions.max_write_buffer_number_to_maintain is deleted. It's deprecated since introduction of a better option max_write_buffer_size_to_maintain since RocksDB 6.5.0.
|
||||
* Deprecated API `DB::MaxMemCompactionLevel()`.
|
||||
* Deprecated `ReadOptions::ignore_range_deletions`.
|
||||
* Deprecated API `experimental::PromoteL0()`.
|
||||
* Added arbitrary string map for additional options to be overriden for remote compactions
|
||||
* The fail_if_options_file_error option in DBOptions has been removed. The behavior now is to always return failure in any API that fails to persist the OPTIONS file.
|
||||
|
||||
### Behavior Changes
|
||||
* Make stats `PREFETCH_BYTES_USEFUL`, `PREFETCH_HITS`, `PREFETCH_BYTES` only account for prefetching during user initiated scan
|
||||
|
||||
### Bug Fixes
|
||||
* Fix a bug in Posix file system that the FSWritableFile created via `FileSystem::ReopenWritableFile` internally does not track the correct file size.
|
||||
* Fix a bug where tail size of remote compaction output is not persisted in primary db's manifest
|
||||
|
||||
## 10.1.0 (03/24/2025)
|
||||
### New Features
|
||||
* Added a new `DBOptions.calculate_sst_write_lifetime_hint_set` setting that allows to customize which compaction styles SST write lifetime hint calculation is allowed on. Today RocksDB supports only two modes `kCompactionStyleLevel` and `kCompactionStyleUniversal`.
|
||||
|
||||
@@ -2489,7 +2489,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 78286282478e1ae05b2e8cbcf0e2139eab283bea
|
||||
cd third-party/folly && git reset --hard 8e8186f67de7a23d3a07366946b1617343927d84
|
||||
@# NOTE: this hack is required for clang in some cases
|
||||
perl -pi -e 's/int rv = syscall/int rv = (int)syscall/' third-party/folly/folly/detail/Futex.cpp
|
||||
@# NOTE: this hack is required for gcc in some cases
|
||||
|
||||
@@ -118,6 +118,9 @@ fi
|
||||
# fi
|
||||
set -e
|
||||
|
||||
# Exclude third-party from formatting
|
||||
EXCLUDE=':!third-party/'
|
||||
|
||||
uncommitted_code=`git diff HEAD`
|
||||
|
||||
# If there's no uncommitted changes, we assume user are doing post-commit
|
||||
@@ -137,11 +140,11 @@ then
|
||||
# should be relevant for formatting fixes.
|
||||
FORMAT_UPSTREAM_MERGE_BASE="$(git merge-base "$FORMAT_UPSTREAM" HEAD)"
|
||||
# Get the differences
|
||||
diffs=$(git diff -U0 "$FORMAT_UPSTREAM_MERGE_BASE" | $CLANG_FORMAT_DIFF -p 1) || true
|
||||
diffs=$(git diff -U0 "$FORMAT_UPSTREAM_MERGE_BASE" -- $EXCLUDE | $CLANG_FORMAT_DIFF -p 1) || true
|
||||
echo "Checking format of changes not yet in $FORMAT_UPSTREAM..."
|
||||
else
|
||||
# Check the format of uncommitted lines,
|
||||
diffs=$(git diff -U0 HEAD | $CLANG_FORMAT_DIFF -p 1) || true
|
||||
diffs=$(git diff -U0 HEAD -- $EXCLUDE | $CLANG_FORMAT_DIFF -p 1) || true
|
||||
echo "Checking format of uncommitted changes..."
|
||||
fi
|
||||
|
||||
@@ -187,9 +190,9 @@ fi
|
||||
# Do in-place format adjustment.
|
||||
if [ -z "$uncommitted_code" ]
|
||||
then
|
||||
git diff -U0 "$FORMAT_UPSTREAM_MERGE_BASE" | $CLANG_FORMAT_DIFF -i -p 1
|
||||
git diff -U0 "$FORMAT_UPSTREAM_MERGE_BASE" -- $EXCLUDE | $CLANG_FORMAT_DIFF -i -p 1
|
||||
else
|
||||
git diff -U0 HEAD | $CLANG_FORMAT_DIFF -i -p 1
|
||||
git diff -U0 HEAD -- $EXCLUDE | $CLANG_FORMAT_DIFF -i -p 1
|
||||
fi
|
||||
echo "Files reformatted!"
|
||||
|
||||
|
||||
Vendored
+35
-32
@@ -24,7 +24,14 @@ CompressedSecondaryCache::CompressedSecondaryCache(
|
||||
cache_res_mgr_(std::make_shared<ConcurrentCacheReservationManager>(
|
||||
std::make_shared<CacheReservationManagerImpl<CacheEntryRole::kMisc>>(
|
||||
cache_))),
|
||||
disable_cache_(opts.capacity == 0) {}
|
||||
disable_cache_(opts.capacity == 0) {
|
||||
auto mgr =
|
||||
GetBuiltinCompressionManager(cache_options_.compress_format_version);
|
||||
compressor_ = mgr->GetCompressor(cache_options_.compression_opts,
|
||||
cache_options_.compression_type);
|
||||
decompressor_ =
|
||||
mgr->GetDecompressorOptimizeFor(cache_options_.compression_type);
|
||||
}
|
||||
|
||||
CompressedSecondaryCache::~CompressedSecondaryCache() = default;
|
||||
|
||||
@@ -97,25 +104,24 @@ std::unique_ptr<SecondaryCacheResultHandle> CompressedSecondaryCache::Lookup(
|
||||
kNoCompression, CacheTier::kVolatileTier,
|
||||
create_context, allocator, &value, &charge);
|
||||
} else {
|
||||
UncompressionContext uncompression_context(
|
||||
cache_options_.compression_type);
|
||||
UncompressionInfo uncompression_info(uncompression_context,
|
||||
UncompressionDict::GetEmptyDict(),
|
||||
cache_options_.compression_type);
|
||||
|
||||
size_t uncompressed_size{0};
|
||||
CacheAllocationPtr uncompressed =
|
||||
UncompressData(uncompression_info, (char*)data_ptr,
|
||||
handle_value_charge, &uncompressed_size,
|
||||
cache_options_.compress_format_version, allocator);
|
||||
|
||||
if (!uncompressed) {
|
||||
cache_->Release(lru_handle, /*erase_if_last_ref=*/true);
|
||||
return nullptr;
|
||||
// TODO: can we work some magic with create_cb, which might be based on
|
||||
// custom compression, to decompress without an extra copy in create_cb?
|
||||
Decompressor::Args args;
|
||||
args.compressed_data = Slice(data_ptr, handle_value_charge);
|
||||
args.compression_type = cache_options_.compression_type;
|
||||
s = decompressor_->ExtractUncompressedSize(args);
|
||||
assert(s.ok());
|
||||
if (s.ok()) {
|
||||
auto uncompressed = std::make_unique<char[]>(args.uncompressed_size);
|
||||
s = decompressor_->DecompressBlock(args, uncompressed.get());
|
||||
assert(s.ok());
|
||||
if (s.ok()) {
|
||||
s = helper->create_cb(
|
||||
Slice(uncompressed.get(), args.uncompressed_size), kNoCompression,
|
||||
CacheTier::kVolatileTier, create_context, allocator, &value,
|
||||
&charge);
|
||||
}
|
||||
}
|
||||
s = helper->create_cb(Slice(uncompressed.get(), uncompressed_size),
|
||||
kNoCompression, CacheTier::kVolatileTier,
|
||||
create_context, allocator, &value, &charge);
|
||||
}
|
||||
} else {
|
||||
// The item was not compressed by us. Let the helper create_cb
|
||||
@@ -198,20 +204,17 @@ Status CompressedSecondaryCache::InsertInternal(
|
||||
type == kNoCompression &&
|
||||
!cache_options_.do_not_compress_roles.Contains(helper->role)) {
|
||||
PERF_COUNTER_ADD(compressed_sec_cache_uncompressed_bytes, data_size);
|
||||
CompressionContext compression_context(cache_options_.compression_type,
|
||||
cache_options_.compression_opts);
|
||||
uint64_t sample_for_compression{0};
|
||||
CompressionInfo compression_info(
|
||||
cache_options_.compression_opts, compression_context,
|
||||
CompressionDict::GetEmptyDict(), cache_options_.compression_type,
|
||||
sample_for_compression);
|
||||
|
||||
bool success =
|
||||
CompressData(val, compression_info,
|
||||
cache_options_.compress_format_version, &compressed_val);
|
||||
|
||||
if (!success) {
|
||||
return Status::Corruption("Error compressing value.");
|
||||
CompressionType to_type = kNoCompression;
|
||||
s = compressor_->CompressBlock(val, &compressed_val, &to_type,
|
||||
nullptr /*working_area*/);
|
||||
if (!s.ok()) {
|
||||
return s;
|
||||
}
|
||||
// TODO: allow values not compressed when there's no size savings?
|
||||
assert(to_type == cache_options_.compression_type);
|
||||
if (to_type != cache_options_.compression_type) {
|
||||
return Status::Corruption("Failed to compress value.");
|
||||
}
|
||||
|
||||
val = Slice(compressed_val);
|
||||
|
||||
Vendored
+2
@@ -145,6 +145,8 @@ class CompressedSecondaryCache : public SecondaryCache {
|
||||
const Cache::CacheItemHelper* GetHelper(bool enable_custom_split_merge) const;
|
||||
std::shared_ptr<Cache> cache_;
|
||||
CompressedSecondaryCacheOptions cache_options_;
|
||||
std::unique_ptr<Compressor> compressor_;
|
||||
std::shared_ptr<Decompressor> decompressor_;
|
||||
mutable port::Mutex capacity_mutex_;
|
||||
std::shared_ptr<ConcurrentCacheReservationManager> cache_res_mgr_;
|
||||
bool disable_cache_;
|
||||
|
||||
Vendored
+11
-1
@@ -121,7 +121,17 @@ CacheWithSecondaryAdapter::~CacheWithSecondaryAdapter() {
|
||||
assert(s.ok());
|
||||
assert(placeholder_usage_ == 0);
|
||||
assert(reserved_usage_ == 0);
|
||||
assert(pri_cache_res_->GetTotalMemoryUsed() == sec_capacity);
|
||||
bool pri_cache_res_mismatch =
|
||||
pri_cache_res_->GetTotalMemoryUsed() != sec_capacity;
|
||||
if (pri_cache_res_mismatch) {
|
||||
fprintf(stderr,
|
||||
"~CacheWithSecondaryAdapter: Primary cache reservation: "
|
||||
"%zu, Secondary cache capacity: %zu, "
|
||||
"Secondary cache reserved: %zu\n",
|
||||
pri_cache_res_->GetTotalMemoryUsed(), sec_capacity,
|
||||
sec_reserved_);
|
||||
assert(pri_cache_res_mismatch);
|
||||
}
|
||||
}
|
||||
#endif // NDEBUG
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ void ArenaWrappedDBIter::Init(
|
||||
db_iter_ = DBIter::NewIter(
|
||||
env, read_options_, ioptions, mutable_cf_options,
|
||||
ioptions.user_comparator, /*internal_iter=*/nullptr, version, sequence,
|
||||
read_callback, cfh, expose_blob_index, active_mem, &arena_);
|
||||
read_callback, active_mem, cfh, expose_blob_index, &arena_);
|
||||
|
||||
sv_number_ = version_number;
|
||||
allow_refresh_ = allow_refresh;
|
||||
|
||||
@@ -267,10 +267,9 @@ Status BlobFileBuilder::CompressBlobIfNeeded(
|
||||
// TODO: allow user CompressionOptions, including max_compressed_bytes_per_kb
|
||||
CompressionOptions opts;
|
||||
CompressionContext context(blob_compression_type_, opts);
|
||||
constexpr uint64_t sample_for_compression = 0;
|
||||
|
||||
CompressionInfo info(opts, context, CompressionDict::GetEmptyDict(),
|
||||
blob_compression_type_, sample_for_compression);
|
||||
blob_compression_type_);
|
||||
|
||||
constexpr uint32_t compression_format_version = 2;
|
||||
|
||||
@@ -279,8 +278,8 @@ Status BlobFileBuilder::CompressBlobIfNeeded(
|
||||
{
|
||||
StopWatch stop_watch(immutable_options_->clock, immutable_options_->stats,
|
||||
BLOB_DB_COMPRESSION_MICROS);
|
||||
success =
|
||||
CompressData(*blob, info, compression_format_version, compressed_blob);
|
||||
success = OLD_CompressData(*blob, info, compression_format_version,
|
||||
compressed_blob);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
|
||||
@@ -405,10 +405,9 @@ TEST_F(BlobFileBuilderTest, Compression) {
|
||||
|
||||
CompressionOptions opts;
|
||||
CompressionContext context(kSnappyCompression, opts);
|
||||
constexpr uint64_t sample_for_compression = 0;
|
||||
|
||||
CompressionInfo info(opts, context, CompressionDict::GetEmptyDict(),
|
||||
kSnappyCompression, sample_for_compression);
|
||||
kSnappyCompression);
|
||||
|
||||
std::string compressed_value;
|
||||
ASSERT_TRUE(Snappy_Compress(info, uncompressed_value.data(),
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <iosfwd>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
@@ -250,7 +250,8 @@ Status BlobFileReader::ReadFromFile(const RandomAccessFileReader* file_reader,
|
||||
Status s;
|
||||
|
||||
IOOptions io_options;
|
||||
s = file_reader->PrepareIOOptions(read_options, io_options);
|
||||
IODebugContext dbg;
|
||||
s = file_reader->PrepareIOOptions(read_options, io_options, &dbg);
|
||||
if (!s.ok()) {
|
||||
return s;
|
||||
}
|
||||
@@ -259,13 +260,13 @@ Status BlobFileReader::ReadFromFile(const RandomAccessFileReader* file_reader,
|
||||
constexpr char* scratch = nullptr;
|
||||
|
||||
s = file_reader->Read(io_options, read_offset, read_size, slice, scratch,
|
||||
aligned_buf);
|
||||
aligned_buf, &dbg);
|
||||
} else {
|
||||
buf->reset(new char[read_size]);
|
||||
constexpr AlignedBuf* aligned_scratch = nullptr;
|
||||
|
||||
s = file_reader->Read(io_options, read_offset, read_size, slice, buf->get(),
|
||||
aligned_scratch);
|
||||
aligned_scratch, &dbg);
|
||||
}
|
||||
|
||||
if (!s.ok()) {
|
||||
@@ -334,7 +335,8 @@ Status BlobFileReader::GetBlob(
|
||||
constexpr bool for_compaction = true;
|
||||
|
||||
IOOptions io_options;
|
||||
s = file_reader_->PrepareIOOptions(read_options, io_options);
|
||||
IODebugContext dbg;
|
||||
s = file_reader_->PrepareIOOptions(read_options, io_options, &dbg);
|
||||
if (!s.ok()) {
|
||||
return s;
|
||||
}
|
||||
@@ -463,10 +465,11 @@ void BlobFileReader::MultiGetBlob(
|
||||
PERF_COUNTER_ADD(blob_read_count, num_blobs);
|
||||
PERF_COUNTER_ADD(blob_read_byte, total_len);
|
||||
IOOptions opts;
|
||||
s = file_reader_->PrepareIOOptions(read_options, opts);
|
||||
IODebugContext dbg;
|
||||
s = file_reader_->PrepareIOOptions(read_options, opts, &dbg);
|
||||
if (s.ok()) {
|
||||
s = file_reader_->MultiRead(opts, read_reqs.data(), read_reqs.size(),
|
||||
direct_io ? &aligned_buf : nullptr);
|
||||
direct_io ? &aligned_buf : nullptr, &dbg);
|
||||
}
|
||||
if (!s.ok()) {
|
||||
for (auto& req : read_reqs) {
|
||||
@@ -602,9 +605,9 @@ Status BlobFileReader::UncompressBlobIfNeeded(
|
||||
{
|
||||
PERF_TIMER_GUARD(blob_decompress_time);
|
||||
StopWatch stop_watch(clock, statistics, BLOB_DB_DECOMPRESSION_MICROS);
|
||||
output = UncompressData(info, value_slice.data(), value_slice.size(),
|
||||
&uncompressed_size, compression_format_version,
|
||||
allocator);
|
||||
output = OLD_UncompressData(info, value_slice.data(), value_slice.size(),
|
||||
&uncompressed_size, compression_format_version,
|
||||
allocator);
|
||||
}
|
||||
|
||||
TEST_SYNC_POINT_CALLBACK(
|
||||
|
||||
@@ -75,15 +75,14 @@ void WriteBlobFile(const ImmutableOptions& immutable_options,
|
||||
} else {
|
||||
CompressionOptions opts;
|
||||
CompressionContext context(compression, opts);
|
||||
constexpr uint64_t sample_for_compression = 0;
|
||||
CompressionInfo info(opts, context, CompressionDict::GetEmptyDict(),
|
||||
compression, sample_for_compression);
|
||||
compression);
|
||||
|
||||
constexpr uint32_t compression_format_version = 2;
|
||||
|
||||
for (size_t i = 0; i < num; ++i) {
|
||||
ASSERT_TRUE(CompressData(blobs[i], info, compression_format_version,
|
||||
&compressed_blobs[i]));
|
||||
ASSERT_TRUE(OLD_CompressData(blobs[i], info, compression_format_version,
|
||||
&compressed_blobs[i]));
|
||||
blobs_to_write[i] = compressed_blobs[i];
|
||||
blob_sizes[i] = compressed_blobs[i].size();
|
||||
}
|
||||
|
||||
@@ -77,15 +77,14 @@ void WriteBlobFile(const ImmutableOptions& immutable_options,
|
||||
} else {
|
||||
CompressionOptions opts;
|
||||
CompressionContext context(compression, opts);
|
||||
constexpr uint64_t sample_for_compression = 0;
|
||||
CompressionInfo info(opts, context, CompressionDict::GetEmptyDict(),
|
||||
compression, sample_for_compression);
|
||||
compression);
|
||||
|
||||
constexpr uint32_t compression_format_version = 2;
|
||||
|
||||
for (size_t i = 0; i < num; ++i) {
|
||||
ASSERT_TRUE(CompressData(blobs[i], info, compression_format_version,
|
||||
&compressed_blobs[i]));
|
||||
ASSERT_TRUE(OLD_CompressData(blobs[i], info, compression_format_version,
|
||||
&compressed_blobs[i]));
|
||||
blobs_to_write[i] = compressed_blobs[i];
|
||||
blob_sizes[i] = compressed_blobs[i].size();
|
||||
}
|
||||
|
||||
+14
-4
@@ -74,8 +74,8 @@ Status BuildTable(
|
||||
EventLogger* event_logger, int job_id, TableProperties* table_properties,
|
||||
Env::WriteLifeTimeHint write_hint, const std::string* full_history_ts_low,
|
||||
BlobFileCompletionCallback* blob_callback, Version* version,
|
||||
uint64_t* num_input_entries, uint64_t* memtable_payload_bytes,
|
||||
uint64_t* memtable_garbage_bytes) {
|
||||
uint64_t* memtable_payload_bytes, uint64_t* memtable_garbage_bytes,
|
||||
InternalStats::CompactionStats* flush_stats) {
|
||||
assert((tboptions.column_family_id ==
|
||||
TablePropertiesCollectorFactory::Context::kUnknownColumnFamily) ==
|
||||
tboptions.column_family_name.empty());
|
||||
@@ -253,6 +253,10 @@ Status BuildTable(
|
||||
}
|
||||
builder->Add(key_after_flush, value_after_flush);
|
||||
|
||||
if (flush_stats) {
|
||||
flush_stats->num_output_records++;
|
||||
}
|
||||
|
||||
s = meta->UpdateBoundaries(key_after_flush, value_after_flush,
|
||||
ikey.sequence, ikey.type);
|
||||
if (!s.ok()) {
|
||||
@@ -284,6 +288,9 @@ Status BuildTable(
|
||||
auto tombstone = range_del_it->Tombstone();
|
||||
std::pair<InternalKey, Slice> kv = tombstone.Serialize();
|
||||
builder->Add(kv.first.Encode(), kv.second);
|
||||
if (flush_stats) {
|
||||
flush_stats->num_output_records++;
|
||||
}
|
||||
InternalKey tombstone_end = tombstone.SerializeEndKey();
|
||||
meta->UpdateBoundariesForRange(kv.first, tombstone_end, tombstone.seq_,
|
||||
tboptions.internal_comparator);
|
||||
@@ -305,9 +312,9 @@ Status BuildTable(
|
||||
|
||||
TEST_SYNC_POINT("BuildTable:BeforeFinishBuildTable");
|
||||
const bool empty = builder->IsEmpty();
|
||||
if (num_input_entries != nullptr) {
|
||||
if (flush_stats) {
|
||||
assert(c_iter.HasNumInputEntryScanned());
|
||||
*num_input_entries =
|
||||
flush_stats->num_input_records =
|
||||
c_iter.NumInputEntryScanned() + num_unfragmented_tombstones;
|
||||
}
|
||||
if (!s.ok() || empty) {
|
||||
@@ -334,6 +341,9 @@ Status BuildTable(
|
||||
}
|
||||
|
||||
if (s.ok() && !empty) {
|
||||
if (flush_stats) {
|
||||
flush_stats->bytes_written_pre_comp = builder->PreCompressionSize();
|
||||
}
|
||||
uint64_t file_size = builder->FileSize();
|
||||
meta->fd.file_size = file_size;
|
||||
meta->tail_size = builder->GetTailSize();
|
||||
|
||||
+5
-4
@@ -10,6 +10,7 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "db/internal_stats.h"
|
||||
#include "db/range_tombstone_fragmenter.h"
|
||||
#include "db/seqno_to_time_mapping.h"
|
||||
#include "db/table_properties_collector.h"
|
||||
@@ -34,7 +35,6 @@ class SnapshotChecker;
|
||||
class TableCache;
|
||||
class TableBuilder;
|
||||
class WritableFileWriter;
|
||||
class InternalStats;
|
||||
class BlobFileCompletionCallback;
|
||||
|
||||
// Convenience function for NewTableBuilder on the embedded table_factory.
|
||||
@@ -49,6 +49,7 @@ TableBuilder* NewTableBuilder(const TableBuilderOptions& tboptions,
|
||||
//
|
||||
// @param column_family_name Name of the column family that is also identified
|
||||
// by column_family_id, or empty string if unknown.
|
||||
// @param flush_stats treat flush as level 0 compaction in internal stats
|
||||
Status BuildTable(
|
||||
const std::string& dbname, VersionSet* versions,
|
||||
const ImmutableDBOptions& db_options, const TableBuilderOptions& tboptions,
|
||||
@@ -69,8 +70,8 @@ Status BuildTable(
|
||||
Env::WriteLifeTimeHint write_hint = Env::WLTH_NOT_SET,
|
||||
const std::string* full_history_ts_low = nullptr,
|
||||
BlobFileCompletionCallback* blob_callback = nullptr,
|
||||
Version* version = nullptr, uint64_t* num_input_entries = nullptr,
|
||||
uint64_t* memtable_payload_bytes = nullptr,
|
||||
uint64_t* memtable_garbage_bytes = nullptr);
|
||||
Version* version = nullptr, uint64_t* memtable_payload_bytes = nullptr,
|
||||
uint64_t* memtable_garbage_bytes = nullptr,
|
||||
InternalStats::CompactionStats* flush_stats = nullptr);
|
||||
|
||||
} // namespace ROCKSDB_NAMESPACE
|
||||
@@ -24,12 +24,14 @@
|
||||
#include "rocksdb/experimental.h"
|
||||
#include "rocksdb/filter_policy.h"
|
||||
#include "rocksdb/iterator.h"
|
||||
#include "rocksdb/listener.h"
|
||||
#include "rocksdb/memtablerep.h"
|
||||
#include "rocksdb/merge_operator.h"
|
||||
#include "rocksdb/options.h"
|
||||
#include "rocksdb/perf_context.h"
|
||||
#include "rocksdb/rate_limiter.h"
|
||||
#include "rocksdb/slice_transform.h"
|
||||
#include "rocksdb/sst_file_manager.h"
|
||||
#include "rocksdb/statistics.h"
|
||||
#include "rocksdb/status.h"
|
||||
#include "rocksdb/table.h"
|
||||
@@ -49,6 +51,7 @@
|
||||
#include "util/stderr_logger.h"
|
||||
#include "utilities/merge_operators.h"
|
||||
|
||||
using ROCKSDB_NAMESPACE::BackgroundErrorReason;
|
||||
using ROCKSDB_NAMESPACE::BackupEngine;
|
||||
using ROCKSDB_NAMESPACE::BackupEngineOptions;
|
||||
using ROCKSDB_NAMESPACE::BackupID;
|
||||
@@ -65,7 +68,9 @@ using ROCKSDB_NAMESPACE::ColumnFamilyMetaData;
|
||||
using ROCKSDB_NAMESPACE::ColumnFamilyOptions;
|
||||
using ROCKSDB_NAMESPACE::CompactionFilter;
|
||||
using ROCKSDB_NAMESPACE::CompactionFilterFactory;
|
||||
using ROCKSDB_NAMESPACE::CompactionJobInfo;
|
||||
using ROCKSDB_NAMESPACE::CompactionOptionsFIFO;
|
||||
using ROCKSDB_NAMESPACE::CompactionReason;
|
||||
using ROCKSDB_NAMESPACE::CompactRangeOptions;
|
||||
using ROCKSDB_NAMESPACE::Comparator;
|
||||
using ROCKSDB_NAMESPACE::CompressionType;
|
||||
@@ -76,8 +81,11 @@ using ROCKSDB_NAMESPACE::DBOptions;
|
||||
using ROCKSDB_NAMESPACE::DbPath;
|
||||
using ROCKSDB_NAMESPACE::Env;
|
||||
using ROCKSDB_NAMESPACE::EnvOptions;
|
||||
using ROCKSDB_NAMESPACE::EventListener;
|
||||
using ROCKSDB_NAMESPACE::ExternalFileIngestionInfo;
|
||||
using ROCKSDB_NAMESPACE::FileLock;
|
||||
using ROCKSDB_NAMESPACE::FilterPolicy;
|
||||
using ROCKSDB_NAMESPACE::FlushJobInfo;
|
||||
using ROCKSDB_NAMESPACE::FlushOptions;
|
||||
using ROCKSDB_NAMESPACE::HistogramData;
|
||||
using ROCKSDB_NAMESPACE::HyperClockCacheOptions;
|
||||
@@ -90,6 +98,7 @@ using ROCKSDB_NAMESPACE::Logger;
|
||||
using ROCKSDB_NAMESPACE::LRUCacheOptions;
|
||||
using ROCKSDB_NAMESPACE::MemoryAllocator;
|
||||
using ROCKSDB_NAMESPACE::MemoryUtil;
|
||||
using ROCKSDB_NAMESPACE::MemTableInfo;
|
||||
using ROCKSDB_NAMESPACE::MergeOperator;
|
||||
using ROCKSDB_NAMESPACE::NewBloomFilterPolicy;
|
||||
using ROCKSDB_NAMESPACE::NewCompactOnDeletionCollectorFactory;
|
||||
@@ -113,10 +122,12 @@ using ROCKSDB_NAMESPACE::Slice;
|
||||
using ROCKSDB_NAMESPACE::SliceParts;
|
||||
using ROCKSDB_NAMESPACE::SliceTransform;
|
||||
using ROCKSDB_NAMESPACE::Snapshot;
|
||||
using ROCKSDB_NAMESPACE::SstFileManager;
|
||||
using ROCKSDB_NAMESPACE::SstFileMetaData;
|
||||
using ROCKSDB_NAMESPACE::SstFileWriter;
|
||||
using ROCKSDB_NAMESPACE::Status;
|
||||
using ROCKSDB_NAMESPACE::StderrLogger;
|
||||
using ROCKSDB_NAMESPACE::SubcompactionJobInfo;
|
||||
using ROCKSDB_NAMESPACE::TablePropertiesCollectorFactory;
|
||||
using ROCKSDB_NAMESPACE::Transaction;
|
||||
using ROCKSDB_NAMESPACE::TransactionDB;
|
||||
@@ -130,6 +141,8 @@ using ROCKSDB_NAMESPACE::WriteBatch;
|
||||
using ROCKSDB_NAMESPACE::WriteBatchWithIndex;
|
||||
using ROCKSDB_NAMESPACE::WriteBufferManager;
|
||||
using ROCKSDB_NAMESPACE::WriteOptions;
|
||||
using ROCKSDB_NAMESPACE::WriteStallCondition;
|
||||
using ROCKSDB_NAMESPACE::WriteStallInfo;
|
||||
|
||||
using std::unordered_set;
|
||||
using std::vector;
|
||||
@@ -139,6 +152,9 @@ extern "C" {
|
||||
struct rocksdb_t {
|
||||
DB* rep;
|
||||
};
|
||||
struct rocksdb_status_ptr_t {
|
||||
Status* rep;
|
||||
};
|
||||
struct rocksdb_backup_engine_t {
|
||||
BackupEngine* rep;
|
||||
};
|
||||
@@ -226,6 +242,9 @@ struct rocksdb_cache_t {
|
||||
struct rocksdb_write_buffer_manager_t {
|
||||
std::shared_ptr<WriteBufferManager> rep;
|
||||
};
|
||||
struct rocksdb_sst_file_manager_t {
|
||||
std::shared_ptr<SstFileManager> rep;
|
||||
};
|
||||
struct rocksdb_livefiles_t {
|
||||
std::vector<LiveFileMetaData> rep;
|
||||
};
|
||||
@@ -292,6 +311,28 @@ struct rocksdb_compactionfiltercontext_t {
|
||||
CompactionFilter::Context rep;
|
||||
};
|
||||
|
||||
struct rocksdb_flushjobinfo_t {
|
||||
FlushJobInfo rep;
|
||||
};
|
||||
struct rocksdb_writestallcondition_t {
|
||||
WriteStallCondition rep;
|
||||
};
|
||||
struct rocksdb_writestallinfo_t {
|
||||
WriteStallInfo rep;
|
||||
};
|
||||
struct rocksdb_memtableinfo_t {
|
||||
MemTableInfo rep;
|
||||
};
|
||||
struct rocksdb_compactionjobinfo_t {
|
||||
CompactionJobInfo rep;
|
||||
};
|
||||
struct rocksdb_subcompactionjobinfo_t {
|
||||
SubcompactionJobInfo rep;
|
||||
};
|
||||
struct rocksdb_externalfileingestioninfo_t {
|
||||
ExternalFileIngestionInfo rep;
|
||||
};
|
||||
|
||||
struct rocksdb_statistics_histogram_data_t {
|
||||
rocksdb_statistics_histogram_data_t() : rep() {}
|
||||
HistogramData rep;
|
||||
@@ -2627,6 +2668,16 @@ rocksdb_iterator_t* rocksdb_writebatch_wi_create_iterator_with_base(
|
||||
return result;
|
||||
}
|
||||
|
||||
rocksdb_iterator_t* rocksdb_writebatch_wi_create_iterator_with_base_readopts(
|
||||
rocksdb_writebatch_wi_t* wbwi, rocksdb_iterator_t* base_iterator,
|
||||
const rocksdb_readoptions_t* options) {
|
||||
rocksdb_iterator_t* result = new rocksdb_iterator_t;
|
||||
result->rep =
|
||||
wbwi->rep->NewIteratorWithBase(base_iterator->rep, &options->rep);
|
||||
delete base_iterator;
|
||||
return result;
|
||||
}
|
||||
|
||||
rocksdb_iterator_t* rocksdb_writebatch_wi_create_iterator_with_base_cf(
|
||||
rocksdb_writebatch_wi_t* wbwi, rocksdb_iterator_t* base_iterator,
|
||||
rocksdb_column_family_handle_t* column_family) {
|
||||
@@ -2637,6 +2688,17 @@ rocksdb_iterator_t* rocksdb_writebatch_wi_create_iterator_with_base_cf(
|
||||
return result;
|
||||
}
|
||||
|
||||
rocksdb_iterator_t* rocksdb_writebatch_wi_create_iterator_with_base_cf_readopts(
|
||||
rocksdb_writebatch_wi_t* wbwi, rocksdb_iterator_t* base_iterator,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const rocksdb_readoptions_t* options) {
|
||||
rocksdb_iterator_t* result = new rocksdb_iterator_t;
|
||||
result->rep = wbwi->rep->NewIteratorWithBase(
|
||||
column_family->rep, base_iterator->rep, &options->rep);
|
||||
delete base_iterator;
|
||||
return result;
|
||||
}
|
||||
|
||||
char* rocksdb_writebatch_wi_get_from_batch(rocksdb_writebatch_wi_t* wbwi,
|
||||
const rocksdb_options_t* options,
|
||||
const char* key, size_t keylen,
|
||||
@@ -2696,6 +2758,23 @@ char* rocksdb_writebatch_wi_get_from_batch_and_db(
|
||||
return result;
|
||||
}
|
||||
|
||||
rocksdb_pinnableslice_t* rocksdb_writebatch_wi_get_pinned_from_batch_and_db(
|
||||
rocksdb_writebatch_wi_t* wbwi, rocksdb_t* db,
|
||||
const rocksdb_readoptions_t* options, const char* key, size_t keylen,
|
||||
char** errptr) {
|
||||
rocksdb_pinnableslice_t* v = new (rocksdb_pinnableslice_t);
|
||||
Status s = wbwi->rep->GetFromBatchAndDB(db->rep, options->rep,
|
||||
Slice(key, keylen), &v->rep);
|
||||
if (!s.ok()) {
|
||||
delete (v);
|
||||
if (!s.IsNotFound()) {
|
||||
SaveError(errptr, s);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
char* rocksdb_writebatch_wi_get_from_batch_and_db_cf(
|
||||
rocksdb_writebatch_wi_t* wbwi, rocksdb_t* db,
|
||||
const rocksdb_readoptions_t* options,
|
||||
@@ -2717,6 +2796,24 @@ char* rocksdb_writebatch_wi_get_from_batch_and_db_cf(
|
||||
return result;
|
||||
}
|
||||
|
||||
rocksdb_pinnableslice_t* rocksdb_writebatch_wi_get_pinned_from_batch_and_db_cf(
|
||||
rocksdb_writebatch_wi_t* wbwi, rocksdb_t* db,
|
||||
const rocksdb_readoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, char** errptr) {
|
||||
rocksdb_pinnableslice_t* v = new (rocksdb_pinnableslice_t);
|
||||
Status s = wbwi->rep->GetFromBatchAndDB(
|
||||
db->rep, options->rep, column_family->rep, Slice(key, keylen), &v->rep);
|
||||
if (!s.ok()) {
|
||||
delete (v);
|
||||
if (!s.IsNotFound()) {
|
||||
SaveError(errptr, s);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
void rocksdb_write_writebatch_wi(rocksdb_t* db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
rocksdb_writebatch_wi_t* wbwi, char** errptr) {
|
||||
@@ -2930,6 +3027,352 @@ void rocksdb_block_based_options_set_unpartitioned_pinning_tier(
|
||||
static_cast<ROCKSDB_NAMESPACE::PinningTier>(v);
|
||||
}
|
||||
|
||||
/* FlushJobInfo */
|
||||
|
||||
const char* rocksdb_flushjobinfo_cf_name(const rocksdb_flushjobinfo_t* info,
|
||||
size_t* size) {
|
||||
*size = info->rep.cf_name.size();
|
||||
return info->rep.cf_name.data();
|
||||
}
|
||||
|
||||
const char* rocksdb_flushjobinfo_file_path(const rocksdb_flushjobinfo_t* info,
|
||||
size_t* size) {
|
||||
*size = info->rep.file_path.size();
|
||||
return info->rep.file_path.data();
|
||||
}
|
||||
|
||||
unsigned char rocksdb_flushjobinfo_triggered_writes_slowdown(
|
||||
const rocksdb_flushjobinfo_t* info) {
|
||||
return info->rep.triggered_writes_slowdown;
|
||||
}
|
||||
|
||||
unsigned char rocksdb_flushjobinfo_triggered_writes_stop(
|
||||
const rocksdb_flushjobinfo_t* info) {
|
||||
return info->rep.triggered_writes_stop;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_flushjobinfo_largest_seqno(
|
||||
const rocksdb_flushjobinfo_t* info) {
|
||||
return info->rep.largest_seqno;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_flushjobinfo_smallest_seqno(
|
||||
const rocksdb_flushjobinfo_t* info) {
|
||||
return info->rep.smallest_seqno;
|
||||
}
|
||||
|
||||
void rocksdb_reset_status(rocksdb_status_ptr_t* status_ptr) {
|
||||
auto ptr = status_ptr->rep;
|
||||
*ptr = Status::OK();
|
||||
}
|
||||
|
||||
/* CompactionJobInfo */
|
||||
|
||||
void rocksdb_compactionjobinfo_status(const rocksdb_compactionjobinfo_t* info,
|
||||
char** errptr) {
|
||||
SaveError(errptr, info->rep.status);
|
||||
}
|
||||
|
||||
const char* rocksdb_compactionjobinfo_cf_name(
|
||||
const rocksdb_compactionjobinfo_t* info, size_t* size) {
|
||||
*size = info->rep.cf_name.size();
|
||||
return info->rep.cf_name.data();
|
||||
}
|
||||
|
||||
size_t rocksdb_compactionjobinfo_input_files_count(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.input_files.size();
|
||||
}
|
||||
|
||||
const char* rocksdb_compactionjobinfo_input_file_at(
|
||||
const rocksdb_compactionjobinfo_t* info, size_t pos, size_t* size) {
|
||||
assert(info != nullptr);
|
||||
assert(pos < info->rep.input_files.size());
|
||||
|
||||
const std::string& path = info->rep.input_files[pos];
|
||||
*size = path.size();
|
||||
return path.data();
|
||||
}
|
||||
|
||||
size_t rocksdb_compactionjobinfo_output_files_count(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.output_files.size();
|
||||
}
|
||||
|
||||
const char* rocksdb_compactionjobinfo_output_file_at(
|
||||
const rocksdb_compactionjobinfo_t* info, size_t pos, size_t* size) {
|
||||
assert(info != nullptr);
|
||||
assert(pos < info->rep.output_files.size());
|
||||
|
||||
const std::string& path = info->rep.output_files[pos];
|
||||
*size = path.size();
|
||||
return path.data();
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compactionjobinfo_elapsed_micros(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.stats.elapsed_micros;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compactionjobinfo_num_corrupt_keys(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.stats.num_corrupt_keys;
|
||||
}
|
||||
|
||||
int rocksdb_compactionjobinfo_base_input_level(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.base_input_level;
|
||||
}
|
||||
|
||||
int rocksdb_compactionjobinfo_output_level(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.output_level;
|
||||
}
|
||||
|
||||
size_t rocksdb_compactionjobinfo_num_input_files(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.stats.num_input_files;
|
||||
}
|
||||
|
||||
size_t rocksdb_compactionjobinfo_num_input_files_at_output_level(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.stats.num_input_files_at_output_level;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compactionjobinfo_input_records(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.stats.num_input_records;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compactionjobinfo_output_records(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.stats.num_output_records;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compactionjobinfo_total_input_bytes(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.stats.total_input_bytes;
|
||||
}
|
||||
|
||||
uint64_t rocksdb_compactionjobinfo_total_output_bytes(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return info->rep.stats.total_output_bytes;
|
||||
}
|
||||
|
||||
uint32_t rocksdb_compactionjobinfo_compaction_reason(
|
||||
const rocksdb_compactionjobinfo_t* info) {
|
||||
return static_cast<uint32_t>(info->rep.compaction_reason);
|
||||
}
|
||||
|
||||
/* SubcompactionJobInfo */
|
||||
|
||||
void rocksdb_subcompactionjobinfo_status(
|
||||
const rocksdb_subcompactionjobinfo_t* info, char** errptr) {
|
||||
SaveError(errptr, info->rep.status);
|
||||
}
|
||||
|
||||
const char* rocksdb_subcompactionjobinfo_cf_name(
|
||||
const rocksdb_subcompactionjobinfo_t* info, size_t* size) {
|
||||
*size = info->rep.cf_name.size();
|
||||
return info->rep.cf_name.data();
|
||||
}
|
||||
|
||||
uint64_t rocksdb_subcompactionjobinfo_thread_id(
|
||||
const rocksdb_subcompactionjobinfo_t* info) {
|
||||
return info->rep.thread_id;
|
||||
}
|
||||
|
||||
int rocksdb_subcompactionjobinfo_base_input_level(
|
||||
const rocksdb_subcompactionjobinfo_t* info) {
|
||||
return info->rep.base_input_level;
|
||||
}
|
||||
|
||||
int rocksdb_subcompactionjobinfo_output_level(
|
||||
const rocksdb_subcompactionjobinfo_t* info) {
|
||||
return info->rep.output_level;
|
||||
}
|
||||
|
||||
/* ExternalFileIngestionInfo */
|
||||
|
||||
const char* rocksdb_externalfileingestioninfo_cf_name(
|
||||
const rocksdb_externalfileingestioninfo_t* info, size_t* size) {
|
||||
*size = info->rep.cf_name.size();
|
||||
return info->rep.cf_name.data();
|
||||
}
|
||||
|
||||
const char* rocksdb_externalfileingestioninfo_internal_file_path(
|
||||
const rocksdb_externalfileingestioninfo_t* info, size_t* size) {
|
||||
*size = info->rep.internal_file_path.size();
|
||||
return info->rep.internal_file_path.data();
|
||||
}
|
||||
|
||||
/* External write stall info */
|
||||
extern ROCKSDB_LIBRARY_API const char* rocksdb_writestallinfo_cf_name(
|
||||
const rocksdb_writestallinfo_t* info, size_t* size) {
|
||||
*size = info->rep.cf_name.size();
|
||||
return info->rep.cf_name.data();
|
||||
}
|
||||
|
||||
const rocksdb_writestallcondition_t* rocksdb_writestallinfo_cur(
|
||||
const rocksdb_writestallinfo_t* info) {
|
||||
return reinterpret_cast<const rocksdb_writestallcondition_t*>(
|
||||
&info->rep.condition.cur);
|
||||
}
|
||||
|
||||
const rocksdb_writestallcondition_t* rocksdb_writestallinfo_prev(
|
||||
const rocksdb_writestallinfo_t* info) {
|
||||
return reinterpret_cast<const rocksdb_writestallcondition_t*>(
|
||||
&info->rep.condition.prev);
|
||||
}
|
||||
|
||||
const char* rocksdb_memtableinfo_cf_name(const rocksdb_memtableinfo_t* info,
|
||||
size_t* size) {
|
||||
*size = info->rep.cf_name.size();
|
||||
return info->rep.cf_name.data();
|
||||
}
|
||||
|
||||
uint64_t rocksdb_memtableinfo_first_seqno(const rocksdb_memtableinfo_t* info) {
|
||||
return info->rep.first_seqno;
|
||||
}
|
||||
uint64_t rocksdb_memtableinfo_earliest_seqno(
|
||||
const rocksdb_memtableinfo_t* info) {
|
||||
return info->rep.earliest_seqno;
|
||||
}
|
||||
uint64_t rocksdb_memtableinfo_num_entries(const rocksdb_memtableinfo_t* info) {
|
||||
return info->rep.num_entries;
|
||||
}
|
||||
uint64_t rocksdb_memtableinfo_num_deletes(const rocksdb_memtableinfo_t* info) {
|
||||
return info->rep.num_deletes;
|
||||
}
|
||||
|
||||
/* event listener */
|
||||
|
||||
struct rocksdb_eventlistener_t : public EventListener {
|
||||
void* state_{};
|
||||
void (*destructor_)(void*){};
|
||||
void (*on_flush_begin)(void*, rocksdb_t*, const rocksdb_flushjobinfo_t*){};
|
||||
void (*on_flush_completed)(void*, rocksdb_t*,
|
||||
const rocksdb_flushjobinfo_t*){};
|
||||
void (*on_compaction_begin)(void*, rocksdb_t*,
|
||||
const rocksdb_compactionjobinfo_t*){};
|
||||
void (*on_compaction_completed)(void*, rocksdb_t*,
|
||||
const rocksdb_compactionjobinfo_t*){};
|
||||
void (*on_subcompaction_begin)(void*,
|
||||
const rocksdb_subcompactionjobinfo_t*){};
|
||||
void (*on_subcompaction_completed)(void*,
|
||||
const rocksdb_subcompactionjobinfo_t*){};
|
||||
void (*on_external_file_ingested)(
|
||||
void*, rocksdb_t*, const rocksdb_externalfileingestioninfo_t*){};
|
||||
void (*on_background_error)(void*, uint32_t, rocksdb_status_ptr_t*){};
|
||||
void (*on_stall_conditions_changed)(void*, const rocksdb_writestallinfo_t*){};
|
||||
void (*on_memtable_sealed)(void*, const rocksdb_memtableinfo_t*){};
|
||||
|
||||
rocksdb_eventlistener_t() = default;
|
||||
|
||||
rocksdb_eventlistener_t(const rocksdb_eventlistener_t&) = delete;
|
||||
rocksdb_eventlistener_t& operator=(const rocksdb_eventlistener_t&) = delete;
|
||||
rocksdb_eventlistener_t(rocksdb_eventlistener_t&&) = delete;
|
||||
rocksdb_eventlistener_t& operator=(rocksdb_eventlistener_t&&) = delete;
|
||||
|
||||
void OnFlushBegin(DB* db, const FlushJobInfo& info) override {
|
||||
rocksdb_t c_db = {db};
|
||||
on_flush_begin(state_, &c_db,
|
||||
reinterpret_cast<const rocksdb_flushjobinfo_t*>(&info));
|
||||
}
|
||||
|
||||
void OnFlushCompleted(DB* db, const FlushJobInfo& info) override {
|
||||
rocksdb_t c_db = {db};
|
||||
on_flush_completed(state_, &c_db,
|
||||
reinterpret_cast<const rocksdb_flushjobinfo_t*>(&info));
|
||||
}
|
||||
|
||||
void OnCompactionBegin(DB* db, const CompactionJobInfo& info) override {
|
||||
rocksdb_t c_db = {db};
|
||||
on_compaction_begin(
|
||||
state_, &c_db,
|
||||
reinterpret_cast<const rocksdb_compactionjobinfo_t*>(&info));
|
||||
}
|
||||
|
||||
void OnCompactionCompleted(DB* db, const CompactionJobInfo& info) override {
|
||||
rocksdb_t c_db = {db};
|
||||
on_compaction_completed(
|
||||
state_, &c_db,
|
||||
reinterpret_cast<const rocksdb_compactionjobinfo_t*>(&info));
|
||||
}
|
||||
|
||||
void OnSubcompactionBegin(const SubcompactionJobInfo& info) override {
|
||||
on_subcompaction_begin(
|
||||
state_, reinterpret_cast<const rocksdb_subcompactionjobinfo_t*>(&info));
|
||||
}
|
||||
|
||||
void OnSubcompactionCompleted(const SubcompactionJobInfo& info) override {
|
||||
on_subcompaction_completed(
|
||||
state_, reinterpret_cast<const rocksdb_subcompactionjobinfo_t*>(&info));
|
||||
}
|
||||
|
||||
void OnExternalFileIngested(DB* db,
|
||||
const ExternalFileIngestionInfo& info) override {
|
||||
rocksdb_t c_db = {db};
|
||||
on_external_file_ingested(
|
||||
state_, &c_db,
|
||||
reinterpret_cast<const rocksdb_externalfileingestioninfo_t*>(&info));
|
||||
}
|
||||
|
||||
void OnBackgroundError(BackgroundErrorReason reason,
|
||||
Status* status) override {
|
||||
rocksdb_status_ptr_t* s = new rocksdb_status_ptr_t;
|
||||
s->rep = status;
|
||||
on_background_error(state_, static_cast<uint32_t>(reason), s);
|
||||
delete s;
|
||||
}
|
||||
|
||||
void OnStallConditionsChanged(const WriteStallInfo& info) override {
|
||||
on_stall_conditions_changed(
|
||||
state_, reinterpret_cast<const rocksdb_writestallinfo_t*>(&info));
|
||||
}
|
||||
|
||||
void OnMemTableSealed(const MemTableInfo& info) override {
|
||||
on_memtable_sealed(state_,
|
||||
reinterpret_cast<const rocksdb_memtableinfo_t*>(&info));
|
||||
}
|
||||
|
||||
~rocksdb_eventlistener_t() override { destructor_(state_); }
|
||||
};
|
||||
|
||||
rocksdb_eventlistener_t* rocksdb_eventlistener_create(
|
||||
void* state_, void (*destructor_)(void*), on_flush_begin_cb on_flush_begin,
|
||||
on_flush_completed_cb on_flush_completed,
|
||||
on_compaction_begin_cb on_compaction_begin,
|
||||
on_compaction_completed_cb on_compaction_completed,
|
||||
on_subcompaction_begin_cb on_subcompaction_begin,
|
||||
on_subcompaction_completed_cb on_subcompaction_completed,
|
||||
on_external_file_ingested_cb on_external_file_ingested,
|
||||
on_background_error_cb on_background_error,
|
||||
on_stall_conditions_changed_cb on_stall_conditions_changed,
|
||||
on_memtable_sealed_cb on_memtable_sealed) {
|
||||
rocksdb_eventlistener_t* et = new rocksdb_eventlistener_t;
|
||||
et->state_ = state_;
|
||||
et->destructor_ = destructor_;
|
||||
et->on_flush_begin = on_flush_begin;
|
||||
et->on_flush_completed = on_flush_completed;
|
||||
et->on_compaction_begin = on_compaction_begin;
|
||||
et->on_compaction_completed = on_compaction_completed;
|
||||
et->on_subcompaction_begin = on_subcompaction_begin;
|
||||
et->on_subcompaction_completed = on_subcompaction_completed;
|
||||
et->on_external_file_ingested = on_external_file_ingested;
|
||||
et->on_background_error = on_background_error;
|
||||
et->on_stall_conditions_changed = on_stall_conditions_changed;
|
||||
et->on_memtable_sealed = on_memtable_sealed;
|
||||
return et;
|
||||
}
|
||||
|
||||
void rocksdb_eventlistener_destroy(rocksdb_eventlistener_t* t) { delete t; }
|
||||
|
||||
void rocksdb_options_add_eventlistener(rocksdb_options_t* opt,
|
||||
rocksdb_eventlistener_t* t) {
|
||||
opt->rep.listeners.emplace_back(std::shared_ptr<EventListener>(t));
|
||||
}
|
||||
|
||||
rocksdb_cuckoo_table_options_t* rocksdb_cuckoo_options_create() {
|
||||
return new rocksdb_cuckoo_table_options_t;
|
||||
}
|
||||
@@ -4332,6 +4775,8 @@ uint64_t rocksdb_perfcontext_metric(rocksdb_perfcontext_t* context,
|
||||
return rep->internal_recent_skipped_count;
|
||||
case rocksdb_internal_merge_count:
|
||||
return rep->internal_merge_count;
|
||||
case rocksdb_internal_merge_point_lookup_count:
|
||||
return rep->internal_merge_point_lookup_count;
|
||||
case rocksdb_get_snapshot_time:
|
||||
return rep->get_snapshot_time;
|
||||
case rocksdb_get_from_memtable_time:
|
||||
@@ -5239,6 +5684,67 @@ ROCKSDB_LIBRARY_API void rocksdb_write_buffer_manager_set_allow_stall(
|
||||
wbm->rep->SetAllowStall(new_allow_stall);
|
||||
}
|
||||
|
||||
rocksdb_sst_file_manager_t* rocksdb_sst_file_manager_create(
|
||||
rocksdb_env_t* env) {
|
||||
rocksdb_sst_file_manager_t* sfm = new rocksdb_sst_file_manager_t;
|
||||
sfm->rep.reset(ROCKSDB_NAMESPACE::NewSstFileManager(env->rep));
|
||||
return sfm;
|
||||
}
|
||||
|
||||
void rocksdb_sst_file_manager_destroy(rocksdb_sst_file_manager_t* sfm) {
|
||||
delete sfm;
|
||||
}
|
||||
|
||||
void rocksdb_sst_file_manager_set_max_allowed_space_usage(
|
||||
rocksdb_sst_file_manager_t* sfm, uint64_t max_allowed_space) {
|
||||
sfm->rep->SetMaxAllowedSpaceUsage(max_allowed_space);
|
||||
}
|
||||
|
||||
void rocksdb_sst_file_manager_set_compaction_buffer_size(
|
||||
rocksdb_sst_file_manager_t* sfm, uint64_t compaction_buffer_size) {
|
||||
sfm->rep->SetCompactionBufferSize(compaction_buffer_size);
|
||||
}
|
||||
|
||||
bool rocksdb_sst_file_manager_is_max_allowed_space_reached(
|
||||
rocksdb_sst_file_manager_t* sfm) {
|
||||
return sfm->rep->IsMaxAllowedSpaceReached();
|
||||
}
|
||||
|
||||
bool rocksdb_sst_file_manager_is_max_allowed_space_reached_including_compactions(
|
||||
rocksdb_sst_file_manager_t* sfm) {
|
||||
return sfm->rep->IsMaxAllowedSpaceReachedIncludingCompactions();
|
||||
}
|
||||
|
||||
uint64_t rocksdb_sst_file_manager_get_total_size(
|
||||
rocksdb_sst_file_manager_t* sfm) {
|
||||
return sfm->rep->GetTotalSize();
|
||||
}
|
||||
|
||||
int64_t rocksdb_sst_file_manager_get_delete_rate_bytes_per_second(
|
||||
rocksdb_sst_file_manager_t* sfm) {
|
||||
return sfm->rep->GetDeleteRateBytesPerSecond();
|
||||
}
|
||||
|
||||
void rocksdb_sst_file_manager_set_delete_rate_bytes_per_second(
|
||||
rocksdb_sst_file_manager_t* sfm, int64_t delete_rate) {
|
||||
return sfm->rep->SetDeleteRateBytesPerSecond(delete_rate);
|
||||
}
|
||||
|
||||
double rocksdb_sst_file_manager_get_max_trash_db_ratio(
|
||||
rocksdb_sst_file_manager_t* sfm) {
|
||||
return sfm->rep->GetMaxTrashDBRatio();
|
||||
}
|
||||
|
||||
void rocksdb_sst_file_manager_set_max_trash_db_ratio(
|
||||
rocksdb_sst_file_manager_t* sfm, double ratio) {
|
||||
return sfm->rep->SetMaxTrashDBRatio(ratio);
|
||||
}
|
||||
|
||||
uint64_t rocksdb_sst_file_manager_get_total_trash_size(
|
||||
rocksdb_sst_file_manager_t* sfm) {
|
||||
return sfm->rep->GetTotalTrashSize();
|
||||
}
|
||||
|
||||
rocksdb_dbpath_t* rocksdb_dbpath_create(const char* path,
|
||||
uint64_t target_size) {
|
||||
rocksdb_dbpath_t* result = new rocksdb_dbpath_t;
|
||||
|
||||
+104
@@ -103,6 +103,12 @@ static void CheckValue(char* err, const char* expected, char** actual,
|
||||
Free(actual);
|
||||
}
|
||||
|
||||
static void CheckPinnedValue(char* err, const char* expected,
|
||||
const char** actual, size_t actual_length) {
|
||||
CheckNoError(err);
|
||||
CheckEqual(expected, *actual, actual_length);
|
||||
}
|
||||
|
||||
static void CheckGet(rocksdb_t* db, const rocksdb_readoptions_t* options,
|
||||
const char* key, const char* expected) {
|
||||
char* err = NULL;
|
||||
@@ -1245,6 +1251,8 @@ int main(int argc, char** argv) {
|
||||
CheckCondition(count == 3);
|
||||
size_t size;
|
||||
char* value;
|
||||
const char* pinned_value;
|
||||
rocksdb_pinnableslice_t* p;
|
||||
value = rocksdb_writebatch_wi_get_from_batch(wbi, options, "box", 3, &size,
|
||||
&err);
|
||||
CheckValue(err, "c", &value, size);
|
||||
@@ -1254,9 +1262,19 @@ int main(int argc, char** argv) {
|
||||
value = rocksdb_writebatch_wi_get_from_batch_and_db(wbi, db, roptions,
|
||||
"foo", 3, &size, &err);
|
||||
CheckValue(err, "hello", &value, size);
|
||||
p = rocksdb_writebatch_wi_get_pinned_from_batch_and_db(wbi, db, roptions,
|
||||
"foo", 3, &err);
|
||||
pinned_value = rocksdb_pinnableslice_value(p, &size);
|
||||
CheckPinnedValue(err, "hello", &pinned_value, size);
|
||||
rocksdb_pinnableslice_destroy(p);
|
||||
value = rocksdb_writebatch_wi_get_from_batch_and_db(wbi, db, roptions,
|
||||
"box", 3, &size, &err);
|
||||
CheckValue(err, "c", &value, size);
|
||||
p = rocksdb_writebatch_wi_get_pinned_from_batch_and_db(wbi, db, roptions,
|
||||
"box", 3, &err);
|
||||
pinned_value = rocksdb_pinnableslice_value(p, &size);
|
||||
CheckPinnedValue(err, "c", &pinned_value, size);
|
||||
rocksdb_pinnableslice_destroy(p);
|
||||
rocksdb_write_writebatch_wi(db, woptions, wbi, &err);
|
||||
CheckNoError(err);
|
||||
CheckGet(db, roptions, "foo", "hello");
|
||||
@@ -1362,6 +1380,46 @@ int main(int argc, char** argv) {
|
||||
rocksdb_writebatch_wi_destroy(wbi);
|
||||
}
|
||||
|
||||
StartPhase("wbwi_iter_readoptions");
|
||||
{
|
||||
rocksdb_readoptions_t* iter_roptions = rocksdb_readoptions_create();
|
||||
rocksdb_readoptions_set_iterate_lower_bound(iter_roptions, "boy", 3);
|
||||
rocksdb_readoptions_set_iterate_upper_bound(iter_roptions, "fool", 4);
|
||||
rocksdb_iterator_t* base_iter = rocksdb_create_iterator(db, iter_roptions);
|
||||
rocksdb_writebatch_wi_t* wbi = rocksdb_writebatch_wi_create(0, 1);
|
||||
rocksdb_writebatch_wi_put(wbi, "bar", 3, "b",
|
||||
1); // should get filtered out
|
||||
rocksdb_writebatch_wi_put(wbi, "cat", 3, "miau", 4);
|
||||
rocksdb_writebatch_wi_put(wbi, "gnu", 3, "muh",
|
||||
3); // should get filtered out
|
||||
rocksdb_iterator_t* iter =
|
||||
rocksdb_writebatch_wi_create_iterator_with_base_readopts(wbi, base_iter,
|
||||
iter_roptions);
|
||||
CheckCondition(!rocksdb_iter_valid(iter));
|
||||
rocksdb_iter_seek_to_first(iter);
|
||||
CheckCondition(rocksdb_iter_valid(iter));
|
||||
CheckIter(iter, "cat", "miau");
|
||||
rocksdb_iter_next(iter);
|
||||
CheckIter(iter, "foo", "hello");
|
||||
rocksdb_iter_prev(iter);
|
||||
CheckIter(iter, "cat", "miau");
|
||||
rocksdb_iter_prev(iter);
|
||||
CheckCondition(!rocksdb_iter_valid(iter));
|
||||
rocksdb_iter_seek_to_last(iter);
|
||||
CheckIter(iter, "foo", "hello");
|
||||
rocksdb_iter_seek(iter, "b", 1);
|
||||
CheckIter(iter, "cat", "miau");
|
||||
rocksdb_iter_seek_for_prev(iter, "d", 1);
|
||||
CheckIter(iter, "cat", "miau");
|
||||
rocksdb_iter_seek_for_prev(iter, "fool", 3);
|
||||
CheckIter(iter, "foo", "hello");
|
||||
rocksdb_iter_get_error(iter, &err);
|
||||
CheckNoError(err);
|
||||
rocksdb_iter_destroy(iter);
|
||||
rocksdb_writebatch_wi_destroy(wbi);
|
||||
rocksdb_readoptions_destroy(iter_roptions);
|
||||
}
|
||||
|
||||
StartPhase("multiget");
|
||||
{
|
||||
const char* keys[3] = {"box", "foo", "notfound"};
|
||||
@@ -1792,6 +1850,35 @@ int main(int argc, char** argv) {
|
||||
rocksdb_flush_wal(db, 1, &err);
|
||||
CheckNoError(err);
|
||||
|
||||
// Test WriteBatchWithIndex iteration with Column Family
|
||||
rocksdb_writebatch_wi_t* wbwi = rocksdb_writebatch_wi_create(0, true);
|
||||
rocksdb_writebatch_wi_put_cf(wbwi, handles[1], "boat", 4, "row",
|
||||
3); // should be filtered out
|
||||
rocksdb_writebatch_wi_put_cf(wbwi, handles[1], "buffy", 5, "charmed", 7);
|
||||
rocksdb_writebatch_wi_put_cf(wbwi, handles[1], "bus", 3, "yellow",
|
||||
6); // should be filtered out
|
||||
rocksdb_readoptions_t* iter_roptions = rocksdb_readoptions_create();
|
||||
rocksdb_readoptions_set_iterate_lower_bound(iter_roptions, "bu", 2);
|
||||
rocksdb_readoptions_set_iterate_upper_bound(iter_roptions, "buffz", 5);
|
||||
rocksdb_iterator_t* base_iter =
|
||||
rocksdb_create_iterator_cf(db, iter_roptions, handles[1]);
|
||||
rocksdb_iterator_t* wbwi_iter =
|
||||
rocksdb_writebatch_wi_create_iterator_with_base_cf_readopts(
|
||||
wbwi, base_iter, handles[1], iter_roptions);
|
||||
|
||||
CheckCondition(!rocksdb_iter_valid(wbwi_iter));
|
||||
rocksdb_iter_seek_to_first(wbwi_iter);
|
||||
CheckCondition(rocksdb_iter_valid(wbwi_iter));
|
||||
CheckIter(wbwi_iter, "buff", "rocksdb");
|
||||
rocksdb_iter_next(wbwi_iter);
|
||||
CheckIter(wbwi_iter, "buffy", "charmed");
|
||||
rocksdb_iter_next(wbwi_iter);
|
||||
CheckCondition(!rocksdb_iter_valid(wbwi_iter));
|
||||
|
||||
rocksdb_iter_destroy(wbwi_iter);
|
||||
rocksdb_writebatch_wi_destroy(wbwi);
|
||||
rocksdb_readoptions_destroy(iter_roptions);
|
||||
|
||||
const char* keys[3] = {"box", "box", "barfooxx"};
|
||||
const rocksdb_column_family_handle_t* get_handles[3] = {
|
||||
handles[0], handles[1], handles[1]};
|
||||
@@ -4050,6 +4137,23 @@ int main(int argc, char** argv) {
|
||||
rocksdb_cache_destroy(lru);
|
||||
}
|
||||
|
||||
StartPhase("sst_file_manager");
|
||||
{
|
||||
rocksdb_sst_file_manager_t* sst_file_manager;
|
||||
sst_file_manager = rocksdb_sst_file_manager_create(env);
|
||||
rocksdb_sst_file_manager_set_delete_rate_bytes_per_second(sst_file_manager,
|
||||
1);
|
||||
rocksdb_sst_file_manager_set_max_trash_db_ratio(sst_file_manager, 0.75);
|
||||
|
||||
CheckCondition(1 ==
|
||||
rocksdb_sst_file_manager_get_delete_rate_bytes_per_second(
|
||||
sst_file_manager));
|
||||
CheckCondition(0.75 == rocksdb_sst_file_manager_get_max_trash_db_ratio(
|
||||
sst_file_manager));
|
||||
|
||||
rocksdb_sst_file_manager_destroy(sst_file_manager);
|
||||
}
|
||||
|
||||
StartPhase("cancel_all_background_work");
|
||||
rocksdb_cancel_all_background_work(db, 1);
|
||||
|
||||
|
||||
@@ -283,6 +283,13 @@ class Compaction {
|
||||
// are non-overlapping and can be trivially moved.
|
||||
bool is_trivial_move() const { return is_trivial_move_; }
|
||||
|
||||
bool is_trivial_copy_compaction() const {
|
||||
return immutable_options_.compaction_style == kCompactionStyleFIFO &&
|
||||
compaction_reason_ == CompactionReason::kChangeTemperature &&
|
||||
mutable_cf_options_.compaction_options_fifo
|
||||
.allow_trivial_copy_when_change_temperature;
|
||||
}
|
||||
|
||||
// How many total levels are there?
|
||||
int number_levels() const { return number_levels_; }
|
||||
|
||||
|
||||
@@ -878,7 +878,14 @@ Status CompactionJob::Run() {
|
||||
UpdateCompactionJobOutputStats(internal_stats_);
|
||||
|
||||
// Verify number of output records
|
||||
if (status.ok() && db_options_.compaction_verify_record_count) {
|
||||
// Only verify on table with format collects table properties
|
||||
const auto& mutable_cf_options = compact_->compaction->mutable_cf_options();
|
||||
if (status.ok() &&
|
||||
(mutable_cf_options.table_factory->IsInstanceOf(
|
||||
TableFactory::kBlockBasedTableName()) ||
|
||||
mutable_cf_options.table_factory->IsInstanceOf(
|
||||
TableFactory::kPlainTableName())) &&
|
||||
db_options_.compaction_verify_record_count) {
|
||||
uint64_t total_output_num = 0;
|
||||
for (const auto& state : compact_->sub_compact_states) {
|
||||
for (const auto& output : state.GetOutputs()) {
|
||||
@@ -2293,8 +2300,8 @@ void CompactionJob::LogCompaction() {
|
||||
cfd->GetName().c_str(), scratch);
|
||||
// build event logger report
|
||||
auto stream = event_logger_->Log();
|
||||
stream << "job" << job_id_ << "event" << "compaction_started"
|
||||
<< "compaction_reason"
|
||||
stream << "job" << job_id_ << "event" << "compaction_started" << "cf_name"
|
||||
<< cfd->GetName() << "compaction_reason"
|
||||
<< GetCompactionReasonString(compaction->compaction_reason());
|
||||
for (size_t i = 0; i < compaction->num_input_levels(); ++i) {
|
||||
stream << ("files_L" + std::to_string(compaction->level(i)));
|
||||
|
||||
@@ -427,8 +427,9 @@ struct CompactionServiceInput {
|
||||
// CompactionServiceOutputFile is the metadata for the output SST file
|
||||
struct CompactionServiceOutputFile {
|
||||
std::string file_name;
|
||||
SequenceNumber smallest_seqno;
|
||||
SequenceNumber largest_seqno;
|
||||
uint64_t file_size{};
|
||||
SequenceNumber smallest_seqno{};
|
||||
SequenceNumber largest_seqno{};
|
||||
std::string smallest_internal_key;
|
||||
std::string largest_internal_key;
|
||||
uint64_t oldest_ancester_time = kUnknownOldestAncesterTime;
|
||||
@@ -436,24 +437,26 @@ struct CompactionServiceOutputFile {
|
||||
uint64_t epoch_number = kUnknownEpochNumber;
|
||||
std::string file_checksum = kUnknownFileChecksum;
|
||||
std::string file_checksum_func_name = kUnknownFileChecksumFuncName;
|
||||
uint64_t paranoid_hash;
|
||||
uint64_t paranoid_hash{};
|
||||
bool marked_for_compaction;
|
||||
UniqueId64x2 unique_id{};
|
||||
TableProperties table_properties;
|
||||
bool is_proximal_level_output;
|
||||
Temperature file_temperature;
|
||||
Temperature file_temperature = Temperature::kUnknown;
|
||||
|
||||
CompactionServiceOutputFile() = default;
|
||||
CompactionServiceOutputFile(
|
||||
const std::string& name, SequenceNumber smallest, SequenceNumber largest,
|
||||
std::string _smallest_internal_key, std::string _largest_internal_key,
|
||||
uint64_t _oldest_ancester_time, uint64_t _file_creation_time,
|
||||
uint64_t _epoch_number, const std::string& _file_checksum,
|
||||
const std::string& name, uint64_t size, SequenceNumber smallest,
|
||||
SequenceNumber largest, std::string _smallest_internal_key,
|
||||
std::string _largest_internal_key, uint64_t _oldest_ancester_time,
|
||||
uint64_t _file_creation_time, uint64_t _epoch_number,
|
||||
const std::string& _file_checksum,
|
||||
const std::string& _file_checksum_func_name, uint64_t _paranoid_hash,
|
||||
bool _marked_for_compaction, UniqueId64x2 _unique_id,
|
||||
const TableProperties& _table_properties, bool _is_proximal_level_output,
|
||||
Temperature _file_temperature)
|
||||
: file_name(name),
|
||||
file_size(size),
|
||||
smallest_seqno(smallest),
|
||||
largest_seqno(largest),
|
||||
smallest_internal_key(std::move(_smallest_internal_key)),
|
||||
|
||||
@@ -232,11 +232,6 @@ class CompactionJobTestBase : public testing::Test {
|
||||
// set default for the tests
|
||||
mutable_cf_options_.target_file_size_base = 1024 * 1024;
|
||||
mutable_cf_options_.max_compaction_bytes = 10 * 1024 * 1024;
|
||||
|
||||
// Turn off compaction_verify_record_count MockTables
|
||||
if (table_type == TableTypeForTest::kMockTable) {
|
||||
db_options_.compaction_verify_record_count = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SetUp() override {
|
||||
@@ -1674,6 +1669,7 @@ TEST_F(CompactionJobTest, ResultSerialization) {
|
||||
UniqueId64x2 id{rnd64.Uniform(UINT64_MAX), rnd64.Uniform(UINT64_MAX)};
|
||||
result.output_files.emplace_back(
|
||||
rnd.RandomString(rnd.Uniform(kStrMaxLen)) /* file_name */,
|
||||
rnd64.Uniform(UINT64_MAX) /* file_size */,
|
||||
rnd64.Uniform(UINT64_MAX) /* smallest_seqno */,
|
||||
rnd64.Uniform(UINT64_MAX) /* largest_seqno */,
|
||||
rnd.RandomBinaryString(
|
||||
|
||||
@@ -54,6 +54,7 @@ Status CompactionOutputs::Finish(
|
||||
}
|
||||
current_output().finished = true;
|
||||
stats_.bytes_written += current_bytes;
|
||||
stats_.bytes_written_pre_comp += builder_->PreCompressionSize();
|
||||
stats_.num_output_files = static_cast<int>(outputs_.size());
|
||||
|
||||
return s;
|
||||
|
||||
@@ -1134,10 +1134,15 @@ TEST_F(CompactionPickerTest, FIFOToCold1) {
|
||||
fifo_options_.max_table_files_size = kMaxSize;
|
||||
fifo_options_.file_temperature_age_thresholds = {
|
||||
{Temperature::kCold, kColdThreshold}};
|
||||
fifo_options_.allow_trivial_copy_when_change_temperature = true;
|
||||
fifo_options_.trivial_copy_buffer_size = 16 * 1024 * 1024;
|
||||
mutable_cf_options_.compaction_options_fifo = fifo_options_;
|
||||
mutable_cf_options_.level0_file_num_compaction_trigger = 100;
|
||||
mutable_cf_options_.max_compaction_bytes = kFileSize * 100;
|
||||
FIFOCompactionPicker fifo_compaction_picker(ioptions_, &icmp_);
|
||||
|
||||
auto copiedIOptions = ioptions_;
|
||||
copiedIOptions.compaction_style = kCompactionStyleFIFO;
|
||||
FIFOCompactionPicker fifo_compaction_picker(copiedIOptions, &icmp_);
|
||||
|
||||
int64_t current_time = 0;
|
||||
ASSERT_OK(Env::Default()->GetCurrentTime(¤t_time));
|
||||
@@ -1186,7 +1191,10 @@ TEST_F(CompactionPickerTest, FIFOToColdMaxCompactionSize) {
|
||||
mutable_cf_options_.compaction_options_fifo = fifo_options_;
|
||||
mutable_cf_options_.level0_file_num_compaction_trigger = 100;
|
||||
mutable_cf_options_.max_compaction_bytes = kFileSize * 9;
|
||||
FIFOCompactionPicker fifo_compaction_picker(ioptions_, &icmp_);
|
||||
|
||||
auto copiedIOptions = ioptions_;
|
||||
copiedIOptions.compaction_style = kCompactionStyleFIFO;
|
||||
FIFOCompactionPicker fifo_compaction_picker(copiedIOptions, &icmp_);
|
||||
|
||||
int64_t current_time = 0;
|
||||
ASSERT_OK(Env::Default()->GetCurrentTime(¤t_time));
|
||||
@@ -1253,7 +1261,10 @@ TEST_F(CompactionPickerTest, FIFOToColdWithExistingCold) {
|
||||
mutable_cf_options_.compaction_options_fifo = fifo_options_;
|
||||
mutable_cf_options_.level0_file_num_compaction_trigger = 100;
|
||||
mutable_cf_options_.max_compaction_bytes = kFileSize * 100;
|
||||
FIFOCompactionPicker fifo_compaction_picker(ioptions_, &icmp_);
|
||||
|
||||
auto copiedIOptions = ioptions_;
|
||||
copiedIOptions.compaction_style = kCompactionStyleFIFO;
|
||||
FIFOCompactionPicker fifo_compaction_picker(copiedIOptions, &icmp_);
|
||||
|
||||
int64_t current_time = 0;
|
||||
ASSERT_OK(Env::Default()->GetCurrentTime(¤t_time));
|
||||
@@ -1318,7 +1329,10 @@ TEST_F(CompactionPickerTest, FIFOToColdWithHotBetweenCold) {
|
||||
mutable_cf_options_.compaction_options_fifo = fifo_options_;
|
||||
mutable_cf_options_.level0_file_num_compaction_trigger = 100;
|
||||
mutable_cf_options_.max_compaction_bytes = kFileSize * 100;
|
||||
FIFOCompactionPicker fifo_compaction_picker(ioptions_, &icmp_);
|
||||
|
||||
auto copiedIOptions = ioptions_;
|
||||
copiedIOptions.compaction_style = kCompactionStyleFIFO;
|
||||
FIFOCompactionPicker fifo_compaction_picker(copiedIOptions, &icmp_);
|
||||
|
||||
int64_t current_time = 0;
|
||||
ASSERT_OK(Env::Default()->GetCurrentTime(¤t_time));
|
||||
@@ -1385,7 +1399,10 @@ TEST_F(CompactionPickerTest, FIFOToHotAndWarm) {
|
||||
mutable_cf_options_.compaction_options_fifo = fifo_options_;
|
||||
mutable_cf_options_.level0_file_num_compaction_trigger = 100;
|
||||
mutable_cf_options_.max_compaction_bytes = kFileSize * 100;
|
||||
FIFOCompactionPicker fifo_compaction_picker(ioptions_, &icmp_);
|
||||
|
||||
auto copiedIOptions = ioptions_;
|
||||
copiedIOptions.compaction_style = kCompactionStyleFIFO;
|
||||
FIFOCompactionPicker fifo_compaction_picker(copiedIOptions, &icmp_);
|
||||
|
||||
int64_t current_time = 0;
|
||||
ASSERT_OK(Env::Default()->GetCurrentTime(¤t_time));
|
||||
|
||||
@@ -74,7 +74,9 @@ CompactionJob::ProcessKeyValueCompactionWithCompactionService(
|
||||
compaction->column_family_data()->GetName().c_str(), job_id_,
|
||||
compaction_input.output_level, input_files_oss.str().c_str());
|
||||
CompactionServiceJobInfo info(
|
||||
dbname_, db_id_, db_session_id_, GetCompactionId(sub_compact),
|
||||
dbname_, db_id_, db_session_id_,
|
||||
compaction->column_family_data()->GetID(),
|
||||
compaction->column_family_data()->GetName(), GetCompactionId(sub_compact),
|
||||
thread_pri_, compaction->compaction_reason(),
|
||||
compaction->is_full_compaction(), compaction->is_manual_compaction(),
|
||||
compaction->bottommost_level(), compaction->start_level(),
|
||||
@@ -113,7 +115,7 @@ CompactionJob::ProcessKeyValueCompactionWithCompactionService(
|
||||
}
|
||||
|
||||
std::string debug_str_before_wait =
|
||||
compaction->input_version()->DebugString();
|
||||
compaction->input_version()->DebugString(/*hex=*/true);
|
||||
|
||||
ROCKS_LOG_INFO(db_options_.info_log,
|
||||
"[%s] [JOB %d] Waiting for remote compaction...",
|
||||
@@ -124,13 +126,14 @@ CompactionJob::ProcessKeyValueCompactionWithCompactionService(
|
||||
&compaction_result_binary);
|
||||
|
||||
if (compaction_status != CompactionServiceJobStatus::kSuccess) {
|
||||
ROCKS_LOG_ERROR(db_options_.info_log,
|
||||
"[%s] [JOB %d] Wait() status is not kSuccess. "
|
||||
"\nDebugString Before Wait():\n%s"
|
||||
"\nDebugString After Wait():\n%s",
|
||||
compaction->column_family_data()->GetName().c_str(),
|
||||
job_id_, debug_str_before_wait.c_str(),
|
||||
compaction->input_version()->DebugString().c_str());
|
||||
ROCKS_LOG_ERROR(
|
||||
db_options_.info_log,
|
||||
"[%s] [JOB %d] Wait() status is not kSuccess. "
|
||||
"\nDebugString Before Wait():\n%s"
|
||||
"\nDebugString After Wait():\n%s",
|
||||
compaction->column_family_data()->GetName().c_str(), job_id_,
|
||||
debug_str_before_wait.c_str(),
|
||||
compaction->input_version()->DebugString(/*hex=*/true).c_str());
|
||||
}
|
||||
|
||||
if (compaction_status == CompactionServiceJobStatus::kUseLocal) {
|
||||
@@ -218,18 +221,24 @@ CompactionJob::ProcessKeyValueCompactionWithCompactionService(
|
||||
}
|
||||
|
||||
FileMetaData meta;
|
||||
uint64_t file_size;
|
||||
// FIXME: file_size should be part of CompactionServiceOutputFile so that
|
||||
// we don't get DB corruption if the full file size has not been propagated
|
||||
// back to the caller through the file system (which could have metadata
|
||||
// lag or caching bugs).
|
||||
s = fs_->GetFileSize(tgt_file, IOOptions(), &file_size, nullptr);
|
||||
uint64_t file_size = file.file_size;
|
||||
|
||||
// TODO - Clean this up in the next release.
|
||||
// For backward compatibility - in case the remote worker does not populate
|
||||
// the file_size yet. If missing, continue to populate this from the file
|
||||
// system.
|
||||
if (file_size == 0) {
|
||||
s = fs_->GetFileSize(tgt_file, IOOptions(), &file_size, nullptr);
|
||||
}
|
||||
|
||||
if (!s.ok()) {
|
||||
sub_compact->status = s;
|
||||
db_options_.compaction_service->OnInstallation(
|
||||
response.scheduled_job_id, CompactionServiceJobStatus::kFailure);
|
||||
return CompactionServiceJobStatus::kFailure;
|
||||
}
|
||||
assert(file_size > 0);
|
||||
|
||||
meta.fd = FileDescriptor(file_num, compaction->output_path_id(), file_size,
|
||||
file.smallest_seqno, file.largest_seqno);
|
||||
meta.smallest.DecodeFrom(file.smallest_internal_key);
|
||||
@@ -418,14 +427,14 @@ Status CompactionServiceCompactionJob::Run() {
|
||||
for (const auto& output_file : sub_compact->GetOutputs()) {
|
||||
auto& meta = output_file.meta;
|
||||
compaction_result_->output_files.emplace_back(
|
||||
MakeTableFileName(meta.fd.GetNumber()), meta.fd.smallest_seqno,
|
||||
meta.fd.largest_seqno, meta.smallest.Encode().ToString(),
|
||||
meta.largest.Encode().ToString(), meta.oldest_ancester_time,
|
||||
meta.file_creation_time, meta.epoch_number, meta.file_checksum,
|
||||
meta.file_checksum_func_name, output_file.validator.GetHash(),
|
||||
meta.marked_for_compaction, meta.unique_id,
|
||||
*output_file.table_properties, output_file.is_proximal_level,
|
||||
meta.temperature);
|
||||
MakeTableFileName(meta.fd.GetNumber()), meta.fd.GetFileSize(),
|
||||
meta.fd.smallest_seqno, meta.fd.largest_seqno,
|
||||
meta.smallest.Encode().ToString(), meta.largest.Encode().ToString(),
|
||||
meta.oldest_ancester_time, meta.file_creation_time, meta.epoch_number,
|
||||
meta.file_checksum, meta.file_checksum_func_name,
|
||||
output_file.validator.GetHash(), meta.marked_for_compaction,
|
||||
meta.unique_id, *output_file.table_properties,
|
||||
output_file.is_proximal_level, meta.temperature);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -525,6 +534,10 @@ static std::unordered_map<std::string, OptionTypeInfo>
|
||||
{offsetof(struct CompactionServiceOutputFile, file_name),
|
||||
OptionType::kEncodedString, OptionVerificationType::kNormal,
|
||||
OptionTypeFlags::kNone}},
|
||||
{"file_size",
|
||||
{offsetof(struct CompactionServiceOutputFile, file_size),
|
||||
OptionType::kUInt64T, OptionVerificationType::kNormal,
|
||||
OptionTypeFlags::kNone}},
|
||||
{"smallest_seqno",
|
||||
{offsetof(struct CompactionServiceOutputFile, smallest_seqno),
|
||||
OptionType::kUInt64T, OptionVerificationType::kNormal,
|
||||
|
||||
@@ -21,10 +21,10 @@ class MyTestCompactionService : public CompactionService {
|
||||
: db_path_(std::move(db_path)),
|
||||
options_(options),
|
||||
statistics_(statistics),
|
||||
start_info_("na", "na", "na", 0, Env::TOTAL, CompactionReason::kUnknown,
|
||||
false, false, false, -1, -1),
|
||||
wait_info_("na", "na", "na", 0, Env::TOTAL, CompactionReason::kUnknown,
|
||||
false, false, false, -1, -1),
|
||||
start_info_("na", "na", "na", 0, "na", 0, Env::TOTAL,
|
||||
CompactionReason::kUnknown, false, false, false, -1, -1),
|
||||
wait_info_("na", "na", "na", 0, "na", 0, Env::TOTAL,
|
||||
CompactionReason::kUnknown, false, false, false, -1, -1),
|
||||
listeners_(listeners),
|
||||
table_properties_collector_factories_(
|
||||
std::move(table_properties_collector_factories)) {}
|
||||
@@ -434,6 +434,30 @@ TEST_F(CompactionServiceTest, ManualCompaction) {
|
||||
ASSERT_OK(result.status);
|
||||
ASSERT_TRUE(result.stats.is_manual_compaction);
|
||||
ASSERT_TRUE(result.stats.is_remote_compaction);
|
||||
|
||||
auto info = my_cs->GetCompactionInfoForStart();
|
||||
ASSERT_EQ(0, info.cf_id);
|
||||
ASSERT_EQ(kDefaultColumnFamilyName, info.cf_name);
|
||||
|
||||
info = my_cs->GetCompactionInfoForWait();
|
||||
ASSERT_EQ(0, info.cf_id);
|
||||
ASSERT_EQ(kDefaultColumnFamilyName, info.cf_name);
|
||||
|
||||
// Test non-default CF
|
||||
ASSERT_OK(
|
||||
db_->CompactRange(CompactRangeOptions(), handles_[1], nullptr, nullptr));
|
||||
my_cs->GetResult(&result);
|
||||
ASSERT_OK(result.status);
|
||||
ASSERT_TRUE(result.stats.is_manual_compaction);
|
||||
ASSERT_TRUE(result.stats.is_remote_compaction);
|
||||
|
||||
info = my_cs->GetCompactionInfoForStart();
|
||||
ASSERT_EQ(handles_[1]->GetID(), info.cf_id);
|
||||
ASSERT_EQ(handles_[1]->GetName(), info.cf_name);
|
||||
|
||||
info = my_cs->GetCompactionInfoForWait();
|
||||
ASSERT_EQ(handles_[1]->GetID(), info.cf_id);
|
||||
ASSERT_EQ(handles_[1]->GetName(), info.cf_name);
|
||||
}
|
||||
|
||||
TEST_F(CompactionServiceTest, CompactionOutputFileIOError) {
|
||||
@@ -1371,6 +1395,7 @@ TEST_F(CompactionServiceTest, CompactionInfo) {
|
||||
ASSERT_EQ(true, info.bottommost_level);
|
||||
ASSERT_EQ(1, info.base_input_level);
|
||||
ASSERT_EQ(2, info.output_level);
|
||||
ASSERT_EQ(kDefaultColumnFamilyName, info.cf_name);
|
||||
|
||||
// Test priority BOTTOM
|
||||
env_->SetBackgroundThreads(1, Env::BOTTOM);
|
||||
|
||||
@@ -225,6 +225,8 @@ TEST_F(TieredCompactionTest, SequenceBasedTieredStorageUniversal) {
|
||||
flush_stats.micros = 1;
|
||||
flush_stats.bytes_written = bytes_per_file;
|
||||
flush_stats.num_output_files = 1;
|
||||
flush_stats.num_input_records = kNumKeys;
|
||||
flush_stats.num_output_records = kNumKeys;
|
||||
expect_stats[0].Add(flush_stats);
|
||||
}
|
||||
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||
@@ -1080,6 +1082,8 @@ TEST_F(TieredCompactionTest, SequenceBasedTieredStorageLevel) {
|
||||
flush_stats.micros = 1;
|
||||
flush_stats.bytes_written = bytes_per_file;
|
||||
flush_stats.num_output_files = 1;
|
||||
flush_stats.num_input_records = kNumKeys;
|
||||
flush_stats.num_output_records = kNumKeys;
|
||||
expect_stats[0].Add(flush_stats);
|
||||
}
|
||||
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||
|
||||
@@ -851,9 +851,6 @@ TEST_F(CorruptionTest, ParanoidFileChecksOnCompact) {
|
||||
options.env = env_.get();
|
||||
options.paranoid_file_checks = true;
|
||||
options.create_if_missing = true;
|
||||
// Skip verifying record count against TableProperties for
|
||||
// MockTables
|
||||
options.compaction_verify_record_count = false;
|
||||
Status s;
|
||||
for (const auto& mode : corruption_modes) {
|
||||
delete db_;
|
||||
|
||||
@@ -5086,6 +5086,7 @@ TEST_F(DBBasicTest, DisallowMemtableWrite) {
|
||||
options_allow.create_if_missing = true;
|
||||
Options options_disallow = options_allow;
|
||||
options_disallow.disallow_memtable_writes = true;
|
||||
options_disallow.paranoid_memory_checks = true;
|
||||
|
||||
DestroyAndReopen(options_allow);
|
||||
// CFs allowing and disallowing memtable write
|
||||
@@ -5125,6 +5126,11 @@ TEST_F(DBBasicTest, DisallowMemtableWrite) {
|
||||
EXPECT_EQ(Get(2, "b2"), "2");
|
||||
EXPECT_EQ(Get(3, "b3"), "NOT_FOUND");
|
||||
|
||||
std::unique_ptr<Iterator> iter(
|
||||
dbfull()->NewIterator(ReadOptions(), handles_[3]));
|
||||
iter->Seek("a3");
|
||||
ASSERT_OK(iter->status());
|
||||
iter.reset();
|
||||
// When the DB is re-opened with WAL entries for a CF that is newly setting
|
||||
// disallow_memtable_writes, we detect that and fail the open gracefully.
|
||||
ASSERT_EQ(TryReopenWithColumnFamilies(
|
||||
|
||||
@@ -506,6 +506,8 @@ TEST_P(DBBlockCacheTest1, WarmCacheWithBlocksDuringFlush) {
|
||||
table_options.prepopulate_block_cache =
|
||||
BlockBasedTableOptions::PrepopulateBlockCache::kFlushOnly;
|
||||
options.table_factory.reset(NewBlockBasedTableFactory(table_options));
|
||||
// Include a compression dictionary block
|
||||
options.compression_opts.max_dict_bytes = 123;
|
||||
DestroyAndReopen(options);
|
||||
|
||||
std::string value(kValueSize, 'a');
|
||||
@@ -537,6 +539,9 @@ TEST_P(DBBlockCacheTest1, WarmCacheWithBlocksDuringFlush) {
|
||||
options.statistics->getTickerCount(BLOCK_CACHE_FILTER_HIT));
|
||||
}
|
||||
ASSERT_EQ(0, options.statistics->getTickerCount(BLOCK_CACHE_FILTER_MISS));
|
||||
|
||||
// Including compression dict
|
||||
ASSERT_EQ(0, options.statistics->getTickerCount(BLOCK_CACHE_MISS));
|
||||
}
|
||||
|
||||
// Verify compaction not counted
|
||||
|
||||
+126
-96
@@ -9434,104 +9434,134 @@ TEST_F(DBCompactionTest, CompactionWithChecksumHandoffManifest2) {
|
||||
}
|
||||
|
||||
TEST_F(DBCompactionTest, FIFOChangeTemperature) {
|
||||
for (bool write_time_default : {false, true}) {
|
||||
SCOPED_TRACE("write time default? " + std::to_string(write_time_default));
|
||||
for (bool should_allow_trivial_copy : {false, true}) {
|
||||
for (bool write_time_default : {false, true}) {
|
||||
int32_t before_compaction_calls = 0;
|
||||
int32_t after_compaction_calls = 0;
|
||||
if (should_allow_trivial_copy) {
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"DBImpl::BackgroundCompaction:TriviaCopyBeforeCompaction",
|
||||
[&](void*) { ++before_compaction_calls; });
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"DBImpl::BackgroundCompaction:TriviaCopyAfterCompaction",
|
||||
[&](void*) { ++after_compaction_calls; });
|
||||
} else {
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"DBImpl::BackgroundCompaction:BeforeCompaction",
|
||||
[&](void*) { ++before_compaction_calls; });
|
||||
|
||||
Options options = CurrentOptions();
|
||||
options.compaction_style = kCompactionStyleFIFO;
|
||||
options.num_levels = 1;
|
||||
options.max_open_files = -1;
|
||||
options.level0_file_num_compaction_trigger = 2;
|
||||
options.create_if_missing = true;
|
||||
CompactionOptionsFIFO fifo_options;
|
||||
fifo_options.file_temperature_age_thresholds = {{Temperature::kCold, 1000}};
|
||||
fifo_options.max_table_files_size = 100000000;
|
||||
options.compaction_options_fifo = fifo_options;
|
||||
env_->SetMockSleep();
|
||||
if (write_time_default) {
|
||||
options.default_write_temperature = Temperature::kWarm;
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"DBImpl::BackgroundCompaction:AfterCompaction",
|
||||
[&](void*) { ++after_compaction_calls; });
|
||||
}
|
||||
|
||||
SCOPED_TRACE("write time default? " + std::to_string(write_time_default));
|
||||
|
||||
Options options = CurrentOptions();
|
||||
options.compaction_style = kCompactionStyleFIFO;
|
||||
options.num_levels = 1;
|
||||
options.max_open_files = -1;
|
||||
options.level0_file_num_compaction_trigger = 2;
|
||||
options.create_if_missing = true;
|
||||
CompactionOptionsFIFO fifo_options;
|
||||
fifo_options.file_temperature_age_thresholds = {
|
||||
{Temperature::kCold, 1000}};
|
||||
fifo_options.max_table_files_size = 100000000;
|
||||
fifo_options.allow_trivial_copy_when_change_temperature =
|
||||
should_allow_trivial_copy;
|
||||
fifo_options.trivial_copy_buffer_size = 4096;
|
||||
options.compaction_options_fifo = fifo_options;
|
||||
env_->SetMockSleep();
|
||||
if (write_time_default) {
|
||||
options.default_write_temperature = Temperature::kWarm;
|
||||
}
|
||||
// Should be ignored (TODO: fail?)
|
||||
options.last_level_temperature = Temperature::kHot;
|
||||
Reopen(options);
|
||||
|
||||
int total_cold = 0;
|
||||
int total_warm = 0;
|
||||
int total_hot = 0;
|
||||
int total_unknown = 0;
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"NewWritableFile::FileOptions.temperature", [&](void* arg) {
|
||||
Temperature temperature = *(static_cast<Temperature*>(arg));
|
||||
if (temperature == Temperature::kCold) {
|
||||
total_cold++;
|
||||
} else if (temperature == Temperature::kWarm) {
|
||||
total_warm++;
|
||||
} else if (temperature == Temperature::kHot) {
|
||||
total_hot++;
|
||||
} else {
|
||||
assert(temperature == Temperature::kUnknown);
|
||||
total_unknown++;
|
||||
}
|
||||
});
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
// The file system does not support checksum handoff. The check
|
||||
// will be ignored.
|
||||
ASSERT_OK(Put(Key(0), "value1"));
|
||||
env_->MockSleepForSeconds(800);
|
||||
ASSERT_OK(Put(Key(2), "value2"));
|
||||
ASSERT_OK(Flush());
|
||||
|
||||
ASSERT_OK(Put(Key(0), "value1"));
|
||||
ASSERT_OK(Put(Key(2), "value2"));
|
||||
ASSERT_OK(Flush());
|
||||
|
||||
// First two L0 files both become eligible for temperature change
|
||||
// compaction They should be compacted one-by-one.
|
||||
ASSERT_OK(Put(Key(0), "value1"));
|
||||
env_->MockSleepForSeconds(1200);
|
||||
ASSERT_OK(Put(Key(2), "value2"));
|
||||
ASSERT_OK(Flush());
|
||||
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||
|
||||
if (write_time_default) {
|
||||
// Also test dynamic option change
|
||||
ASSERT_OK(db_->SetOptions({{"default_write_temperature", "kHot"}}));
|
||||
}
|
||||
|
||||
ASSERT_OK(Put(Key(0), "value1"));
|
||||
env_->MockSleepForSeconds(800);
|
||||
ASSERT_OK(Put(Key(2), "value2"));
|
||||
ASSERT_OK(Flush());
|
||||
|
||||
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
|
||||
|
||||
ColumnFamilyMetaData metadata;
|
||||
db_->GetColumnFamilyMetaData(&metadata);
|
||||
ASSERT_EQ(4, metadata.file_count);
|
||||
if (write_time_default) {
|
||||
ASSERT_EQ(Temperature::kHot, metadata.levels[0].files[0].temperature);
|
||||
ASSERT_EQ(Temperature::kWarm, metadata.levels[0].files[1].temperature);
|
||||
// Includes obsolete/deleted files moved to cold
|
||||
ASSERT_EQ(total_warm, 3);
|
||||
ASSERT_EQ(total_hot, 1);
|
||||
// Includes non-SST DB files
|
||||
ASSERT_GT(total_unknown, 0);
|
||||
} else {
|
||||
ASSERT_EQ(Temperature::kUnknown,
|
||||
metadata.levels[0].files[0].temperature);
|
||||
ASSERT_EQ(Temperature::kUnknown,
|
||||
metadata.levels[0].files[1].temperature);
|
||||
ASSERT_EQ(total_warm, 0);
|
||||
ASSERT_EQ(total_hot, 0);
|
||||
// Includes non-SST DB files
|
||||
ASSERT_GT(total_unknown, 4);
|
||||
}
|
||||
ASSERT_EQ(Temperature::kCold, metadata.levels[0].files[2].temperature);
|
||||
ASSERT_EQ(Temperature::kCold, metadata.levels[0].files[3].temperature);
|
||||
ASSERT_EQ(2, total_cold);
|
||||
|
||||
ASSERT_EQ(2, before_compaction_calls);
|
||||
ASSERT_EQ(2, after_compaction_calls);
|
||||
|
||||
Destroy(options);
|
||||
}
|
||||
// Should be ignored (TODO: fail?)
|
||||
options.last_level_temperature = Temperature::kHot;
|
||||
Reopen(options);
|
||||
|
||||
int total_cold = 0;
|
||||
int total_warm = 0;
|
||||
int total_hot = 0;
|
||||
int total_unknown = 0;
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"NewWritableFile::FileOptions.temperature", [&](void* arg) {
|
||||
Temperature temperature = *(static_cast<Temperature*>(arg));
|
||||
if (temperature == Temperature::kCold) {
|
||||
total_cold++;
|
||||
} else if (temperature == Temperature::kWarm) {
|
||||
total_warm++;
|
||||
} else if (temperature == Temperature::kHot) {
|
||||
total_hot++;
|
||||
} else {
|
||||
assert(temperature == Temperature::kUnknown);
|
||||
total_unknown++;
|
||||
}
|
||||
});
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
// The file system does not support checksum handoff. The check
|
||||
// will be ignored.
|
||||
ASSERT_OK(Put(Key(0), "value1"));
|
||||
env_->MockSleepForSeconds(800);
|
||||
ASSERT_OK(Put(Key(2), "value2"));
|
||||
ASSERT_OK(Flush());
|
||||
|
||||
ASSERT_OK(Put(Key(0), "value1"));
|
||||
ASSERT_OK(Put(Key(2), "value2"));
|
||||
ASSERT_OK(Flush());
|
||||
|
||||
// First two L0 files both become eligible for temperature change compaction
|
||||
// They should be compacted one-by-one.
|
||||
ASSERT_OK(Put(Key(0), "value1"));
|
||||
env_->MockSleepForSeconds(1200);
|
||||
ASSERT_OK(Put(Key(2), "value2"));
|
||||
ASSERT_OK(Flush());
|
||||
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||
|
||||
if (write_time_default) {
|
||||
// Also test dynamic option change
|
||||
ASSERT_OK(db_->SetOptions({{"default_write_temperature", "kHot"}}));
|
||||
}
|
||||
|
||||
ASSERT_OK(Put(Key(0), "value1"));
|
||||
env_->MockSleepForSeconds(800);
|
||||
ASSERT_OK(Put(Key(2), "value2"));
|
||||
ASSERT_OK(Flush());
|
||||
|
||||
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
|
||||
|
||||
ColumnFamilyMetaData metadata;
|
||||
db_->GetColumnFamilyMetaData(&metadata);
|
||||
ASSERT_EQ(4, metadata.file_count);
|
||||
if (write_time_default) {
|
||||
ASSERT_EQ(Temperature::kHot, metadata.levels[0].files[0].temperature);
|
||||
ASSERT_EQ(Temperature::kWarm, metadata.levels[0].files[1].temperature);
|
||||
// Includes obsolete/deleted files moved to cold
|
||||
ASSERT_EQ(total_warm, 3);
|
||||
ASSERT_EQ(total_hot, 1);
|
||||
// Includes non-SST DB files
|
||||
ASSERT_GT(total_unknown, 0);
|
||||
} else {
|
||||
ASSERT_EQ(Temperature::kUnknown, metadata.levels[0].files[0].temperature);
|
||||
ASSERT_EQ(Temperature::kUnknown, metadata.levels[0].files[1].temperature);
|
||||
ASSERT_EQ(total_warm, 0);
|
||||
ASSERT_EQ(total_hot, 0);
|
||||
// Includes non-SST DB files
|
||||
ASSERT_GT(total_unknown, 4);
|
||||
}
|
||||
ASSERT_EQ(Temperature::kCold, metadata.levels[0].files[2].temperature);
|
||||
ASSERT_EQ(Temperature::kCold, metadata.levels[0].files[3].temperature);
|
||||
ASSERT_EQ(2, total_cold);
|
||||
|
||||
Destroy(options);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3504,6 +3504,63 @@ TEST_F(DBFlushTest, DBStuckAfterAtomicFlushError) {
|
||||
ASSERT_OK(dbfull()->TEST_WaitForBackgroundWork());
|
||||
ASSERT_EQ(1, NumTableFilesAtLevel(0));
|
||||
}
|
||||
|
||||
TEST_F(DBFlushTest, VerifyOutputRecordCount) {
|
||||
for (bool use_plain_table : {false, true}) {
|
||||
Options options = CurrentOptions();
|
||||
options.flush_verify_memtable_count = true;
|
||||
options.merge_operator = MergeOperators::CreateStringAppendOperator();
|
||||
DestroyAndReopen(options);
|
||||
// Verify flush output record count verification in different table
|
||||
// formats
|
||||
if (use_plain_table) {
|
||||
options.table_factory.reset(NewPlainTableFactory());
|
||||
}
|
||||
|
||||
// Verify that flush output record count verification does not produce false
|
||||
// positives.
|
||||
ASSERT_OK(Merge("k0", "v1"));
|
||||
ASSERT_OK(Put("k1", "v1"));
|
||||
ASSERT_OK(Put("k2", "v1"));
|
||||
ASSERT_OK(SingleDelete("k2"));
|
||||
ASSERT_OK(Delete("k2"));
|
||||
ASSERT_OK(Delete("k3"));
|
||||
ASSERT_OK(db_->DeleteRange(WriteOptions(), "k1", "k3"));
|
||||
ASSERT_OK(Flush());
|
||||
|
||||
// Verify that flush output record count verification catch corruption
|
||||
DestroyAndReopen(options);
|
||||
if (use_plain_table) {
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"PlainTableBuilder::Add::skip",
|
||||
[&](void* skip) { *(bool*)skip = true; });
|
||||
|
||||
} else {
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"BlockBasedTableBuilder::Add::skip",
|
||||
[&](void* skip) { *(bool*)skip = true; });
|
||||
}
|
||||
SyncPoint::GetInstance()->EnableProcessing();
|
||||
const char* expect =
|
||||
"Number of keys in flush output SST files does not match";
|
||||
|
||||
// 1. During DB open flush
|
||||
ASSERT_OK(Put("k1", "v1"));
|
||||
ASSERT_OK(Put("k2", "v1"));
|
||||
Status s = TryReopen(options);
|
||||
ASSERT_TRUE(s.IsCorruption());
|
||||
ASSERT_TRUE(std::strstr(s.getState(), expect));
|
||||
|
||||
// 2. During regular flush
|
||||
DestroyAndReopen(options);
|
||||
ASSERT_OK(Put("k1", "v1"));
|
||||
ASSERT_OK(Put("k2", "v1"));
|
||||
s = Flush();
|
||||
ASSERT_TRUE(s.IsCorruption());
|
||||
ASSERT_TRUE(std::strstr(s.getState(), expect));
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
|
||||
}
|
||||
}
|
||||
} // namespace ROCKSDB_NAMESPACE
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
+11
-9
@@ -3886,12 +3886,14 @@ Iterator* DBImpl::NewIterator(const ReadOptions& _read_options,
|
||||
|
||||
auto iter = new ForwardIterator(this, read_options, cfd, sv,
|
||||
/* allow_unprepared_value */ true);
|
||||
// TODO(cbi): Add support for `memtable_op_scan_flush_trigger` for tailing
|
||||
// iterator. This requires refreshing DBIter's pointer to active_mem when
|
||||
// tailing iterator refreshes to new memtable internally.
|
||||
result = DBIter::NewIter(env_, read_options, cfd->ioptions(),
|
||||
sv->mutable_cf_options, cfd->user_comparator(),
|
||||
iter, sv->current, kMaxSequenceNumber,
|
||||
/*read_callback=*/nullptr, cfh,
|
||||
/*expose_blob_index=*/false,
|
||||
/*active_mem=*/sv->mem);
|
||||
/*read_callback=*/nullptr, /*active_mem=*/nullptr,
|
||||
cfh, /*expose_blob_index=*/false);
|
||||
} else {
|
||||
// Note: no need to consider the special case of
|
||||
// last_seq_same_as_publish_seq_==false since NewIterator is overridden in
|
||||
@@ -4095,12 +4097,12 @@ Status DBImpl::NewIterators(
|
||||
auto iter = new ForwardIterator(this, read_options, cf_sv_pair.cfd,
|
||||
cf_sv_pair.super_version,
|
||||
/* allow_unprepared_value */ true);
|
||||
iterators->push_back(
|
||||
DBIter::NewIter(env_, read_options, cf_sv_pair.cfd->ioptions(),
|
||||
cf_sv_pair.super_version->mutable_cf_options,
|
||||
cf_sv_pair.cfd->user_comparator(), iter,
|
||||
cf_sv_pair.super_version->current, kMaxSequenceNumber,
|
||||
nullptr /*read_callback*/, cf_sv_pair.cfh));
|
||||
iterators->push_back(DBIter::NewIter(
|
||||
env_, read_options, cf_sv_pair.cfd->ioptions(),
|
||||
cf_sv_pair.super_version->mutable_cf_options,
|
||||
cf_sv_pair.cfd->user_comparator(), iter,
|
||||
cf_sv_pair.super_version->current, kMaxSequenceNumber,
|
||||
nullptr /*read_callback*/, /*active_mem=*/nullptr, cf_sv_pair.cfh));
|
||||
}
|
||||
} else {
|
||||
for (const auto& cf_sv_pair : cf_sv_pairs) {
|
||||
|
||||
@@ -2577,7 +2577,7 @@ class DBImpl : public DB {
|
||||
bool ShouldntRunManualCompaction(ManualCompactionState* m);
|
||||
bool HaveManualCompaction(ColumnFamilyData* cfd);
|
||||
bool MCOverlap(ManualCompactionState* m, ManualCompactionState* m1);
|
||||
void UpdateDeletionCompactionStats(const std::unique_ptr<Compaction>& c);
|
||||
void UpdateFIFOCompactionStatus(const std::unique_ptr<Compaction>& c);
|
||||
|
||||
// May open and read table files for table property.
|
||||
// Should not be called while holding mutex_.
|
||||
|
||||
@@ -13,12 +13,14 @@
|
||||
#include "db/db_impl/db_impl.h"
|
||||
#include "db/error_handler.h"
|
||||
#include "db/event_helpers.h"
|
||||
#include "file/file_util.h"
|
||||
#include "file/sst_file_manager_impl.h"
|
||||
#include "logging/logging.h"
|
||||
#include "monitoring/iostats_context_imp.h"
|
||||
#include "monitoring/perf_context_imp.h"
|
||||
#include "monitoring/thread_status_updater.h"
|
||||
#include "monitoring/thread_status_util.h"
|
||||
#include "options/options_helper.h"
|
||||
#include "rocksdb/file_system.h"
|
||||
#include "rocksdb/io_status.h"
|
||||
#include "rocksdb/options.h"
|
||||
@@ -3786,11 +3788,251 @@ Status DBImpl::BackgroundCompaction(bool* made_progress,
|
||||
c->column_family_data()->GetName().c_str(),
|
||||
c->num_input_files(0));
|
||||
if (status.ok() && io_s.ok()) {
|
||||
UpdateDeletionCompactionStats(c);
|
||||
UpdateFIFOCompactionStatus(c);
|
||||
}
|
||||
*made_progress = true;
|
||||
TEST_SYNC_POINT_CALLBACK("DBImpl::BackgroundCompaction:AfterCompaction",
|
||||
c->column_family_data());
|
||||
} else if (c->is_trivial_copy_compaction()) {
|
||||
TEST_SYNC_POINT_CALLBACK(
|
||||
"DBImpl::BackgroundCompaction:TriviaCopyBeforeCompaction",
|
||||
c->column_family_data());
|
||||
assert(c->num_input_files(1) == 0);
|
||||
assert(c->column_family_data()->ioptions().compaction_style ==
|
||||
kCompactionStyleFIFO);
|
||||
assert(c->compaction_reason() == CompactionReason::kChangeTemperature);
|
||||
|
||||
compaction_job_stats.num_input_files = c->num_input_files(0);
|
||||
|
||||
NotifyOnCompactionBegin(c->column_family_data(), c.get(), status,
|
||||
compaction_job_stats, job_context->job_id);
|
||||
|
||||
std::vector<FileMetaData> out_files;
|
||||
for (const auto& in_file : *c->inputs(0)) {
|
||||
const uint64_t out_file_number = versions_->NewFileNumber();
|
||||
const std::string in_fname =
|
||||
TableFileName(c->immutable_options().cf_paths,
|
||||
in_file->fd.GetNumber(), in_file->fd.GetPathId());
|
||||
const std::string out_fname =
|
||||
TableFileName(c->immutable_options().cf_paths, out_file_number,
|
||||
c->output_path_id());
|
||||
|
||||
// TODO (mikechuang): Currently skip calling
|
||||
// EventHelpers::NotifyTableFileCreationStarted for the trivial copy.
|
||||
// Since it's a trivial copy we should ideally use the exact
|
||||
// TableProperties from the input file but that will break some existing
|
||||
// stress tests. For now skip the listener call for the FIFO
|
||||
// kChangeTemperature trivial copy move.
|
||||
|
||||
int64_t tmp_current_time = 0;
|
||||
auto get_time_status =
|
||||
immutable_db_options_.clock->GetCurrentTime(&tmp_current_time);
|
||||
if (!get_time_status.ok()) {
|
||||
ROCKS_LOG_BUFFER(log_buffer,
|
||||
"[%s] WARNING: Failed to get current time %s "
|
||||
"status=%s",
|
||||
c->column_family_data()->GetName().c_str(),
|
||||
get_time_status.ToString().c_str());
|
||||
}
|
||||
uint64_t out_file_creation_time = static_cast<uint64_t>(tmp_current_time);
|
||||
|
||||
FileOptions copied_file_options = file_options_;
|
||||
copied_file_options.temperature = c->output_temperature();
|
||||
std::unique_ptr<WritableFileWriter> dest_writer;
|
||||
{
|
||||
std::unique_ptr<FSWritableFile> dest_file;
|
||||
IOStatus writable_file_io_status =
|
||||
immutable_db_options_.fs.get()->NewWritableFile(
|
||||
out_fname, copied_file_options, &dest_file, nullptr /* dbg */);
|
||||
TEST_SYNC_POINT_CALLBACK(
|
||||
"NewWritableFile::FileOptions.temperature",
|
||||
const_cast<Temperature*>(&copied_file_options.temperature));
|
||||
if (!writable_file_io_status.ok()) {
|
||||
io_s = writable_file_io_status;
|
||||
ROCKS_LOG_BUFFER(
|
||||
log_buffer,
|
||||
"[%s] Error: Abort trivial copy compaction, failed to open "
|
||||
"NewWritableFile %s\n"
|
||||
" out_fname=%s, temperature=%s, io_status=%s",
|
||||
c->column_family_data()->GetName().c_str(), out_fname.c_str(),
|
||||
temperature_to_string[c->output_temperature()].c_str(),
|
||||
io_s.ToString().c_str());
|
||||
break;
|
||||
}
|
||||
|
||||
FileTypeSet tmp_set = immutable_db_options_.checksum_handoff_file_types;
|
||||
dest_writer.reset(new WritableFileWriter(
|
||||
std::move(dest_file), out_fname, copied_file_options,
|
||||
immutable_db_options_.clock, io_tracer_,
|
||||
immutable_db_options_.stats, Histograms::SST_WRITE_MICROS,
|
||||
c->immutable_options().listeners,
|
||||
immutable_db_options_.file_checksum_gen_factory.get(),
|
||||
tmp_set.Contains(FileType::kTableFile), false));
|
||||
}
|
||||
|
||||
ROCKS_LOG_BUFFER(
|
||||
log_buffer,
|
||||
"[%s] Started copying from: %s\n"
|
||||
" temperature=%s, to: %s, temperature=%s, buffer_size=%" PRIu64,
|
||||
c->column_family_data()->GetName().c_str(), in_fname.c_str(),
|
||||
temperature_to_string[in_file->temperature].c_str(),
|
||||
out_fname.c_str(),
|
||||
temperature_to_string[c->output_temperature()].c_str(),
|
||||
c->mutable_cf_options()
|
||||
.compaction_options_fifo.trivial_copy_buffer_size);
|
||||
// Add IO_LOW HINT for compaction
|
||||
IOOptions copy_files_compaction_io_options;
|
||||
copy_files_compaction_io_options.rate_limiter_priority =
|
||||
Env::IOPriority::IO_LOW;
|
||||
copy_files_compaction_io_options.type = IOType::kData;
|
||||
copy_files_compaction_io_options.io_activity =
|
||||
Env::IOActivity::kCompaction;
|
||||
|
||||
IOStatus copy_file_io_status = CopyFile(
|
||||
immutable_db_options_.fs.get() /* fileSystem */,
|
||||
in_fname /* source */, in_file->temperature /* src_temp_hint */,
|
||||
dest_writer /* dest_writer */, 0 /* size */, true /* use_fsync */,
|
||||
io_tracer_ /* io_tracer*/,
|
||||
c->mutable_cf_options()
|
||||
.compaction_options_fifo
|
||||
.trivial_copy_buffer_size /* max_read_buffer_size
|
||||
*/
|
||||
,
|
||||
copy_files_compaction_io_options /* readIOOptions */,
|
||||
copy_files_compaction_io_options /* writeIOOptions */);
|
||||
if (dest_writer) {
|
||||
IOOptions close_files_compaction_io_options;
|
||||
close_files_compaction_io_options.rate_limiter_priority =
|
||||
Env::IOPriority::IO_LOW;
|
||||
close_files_compaction_io_options.type = IOType::kData;
|
||||
close_files_compaction_io_options.io_activity =
|
||||
Env::IOActivity::kCompaction;
|
||||
// Close the dest_write
|
||||
io_s = dest_writer->Close(close_files_compaction_io_options);
|
||||
if (!io_s.ok()) {
|
||||
ROCKS_LOG_BUFFER(
|
||||
log_buffer,
|
||||
"[%s] Failed to close the writer. Failed to copy from: %s\n"
|
||||
" temperature=%s, to=%s, temperature=%s, io_status=%s",
|
||||
c->column_family_data()->GetName().c_str(), in_fname.c_str(),
|
||||
temperature_to_string[in_file->temperature].c_str(),
|
||||
out_fname.c_str(),
|
||||
temperature_to_string[c->output_temperature()].c_str(),
|
||||
io_s.ToString().c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
io_s = copy_file_io_status;
|
||||
|
||||
if (!io_s.ok()) {
|
||||
ROCKS_LOG_BUFFER(log_buffer,
|
||||
"[%s] Failed to copy from: %s\n"
|
||||
" temperature=%s, to=%s, temperature=%s, io_status=%s",
|
||||
c->column_family_data()->GetName().c_str(),
|
||||
in_fname.c_str(),
|
||||
temperature_to_string[in_file->temperature].c_str(),
|
||||
out_fname.c_str(),
|
||||
temperature_to_string[c->output_temperature()].c_str(),
|
||||
io_s.ToString().c_str());
|
||||
break;
|
||||
}
|
||||
ROCKS_LOG_BUFFER(log_buffer,
|
||||
"[%s] Successfully copying from: %s\n"
|
||||
" temperature=%s, to=%s, temperature=%s, io_status=%s",
|
||||
c->column_family_data()->GetName().c_str(),
|
||||
in_fname.c_str(),
|
||||
temperature_to_string[in_file->temperature].c_str(),
|
||||
out_fname.c_str(),
|
||||
temperature_to_string[c->output_temperature()].c_str(),
|
||||
io_s.ToString().c_str());
|
||||
|
||||
FileMetaData out_file_metadata{
|
||||
out_file_number,
|
||||
c->output_path_id(),
|
||||
in_file->fd.GetFileSize(),
|
||||
in_file->smallest,
|
||||
in_file->largest,
|
||||
in_file->fd.smallest_seqno,
|
||||
in_file->fd.largest_seqno,
|
||||
false /* marked_for_compact */,
|
||||
c->output_temperature() /* temperature */,
|
||||
in_file->oldest_blob_file_number,
|
||||
in_file->oldest_ancester_time,
|
||||
out_file_creation_time,
|
||||
c->MinInputFileEpochNumber(),
|
||||
dest_writer->GetFileChecksum(),
|
||||
dest_writer->GetFileChecksumFuncName(),
|
||||
in_file->unique_id,
|
||||
in_file->compensated_range_deletion_size,
|
||||
in_file->tail_size,
|
||||
in_file->user_defined_timestamps_persisted};
|
||||
|
||||
out_files.push_back(std::move(out_file_metadata));
|
||||
}
|
||||
|
||||
// Update version set
|
||||
if (status.ok() && io_s.ok()) {
|
||||
// NOTE: ChangeTemperature should only copy one file at one file
|
||||
// hence *c->inputs(0) == out_files.size() == 1 if copy succeeded
|
||||
assert(c->inputs(0)->size() == 1);
|
||||
assert(out_files.size() == 1);
|
||||
|
||||
auto out_file_metadata_it = out_files.begin();
|
||||
for (const auto& in_file : *c->inputs(0)) {
|
||||
if (out_file_metadata_it == out_files.end()) {
|
||||
break;
|
||||
}
|
||||
|
||||
c->edit()->DeleteFile(c->level(), in_file->fd.GetNumber());
|
||||
c->edit()->AddFile(c->level(), *out_file_metadata_it);
|
||||
++out_file_metadata_it;
|
||||
}
|
||||
|
||||
status = versions_->LogAndApply(
|
||||
c->column_family_data(), read_options, write_options, c->edit(),
|
||||
&mutex_, directories_.GetDbDir(),
|
||||
/*new_descriptor_log=*/false, /*column_family_options=*/nullptr,
|
||||
[&c, &compaction_released](const Status& s) {
|
||||
c->ReleaseCompactionFiles(s);
|
||||
compaction_released = true;
|
||||
});
|
||||
}
|
||||
|
||||
// TODO (mikechuang): Currently skip calling
|
||||
// EventHelper::LogAndNotifyTableFileCreationFinished for the trivial copy.
|
||||
// Since it's a trivial copy we should ideally use the exact TableProperties
|
||||
// from the input file but that will break some existing stress tests. For
|
||||
// now skip the listener call for the FIFO kChangeTemperature trivial copy
|
||||
// move.
|
||||
|
||||
if (io_s.ok()) {
|
||||
io_s = versions_->io_status();
|
||||
}
|
||||
|
||||
InstallSuperVersionAndScheduleWork(
|
||||
c->column_family_data(), job_context->superversion_contexts.data());
|
||||
if (status.ok() && io_s.ok()) {
|
||||
UpdateFIFOCompactionStatus(c);
|
||||
} else {
|
||||
for (const auto& in_file : *c->inputs(0)) {
|
||||
const std::string in_fname =
|
||||
TableFileName(c->immutable_options().cf_paths,
|
||||
in_file->fd.GetNumber(), in_file->fd.GetPathId());
|
||||
ROCKS_LOG_BUFFER(
|
||||
log_buffer,
|
||||
"[%s] Failed to do trvial copy compaction: %s"
|
||||
" temperature=%s, to temperature=%s, status=%s, io_status=%s",
|
||||
c->column_family_data()->GetName().c_str(), in_fname.c_str(),
|
||||
temperature_to_string[in_file->temperature].c_str(),
|
||||
temperature_to_string[c->output_temperature()].c_str(),
|
||||
status.ToString().c_str(), io_s.ToString().c_str());
|
||||
}
|
||||
}
|
||||
*made_progress = true;
|
||||
TEST_SYNC_POINT_CALLBACK(
|
||||
"DBImpl::BackgroundCompaction:TriviaCopyAfterCompaction",
|
||||
c->column_family_data());
|
||||
} else if (!trivial_move_disallowed && c->IsTrivialMove()) {
|
||||
TEST_SYNC_POINT("DBImpl::BackgroundCompaction:TrivialMove");
|
||||
TEST_SYNC_POINT_CALLBACK("DBImpl::BackgroundCompaction:BeforeCompaction",
|
||||
@@ -4176,8 +4418,7 @@ bool DBImpl::MCOverlap(ManualCompactionState* m, ManualCompactionState* m1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void DBImpl::UpdateDeletionCompactionStats(
|
||||
const std::unique_ptr<Compaction>& c) {
|
||||
void DBImpl::UpdateFIFOCompactionStatus(const std::unique_ptr<Compaction>& c) {
|
||||
if (c == nullptr) {
|
||||
return;
|
||||
}
|
||||
@@ -4191,6 +4432,9 @@ void DBImpl::UpdateDeletionCompactionStats(
|
||||
case CompactionReason::kFIFOTtl:
|
||||
RecordTick(stats_, FIFO_TTL_COMPACTIONS);
|
||||
break;
|
||||
case CompactionReason::kChangeTemperature:
|
||||
RecordTick(stats_, FIFO_CHANGE_TEMPERATURE_COMPACTIONS);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
|
||||
@@ -84,6 +84,7 @@ void DBImpl::TEST_GetFilesMetaData(
|
||||
}
|
||||
|
||||
uint64_t DBImpl::TEST_Current_Manifest_FileNo() {
|
||||
InstrumentedMutexLock l(&mutex_);
|
||||
return versions_->manifest_file_number();
|
||||
}
|
||||
|
||||
|
||||
+48
-23
@@ -2000,6 +2000,9 @@ Status DBImpl::WriteLevel0TableForRecovery(int job_id, ColumnFamilyData* cfd,
|
||||
const size_t ts_sz = ucmp->timestamp_size();
|
||||
const bool logical_strip_timestamp =
|
||||
ts_sz > 0 && !cfd->ioptions().persist_user_defined_timestamps;
|
||||
// Note that here we treat flush as level 0 compaction in internal stats
|
||||
InternalStats::CompactionStats flush_stats(CompactionReason::kFlush,
|
||||
1 /* count */);
|
||||
{
|
||||
ScopedArenaPtr<InternalIterator> iter(
|
||||
logical_strip_timestamp
|
||||
@@ -2072,19 +2075,20 @@ Status DBImpl::WriteLevel0TableForRecovery(int job_id, ColumnFamilyData* cfd,
|
||||
kMaxSequenceNumber);
|
||||
Version* version = cfd->current();
|
||||
version->Ref();
|
||||
uint64_t num_input_entries = 0;
|
||||
s = BuildTable(dbname_, versions_.get(), immutable_db_options_, tboptions,
|
||||
file_options_for_compaction_, cfd->table_cache(),
|
||||
iter.get(), std::move(range_del_iters), &meta,
|
||||
&blob_file_additions, snapshot_seqs, earliest_snapshot,
|
||||
earliest_write_conflict_snapshot, kMaxSequenceNumber,
|
||||
snapshot_checker, paranoid_file_checks,
|
||||
cfd->internal_stats(), &io_s, io_tracer_,
|
||||
BlobFileCreationReason::kRecovery,
|
||||
nullptr /* seqno_to_time_mapping */, &event_logger_,
|
||||
job_id, nullptr /* table_properties */, write_hint,
|
||||
nullptr /*full_history_ts_low*/, &blob_callback_, version,
|
||||
&num_input_entries);
|
||||
TableProperties temp_table_proerties;
|
||||
s = BuildTable(
|
||||
dbname_, versions_.get(), immutable_db_options_, tboptions,
|
||||
file_options_for_compaction_, cfd->table_cache(), iter.get(),
|
||||
std::move(range_del_iters), &meta, &blob_file_additions,
|
||||
snapshot_seqs, earliest_snapshot, earliest_write_conflict_snapshot,
|
||||
kMaxSequenceNumber, snapshot_checker, paranoid_file_checks,
|
||||
cfd->internal_stats(), &io_s, io_tracer_,
|
||||
BlobFileCreationReason::kRecovery,
|
||||
nullptr /* seqno_to_time_mapping */, &event_logger_, job_id,
|
||||
&temp_table_proerties /* table_properties */, write_hint,
|
||||
nullptr /*full_history_ts_low*/, &blob_callback_, version,
|
||||
nullptr /* memtable_payload_bytes */,
|
||||
nullptr /* memtable_garbage_bytes */, &flush_stats);
|
||||
version->Unref();
|
||||
LogFlush(immutable_db_options_.info_log);
|
||||
ROCKS_LOG_DEBUG(immutable_db_options_.info_log,
|
||||
@@ -2100,10 +2104,31 @@ Status DBImpl::WriteLevel0TableForRecovery(int job_id, ColumnFamilyData* cfd,
|
||||
}
|
||||
|
||||
uint64_t total_num_entries = mem->NumEntries();
|
||||
if (s.ok() && total_num_entries != num_input_entries) {
|
||||
if (s.ok() && total_num_entries != flush_stats.num_input_records) {
|
||||
std::string msg = "Expected " + std::to_string(total_num_entries) +
|
||||
" entries in memtable, but read " +
|
||||
std::to_string(num_input_entries);
|
||||
std::to_string(flush_stats.num_input_records);
|
||||
ROCKS_LOG_WARN(immutable_db_options_.info_log,
|
||||
"[%s] [JOB %d] Level-0 flush during recover: %s",
|
||||
cfd->GetName().c_str(), job_id, msg.c_str());
|
||||
if (immutable_db_options_.flush_verify_memtable_count) {
|
||||
s = Status::Corruption(msg);
|
||||
}
|
||||
}
|
||||
// Only verify on table with format collects table properties
|
||||
const auto& mutable_cf_options = cfd->GetLatestMutableCFOptions();
|
||||
if (s.ok() &&
|
||||
(mutable_cf_options.table_factory->IsInstanceOf(
|
||||
TableFactory::kBlockBasedTableName()) ||
|
||||
mutable_cf_options.table_factory->IsInstanceOf(
|
||||
TableFactory::kPlainTableName())) &&
|
||||
flush_stats.num_output_records != temp_table_proerties.num_entries) {
|
||||
std::string msg =
|
||||
"Number of keys in flush output SST files does not match "
|
||||
"number of keys added to the table. Expected " +
|
||||
std::to_string(flush_stats.num_output_records) + " but there are " +
|
||||
std::to_string(temp_table_proerties.num_entries) +
|
||||
" in output SST files";
|
||||
ROCKS_LOG_WARN(immutable_db_options_.info_log,
|
||||
"[%s] [JOB %d] Level-0 flush during recover: %s",
|
||||
cfd->GetName().c_str(), job_id, msg.c_str());
|
||||
@@ -2151,25 +2176,25 @@ Status DBImpl::WriteLevel0TableForRecovery(int job_id, ColumnFamilyData* cfd,
|
||||
}
|
||||
}
|
||||
|
||||
InternalStats::CompactionStats stats(CompactionReason::kFlush, 1);
|
||||
stats.micros = immutable_db_options_.clock->NowMicros() - start_micros;
|
||||
flush_stats.micros = immutable_db_options_.clock->NowMicros() - start_micros;
|
||||
|
||||
if (has_output) {
|
||||
stats.bytes_written = meta.fd.GetFileSize();
|
||||
stats.num_output_files = 1;
|
||||
flush_stats.bytes_written = meta.fd.GetFileSize();
|
||||
flush_stats.num_output_files = 1;
|
||||
}
|
||||
|
||||
const auto& blobs = edit->GetBlobFileAdditions();
|
||||
for (const auto& blob : blobs) {
|
||||
stats.bytes_written_blob += blob.GetTotalBlobBytes();
|
||||
flush_stats.bytes_written_blob += blob.GetTotalBlobBytes();
|
||||
}
|
||||
|
||||
stats.num_output_files_blob = static_cast<int>(blobs.size());
|
||||
flush_stats.num_output_files_blob = static_cast<int>(blobs.size());
|
||||
|
||||
cfd->internal_stats()->AddCompactionStats(level, Env::Priority::USER, stats);
|
||||
cfd->internal_stats()->AddCompactionStats(level, Env::Priority::USER,
|
||||
flush_stats);
|
||||
cfd->internal_stats()->AddCFStats(
|
||||
InternalStats::BYTES_FLUSHED,
|
||||
stats.bytes_written + stats.bytes_written_blob);
|
||||
flush_stats.bytes_written + flush_stats.bytes_written_blob);
|
||||
RecordTick(stats_, COMPACT_WRITE_BYTES, meta.fd.GetFileSize());
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -728,13 +728,13 @@ Status DBImplSecondary::TryCatchUpWithPrimary() {
|
||||
// instance
|
||||
if (s.ok()) {
|
||||
s = FindAndRecoverLogFiles(&cfds_changed, &job_context);
|
||||
}
|
||||
if (s.IsPathNotFound()) {
|
||||
ROCKS_LOG_INFO(
|
||||
immutable_db_options_.info_log,
|
||||
"Secondary tries to read WAL, but WAL file(s) have already "
|
||||
"been purged by primary.");
|
||||
s = Status::OK();
|
||||
if (s.IsPathNotFound()) {
|
||||
ROCKS_LOG_INFO(
|
||||
immutable_db_options_.info_log,
|
||||
"Secondary tries to read WAL, but WAL file(s) have already "
|
||||
"been purged by primary.");
|
||||
s = Status::OK();
|
||||
}
|
||||
}
|
||||
if (s.ok()) {
|
||||
for (auto cfd : cfds_changed) {
|
||||
@@ -909,7 +909,7 @@ Status DBImplSecondary::CompactWithoutInstallation(
|
||||
ROCKS_LOG_ERROR(
|
||||
immutable_db_options_.info_log,
|
||||
"GetCompactionInputsFromFileNumbers() failed - %s.\n DebugString: %s",
|
||||
s.ToString().c_str(), version->DebugString().c_str());
|
||||
s.ToString().c_str(), version->DebugString(/*hex=*/true).c_str());
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
@@ -929,6 +929,7 @@ Status DBImpl::WriteImpl(const WriteOptions& write_options,
|
||||
/*min_prep_log=*/log_ref, last_sequence,
|
||||
/*memtable_updated=*/memtable_update_count > 0,
|
||||
write_options.ignore_missing_column_families);
|
||||
RecordTick(stats_, NUMBER_WBWI_INGEST);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
||||
|
||||
#include <iomanip>
|
||||
|
||||
#include "db/db_test_util.h"
|
||||
#include "port/stack_trace.h"
|
||||
#include "test_util/testutil.h"
|
||||
|
||||
+4
-4
@@ -71,9 +71,9 @@ class DBIter final : public Iterator {
|
||||
InternalIterator* internal_iter,
|
||||
const Version* version, const SequenceNumber& sequence,
|
||||
ReadCallback* read_callback,
|
||||
ReadOnlyMemTable* active_mem,
|
||||
ColumnFamilyHandleImpl* cfh = nullptr,
|
||||
bool expose_blob_index = false,
|
||||
ReadOnlyMemTable* active_mem = nullptr,
|
||||
Arena* arena = nullptr) {
|
||||
void* mem = arena ? arena->AllocateAligned(sizeof(DBIter))
|
||||
: operator new(sizeof(DBIter));
|
||||
@@ -475,9 +475,9 @@ class DBIter final : public Iterator {
|
||||
const size_t timestamp_size_;
|
||||
std::string saved_timestamp_;
|
||||
std::optional<std::vector<ScanOptions>> scan_opts_;
|
||||
ReadOnlyMemTable* active_mem_;
|
||||
SequenceNumber memtable_seqno_lb_;
|
||||
uint32_t memtable_op_scan_flush_trigger_;
|
||||
ReadOnlyMemTable* const active_mem_;
|
||||
const SequenceNumber memtable_seqno_lb_;
|
||||
const uint32_t memtable_op_scan_flush_trigger_;
|
||||
Direction direction_;
|
||||
bool valid_;
|
||||
bool current_entry_is_merged_;
|
||||
|
||||
@@ -532,7 +532,7 @@ TEST_F(DBIteratorStressTest, StressTest) {
|
||||
env_, ropt, ImmutableOptions(options),
|
||||
MutableCFOptions(options), BytewiseComparator(),
|
||||
internal_iter, /*version=*/nullptr, sequence,
|
||||
nullptr /*read_callback*/));
|
||||
nullptr /*read_callback*/, /*active_mem=*/nullptr));
|
||||
}
|
||||
|
||||
// Do a random operation. It's important to do it on ref_it
|
||||
|
||||
+84
-82
@@ -262,7 +262,7 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 10 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -296,7 +296,7 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 10 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -323,7 +323,7 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 10 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -356,7 +356,7 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 10 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -392,7 +392,7 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 10 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(!db_iter->Valid());
|
||||
@@ -423,7 +423,7 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 7 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
SetPerfLevel(kEnableCount);
|
||||
ASSERT_TRUE(GetPerfLevel() == kEnableCount);
|
||||
@@ -462,7 +462,7 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 4 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -488,7 +488,7 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 10 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(!db_iter->Valid());
|
||||
@@ -512,7 +512,7 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 10 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -548,7 +548,7 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 7 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
SetPerfLevel(kEnableCount);
|
||||
ASSERT_TRUE(GetPerfLevel() == kEnableCount);
|
||||
@@ -579,7 +579,7 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 10 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -623,7 +623,7 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 2 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "b");
|
||||
@@ -655,7 +655,7 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 10 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "c");
|
||||
@@ -686,7 +686,7 @@ TEST_F(DBIteratorTest, DBIteratorEmpty) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 0 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(!db_iter->Valid());
|
||||
ASSERT_OK(db_iter->status());
|
||||
@@ -699,7 +699,7 @@ TEST_F(DBIteratorTest, DBIteratorEmpty) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 0 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(!db_iter->Valid());
|
||||
ASSERT_OK(db_iter->status());
|
||||
@@ -723,7 +723,7 @@ TEST_F(DBIteratorTest, DBIteratorUseSkipCountSkips) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ImmutableOptions(options), MutableCFOptions(options),
|
||||
BytewiseComparator(), internal_iter, nullptr /* version */,
|
||||
2 /* sequence */, nullptr /* read_callback */));
|
||||
2 /* sequence */, nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "c");
|
||||
@@ -770,7 +770,7 @@ TEST_F(DBIteratorTest, DBIteratorUseSkip) {
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, i + 2 /* sequence */,
|
||||
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -808,7 +808,7 @@ TEST_F(DBIteratorTest, DBIteratorUseSkip) {
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, i + 2 /* sequence */,
|
||||
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -838,8 +838,7 @@ TEST_F(DBIteratorTest, DBIteratorUseSkip) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 202 /* sequence */,
|
||||
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -874,7 +873,7 @@ TEST_F(DBIteratorTest, DBIteratorUseSkip) {
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, i /* sequence */,
|
||||
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(!db_iter->Valid());
|
||||
ASSERT_OK(db_iter->status());
|
||||
@@ -893,7 +892,7 @@ TEST_F(DBIteratorTest, DBIteratorUseSkip) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 200 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "c");
|
||||
@@ -931,7 +930,7 @@ TEST_F(DBIteratorTest, DBIteratorUseSkip) {
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, i + 2 /* sequence */,
|
||||
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -968,7 +967,7 @@ TEST_F(DBIteratorTest, DBIteratorUseSkip) {
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, i + 2 /* sequence */,
|
||||
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -1019,7 +1018,7 @@ TEST_F(DBIteratorTest, DBIteratorSkipInternalKeys) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 10 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -1066,7 +1065,7 @@ TEST_F(DBIteratorTest, DBIteratorSkipInternalKeys) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 10 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -1111,7 +1110,7 @@ TEST_F(DBIteratorTest, DBIteratorSkipInternalKeys) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 10 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -1150,7 +1149,7 @@ TEST_F(DBIteratorTest, DBIteratorSkipInternalKeys) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 10 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -1186,7 +1185,7 @@ TEST_F(DBIteratorTest, DBIteratorSkipInternalKeys) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 10 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -1217,7 +1216,7 @@ TEST_F(DBIteratorTest, DBIteratorSkipInternalKeys) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 10 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -1255,7 +1254,7 @@ TEST_F(DBIteratorTest, DBIteratorSkipInternalKeys) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 10 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -1294,7 +1293,7 @@ TEST_F(DBIteratorTest, DBIteratorSkipInternalKeys) {
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 2 * i + 1 /* sequence */,
|
||||
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -1348,7 +1347,7 @@ TEST_F(DBIteratorTest, DBIteratorSkipInternalKeys) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, MutableCFOptions(options), BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 2 * i + 1 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -1391,7 +1390,7 @@ TEST_F(DBIteratorTest, DBIteratorTimedPutBasic) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ImmutableOptions(options), MutableCFOptions(options),
|
||||
BytewiseComparator(), internal_iter, nullptr /* version */,
|
||||
7 /* sequence */, nullptr /* read_callback */));
|
||||
7 /* sequence */, nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1441,7 +1440,7 @@ TEST_F(DBIteratorTest, DBIterator1) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ImmutableOptions(options), MutableCFOptions(options),
|
||||
BytewiseComparator(), internal_iter, nullptr /* version */,
|
||||
1 /* sequence */, nullptr /* read_callback */));
|
||||
1 /* sequence */, nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1470,7 +1469,7 @@ TEST_F(DBIteratorTest, DBIterator2) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ImmutableOptions(options), MutableCFOptions(options),
|
||||
BytewiseComparator(), internal_iter, nullptr /* version */,
|
||||
0 /* sequence */, nullptr /* read_callback */));
|
||||
0 /* sequence */, nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1495,7 +1494,7 @@ TEST_F(DBIteratorTest, DBIterator3) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ImmutableOptions(options), MutableCFOptions(options),
|
||||
BytewiseComparator(), internal_iter, nullptr /* version */,
|
||||
2 /* sequence */, nullptr /* read_callback */));
|
||||
2 /* sequence */, nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1520,7 +1519,7 @@ TEST_F(DBIteratorTest, DBIterator4) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ImmutableOptions(options), MutableCFOptions(options),
|
||||
BytewiseComparator(), internal_iter, nullptr /* version */,
|
||||
4 /* sequence */, nullptr /* read_callback */));
|
||||
4 /* sequence */, nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1554,7 +1553,7 @@ TEST_F(DBIteratorTest, DBIterator5) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 0 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1578,7 +1577,7 @@ TEST_F(DBIteratorTest, DBIterator5) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 1 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1602,7 +1601,7 @@ TEST_F(DBIteratorTest, DBIterator5) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 2 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1626,7 +1625,7 @@ TEST_F(DBIteratorTest, DBIterator5) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 3 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1650,7 +1649,7 @@ TEST_F(DBIteratorTest, DBIterator5) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 4 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1674,7 +1673,7 @@ TEST_F(DBIteratorTest, DBIterator5) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 5 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1698,7 +1697,7 @@ TEST_F(DBIteratorTest, DBIterator5) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 6 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1720,7 +1719,7 @@ TEST_F(DBIteratorTest, DBIterator5) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 10 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->Seek("b");
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "b");
|
||||
@@ -1751,7 +1750,7 @@ TEST_F(DBIteratorTest, DBIterator6) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 0 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1775,7 +1774,7 @@ TEST_F(DBIteratorTest, DBIterator6) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 1 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1799,7 +1798,7 @@ TEST_F(DBIteratorTest, DBIterator6) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 2 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1823,7 +1822,7 @@ TEST_F(DBIteratorTest, DBIterator6) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 3 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(!db_iter->Valid());
|
||||
ASSERT_OK(db_iter->status());
|
||||
@@ -1843,7 +1842,7 @@ TEST_F(DBIteratorTest, DBIterator6) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 4 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1867,7 +1866,7 @@ TEST_F(DBIteratorTest, DBIterator6) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 5 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1891,7 +1890,7 @@ TEST_F(DBIteratorTest, DBIterator6) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 6 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1935,7 +1934,7 @@ TEST_F(DBIteratorTest, DBIterator7) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 0 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1971,7 +1970,7 @@ TEST_F(DBIteratorTest, DBIterator7) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 2 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -2013,7 +2012,7 @@ TEST_F(DBIteratorTest, DBIterator7) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 4 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -2055,7 +2054,7 @@ TEST_F(DBIteratorTest, DBIterator7) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 5 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -2102,7 +2101,7 @@ TEST_F(DBIteratorTest, DBIterator7) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 6 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -2150,7 +2149,7 @@ TEST_F(DBIteratorTest, DBIterator7) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 7 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -2192,7 +2191,7 @@ TEST_F(DBIteratorTest, DBIterator7) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 9 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -2240,7 +2239,7 @@ TEST_F(DBIteratorTest, DBIterator7) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 13 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -2289,7 +2288,7 @@ TEST_F(DBIteratorTest, DBIterator7) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ioptions, mutable_cf_options, BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 14 /* sequence */,
|
||||
nullptr /* read_callback */));
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -2321,7 +2320,7 @@ TEST_F(DBIteratorTest, DBIterator8) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ImmutableOptions(options), MutableCFOptions(options),
|
||||
BytewiseComparator(), internal_iter, nullptr /* version */,
|
||||
10 /* sequence */, nullptr /* read_callback */));
|
||||
10 /* sequence */, nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "b");
|
||||
@@ -2349,10 +2348,11 @@ TEST_F(DBIteratorTest, DBIterator9) {
|
||||
internal_iter->AddMerge("d", "merge_6");
|
||||
internal_iter->Finish();
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ImmutableOptions(options), MutableCFOptions(options),
|
||||
BytewiseComparator(), internal_iter, nullptr /* version */,
|
||||
10 /* sequence */, nullptr /* read_callback */));
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
DBIter::NewIter(env_, ro, ImmutableOptions(options),
|
||||
MutableCFOptions(options), BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 10 /* sequence */,
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -2419,7 +2419,7 @@ TEST_F(DBIteratorTest, DBIterator10) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ImmutableOptions(options), MutableCFOptions(options),
|
||||
BytewiseComparator(), internal_iter, nullptr /* version */,
|
||||
10 /* sequence */, nullptr /* read_callback */));
|
||||
10 /* sequence */, nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
db_iter->Seek("c");
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -2459,7 +2459,7 @@ TEST_F(DBIteratorTest, SeekToLastOccurrenceSeq0) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ImmutableOptions(options), MutableCFOptions(options),
|
||||
BytewiseComparator(), internal_iter, nullptr /* version */,
|
||||
10 /* sequence */, 0 /* force seek */, nullptr /* read_callback */));
|
||||
10 /* sequence */, nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -2489,7 +2489,7 @@ TEST_F(DBIteratorTest, DBIterator11) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ImmutableOptions(options), MutableCFOptions(options),
|
||||
BytewiseComparator(), internal_iter, nullptr /* version */,
|
||||
1 /* sequence */, nullptr /* read_callback */));
|
||||
1 /* sequence */, nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -2517,7 +2517,7 @@ TEST_F(DBIteratorTest, DBIterator12) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ImmutableOptions(options), MutableCFOptions(options),
|
||||
BytewiseComparator(), internal_iter, nullptr /* version */,
|
||||
10 /* sequence */, 0 /* force seek */, nullptr /* read_callback */));
|
||||
10 /* sequence */, nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "c");
|
||||
@@ -2557,7 +2557,7 @@ TEST_F(DBIteratorTest, DBIterator13) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ImmutableOptions(options), MutableCFOptions(options),
|
||||
BytewiseComparator(), internal_iter, nullptr /* version */,
|
||||
2 /* sequence */, nullptr /* read_callback */));
|
||||
2 /* sequence */, nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->Seek("b");
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), key);
|
||||
@@ -2587,7 +2587,7 @@ TEST_F(DBIteratorTest, DBIterator14) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ImmutableOptions(options), MutableCFOptions(options),
|
||||
BytewiseComparator(), internal_iter, nullptr /* version */,
|
||||
4 /* sequence */, nullptr /* read_callback */));
|
||||
4 /* sequence */, nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
db_iter->Seek("b");
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "b");
|
||||
@@ -2627,7 +2627,8 @@ class DBIterWithMergeIterTest : public testing::Test {
|
||||
db_iter_.reset(DBIter::NewIter(
|
||||
env_, ro_, ImmutableOptions(options_), MutableCFOptions(options_),
|
||||
BytewiseComparator(), merge_iter, nullptr /* version */,
|
||||
8 /* read data earlier than seqId 8 */, nullptr /* read_callback */));
|
||||
8 /* read data earlier than seqId 8 */, nullptr /* read_callback */,
|
||||
/*active_mem=*/nullptr));
|
||||
}
|
||||
|
||||
Env* env_;
|
||||
@@ -3066,7 +3067,7 @@ TEST_F(DBIteratorTest, SeekPrefixTombstones) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ImmutableOptions(options), MutableCFOptions(options),
|
||||
BytewiseComparator(), internal_iter, nullptr /* version */,
|
||||
10 /* sequence */, nullptr /* read_callback */));
|
||||
10 /* sequence */, nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
int skipped_keys = 0;
|
||||
|
||||
@@ -3099,10 +3100,11 @@ TEST_F(DBIteratorTest, SeekToFirstLowerBound) {
|
||||
Slice lower_bound(lower_bound_str);
|
||||
ro.iterate_lower_bound = &lower_bound;
|
||||
Options options;
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ImmutableOptions(options), MutableCFOptions(options),
|
||||
BytewiseComparator(), internal_iter, nullptr /* version */,
|
||||
10 /* sequence */, nullptr /* read_callback */));
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
DBIter::NewIter(env_, ro, ImmutableOptions(options),
|
||||
MutableCFOptions(options), BytewiseComparator(),
|
||||
internal_iter, nullptr /* version */, 10 /* sequence */,
|
||||
nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
db_iter->SeekToFirst();
|
||||
if (i == kNumKeys + 1) {
|
||||
@@ -3141,7 +3143,7 @@ TEST_F(DBIteratorTest, PrevLowerBound) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ImmutableOptions(options), MutableCFOptions(options),
|
||||
BytewiseComparator(), internal_iter, nullptr /* version */,
|
||||
10 /* sequence */, nullptr /* read_callback */));
|
||||
10 /* sequence */, nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
db_iter->SeekToLast();
|
||||
for (int i = kNumKeys; i >= kLowerBound; --i) {
|
||||
@@ -3169,7 +3171,7 @@ TEST_F(DBIteratorTest, SeekLessLowerBound) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ro, ImmutableOptions(options), MutableCFOptions(options),
|
||||
BytewiseComparator(), internal_iter, nullptr /* version */,
|
||||
10 /* sequence */, nullptr /* read_callback */));
|
||||
10 /* sequence */, nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
auto before_lower_bound_str = std::to_string(kLowerBound - 1);
|
||||
Slice before_lower_bound(lower_bound_str);
|
||||
@@ -3194,7 +3196,7 @@ TEST_F(DBIteratorTest, ReverseToForwardWithDisappearingKeys) {
|
||||
std::unique_ptr<Iterator> db_iter(DBIter::NewIter(
|
||||
env_, ReadOptions(), ImmutableOptions(options), MutableCFOptions(options),
|
||||
BytewiseComparator(), internal_iter, nullptr /* version */,
|
||||
10 /* sequence */, nullptr /* read_callback */));
|
||||
10 /* sequence */, nullptr /* read_callback */, /*active_mem=*/nullptr));
|
||||
|
||||
db_iter->SeekForPrev("a");
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -377,6 +377,8 @@ TEST_F(DBPropertiesTest, AggregatedTableProperties) {
|
||||
NewBloomFilterPolicy(kBloomBitsPerKey, false));
|
||||
table_options.block_size = 1024;
|
||||
options.table_factory.reset(NewBlockBasedTableFactory(table_options));
|
||||
// The checks assume kTableCount number of files
|
||||
options.disable_auto_compactions = true;
|
||||
|
||||
DestroyAndReopen(options);
|
||||
|
||||
@@ -567,7 +569,7 @@ TEST_F(DBPropertiesTest, AggregatedTablePropertiesAtLevel) {
|
||||
options.target_file_size_base = 8192;
|
||||
options.max_bytes_for_level_base = 10000;
|
||||
options.max_bytes_for_level_multiplier = 2;
|
||||
// This ensures there no compaction happening when we call GetProperty().
|
||||
// The checks assume kTableCount number of files
|
||||
options.disable_auto_compactions = true;
|
||||
options.merge_operator.reset(new TestPutOperator());
|
||||
|
||||
|
||||
+97
-1
@@ -144,6 +144,103 @@ TEST_F(DBTest, MockEnvTest) {
|
||||
delete db;
|
||||
}
|
||||
|
||||
TEST_F(DBTest, RequestIdPlumbingTest) {
|
||||
// test that request_id is passed to the filesystem, from
|
||||
// ReadOptions to IODebugContext
|
||||
Options options = CurrentOptions();
|
||||
options.env = env_;
|
||||
|
||||
// Create a mock environment to capture IODebugContext during reads
|
||||
const std::string* captured_request_id_dbg;
|
||||
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"RandomAccessFileReader::Read:IODebugContext", [&](void* arg) {
|
||||
IODebugContext* dbg = static_cast<IODebugContext*>(arg);
|
||||
if (dbg == nullptr) {
|
||||
captured_request_id_dbg = nullptr;
|
||||
} else {
|
||||
captured_request_id_dbg = dbg->request_id;
|
||||
}
|
||||
});
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
ASSERT_OK(Put("k1", "v1"));
|
||||
ASSERT_OK(Flush());
|
||||
|
||||
// test request_id plumbing during a get
|
||||
{
|
||||
const std::string test_request_id = "test_request_id_123";
|
||||
ReadOptions read_opts;
|
||||
read_opts.request_id = &test_request_id;
|
||||
std::string value;
|
||||
ASSERT_OK(db_->Get(read_opts, "k1", &value));
|
||||
|
||||
// Verify the request_id was propagated to the file system
|
||||
ASSERT_NE(captured_request_id_dbg, nullptr);
|
||||
ASSERT_EQ(*captured_request_id_dbg, test_request_id);
|
||||
}
|
||||
|
||||
captured_request_id_dbg = nullptr;
|
||||
|
||||
// test request_id plumbing during iterator seek
|
||||
ASSERT_OK(Put("k2", "v2"));
|
||||
ASSERT_OK(Flush());
|
||||
{
|
||||
ReadOptions read_opts;
|
||||
const std::string request_id = "test_request_id_456";
|
||||
read_opts.request_id = &request_id;
|
||||
|
||||
std::unique_ptr<Iterator> iter(db_->NewIterator(read_opts));
|
||||
iter->Seek("k2");
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
|
||||
// Verify the request_id was propagated to the file system
|
||||
ASSERT_NE(captured_request_id_dbg, nullptr);
|
||||
ASSERT_EQ(*captured_request_id_dbg, request_id);
|
||||
}
|
||||
|
||||
// test request_id plumbing during multiget
|
||||
captured_request_id_dbg = nullptr;
|
||||
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearAllCallBacks();
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"RandomAccessFileReader::MultiRead:IODebugContext", [&](void* arg) {
|
||||
IODebugContext* dbg = static_cast<IODebugContext*>(arg);
|
||||
if (dbg == nullptr) {
|
||||
captured_request_id_dbg = nullptr;
|
||||
} else {
|
||||
captured_request_id_dbg = dbg->request_id;
|
||||
}
|
||||
});
|
||||
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
ASSERT_OK(Put("k3", "v3"));
|
||||
ASSERT_OK(Put("k4", "v4"));
|
||||
ASSERT_OK(Flush());
|
||||
|
||||
{
|
||||
ReadOptions read_opts;
|
||||
const std::string multiget_request_id = "test_request_id_789";
|
||||
read_opts.request_id = &multiget_request_id;
|
||||
|
||||
std::vector<std::string> values;
|
||||
std::vector<Slice> keys = {Slice("k3"), Slice("k4")};
|
||||
|
||||
values.resize(keys.size());
|
||||
|
||||
std::vector<ColumnFamilyHandle*> cfhs(keys.size(),
|
||||
db_->DefaultColumnFamily());
|
||||
db_->MultiGet(read_opts, cfhs, keys, &values);
|
||||
|
||||
ASSERT_NE(captured_request_id_dbg, nullptr);
|
||||
ASSERT_EQ(*captured_request_id_dbg, multiget_request_id);
|
||||
}
|
||||
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearAllCallBacks();
|
||||
}
|
||||
|
||||
TEST_F(DBTest, MemEnvTest) {
|
||||
std::unique_ptr<Env> env{NewMemEnv(Env::Default())};
|
||||
Options options;
|
||||
@@ -5463,7 +5560,6 @@ TEST_F(DBTest, DynamicLevelCompressionPerLevel2) {
|
||||
options.max_bytes_for_level_multiplier = 8;
|
||||
options.max_background_compactions = 1;
|
||||
options.num_levels = 5;
|
||||
options.compaction_verify_record_count = false;
|
||||
std::shared_ptr<mock::MockTableFactory> mtf(new mock::MockTableFactory);
|
||||
options.table_factory = mtf;
|
||||
|
||||
|
||||
+2
-4
@@ -1722,16 +1722,14 @@ TEST_P(CompressionFailuresTest, CompressionFailures) {
|
||||
});
|
||||
} else if (compression_failure_type_ == kTestDecompressionFail) {
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"UncompressBlockData:TamperWithReturnValue", [](void* arg) {
|
||||
"DecompressBlockData:TamperWithReturnValue", [](void* arg) {
|
||||
Status* ret = static_cast<Status*>(arg);
|
||||
ASSERT_OK(*ret);
|
||||
*ret = Status::Corruption("kTestDecompressionFail");
|
||||
});
|
||||
} else if (compression_failure_type_ == kTestDecompressionCorruption) {
|
||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||
"UncompressBlockData:"
|
||||
"TamperWithDecompressionOutput",
|
||||
[](void* arg) {
|
||||
"DecompressBlockData:TamperWithDecompressionOutput", [](void* arg) {
|
||||
BlockContents* contents = static_cast<BlockContents*>(arg);
|
||||
// Ensure uncompressed data != original data
|
||||
const size_t len = contents->data.size() + 1;
|
||||
|
||||
@@ -260,55 +260,6 @@ TEST_F(ExternalSSTFileBasicTest, Basic) {
|
||||
s = sst_file_writer.DeleteRange(Key(100), Key(200));
|
||||
ASSERT_NOK(s) << s.ToString();
|
||||
|
||||
DestroyAndReopen(options);
|
||||
|
||||
SyncPoint::GetInstance()->LoadDependency({
|
||||
{"DBImpl::IngestExternalFile:AfterIncIngestFileCounter",
|
||||
"ExternalSSTFileBasicTest.LiveWriteStart"},
|
||||
{"WriteThread::JoinBatchGroup:Wait",
|
||||
"DBImpl::IngestExternalFile:AfterIncIngestFileCounter:2"},
|
||||
});
|
||||
SyncPoint::GetInstance()->EnableProcessing();
|
||||
PerfContext* write_thread_perf_context;
|
||||
std::thread write_thread([&] {
|
||||
TEST_SYNC_POINT("ExternalSSTFileBasicTest.LiveWriteStart");
|
||||
SetPerfLevel(kEnableWait);
|
||||
write_thread_perf_context = get_perf_context();
|
||||
write_thread_perf_context->Reset();
|
||||
ASSERT_OK(db_->Put(WriteOptions(), "bar", "v2"));
|
||||
ASSERT_GT(write_thread_perf_context->write_thread_wait_nanos, 0);
|
||||
// Test sync points were used to make sure this live write enter write
|
||||
// thread after the file ingestion entered write thread. So by the time this
|
||||
// live write finishes, the latest seqno is 1 means file ingestion used
|
||||
// seqno 0.
|
||||
ASSERT_EQ(db_->GetLatestSequenceNumber(), 1U);
|
||||
});
|
||||
|
||||
// Add file using file path
|
||||
SetPerfLevel(kEnableTimeExceptForMutex);
|
||||
PerfContext* perf_ctx = get_perf_context();
|
||||
perf_ctx->Reset();
|
||||
s = DeprecatedAddFile({file1});
|
||||
ASSERT_GT(perf_context.file_ingestion_nanos, 0);
|
||||
ASSERT_GT(perf_context.file_ingestion_blocking_live_writes_nanos, 0);
|
||||
ASSERT_OK(s) << s.ToString();
|
||||
for (int k = 0; k < 100; k++) {
|
||||
ASSERT_EQ(Get(Key(k)), Key(k) + "_val");
|
||||
}
|
||||
|
||||
write_thread.join();
|
||||
SyncPoint::GetInstance()->DisableProcessing();
|
||||
|
||||
// Re-ingest the file just to check the perf context not enabled at and below
|
||||
// kEnableWait.
|
||||
SetPerfLevel(kEnableWait);
|
||||
perf_ctx->Reset();
|
||||
IngestExternalFileOptions opts;
|
||||
opts.allow_global_seqno = true;
|
||||
opts.allow_blocking_flush = true;
|
||||
ASSERT_OK(db_->IngestExternalFile({file1}, opts));
|
||||
ASSERT_EQ(perf_context.file_ingestion_nanos, 0);
|
||||
ASSERT_EQ(perf_context.file_ingestion_blocking_live_writes_nanos, 0);
|
||||
DestroyAndRecreateExternalSSTFilesDir();
|
||||
}
|
||||
|
||||
|
||||
+48
-25
@@ -868,7 +868,9 @@ Status FlushJob::WriteLevel0Table() {
|
||||
ts_sz > 0 && !cfd_->ioptions().persist_user_defined_timestamps;
|
||||
|
||||
std::vector<BlobFileAddition> blob_file_additions;
|
||||
|
||||
// Note that here we treat flush as level 0 compaction in internal stats
|
||||
InternalStats::CompactionStats flush_stats(CompactionReason::kFlush,
|
||||
1 /* count**/);
|
||||
{
|
||||
auto write_hint = base_->storage_info()->CalculateSSTWriteHint(
|
||||
/*level=*/0, db_options_.calculate_sst_write_lifetime_hint_set);
|
||||
@@ -887,7 +889,7 @@ Status FlushJob::WriteLevel0Table() {
|
||||
ro.total_order_seek = true;
|
||||
ro.io_activity = Env::IOActivity::kFlush;
|
||||
Arena arena;
|
||||
uint64_t total_num_entries = 0, total_num_deletes = 0;
|
||||
uint64_t total_num_input_entries = 0, total_num_deletes = 0;
|
||||
uint64_t total_data_size = 0;
|
||||
size_t total_memory_usage = 0;
|
||||
uint64_t total_num_range_deletes = 0;
|
||||
@@ -922,7 +924,7 @@ Status FlushJob::WriteLevel0Table() {
|
||||
if (range_del_iter != nullptr) {
|
||||
range_del_iters.emplace_back(range_del_iter);
|
||||
}
|
||||
total_num_entries += m->NumEntries();
|
||||
total_num_input_entries += m->NumEntries();
|
||||
total_num_deletes += m->NumDeletion();
|
||||
total_data_size += m->GetDataSize();
|
||||
total_memory_usage += m->ApproximateMemoryUsage();
|
||||
@@ -934,11 +936,12 @@ Status FlushJob::WriteLevel0Table() {
|
||||
// "Write Buffer Full", should make update flush_reason_ accordingly.
|
||||
event_logger_->Log() << "job" << job_context_->job_id << "event"
|
||||
<< "flush_started" << "num_memtables" << mems_.size()
|
||||
<< "num_entries" << total_num_entries << "num_deletes"
|
||||
<< total_num_deletes << "total_data_size"
|
||||
<< total_data_size << "memory_usage"
|
||||
<< total_memory_usage << "num_range_deletes"
|
||||
<< total_num_range_deletes << "flush_reason"
|
||||
<< "total_num_input_entries" << total_num_input_entries
|
||||
<< "num_deletes" << total_num_deletes
|
||||
<< "total_data_size" << total_data_size
|
||||
<< "memory_usage" << total_memory_usage
|
||||
<< "num_range_deletes" << total_num_range_deletes
|
||||
<< "flush_reason"
|
||||
<< GetFlushReasonString(flush_reason_);
|
||||
|
||||
{
|
||||
@@ -976,7 +979,6 @@ Status FlushJob::WriteLevel0Table() {
|
||||
meta_.oldest_ancester_time = oldest_ancester_time;
|
||||
meta_.file_creation_time = current_time;
|
||||
|
||||
uint64_t num_input_entries = 0;
|
||||
uint64_t memtable_payload_bytes = 0;
|
||||
uint64_t memtable_garbage_bytes = 0;
|
||||
IOStatus io_s;
|
||||
@@ -1010,16 +1012,38 @@ Status FlushJob::WriteLevel0Table() {
|
||||
cfd_->internal_stats(), &io_s, io_tracer_,
|
||||
BlobFileCreationReason::kFlush, seqno_to_time_mapping_.get(),
|
||||
event_logger_, job_context_->job_id, &table_properties_, write_hint,
|
||||
full_history_ts_low, blob_callback_, base_, &num_input_entries,
|
||||
&memtable_payload_bytes, &memtable_garbage_bytes);
|
||||
full_history_ts_low, blob_callback_, base_, &memtable_payload_bytes,
|
||||
&memtable_garbage_bytes, &flush_stats);
|
||||
TEST_SYNC_POINT_CALLBACK("FlushJob::WriteLevel0Table:s", &s);
|
||||
// TODO: Cleanup io_status in BuildTable and table builders
|
||||
assert(!s.ok() || io_s.ok());
|
||||
io_s.PermitUncheckedError();
|
||||
if (num_input_entries != total_num_entries && s.ok()) {
|
||||
std::string msg = "Expected " + std::to_string(total_num_entries) +
|
||||
if (s.ok() && total_num_input_entries != flush_stats.num_input_records) {
|
||||
std::string msg = "Expected " +
|
||||
std::to_string(total_num_input_entries) +
|
||||
" entries in memtables, but read " +
|
||||
std::to_string(num_input_entries);
|
||||
std::to_string(flush_stats.num_input_records);
|
||||
ROCKS_LOG_WARN(db_options_.info_log, "[%s] [JOB %d] Level-0 flush %s",
|
||||
cfd_->GetName().c_str(), job_context_->job_id,
|
||||
msg.c_str());
|
||||
if (db_options_.flush_verify_memtable_count) {
|
||||
s = Status::Corruption(msg);
|
||||
}
|
||||
}
|
||||
|
||||
// Only verify on table with format collects table properties
|
||||
if (s.ok() &&
|
||||
(mutable_cf_options_.table_factory->IsInstanceOf(
|
||||
TableFactory::kBlockBasedTableName()) ||
|
||||
mutable_cf_options_.table_factory->IsInstanceOf(
|
||||
TableFactory::kPlainTableName())) &&
|
||||
flush_stats.num_output_records != table_properties_.num_entries) {
|
||||
std::string msg =
|
||||
"Number of keys in flush output SST files does not match "
|
||||
"number of keys added to the table. Expected " +
|
||||
std::to_string(flush_stats.num_output_records) + " but there are " +
|
||||
std::to_string(table_properties_.num_entries) +
|
||||
" in output SST files";
|
||||
ROCKS_LOG_WARN(db_options_.info_log, "[%s] [JOB %d] Level-0 flush %s",
|
||||
cfd_->GetName().c_str(), job_context_->job_id,
|
||||
msg.c_str());
|
||||
@@ -1085,12 +1109,10 @@ Status FlushJob::WriteLevel0Table() {
|
||||
// Piggyback FlushJobInfo on the first first flushed memtable.
|
||||
mems_[0]->SetFlushJobInfo(GetFlushJobInfo());
|
||||
|
||||
// Note that here we treat flush as level 0 compaction in internal stats
|
||||
InternalStats::CompactionStats stats(CompactionReason::kFlush, 1);
|
||||
const uint64_t micros = clock_->NowMicros() - start_micros;
|
||||
const uint64_t cpu_micros = clock_->CPUMicros() - start_cpu_micros;
|
||||
stats.micros = micros;
|
||||
stats.cpu_micros = cpu_micros;
|
||||
flush_stats.micros = micros;
|
||||
flush_stats.cpu_micros = cpu_micros;
|
||||
|
||||
ROCKS_LOG_INFO(db_options_.info_log,
|
||||
"[%s] [JOB %d] Flush lasted %" PRIu64
|
||||
@@ -1099,22 +1121,23 @@ Status FlushJob::WriteLevel0Table() {
|
||||
cpu_micros);
|
||||
|
||||
if (has_output) {
|
||||
stats.bytes_written = meta_.fd.GetFileSize();
|
||||
stats.num_output_files = 1;
|
||||
flush_stats.bytes_written = meta_.fd.GetFileSize();
|
||||
flush_stats.num_output_files = 1;
|
||||
}
|
||||
|
||||
const auto& blobs = edit_->GetBlobFileAdditions();
|
||||
for (const auto& blob : blobs) {
|
||||
stats.bytes_written_blob += blob.GetTotalBlobBytes();
|
||||
flush_stats.bytes_written_blob += blob.GetTotalBlobBytes();
|
||||
}
|
||||
|
||||
stats.num_output_files_blob = static_cast<int>(blobs.size());
|
||||
flush_stats.num_output_files_blob = static_cast<int>(blobs.size());
|
||||
|
||||
RecordTimeToHistogram(stats_, FLUSH_TIME, stats.micros);
|
||||
cfd_->internal_stats()->AddCompactionStats(0 /* level */, thread_pri_, stats);
|
||||
RecordTimeToHistogram(stats_, FLUSH_TIME, flush_stats.micros);
|
||||
cfd_->internal_stats()->AddCompactionStats(0 /* level */, thread_pri_,
|
||||
flush_stats);
|
||||
cfd_->internal_stats()->AddCFStats(
|
||||
InternalStats::BYTES_FLUSHED,
|
||||
stats.bytes_written + stats.bytes_written_blob);
|
||||
flush_stats.bytes_written + flush_stats.bytes_written_blob);
|
||||
RecordFlushIOStats();
|
||||
|
||||
return s;
|
||||
|
||||
@@ -42,6 +42,7 @@ using MinIterHeap =
|
||||
std::priority_queue<InternalIterator*, std::vector<InternalIterator*>,
|
||||
MinIterComparator>;
|
||||
|
||||
// TODO: name to TailingIterator
|
||||
/**
|
||||
* ForwardIterator is a special type of iterator that only supports Seek()
|
||||
* and Next(). It is expected to perform better than TailingIterator by
|
||||
|
||||
+15
-8
@@ -45,6 +45,8 @@ const std::map<LevelStatType, LevelStat> InternalStats::compaction_level_stats =
|
||||
{LevelStatType::RN_GB, LevelStat{"RnGB", "Rn(GB)"}},
|
||||
{LevelStatType::RNP1_GB, LevelStat{"Rnp1GB", "Rnp1(GB)"}},
|
||||
{LevelStatType::WRITE_GB, LevelStat{"WriteGB", "Write(GB)"}},
|
||||
{LevelStatType::WRITE_PRE_COMP_GB,
|
||||
LevelStat{"WPreCompGB", "WPreComp(GB)"}},
|
||||
{LevelStatType::W_NEW_GB, LevelStat{"WnewGB", "Wnew(GB)"}},
|
||||
{LevelStatType::MOVED_GB, LevelStat{"MovedGB", "Moved(GB)"}},
|
||||
{LevelStatType::WRITE_AMP, LevelStat{"WriteAmp", "W-Amp"}},
|
||||
@@ -100,19 +102,20 @@ void PrintLevelStatsHeader(char* buf, size_t len, const std::string& cf_name,
|
||||
int line_size = snprintf(
|
||||
buf + written_size, len - written_size,
|
||||
"%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s "
|
||||
"%s "
|
||||
"%s\n",
|
||||
// Note that we skip COMPACTED_FILES and merge it with Files column
|
||||
group_by.c_str(), hdr(LevelStatType::NUM_FILES),
|
||||
hdr(LevelStatType::SIZE_BYTES), hdr(LevelStatType::SCORE),
|
||||
hdr(LevelStatType::READ_GB), hdr(LevelStatType::RN_GB),
|
||||
hdr(LevelStatType::RNP1_GB), hdr(LevelStatType::WRITE_GB),
|
||||
hdr(LevelStatType::W_NEW_GB), hdr(LevelStatType::MOVED_GB),
|
||||
hdr(LevelStatType::WRITE_AMP), hdr(LevelStatType::READ_MBPS),
|
||||
hdr(LevelStatType::WRITE_MBPS), hdr(LevelStatType::COMP_SEC),
|
||||
hdr(LevelStatType::COMP_CPU_SEC), hdr(LevelStatType::COMP_COUNT),
|
||||
hdr(LevelStatType::AVG_SEC), hdr(LevelStatType::KEY_IN),
|
||||
hdr(LevelStatType::KEY_DROP), hdr(LevelStatType::R_BLOB_GB),
|
||||
hdr(LevelStatType::W_BLOB_GB));
|
||||
hdr(LevelStatType::WRITE_PRE_COMP_GB), hdr(LevelStatType::W_NEW_GB),
|
||||
hdr(LevelStatType::MOVED_GB), hdr(LevelStatType::WRITE_AMP),
|
||||
hdr(LevelStatType::READ_MBPS), hdr(LevelStatType::WRITE_MBPS),
|
||||
hdr(LevelStatType::COMP_SEC), hdr(LevelStatType::COMP_CPU_SEC),
|
||||
hdr(LevelStatType::COMP_COUNT), hdr(LevelStatType::AVG_SEC),
|
||||
hdr(LevelStatType::KEY_IN), hdr(LevelStatType::KEY_DROP),
|
||||
hdr(LevelStatType::R_BLOB_GB), hdr(LevelStatType::W_BLOB_GB));
|
||||
|
||||
written_size += line_size;
|
||||
written_size = std::min(written_size, static_cast<int>(len));
|
||||
@@ -140,6 +143,8 @@ void PrepareLevelStats(std::map<LevelStatType, double>* level_stats,
|
||||
stats.bytes_read_non_output_levels / kGB;
|
||||
(*level_stats)[LevelStatType::RNP1_GB] = stats.bytes_read_output_level / kGB;
|
||||
(*level_stats)[LevelStatType::WRITE_GB] = stats.bytes_written / kGB;
|
||||
(*level_stats)[LevelStatType::WRITE_PRE_COMP_GB] =
|
||||
stats.bytes_written_pre_comp / kGB;
|
||||
(*level_stats)[LevelStatType::W_NEW_GB] = bytes_new / kGB;
|
||||
(*level_stats)[LevelStatType::MOVED_GB] = stats.bytes_moved / kGB;
|
||||
(*level_stats)[LevelStatType::WRITE_AMP] = w_amp;
|
||||
@@ -164,12 +169,13 @@ void PrintLevelStats(char* buf, size_t len, const std::string& name,
|
||||
buf, len,
|
||||
"%4s " /* Level */
|
||||
"%6d/%-3d " /* Files */
|
||||
"%8s " /* Size */
|
||||
"%10s " /* Size */
|
||||
"%5.1f " /* Score */
|
||||
"%8.1f " /* Read(GB) */
|
||||
"%7.1f " /* Rn(GB) */
|
||||
"%8.1f " /* Rnp1(GB) */
|
||||
"%9.1f " /* Write(GB) */
|
||||
"%9.1f " /* WPreComp(GB) */
|
||||
"%8.1f " /* Wnew(GB) */
|
||||
"%9.1f " /* Moved(GB) */
|
||||
"%5.1f " /* W-Amp */
|
||||
@@ -193,6 +199,7 @@ void PrintLevelStats(char* buf, size_t len, const std::string& name,
|
||||
stat_value.at(LevelStatType::RN_GB),
|
||||
stat_value.at(LevelStatType::RNP1_GB),
|
||||
stat_value.at(LevelStatType::WRITE_GB),
|
||||
stat_value.at(LevelStatType::WRITE_PRE_COMP_GB),
|
||||
stat_value.at(LevelStatType::W_NEW_GB),
|
||||
stat_value.at(LevelStatType::MOVED_GB),
|
||||
stat_value.at(LevelStatType::WRITE_AMP),
|
||||
|
||||
+15
-1
@@ -71,6 +71,7 @@ enum class LevelStatType {
|
||||
RN_GB,
|
||||
RNP1_GB,
|
||||
WRITE_GB,
|
||||
WRITE_PRE_COMP_GB,
|
||||
W_NEW_GB,
|
||||
MOVED_GB,
|
||||
WRITE_AMP,
|
||||
@@ -179,6 +180,9 @@ class InternalStats {
|
||||
// Total number of bytes written to table files during compaction
|
||||
uint64_t bytes_written;
|
||||
|
||||
// Total number of bytes written pre-compression during compaction
|
||||
uint64_t bytes_written_pre_comp;
|
||||
|
||||
// Total number of bytes written to blob files during compaction
|
||||
uint64_t bytes_written_blob;
|
||||
|
||||
@@ -231,6 +235,7 @@ class InternalStats {
|
||||
bytes_skipped_output_level(0),
|
||||
bytes_read_blob(0),
|
||||
bytes_written(0),
|
||||
bytes_written_pre_comp(0),
|
||||
bytes_written_blob(0),
|
||||
bytes_moved(0),
|
||||
num_input_files_in_non_output_levels(0),
|
||||
@@ -258,6 +263,7 @@ class InternalStats {
|
||||
bytes_skipped_output_level(0),
|
||||
bytes_read_blob(0),
|
||||
bytes_written(0),
|
||||
bytes_written_pre_comp(0),
|
||||
bytes_written_blob(0),
|
||||
bytes_moved(0),
|
||||
num_input_files_in_non_output_levels(0),
|
||||
@@ -291,6 +297,7 @@ class InternalStats {
|
||||
bytes_skipped_output_level(c.bytes_skipped_output_level),
|
||||
bytes_read_blob(c.bytes_read_blob),
|
||||
bytes_written(c.bytes_written),
|
||||
bytes_written_pre_comp(c.bytes_written_pre_comp),
|
||||
bytes_written_blob(c.bytes_written_blob),
|
||||
bytes_moved(c.bytes_moved),
|
||||
num_input_files_in_non_output_levels(
|
||||
@@ -321,6 +328,7 @@ class InternalStats {
|
||||
bytes_skipped_output_level = c.bytes_skipped_output_level;
|
||||
bytes_read_blob = c.bytes_read_blob;
|
||||
bytes_written = c.bytes_written;
|
||||
bytes_written_pre_comp = c.bytes_written_pre_comp;
|
||||
bytes_written_blob = c.bytes_written_blob;
|
||||
bytes_moved = c.bytes_moved;
|
||||
num_input_files_in_non_output_levels =
|
||||
@@ -353,6 +361,7 @@ class InternalStats {
|
||||
this->bytes_skipped_output_level = 0;
|
||||
this->bytes_read_blob = 0;
|
||||
this->bytes_written = 0;
|
||||
this->bytes_written_pre_comp = 0;
|
||||
this->bytes_written_blob = 0;
|
||||
this->bytes_moved = 0;
|
||||
this->num_input_files_in_non_output_levels = 0;
|
||||
@@ -381,6 +390,7 @@ class InternalStats {
|
||||
this->bytes_skipped_output_level += c.bytes_skipped_output_level;
|
||||
this->bytes_read_blob += c.bytes_read_blob;
|
||||
this->bytes_written += c.bytes_written;
|
||||
this->bytes_written_pre_comp += c.bytes_written_pre_comp;
|
||||
this->bytes_written_blob += c.bytes_written_blob;
|
||||
this->bytes_moved += c.bytes_moved;
|
||||
this->num_input_files_in_non_output_levels +=
|
||||
@@ -413,6 +423,7 @@ class InternalStats {
|
||||
this->bytes_skipped_output_level -= c.bytes_skipped_output_level;
|
||||
this->bytes_read_blob -= c.bytes_read_blob;
|
||||
this->bytes_written -= c.bytes_written;
|
||||
this->bytes_written_pre_comp -= c.bytes_written_pre_comp;
|
||||
this->bytes_written_blob -= c.bytes_written_blob;
|
||||
this->bytes_moved -= c.bytes_moved;
|
||||
this->num_input_files_in_non_output_levels -=
|
||||
@@ -697,7 +708,10 @@ class InternalStats {
|
||||
// a full cache, which would force a re-scan on the next GetStats.
|
||||
std::shared_ptr<CacheEntryStatsCollector<CacheEntryRoleStats>>
|
||||
cache_entry_stats_collector_;
|
||||
// Per-ColumnFamily/level compaction stats
|
||||
|
||||
// Per-column family and level compaction statistics, including flush and file
|
||||
// ingestion. These are treated as compactions to L0 or the level where the
|
||||
// file was ingested.
|
||||
std::vector<CompactionStats> comp_stats_;
|
||||
std::vector<CompactionStats> comp_stats_by_pri_;
|
||||
CompactionStats per_key_placement_comp_stats_;
|
||||
|
||||
@@ -418,6 +418,7 @@ DECLARE_uint32(uncache_aggressiveness);
|
||||
DECLARE_int32(test_ingest_standalone_range_deletion_one_in);
|
||||
DECLARE_bool(allow_unprepared_value);
|
||||
DECLARE_string(file_temperature_age_thresholds);
|
||||
DECLARE_bool(allow_trivial_copy_when_change_temperature);
|
||||
DECLARE_uint32(commit_bypass_memtable_one_in);
|
||||
DECLARE_bool(track_and_verify_wals);
|
||||
DECLARE_bool(enable_remote_compaction);
|
||||
|
||||
@@ -536,6 +536,9 @@ DEFINE_string(file_temperature_age_thresholds, "",
|
||||
"See CompactionOptionsFIFO::file_temperature_age_thresholds. "
|
||||
"empty == unset");
|
||||
|
||||
DEFINE_bool(allow_trivial_copy_when_change_temperature, true,
|
||||
"Allow kChangeTemperature to do trivial copy");
|
||||
|
||||
static const bool FLAGS_subcompactions_dummy __attribute__((__unused__)) =
|
||||
RegisterFlagValidator(&FLAGS_subcompactions, &ValidateUint32Range);
|
||||
|
||||
|
||||
@@ -26,25 +26,50 @@ class DbStressTablePropertiesCollector : public TablePropertiesCollector {
|
||||
Status AddUserKey(const Slice& /* key */, const Slice& /* value */,
|
||||
EntryType /*type*/, SequenceNumber /*seq*/,
|
||||
uint64_t /*file_size*/) override {
|
||||
++keys_added;
|
||||
++all_calls;
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status Finish(UserCollectedProperties* /* properties */) override {
|
||||
void BlockAdd(uint64_t /* block_uncomp_bytes */,
|
||||
uint64_t /* block_compressed_bytes_fast */,
|
||||
uint64_t /* block_compressed_bytes_slow */) override {
|
||||
++blocks_added;
|
||||
++all_calls;
|
||||
}
|
||||
|
||||
Status Finish(UserCollectedProperties* properties) override {
|
||||
++all_calls;
|
||||
(*properties)["db_stress_collector_property"] =
|
||||
std::to_string(keys_added) + ";" + std::to_string(blocks_added) + ";" +
|
||||
std::to_string(all_calls);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
UserCollectedProperties GetReadableProperties() const override {
|
||||
return UserCollectedProperties{};
|
||||
UserCollectedProperties props;
|
||||
const_cast<DbStressTablePropertiesCollector*>(this)->Finish(&props);
|
||||
return props;
|
||||
}
|
||||
|
||||
const char* Name() const override {
|
||||
return "DbStressTablePropertiesCollector";
|
||||
}
|
||||
|
||||
bool NeedCompact() const override { return need_compact_; }
|
||||
bool NeedCompact() const override {
|
||||
++all_calls;
|
||||
return need_compact_;
|
||||
}
|
||||
|
||||
private:
|
||||
const bool need_compact_;
|
||||
// These are tracked to detect race conditions that would arise from RocksDB
|
||||
// invoking TablePropertiesCollector functions in an unsynchronized way, as
|
||||
// TablePropertiesCollectors are allowed (encouraged) not to be thread safe.
|
||||
size_t keys_added = 0;
|
||||
size_t blocks_added = 0;
|
||||
// Including race between BlockAdd and AddUserKey (etc.)
|
||||
mutable size_t all_calls = 0;
|
||||
};
|
||||
|
||||
// A `DbStressTablePropertiesCollectorFactory` creates
|
||||
|
||||
@@ -427,6 +427,11 @@ bool StressTest::BuildOptionsTable() {
|
||||
std::vector<std::string>{
|
||||
"{{temperature=kWarm;age=30}:{temperature=kCold;age=300}}",
|
||||
"{{temperature=kCold;age=100}}", "{}"});
|
||||
options_tbl.emplace(
|
||||
"allow_trivial_copy_when_change_temperature",
|
||||
std::vector<std::string>{
|
||||
FLAGS_allow_trivial_copy_when_change_temperature ? "true"
|
||||
: "false"});
|
||||
}
|
||||
|
||||
// NOTE: allow -1 to mean starting disabled but dynamically changing
|
||||
@@ -838,11 +843,21 @@ Status StressTest::NewTxn(WriteOptions& write_opts, ThreadState* thread,
|
||||
FLAGS_use_only_the_last_commit_time_batch_for_recovery;
|
||||
txn_options.lock_timeout = 600000; // 10 min
|
||||
txn_options.deadlock_detect = true;
|
||||
if (FLAGS_commit_bypass_memtable_one_in > 0) {
|
||||
if (FLAGS_commit_bypass_memtable_one_in > 0 &&
|
||||
thread->rand.OneIn(FLAGS_commit_bypass_memtable_one_in)) {
|
||||
assert(FLAGS_txn_write_policy == 0);
|
||||
assert(FLAGS_user_timestamp_size == 0);
|
||||
txn_options.commit_bypass_memtable =
|
||||
thread->rand.OneIn(FLAGS_commit_bypass_memtable_one_in);
|
||||
if (thread->rand.OneIn(2)) {
|
||||
txn_options.commit_bypass_memtable = true;
|
||||
}
|
||||
if (thread->rand.OneIn(2)) {
|
||||
txn_options.large_txn_commit_optimize_threshold = 1;
|
||||
}
|
||||
if (thread->rand.OneIn(2) ||
|
||||
(!txn_options.commit_bypass_memtable &&
|
||||
txn_options.large_txn_commit_optimize_threshold != 1)) {
|
||||
txn_options.large_txn_commit_optimize_byte_threshold = 1;
|
||||
}
|
||||
if (commit_bypass_memtable) {
|
||||
*commit_bypass_memtable = txn_options.commit_bypass_memtable;
|
||||
}
|
||||
@@ -4216,10 +4231,14 @@ void InitializeOptionsFromFlags(
|
||||
StringToTemperature(FLAGS_default_temperature.c_str());
|
||||
|
||||
if (!FLAGS_file_temperature_age_thresholds.empty()) {
|
||||
const std::string allowTrivialCopyBoolStr =
|
||||
FLAGS_allow_trivial_copy_when_change_temperature ? "true" : "false";
|
||||
Status s = GetColumnFamilyOptionsFromString(
|
||||
{}, options,
|
||||
"compaction_options_fifo={file_temperature_age_thresholds=" +
|
||||
FLAGS_file_temperature_age_thresholds + "}",
|
||||
FLAGS_file_temperature_age_thresholds +
|
||||
";allow_trivial_copy_when_change_temperature=" +
|
||||
allowTrivialCopyBoolStr + "}",
|
||||
&options);
|
||||
if (!s.ok()) {
|
||||
fprintf(stderr, "While setting file_temperature_age_thresholds: %s\n",
|
||||
|
||||
@@ -233,6 +233,13 @@ class NonBatchedOpsStressTest : public StressTest {
|
||||
}
|
||||
|
||||
Status s = secondary_db_->TryCatchUpWithPrimary();
|
||||
#ifndef NDEBUG
|
||||
uint64_t manifest_num = static_cast_with_check<DBImpl>(secondary_db_)
|
||||
->TEST_Current_Manifest_FileNo();
|
||||
#else
|
||||
uint64_t manifest_num = 0;
|
||||
#endif
|
||||
|
||||
if (!s.ok()) {
|
||||
VerificationAbort(shared,
|
||||
"Secondary failed to catch up to the primary");
|
||||
@@ -267,9 +274,11 @@ class NonBatchedOpsStressTest : public StressTest {
|
||||
assert(!pre_read_expected_values.empty() &&
|
||||
static_cast<size_t>(i - start) <
|
||||
pre_read_expected_values.size());
|
||||
VerifyValueRange(static_cast<int>(cf), i, options, shared, from_db,
|
||||
/* msg_prefix */ "Secondary get verification", s,
|
||||
pre_read_expected_values[i - start]);
|
||||
VerifyValueRange(
|
||||
static_cast<int>(cf), i, options, shared, from_db,
|
||||
/* msg_prefix */ "Secondary get verification, manifest: " +
|
||||
std::to_string(manifest_num),
|
||||
s, pre_read_expected_values[i - start]);
|
||||
}
|
||||
}
|
||||
} else if (method == VerificationMethod::kGetEntity) {
|
||||
|
||||
+32
-14
@@ -22,7 +22,10 @@ IOStatus CopyFile(FileSystem* fs, const std::string& source,
|
||||
Temperature src_temp_hint,
|
||||
std::unique_ptr<WritableFileWriter>& dest_writer,
|
||||
uint64_t size, bool use_fsync,
|
||||
const std::shared_ptr<IOTracer>& io_tracer) {
|
||||
const std::shared_ptr<IOTracer>& io_tracer,
|
||||
uint64_t max_read_buffer_size,
|
||||
const std::optional<IOOptions>& readIOOptions,
|
||||
const std::optional<IOOptions>& writeIOOptions) {
|
||||
FileOptions soptions;
|
||||
IOStatus io_s;
|
||||
std::unique_ptr<SequentialFileReader> src_reader;
|
||||
@@ -38,7 +41,8 @@ IOStatus CopyFile(FileSystem* fs, const std::string& source,
|
||||
|
||||
if (size == 0) {
|
||||
// default argument means copy everything
|
||||
io_s = fs->GetFileSize(source, opts, &size, nullptr);
|
||||
io_s =
|
||||
fs->GetFileSize(source, readIOOptions.value_or(opts), &size, nullptr);
|
||||
if (!io_s.ok()) {
|
||||
return io_s;
|
||||
}
|
||||
@@ -47,14 +51,23 @@ IOStatus CopyFile(FileSystem* fs, const std::string& source,
|
||||
new SequentialFileReader(std::move(srcfile), source, io_tracer));
|
||||
}
|
||||
|
||||
char buffer[4096];
|
||||
const size_t read_buffer_size = std::max(
|
||||
static_cast<size_t>(4096), static_cast<size_t>(max_read_buffer_size));
|
||||
std::unique_ptr<char[]> buffer;
|
||||
buffer.reset(new char[read_buffer_size]);
|
||||
|
||||
Env::IOPriority read_rate_limiter_priority = Env::IO_TOTAL;
|
||||
if (readIOOptions.has_value()) {
|
||||
read_rate_limiter_priority = readIOOptions.value().rate_limiter_priority;
|
||||
}
|
||||
Slice slice;
|
||||
while (size > 0) {
|
||||
size_t bytes_to_read = std::min(sizeof(buffer), static_cast<size_t>(size));
|
||||
size_t bytes_to_read = std::min(static_cast<size_t>(read_buffer_size),
|
||||
static_cast<size_t>(size));
|
||||
// TODO: rate limit copy file
|
||||
io_s = status_to_io_status(
|
||||
src_reader->Read(bytes_to_read, &slice, buffer,
|
||||
Env::IO_TOTAL /* rate_limiter_priority */));
|
||||
io_s = status_to_io_status(src_reader->Read(
|
||||
bytes_to_read, &slice, buffer.get(),
|
||||
read_rate_limiter_priority /* rate_limiter_priority */));
|
||||
if (!io_s.ok()) {
|
||||
return io_s;
|
||||
}
|
||||
@@ -65,19 +78,22 @@ IOStatus CopyFile(FileSystem* fs, const std::string& source,
|
||||
std::to_string(dest_writer->GetFileSize()));
|
||||
}
|
||||
|
||||
io_s = dest_writer->Append(opts, slice);
|
||||
io_s = dest_writer->Append(writeIOOptions.value_or(opts), slice);
|
||||
if (!io_s.ok()) {
|
||||
return io_s;
|
||||
}
|
||||
size -= slice.size();
|
||||
}
|
||||
return dest_writer->Sync(opts, use_fsync);
|
||||
return dest_writer->Sync(writeIOOptions.value_or(opts), use_fsync);
|
||||
}
|
||||
|
||||
IOStatus CopyFile(FileSystem* fs, const std::string& source,
|
||||
Temperature src_temp_hint, const std::string& destination,
|
||||
Temperature dst_temp, uint64_t size, bool use_fsync,
|
||||
const std::shared_ptr<IOTracer>& io_tracer) {
|
||||
const std::shared_ptr<IOTracer>& io_tracer,
|
||||
uint64_t max_read_buffer_size,
|
||||
const std::optional<IOOptions>& readIOOptions,
|
||||
const std::optional<IOOptions>& writeIOOptions) {
|
||||
FileOptions options;
|
||||
IOStatus io_s;
|
||||
std::unique_ptr<WritableFileWriter> dest_writer;
|
||||
@@ -96,7 +112,8 @@ IOStatus CopyFile(FileSystem* fs, const std::string& source,
|
||||
}
|
||||
|
||||
return CopyFile(fs, source, src_temp_hint, dest_writer, size, use_fsync,
|
||||
io_tracer);
|
||||
io_tracer, max_read_buffer_size, readIOOptions,
|
||||
writeIOOptions);
|
||||
}
|
||||
|
||||
// Utility function to create a file with the provided contents
|
||||
@@ -230,15 +247,16 @@ IOStatus GenerateOneFileChecksum(
|
||||
Slice slice;
|
||||
uint64_t offset = 0;
|
||||
IOOptions opts;
|
||||
io_s = reader->PrepareIOOptions(read_options, opts);
|
||||
IODebugContext dbg;
|
||||
io_s = reader->PrepareIOOptions(read_options, opts, &dbg);
|
||||
if (!io_s.ok()) {
|
||||
return io_s;
|
||||
}
|
||||
while (size > 0) {
|
||||
size_t bytes_to_read =
|
||||
static_cast<size_t>(std::min(uint64_t{readahead_size}, size));
|
||||
io_s =
|
||||
reader->Read(opts, offset, bytes_to_read, &slice, buf.get(), nullptr);
|
||||
io_s = reader->Read(opts, offset, bytes_to_read, &slice, buf.get(), nullptr,
|
||||
&dbg);
|
||||
if (!io_s.ok()) {
|
||||
return IOStatus::Corruption("file read failed with error: " +
|
||||
io_s.ToString());
|
||||
|
||||
+22
-5
@@ -24,18 +24,28 @@ IOStatus CopyFile(FileSystem* fs, const std::string& source,
|
||||
Temperature src_temp_hint,
|
||||
std::unique_ptr<WritableFileWriter>& dest_writer,
|
||||
uint64_t size, bool use_fsync,
|
||||
const std::shared_ptr<IOTracer>& io_tracer);
|
||||
const std::shared_ptr<IOTracer>& io_tracer,
|
||||
uint64_t max_read_buffer_size = 4096,
|
||||
const std::optional<IOOptions>& readIOOptions = {},
|
||||
const std::optional<IOOptions>& writeIOOptions = {});
|
||||
IOStatus CopyFile(FileSystem* fs, const std::string& source,
|
||||
Temperature src_temp_hint, const std::string& destination,
|
||||
Temperature dst_temp, uint64_t size, bool use_fsync,
|
||||
const std::shared_ptr<IOTracer>& io_tracer);
|
||||
const std::shared_ptr<IOTracer>& io_tracer,
|
||||
uint64_t max_read_buffer_size = 4096,
|
||||
const std::optional<IOOptions>& readIOOptions = {},
|
||||
const std::optional<IOOptions>& writeIOOptions = {});
|
||||
inline IOStatus CopyFile(const std::shared_ptr<FileSystem>& fs,
|
||||
const std::string& source, Temperature src_temp_hint,
|
||||
const std::string& destination, Temperature dst_temp,
|
||||
uint64_t size, bool use_fsync,
|
||||
const std::shared_ptr<IOTracer>& io_tracer) {
|
||||
const std::shared_ptr<IOTracer>& io_tracer,
|
||||
uint64_t max_read_buffer_size = 4096,
|
||||
const std::optional<IOOptions>& readIOOptions = {},
|
||||
const std::optional<IOOptions>& writeIOOptions = {}) {
|
||||
return CopyFile(fs.get(), source, src_temp_hint, destination, dst_temp, size,
|
||||
use_fsync, io_tracer);
|
||||
use_fsync, io_tracer, max_read_buffer_size, readIOOptions,
|
||||
writeIOOptions);
|
||||
}
|
||||
IOStatus CreateFile(FileSystem* fs, const std::string& destination,
|
||||
const std::string& contents, bool use_fsync);
|
||||
@@ -76,7 +86,14 @@ IOStatus GenerateOneFileChecksum(
|
||||
const ReadOptions& read_options, Statistics* stats, SystemClock* clock);
|
||||
|
||||
inline IOStatus PrepareIOFromReadOptions(const ReadOptions& ro,
|
||||
SystemClock* clock, IOOptions& opts) {
|
||||
SystemClock* clock, IOOptions& opts,
|
||||
IODebugContext* dbg = nullptr) {
|
||||
if (ro.request_id != nullptr) {
|
||||
if (dbg != nullptr && dbg->request_id == nullptr) {
|
||||
dbg->SetRequestId(ro.request_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (ro.deadline.count()) {
|
||||
std::chrono::microseconds now =
|
||||
std::chrono::microseconds(clock->NowMicros());
|
||||
|
||||
@@ -106,11 +106,14 @@ IOStatus RandomAccessFileReader::Create(
|
||||
|
||||
IOStatus RandomAccessFileReader::Read(const IOOptions& opts, uint64_t offset,
|
||||
size_t n, Slice* result, char* scratch,
|
||||
AlignedBuf* aligned_buf) const {
|
||||
AlignedBuf* aligned_buf,
|
||||
IODebugContext* dbg) const {
|
||||
(void)aligned_buf;
|
||||
const Env::IOPriority rate_limiter_priority = opts.rate_limiter_priority;
|
||||
|
||||
TEST_SYNC_POINT_CALLBACK("RandomAccessFileReader::Read", nullptr);
|
||||
TEST_SYNC_POINT_CALLBACK("RandomAccessFileReader::Read:IODebugContext",
|
||||
const_cast<void*>(static_cast<void*>(dbg)));
|
||||
|
||||
// To be paranoid: modify scratch a little bit, so in case underlying
|
||||
// FileSystem doesn't fill the buffer but return success and `scratch` returns
|
||||
@@ -175,7 +178,7 @@ IOStatus RandomAccessFileReader::Read(const IOOptions& opts, uint64_t offset,
|
||||
// the opts.timeout before calling file_->Read
|
||||
assert(!opts.timeout.count() || allowed == read_size);
|
||||
io_s = file_->Read(aligned_offset + buf.CurrentSize(), allowed, opts,
|
||||
&tmp, buf.Destination(), nullptr);
|
||||
&tmp, buf.Destination(), dbg);
|
||||
}
|
||||
if (ShouldNotifyListeners()) {
|
||||
auto finish_ts = FileOperationInfo::FinishNow();
|
||||
@@ -237,7 +240,7 @@ IOStatus RandomAccessFileReader::Read(const IOOptions& opts, uint64_t offset,
|
||||
// the opts.timeout before calling file_->Read
|
||||
assert(!opts.timeout.count() || allowed == n);
|
||||
io_s = file_->Read(offset + pos, allowed, opts, &tmp_result,
|
||||
scratch + pos, nullptr);
|
||||
scratch + pos, dbg);
|
||||
}
|
||||
if (ShouldNotifyListeners()) {
|
||||
auto finish_ts = FileOperationInfo::FinishNow();
|
||||
@@ -311,7 +314,8 @@ bool TryMerge(FSReadRequest* dest, const FSReadRequest& src) {
|
||||
IOStatus RandomAccessFileReader::MultiRead(const IOOptions& opts,
|
||||
FSReadRequest* read_reqs,
|
||||
size_t num_reqs,
|
||||
AlignedBuf* aligned_buf) const {
|
||||
AlignedBuf* aligned_buf,
|
||||
IODebugContext* dbg) const {
|
||||
(void)aligned_buf; // suppress warning of unused variable in LITE mode
|
||||
assert(num_reqs > 0);
|
||||
|
||||
@@ -420,8 +424,10 @@ IOStatus RandomAccessFileReader::MultiRead(const IOOptions& opts,
|
||||
remaining_bytes -= request_bytes;
|
||||
}
|
||||
}
|
||||
io_s = file_->MultiRead(fs_reqs, num_fs_reqs, opts,
|
||||
/*IODebugContext*=*/nullptr);
|
||||
TEST_SYNC_POINT_CALLBACK(
|
||||
"RandomAccessFileReader::MultiRead:IODebugContext",
|
||||
const_cast<void*>(static_cast<void*>(dbg)));
|
||||
io_s = file_->MultiRead(fs_reqs, num_fs_reqs, opts, dbg);
|
||||
RecordInHistogram(stats_, MULTIGET_IO_BATCH_SIZE, num_fs_reqs);
|
||||
}
|
||||
|
||||
@@ -475,18 +481,21 @@ IOStatus RandomAccessFileReader::MultiRead(const IOOptions& opts,
|
||||
}
|
||||
|
||||
IOStatus RandomAccessFileReader::PrepareIOOptions(const ReadOptions& ro,
|
||||
IOOptions& opts) const {
|
||||
IOOptions& opts,
|
||||
IODebugContext* dbg) const {
|
||||
if (clock_ != nullptr) {
|
||||
return PrepareIOFromReadOptions(ro, clock_, opts);
|
||||
return PrepareIOFromReadOptions(ro, clock_, opts, dbg);
|
||||
} else {
|
||||
return PrepareIOFromReadOptions(ro, SystemClock::Default().get(), opts);
|
||||
return PrepareIOFromReadOptions(ro, SystemClock::Default().get(), opts,
|
||||
dbg);
|
||||
}
|
||||
}
|
||||
|
||||
IOStatus RandomAccessFileReader::ReadAsync(
|
||||
FSReadRequest& req, const IOOptions& opts,
|
||||
std::function<void(FSReadRequest&, void*)> cb, void* cb_arg,
|
||||
void** io_handle, IOHandleDeleter* del_fn, AlignedBuf* aligned_buf) {
|
||||
void** io_handle, IOHandleDeleter* del_fn, AlignedBuf* aligned_buf,
|
||||
IODebugContext* dbg) {
|
||||
IOStatus s;
|
||||
// Create a callback and populate info.
|
||||
auto read_async_callback =
|
||||
@@ -532,14 +541,14 @@ IOStatus RandomAccessFileReader::ReadAsync(
|
||||
(stats_ != nullptr) ? &elapsed : nullptr, true /*overwrite*/,
|
||||
true /*delay_enabled*/);
|
||||
s = file_->ReadAsync(aligned_req, opts, read_async_callback,
|
||||
read_async_info, io_handle, del_fn, nullptr /*dbg*/);
|
||||
read_async_info, io_handle, del_fn, dbg);
|
||||
} else {
|
||||
StopWatch sw(clock_, stats_, hist_type_,
|
||||
GetFileReadHistograms(stats_, opts.io_activity),
|
||||
(stats_ != nullptr) ? &elapsed : nullptr, true /*overwrite*/,
|
||||
true /*delay_enabled*/);
|
||||
s = file_->ReadAsync(req, opts, read_async_callback, read_async_info,
|
||||
io_handle, del_fn, nullptr /*dbg*/);
|
||||
io_handle, del_fn, dbg);
|
||||
}
|
||||
RecordTick(stats_, READ_ASYNC_MICROS, elapsed);
|
||||
|
||||
|
||||
@@ -164,7 +164,8 @@ class RandomAccessFileReader {
|
||||
// the internally allocated buffer on return, and the result refers to a
|
||||
// region in aligned_buf.
|
||||
IOStatus Read(const IOOptions& opts, uint64_t offset, size_t n, Slice* result,
|
||||
char* scratch, AlignedBuf* aligned_buf) const;
|
||||
char* scratch, AlignedBuf* aligned_buf,
|
||||
IODebugContext* dbg = nullptr) const;
|
||||
|
||||
// REQUIRES:
|
||||
// num_reqs > 0, reqs do not overlap, and offsets in reqs are increasing.
|
||||
@@ -172,10 +173,12 @@ class RandomAccessFileReader {
|
||||
// In direct IO mode, aligned_buf stores the aligned buffer allocated inside
|
||||
// MultiRead, the result Slices in reqs refer to aligned_buf.
|
||||
IOStatus MultiRead(const IOOptions& opts, FSReadRequest* reqs,
|
||||
size_t num_reqs, AlignedBuf* aligned_buf) const;
|
||||
size_t num_reqs, AlignedBuf* aligned_buf,
|
||||
IODebugContext* dbg = nullptr) const;
|
||||
|
||||
IOStatus Prefetch(const IOOptions& opts, uint64_t offset, size_t n) const {
|
||||
return file_->Prefetch(offset, n, opts, nullptr);
|
||||
IOStatus Prefetch(const IOOptions& opts, uint64_t offset, size_t n,
|
||||
IODebugContext* dbg = nullptr) const {
|
||||
return file_->Prefetch(offset, n, opts, dbg);
|
||||
}
|
||||
|
||||
FSRandomAccessFile* file() { return file_.get(); }
|
||||
@@ -184,12 +187,13 @@ class RandomAccessFileReader {
|
||||
|
||||
bool use_direct_io() const { return file_->use_direct_io(); }
|
||||
|
||||
IOStatus PrepareIOOptions(const ReadOptions& ro, IOOptions& opts) const;
|
||||
IOStatus PrepareIOOptions(const ReadOptions& ro, IOOptions& opts,
|
||||
IODebugContext* dbg = nullptr) const;
|
||||
|
||||
IOStatus ReadAsync(FSReadRequest& req, const IOOptions& opts,
|
||||
std::function<void(FSReadRequest&, void*)> cb,
|
||||
void* cb_arg, void** io_handle, IOHandleDeleter* del_fn,
|
||||
AlignedBuf* aligned_buf);
|
||||
AlignedBuf* aligned_buf, IODebugContext* dbg = nullptr);
|
||||
|
||||
void ReadAsyncCallback(FSReadRequest& req, void* cb_arg);
|
||||
};
|
||||
|
||||
@@ -147,8 +147,9 @@ TEST_F(RandomAccessFileReaderTest, MultiReadDirectIO) {
|
||||
reqs.push_back(std::move(r0));
|
||||
reqs.push_back(std::move(r1));
|
||||
AlignedBuf aligned_buf;
|
||||
ASSERT_OK(
|
||||
r->MultiRead(IOOptions(), reqs.data(), reqs.size(), &aligned_buf));
|
||||
IODebugContext dbg;
|
||||
ASSERT_OK(r->MultiRead(IOOptions(), reqs.data(), reqs.size(), &aligned_buf,
|
||||
&dbg));
|
||||
|
||||
AssertResult(content, reqs);
|
||||
|
||||
@@ -192,8 +193,9 @@ TEST_F(RandomAccessFileReaderTest, MultiReadDirectIO) {
|
||||
reqs.push_back(std::move(r1));
|
||||
reqs.push_back(std::move(r2));
|
||||
AlignedBuf aligned_buf;
|
||||
ASSERT_OK(
|
||||
r->MultiRead(IOOptions(), reqs.data(), reqs.size(), &aligned_buf));
|
||||
IODebugContext dbg;
|
||||
ASSERT_OK(r->MultiRead(IOOptions(), reqs.data(), reqs.size(), &aligned_buf,
|
||||
&dbg));
|
||||
|
||||
AssertResult(content, reqs);
|
||||
|
||||
@@ -237,8 +239,9 @@ TEST_F(RandomAccessFileReaderTest, MultiReadDirectIO) {
|
||||
reqs.push_back(std::move(r1));
|
||||
reqs.push_back(std::move(r2));
|
||||
AlignedBuf aligned_buf;
|
||||
ASSERT_OK(
|
||||
r->MultiRead(IOOptions(), reqs.data(), reqs.size(), &aligned_buf));
|
||||
IODebugContext dbg;
|
||||
ASSERT_OK(r->MultiRead(IOOptions(), reqs.data(), reqs.size(), &aligned_buf,
|
||||
&dbg));
|
||||
|
||||
AssertResult(content, reqs);
|
||||
|
||||
@@ -274,8 +277,9 @@ TEST_F(RandomAccessFileReaderTest, MultiReadDirectIO) {
|
||||
reqs.push_back(std::move(r0));
|
||||
reqs.push_back(std::move(r1));
|
||||
AlignedBuf aligned_buf;
|
||||
ASSERT_OK(
|
||||
r->MultiRead(IOOptions(), reqs.data(), reqs.size(), &aligned_buf));
|
||||
IODebugContext dbg;
|
||||
ASSERT_OK(r->MultiRead(IOOptions(), reqs.data(), reqs.size(), &aligned_buf,
|
||||
&dbg));
|
||||
|
||||
AssertResult(content, reqs);
|
||||
|
||||
|
||||
@@ -115,6 +115,21 @@ struct CompactionOptionsFIFO {
|
||||
// Default: empty
|
||||
std::vector<FileTemperatureAge> file_temperature_age_thresholds{};
|
||||
|
||||
// EXPERIMENTAL
|
||||
// If true, when compaction is picked for kChangeTemperature reason,
|
||||
// allow the trivia copy of the sst file from source FileSystem to
|
||||
// destination FileSystem. If false, the changeTemperature will be
|
||||
// the non-trivial copy by iterating/appending blocks by blocks of the
|
||||
// sst file.
|
||||
bool allow_trivial_copy_when_change_temperature = false;
|
||||
|
||||
// EXPERIMENTAL
|
||||
// If 'allow_trivia_copy_op_when_change_temperature=true', the tmp buffer size
|
||||
// to copy the file from the source FileSystem to the destnation FileSystem.
|
||||
// If 'allow_trivia_copy_op_when_change_temperature=false', this field will
|
||||
// not be used. The minmum buffer size must be at least 4KiB
|
||||
uint64_t trivial_copy_buffer_size = 4096;
|
||||
|
||||
CompactionOptionsFIFO() : max_table_files_size(1 * 1024 * 1024 * 1024) {}
|
||||
CompactionOptionsFIFO(uint64_t _max_table_files_size, bool _allow_compaction)
|
||||
: max_table_files_size(_max_table_files_size),
|
||||
@@ -1106,6 +1121,8 @@ struct AdvancedColumnFamilyOptions {
|
||||
// CompactOnDeletionCollectorFactory) together with this option to compact
|
||||
// away tombstones after the memtable is flushed.
|
||||
//
|
||||
// Note that this option has no effect on tailing iterators yet.
|
||||
//
|
||||
// Default: 0 (disabled)
|
||||
// Dynamically changeable through the SetOptions() API.
|
||||
uint32_t memtable_op_scan_flush_trigger = 0;
|
||||
|
||||
+208
-2
@@ -69,6 +69,7 @@ extern "C" {
|
||||
/* Exported types */
|
||||
|
||||
typedef struct rocksdb_t rocksdb_t;
|
||||
typedef struct rocksdb_status_ptr_t rocksdb_status_ptr_t;
|
||||
typedef struct rocksdb_backup_engine_t rocksdb_backup_engine_t;
|
||||
typedef struct rocksdb_backup_engine_info_t rocksdb_backup_engine_info_t;
|
||||
typedef struct rocksdb_backup_engine_options_t rocksdb_backup_engine_options_t;
|
||||
@@ -79,6 +80,7 @@ typedef struct rocksdb_hyper_clock_cache_options_t
|
||||
rocksdb_hyper_clock_cache_options_t;
|
||||
typedef struct rocksdb_cache_t rocksdb_cache_t;
|
||||
typedef struct rocksdb_write_buffer_manager_t rocksdb_write_buffer_manager_t;
|
||||
typedef struct rocksdb_sst_file_manager_t rocksdb_sst_file_manager_t;
|
||||
typedef struct rocksdb_compactionfilter_t rocksdb_compactionfilter_t;
|
||||
typedef struct rocksdb_compactionfiltercontext_t
|
||||
rocksdb_compactionfiltercontext_t;
|
||||
@@ -141,6 +143,15 @@ typedef struct rocksdb_statistics_histogram_data_t
|
||||
rocksdb_statistics_histogram_data_t;
|
||||
typedef struct rocksdb_wait_for_compact_options_t
|
||||
rocksdb_wait_for_compact_options_t;
|
||||
typedef struct rocksdb_flushjobinfo_t rocksdb_flushjobinfo_t;
|
||||
typedef struct rocksdb_compactionjobinfo_t rocksdb_compactionjobinfo_t;
|
||||
typedef struct rocksdb_subcompactionjobinfo_t rocksdb_subcompactionjobinfo_t;
|
||||
typedef struct rocksdb_externalfileingestioninfo_t
|
||||
rocksdb_externalfileingestioninfo_t;
|
||||
typedef struct rocksdb_eventlistener_t rocksdb_eventlistener_t;
|
||||
typedef struct rocksdb_writestallinfo_t rocksdb_writestallinfo_t;
|
||||
typedef struct rocksdb_writestallcondition_t rocksdb_writestallcondition_t;
|
||||
typedef struct rocksdb_memtableinfo_t rocksdb_memtableinfo_t;
|
||||
|
||||
/* DB operations */
|
||||
|
||||
@@ -986,11 +997,22 @@ extern ROCKSDB_LIBRARY_API char* rocksdb_writebatch_wi_get_from_batch_and_db(
|
||||
rocksdb_writebatch_wi_t* wbwi, rocksdb_t* db,
|
||||
const rocksdb_readoptions_t* options, const char* key, size_t keylen,
|
||||
size_t* vallen, char** errptr);
|
||||
extern ROCKSDB_LIBRARY_API rocksdb_pinnableslice_t*
|
||||
rocksdb_writebatch_wi_get_pinned_from_batch_and_db(
|
||||
rocksdb_writebatch_wi_t* wbwi, rocksdb_t* db,
|
||||
const rocksdb_readoptions_t* options, const char* key, size_t keylen,
|
||||
char** errptr);
|
||||
extern ROCKSDB_LIBRARY_API char* rocksdb_writebatch_wi_get_from_batch_and_db_cf(
|
||||
rocksdb_writebatch_wi_t* wbwi, rocksdb_t* db,
|
||||
const rocksdb_readoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, size_t* vallen, char** errptr);
|
||||
extern ROCKSDB_LIBRARY_API rocksdb_pinnableslice_t*
|
||||
rocksdb_writebatch_wi_get_pinned_from_batch_and_db_cf(
|
||||
rocksdb_writebatch_wi_t* wbwi, rocksdb_t* db,
|
||||
const rocksdb_readoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, char** errptr);
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_write_writebatch_wi(
|
||||
rocksdb_t* db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_writebatch_wi_t* wbwi, char** errptr);
|
||||
@@ -998,13 +1020,20 @@ extern ROCKSDB_LIBRARY_API rocksdb_iterator_t*
|
||||
rocksdb_writebatch_wi_create_iterator_with_base(
|
||||
rocksdb_writebatch_wi_t* wbwi, rocksdb_iterator_t* base_iterator);
|
||||
extern ROCKSDB_LIBRARY_API rocksdb_iterator_t*
|
||||
rocksdb_writebatch_wi_create_iterator_with_base_readopts(
|
||||
rocksdb_writebatch_wi_t* wbwi, rocksdb_iterator_t* base_iterator,
|
||||
const rocksdb_readoptions_t* options);
|
||||
extern ROCKSDB_LIBRARY_API rocksdb_iterator_t*
|
||||
rocksdb_writebatch_wi_create_iterator_with_base_cf(
|
||||
rocksdb_writebatch_wi_t* wbwi, rocksdb_iterator_t* base_iterator,
|
||||
rocksdb_column_family_handle_t* cf);
|
||||
extern ROCKSDB_LIBRARY_API rocksdb_iterator_t*
|
||||
rocksdb_writebatch_wi_create_iterator_with_base_cf_readopts(
|
||||
rocksdb_writebatch_wi_t* wbwi, rocksdb_iterator_t* base_iterator,
|
||||
rocksdb_column_family_handle_t* cf, const rocksdb_readoptions_t* options);
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_wi_update_timestamps(
|
||||
rocksdb_writebatch_wi_t* wbwi, const char* ts, size_t tslen, void* state,
|
||||
size_t (*get_ts_size)(void*, uint32_t), char** errptr);
|
||||
|
||||
/* Options utils */
|
||||
|
||||
// Load the latest rocksdb options from the specified db_path.
|
||||
@@ -1126,6 +1155,137 @@ rocksdb_block_based_options_set_unpartitioned_pinning_tier(
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_options_set_write_buffer_manager(
|
||||
rocksdb_options_t* opt, rocksdb_write_buffer_manager_t* wbm);
|
||||
|
||||
/* Flush job info */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API const char* rocksdb_flushjobinfo_cf_name(
|
||||
const rocksdb_flushjobinfo_t*, size_t*);
|
||||
extern ROCKSDB_LIBRARY_API const char* rocksdb_flushjobinfo_file_path(
|
||||
const rocksdb_flushjobinfo_t*, size_t*);
|
||||
extern ROCKSDB_LIBRARY_API unsigned char
|
||||
rocksdb_flushjobinfo_triggered_writes_slowdown(const rocksdb_flushjobinfo_t*);
|
||||
extern ROCKSDB_LIBRARY_API unsigned char
|
||||
rocksdb_flushjobinfo_triggered_writes_stop(const rocksdb_flushjobinfo_t*);
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_flushjobinfo_largest_seqno(const rocksdb_flushjobinfo_t*);
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_flushjobinfo_smallest_seqno(const rocksdb_flushjobinfo_t*);
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_reset_status(
|
||||
rocksdb_status_ptr_t* status_ptr);
|
||||
|
||||
/* Compaction job info */
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_compactionjobinfo_status(
|
||||
const rocksdb_compactionjobinfo_t* info, char** errptr);
|
||||
extern ROCKSDB_LIBRARY_API const char* rocksdb_compactionjobinfo_cf_name(
|
||||
const rocksdb_compactionjobinfo_t*, size_t*);
|
||||
extern ROCKSDB_LIBRARY_API size_t
|
||||
rocksdb_compactionjobinfo_input_files_count(const rocksdb_compactionjobinfo_t*);
|
||||
extern ROCKSDB_LIBRARY_API const char* rocksdb_compactionjobinfo_input_file_at(
|
||||
const rocksdb_compactionjobinfo_t*, size_t pos, size_t*);
|
||||
extern ROCKSDB_LIBRARY_API size_t rocksdb_compactionjobinfo_output_files_count(
|
||||
const rocksdb_compactionjobinfo_t*);
|
||||
extern ROCKSDB_LIBRARY_API const char* rocksdb_compactionjobinfo_output_file_at(
|
||||
const rocksdb_compactionjobinfo_t*, size_t pos, size_t*);
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compactionjobinfo_elapsed_micros(const rocksdb_compactionjobinfo_t*);
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compactionjobinfo_num_corrupt_keys(const rocksdb_compactionjobinfo_t*);
|
||||
extern ROCKSDB_LIBRARY_API int rocksdb_compactionjobinfo_base_input_level(
|
||||
const rocksdb_compactionjobinfo_t*);
|
||||
extern ROCKSDB_LIBRARY_API int rocksdb_compactionjobinfo_output_level(
|
||||
const rocksdb_compactionjobinfo_t*);
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compactionjobinfo_input_records(const rocksdb_compactionjobinfo_t*);
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compactionjobinfo_output_records(const rocksdb_compactionjobinfo_t*);
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compactionjobinfo_total_input_bytes(const rocksdb_compactionjobinfo_t*);
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_compactionjobinfo_total_output_bytes(
|
||||
const rocksdb_compactionjobinfo_t*);
|
||||
extern ROCKSDB_LIBRARY_API uint32_t rocksdb_compactionjobinfo_compaction_reason(
|
||||
const rocksdb_compactionjobinfo_t* info);
|
||||
extern ROCKSDB_LIBRARY_API size_t rocksdb_compactionjobinfo_num_input_files(
|
||||
const rocksdb_compactionjobinfo_t* info);
|
||||
extern ROCKSDB_LIBRARY_API size_t
|
||||
rocksdb_compactionjobinfo_num_input_files_at_output_level(
|
||||
const rocksdb_compactionjobinfo_t* info);
|
||||
|
||||
/* Subcompaction job info */
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_subcompactionjobinfo_status(
|
||||
const rocksdb_subcompactionjobinfo_t*, char**);
|
||||
extern ROCKSDB_LIBRARY_API const char* rocksdb_subcompactionjobinfo_cf_name(
|
||||
const rocksdb_subcompactionjobinfo_t*, size_t*);
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_subcompactionjobinfo_thread_id(const rocksdb_subcompactionjobinfo_t*);
|
||||
extern ROCKSDB_LIBRARY_API int rocksdb_subcompactionjobinfo_base_input_level(
|
||||
const rocksdb_subcompactionjobinfo_t*);
|
||||
extern ROCKSDB_LIBRARY_API int rocksdb_subcompactionjobinfo_output_level(
|
||||
const rocksdb_subcompactionjobinfo_t*);
|
||||
|
||||
/* External file ingestion info */
|
||||
extern ROCKSDB_LIBRARY_API const char*
|
||||
rocksdb_externalfileingestioninfo_cf_name(
|
||||
const rocksdb_externalfileingestioninfo_t*, size_t*);
|
||||
extern ROCKSDB_LIBRARY_API const char*
|
||||
rocksdb_externalfileingestioninfo_internal_file_path(
|
||||
const rocksdb_externalfileingestioninfo_t*, size_t*);
|
||||
|
||||
/* External write stall info */
|
||||
extern ROCKSDB_LIBRARY_API const char* rocksdb_writestallinfo_cf_name(
|
||||
const rocksdb_writestallinfo_t*, size_t*);
|
||||
extern ROCKSDB_LIBRARY_API const rocksdb_writestallcondition_t*
|
||||
rocksdb_writestallinfo_cur(const rocksdb_writestallinfo_t*);
|
||||
extern ROCKSDB_LIBRARY_API const rocksdb_writestallcondition_t*
|
||||
rocksdb_writestallinfo_prev(const rocksdb_writestallinfo_t*);
|
||||
extern ROCKSDB_LIBRARY_API const char* rocksdb_memtableinfo_cf_name(
|
||||
const rocksdb_memtableinfo_t*, size_t*);
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_memtableinfo_first_seqno(const rocksdb_memtableinfo_t*);
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_memtableinfo_earliest_seqno(const rocksdb_memtableinfo_t*);
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_memtableinfo_num_entries(const rocksdb_memtableinfo_t*);
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_memtableinfo_num_deletes(const rocksdb_memtableinfo_t*);
|
||||
|
||||
/* Event listener */
|
||||
|
||||
typedef void (*on_flush_begin_cb)(void*, rocksdb_t*,
|
||||
const rocksdb_flushjobinfo_t*);
|
||||
typedef void (*on_flush_completed_cb)(void*, rocksdb_t*,
|
||||
const rocksdb_flushjobinfo_t*);
|
||||
typedef void (*on_compaction_begin_cb)(void*, rocksdb_t*,
|
||||
const rocksdb_compactionjobinfo_t*);
|
||||
typedef void (*on_compaction_completed_cb)(void*, rocksdb_t*,
|
||||
const rocksdb_compactionjobinfo_t*);
|
||||
typedef void (*on_subcompaction_begin_cb)(
|
||||
void*, const rocksdb_subcompactionjobinfo_t*);
|
||||
typedef void (*on_subcompaction_completed_cb)(
|
||||
void*, const rocksdb_subcompactionjobinfo_t*);
|
||||
typedef void (*on_external_file_ingested_cb)(
|
||||
void*, rocksdb_t*, const rocksdb_externalfileingestioninfo_t*);
|
||||
typedef void (*on_background_error_cb)(void*, uint32_t, rocksdb_status_ptr_t*);
|
||||
typedef void (*on_stall_conditions_changed_cb)(void*,
|
||||
const rocksdb_writestallinfo_t*);
|
||||
typedef void (*rocksdb_logger_logv_cb)(void*, uint32_t log_level, const char*);
|
||||
typedef void (*on_memtable_sealed_cb)(void*, const rocksdb_memtableinfo_t*);
|
||||
extern ROCKSDB_LIBRARY_API rocksdb_eventlistener_t*
|
||||
rocksdb_eventlistener_create(
|
||||
void* state_, void (*destructor_)(void*), on_flush_begin_cb on_flush_begin,
|
||||
on_flush_completed_cb on_flush_completed,
|
||||
on_compaction_begin_cb on_compaction_begin,
|
||||
on_compaction_completed_cb on_compaction_completed,
|
||||
on_subcompaction_begin_cb on_subcompaction_begin,
|
||||
on_subcompaction_completed_cb on_subcompaction_completed,
|
||||
on_external_file_ingested_cb on_external_file_ingested,
|
||||
on_background_error_cb on_background_error,
|
||||
on_stall_conditions_changed_cb on_stall_conditions_changed,
|
||||
on_memtable_sealed_cb on_memtable_sealed);
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_eventlistener_destroy(
|
||||
rocksdb_eventlistener_t*);
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_options_add_eventlistener(
|
||||
rocksdb_options_t*, rocksdb_eventlistener_t*);
|
||||
|
||||
/* Cuckoo table options */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API rocksdb_cuckoo_table_options_t*
|
||||
@@ -1875,7 +2035,8 @@ enum {
|
||||
rocksdb_blob_decompress_time,
|
||||
rocksdb_internal_range_del_reseek_count,
|
||||
rocksdb_block_read_cpu_time,
|
||||
rocksdb_total_metric_count = 79
|
||||
rocksdb_internal_merge_point_lookup_count,
|
||||
rocksdb_total_metric_count = 80
|
||||
};
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_set_perf_level(int);
|
||||
@@ -2225,6 +2386,51 @@ extern ROCKSDB_LIBRARY_API void rocksdb_write_buffer_manager_set_buffer_size(
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_write_buffer_manager_set_allow_stall(
|
||||
rocksdb_write_buffer_manager_t* wbm, bool new_allow_stall);
|
||||
|
||||
/* SstFileManager */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API rocksdb_sst_file_manager_t*
|
||||
rocksdb_sst_file_manager_create(rocksdb_env_t* env);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_sst_file_manager_destroy(
|
||||
rocksdb_sst_file_manager_t* sfm);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void
|
||||
rocksdb_sst_file_manager_set_max_allowed_space_usage(
|
||||
rocksdb_sst_file_manager_t* sfm, uint64_t max_allowed_space);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void
|
||||
rocksdb_sst_file_manager_set_compaction_buffer_size(
|
||||
rocksdb_sst_file_manager_t* sfm, uint64_t compaction_buffer_size);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API bool
|
||||
rocksdb_sst_file_manager_is_max_allowed_space_reached(
|
||||
rocksdb_sst_file_manager_t* sfm);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API bool
|
||||
rocksdb_sst_file_manager_is_max_allowed_space_reached_including_compactions(
|
||||
rocksdb_sst_file_manager_t* sfm);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_sst_file_manager_get_total_size(rocksdb_sst_file_manager_t* sfm);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API int64_t
|
||||
rocksdb_sst_file_manager_get_delete_rate_bytes_per_second(
|
||||
rocksdb_sst_file_manager_t* sfm);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void
|
||||
rocksdb_sst_file_manager_set_delete_rate_bytes_per_second(
|
||||
rocksdb_sst_file_manager_t* sfm, int64_t delete_rate);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API double
|
||||
rocksdb_sst_file_manager_get_max_trash_db_ratio(
|
||||
rocksdb_sst_file_manager_t* sfm);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API void rocksdb_sst_file_manager_set_max_trash_db_ratio(
|
||||
rocksdb_sst_file_manager_t* sfm, double ratio);
|
||||
|
||||
extern ROCKSDB_LIBRARY_API uint64_t
|
||||
rocksdb_sst_file_manager_get_total_trash_size(rocksdb_sst_file_manager_t* sfm);
|
||||
|
||||
/* HyperClockCache */
|
||||
|
||||
extern ROCKSDB_LIBRARY_API rocksdb_hyper_clock_cache_options_t*
|
||||
|
||||
@@ -27,6 +27,8 @@ enum CompressionType : unsigned char {
|
||||
kXpressCompression = 0x6,
|
||||
kZSTD = 0x7,
|
||||
|
||||
// TODO: add enum values for user custom compression types
|
||||
|
||||
// kDisableCompressionOption is used to disable some compression options.
|
||||
kDisableCompressionOption = 0xff,
|
||||
};
|
||||
|
||||
@@ -125,6 +125,17 @@ class ExternalTableReader {
|
||||
std::vector<std::string>* values,
|
||||
std::vector<Status>* statuses) = 0;
|
||||
|
||||
// Allocate and return the contents of the properties block. If the builder
|
||||
// supports PutPropertiesBlock(), then this must be supported. The
|
||||
// properties block should be written to the table file as is (no
|
||||
// compression or mutation of any kind), and its offset in the file
|
||||
// should be returned in file_offset.
|
||||
virtual Status GetPropertiesBlock(std::unique_ptr<char[]>* /*property_block*/,
|
||||
uint64_t* /*size*/,
|
||||
uint64_t* /*file_offset*/) {
|
||||
return Status::NotSupported();
|
||||
}
|
||||
|
||||
// Return TableProperties for the file. At a minimum, the following
|
||||
// properties need to be returned -
|
||||
// comparator_name
|
||||
@@ -179,6 +190,11 @@ class ExternalTableBuilder {
|
||||
// Finish().
|
||||
virtual uint64_t FileSize() const = 0;
|
||||
|
||||
// Write the raw properties block as is in the table file
|
||||
virtual Status PutPropertiesBlock(const Slice& /*property_block*/) {
|
||||
return Status::NotSupported();
|
||||
}
|
||||
|
||||
// As mentioned in earlier comments, the following table properties must be
|
||||
// returned at a minimum -
|
||||
// comparator_name
|
||||
@@ -253,7 +269,7 @@ class ExternalTableFactory : public Customizable {
|
||||
|
||||
// Allocate a TableFactory that wraps around an ExternalTableFactory. Use this
|
||||
// to allocate and set in ColumnFamilyOptions::table_factory.
|
||||
std::shared_ptr<TableFactory> NewExternalTableFactory(
|
||||
std::unique_ptr<TableFactory> NewExternalTableFactory(
|
||||
std::shared_ptr<ExternalTableFactory> inner_factory);
|
||||
|
||||
} // namespace ROCKSDB_NAMESPACE
|
||||
@@ -220,6 +220,8 @@ struct FileOptions : EnvOptions {
|
||||
|
||||
// A structure to pass back some debugging information from the FileSystem
|
||||
// implementation to RocksDB in case of an IO error
|
||||
// TODO(virajthakur): Update all calls to FS APIs for writes to pass in
|
||||
// IODebugContext
|
||||
struct IODebugContext {
|
||||
// file_path to be filled in by RocksDB in case of an error
|
||||
std::string file_path;
|
||||
@@ -230,8 +232,9 @@ struct IODebugContext {
|
||||
// To be set by the FileSystem implementation
|
||||
std::string msg;
|
||||
|
||||
// To be set by the underlying FileSystem implementation.
|
||||
std::string request_id;
|
||||
// To be set by the application, to allow tracing logs/metrics from user ->
|
||||
// RocksDB -> FS.
|
||||
const std::string* request_id = nullptr;
|
||||
|
||||
// In order to log required information in IO tracing for different
|
||||
// operations, Each bit in trace_data stores which corresponding info from
|
||||
@@ -255,7 +258,7 @@ struct IODebugContext {
|
||||
|
||||
// Called by underlying file system to set request_id and log request_id in
|
||||
// IOTracing.
|
||||
void SetRequestId(const std::string& _request_id) {
|
||||
void SetRequestId(const std::string* _request_id) {
|
||||
request_id = _request_id;
|
||||
trace_data |= (1 << TraceData::kRequestID);
|
||||
}
|
||||
|
||||
@@ -464,6 +464,12 @@ struct CompactionServiceJobInfo {
|
||||
std::string db_name;
|
||||
std::string db_id;
|
||||
std::string db_session_id;
|
||||
|
||||
// the id of the column family where the compaction happened.
|
||||
uint32_t cf_id;
|
||||
// the name of the column family where the compaction happened.
|
||||
std::string cf_name;
|
||||
|
||||
uint64_t job_id; // job_id is only unique within the current DB and session,
|
||||
// restart DB will reset the job_id. `db_id` and
|
||||
// `db_session_id` could help you build unique id across
|
||||
@@ -484,7 +490,8 @@ struct CompactionServiceJobInfo {
|
||||
int output_level;
|
||||
|
||||
CompactionServiceJobInfo(std::string db_name_, std::string db_id_,
|
||||
std::string db_session_id_, uint64_t job_id_,
|
||||
std::string db_session_id_, uint32_t cf_id_,
|
||||
std::string cf_name_, uint64_t job_id_,
|
||||
Env::Priority priority_,
|
||||
CompactionReason compaction_reason_,
|
||||
bool is_full_compaction_, bool is_manual_compaction_,
|
||||
@@ -493,6 +500,8 @@ struct CompactionServiceJobInfo {
|
||||
: db_name(std::move(db_name_)),
|
||||
db_id(std::move(db_id_)),
|
||||
db_session_id(std::move(db_session_id_)),
|
||||
cf_id(cf_id_),
|
||||
cf_name(std::move(cf_name_)),
|
||||
job_id(job_id_),
|
||||
priority(priority_),
|
||||
compaction_reason(compaction_reason_),
|
||||
@@ -605,7 +614,8 @@ struct DBOptions {
|
||||
// DEPRECATED: This option might be removed in a future release.
|
||||
//
|
||||
// If true, during memtable flush, RocksDB will validate total entries
|
||||
// read in flush, and compare with counter inserted into it.
|
||||
// read in flush, total entries written in the SST and compare them with
|
||||
// counter of keys added.
|
||||
//
|
||||
// The option is here to turn the feature off in case this new validation
|
||||
// feature has a bug. The option may be removed in the future once the
|
||||
@@ -2052,6 +2062,19 @@ struct ReadOptions {
|
||||
|
||||
// *** END options for RocksDB internal use only ***
|
||||
|
||||
// *** BEGIN per-request settings for internal team use only ***
|
||||
|
||||
// TODO: create a new struct for per-request options, potentially including
|
||||
// timestamps in point lookups/scans
|
||||
|
||||
// request_id is a unique id assigned by the application. It is used to allow
|
||||
// us to link file system metrics/logs to rocksDB and application logs. This
|
||||
// request_id may not be unique to each RocksDB api call - it could refer to
|
||||
// an application level request that results in multiple RocksDB api calls
|
||||
const std::string* request_id = nullptr;
|
||||
|
||||
// *** END per-request settings for internal team use only ***
|
||||
|
||||
ReadOptions() {}
|
||||
ReadOptions(bool _verify_checksums, bool _fill_cache);
|
||||
explicit ReadOptions(Env::IOActivity _io_activity);
|
||||
|
||||
@@ -516,6 +516,7 @@ enum Tickers : uint32_t {
|
||||
// Number of FIFO compactions that drop files based on different reasons
|
||||
FIFO_MAX_SIZE_COMPACTIONS,
|
||||
FIFO_TTL_COMPACTIONS,
|
||||
FIFO_CHANGE_TEMPERATURE_COMPACTIONS,
|
||||
|
||||
// Number of bytes prefetched during user initiated scan
|
||||
PREFETCH_BYTES,
|
||||
@@ -535,6 +536,12 @@ enum Tickers : uint32_t {
|
||||
FILE_READ_CORRUPTION_RETRY_COUNT,
|
||||
FILE_READ_CORRUPTION_RETRY_SUCCESS_COUNT,
|
||||
|
||||
// Counter for the number of times a WBWI is ingested into the DB. This
|
||||
// happens when IngestWriteBatchWithIndex() is used and when large
|
||||
// transaction optimization is enabled through
|
||||
// TransactionOptions::large_txn_commit_optimize_threshold.
|
||||
NUMBER_WBWI_INGEST,
|
||||
|
||||
TICKER_ENUM_MAX
|
||||
};
|
||||
|
||||
@@ -672,6 +679,9 @@ enum Histograms : uint32_t {
|
||||
// system's prefetch) from the end of SST table during block based table open
|
||||
TABLE_OPEN_PREFETCH_TAIL_READ_BYTES,
|
||||
|
||||
// Number of operations per transaction.
|
||||
NUM_OP_PER_TRANSACTION,
|
||||
|
||||
HISTOGRAM_ENUM_MAX
|
||||
};
|
||||
|
||||
|
||||
@@ -316,6 +316,8 @@ class Status {
|
||||
return Status(kInvalidArgument, kTxnNotPrepared, msg, msg2);
|
||||
}
|
||||
|
||||
static Status LockLimit() { return Status(kAborted, kLockLimit); }
|
||||
|
||||
// Returns true iff the status indicates success.
|
||||
bool ok() const {
|
||||
MarkChecked();
|
||||
|
||||
@@ -254,10 +254,12 @@ struct TransactionDBOptions {
|
||||
// for more details.
|
||||
std::vector<std::shared_ptr<SecondaryIndex>> secondary_indices;
|
||||
|
||||
// EXPERIMENTAL, SUBJECT TO CHANGE
|
||||
// Deprecated, this option has no effect and may be removed in the future.
|
||||
// Use TransactionOptions::large_txn_commit_optimize_threshold instead.
|
||||
//
|
||||
// This option is only valid for write committed. If the number of updates in
|
||||
// a transaction exceeds this threshold, then the transaction commit will skip
|
||||
// insertions into memtable as an optimization to reduce commit latency.
|
||||
// a transaction is at least this threshold, then the transaction commit will
|
||||
// skip insertions into memtable as an optimization to reduce commit latency.
|
||||
// See comment for TransactionOptions::commit_bypass_memtable for more detail.
|
||||
// Setting TransactionOptions::commit_bypass_memtable to true takes precedence
|
||||
// over this option.
|
||||
@@ -364,6 +366,22 @@ struct TransactionOptions {
|
||||
// DeleteRange, SingleDelete.
|
||||
bool write_batch_track_timestamp_size = false;
|
||||
|
||||
// The following three options enable optimizations for large transaction
|
||||
// commit to bypass memtable write.
|
||||
// - If any transaction's commit should bybass memtable write,
|
||||
// set commit_bypass_memtable to true.
|
||||
// - If only bypass memtable write for transactions with >= n operations,
|
||||
// set commit_bypass_memtable to false,
|
||||
// large_txn_commit_optimize_threshold to n, and
|
||||
// large_txn_commit_optimize_byte_threshold to 0.
|
||||
// Similarly for only optimize when a transaction's write batch size is >= n.
|
||||
// - If bypass memtable write for transactions with >= n operations or >= x
|
||||
// bytes,
|
||||
// set commit_bypass_memtable to false,
|
||||
// large_txn_commit_optimize_threshold to n, and
|
||||
// large_txn_commit_optimize_byte_threshold to x.
|
||||
//
|
||||
//
|
||||
// EXPERIMENTAL, SUBJECT TO CHANGE
|
||||
// Only supports write-committed policy. If set to true, the transaction will
|
||||
// skip memtable write and ingest into the DB directly during Commit(). This
|
||||
@@ -387,6 +405,22 @@ struct TransactionOptions {
|
||||
// can cause flush/compaction to report `num_single_del_mismatch` due to
|
||||
// consecutive SingleDeletes.
|
||||
bool commit_bypass_memtable = false;
|
||||
|
||||
// EXPERIMENTAL, SUBJECT TO CHANGE
|
||||
// When the number of updates in a transaction is at least this threshold,
|
||||
// we will enable optimizations for commiting a large transaction. See
|
||||
// comment for `commit_bypass_memtable` for more optimization detail.
|
||||
//
|
||||
// Default: 0 (disabled).
|
||||
uint32_t large_txn_commit_optimize_threshold = 0;
|
||||
|
||||
// EXPERIMENTAL, SUBJECT TO CHANGE
|
||||
// When the size of a transaction's write batch is at least this threshold,
|
||||
// we will enable optimizations for commiting a large transaction. See
|
||||
// comment for `commit_bypass_memtable` for more optimization detail.
|
||||
//
|
||||
// Default: 0 (disabled).
|
||||
uint64_t large_txn_commit_optimize_byte_threshold = 0;
|
||||
};
|
||||
|
||||
// The per-write optimizations that do not involve transactions. TransactionDB
|
||||
|
||||
@@ -236,7 +236,8 @@ class WriteBatchWithIndex : public WriteBatchBase {
|
||||
Iterator* base_iterator,
|
||||
const ReadOptions* opts = nullptr);
|
||||
// default column family
|
||||
Iterator* NewIteratorWithBase(Iterator* base_iterator);
|
||||
Iterator* NewIteratorWithBase(Iterator* base_iterator,
|
||||
const ReadOptions* opts = nullptr);
|
||||
|
||||
// Similar to DB::Get() but will only read the key from this batch.
|
||||
// If the batch does not have enough data to resolve Merge operations,
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
// 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 2
|
||||
#define ROCKSDB_PATCH 0
|
||||
#define ROCKSDB_MINOR 3
|
||||
#define ROCKSDB_PATCH 4
|
||||
|
||||
// Do not use these. We made the mistake of declaring macros starting with
|
||||
// double underscore. Now we have to live with our choice. We'll deprecate these
|
||||
|
||||
@@ -5273,6 +5273,8 @@ class TickerTypeJni {
|
||||
return -0x56;
|
||||
case ROCKSDB_NAMESPACE::Tickers::FILE_READ_CORRUPTION_RETRY_SUCCESS_COUNT:
|
||||
return -0x57;
|
||||
case ROCKSDB_NAMESPACE::Tickers::FIFO_CHANGE_TEMPERATURE_COMPACTIONS:
|
||||
return -0x58;
|
||||
case ROCKSDB_NAMESPACE::Tickers::TICKER_ENUM_MAX:
|
||||
// -0x54 is the max value at this time. Since these values are exposed
|
||||
// directly to Java clients, we'll keep the value the same till the next
|
||||
@@ -5735,6 +5737,8 @@ class TickerTypeJni {
|
||||
case -0x57:
|
||||
return ROCKSDB_NAMESPACE::Tickers::
|
||||
FILE_READ_CORRUPTION_RETRY_SUCCESS_COUNT;
|
||||
case -0x58:
|
||||
return ROCKSDB_NAMESPACE::Tickers::FIFO_CHANGE_TEMPERATURE_COMPACTIONS;
|
||||
case -0x54:
|
||||
// -0x54 is the max value at this time. Since these values are exposed
|
||||
// directly to Java clients, we'll keep the value the same till the next
|
||||
|
||||
@@ -341,6 +341,36 @@ jobjectArray Java_org_rocksdb_Transaction_multiGet__JJ_3_3B(
|
||||
statuses);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_Transaction
|
||||
* Method: multiGet
|
||||
* Signature: (JJJ[[B)[[B
|
||||
*/
|
||||
jobjectArray Java_org_rocksdb_Transaction_multiGet__JJJ_3_3B(
|
||||
JNIEnv* env, jclass /*jobj*/, jlong jhandle, jlong jread_options_handle,
|
||||
jlong jcf_handle, jobjectArray jkeys) {
|
||||
ROCKSDB_NAMESPACE::MultiGetJNIKeys keys;
|
||||
if (!keys.fromByteArrays(env, jkeys)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto* txn = reinterpret_cast<ROCKSDB_NAMESPACE::Transaction*>(jhandle);
|
||||
auto* cf_handle =
|
||||
reinterpret_cast<ROCKSDB_NAMESPACE::ColumnFamilyHandle*>(jcf_handle);
|
||||
|
||||
size_t num_keys = keys.size();
|
||||
std::vector<ROCKSDB_NAMESPACE::PinnableSlice> values(num_keys);
|
||||
std::vector<ROCKSDB_NAMESPACE::Status> statuses(num_keys);
|
||||
|
||||
txn->MultiGet(
|
||||
*reinterpret_cast<ROCKSDB_NAMESPACE::ReadOptions*>(jread_options_handle),
|
||||
cf_handle, num_keys, keys.slices().data(), values.data(), statuses.data(),
|
||||
/*sorted_input=*/false);
|
||||
|
||||
return ROCKSDB_NAMESPACE::MultiGetJNIValues::byteArrays<
|
||||
ROCKSDB_NAMESPACE::PinnableSlice>(env, values, statuses);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_Transaction
|
||||
* Method: getForUpdate
|
||||
|
||||
@@ -661,6 +661,46 @@ public class Transaction extends RocksObject {
|
||||
return Arrays.asList(multiGet(nativeHandle_, readOptions.nativeHandle_, keysArray));
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is similar to
|
||||
* {@link RocksDB#multiGetAsList} except it will
|
||||
* also read pending changes in this transaction.
|
||||
* Currently, this function will return Status::MergeInProgress if the most
|
||||
* recent write to the queried key in this batch is a Merge.
|
||||
* <p>
|
||||
* If {@link ReadOptions#snapshot()} is not set, the current version of the
|
||||
* key will be read. Calling {@link #setSnapshot()} does not affect the
|
||||
* version of the data returned.
|
||||
* <p>
|
||||
* Note that setting {@link ReadOptions#setSnapshot(Snapshot)} will affect
|
||||
* what is read from the DB but will NOT change which keys are read from this
|
||||
* transaction (the keys in this transaction do not yet belong to any snapshot
|
||||
* and will be fetched regardless).
|
||||
* <p>
|
||||
* This method uses the optimized path with support for batched reads.
|
||||
*
|
||||
* @param readOptions Read options.=
|
||||
* {@link org.rocksdb.ColumnFamilyHandle} instances.
|
||||
* @param columnFamilyHandle {@link org.rocksdb.ColumnFamilyHandle}
|
||||
* instance
|
||||
* @param keys of keys for which values need to be retrieved.
|
||||
*
|
||||
* @return Array of values, one for each key
|
||||
*
|
||||
* @throws RocksDBException thrown if error happens in underlying
|
||||
* native library.
|
||||
*/
|
||||
public List<byte[]> multiGetAsList(final ReadOptions readOptions,
|
||||
final ColumnFamilyHandle columnFamilyHandle, final List<byte[]> keys)
|
||||
throws RocksDBException {
|
||||
if (keys.isEmpty()) {
|
||||
return new ArrayList<>(0);
|
||||
}
|
||||
final byte[][] keysArray = keys.toArray(new byte[keys.size()][]);
|
||||
return Arrays.asList(multiGet(
|
||||
nativeHandle_, readOptions.nativeHandle_, columnFamilyHandle.nativeHandle_, keysArray));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read this key and ensure that this transaction will only
|
||||
* be able to be committed if this key is not written outside this
|
||||
@@ -2877,6 +2917,8 @@ public class Transaction extends RocksObject {
|
||||
final byte[][] keys, final long[] columnFamilyHandles) throws RocksDBException;
|
||||
private static native byte[][] multiGet(
|
||||
final long handle, final long readOptionsHandle, final byte[][] keys) throws RocksDBException;
|
||||
private static native byte[][] multiGet(final long nativeHandle, final long readOptionsHandle,
|
||||
final long cfHandle, final byte[][] keys) throws RocksDBException;
|
||||
private static native byte[] getForUpdate(final long handle, final long readOptionsHandle,
|
||||
final byte[] key, final int keyOffset, final int keyLength, final long columnFamilyHandle,
|
||||
final boolean exclusive, final boolean doValidate) throws RocksDBException;
|
||||
|
||||
@@ -345,6 +345,32 @@ public class TransactionTest extends AbstractTransactionTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiGetAsList() throws RocksDBException {
|
||||
final byte[] k1 = "k1".getBytes(UTF_8);
|
||||
final byte[] k2 = "k2".getBytes(UTF_8);
|
||||
final byte[] k3 = "k3".getBytes(UTF_8);
|
||||
final byte[] v1 = "v1".getBytes(UTF_8);
|
||||
final byte[] v2 = "v2".getBytes(UTF_8);
|
||||
|
||||
try (final DBContainer dbContainer = startDb();
|
||||
final ReadOptions readOptions = new ReadOptions()) {
|
||||
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
|
||||
|
||||
try (final Transaction txn = dbContainer.beginTransaction()) {
|
||||
txn.put(testCf, k1, v1);
|
||||
txn.put(testCf, k2, v2);
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
try (final Transaction txn = dbContainer.beginTransaction()) {
|
||||
final List<byte[]> result =
|
||||
txn.multiGetAsList(readOptions, testCf, Arrays.asList(k1, k2, k3));
|
||||
assertThat(result).containsExactly(v1, v2, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void name() throws RocksDBException {
|
||||
try(final DBContainer dbContainer = startDb();
|
||||
|
||||
@@ -31,7 +31,7 @@ using CacheAllocationPtr = std::unique_ptr<char[], CustomDeleter>;
|
||||
inline CacheAllocationPtr AllocateBlock(size_t size,
|
||||
MemoryAllocator* allocator) {
|
||||
if (allocator) {
|
||||
auto block = reinterpret_cast<char*>(allocator->Allocate(size));
|
||||
auto block = static_cast<char*>(allocator->Allocate(size));
|
||||
return CacheAllocationPtr(block, allocator);
|
||||
}
|
||||
return CacheAllocationPtr(new char[size]);
|
||||
|
||||
@@ -79,6 +79,10 @@ class VectorRep : public MemTableRep {
|
||||
// Advance to the first entry with a key >= target
|
||||
void Seek(const Slice& user_key, const char* memtable_key) override;
|
||||
|
||||
// Seek and do some memory validation
|
||||
Status SeekAndValidate(const Slice& internal_key, const char* memtable_key,
|
||||
bool allow_data_in_errors) override;
|
||||
|
||||
// Advance to the first entry with a key <= target
|
||||
void SeekForPrev(const Slice& user_key, const char* memtable_key) override;
|
||||
|
||||
@@ -221,6 +225,22 @@ void VectorRep::Iterator::Seek(const Slice& user_key,
|
||||
.first;
|
||||
}
|
||||
|
||||
Status VectorRep::Iterator::SeekAndValidate(const Slice& /* internal_key */,
|
||||
const char* /* memtable_key */,
|
||||
bool /* allow_data_in_errors */) {
|
||||
if (vrep_) {
|
||||
WriteLock l(&vrep_->rwlock_);
|
||||
if (bucket_->begin() == bucket_->end()) {
|
||||
// Memtable is empty
|
||||
return Status::OK();
|
||||
} else {
|
||||
return Status::NotSupported("SeekAndValidate() not implemented");
|
||||
}
|
||||
} else {
|
||||
return Status::NotSupported("SeekAndValidate() not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
// Advance to the first entry with a key <= target
|
||||
void VectorRep::Iterator::SeekForPrev(const Slice& /*user_key*/,
|
||||
const char* /*memtable_key*/) {
|
||||
|
||||
@@ -262,6 +262,8 @@ const std::vector<std::pair<Tickers, std::string>> TickersNameMap = {
|
||||
{READAHEAD_TRIMMED, "rocksdb.readahead.trimmed"},
|
||||
{FIFO_MAX_SIZE_COMPACTIONS, "rocksdb.fifo.max.size.compactions"},
|
||||
{FIFO_TTL_COMPACTIONS, "rocksdb.fifo.ttl.compactions"},
|
||||
{FIFO_CHANGE_TEMPERATURE_COMPACTIONS,
|
||||
"rocksdb.fifo.change_temperature.compactions"},
|
||||
{PREFETCH_BYTES, "rocksdb.prefetch.bytes"},
|
||||
{PREFETCH_BYTES_USEFUL, "rocksdb.prefetch.bytes.useful"},
|
||||
{PREFETCH_HITS, "rocksdb.prefetch.hits"},
|
||||
@@ -270,6 +272,7 @@ const std::vector<std::pair<Tickers, std::string>> TickersNameMap = {
|
||||
"rocksdb.file.read.corruption.retry.count"},
|
||||
{FILE_READ_CORRUPTION_RETRY_SUCCESS_COUNT,
|
||||
"rocksdb.file.read.corruption.retry.success.count"},
|
||||
{NUMBER_WBWI_INGEST, "rocksdb.number.wbwi.ingest"},
|
||||
};
|
||||
|
||||
const std::vector<std::pair<Histograms, std::string>> HistogramsNameMap = {
|
||||
@@ -341,6 +344,7 @@ const std::vector<std::pair<Histograms, std::string>> HistogramsNameMap = {
|
||||
{ASYNC_PREFETCH_ABORT_MICROS, "rocksdb.async.prefetch.abort.micros"},
|
||||
{TABLE_OPEN_PREFETCH_TAIL_READ_BYTES,
|
||||
"rocksdb.table.open.prefetch.tail.read.bytes"},
|
||||
{NUM_OP_PER_TRANSACTION, "rocksdb.num.op.per.transaction"},
|
||||
};
|
||||
|
||||
std::shared_ptr<Statistics> CreateDBStatistics() {
|
||||
|
||||
+10
-1
@@ -301,7 +301,16 @@ static std::unordered_map<std::string, OptionTypeInfo>
|
||||
OptionTypeInfo::Struct("file_temperature_age_thresholds",
|
||||
&file_temperature_age_type_info, 0,
|
||||
OptionVerificationType::kNormal,
|
||||
OptionTypeFlags::kMutable))}};
|
||||
OptionTypeFlags::kMutable))},
|
||||
{"allow_trivial_copy_when_change_temperature",
|
||||
{offsetof(struct CompactionOptionsFIFO,
|
||||
allow_trivial_copy_when_change_temperature),
|
||||
OptionType::kBoolean, OptionVerificationType::kNormal,
|
||||
OptionTypeFlags::kMutable}},
|
||||
{"trivial_copy_buffer_size",
|
||||
{offsetof(struct CompactionOptionsFIFO, trivial_copy_buffer_size),
|
||||
OptionType::kUInt64T, OptionVerificationType::kNormal,
|
||||
OptionTypeFlags::kMutable}}};
|
||||
|
||||
static std::unordered_map<std::string, OptionTypeInfo>
|
||||
universal_compaction_options_type_info = {
|
||||
|
||||
+99
-1
@@ -151,7 +151,7 @@ char* Decompress(const char* input_data, size_t input_length,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<void, decltype(CloseDecompressorFun)> compressorGuard(
|
||||
std::unique_ptr<void, decltype(CloseDecompressorFun)> decompressorGuard(
|
||||
decompressor, CloseDecompressorFun);
|
||||
|
||||
SIZE_T decompressedBufferSize = 0;
|
||||
@@ -201,6 +201,104 @@ char* Decompress(const char* input_data, size_t input_length,
|
||||
// Return the raw buffer to the caller supporting the tradition
|
||||
return outputBuffer.release();
|
||||
}
|
||||
|
||||
int64_t GetDecompressedSize(const char* input_data, size_t input_length) {
|
||||
assert(input_data != nullptr);
|
||||
|
||||
if (input_length == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
COMPRESS_ALLOCATION_ROUTINES* allocRoutinesPtr = nullptr;
|
||||
|
||||
DECOMPRESSOR_HANDLE decompressor = NULL;
|
||||
|
||||
BOOL success =
|
||||
CreateDecompressor(COMPRESS_ALGORITHM_XPRESS, // Compression Algorithm
|
||||
allocRoutinesPtr, // Optional allocation routine
|
||||
&decompressor); // Handle
|
||||
|
||||
if (!success) {
|
||||
#ifdef _DEBUG
|
||||
std::cerr << "XPRESS: Failed to create Decompressor LastError "
|
||||
<< GetLastError() << std::endl;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::unique_ptr<void, decltype(CloseDecompressorFun)> decompressorGuard(
|
||||
decompressor, CloseDecompressorFun);
|
||||
|
||||
SIZE_T decompressedBufferSize = 0;
|
||||
|
||||
success = ::Decompress(decompressor, // Compressor Handle
|
||||
const_cast<char*>(input_data), // Compressed data
|
||||
input_length, // Compressed data size
|
||||
NULL, // Buffer set to NULL
|
||||
0, // Buffer size set to 0
|
||||
&decompressedBufferSize); // Decompressed Data size
|
||||
|
||||
assert(!success);
|
||||
auto lastError = GetLastError();
|
||||
|
||||
if (lastError != ERROR_INSUFFICIENT_BUFFER) {
|
||||
#ifdef _DEBUG
|
||||
std::cerr
|
||||
<< "XPRESS: Failed to estimate decompressed buffer size LastError "
|
||||
<< lastError << std::endl;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
assert(decompressedBufferSize > 0);
|
||||
return static_cast<int64_t>(decompressedBufferSize);
|
||||
}
|
||||
|
||||
int64_t DecompressToBuffer(const char* input, size_t input_length, char* output,
|
||||
size_t output_length) {
|
||||
assert(input != nullptr);
|
||||
assert(output != nullptr);
|
||||
|
||||
if (input_length == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
COMPRESS_ALLOCATION_ROUTINES* allocRoutinesPtr = nullptr;
|
||||
|
||||
DECOMPRESSOR_HANDLE decompressor = NULL;
|
||||
|
||||
BOOL success =
|
||||
CreateDecompressor(COMPRESS_ALGORITHM_XPRESS, // Compression Algorithm
|
||||
allocRoutinesPtr, // Optional allocation routine
|
||||
&decompressor); // Handle
|
||||
|
||||
if (!success) {
|
||||
#ifdef _DEBUG
|
||||
std::cerr << "XPRESS: Failed to create Decompressor LastError "
|
||||
<< GetLastError() << std::endl;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::unique_ptr<void, decltype(CloseDecompressorFun)> decompressorGuard(
|
||||
decompressor, CloseDecompressorFun);
|
||||
|
||||
SIZE_T decompressedDataSize = 0;
|
||||
|
||||
success = ::Decompress(decompressor, const_cast<char*>(input), input_length,
|
||||
output, output_length, &decompressedDataSize);
|
||||
|
||||
if (!success) {
|
||||
#ifdef _DEBUG
|
||||
std::cerr << "XPRESS: Failed to decompress LastError " << GetLastError()
|
||||
<< std::endl;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
return static_cast<int64_t>(decompressedDataSize);
|
||||
}
|
||||
|
||||
} // namespace xpress
|
||||
} // namespace port
|
||||
} // namespace ROCKSDB_NAMESPACE
|
||||
|
||||
@@ -21,6 +21,12 @@ bool Compress(const char* input, size_t length, std::string* output);
|
||||
|
||||
char* Decompress(const char* input_data, size_t input_length,
|
||||
size_t* uncompressed_size);
|
||||
|
||||
int64_t GetDecompressedSize(const char* input, size_t input_length);
|
||||
|
||||
int64_t DecompressToBuffer(const char* input, size_t input_length, char* output,
|
||||
size_t output_length);
|
||||
|
||||
} // namespace xpress
|
||||
} // namespace port
|
||||
} // namespace ROCKSDB_NAMESPACE
|
||||
File diff suppressed because it is too large.
Load diff
@@ -83,6 +83,8 @@ class BlockBasedTableBuilder : public TableBuilder {
|
||||
|
||||
bool IsEmpty() const override;
|
||||
|
||||
uint64_t PreCompressionSize() const override;
|
||||
|
||||
// Size of the file generated so far. If invoked after a successful
|
||||
// Finish() call, returns the size of the final generated file.
|
||||
uint64_t FileSize() const override;
|
||||
@@ -118,12 +120,6 @@ class BlockBasedTableBuilder : public TableBuilder {
|
||||
// REQUIRES: `rep_->state == kBuffered`
|
||||
void EnterUnbuffered();
|
||||
|
||||
// Call block's Finish() method and then
|
||||
// - in buffered mode, buffer the uncompressed block contents.
|
||||
// - in unbuffered mode, write the compressed block contents to file.
|
||||
void WriteBlock(BlockBuilder* block, BlockHandle* handle,
|
||||
BlockType blocktype);
|
||||
|
||||
// Compress and write block content to the file.
|
||||
void WriteBlock(const Slice& block_contents, BlockHandle* handle,
|
||||
BlockType block_type);
|
||||
@@ -159,7 +155,7 @@ class BlockBasedTableBuilder : public TableBuilder {
|
||||
class BlockBasedTablePropertiesCollectorFactory;
|
||||
class BlockBasedTablePropertiesCollector;
|
||||
Rep* rep_;
|
||||
|
||||
struct WorkingAreaPair;
|
||||
struct ParallelCompressionRep;
|
||||
|
||||
// Advanced operation: flush any buffered key/value pairs to file.
|
||||
@@ -175,17 +171,13 @@ class BlockBasedTableBuilder : public TableBuilder {
|
||||
|
||||
// Get blocks from mem-table walking thread, compress them and
|
||||
// pass them to the write thread. Used in parallel compression mode only
|
||||
void BGWorkCompression(const CompressionContext& compression_ctx,
|
||||
UncompressionContext* verify_ctx);
|
||||
void BGWorkCompression(WorkingAreaPair& working_area);
|
||||
|
||||
// Given uncompressed block content, try to compress it and return result and
|
||||
// compression type
|
||||
void CompressAndVerifyBlock(const Slice& uncompressed_block_data,
|
||||
bool is_data_block,
|
||||
const CompressionContext& compression_ctx,
|
||||
UncompressionContext* verify_ctx,
|
||||
bool is_data_block, WorkingAreaPair& working_area,
|
||||
std::string* compressed_output,
|
||||
Slice* result_block_contents,
|
||||
CompressionType* result_compression_type,
|
||||
Status* out_status);
|
||||
|
||||
@@ -200,16 +192,4 @@ class BlockBasedTableBuilder : public TableBuilder {
|
||||
void StopParallelCompression();
|
||||
};
|
||||
|
||||
Slice CompressBlock(const Slice& uncompressed_data, const CompressionInfo& info,
|
||||
CompressionType* type, uint32_t format_version,
|
||||
bool do_sample, std::string* compressed_output,
|
||||
std::string* sampled_output_fast,
|
||||
std::string* sampled_output_slow);
|
||||
|
||||
#ifndef NDEBUG
|
||||
// 0 == disable the hack
|
||||
// > 0 => counter for rotating through compression types
|
||||
extern RelaxedAtomic<uint64_t> g_hack_mixed_compression_in_block_based_table;
|
||||
#endif
|
||||
|
||||
} // namespace ROCKSDB_NAMESPACE
|
||||
@@ -91,13 +91,13 @@ CacheAllocationPtr CopyBufferToHeap(MemoryAllocator* allocator, Slice& buf) {
|
||||
#define INSTANTIATE_BLOCKLIKE_TEMPLATES(T) \
|
||||
template Status BlockBasedTable::RetrieveBlock<T>( \
|
||||
FilePrefetchBuffer * prefetch_buffer, const ReadOptions& ro, \
|
||||
const BlockHandle& handle, const UncompressionDict& uncompression_dict, \
|
||||
const BlockHandle& handle, UnownedPtr<Decompressor> decomp, \
|
||||
CachableEntry<T>* out_parsed_block, GetContext* get_context, \
|
||||
BlockCacheLookupContext* lookup_context, bool for_compaction, \
|
||||
bool use_cache, bool async_read, bool use_block_cache_for_lookup) const; \
|
||||
template Status BlockBasedTable::MaybeReadBlockAndLoadToCache<T>( \
|
||||
FilePrefetchBuffer * prefetch_buffer, const ReadOptions& ro, \
|
||||
const BlockHandle& handle, const UncompressionDict& uncompression_dict, \
|
||||
const BlockHandle& handle, UnownedPtr<Decompressor> decomp, \
|
||||
bool for_compaction, CachableEntry<T>* block_entry, \
|
||||
GetContext* get_context, BlockCacheLookupContext* lookup_context, \
|
||||
BlockContents* contents, bool async_read, \
|
||||
@@ -107,7 +107,7 @@ CacheAllocationPtr CopyBufferToHeap(MemoryAllocator* allocator, Slice& buf) {
|
||||
CachableEntry<T>* out_parsed_block) const;
|
||||
|
||||
INSTANTIATE_BLOCKLIKE_TEMPLATES(ParsedFullFilterBlock);
|
||||
INSTANTIATE_BLOCKLIKE_TEMPLATES(UncompressionDict);
|
||||
INSTANTIATE_BLOCKLIKE_TEMPLATES(DecompressorDict);
|
||||
INSTANTIATE_BLOCKLIKE_TEMPLATES(Block_kData);
|
||||
INSTANTIATE_BLOCKLIKE_TEMPLATES(Block_kIndex);
|
||||
INSTANTIATE_BLOCKLIKE_TEMPLATES(Block_kFilterPartitionIndex);
|
||||
@@ -195,7 +195,7 @@ Status ReadAndParseBlockFromFile(
|
||||
const Footer& footer, const ReadOptions& options, const BlockHandle& handle,
|
||||
std::unique_ptr<TBlocklike>* result, const ImmutableOptions& ioptions,
|
||||
BlockCreateContext& create_context, bool maybe_compressed,
|
||||
const UncompressionDict& uncompression_dict,
|
||||
UnownedPtr<Decompressor> decomp,
|
||||
const PersistentCacheOptions& cache_options,
|
||||
MemoryAllocator* memory_allocator, bool for_compaction, bool async_read) {
|
||||
assert(result);
|
||||
@@ -204,8 +204,8 @@ Status ReadAndParseBlockFromFile(
|
||||
BlockFetcher block_fetcher(
|
||||
file, prefetch_buffer, footer, options, handle, &contents, ioptions,
|
||||
/*do_uncompress*/ maybe_compressed, maybe_compressed,
|
||||
TBlocklike::kBlockType, uncompression_dict, cache_options,
|
||||
memory_allocator, nullptr, for_compaction);
|
||||
TBlocklike::kBlockType, decomp, cache_options, memory_allocator, nullptr,
|
||||
for_compaction);
|
||||
Status s;
|
||||
// If prefetch_buffer is not allocated, it will fallback to synchronous
|
||||
// reading of block contents.
|
||||
@@ -683,7 +683,8 @@ Status BlockBasedTable::Open(
|
||||
// 6. [meta block: index]
|
||||
// 7. [meta block: filter]
|
||||
IOOptions opts;
|
||||
s = file->PrepareIOOptions(ro, opts);
|
||||
IODebugContext dbg;
|
||||
s = file->PrepareIOOptions(ro, opts, &dbg);
|
||||
if (s.ok()) {
|
||||
s = ReadFooterFromFile(opts, file.get(), *ioptions.fs,
|
||||
prefetch_buffer.get(), file_size, &footer,
|
||||
@@ -708,6 +709,13 @@ Status BlockBasedTable::Open(
|
||||
rep->file = std::move(file);
|
||||
rep->footer = footer;
|
||||
|
||||
// Some ancient versions (~2.5 - 2.7, format_version=1) could compress the
|
||||
// metaindex block, so we need to allow for that
|
||||
if (footer.format_version() < 2) {
|
||||
auto mgr = GetBuiltinCompressionManager(/*compression_format_version=*/1);
|
||||
rep->decompressor = mgr->GetDecompressor();
|
||||
}
|
||||
|
||||
// For fully portable/stable cache keys, we need to read the properties
|
||||
// block before setting up cache keys. TODO: consider setting up a bootstrap
|
||||
// cache key for PersistentCache to use for metaindex and properties blocks.
|
||||
@@ -738,13 +746,23 @@ Status BlockBasedTable::Open(
|
||||
return s;
|
||||
}
|
||||
|
||||
CompressionType saved_comp_type = CompressionTypeFromString(
|
||||
rep->table_properties ? rep->table_properties->compression_name
|
||||
: std::string{});
|
||||
if (saved_comp_type != kNoCompression) {
|
||||
// Includes "unrecognized" or "unspecified" case, including some old files
|
||||
// before the compression_name table property was introduced in
|
||||
// version 4.9.0
|
||||
// TODO: custom CompressionManager
|
||||
auto mgr = GetBuiltinCompressionManager(
|
||||
GetCompressFormatForVersion(footer.format_version()));
|
||||
rep->decompressor = mgr->GetDecompressorOptimizeFor(saved_comp_type);
|
||||
}
|
||||
|
||||
// Populate BlockCreateContext
|
||||
bool blocks_definitely_zstd_compressed =
|
||||
rep->table_properties && (rep->table_properties->compression_name ==
|
||||
CompressionTypeToString(kZSTD));
|
||||
rep->create_context = BlockCreateContext(
|
||||
&rep->table_options, &rep->ioptions, rep->ioptions.stats,
|
||||
blocks_definitely_zstd_compressed, block_protection_bytes_per_key,
|
||||
rep->decompressor.get(), block_protection_bytes_per_key,
|
||||
rep->internal_comparator.user_comparator(), rep->index_value_is_full,
|
||||
rep->index_has_first_key);
|
||||
|
||||
@@ -934,7 +952,8 @@ Status BlockBasedTable::PrefetchTail(
|
||||
#endif // NDEBUG
|
||||
|
||||
IOOptions opts;
|
||||
Status s = file->PrepareIOOptions(ro, opts);
|
||||
IODebugContext dbg;
|
||||
Status s = file->PrepareIOOptions(ro, opts, &dbg);
|
||||
// Try file system prefetch
|
||||
if (s.ok() && !file->use_direct_io() && !force_direct_prefetch) {
|
||||
if (!file->Prefetch(opts, prefetch_off, prefetch_len).IsNotSupported()) {
|
||||
@@ -997,9 +1016,6 @@ Status BlockBasedTable::ReadPropertiesBlock(
|
||||
"Problem reading or processing seqno-to-time mapping: %s",
|
||||
s.ToString().c_str());
|
||||
}
|
||||
rep_->blocks_maybe_compressed =
|
||||
rep_->table_properties->compression_name !=
|
||||
CompressionTypeToString(kNoCompression);
|
||||
}
|
||||
} else {
|
||||
ROCKS_LOG_ERROR(rep_->ioptions.logger,
|
||||
@@ -1239,7 +1255,10 @@ Status BlockBasedTable::PrefetchIndexAndFilterBlocks(
|
||||
}
|
||||
}
|
||||
|
||||
if (!rep_->compression_dict_handle.IsNull()) {
|
||||
// NOTE: before the fix to https://github.com/facebook/rocksdb/issues/12409, a
|
||||
// file could have a (de)compression dictionary block without a configured
|
||||
// compression, so we need to ignore the dictionary in that case.
|
||||
if (!rep_->compression_dict_handle.IsNull() && rep_->decompressor) {
|
||||
std::unique_ptr<UncompressionDictReader> uncompression_dict_reader;
|
||||
s = UncompressionDictReader::Create(
|
||||
this, ro, prefetch_buffer, use_cache, prefetch_all || pin_unpartitioned,
|
||||
@@ -1301,10 +1320,9 @@ Status BlockBasedTable::ReadMetaIndexBlock(
|
||||
Status s = ReadAndParseBlockFromFile(
|
||||
rep_->file.get(), prefetch_buffer, rep_->footer, ro,
|
||||
rep_->footer.metaindex_handle(), &metaindex, rep_->ioptions,
|
||||
rep_->create_context, true /*maybe_compressed*/,
|
||||
UncompressionDict::GetEmptyDict(), rep_->persistent_cache_options,
|
||||
GetMemoryAllocator(rep_->table_options), false /* for_compaction */,
|
||||
false /* async_read */);
|
||||
rep_->create_context, true /*maybe_compressed*/, rep_->decompressor.get(),
|
||||
rep_->persistent_cache_options, GetMemoryAllocator(rep_->table_options),
|
||||
false /* for_compaction */, false /* async_read */);
|
||||
|
||||
if (!s.ok()) {
|
||||
ROCKS_LOG_ERROR(rep_->ioptions.logger,
|
||||
@@ -1343,7 +1361,7 @@ template <typename TBlocklike>
|
||||
WithBlocklikeCheck<Status, TBlocklike> BlockBasedTable::GetDataBlockFromCache(
|
||||
const Slice& cache_key, BlockCacheInterface<TBlocklike> block_cache,
|
||||
CachableEntry<TBlocklike>* out_parsed_block, GetContext* get_context,
|
||||
const UncompressionDict* dict) const {
|
||||
UnownedPtr<Decompressor> decomp) const {
|
||||
assert(out_parsed_block);
|
||||
assert(out_parsed_block->IsEmpty());
|
||||
|
||||
@@ -1352,12 +1370,24 @@ WithBlocklikeCheck<Status, TBlocklike> BlockBasedTable::GetDataBlockFromCache(
|
||||
|
||||
// Lookup uncompressed cache first
|
||||
if (block_cache) {
|
||||
BlockCreateContext create_ctx = rep_->create_context;
|
||||
create_ctx.dict = dict;
|
||||
assert(!cache_key.empty());
|
||||
auto cache_handle = block_cache.LookupFull(
|
||||
cache_key, &create_ctx, GetCachePriority<TBlocklike>(), statistics,
|
||||
rep_->ioptions.lowest_used_cache_tier);
|
||||
typename BlockCacheInterface<TBlocklike>::TypedHandle* cache_handle;
|
||||
if (decomp.get() != rep_->decompressor.get() && decomp) {
|
||||
// `decomp` must be a dictionary-aware decompressor, which is only
|
||||
// available in the block cache (so that dictionaries can be evicted
|
||||
// from memory) and can't live in the table reader.
|
||||
// NOTE: inefficient BlockCreateContext copy for dict-aware decompressor
|
||||
// (see TODO in block_cache.h)
|
||||
BlockCreateContext create_ctx = rep_->create_context;
|
||||
create_ctx.decompressor = decomp.get();
|
||||
cache_handle = block_cache.LookupFull(
|
||||
cache_key, &create_ctx, GetCachePriority<TBlocklike>(), statistics,
|
||||
rep_->ioptions.lowest_used_cache_tier);
|
||||
} else {
|
||||
cache_handle = block_cache.LookupFull(
|
||||
cache_key, &rep_->create_context, GetCachePriority<TBlocklike>(),
|
||||
statistics, rep_->ioptions.lowest_used_cache_tier);
|
||||
}
|
||||
|
||||
// Avoid updating metrics here if the handle is not complete yet. This
|
||||
// happens with MultiGet and secondary cache. So update the metrics only
|
||||
@@ -1387,10 +1417,9 @@ WithBlocklikeCheck<Status, TBlocklike> BlockBasedTable::PutDataBlockToCache(
|
||||
CachableEntry<TBlocklike>* out_parsed_block,
|
||||
BlockContents&& uncompressed_block_contents,
|
||||
BlockContents&& compressed_block_contents, CompressionType block_comp_type,
|
||||
const UncompressionDict& uncompression_dict,
|
||||
MemoryAllocator* memory_allocator, GetContext* get_context) const {
|
||||
UnownedPtr<Decompressor> decomp, MemoryAllocator* memory_allocator,
|
||||
GetContext* get_context) const {
|
||||
const ImmutableOptions& ioptions = rep_->ioptions;
|
||||
const uint32_t format_version = rep_->table_options.format_version;
|
||||
assert(out_parsed_block);
|
||||
assert(out_parsed_block->IsEmpty());
|
||||
|
||||
@@ -1402,12 +1431,10 @@ WithBlocklikeCheck<Status, TBlocklike> BlockBasedTable::PutDataBlockToCache(
|
||||
uncompressed_block_contents.data.empty()) {
|
||||
assert(compressed_block_contents.data.data());
|
||||
// Retrieve the uncompressed contents into a new buffer
|
||||
UncompressionContext context(block_comp_type);
|
||||
UncompressionInfo info(context, uncompression_dict, block_comp_type);
|
||||
s = UncompressBlockData(info, compressed_block_contents.data.data(),
|
||||
compressed_block_contents.data.size(),
|
||||
&uncompressed_block_contents, format_version,
|
||||
ioptions, memory_allocator);
|
||||
s = DecompressBlockData(
|
||||
compressed_block_contents.data.data(),
|
||||
compressed_block_contents.data.size(), block_comp_type, *decomp,
|
||||
&uncompressed_block_contents, ioptions, memory_allocator);
|
||||
if (!s.ok()) {
|
||||
return s;
|
||||
}
|
||||
@@ -1520,15 +1547,18 @@ Status BlockBasedTable::LookupAndPinBlocksInCache(
|
||||
assert(block_cache);
|
||||
|
||||
Status s;
|
||||
CachableEntry<UncompressionDict> uncompression_dict;
|
||||
CachableEntry<DecompressorDict> cached_dict;
|
||||
if (rep_->uncompression_dict_reader) {
|
||||
s = rep_->uncompression_dict_reader->GetOrReadUncompressionDictionary(
|
||||
/* prefetch_buffer= */ nullptr, ro,
|
||||
/* get_context= */ nullptr, /* lookup_context= */ nullptr,
|
||||
&uncompression_dict);
|
||||
&cached_dict);
|
||||
if (!s.ok()) {
|
||||
return s;
|
||||
}
|
||||
if (!cached_dict.GetValue()) {
|
||||
return Status::Corruption("Success but no dictionary read");
|
||||
}
|
||||
}
|
||||
|
||||
// Do the lookup.
|
||||
@@ -1537,14 +1567,20 @@ Status BlockBasedTable::LookupAndPinBlocksInCache(
|
||||
|
||||
Statistics* statistics = rep_->ioptions.statistics.get();
|
||||
|
||||
BlockCreateContext create_ctx = rep_->create_context;
|
||||
create_ctx.dict = uncompression_dict.GetValue()
|
||||
? uncompression_dict.GetValue()
|
||||
: &UncompressionDict::GetEmptyDict();
|
||||
|
||||
auto cache_handle =
|
||||
block_cache.LookupFull(key, &create_ctx, GetCachePriority<TBlocklike>(),
|
||||
statistics, rep_->ioptions.lowest_used_cache_tier);
|
||||
typename BlockCacheInterface<TBlocklike>::TypedHandle* cache_handle;
|
||||
if (cached_dict.GetValue()) {
|
||||
// NOTE: inefficient BlockCreateContext copy for dict-aware decompressor
|
||||
// (see TODO in block_cache.h)
|
||||
BlockCreateContext create_ctx = rep_->create_context;
|
||||
create_ctx.decompressor = cached_dict.GetValue()->decompressor_.get();
|
||||
cache_handle = block_cache.LookupFull(
|
||||
key, &create_ctx, GetCachePriority<TBlocklike>(), statistics,
|
||||
rep_->ioptions.lowest_used_cache_tier);
|
||||
} else {
|
||||
cache_handle = block_cache.LookupFull(
|
||||
key, &rep_->create_context, GetCachePriority<TBlocklike>(), statistics,
|
||||
rep_->ioptions.lowest_used_cache_tier);
|
||||
}
|
||||
|
||||
if (!cache_handle) {
|
||||
UpdateCacheMissMetrics(TBlocklike::kBlockType, /* get_context = */ nullptr);
|
||||
@@ -1573,7 +1609,7 @@ template <typename TBlocklike>
|
||||
WithBlocklikeCheck<Status, TBlocklike>
|
||||
BlockBasedTable::MaybeReadBlockAndLoadToCache(
|
||||
FilePrefetchBuffer* prefetch_buffer, const ReadOptions& ro,
|
||||
const BlockHandle& handle, const UncompressionDict& uncompression_dict,
|
||||
const BlockHandle& handle, UnownedPtr<Decompressor> decomp,
|
||||
bool for_compaction, CachableEntry<TBlocklike>* out_parsed_block,
|
||||
GetContext* get_context, BlockCacheLookupContext* lookup_context,
|
||||
BlockContents* contents, bool async_read,
|
||||
@@ -1597,7 +1633,7 @@ BlockBasedTable::MaybeReadBlockAndLoadToCache(
|
||||
if (!contents) {
|
||||
if (use_block_cache_for_lookup) {
|
||||
s = GetDataBlockFromCache(key, block_cache, out_parsed_block,
|
||||
get_context, &uncompression_dict);
|
||||
get_context, decomp);
|
||||
// Value could still be null at this point, so check the cache handle
|
||||
// and update the read pattern for prefetching
|
||||
if (out_parsed_block->GetValue() ||
|
||||
@@ -1627,7 +1663,7 @@ BlockBasedTable::MaybeReadBlockAndLoadToCache(
|
||||
const bool maybe_compressed =
|
||||
TBlocklike::kBlockType != BlockType::kFilter &&
|
||||
TBlocklike::kBlockType != BlockType::kCompressionDictionary &&
|
||||
rep_->blocks_maybe_compressed;
|
||||
rep_->decompressor;
|
||||
// This flag, if true, tells BlockFetcher to return the uncompressed
|
||||
// block when ReadBlockContents() is called.
|
||||
const bool do_uncompress = maybe_compressed;
|
||||
@@ -1651,8 +1687,7 @@ BlockBasedTable::MaybeReadBlockAndLoadToCache(
|
||||
BlockFetcher block_fetcher(
|
||||
rep_->file.get(), prefetch_buffer, rep_->footer, ro, handle,
|
||||
&tmp_contents, rep_->ioptions, do_uncompress, maybe_compressed,
|
||||
TBlocklike::kBlockType, uncompression_dict,
|
||||
rep_->persistent_cache_options,
|
||||
TBlocklike::kBlockType, decomp, rep_->persistent_cache_options,
|
||||
GetMemoryAllocator(rep_->table_options),
|
||||
/*allocator=*/nullptr);
|
||||
|
||||
@@ -1667,7 +1702,7 @@ BlockBasedTable::MaybeReadBlockAndLoadToCache(
|
||||
s = block_fetcher.ReadBlockContents();
|
||||
}
|
||||
|
||||
contents_comp_type = block_fetcher.get_compression_type();
|
||||
contents_comp_type = block_fetcher.compression_type();
|
||||
if (get_context) {
|
||||
switch (TBlocklike::kBlockType) {
|
||||
case BlockType::kIndex:
|
||||
@@ -1699,7 +1734,7 @@ BlockBasedTable::MaybeReadBlockAndLoadToCache(
|
||||
// block in block_fetcher
|
||||
s = PutDataBlockToCache(
|
||||
key, block_cache, out_parsed_block, std::move(uncomp_contents),
|
||||
std::move(comp_contents), contents_comp_type, uncompression_dict,
|
||||
std::move(comp_contents), contents_comp_type, decomp,
|
||||
GetMemoryAllocator(rep_->table_options), get_context);
|
||||
}
|
||||
} else {
|
||||
@@ -1715,7 +1750,7 @@ BlockBasedTable::MaybeReadBlockAndLoadToCache(
|
||||
// the block to the cache.
|
||||
s = PutDataBlockToCache(
|
||||
key, block_cache, out_parsed_block, std::move(uncomp_contents),
|
||||
std::move(comp_contents), contents_comp_type, uncompression_dict,
|
||||
std::move(comp_contents), contents_comp_type, decomp,
|
||||
GetMemoryAllocator(rep_->table_options), get_context);
|
||||
}
|
||||
}
|
||||
@@ -1830,7 +1865,7 @@ void BlockBasedTable::FinishTraceRecord(
|
||||
template <typename TBlocklike /*, auto*/>
|
||||
WithBlocklikeCheck<Status, TBlocklike> BlockBasedTable::RetrieveBlock(
|
||||
FilePrefetchBuffer* prefetch_buffer, const ReadOptions& ro,
|
||||
const BlockHandle& handle, const UncompressionDict& uncompression_dict,
|
||||
const BlockHandle& handle, UnownedPtr<Decompressor> decomp,
|
||||
CachableEntry<TBlocklike>* out_parsed_block, GetContext* get_context,
|
||||
BlockCacheLookupContext* lookup_context, bool for_compaction,
|
||||
bool use_cache, bool async_read, bool use_block_cache_for_lookup) const {
|
||||
@@ -1840,8 +1875,8 @@ WithBlocklikeCheck<Status, TBlocklike> BlockBasedTable::RetrieveBlock(
|
||||
Status s;
|
||||
if (use_cache) {
|
||||
s = MaybeReadBlockAndLoadToCache(
|
||||
prefetch_buffer, ro, handle, uncompression_dict, for_compaction,
|
||||
out_parsed_block, get_context, lookup_context,
|
||||
prefetch_buffer, ro, handle, decomp, for_compaction, out_parsed_block,
|
||||
get_context, lookup_context,
|
||||
/*contents=*/nullptr, async_read, use_block_cache_for_lookup);
|
||||
|
||||
if (!s.ok()) {
|
||||
@@ -1865,7 +1900,7 @@ WithBlocklikeCheck<Status, TBlocklike> BlockBasedTable::RetrieveBlock(
|
||||
const bool maybe_compressed =
|
||||
TBlocklike::kBlockType != BlockType::kFilter &&
|
||||
TBlocklike::kBlockType != BlockType::kCompressionDictionary &&
|
||||
rep_->blocks_maybe_compressed;
|
||||
rep_->decompressor;
|
||||
std::unique_ptr<TBlocklike> block;
|
||||
|
||||
{
|
||||
@@ -1874,9 +1909,9 @@ WithBlocklikeCheck<Status, TBlocklike> BlockBasedTable::RetrieveBlock(
|
||||
StopWatch sw(rep_->ioptions.clock, rep_->ioptions.stats, histogram);
|
||||
s = ReadAndParseBlockFromFile(
|
||||
rep_->file.get(), prefetch_buffer, rep_->footer, ro, handle, &block,
|
||||
rep_->ioptions, rep_->create_context, maybe_compressed,
|
||||
uncompression_dict, rep_->persistent_cache_options,
|
||||
GetMemoryAllocator(rep_->table_options), for_compaction, async_read);
|
||||
rep_->ioptions, rep_->create_context, maybe_compressed, decomp,
|
||||
rep_->persistent_cache_options, GetMemoryAllocator(rep_->table_options),
|
||||
for_compaction, async_read);
|
||||
|
||||
if (get_context) {
|
||||
switch (TBlocklike::kBlockType) {
|
||||
@@ -2558,8 +2593,8 @@ Status BlockBasedTable::VerifyChecksumInBlocks(
|
||||
BlockFetcher block_fetcher(
|
||||
rep_->file.get(), &prefetch_buffer, rep_->footer, read_options, handle,
|
||||
&contents, rep_->ioptions, false /* decompress */,
|
||||
false /*maybe_compressed*/, BlockType::kData,
|
||||
UncompressionDict::GetEmptyDict(), rep_->persistent_cache_options);
|
||||
false /*maybe_compressed*/, BlockType::kData, nullptr /*decompressor*/,
|
||||
rep_->persistent_cache_options);
|
||||
s = block_fetcher.ReadBlockContents();
|
||||
if (!s.ok()) {
|
||||
break;
|
||||
@@ -2648,12 +2683,12 @@ Status BlockBasedTable::VerifyChecksumInMetaBlocks(
|
||||
// if it was checked on open.
|
||||
} else {
|
||||
// FIXME? Need to verify checksums of index and filter partitions?
|
||||
s = BlockFetcher(
|
||||
rep_->file.get(), nullptr /* prefetch buffer */, rep_->footer,
|
||||
read_options, handle, &contents, rep_->ioptions,
|
||||
false /* decompress */, false /*maybe_compressed*/,
|
||||
GetBlockTypeForMetaBlockByName(meta_block_name),
|
||||
UncompressionDict::GetEmptyDict(), rep_->persistent_cache_options)
|
||||
s = BlockFetcher(rep_->file.get(), nullptr /* prefetch buffer */,
|
||||
rep_->footer, read_options, handle, &contents,
|
||||
rep_->ioptions, false /* decompress */,
|
||||
false /*maybe_compressed*/,
|
||||
GetBlockTypeForMetaBlockByName(meta_block_name),
|
||||
nullptr /*decompressor*/, rep_->persistent_cache_options)
|
||||
.ReadBlockContents();
|
||||
}
|
||||
if (!s.ok()) {
|
||||
@@ -3033,7 +3068,7 @@ Status BlockBasedTable::DumpTable(WritableFile* out_file) {
|
||||
|
||||
// Output compression dictionary
|
||||
if (rep_->uncompression_dict_reader) {
|
||||
CachableEntry<UncompressionDict> uncompression_dict;
|
||||
CachableEntry<DecompressorDict> uncompression_dict;
|
||||
s = rep_->uncompression_dict_reader->GetOrReadUncompressionDictionary(
|
||||
nullptr /* prefetch_buffer */, ro, nullptr /* get_context */,
|
||||
nullptr /* lookup_context */, &uncompression_dict);
|
||||
|
||||
@@ -364,7 +364,7 @@ class BlockBasedTable : public TableReader {
|
||||
template <typename TBlocklike>
|
||||
WithBlocklikeCheck<Status, TBlocklike> MaybeReadBlockAndLoadToCache(
|
||||
FilePrefetchBuffer* prefetch_buffer, const ReadOptions& ro,
|
||||
const BlockHandle& handle, const UncompressionDict& uncompression_dict,
|
||||
const BlockHandle& handle, UnownedPtr<Decompressor> decomp,
|
||||
bool for_compaction, CachableEntry<TBlocklike>* block_entry,
|
||||
GetContext* get_context, BlockCacheLookupContext* lookup_context,
|
||||
BlockContents* contents, bool async_read,
|
||||
@@ -376,7 +376,7 @@ class BlockBasedTable : public TableReader {
|
||||
template <typename TBlocklike>
|
||||
WithBlocklikeCheck<Status, TBlocklike> RetrieveBlock(
|
||||
FilePrefetchBuffer* prefetch_buffer, const ReadOptions& ro,
|
||||
const BlockHandle& handle, const UncompressionDict& uncompression_dict,
|
||||
const BlockHandle& handle, UnownedPtr<Decompressor> decomp,
|
||||
CachableEntry<TBlocklike>* block_entry, GetContext* get_context,
|
||||
BlockCacheLookupContext* lookup_context, bool for_compaction,
|
||||
bool use_cache, bool async_read, bool use_block_cache_for_lookup) const;
|
||||
@@ -397,7 +397,7 @@ class BlockBasedTable : public TableReader {
|
||||
const MultiGetRange* batch,
|
||||
const autovector<BlockHandle, MultiGetContext::MAX_BATCH_SIZE>* handles,
|
||||
Status* statuses, CachableEntry<Block_kData>* results, char* scratch,
|
||||
const UncompressionDict& uncompression_dict, bool use_fs_scratch);
|
||||
UnownedPtr<Decompressor> decomp, bool use_fs_scratch);
|
||||
|
||||
// Get the iterator from the index reader.
|
||||
//
|
||||
@@ -429,7 +429,7 @@ class BlockBasedTable : public TableReader {
|
||||
WithBlocklikeCheck<Status, TBlocklike> GetDataBlockFromCache(
|
||||
const Slice& cache_key, BlockCacheInterface<TBlocklike> block_cache,
|
||||
CachableEntry<TBlocklike>* block, GetContext* get_context,
|
||||
const UncompressionDict* dict) const;
|
||||
UnownedPtr<Decompressor> decomp) const;
|
||||
|
||||
// Put a maybe compressed block to the corresponding block caches.
|
||||
// This method will perform decompression against block_contents if needed
|
||||
@@ -447,8 +447,7 @@ class BlockBasedTable : public TableReader {
|
||||
CachableEntry<TBlocklike>* cached_block,
|
||||
BlockContents&& uncompressed_block_contents,
|
||||
BlockContents&& compressed_block_contents,
|
||||
CompressionType block_comp_type,
|
||||
const UncompressionDict& uncompression_dict,
|
||||
CompressionType block_comp_type, UnownedPtr<Decompressor> decomp,
|
||||
MemoryAllocator* memory_allocator, GetContext* get_context) const;
|
||||
|
||||
// Calls (*handle_result)(arg, ...) repeatedly, starting with the entry found
|
||||
@@ -650,9 +649,11 @@ struct BlockBasedTable::Rep {
|
||||
Slice min_timestamp;
|
||||
Slice max_timestamp;
|
||||
|
||||
// If false, blocks in this file are definitely all uncompressed. Knowing this
|
||||
// before reading individual blocks enables certain optimizations.
|
||||
bool blocks_maybe_compressed = true;
|
||||
// If blocks might be compressed, refers to a decompressor that can decompress
|
||||
// them. (nullptr -> no blocks compressed) However, if (data) blocks are
|
||||
// dictionary compressed, a dictionary-aware decompressor is needed, which
|
||||
// might live in the block cache.
|
||||
std::shared_ptr<Decompressor> decompressor;
|
||||
|
||||
// These describe how index is encoded.
|
||||
bool index_has_first_key = false;
|
||||
|
||||
@@ -60,34 +60,33 @@ TBlockIter* BlockBasedTable::NewDataBlockIterator(
|
||||
}
|
||||
|
||||
CachableEntry<Block> block;
|
||||
if (rep_->uncompression_dict_reader && block_type == BlockType::kData) {
|
||||
CachableEntry<UncompressionDict> uncompression_dict;
|
||||
// For async scans, don't use the prefetch buffer since an async prefetch
|
||||
// might already be under way and this would invalidate it. Also, the
|
||||
// uncompression dict is typically at the end of the file and would
|
||||
// most likely break the sequentiality of the access pattern.
|
||||
// Same is with auto_readahead_size. It iterates over index to lookup for
|
||||
// data blocks. And this could break the the sequentiality of the access
|
||||
// pattern.
|
||||
s = rep_->uncompression_dict_reader->GetOrReadUncompressionDictionary(
|
||||
((ro.async_io || ro.auto_readahead_size) ? nullptr : prefetch_buffer),
|
||||
ro, get_context, lookup_context, &uncompression_dict);
|
||||
if (!s.ok()) {
|
||||
iter->Invalidate(s);
|
||||
return iter;
|
||||
{
|
||||
CachableEntry<DecompressorDict> dict;
|
||||
Decompressor* decomp = rep_->decompressor.get();
|
||||
if (rep_->uncompression_dict_reader && block_type == BlockType::kData) {
|
||||
// For async scans, don't use the prefetch buffer since an async prefetch
|
||||
// might already be under way and this would invalidate it. Also, the
|
||||
// uncompression dict is typically at the end of the file and would
|
||||
// most likely break the sequentiality of the access pattern.
|
||||
// Same is with auto_readahead_size. It iterates over index to lookup for
|
||||
// data blocks. And this could break the the sequentiality of the access
|
||||
// pattern.
|
||||
s = rep_->uncompression_dict_reader->GetOrReadUncompressionDictionary(
|
||||
((ro.async_io || ro.auto_readahead_size) ? nullptr : prefetch_buffer),
|
||||
ro, get_context, lookup_context, &dict);
|
||||
if (!s.ok()) {
|
||||
iter->Invalidate(s);
|
||||
return iter;
|
||||
}
|
||||
assert(dict.GetValue());
|
||||
if (dict.GetValue()) {
|
||||
decomp = dict.GetValue()->decompressor_.get();
|
||||
}
|
||||
}
|
||||
const UncompressionDict& dict = uncompression_dict.GetValue()
|
||||
? *uncompression_dict.GetValue()
|
||||
: UncompressionDict::GetEmptyDict();
|
||||
s = RetrieveBlock(
|
||||
prefetch_buffer, ro, handle, dict, &block.As<IterBlocklike>(),
|
||||
prefetch_buffer, ro, handle, decomp, &block.As<IterBlocklike>(),
|
||||
get_context, lookup_context, for_compaction,
|
||||
/* use_cache */ true, async_read, use_block_cache_for_lookup);
|
||||
} else {
|
||||
s = RetrieveBlock(
|
||||
prefetch_buffer, ro, handle, UncompressionDict::GetEmptyDict(),
|
||||
&block.As<IterBlocklike>(), get_context, lookup_context, for_compaction,
|
||||
/* use_cache */ true, async_read, use_block_cache_for_lookup);
|
||||
}
|
||||
|
||||
if (s.IsTryAgain() && async_read) {
|
||||
|
||||
@@ -33,7 +33,7 @@ DEFINE_SYNC_AND_ASYNC(void, BlockBasedTable::RetrieveMultipleBlocks)
|
||||
(const ReadOptions& options, const MultiGetRange* batch,
|
||||
const autovector<BlockHandle, MultiGetContext::MAX_BATCH_SIZE>* handles,
|
||||
Status* statuses, CachableEntry<Block_kData>* results, char* scratch,
|
||||
const UncompressionDict& uncompression_dict, bool use_fs_scratch) const {
|
||||
UnownedPtr<Decompressor> decomp, bool use_fs_scratch) const {
|
||||
RandomAccessFileReader* file = rep_->file.get();
|
||||
const Footer& footer = rep_->footer;
|
||||
const ImmutableOptions& ioptions = rep_->ioptions;
|
||||
@@ -51,7 +51,7 @@ DEFINE_SYNC_AND_ASYNC(void, BlockBasedTable::RetrieveMultipleBlocks)
|
||||
|
||||
// XXX: use_cache=true means double cache query?
|
||||
statuses[idx_in_batch] = RetrieveBlock(
|
||||
nullptr, options, handle, uncompression_dict,
|
||||
nullptr, options, handle, decomp,
|
||||
&results[idx_in_batch].As<Block_kData>(), mget_iter->get_context,
|
||||
/* lookup_context */ nullptr,
|
||||
/* for_compaction */ false, /* use_cache */ true,
|
||||
@@ -138,17 +138,18 @@ DEFINE_SYNC_AND_ASYNC(void, BlockBasedTable::RetrieveMultipleBlocks)
|
||||
AlignedBuf direct_io_buf;
|
||||
{
|
||||
IOOptions opts;
|
||||
IOStatus s = file->PrepareIOOptions(options, opts);
|
||||
IODebugContext dbg;
|
||||
IOStatus s = file->PrepareIOOptions(options, opts, &dbg);
|
||||
if (s.ok()) {
|
||||
#if defined(WITH_COROUTINES)
|
||||
if (file->use_direct_io()) {
|
||||
#endif // WITH_COROUTINES
|
||||
s = file->MultiRead(opts, &read_reqs[0], read_reqs.size(),
|
||||
&direct_io_buf);
|
||||
&direct_io_buf, &dbg);
|
||||
#if defined(WITH_COROUTINES)
|
||||
} else {
|
||||
co_await batch->context()->reader().MultiReadAsync(
|
||||
file, opts, &read_reqs[0], read_reqs.size(), &direct_io_buf);
|
||||
file, opts, &read_reqs[0], read_reqs.size(), &direct_io_buf, &dbg);
|
||||
}
|
||||
#endif // WITH_COROUTINES
|
||||
}
|
||||
@@ -240,10 +241,11 @@ DEFINE_SYNC_AND_ASYNC(void, BlockBasedTable::RetrieveMultipleBlocks)
|
||||
// its not a memory mapped file
|
||||
Slice result;
|
||||
IOOptions opts;
|
||||
IOStatus io_s = file->PrepareIOOptions(options, opts);
|
||||
IODebugContext dbg;
|
||||
IOStatus io_s = file->PrepareIOOptions(options, opts, &dbg);
|
||||
opts.verify_and_reconstruct_read = true;
|
||||
io_s = file->Read(opts, handle.offset(), BlockSizeWithTrailer(handle),
|
||||
&result, const_cast<char*>(data), nullptr);
|
||||
&result, const_cast<char*>(data), nullptr, &dbg);
|
||||
if (io_s.ok()) {
|
||||
assert(result.data() == data);
|
||||
assert(result.size() == BlockSizeWithTrailer(handle));
|
||||
@@ -298,7 +300,7 @@ DEFINE_SYNC_AND_ASYNC(void, BlockBasedTable::RetrieveMultipleBlocks)
|
||||
// necessary. Since we're passing the serialized block contents, it
|
||||
// will avoid looking up the block cache
|
||||
s = MaybeReadBlockAndLoadToCache(
|
||||
nullptr, options, handle, uncompression_dict,
|
||||
nullptr, options, handle, decomp,
|
||||
/*for_compaction=*/false, block_entry, mget_iter->get_context,
|
||||
/*lookup_context=*/nullptr, &serialized_block,
|
||||
/*async_read=*/false, /*use_block_cache_for_lookup=*/true);
|
||||
@@ -320,11 +322,9 @@ DEFINE_SYNC_AND_ASYNC(void, BlockBasedTable::RetrieveMultipleBlocks)
|
||||
GetBlockCompressionType(serialized_block);
|
||||
BlockContents contents;
|
||||
if (compression_type != kNoCompression) {
|
||||
UncompressionContext context(compression_type);
|
||||
UncompressionInfo info(context, uncompression_dict, compression_type);
|
||||
s = UncompressSerializedBlock(
|
||||
info, req.result.data() + req_offset, handle.size(), &contents,
|
||||
footer.format_version(), rep_->ioptions, memory_allocator);
|
||||
s = DecompressSerializedBlock(
|
||||
req.result.data() + req_offset, handle.size(), compression_type,
|
||||
*decomp, &contents, rep_->ioptions, memory_allocator);
|
||||
} else {
|
||||
// There are two cases here:
|
||||
// 1) caller uses the shared buffer (scratch or direct io buffer);
|
||||
@@ -421,10 +421,10 @@ DEFINE_SYNC_AND_ASYNC(void, BlockBasedTable::MultiGet)
|
||||
{
|
||||
MultiGetRange data_block_range(sst_file_range, sst_file_range.begin(),
|
||||
sst_file_range.end());
|
||||
CachableEntry<UncompressionDict> uncompression_dict;
|
||||
Status uncompression_dict_status;
|
||||
uncompression_dict_status.PermitUncheckedError();
|
||||
bool uncompression_dict_inited = false;
|
||||
CachableEntry<DecompressorDict> dict;
|
||||
Status dict_status;
|
||||
dict_status.PermitUncheckedError();
|
||||
bool dict_inited = false;
|
||||
size_t total_len = 0;
|
||||
|
||||
// GetContext for any key will do, as the stats will be aggregated
|
||||
@@ -466,26 +466,26 @@ DEFINE_SYNC_AND_ASYNC(void, BlockBasedTable::MultiGet)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!uncompression_dict_inited && rep_->uncompression_dict_reader) {
|
||||
uncompression_dict_status =
|
||||
rep_->uncompression_dict_reader
|
||||
->GetOrReadUncompressionDictionary(
|
||||
nullptr /* prefetch_buffer */, read_options,
|
||||
get_context, &metadata_lookup_context,
|
||||
&uncompression_dict);
|
||||
uncompression_dict_inited = true;
|
||||
if (!dict_inited && rep_->uncompression_dict_reader) {
|
||||
dict_status = rep_->uncompression_dict_reader
|
||||
->GetOrReadUncompressionDictionary(
|
||||
nullptr /* prefetch_buffer */, read_options,
|
||||
get_context, &metadata_lookup_context, &dict);
|
||||
dict_inited = true;
|
||||
}
|
||||
|
||||
if (!uncompression_dict_status.ok()) {
|
||||
assert(!uncompression_dict_status.IsNotFound());
|
||||
*(miter->s) = uncompression_dict_status;
|
||||
if (!dict_status.ok()) {
|
||||
assert(!dict_status.IsNotFound());
|
||||
*(miter->s) = dict_status;
|
||||
data_block_range.SkipKey(miter);
|
||||
sst_file_range.SkipKey(miter);
|
||||
continue;
|
||||
} else {
|
||||
assert(!dict_inited || dict.GetValue() != nullptr);
|
||||
}
|
||||
if (dict.GetValue()) {
|
||||
create_ctx.decompressor = dict.GetValue()->decompressor_.get();
|
||||
}
|
||||
create_ctx.dict = uncompression_dict.GetValue()
|
||||
? uncompression_dict.GetValue()
|
||||
: &UncompressionDict::GetEmptyDict();
|
||||
|
||||
if (v.handle.offset() == prev_offset) {
|
||||
// This key can reuse the previous block (later on).
|
||||
@@ -565,11 +565,8 @@ DEFINE_SYNC_AND_ASYNC(void, BlockBasedTable::MultiGet)
|
||||
if (total_len) {
|
||||
char* scratch = nullptr;
|
||||
bool use_fs_scratch = false;
|
||||
const UncompressionDict& dict = uncompression_dict.GetValue()
|
||||
? *uncompression_dict.GetValue()
|
||||
: UncompressionDict::GetEmptyDict();
|
||||
assert(uncompression_dict_inited || !rep_->uncompression_dict_reader);
|
||||
assert(uncompression_dict_status.ok());
|
||||
assert(dict_inited || !rep_->uncompression_dict_reader);
|
||||
assert(dict_status.ok());
|
||||
|
||||
if (!rep_->file->use_direct_io()) {
|
||||
if (CheckFSFeatureSupport(rep_->ioptions.fs.get(),
|
||||
@@ -589,7 +586,7 @@ DEFINE_SYNC_AND_ASYNC(void, BlockBasedTable::MultiGet)
|
||||
// 3. If blocks are compressed and no compressed block cache, use
|
||||
// stack buf
|
||||
if (!use_fs_scratch && !rep_->file->use_direct_io() &&
|
||||
rep_->blocks_maybe_compressed) {
|
||||
rep_->decompressor) {
|
||||
if (total_len <= kMultiGetReadStackBufSize) {
|
||||
scratch = stack_buf;
|
||||
} else {
|
||||
@@ -599,7 +596,10 @@ DEFINE_SYNC_AND_ASYNC(void, BlockBasedTable::MultiGet)
|
||||
}
|
||||
CO_AWAIT(RetrieveMultipleBlocks)
|
||||
(read_options, &data_block_range, &block_handles, &statuses[0],
|
||||
&results[0], scratch, dict, use_fs_scratch);
|
||||
&results[0], scratch,
|
||||
dict.GetValue() ? dict.GetValue()->decompressor_.get()
|
||||
: rep_->decompressor.get(),
|
||||
use_fs_scratch);
|
||||
if (get_context) {
|
||||
++(get_context->get_context_stats_.num_sst_read);
|
||||
}
|
||||
|
||||
@@ -190,6 +190,8 @@ class BlockBasedTableReaderBaseTest : public testing::Test {
|
||||
|
||||
if (status) {
|
||||
*status = s;
|
||||
} else {
|
||||
ASSERT_OK(s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,10 +52,10 @@ void BlockCreateContext::Create(
|
||||
table_options->filter_policy.get(), std::move(block)));
|
||||
}
|
||||
|
||||
void BlockCreateContext::Create(std::unique_ptr<UncompressionDict>* parsed_out,
|
||||
void BlockCreateContext::Create(std::unique_ptr<DecompressorDict>* parsed_out,
|
||||
BlockContents&& block) {
|
||||
parsed_out->reset(new UncompressionDict(
|
||||
block.data, std::move(block.allocation), using_zstd));
|
||||
parsed_out->reset(new DecompressorDict(
|
||||
block.data, std::move(block.allocation), *decompressor));
|
||||
}
|
||||
|
||||
namespace {
|
||||
@@ -69,7 +69,7 @@ const std::array<const Cache::CacheItemHelper*,
|
||||
BlockCacheInterface<ParsedFullFilterBlock>::GetFullHelper(),
|
||||
BlockCacheInterface<Block_kFilterPartitionIndex>::GetFullHelper(),
|
||||
nullptr, // kProperties
|
||||
BlockCacheInterface<UncompressionDict>::GetFullHelper(),
|
||||
BlockCacheInterface<DecompressorDict>::GetFullHelper(),
|
||||
BlockCacheInterface<Block_kRangeDeletion>::GetFullHelper(),
|
||||
nullptr, // kHashIndexPrefixes
|
||||
nullptr, // kHashIndexMetadata
|
||||
@@ -86,7 +86,7 @@ const std::array<const Cache::CacheItemHelper*,
|
||||
BlockCacheInterface<ParsedFullFilterBlock>::GetBasicHelper(),
|
||||
BlockCacheInterface<Block_kFilterPartitionIndex>::GetBasicHelper(),
|
||||
nullptr, // kProperties
|
||||
BlockCacheInterface<UncompressionDict>::GetBasicHelper(),
|
||||
BlockCacheInterface<DecompressorDict>::GetBasicHelper(),
|
||||
BlockCacheInterface<Block_kRangeDeletion>::GetBasicHelper(),
|
||||
nullptr, // kHashIndexPrefixes
|
||||
nullptr, // kHashIndexMetadata
|
||||
|
||||
@@ -71,15 +71,16 @@ struct BlockCreateContext : public Cache::CreateContext {
|
||||
BlockCreateContext() {}
|
||||
BlockCreateContext(const BlockBasedTableOptions* _table_options,
|
||||
const ImmutableOptions* _ioptions, Statistics* _statistics,
|
||||
bool _using_zstd, uint8_t _protection_bytes_per_key,
|
||||
Decompressor* _decompressor,
|
||||
uint8_t _protection_bytes_per_key,
|
||||
const Comparator* _raw_ucmp,
|
||||
bool _index_value_is_full = false,
|
||||
bool _index_has_first_key = false)
|
||||
: table_options(_table_options),
|
||||
ioptions(_ioptions),
|
||||
statistics(_statistics),
|
||||
decompressor(_decompressor),
|
||||
raw_ucmp(_raw_ucmp),
|
||||
using_zstd(_using_zstd),
|
||||
protection_bytes_per_key(_protection_bytes_per_key),
|
||||
index_value_is_full(_index_value_is_full),
|
||||
index_has_first_key(_index_has_first_key) {}
|
||||
@@ -87,10 +88,9 @@ struct BlockCreateContext : public Cache::CreateContext {
|
||||
const BlockBasedTableOptions* table_options = nullptr;
|
||||
const ImmutableOptions* ioptions = nullptr;
|
||||
Statistics* statistics = nullptr;
|
||||
// TODO: refactor to avoid copying BlockCreateContext for dict in block cache
|
||||
Decompressor* decompressor = nullptr;
|
||||
const Comparator* raw_ucmp = nullptr;
|
||||
const UncompressionDict* dict = nullptr;
|
||||
uint32_t format_version;
|
||||
bool using_zstd = false;
|
||||
uint8_t protection_bytes_per_key = 0;
|
||||
bool index_value_is_full;
|
||||
bool index_has_first_key;
|
||||
@@ -102,12 +102,10 @@ struct BlockCreateContext : public Cache::CreateContext {
|
||||
CompressionType type, MemoryAllocator* alloc) {
|
||||
BlockContents uncompressed_block_contents;
|
||||
if (type != CompressionType::kNoCompression) {
|
||||
assert(dict != nullptr);
|
||||
UncompressionContext context(type);
|
||||
UncompressionInfo info(context, *dict, type);
|
||||
Status s = UncompressBlockData(
|
||||
info, data.data(), data.size(), &uncompressed_block_contents,
|
||||
table_options->format_version, *ioptions, alloc);
|
||||
assert(decompressor != nullptr);
|
||||
Status s =
|
||||
DecompressBlockData(data.data(), data.size(), type, *decompressor,
|
||||
&uncompressed_block_contents, *ioptions, alloc);
|
||||
if (!s.ok()) {
|
||||
parsed_out->reset();
|
||||
return;
|
||||
@@ -130,7 +128,7 @@ struct BlockCreateContext : public Cache::CreateContext {
|
||||
BlockContents&& block);
|
||||
void Create(std::unique_ptr<ParsedFullFilterBlock>* parsed_out,
|
||||
BlockContents&& block);
|
||||
void Create(std::unique_ptr<UncompressionDict>* parsed_out,
|
||||
void Create(std::unique_ptr<DecompressorDict>* parsed_out,
|
||||
BlockContents&& block);
|
||||
};
|
||||
|
||||
|
||||
@@ -39,7 +39,8 @@ void BlockPrefetcher::PrefetchIfNeeded(
|
||||
return;
|
||||
}
|
||||
IOOptions opts;
|
||||
Status s = rep->file->PrepareIOOptions(read_options, opts);
|
||||
IODebugContext dbg;
|
||||
Status s = rep->file->PrepareIOOptions(read_options, opts, &dbg);
|
||||
if (!s.ok()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -833,6 +833,19 @@ class BlockPerKVChecksumTest : public DBTestBase {
|
||||
}
|
||||
};
|
||||
|
||||
namespace {
|
||||
const BlockBasedTableOptions *kTableOptions() {
|
||||
static BlockBasedTableOptions opts{};
|
||||
return &opts;
|
||||
}
|
||||
Decompressor *kDecompressor() {
|
||||
static auto mgr = GetBuiltinCompressionManager(
|
||||
GetCompressFormatForVersion(kTableOptions()->format_version));
|
||||
static auto decomp = mgr->GetDecompressor();
|
||||
return decomp.get();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST_F(BlockPerKVChecksumTest, EmptyBlock) {
|
||||
// Tests that empty block code path is not broken by per kv checksum.
|
||||
BlockBuilder builder(
|
||||
@@ -845,14 +858,11 @@ TEST_F(BlockPerKVChecksumTest, EmptyBlock) {
|
||||
|
||||
std::unique_ptr<Block_kData> data_block;
|
||||
Options options = Options();
|
||||
BlockBasedTableOptions tbo;
|
||||
uint8_t protection_bytes_per_key = 8;
|
||||
BlockCreateContext create_context{&tbo,
|
||||
nullptr,
|
||||
nullptr /* statistics */,
|
||||
false /* using_zstd */,
|
||||
protection_bytes_per_key,
|
||||
options.comparator};
|
||||
BlockCreateContext create_context{
|
||||
kTableOptions(), nullptr,
|
||||
nullptr /* statistics */, kDecompressor(),
|
||||
protection_bytes_per_key, options.comparator};
|
||||
create_context.Create(&data_block, std::move(contents));
|
||||
std::unique_ptr<DataBlockIter> biter{data_block->NewDataIterator(
|
||||
options.comparator, kDisableGlobalSequenceNumber)};
|
||||
@@ -885,14 +895,10 @@ TEST_F(BlockPerKVChecksumTest, InitializeProtectionInfo) {
|
||||
// Make sure that the checksum construction code path does not break
|
||||
// when the block is itself already corrupted.
|
||||
Options options = Options();
|
||||
BlockBasedTableOptions tbo;
|
||||
uint8_t protection_bytes_per_key = 8;
|
||||
BlockCreateContext create_context{&tbo,
|
||||
nullptr /* ioptions */,
|
||||
nullptr /* statistics */,
|
||||
false /* using_zstd */,
|
||||
protection_bytes_per_key,
|
||||
options.comparator};
|
||||
BlockCreateContext create_context{
|
||||
kTableOptions(), nullptr /* ioptions */, nullptr /* statistics */,
|
||||
kDecompressor(), protection_bytes_per_key, options.comparator};
|
||||
|
||||
{
|
||||
std::string invalid_content = "1";
|
||||
@@ -950,20 +956,19 @@ TEST_F(BlockPerKVChecksumTest, ApproximateMemory) {
|
||||
};
|
||||
|
||||
Options options = Options();
|
||||
BlockBasedTableOptions tbo;
|
||||
uint8_t protection_bytes_per_key = 8;
|
||||
BlockCreateContext with_checksum_create_context{
|
||||
&tbo,
|
||||
kTableOptions(),
|
||||
nullptr /* ioptions */,
|
||||
nullptr /* statistics */,
|
||||
false /* using_zstd */,
|
||||
kDecompressor(),
|
||||
protection_bytes_per_key,
|
||||
options.comparator,
|
||||
true /* index_value_is_full */};
|
||||
BlockCreateContext create_context{&tbo,
|
||||
BlockCreateContext create_context{kTableOptions(),
|
||||
nullptr /* ioptions */,
|
||||
nullptr /* statistics */,
|
||||
false /* using_zstd */,
|
||||
kDecompressor(),
|
||||
0,
|
||||
options.comparator,
|
||||
true /* index_value_is_full */};
|
||||
@@ -1054,13 +1059,9 @@ class DataBlockKVChecksumTest
|
||||
std::unique_ptr<Block_kData> GenerateDataBlock(
|
||||
std::vector<std::string> &keys, std::vector<std::string> &values,
|
||||
int num_record) {
|
||||
BlockBasedTableOptions tbo;
|
||||
BlockCreateContext create_context{&tbo,
|
||||
nullptr /* statistics */,
|
||||
nullptr /* ioptions */,
|
||||
false /* using_zstd */,
|
||||
GetChecksumLen(),
|
||||
Options().comparator};
|
||||
BlockCreateContext create_context{
|
||||
kTableOptions(), nullptr /* statistics */, nullptr /* ioptions */,
|
||||
kDecompressor(), GetChecksumLen(), Options().comparator};
|
||||
builder_ = std::make_unique<BlockBuilder>(
|
||||
static_cast<int>(GetRestartInterval()),
|
||||
GetUseDeltaEncoding() /* use_delta_encoding */,
|
||||
@@ -1181,13 +1182,12 @@ class IndexBlockKVChecksumTest
|
||||
std::vector<BlockHandle> &block_handles,
|
||||
std::vector<std::string> &first_keys, int num_record) {
|
||||
Options options = Options();
|
||||
BlockBasedTableOptions tbo;
|
||||
uint8_t protection_bytes_per_key = GetChecksumLen();
|
||||
BlockCreateContext create_context{
|
||||
&tbo,
|
||||
kTableOptions(),
|
||||
nullptr /* ioptions */,
|
||||
nullptr /* statistics */,
|
||||
false /* _using_zstd */,
|
||||
kDecompressor(),
|
||||
protection_bytes_per_key,
|
||||
options.comparator,
|
||||
!UseValueDeltaEncoding() /* value_is_full */,
|
||||
@@ -1324,14 +1324,10 @@ class MetaIndexBlockKVChecksumTest
|
||||
std::vector<std::string> &keys, std::vector<std::string> &values,
|
||||
int num_record) {
|
||||
Options options = Options();
|
||||
BlockBasedTableOptions tbo;
|
||||
uint8_t protection_bytes_per_key = GetChecksumLen();
|
||||
BlockCreateContext create_context{&tbo,
|
||||
nullptr /* ioptions */,
|
||||
nullptr /* statistics */,
|
||||
false /* using_zstd */,
|
||||
protection_bytes_per_key,
|
||||
options.comparator};
|
||||
BlockCreateContext create_context{
|
||||
kTableOptions(), nullptr /* ioptions */, nullptr /* statistics */,
|
||||
kDecompressor(), protection_bytes_per_key, options.comparator};
|
||||
builder_ =
|
||||
std::make_unique<BlockBuilder>(static_cast<int>(GetRestartInterval()));
|
||||
// add a bunch of records to a block
|
||||
@@ -1359,14 +1355,10 @@ INSTANTIATE_TEST_CASE_P(P, MetaIndexBlockKVChecksumTest,
|
||||
|
||||
TEST_P(MetaIndexBlockKVChecksumTest, ChecksumConstructionAndVerification) {
|
||||
Options options = Options();
|
||||
BlockBasedTableOptions tbo;
|
||||
uint8_t protection_bytes_per_key = GetChecksumLen();
|
||||
BlockCreateContext create_context{&tbo,
|
||||
nullptr /* ioptions */,
|
||||
nullptr /* statistics */,
|
||||
false /* using_zstd */,
|
||||
protection_bytes_per_key,
|
||||
options.comparator};
|
||||
BlockCreateContext create_context{
|
||||
kTableOptions(), nullptr /* ioptions */, nullptr /* statistics */,
|
||||
kDecompressor(), protection_bytes_per_key, options.comparator};
|
||||
std::vector<int> num_restart_intervals = {1, 16};
|
||||
for (const auto num_restart_interval : num_restart_intervals) {
|
||||
const int kNumRecords = num_restart_interval * GetRestartInterval();
|
||||
|
||||
@@ -30,8 +30,7 @@ Status FilterBlockReaderCommon<TBlocklike>::ReadFilterBlock(
|
||||
|
||||
const Status s = table->RetrieveBlock(
|
||||
prefetch_buffer, read_options, rep->filter_handle,
|
||||
UncompressionDict::GetEmptyDict(), filter_block, get_context,
|
||||
lookup_context,
|
||||
/* decomp */ nullptr, filter_block, get_context, lookup_context,
|
||||
/* for_compaction */ false, use_cache,
|
||||
/* async_read */ false, /* use_block_cache_for_lookup */ true);
|
||||
|
||||
|
||||
@@ -76,8 +76,8 @@ Status HashIndexReader::Create(const BlockBasedTable* table,
|
||||
BlockFetcher prefixes_block_fetcher(
|
||||
file, prefetch_buffer, footer, ro, prefixes_handle, &prefixes_contents,
|
||||
ioptions, true /*decompress*/, true /*maybe_compressed*/,
|
||||
BlockType::kHashIndexPrefixes, UncompressionDict::GetEmptyDict(),
|
||||
cache_options, memory_allocator);
|
||||
BlockType::kHashIndexPrefixes, rep->decompressor.get(), cache_options,
|
||||
memory_allocator);
|
||||
s = prefixes_block_fetcher.ReadBlockContents();
|
||||
if (!s.ok()) {
|
||||
return s;
|
||||
@@ -87,7 +87,7 @@ Status HashIndexReader::Create(const BlockBasedTable* table,
|
||||
file, prefetch_buffer, footer, ro, prefixes_meta_handle,
|
||||
&prefixes_meta_contents, ioptions, true /*decompress*/,
|
||||
true /*maybe_compressed*/, BlockType::kHashIndexMetadata,
|
||||
UncompressionDict::GetEmptyDict(), cache_options, memory_allocator);
|
||||
rep->decompressor.get(), cache_options, memory_allocator);
|
||||
s = prefixes_meta_block_fetcher.ReadBlockContents();
|
||||
if (!s.ok()) {
|
||||
// TODO: log error
|
||||
|
||||
@@ -26,9 +26,9 @@ Status BlockBasedTable::IndexReaderCommon::ReadIndexBlock(
|
||||
assert(rep != nullptr);
|
||||
|
||||
const Status s = table->RetrieveBlock(
|
||||
prefetch_buffer, read_options, rep->index_handle,
|
||||
UncompressionDict::GetEmptyDict(), &index_block->As<Block_kIndex>(),
|
||||
get_context, lookup_context, /* for_compaction */ false, use_cache,
|
||||
prefetch_buffer, read_options, rep->index_handle, rep->decompressor.get(),
|
||||
&index_block->As<Block_kIndex>(), get_context, lookup_context,
|
||||
/* for_compaction */ false, use_cache,
|
||||
/* async_read */ false, /* use_block_cache_for_lookup */ true);
|
||||
|
||||
return s;
|
||||
|
||||
@@ -413,8 +413,7 @@ Status PartitionedFilterBlockReader::GetFilterPartitionBlock(
|
||||
|
||||
const Status s = table()->RetrieveBlock(
|
||||
prefetch_buffer, read_options, fltr_blk_handle,
|
||||
UncompressionDict::GetEmptyDict(), filter_block, get_context,
|
||||
lookup_context,
|
||||
/* decomp */ nullptr, filter_block, get_context, lookup_context,
|
||||
/* for_compaction */ false, /* use_cache */ true,
|
||||
/* async_read */ false, /* use_block_cache_for_lookup */ true);
|
||||
|
||||
@@ -592,7 +591,8 @@ Status PartitionedFilterBlockReader::CacheDependencies(
|
||||
/*usage=*/FilePrefetchBufferUsage::kUnknown);
|
||||
|
||||
IOOptions opts;
|
||||
s = rep->file->PrepareIOOptions(ro, opts);
|
||||
IODebugContext dbg;
|
||||
s = rep->file->PrepareIOOptions(ro, opts, &dbg);
|
||||
if (s.ok()) {
|
||||
s = prefetch_buffer->Prefetch(opts, rep->file.get(), prefetch_off,
|
||||
static_cast<size_t>(prefetch_len));
|
||||
@@ -610,7 +610,7 @@ Status PartitionedFilterBlockReader::CacheDependencies(
|
||||
// filter blocks
|
||||
s = table()->MaybeReadBlockAndLoadToCache(
|
||||
prefetch_buffer ? prefetch_buffer.get() : tail_prefetch_buffer, ro,
|
||||
handle, UncompressionDict::GetEmptyDict(),
|
||||
handle, /* dict */ nullptr,
|
||||
/* for_compaction */ false, &block, nullptr /* get_context */,
|
||||
&lookup_context, nullptr /* contents */, false,
|
||||
/* use_block_cache_for_lookup */ true);
|
||||
|
||||
@@ -190,7 +190,7 @@ Status PartitionIndexReader::CacheDependencies(
|
||||
// filter blocks
|
||||
Status s = table()->MaybeReadBlockAndLoadToCache(
|
||||
prefetch_buffer ? prefetch_buffer.get() : tail_prefetch_buffer, ro,
|
||||
handle, UncompressionDict::GetEmptyDict(),
|
||||
handle, rep->decompressor.get(),
|
||||
/*for_compaction=*/false, &block.As<Block_kIndex>(),
|
||||
/*get_context=*/nullptr, &lookup_context, /*contents=*/nullptr,
|
||||
/*async_read=*/false, /*use_block_cache_for_lookup=*/true);
|
||||
|
||||
@@ -23,7 +23,7 @@ Status UncompressionDictReader::Create(
|
||||
assert(!pin || prefetch);
|
||||
assert(uncompression_dict_reader);
|
||||
|
||||
CachableEntry<UncompressionDict> uncompression_dict;
|
||||
CachableEntry<DecompressorDict> uncompression_dict;
|
||||
if (prefetch || !use_cache) {
|
||||
const Status s = ReadUncompressionDictionary(
|
||||
table, prefetch_buffer, ro, use_cache, nullptr /* get_context */,
|
||||
@@ -47,7 +47,7 @@ Status UncompressionDictReader::ReadUncompressionDictionary(
|
||||
const BlockBasedTable* table, FilePrefetchBuffer* prefetch_buffer,
|
||||
const ReadOptions& read_options, bool use_cache, GetContext* get_context,
|
||||
BlockCacheLookupContext* lookup_context,
|
||||
CachableEntry<UncompressionDict>* uncompression_dict) {
|
||||
CachableEntry<DecompressorDict>* uncompression_dict) {
|
||||
// TODO: add perf counter for compression dictionary read time
|
||||
|
||||
assert(table);
|
||||
@@ -60,8 +60,7 @@ Status UncompressionDictReader::ReadUncompressionDictionary(
|
||||
|
||||
const Status s = table->RetrieveBlock(
|
||||
prefetch_buffer, read_options, rep->compression_dict_handle,
|
||||
UncompressionDict::GetEmptyDict(), uncompression_dict, get_context,
|
||||
lookup_context,
|
||||
/* decomp */ nullptr, uncompression_dict, get_context, lookup_context,
|
||||
/* for_compaction */ false, use_cache,
|
||||
/* async_read */ false, /* use_block_cache_for_lookup */ true);
|
||||
|
||||
@@ -79,7 +78,7 @@ Status UncompressionDictReader::ReadUncompressionDictionary(
|
||||
Status UncompressionDictReader::GetOrReadUncompressionDictionary(
|
||||
FilePrefetchBuffer* prefetch_buffer, const ReadOptions& ro,
|
||||
GetContext* get_context, BlockCacheLookupContext* lookup_context,
|
||||
CachableEntry<UncompressionDict>* uncompression_dict) const {
|
||||
CachableEntry<DecompressorDict>* uncompression_dict) const {
|
||||
assert(uncompression_dict);
|
||||
|
||||
if (!uncompression_dict_.IsEmpty()) {
|
||||
|
||||
@@ -34,13 +34,13 @@ class UncompressionDictReader {
|
||||
Status GetOrReadUncompressionDictionary(
|
||||
FilePrefetchBuffer* prefetch_buffer, const ReadOptions& ro,
|
||||
GetContext* get_context, BlockCacheLookupContext* lookup_context,
|
||||
CachableEntry<UncompressionDict>* uncompression_dict) const;
|
||||
CachableEntry<DecompressorDict>* uncompression_dict) const;
|
||||
|
||||
size_t ApproximateMemoryUsage() const;
|
||||
|
||||
private:
|
||||
UncompressionDictReader(const BlockBasedTable* t,
|
||||
CachableEntry<UncompressionDict>&& uncompression_dict)
|
||||
CachableEntry<DecompressorDict>&& uncompression_dict)
|
||||
: table_(t), uncompression_dict_(std::move(uncompression_dict)) {
|
||||
assert(table_);
|
||||
}
|
||||
@@ -51,10 +51,10 @@ class UncompressionDictReader {
|
||||
const BlockBasedTable* table, FilePrefetchBuffer* prefetch_buffer,
|
||||
const ReadOptions& read_options, bool use_cache, GetContext* get_context,
|
||||
BlockCacheLookupContext* lookup_context,
|
||||
CachableEntry<UncompressionDict>* uncompression_dict);
|
||||
CachableEntry<DecompressorDict>* uncompression_dict);
|
||||
|
||||
const BlockBasedTable* table_;
|
||||
CachableEntry<UncompressionDict> uncompression_dict_;
|
||||
CachableEntry<DecompressorDict> uncompression_dict_;
|
||||
};
|
||||
|
||||
} // namespace ROCKSDB_NAMESPACE
|
||||
Loaded 100 of 149 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user