]> git.proxmox.com Git - ceph.git/blame - ceph/src/rocksdb/util/compression_context_cache.cc
bump version to 15.2.11-pve1
[ceph.git] / ceph / src / rocksdb / util / compression_context_cache.cc
CommitLineData
11fdf7f2
TL
1// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2// This source code is licensed under both the GPLv2 (found in the
3// COPYING file in the root directory) and Apache 2.0 License
4// (found in the LICENSE.Apache file in the root directory).
5// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
6// Use of this source code is governed by a BSD-style license that can be
7// found in the LICENSE file. See the AUTHORS file for names of contributors.
8//
9
10#include "util/compression_context_cache.h"
11
12#include "util/compression.h"
13#include "util/core_local.h"
14
15#include <atomic>
16
17namespace rocksdb {
18namespace compression_cache {
19
20void* const SentinelValue = nullptr;
21// Cache ZSTD uncompression contexts for reads
22// if needed we can add ZSTD compression context caching
23// which is currently is not done since BlockBasedTableBuilder
24// simply creates one compression context per new SST file.
25struct ZSTDCachedData {
26 // We choose to cache the below structure instead of a ptr
27 // because we want to avoid a) native types leak b) make
28 // cache use transparent for the user
29 ZSTDUncompressCachedData uncomp_cached_data_;
30 std::atomic<void*> zstd_uncomp_sentinel_;
31
32 char
33 padding[(CACHE_LINE_SIZE -
34 (sizeof(ZSTDUncompressCachedData) + sizeof(std::atomic<void*>)) %
35 CACHE_LINE_SIZE)]; // unused padding field
36
37 ZSTDCachedData() : zstd_uncomp_sentinel_(&uncomp_cached_data_) {}
38 ZSTDCachedData(const ZSTDCachedData&) = delete;
39 ZSTDCachedData& operator=(const ZSTDCachedData&) = delete;
40
41 ZSTDUncompressCachedData GetUncompressData(int64_t idx) {
42 ZSTDUncompressCachedData result;
43 void* expected = &uncomp_cached_data_;
44 if (zstd_uncomp_sentinel_.compare_exchange_strong(expected,
45 SentinelValue)) {
46 uncomp_cached_data_.CreateIfNeeded();
47 result.InitFromCache(uncomp_cached_data_, idx);
48 } else {
49 // Creates one time use data
50 result.CreateIfNeeded();
51 }
52 return result;
53 }
54 // Return the entry back into circulation
55 // This is executed only when we successfully obtained
56 // in the first place
57 void ReturnUncompressData() {
58 if (zstd_uncomp_sentinel_.exchange(&uncomp_cached_data_) != SentinelValue) {
59 // Means we are returning while not having it acquired.
60 assert(false);
61 }
62 }
63};
64static_assert(sizeof(ZSTDCachedData) % CACHE_LINE_SIZE == 0,
65 "Expected CACHE_LINE_SIZE alignment");
66} // namespace compression_cache
67
68using namespace compression_cache;
69
70class CompressionContextCache::Rep {
71 public:
72 Rep() {}
73 ZSTDUncompressCachedData GetZSTDUncompressData() {
74 auto p = per_core_uncompr_.AccessElementAndIndex();
75 int64_t idx = static_cast<int64_t>(p.second);
76 return p.first->GetUncompressData(idx);
77 }
78 void ReturnZSTDUncompressData(int64_t idx) {
79 assert(idx >= 0);
80 auto* cn = per_core_uncompr_.AccessAtCore(static_cast<size_t>(idx));
81 cn->ReturnUncompressData();
82 }
83
84 private:
85 CoreLocalArray<ZSTDCachedData> per_core_uncompr_;
86};
87
88CompressionContextCache::CompressionContextCache() : rep_(new Rep()) {}
89
90CompressionContextCache* CompressionContextCache::Instance() {
91 static CompressionContextCache instance;
92 return &instance;
93}
94
95void CompressionContextCache::InitSingleton() { Instance(); }
96
97ZSTDUncompressCachedData
98CompressionContextCache::GetCachedZSTDUncompressData() {
99 return rep_->GetZSTDUncompressData();
100}
101
102void CompressionContextCache::ReturnCachedZSTDUncompressData(int64_t idx) {
103 rep_->ReturnZSTDUncompressData(idx);
104}
105
106CompressionContextCache::~CompressionContextCache() { delete rep_; }
107
108} // namespace rocksdb