|
1 | 1 | /* |
2 | | - * Copyright (C) 2019 HERE Europe B.V. |
| 2 | + * Copyright (C) 2019-2020 HERE Europe B.V. |
3 | 3 | * |
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | 5 | * you may not use this file except in compliance with the License. |
|
21 | 21 |
|
22 | 22 | #include "olp/core/cache/DefaultCache.h" |
23 | 23 |
|
24 | | -#include "DiskCache.h" |
25 | | -#include "InMemoryCache.h" |
26 | | -#include "olp/core/logging/Log.h" |
27 | | -#include "olp/core/porting/make_unique.h" |
28 | | - |
29 | | -namespace { |
30 | | - |
31 | | -constexpr auto kLogTag = "DefaultCache"; |
32 | | - |
33 | | -std::string CreateExpiryKey(const std::string& key) { return key + "::expiry"; } |
34 | | - |
35 | | -time_t GetRemainingExpiryTime(const std::string& key, |
36 | | - olp::cache::DiskCache& disk_cache) { |
37 | | - auto expiry_key = CreateExpiryKey(key); |
38 | | - auto expiry = olp::cache::KeyValueCache::kDefaultExpiry; |
39 | | - auto expiry_value = disk_cache.Get(expiry_key); |
40 | | - if (expiry_value) { |
41 | | - expiry = std::stol(*expiry_value); |
42 | | - expiry -= olp::cache::InMemoryCache::DefaultTimeProvider()(); |
43 | | - } |
44 | | - |
45 | | - return expiry; |
46 | | -} |
47 | | - |
48 | | -void PurgeDiskItem(const std::string& key, olp::cache::DiskCache& disk_cache) { |
49 | | - auto expiry_key = CreateExpiryKey(key); |
50 | | - disk_cache.Remove(key); |
51 | | - disk_cache.Remove(expiry_key); |
52 | | -} |
53 | | - |
54 | | -bool StoreExpiry(const std::string& key, olp::cache::DiskCache& disk_cache, |
55 | | - time_t expiry) { |
56 | | - auto expiry_key = CreateExpiryKey(key); |
57 | | - return disk_cache.Put( |
58 | | - expiry_key, |
59 | | - std::to_string(expiry + |
60 | | - olp::cache::InMemoryCache::DefaultTimeProvider()())); |
61 | | -} |
62 | | - |
63 | | -} // namespace |
| 24 | +#include "DefaultCacheImpl.h" |
64 | 25 |
|
65 | 26 | namespace olp { |
66 | 27 | namespace cache { |
67 | 28 |
|
68 | 29 | DefaultCache::DefaultCache(CacheSettings settings) |
69 | | - : settings_(std::move(settings)), |
70 | | - is_open_(false), |
71 | | - memory_cache_(nullptr), |
72 | | - mutable_cache_(nullptr), |
73 | | - protected_cache_(nullptr) {} |
| 30 | + : impl_(std::make_shared<DefaultCacheImpl>(std::move(settings))) {} |
74 | 31 |
|
75 | 32 | DefaultCache::~DefaultCache() = default; |
76 | 33 |
|
77 | | -DefaultCache::StorageOpenResult DefaultCache::Open() { |
78 | | - std::lock_guard<std::mutex> lock(cache_lock_); |
79 | | - is_open_ = true; |
80 | | - return SetupStorage(); |
81 | | -} |
82 | | - |
83 | | -void DefaultCache::Close() { |
84 | | - std::lock_guard<std::mutex> lock(cache_lock_); |
85 | | - if (!is_open_) { |
86 | | - return; |
87 | | - } |
88 | | - |
89 | | - memory_cache_.reset(); |
90 | | - mutable_cache_.reset(); |
91 | | - protected_cache_.reset(); |
92 | | - is_open_ = false; |
93 | | -} |
94 | | - |
95 | | -bool DefaultCache::Clear() { |
96 | | - std::lock_guard<std::mutex> lock(cache_lock_); |
97 | | - if (!is_open_) { |
98 | | - return false; |
99 | | - } |
| 34 | +DefaultCache::StorageOpenResult DefaultCache::Open() { return impl_->Open(); } |
100 | 35 |
|
101 | | - if (memory_cache_) { |
102 | | - memory_cache_->Clear(); |
103 | | - } |
| 36 | +void DefaultCache::Close() { impl_->Close(); } |
104 | 37 |
|
105 | | - if (mutable_cache_) { |
106 | | - if (!mutable_cache_->Clear()) { |
107 | | - return false; |
108 | | - } |
109 | | - } |
110 | | - |
111 | | - return SetupStorage() == DefaultCache::StorageOpenResult::Success; |
112 | | -} |
| 38 | +bool DefaultCache::Clear() { return impl_->Clear(); } |
113 | 39 |
|
114 | 40 | bool DefaultCache::Put(const std::string& key, const boost::any& value, |
115 | 41 | const Encoder& encoder, time_t expiry) { |
116 | | - std::lock_guard<std::mutex> lock(cache_lock_); |
117 | | - if (!is_open_) { |
118 | | - return false; |
119 | | - } |
120 | | - |
121 | | - auto encoded_item = encoder(); |
122 | | - if (memory_cache_) { |
123 | | - const auto size = encoded_item.size(); |
124 | | - const bool result = memory_cache_->Put(key, value, expiry, size); |
125 | | - if (!result && size > settings_.max_memory_cache_size) { |
126 | | - OLP_SDK_LOG_WARNING_F(kLogTag, |
127 | | - "Failed to store value in memory cache %s, size %d", |
128 | | - key.c_str(), static_cast<int>(size)); |
129 | | - } |
130 | | - } |
131 | | - |
132 | | - if (mutable_cache_) { |
133 | | - if (expiry < KeyValueCache::kDefaultExpiry) { |
134 | | - if (!StoreExpiry(key, *mutable_cache_, expiry)) { |
135 | | - return false; |
136 | | - } |
137 | | - } |
138 | | - |
139 | | - if (!mutable_cache_->Put(key, encoded_item)) { |
140 | | - return false; |
141 | | - } |
142 | | - } |
143 | | - |
144 | | - return true; |
| 42 | + return impl_->Put(key, value, encoder, expiry); |
145 | 43 | } |
146 | 44 |
|
147 | 45 | bool DefaultCache::Put(const std::string& key, |
148 | 46 | const KeyValueCache::ValueTypePtr value, time_t expiry) { |
149 | | - std::lock_guard<std::mutex> lock(cache_lock_); |
150 | | - if (!is_open_) { |
151 | | - return false; |
152 | | - } |
153 | | - |
154 | | - if (memory_cache_) { |
155 | | - const auto size = value->size(); |
156 | | - const bool result = memory_cache_->Put(key, value, expiry, size); |
157 | | - if (!result && size > settings_.max_memory_cache_size) { |
158 | | - OLP_SDK_LOG_WARNING_F(kLogTag, |
159 | | - "Failed to store value in memory cache %s, size %d", |
160 | | - key.c_str(), static_cast<int>(size)); |
161 | | - } |
162 | | - } |
163 | | - |
164 | | - if (mutable_cache_) { |
165 | | - if (expiry < KeyValueCache::kDefaultExpiry) { |
166 | | - if (!StoreExpiry(key, *mutable_cache_, expiry)) { |
167 | | - return false; |
168 | | - } |
169 | | - } |
170 | | - |
171 | | - leveldb::Slice slice(reinterpret_cast<const char*>(value->data()), |
172 | | - value->size()); |
173 | | - if (!mutable_cache_->Put(key, slice)) { |
174 | | - return false; |
175 | | - } |
176 | | - } |
177 | | - |
178 | | - return true; |
| 47 | + return impl_->Put(key, value, expiry); |
179 | 48 | } |
180 | 49 |
|
181 | 50 | boost::any DefaultCache::Get(const std::string& key, const Decoder& decoder) { |
182 | | - std::lock_guard<std::mutex> lock(cache_lock_); |
183 | | - if (!is_open_) { |
184 | | - return boost::any(); |
185 | | - } |
186 | | - |
187 | | - if (memory_cache_) { |
188 | | - auto value = memory_cache_->Get(key); |
189 | | - if (!value.empty()) { |
190 | | - return value; |
191 | | - } |
192 | | - } |
193 | | - |
194 | | - auto disc_cache = GetFromDiscCache(key); |
195 | | - |
196 | | - if (disc_cache) { |
197 | | - auto decoded_item = decoder(disc_cache->first); |
198 | | - if (memory_cache_) { |
199 | | - memory_cache_->Put(key, decoded_item, disc_cache->second, |
200 | | - disc_cache->first.size()); |
201 | | - } |
202 | | - return decoded_item; |
203 | | - } |
204 | | - |
205 | | - return boost::any(); |
| 51 | + return impl_->Get(key, decoder); |
206 | 52 | } |
207 | 53 |
|
208 | 54 | KeyValueCache::ValueTypePtr DefaultCache::Get(const std::string& key) { |
209 | | - std::lock_guard<std::mutex> lock(cache_lock_); |
210 | | - if (!is_open_) { |
211 | | - return nullptr; |
212 | | - } |
213 | | - |
214 | | - if (memory_cache_) { |
215 | | - auto value = memory_cache_->Get(key); |
216 | | - |
217 | | - if (!value.empty()) { |
218 | | - return boost::any_cast<KeyValueCache::ValueTypePtr>(value); |
219 | | - } |
220 | | - } |
221 | | - |
222 | | - auto disc_cache = GetFromDiscCache(key); |
223 | | - if (disc_cache) { |
224 | | - const std::string& cached_data = disc_cache->first; |
225 | | - auto data = std::make_shared<KeyValueCache::ValueType>(cached_data.size()); |
226 | | - |
227 | | - std::memcpy(&data->front(), cached_data.data(), cached_data.size()); |
228 | | - |
229 | | - if (memory_cache_) { |
230 | | - memory_cache_->Put(key, data, disc_cache->second, data->size()); |
231 | | - } |
232 | | - return data; |
233 | | - } |
234 | | - |
235 | | - return nullptr; |
| 55 | + return impl_->Get(key); |
236 | 56 | } |
237 | 57 |
|
238 | | -bool DefaultCache::Remove(const std::string& key) { |
239 | | - std::lock_guard<std::mutex> lock(cache_lock_); |
240 | | - if (!is_open_) { |
241 | | - return false; |
242 | | - } |
243 | | - |
244 | | - if (memory_cache_) { |
245 | | - memory_cache_->Remove(key); |
246 | | - } |
247 | | - |
248 | | - if (mutable_cache_) { |
249 | | - if (!mutable_cache_->Remove(key)) { |
250 | | - return false; |
251 | | - } |
252 | | - } |
253 | | - |
254 | | - return true; |
255 | | -} |
| 58 | +bool DefaultCache::Remove(const std::string& key) { return impl_->Remove(key); } |
256 | 59 |
|
257 | 60 | bool DefaultCache::RemoveKeysWithPrefix(const std::string& key) { |
258 | | - std::lock_guard<std::mutex> lock(cache_lock_); |
259 | | - if (!is_open_) { |
260 | | - return false; |
261 | | - } |
262 | | - |
263 | | - if (memory_cache_) { |
264 | | - memory_cache_->RemoveKeysWithPrefix(key); |
265 | | - } |
266 | | - |
267 | | - if (mutable_cache_) { |
268 | | - return mutable_cache_->RemoveKeysWithPrefix(key); |
269 | | - } |
270 | | - return true; |
271 | | -} |
272 | | - |
273 | | -DefaultCache::StorageOpenResult DefaultCache::SetupStorage() { |
274 | | - auto result = Success; |
275 | | - |
276 | | - memory_cache_.reset(); |
277 | | - mutable_cache_.reset(); |
278 | | - protected_cache_.reset(); |
279 | | - |
280 | | - if (settings_.max_memory_cache_size > 0) { |
281 | | - memory_cache_.reset(new InMemoryCache(settings_.max_memory_cache_size)); |
282 | | - } |
283 | | - |
284 | | - if (settings_.disk_path_mutable) { |
285 | | - StorageSettings storage_settings; |
286 | | - storage_settings.max_disk_storage = settings_.max_disk_storage; |
287 | | - storage_settings.max_chunk_size = settings_.max_chunk_size; |
288 | | - storage_settings.enforce_immediate_flush = |
289 | | - settings_.enforce_immediate_flush; |
290 | | - storage_settings.max_file_size = settings_.max_file_size; |
291 | | - |
292 | | - mutable_cache_ = std::make_unique<DiskCache>(); |
293 | | - auto status = mutable_cache_->Open(settings_.disk_path_mutable.get(), |
294 | | - settings_.disk_path_mutable.get(), |
295 | | - storage_settings, OpenOptions::Default); |
296 | | - if (status == OpenResult::Fail) { |
297 | | - OLP_SDK_LOG_ERROR_F(kLogTag, "Failed to open the mutable cache %s", |
298 | | - settings_.disk_path_mutable.get().c_str()); |
299 | | - |
300 | | - mutable_cache_.reset(); |
301 | | - settings_.disk_path_mutable = boost::none; |
302 | | - result = OpenDiskPathFailure; |
303 | | - } |
304 | | - } |
305 | | - |
306 | | - if (settings_.disk_path_protected) { |
307 | | - protected_cache_ = std::make_unique<DiskCache>(); |
308 | | - auto status = |
309 | | - protected_cache_->Open(settings_.disk_path_protected.get(), |
310 | | - settings_.disk_path_protected.get(), |
311 | | - StorageSettings{}, OpenOptions::ReadOnly); |
312 | | - if (status == OpenResult::Fail) { |
313 | | - OLP_SDK_LOG_ERROR_F(kLogTag, "Failed to reopen protected cache %s", |
314 | | - settings_.disk_path_protected.get().c_str()); |
315 | | - |
316 | | - protected_cache_.reset(); |
317 | | - settings_.disk_path_protected = boost::none; |
318 | | - result = OpenDiskPathFailure; |
319 | | - } |
320 | | - } |
321 | | - |
322 | | - return result; |
323 | | -} |
324 | | - |
325 | | -boost::optional<std::pair<std::string, time_t>> DefaultCache::GetFromDiscCache( |
326 | | - const std::string& key) { |
327 | | - if (protected_cache_) { |
328 | | - auto result = protected_cache_->Get(key); |
329 | | - if (result) { |
330 | | - auto default_expiry = KeyValueCache::kDefaultExpiry; |
331 | | - return std::make_pair(std::move(result.value()), default_expiry); |
332 | | - } |
333 | | - } |
334 | | - |
335 | | - if (mutable_cache_) { |
336 | | - auto expiry = GetRemainingExpiryTime(key, *mutable_cache_); |
337 | | - if (expiry <= 0) { |
338 | | - PurgeDiskItem(key, *mutable_cache_); |
339 | | - } else { |
340 | | - auto result = mutable_cache_->Get(key); |
341 | | - |
342 | | - if (result) { |
343 | | - return std::make_pair(std::move(result.value()), expiry); |
344 | | - } |
345 | | - } |
346 | | - } |
347 | | - return boost::none; |
| 61 | + return impl_->RemoveKeysWithPrefix(key); |
348 | 62 | } |
349 | 63 |
|
350 | 64 | } // namespace cache |
|
0 commit comments