| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- // Copyright (c) Meta Platforms, Inc. and affiliates.
- // This source code is licensed under both the GPLv2 (found in the
- // COPYING file in the root directory) and Apache 2.0 License
- // (found in the LICENSE.Apache file in the root directory).
- #pragma once
- #include "rocksdb/cache.h"
- #include "rocksdb/secondary_cache.h"
- namespace ROCKSDB_NAMESPACE {
- // A SecondaryCache that implements stacking of a compressed secondary cache
- // and a non-volatile (local flash) cache. It implements an admission
- // policy of warming the bottommost tier (local flash) with compressed
- // blocks from the SST on misses, and on hits in the bottommost tier,
- // promoting to the compressed and/or primary block cache. The admission
- // policies of the primary block cache and compressed secondary cache remain
- // unchanged - promote on second access. There is no demotion ofablocks
- // evicted from a tier. They are just discarded.
- //
- // In order to properly handle compressed blocks directly read from SSTs, and
- // to allow writeback of blocks compressed by the compressed secondary
- // cache in the future, we make use of the compression type and source
- // cache tier arguments in InsertSaved.
- class TieredSecondaryCache : public SecondaryCacheWrapper {
- public:
- TieredSecondaryCache(std::shared_ptr<SecondaryCache> comp_sec_cache,
- std::shared_ptr<SecondaryCache> nvm_sec_cache,
- TieredAdmissionPolicy adm_policy)
- : SecondaryCacheWrapper(comp_sec_cache), nvm_sec_cache_(nvm_sec_cache) {
- #ifndef NDEBUG
- assert(adm_policy == TieredAdmissionPolicy::kAdmPolicyThreeQueue);
- #else
- (void)adm_policy;
- #endif
- }
- ~TieredSecondaryCache() override {}
- const char* Name() const override { return "TieredSecondaryCache"; }
- // This is a no-op as we currently don't allow demotion (i.e
- // insertion by the upper layer) of evicted blocks.
- Status Insert(const Slice& /*key*/, Cache::ObjectPtr /*obj*/,
- const Cache::CacheItemHelper* /*helper*/,
- bool /*force_insert*/) override {
- return Status::OK();
- }
- // Warm up the nvm tier directly
- Status InsertSaved(const Slice& key, const Slice& saved,
- CompressionType type = CompressionType::kNoCompression,
- CacheTier source = CacheTier::kVolatileTier) override {
- return nvm_sec_cache_->InsertSaved(key, saved, type, source);
- }
- std::unique_ptr<SecondaryCacheResultHandle> Lookup(
- const Slice& key, const Cache::CacheItemHelper* helper,
- Cache::CreateContext* create_context, bool wait, bool advise_erase,
- Statistics* stats, bool& kept_in_sec_cache) override;
- void WaitAll(std::vector<SecondaryCacheResultHandle*> handles) override;
- private:
- struct CreateContext : public Cache::CreateContext {
- const Slice* key;
- bool advise_erase;
- const Cache::CacheItemHelper* helper;
- Cache::CreateContext* inner_ctx;
- std::shared_ptr<SecondaryCacheResultHandle> inner_handle;
- SecondaryCache* comp_sec_cache;
- Statistics* stats;
- };
- class ResultHandle : public SecondaryCacheResultHandle {
- public:
- ~ResultHandle() override {}
- bool IsReady() override {
- if (inner_handle_ && inner_handle_->IsReady()) {
- Complete();
- }
- return ready_;
- }
- void Wait() override {
- inner_handle_->Wait();
- Complete();
- }
- size_t Size() override { return size_; }
- Cache::ObjectPtr Value() override { return value_; }
- void Complete() {
- size_ = inner_handle_->Size();
- value_ = inner_handle_->Value();
- inner_handle_.reset();
- ready_ = true;
- }
- void SetInnerHandle(std::unique_ptr<SecondaryCacheResultHandle>&& handle) {
- inner_handle_ = std::move(handle);
- }
- void SetSize(size_t size) { size_ = size; }
- void SetValue(Cache::ObjectPtr val) { value_ = val; }
- CreateContext* ctx() { return &ctx_; }
- SecondaryCacheResultHandle* inner_handle() { return inner_handle_.get(); }
- private:
- std::unique_ptr<SecondaryCacheResultHandle> inner_handle_;
- CreateContext ctx_;
- size_t size_;
- Cache::ObjectPtr value_;
- bool ready_ = false;
- };
- static void NoopDelete(Cache::ObjectPtr /*obj*/,
- MemoryAllocator* /*allocator*/) {
- assert(false);
- }
- static size_t ZeroSize(Cache::ObjectPtr /*obj*/) {
- assert(false);
- return 0;
- }
- static Status NoopSaveTo(Cache::ObjectPtr /*from_obj*/,
- size_t /*from_offset*/, size_t /*length*/,
- char* /*out_buf*/) {
- assert(false);
- return Status::OK();
- }
- static Status MaybeInsertAndCreate(const Slice& data, CompressionType type,
- CacheTier source,
- Cache::CreateContext* ctx,
- MemoryAllocator* allocator,
- Cache::ObjectPtr* out_obj,
- size_t* out_charge);
- static const Cache::CacheItemHelper* GetHelper() {
- const static Cache::CacheItemHelper basic_helper(CacheEntryRole::kMisc,
- &NoopDelete);
- const static Cache::CacheItemHelper maybe_insert_and_create_helper{
- CacheEntryRole::kMisc, &NoopDelete, &ZeroSize,
- &NoopSaveTo, &MaybeInsertAndCreate, &basic_helper,
- };
- return &maybe_insert_and_create_helper;
- }
- std::shared_ptr<SecondaryCache> comp_sec_cache_;
- std::shared_ptr<SecondaryCache> nvm_sec_cache_;
- };
- } // namespace ROCKSDB_NAMESPACE
|