ASSERT_OK(Put(ToString(i), value));
ASSERT_OK(Flush());
ASSERT_EQ(i, options.statistics->getTickerCount(BLOCK_CACHE_DATA_ADD));
+ ASSERT_EQ(value, Get(ToString(i)));
+ ASSERT_EQ(0, options.statistics->getTickerCount(BLOCK_CACHE_DATA_MISS));
+ ASSERT_EQ(i, options.statistics->getTickerCount(BLOCK_CACHE_DATA_HIT));
+ }
+}
+
+// This test cache all types of blocks during flush.
+TEST_F(DBBlockCacheTest, WarmCacheWithBlocksDuringFlush) {
+ Options options = CurrentOptions();
+ options.create_if_missing = true;
+ options.statistics = ROCKSDB_NAMESPACE::CreateDBStatistics();
+
+ BlockBasedTableOptions table_options;
+ table_options.block_cache = NewLRUCache(1 << 25, 0, false);
+ table_options.cache_index_and_filter_blocks = true;
+ table_options.prepopulate_block_cache =
+ BlockBasedTableOptions::PrepopulateBlockCache::kFlushOnly;
+ table_options.filter_policy.reset(NewBloomFilterPolicy(10, false));
+ options.table_factory.reset(NewBlockBasedTableFactory(table_options));
+ DestroyAndReopen(options);
+
+ std::string value(kValueSize, 'a');
+ for (size_t i = 1; i < 2; i++) {
+ ASSERT_OK(Put(ToString(i), value));
+ ASSERT_OK(Flush());
+ ASSERT_EQ(i, options.statistics->getTickerCount(BLOCK_CACHE_DATA_ADD));
+ ASSERT_EQ(i, options.statistics->getTickerCount(BLOCK_CACHE_INDEX_ADD));
+ ASSERT_EQ(i, options.statistics->getTickerCount(BLOCK_CACHE_FILTER_ADD));
ASSERT_EQ(value, Get(ToString(i)));
+
ASSERT_EQ(0, options.statistics->getTickerCount(BLOCK_CACHE_DATA_MISS));
ASSERT_EQ(i, options.statistics->getTickerCount(BLOCK_CACHE_DATA_HIT));
+
+ ASSERT_EQ(0, options.statistics->getTickerCount(BLOCK_CACHE_INDEX_MISS));
+ ASSERT_EQ(i * 3, options.statistics->getTickerCount(BLOCK_CACHE_INDEX_HIT));
+
+ ASSERT_EQ(0, options.statistics->getTickerCount(BLOCK_CACHE_FILTER_MISS));
+ ASSERT_EQ(i * 2,
+ options.statistics->getTickerCount(BLOCK_CACHE_FILTER_HIT));
}
}
#endif
#include "table/block_based/block_based_table_factory.h"
#include "table/block_based/block_based_table_reader.h"
#include "table/block_based/block_builder.h"
+#include "table/block_based/block_like_traits.h"
#include "table/block_based/filter_block.h"
#include "table/block_based/filter_policy_internal.h"
#include "table/block_based/full_filter_block.h"
r->get_offset());
r->pc_rep->EmitBlock(block_rep);
} else {
- WriteBlock(&r->data_block, &r->pending_handle, true /* is_data_block */);
+ WriteBlock(&r->data_block, &r->pending_handle, BlockType::kData);
}
}
void BlockBasedTableBuilder::WriteBlock(BlockBuilder* block,
BlockHandle* handle,
- bool is_data_block) {
+ BlockType block_type) {
block->Finish();
std::string raw_block_contents;
block->SwapAndReset(raw_block_contents);
if (rep_->state == Rep::State::kBuffered) {
- assert(is_data_block);
+ assert(block_type == BlockType::kData);
rep_->data_block_buffers.emplace_back(std::move(raw_block_contents));
rep_->data_begin_offset += rep_->data_block_buffers.back().size();
return;
}
- WriteBlock(raw_block_contents, handle, is_data_block);
+ WriteBlock(raw_block_contents, handle, block_type);
}
void BlockBasedTableBuilder::WriteBlock(const Slice& raw_block_contents,
BlockHandle* handle,
- bool is_data_block) {
+ BlockType block_type) {
Rep* r = rep_;
assert(r->state == Rep::State::kUnbuffered);
Slice block_contents;
CompressionType type;
Status compress_status;
+ bool is_data_block = block_type == BlockType::kData;
CompressAndVerifyBlock(raw_block_contents, is_data_block,
*(r->compression_ctxs[0]), r->verify_ctxs[0].get(),
&(r->compressed_output), &(block_contents), &type,
return;
}
- WriteRawBlock(block_contents, type, handle, is_data_block,
- &raw_block_contents);
+ WriteRawBlock(block_contents, type, handle, block_type, &raw_block_contents);
r->compressed_output.clear();
if (is_data_block) {
if (r->filter_builder != nullptr) {
void BlockBasedTableBuilder::WriteRawBlock(const Slice& block_contents,
CompressionType type,
BlockHandle* handle,
- bool is_data_block,
+ BlockType block_type,
const Slice* raw_block_contents) {
Rep* r = rep_;
+ bool is_data_block = block_type == BlockType::kData;
Status s = Status::OK();
IOStatus io_s = IOStatus::OK();
StopWatch sw(r->ioptions.clock, r->ioptions.stats, WRITE_RAW_BLOCK_MICROS);
io_s = r->file->Append(Slice(trailer, kBlockTrailerSize));
if (io_s.ok()) {
assert(s.ok());
- if (is_data_block &&
- r->table_options.prepopulate_block_cache ==
- BlockBasedTableOptions::PrepopulateBlockCache::kFlushOnly) {
+ if (r->table_options.prepopulate_block_cache ==
+ BlockBasedTableOptions::PrepopulateBlockCache::kFlushOnly) {
if (type == kNoCompression) {
- s = InsertBlockInCache(block_contents, handle);
+ s = InsertBlockInCacheHelper(block_contents, handle, block_type);
} else if (raw_block_contents != nullptr) {
- s = InsertBlockInCache(*raw_block_contents, handle);
+ s = InsertBlockInCacheHelper(*raw_block_contents, handle, block_type);
}
if (!s.ok()) {
r->SetStatus(s);
}
r->pc_rep->file_size_estimator.SetCurrBlockRawSize(block_rep->data->size());
-
WriteRawBlock(block_rep->compressed_contents, block_rep->compression_type,
- &r->pending_handle, true /* is_data_block*/,
- &block_rep->contents);
+ &r->pending_handle, BlockType::kData, &block_rep->contents);
if (!ok()) {
break;
}
return s;
}
+Status BlockBasedTableBuilder::InsertBlockInCacheHelper(
+ const Slice& block_contents, const BlockHandle* handle,
+ BlockType block_type) {
+ Status s;
+ if (block_type == BlockType::kData || block_type == BlockType::kIndex) {
+ s = InsertBlockInCache<Block>(block_contents, handle, block_type);
+ } else if (block_type == BlockType::kFilter) {
+ if (rep_->filter_builder->IsBlockBased()) {
+ s = InsertBlockInCache<Block>(block_contents, handle, block_type);
+ } else {
+ s = InsertBlockInCache<ParsedFullFilterBlock>(block_contents, handle,
+ block_type);
+ }
+ } else if (block_type == BlockType::kCompressionDictionary) {
+ s = InsertBlockInCache<UncompressionDict>(block_contents, handle,
+ block_type);
+ }
+ return s;
+}
+
+template <typename TBlocklike>
Status BlockBasedTableBuilder::InsertBlockInCache(const Slice& block_contents,
- const BlockHandle* handle) {
+ const BlockHandle* handle,
+ BlockType block_type) {
// Uncompressed regular block cache
Cache* block_cache = rep_->table_options.block_cache.get();
Status s;
const size_t read_amp_bytes_per_bit =
rep_->table_options.read_amp_bytes_per_bit;
- Block* block = new Block(std::move(results), read_amp_bytes_per_bit);
- size_t charge = block->ApproximateMemoryUsage();
- s = block_cache->Insert(key, block, charge, &DeleteEntryCached<Block>);
- if (s.ok()) {
- BlockBasedTable::UpdateCacheInsertionMetrics(
- BlockType::kData, nullptr /*get_context*/, charge,
- s.IsOkOverwritten(), rep_->ioptions.stats);
- } else {
- RecordTick(rep_->ioptions.stats, BLOCK_CACHE_ADD_FAILURES);
+
+ TBlocklike* block_holder = BlocklikeTraits<TBlocklike>::Create(
+ std::move(results), read_amp_bytes_per_bit,
+ rep_->ioptions.statistics.get(),
+ false /*rep_->blocks_definitely_zstd_compressed*/,
+ rep_->table_options.filter_policy.get());
+
+ if (block_holder->own_bytes()) {
+ size_t charge = block_holder->ApproximateMemoryUsage();
+ s = block_cache->Insert(key, block_holder, charge,
+ &DeleteEntryCached<TBlocklike>);
+
+ if (s.ok()) {
+ BlockBasedTable::UpdateCacheInsertionMetrics(
+ block_type, nullptr /*get_context*/, charge, s.IsOkOverwritten(),
+ rep_->ioptions.stats);
+ } else {
+ RecordTick(rep_->ioptions.stats, BLOCK_CACHE_ADD_FAILURES);
+ }
}
}
return s;
rep_->filter_builder->Finish(filter_block_handle, &s);
assert(s.ok() || s.IsIncomplete());
rep_->props.filter_size += filter_content.size();
- WriteRawBlock(filter_content, kNoCompression, &filter_block_handle);
+ WriteRawBlock(filter_content, kNoCompression, &filter_block_handle,
+ BlockType::kFilter);
}
}
if (ok() && !empty_filter_block) {
if (ok()) {
for (const auto& item : index_blocks.meta_blocks) {
BlockHandle block_handle;
- WriteBlock(item.second, &block_handle, false /* is_data_block */);
+ WriteBlock(item.second, &block_handle, BlockType::kIndex);
if (!ok()) {
break;
}
}
if (ok()) {
if (rep_->table_options.enable_index_compression) {
- WriteBlock(index_blocks.index_block_contents, index_block_handle, false);
+ WriteBlock(index_blocks.index_block_contents, index_block_handle,
+ BlockType::kIndex);
} else {
WriteRawBlock(index_blocks.index_block_contents, kNoCompression,
- index_block_handle);
+ index_block_handle, BlockType::kIndex);
}
}
// If there are more index partitions, finish them and write them out
}
if (rep_->table_options.enable_index_compression) {
WriteBlock(index_blocks.index_block_contents, index_block_handle,
- false);
+ BlockType::kIndex);
} else {
WriteRawBlock(index_blocks.index_block_contents, kNoCompression,
- index_block_handle);
+ index_block_handle, BlockType::kIndex);
}
// The last index_block_handle will be for the partition index block
}
&property_block_builder);
WriteRawBlock(property_block_builder.Finish(), kNoCompression,
- &properties_block_handle);
+ &properties_block_handle, BlockType::kProperties);
}
if (ok()) {
#ifndef NDEBUG
BlockHandle compression_dict_block_handle;
if (ok()) {
WriteRawBlock(rep_->compression_dict->GetRawDict(), kNoCompression,
- &compression_dict_block_handle);
+ &compression_dict_block_handle,
+ BlockType::kCompressionDictionary);
#ifndef NDEBUG
Slice compression_dict = rep_->compression_dict->GetRawDict();
TEST_SYNC_POINT_CALLBACK(
if (ok() && !rep_->range_del_block.empty()) {
BlockHandle range_del_block_handle;
WriteRawBlock(rep_->range_del_block.Finish(), kNoCompression,
- &range_del_block_handle);
+ &range_del_block_handle, BlockType::kRangeDeletion);
meta_index_builder->Add(kRangeDelBlock, range_del_block_handle);
}
}
}
r->index_builder->OnKeyAdded(key);
}
- WriteBlock(Slice(data_block), &r->pending_handle,
- true /* is_data_block */);
+ WriteBlock(Slice(data_block), &r->pending_handle, BlockType::kData);
if (ok() && i + 1 < r->data_block_buffers.size()) {
assert(next_block_iter != nullptr);
Slice first_key_in_next_block = next_block_iter->key();
if (ok()) {
// flush the meta index block
WriteRawBlock(meta_index_builder.Finish(), kNoCompression,
- &metaindex_block_handle);
+ &metaindex_block_handle, BlockType::kMetaIndex);
}
if (ok()) {
WriteFooter(metaindex_block_handle, index_block_handle);