/src/rocksdb/cache/cache.cc
Line | Count | Source (jump to first uncovered line) |
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 | | // |
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 | | #include "rocksdb/cache.h" |
11 | | |
12 | | #include "cache/lru_cache.h" |
13 | | #include "rocksdb/secondary_cache.h" |
14 | | #include "rocksdb/utilities/customizable_util.h" |
15 | | #include "rocksdb/utilities/options_type.h" |
16 | | #include "util/string_util.h" |
17 | | |
18 | | namespace ROCKSDB_NAMESPACE { |
19 | | const Cache::CacheItemHelper kNoopCacheItemHelper{}; |
20 | | |
21 | | static std::unordered_map<std::string, OptionTypeInfo> |
22 | | lru_cache_options_type_info = { |
23 | | {"capacity", |
24 | | {offsetof(struct LRUCacheOptions, capacity), OptionType::kSizeT, |
25 | | OptionVerificationType::kNormal, OptionTypeFlags::kMutable}}, |
26 | | {"num_shard_bits", |
27 | | {offsetof(struct LRUCacheOptions, num_shard_bits), OptionType::kInt, |
28 | | OptionVerificationType::kNormal, OptionTypeFlags::kMutable}}, |
29 | | {"strict_capacity_limit", |
30 | | {offsetof(struct LRUCacheOptions, strict_capacity_limit), |
31 | | OptionType::kBoolean, OptionVerificationType::kNormal, |
32 | | OptionTypeFlags::kMutable}}, |
33 | | {"high_pri_pool_ratio", |
34 | | {offsetof(struct LRUCacheOptions, high_pri_pool_ratio), |
35 | | OptionType::kDouble, OptionVerificationType::kNormal, |
36 | | OptionTypeFlags::kMutable}}, |
37 | | {"low_pri_pool_ratio", |
38 | | {offsetof(struct LRUCacheOptions, low_pri_pool_ratio), |
39 | | OptionType::kDouble, OptionVerificationType::kNormal, |
40 | | OptionTypeFlags::kMutable}}, |
41 | | }; |
42 | | |
43 | | static std::unordered_map<std::string, OptionTypeInfo> |
44 | | comp_sec_cache_options_type_info = { |
45 | | {"capacity", |
46 | | {offsetof(struct CompressedSecondaryCacheOptions, capacity), |
47 | | OptionType::kSizeT, OptionVerificationType::kNormal, |
48 | | OptionTypeFlags::kMutable}}, |
49 | | {"num_shard_bits", |
50 | | {offsetof(struct CompressedSecondaryCacheOptions, num_shard_bits), |
51 | | OptionType::kInt, OptionVerificationType::kNormal, |
52 | | OptionTypeFlags::kMutable}}, |
53 | | {"compression_type", |
54 | | {offsetof(struct CompressedSecondaryCacheOptions, compression_type), |
55 | | OptionType::kCompressionType, OptionVerificationType::kNormal, |
56 | | OptionTypeFlags::kMutable}}, |
57 | | {"compress_format_version", |
58 | | {offsetof(struct CompressedSecondaryCacheOptions, |
59 | | compress_format_version), |
60 | | OptionType::kUInt32T, OptionVerificationType::kNormal, |
61 | | OptionTypeFlags::kMutable}}, |
62 | | {"enable_custom_split_merge", |
63 | | {offsetof(struct CompressedSecondaryCacheOptions, |
64 | | enable_custom_split_merge), |
65 | | OptionType::kBoolean, OptionVerificationType::kNormal, |
66 | | OptionTypeFlags::kMutable}}, |
67 | | }; |
68 | | |
69 | | namespace { |
70 | | static void NoopDelete(Cache::ObjectPtr /*obj*/, |
71 | 0 | MemoryAllocator* /*allocator*/) { |
72 | 0 | assert(false); |
73 | 0 | } |
74 | | |
75 | 0 | static size_t SliceSize(Cache::ObjectPtr obj) { |
76 | 0 | return static_cast<Slice*>(obj)->size(); |
77 | 0 | } |
78 | | |
79 | | static Status SliceSaveTo(Cache::ObjectPtr from_obj, size_t from_offset, |
80 | 0 | size_t length, char* out) { |
81 | 0 | const Slice& slice = *static_cast<Slice*>(from_obj); |
82 | 0 | std::memcpy(out, slice.data() + from_offset, length); |
83 | 0 | return Status::OK(); |
84 | 0 | } |
85 | | |
86 | | static Status NoopCreate(const Slice& /*data*/, CompressionType /*type*/, |
87 | | CacheTier /*source*/, Cache::CreateContext* /*ctx*/, |
88 | | MemoryAllocator* /*allocator*/, |
89 | | Cache::ObjectPtr* /*out_obj*/, |
90 | 0 | size_t* /*out_charge*/) { |
91 | 0 | assert(false); |
92 | 0 | return Status::NotSupported(); |
93 | 0 | } |
94 | | |
95 | | static Cache::CacheItemHelper kBasicCacheItemHelper(CacheEntryRole::kMisc, |
96 | | &NoopDelete); |
97 | | } // namespace |
98 | | |
99 | | const Cache::CacheItemHelper kSliceCacheItemHelper{ |
100 | | CacheEntryRole::kMisc, &NoopDelete, &SliceSize, |
101 | | &SliceSaveTo, &NoopCreate, &kBasicCacheItemHelper, |
102 | | }; |
103 | | |
104 | | Status SecondaryCache::CreateFromString( |
105 | | const ConfigOptions& config_options, const std::string& value, |
106 | 0 | std::shared_ptr<SecondaryCache>* result) { |
107 | 0 | if (value.find("compressed_secondary_cache://") == 0) { |
108 | 0 | std::string args = value; |
109 | 0 | args.erase(0, std::strlen("compressed_secondary_cache://")); |
110 | 0 | Status status; |
111 | 0 | std::shared_ptr<SecondaryCache> sec_cache; |
112 | |
|
113 | 0 | CompressedSecondaryCacheOptions sec_cache_opts; |
114 | 0 | status = OptionTypeInfo::ParseStruct(config_options, "", |
115 | 0 | &comp_sec_cache_options_type_info, "", |
116 | 0 | args, &sec_cache_opts); |
117 | 0 | if (status.ok()) { |
118 | 0 | sec_cache = NewCompressedSecondaryCache(sec_cache_opts); |
119 | 0 | } |
120 | | |
121 | |
|
122 | 0 | if (status.ok()) { |
123 | 0 | result->swap(sec_cache); |
124 | 0 | } |
125 | 0 | return status; |
126 | 0 | } else { |
127 | 0 | return LoadSharedObject<SecondaryCache>(config_options, value, result); |
128 | 0 | } |
129 | 0 | } |
130 | | |
131 | | Status Cache::CreateFromString(const ConfigOptions& config_options, |
132 | | const std::string& value, |
133 | 0 | std::shared_ptr<Cache>* result) { |
134 | 0 | Status status; |
135 | 0 | std::shared_ptr<Cache> cache; |
136 | 0 | if (value.find('=') == std::string::npos) { |
137 | 0 | cache = NewLRUCache(ParseSizeT(value)); |
138 | 0 | } else { |
139 | 0 | LRUCacheOptions cache_opts; |
140 | 0 | status = OptionTypeInfo::ParseStruct(config_options, "", |
141 | 0 | &lru_cache_options_type_info, "", |
142 | 0 | value, &cache_opts); |
143 | 0 | if (status.ok()) { |
144 | 0 | cache = NewLRUCache(cache_opts); |
145 | 0 | } |
146 | 0 | } |
147 | 0 | if (status.ok()) { |
148 | 0 | result->swap(cache); |
149 | 0 | } |
150 | 0 | return status; |
151 | 0 | } |
152 | | |
153 | 0 | bool Cache::AsyncLookupHandle::IsReady() { |
154 | 0 | return pending_handle == nullptr || pending_handle->IsReady(); |
155 | 0 | } |
156 | | |
157 | 0 | bool Cache::AsyncLookupHandle::IsPending() { return pending_handle != nullptr; } |
158 | | |
159 | 0 | Cache::Handle* Cache::AsyncLookupHandle::Result() { |
160 | 0 | assert(!IsPending()); |
161 | 0 | return result_handle; |
162 | 0 | } |
163 | | |
164 | 0 | void Cache::StartAsyncLookup(AsyncLookupHandle& async_handle) { |
165 | 0 | async_handle.found_dummy_entry = false; // in case re-used |
166 | 0 | assert(!async_handle.IsPending()); |
167 | 0 | async_handle.result_handle = |
168 | 0 | Lookup(async_handle.key, async_handle.helper, async_handle.create_context, |
169 | 0 | async_handle.priority, async_handle.stats); |
170 | 0 | } |
171 | | |
172 | 0 | Cache::Handle* Cache::Wait(AsyncLookupHandle& async_handle) { |
173 | 0 | WaitAll(&async_handle, 1); |
174 | 0 | return async_handle.Result(); |
175 | 0 | } |
176 | | |
177 | 0 | void Cache::WaitAll(AsyncLookupHandle* async_handles, size_t count) { |
178 | 0 | for (size_t i = 0; i < count; ++i) { |
179 | 0 | if (async_handles[i].IsPending()) { |
180 | | // If a pending handle gets here, it should be marked at "to be handled |
181 | | // by a caller" by that caller erasing the pending_cache on it. |
182 | 0 | assert(async_handles[i].pending_cache == nullptr); |
183 | 0 | } |
184 | 0 | } |
185 | 0 | } |
186 | | |
187 | 0 | void Cache::SetEvictionCallback(EvictionCallback&& fn) { |
188 | | // Overwriting non-empty with non-empty could indicate a bug |
189 | 0 | assert(!eviction_callback_ || !fn); |
190 | 0 | eviction_callback_ = std::move(fn); |
191 | 0 | } |
192 | | |
193 | | } // namespace ROCKSDB_NAMESPACE |