]> git.proxmox.com Git - ceph.git/blob - ceph/src/kv/rocksdb_cache/ShardedCache.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / kv / rocksdb_cache / ShardedCache.cc
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 __STDC_FORMAT_MACROS
11 #define __STDC_FORMAT_MACROS
12 #endif
13
14 #include "ShardedCache.h"
15
16 #include <string>
17
18 namespace rocksdb_cache {
19
20 ShardedCache::ShardedCache(size_t capacity, int num_shard_bits,
21 bool strict_capacity_limit)
22 : num_shard_bits_(num_shard_bits),
23 capacity_(capacity),
24 strict_capacity_limit_(strict_capacity_limit),
25 last_id_(1) {}
26
27 void ShardedCache::SetCapacity(size_t capacity) {
28 int num_shards = 1 << num_shard_bits_;
29 const size_t per_shard = (capacity + (num_shards - 1)) / num_shards;
30 std::lock_guard<std::mutex> l(capacity_mutex_);
31 for (int s = 0; s < num_shards; s++) {
32 GetShard(s)->SetCapacity(per_shard);
33 }
34 capacity_ = capacity;
35 }
36
37 void ShardedCache::SetStrictCapacityLimit(bool strict_capacity_limit) {
38 int num_shards = 1 << num_shard_bits_;
39 std::lock_guard<std::mutex> l(capacity_mutex_);
40 for (int s = 0; s < num_shards; s++) {
41 GetShard(s)->SetStrictCapacityLimit(strict_capacity_limit);
42 }
43 strict_capacity_limit_ = strict_capacity_limit;
44 }
45
46 rocksdb::Status ShardedCache::Insert(const rocksdb::Slice& key, void* value, size_t charge,
47 DeleterFn deleter,
48 rocksdb::Cache::Handle** handle, Priority priority) {
49 uint32_t hash = HashSlice(key);
50 return GetShard(Shard(hash))
51 ->Insert(key, hash, value, charge, deleter, handle, priority);
52 }
53
54 rocksdb::Cache::Handle* ShardedCache::Lookup(const rocksdb::Slice& key, rocksdb::Statistics* /*stats*/) {
55 uint32_t hash = HashSlice(key);
56 return GetShard(Shard(hash))->Lookup(key, hash);
57 }
58
59 bool ShardedCache::Ref(rocksdb::Cache::Handle* handle) {
60 uint32_t hash = GetHash(handle);
61 return GetShard(Shard(hash))->Ref(handle);
62 }
63
64 bool ShardedCache::Release(rocksdb::Cache::Handle* handle, bool force_erase) {
65 uint32_t hash = GetHash(handle);
66 return GetShard(Shard(hash))->Release(handle, force_erase);
67 }
68
69 void ShardedCache::Erase(const rocksdb::Slice& key) {
70 uint32_t hash = HashSlice(key);
71 GetShard(Shard(hash))->Erase(key, hash);
72 }
73
74 uint64_t ShardedCache::NewId() {
75 return last_id_.fetch_add(1, std::memory_order_relaxed);
76 }
77
78 size_t ShardedCache::GetCapacity() const {
79 std::lock_guard<std::mutex> l(capacity_mutex_);
80 return capacity_;
81 }
82
83 bool ShardedCache::HasStrictCapacityLimit() const {
84 std::lock_guard<std::mutex> l(capacity_mutex_);
85 return strict_capacity_limit_;
86 }
87
88 size_t ShardedCache::GetUsage() const {
89 // We will not lock the cache when getting the usage from shards.
90 int num_shards = 1 << num_shard_bits_;
91 size_t usage = 0;
92 for (int s = 0; s < num_shards; s++) {
93 usage += GetShard(s)->GetUsage();
94 }
95 return usage;
96 }
97
98 size_t ShardedCache::GetUsage(rocksdb::Cache::Handle* handle) const {
99 return GetCharge(handle);
100 }
101
102 size_t ShardedCache::GetPinnedUsage() const {
103 // We will not lock the cache when getting the usage from shards.
104 int num_shards = 1 << num_shard_bits_;
105 size_t usage = 0;
106 for (int s = 0; s < num_shards; s++) {
107 usage += GetShard(s)->GetPinnedUsage();
108 }
109 return usage;
110 }
111
112 #if (ROCKSDB_MAJOR >= 6 && ROCKSDB_MINOR >= 22)
113 DeleterFn ShardedCache::GetDeleter(Handle* handle) const
114 {
115 uint32_t hash = GetHash(handle);
116 return GetShard(Shard(hash))->GetDeleter(handle);
117 }
118
119 void ShardedCache::ApplyToAllEntries(
120 const std::function<void(const rocksdb::Slice& key, void* value, size_t charge,
121 DeleterFn deleter)>& callback,
122 const ApplyToAllEntriesOptions& opts)
123 {
124 int num_shards = 1 << num_shard_bits_;
125 for (int s = 0; s < num_shards; s++) {
126 GetShard(s)->ApplyToAllCacheEntries(callback, true /* thread_safe */);
127 }
128 }
129 #else
130 void ShardedCache::ApplyToAllCacheEntries(void (*callback)(void*, size_t),
131 bool thread_safe) {
132 int num_shards = 1 << num_shard_bits_;
133 for (int s = 0; s < num_shards; s++) {
134 GetShard(s)->ApplyToAllCacheEntries(
135 [callback](const rocksdb::Slice&, void* value, size_t charge, DeleterFn) {
136 callback(value, charge);
137 },
138 thread_safe);
139 }
140 }
141 #endif
142
143 void ShardedCache::EraseUnRefEntries() {
144 int num_shards = 1 << num_shard_bits_;
145 for (int s = 0; s < num_shards; s++) {
146 GetShard(s)->EraseUnRefEntries();
147 }
148 }
149
150 std::string ShardedCache::GetPrintableOptions() const {
151 std::string ret;
152 ret.reserve(20000);
153 const int kBufferSize = 200;
154 char buffer[kBufferSize];
155 {
156 std::lock_guard<std::mutex> l(capacity_mutex_);
157 snprintf(buffer, kBufferSize, " capacity : %zu\n",
158 capacity_);
159 ret.append(buffer);
160 snprintf(buffer, kBufferSize, " num_shard_bits : %d\n", num_shard_bits_);
161 ret.append(buffer);
162 snprintf(buffer, kBufferSize, " strict_capacity_limit : %d\n",
163 strict_capacity_limit_);
164 ret.append(buffer);
165 }
166 ret.append(GetShard(0)->GetPrintableOptions());
167 return ret;
168 }
169 int GetDefaultCacheShardBits(size_t capacity) {
170 int num_shard_bits = 0;
171 size_t min_shard_size = 512L * 1024L; // Every shard is at least 512KB.
172 size_t num_shards = capacity / min_shard_size;
173 while (num_shards >>= 1) {
174 if (++num_shard_bits >= 6) {
175 // No more than 6.
176 return num_shard_bits;
177 }
178 }
179 return num_shard_bits;
180 }
181
182 } // namespace rocksdb_cache