#include "cache/tiered_secondary_cache.h"
#include "monitoring/statistics_impl.h"
namespace ROCKSDB_NAMESPACE {
Status TieredSecondaryCache::MaybeInsertAndCreate(
const Slice& data, CompressionType type, CacheTier source,
Cache::CreateContext* ctx, MemoryAllocator* allocator,
Cache::ObjectPtr* out_obj, size_t* out_charge) {
TieredSecondaryCache::CreateContext* context =
static_cast<TieredSecondaryCache::CreateContext*>(ctx);
assert(source == CacheTier::kVolatileTier);
if (!context->advise_erase && type != kNoCompression) {
context->comp_sec_cache->InsertSaved(*context->key, data, type, source)
.PermitUncheckedError();
RecordTick(context->stats, COMPRESSED_SECONDARY_CACHE_PROMOTIONS);
} else {
RecordTick(context->stats, COMPRESSED_SECONDARY_CACHE_PROMOTION_SKIPS);
}
return context->helper->create_cb(data, type, source, context->inner_ctx,
allocator, out_obj, out_charge);
}
std::unique_ptr<SecondaryCacheResultHandle> TieredSecondaryCache::Lookup(
const Slice& key, const Cache::CacheItemHelper* helper,
Cache::CreateContext* create_context, bool wait, bool advise_erase,
Statistics* stats, bool& kept_in_sec_cache) {
bool dummy = false;
std::unique_ptr<SecondaryCacheResultHandle> result =
target()->Lookup(key, helper, create_context, wait, advise_erase, stats,
dummy);
kept_in_sec_cache = true;
if (result) {
assert(result->IsReady());
return result;
}
const Cache::CacheItemHelper* outer_helper =
TieredSecondaryCache::GetHelper();
if (wait) {
TieredSecondaryCache::CreateContext ctx;
ctx.key = &key;
ctx.advise_erase = advise_erase;
ctx.helper = helper;
ctx.inner_ctx = create_context;
ctx.comp_sec_cache = target();
ctx.stats = stats;
return nvm_sec_cache_->Lookup(key, outer_helper, &ctx, wait, advise_erase,
stats, kept_in_sec_cache);
}
std::unique_ptr<ResultHandle> handle(new ResultHandle());
handle->ctx()->key = &key;
handle->ctx()->advise_erase = advise_erase;
handle->ctx()->helper = helper;
handle->ctx()->inner_ctx = create_context;
handle->ctx()->comp_sec_cache = target();
handle->ctx()->stats = stats;
handle->SetInnerHandle(
nvm_sec_cache_->Lookup(key, outer_helper, handle->ctx(), wait,
advise_erase, stats, kept_in_sec_cache));
if (!handle->inner_handle()) {
handle.reset();
} else {
result.reset(handle.release());
}
return result;
}
void TieredSecondaryCache::WaitAll(
std::vector<SecondaryCacheResultHandle*> handles) {
std::vector<SecondaryCacheResultHandle*> nvm_handles;
std::vector<ResultHandle*> my_handles;
nvm_handles.reserve(handles.size());
for (auto handle : handles) {
if (handle->IsReady()) {
continue;
}
ResultHandle* hdl = static_cast<ResultHandle*>(handle);
nvm_handles.push_back(hdl->inner_handle());
my_handles.push_back(hdl);
}
nvm_sec_cache_->WaitAll(nvm_handles);
for (auto handle : my_handles) {
assert(handle->inner_handle()->IsReady());
handle->Complete();
}
}
}