#include "util/compression_context_cache.h"
#include "util/compression.h"
#include "util/core_local.h"
#include <atomic>
namespace
rocksdb {
namespace
compression_cache {
void
*
const
SentinelValue =
nullptr
;
struct
ZSTDCachedData {
ZSTDUncompressCachedData uncomp_cached_data_;
std::atomic<
void
*> zstd_uncomp_sentinel_;
char
padding[(CACHE_LINE_SIZE -
(
sizeof
(ZSTDUncompressCachedData) +
sizeof
(std::atomic<
void
*>)) %
CACHE_LINE_SIZE)];
ZSTDCachedData() : zstd_uncomp_sentinel_(&uncomp_cached_data_) {}
ZSTDCachedData(
const
ZSTDCachedData&) =
delete
;
ZSTDCachedData& operator=(
const
ZSTDCachedData&) =
delete
;
ZSTDUncompressCachedData GetUncompressData(int64_t idx) {
ZSTDUncompressCachedData result;
void
* expected = &uncomp_cached_data_;
if
(zstd_uncomp_sentinel_.compare_exchange_strong(expected,
SentinelValue)) {
uncomp_cached_data_.CreateIfNeeded();
result.InitFromCache(uncomp_cached_data_, idx);
}
else
{
result.CreateIfNeeded();
}
return
result;
}
void
ReturnUncompressData() {
if
(zstd_uncomp_sentinel_.exchange(&uncomp_cached_data_) != SentinelValue) {
assert
(
false
);
}
}
};
static_assert
(
sizeof
(ZSTDCachedData) % CACHE_LINE_SIZE == 0,
"Expected CACHE_LINE_SIZE alignment"
);
}
using
namespace
compression_cache;
class
CompressionContextCache::Rep {
public
:
Rep() {}
ZSTDUncompressCachedData GetZSTDUncompressData() {
auto
p = per_core_uncompr_.AccessElementAndIndex();
int64_t idx =
static_cast
<int64_t>(p.second);
return
p.first->GetUncompressData(idx);
}
void
ReturnZSTDUncompressData(int64_t idx) {
assert
(idx >= 0);
auto
* cn = per_core_uncompr_.AccessAtCore(
static_cast
<
size_t
>(idx));
cn->ReturnUncompressData();
}
private
:
CoreLocalArray<ZSTDCachedData> per_core_uncompr_;
};
CompressionContextCache::CompressionContextCache() : rep_(
new
Rep()) {}
CompressionContextCache* CompressionContextCache::Instance() {
static
CompressionContextCache instance;
return
&instance;
}
void
CompressionContextCache::InitSingleton() { Instance(); }
ZSTDUncompressCachedData
CompressionContextCache::GetCachedZSTDUncompressData() {
return
rep_->GetZSTDUncompressData();
}
void
CompressionContextCache::ReturnCachedZSTDUncompressData(int64_t idx) {
rep_->ReturnZSTDUncompressData(idx);
}
CompressionContextCache::~CompressionContextCache() {
delete
rep_; }
}