]> git.proxmox.com Git - ceph.git/blob - ceph/src/kv/rocksdb_cache/ShardedCache.h
import ceph quincy 17.2.1
[ceph.git] / ceph / src / kv / rocksdb_cache / ShardedCache.h
1 // Copyright (c) 2018-Present Red Hat Inc. All rights reserved.
2 //
3 // Copyright (c) 2011-2018, Facebook, Inc. All rights reserved.
4 // This source code is licensed under both the GPLv2 and Apache 2.0 License
5 //
6 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
7 // Use of this source code is governed by a BSD-style license that can be
8 // found in the LICENSE file. See the AUTHORS file for names of contributors.
9
10 #ifndef ROCKSDB_SHARDED_CACHE
11 #define ROCKSDB_SHARDED_CACHE
12
13 #include <atomic>
14 #include <string>
15 #include <mutex>
16
17 #include "rocksdb/version.h"
18 #include "rocksdb/cache.h"
19 #include "include/ceph_hash.h"
20 #include "common/PriorityCache.h"
21 //#include "hash.h"
22
23 #ifndef CACHE_LINE_SIZE
24 #define CACHE_LINE_SIZE 64 // XXX arch-specific define
25 #endif
26
27 namespace rocksdb_cache {
28
29 using DeleterFn = void (*)(const rocksdb::Slice& key, void* value);
30
31 // Single cache shard interface.
32 class CacheShard {
33 public:
34 CacheShard() = default;
35 virtual ~CacheShard() = default;
36
37 virtual rocksdb::Status Insert(const rocksdb::Slice& key, uint32_t hash, void* value,
38 size_t charge,
39 DeleterFn deleter,
40 rocksdb::Cache::Handle** handle, rocksdb::Cache::Priority priority) = 0;
41 virtual rocksdb::Cache::Handle* Lookup(const rocksdb::Slice& key, uint32_t hash) = 0;
42 virtual bool Ref(rocksdb::Cache::Handle* handle) = 0;
43 virtual bool Release(rocksdb::Cache::Handle* handle, bool force_erase = false) = 0;
44 virtual void Erase(const rocksdb::Slice& key, uint32_t hash) = 0;
45 virtual void SetCapacity(size_t capacity) = 0;
46 virtual void SetStrictCapacityLimit(bool strict_capacity_limit) = 0;
47 virtual size_t GetUsage() const = 0;
48 virtual size_t GetPinnedUsage() const = 0;
49 virtual void ApplyToAllCacheEntries(
50 const std::function<void(const rocksdb::Slice& key,
51 void* value,
52 size_t charge,
53 DeleterFn)>& callback,
54 bool thread_safe) = 0;
55 virtual void EraseUnRefEntries() = 0;
56 virtual std::string GetPrintableOptions() const { return ""; }
57 virtual DeleterFn GetDeleter(rocksdb::Cache::Handle* handle) const = 0;
58 };
59
60 // Generic cache interface which shards cache by hash of keys. 2^num_shard_bits
61 // shards will be created, with capacity split evenly to each of the shards.
62 // Keys are sharded by the highest num_shard_bits bits of hash value.
63 class ShardedCache : public rocksdb::Cache, public PriorityCache::PriCache {
64 public:
65 ShardedCache(size_t capacity, int num_shard_bits, bool strict_capacity_limit);
66 virtual ~ShardedCache() = default;
67 // rocksdb::Cache
68 virtual const char* Name() const override = 0;
69 virtual rocksdb::Status Insert(const rocksdb::Slice& key, void* value, size_t charge,
70 DeleterFn,
71 rocksdb::Cache::Handle** handle, Priority priority) override;
72 virtual rocksdb::Cache::Handle* Lookup(const rocksdb::Slice& key, rocksdb::Statistics* stats) override;
73 virtual bool Ref(rocksdb::Cache::Handle* handle) override;
74 virtual bool Release(rocksdb::Cache::Handle* handle, bool force_erase = false) override;
75 virtual void* Value(Handle* handle) override = 0;
76 virtual void Erase(const rocksdb::Slice& key) override;
77 virtual uint64_t NewId() override;
78 virtual void SetCapacity(size_t capacity) override;
79 virtual void SetStrictCapacityLimit(bool strict_capacity_limit) override;
80 virtual bool HasStrictCapacityLimit() const override;
81 virtual size_t GetCapacity() const override;
82 virtual size_t GetUsage() const override;
83 virtual size_t GetUsage(rocksdb::Cache::Handle* handle) const override;
84 virtual size_t GetPinnedUsage() const override;
85 virtual size_t GetCharge(Handle* handle) const = 0;
86 #if (ROCKSDB_MAJOR >= 7 || (ROCKSDB_MAJOR == 6 && ROCKSDB_MINOR >= 22))
87 virtual DeleterFn GetDeleter(Handle* handle) const override;
88 #endif
89 virtual void DisownData() override = 0;
90 #if (ROCKSDB_MAJOR >= 7 || (ROCKSDB_MAJOR == 6 && ROCKSDB_MINOR >= 22))
91 virtual void ApplyToAllEntries(
92 const std::function<void(const rocksdb::Slice& key, void* value, size_t charge,
93 DeleterFn deleter)>& callback,
94 const ApplyToAllEntriesOptions& opts) override;
95 #else
96 virtual void ApplyToAllCacheEntries(void (*callback)(void*, size_t),
97 bool thread_safe) override;
98 #endif
99 virtual void EraseUnRefEntries() override;
100 virtual std::string GetPrintableOptions() const override;
101 virtual CacheShard* GetShard(int shard) = 0;
102 virtual const CacheShard* GetShard(int shard) const = 0;
103 virtual uint32_t GetHash(Handle* handle) const = 0;
104
105 int GetNumShardBits() const { return num_shard_bits_; }
106
107 virtual uint32_t get_bin_count() const = 0;
108 virtual void set_bin_count(uint32_t count) = 0;
109
110 // PriCache
111 virtual int64_t get_cache_bytes(PriorityCache::Priority pri) const {
112 return cache_bytes[pri];
113 }
114 virtual int64_t get_cache_bytes() const {
115 int64_t total = 0;
116 for (int i = 0; i < PriorityCache::Priority::LAST + 1; i++) {
117 PriorityCache::Priority pri = static_cast<PriorityCache::Priority>(i);
118 total += get_cache_bytes(pri);
119 }
120 return total;
121 }
122 virtual void set_cache_bytes(PriorityCache::Priority pri, int64_t bytes) {
123 cache_bytes[pri] = bytes;
124 }
125 virtual void add_cache_bytes(PriorityCache::Priority pri, int64_t bytes) {
126 cache_bytes[pri] += bytes;
127 }
128 virtual double get_cache_ratio() const {
129 return cache_ratio;
130 }
131 virtual void set_cache_ratio(double ratio) {
132 cache_ratio = ratio;
133 }
134 virtual uint64_t get_bins(PriorityCache::Priority pri) const {
135 if (pri > PriorityCache::Priority::PRI0 &&
136 pri < PriorityCache::Priority::LAST) {
137 return bins[pri];
138 }
139 return 0;
140 }
141 virtual void set_bins(PriorityCache::Priority pri, uint64_t end_bin) {
142 if (pri <= PriorityCache::Priority::PRI0 ||
143 pri >= PriorityCache::Priority::LAST) {
144 return;
145 }
146 bins[pri] = end_bin;
147 uint64_t max = 0;
148 for (int pri = 1; pri < PriorityCache::Priority::LAST; pri++) {
149 if (bins[pri] > max) {
150 max = bins[pri];
151 }
152 }
153 set_bin_count(max);
154 }
155 virtual void import_bins(const std::vector<uint64_t> &bins_v) {
156 uint64_t max = 0;
157 for (int pri = 1; pri < PriorityCache::Priority::LAST; pri++) {
158 unsigned i = (unsigned) pri - 1;
159 if (i < bins_v.size()) {
160 bins[pri] = bins_v[i];
161 if (bins[pri] > max) {
162 max = bins[pri];
163 }
164 } else {
165 bins[pri] = 0;
166 }
167 }
168 set_bin_count(max);
169 }
170 virtual std::string get_cache_name() const = 0;
171
172 private:
173 static inline uint32_t HashSlice(const rocksdb::Slice& s) {
174 return ceph_str_hash(CEPH_STR_HASH_RJENKINS, s.data(), s.size());
175 // return Hash(s.data(), s.size(), 0);
176 }
177
178 uint32_t Shard(uint32_t hash) const {
179 // Note, hash >> 32 yields hash in gcc, not the zero we expect!
180 return (num_shard_bits_ > 0) ? (hash >> (32 - num_shard_bits_)) : 0;
181 }
182
183 uint64_t bins[PriorityCache::Priority::LAST+1] = {0};
184 int64_t cache_bytes[PriorityCache::Priority::LAST+1] = {0};
185 double cache_ratio = 0;
186
187 int num_shard_bits_;
188 mutable std::mutex capacity_mutex_;
189 size_t capacity_;
190 bool strict_capacity_limit_;
191 std::atomic<uint64_t> last_id_;
192 };
193
194 extern int GetDefaultCacheShardBits(size_t capacity);
195
196 } // namespace rocksdb_cache
197 #endif // ROCKSDB_SHARDED_CACHE