]>
Commit | Line | Data |
---|---|---|
1e59de90 TL |
1 | // Copyright (c) 2021, 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 | #pragma once | |
6 | ||
7 | #include <stdint.h> | |
8 | ||
9 | #include <memory> | |
10 | #include <string> | |
11 | ||
12 | #include "rocksdb/cache.h" | |
13 | #include "rocksdb/customizable.h" | |
14 | #include "rocksdb/slice.h" | |
15 | #include "rocksdb/statistics.h" | |
16 | #include "rocksdb/status.h" | |
17 | ||
18 | namespace ROCKSDB_NAMESPACE { | |
19 | ||
20 | // A handle for lookup result. The handle may not be immediately ready or | |
21 | // have a valid value. The caller must call isReady() to determine if its | |
22 | // ready, and call Wait() in order to block until it becomes ready. | |
23 | // The caller must call value() after it becomes ready to determine if the | |
24 | // handle successfullly read the item. | |
25 | class SecondaryCacheResultHandle { | |
26 | public: | |
27 | virtual ~SecondaryCacheResultHandle() = default; | |
28 | ||
29 | // Returns whether the handle is ready or not | |
30 | virtual bool IsReady() = 0; | |
31 | ||
32 | // Block until handle becomes ready | |
33 | virtual void Wait() = 0; | |
34 | ||
35 | // Return the value. If nullptr, it means the lookup was unsuccessful | |
36 | virtual void* Value() = 0; | |
37 | ||
38 | // Return the size of value | |
39 | virtual size_t Size() = 0; | |
40 | }; | |
41 | ||
42 | // SecondaryCache | |
43 | // | |
44 | // Cache interface for caching blocks on a secondary tier (which can include | |
45 | // non-volatile media, or alternate forms of caching such as compressed data) | |
46 | // | |
47 | // Exceptions MUST NOT propagate out of overridden functions into RocksDB, | |
48 | // because RocksDB is not exception-safe. This could cause undefined behavior | |
49 | // including data loss, unreported corruption, deadlocks, and more. | |
50 | class SecondaryCache : public Customizable { | |
51 | public: | |
52 | ~SecondaryCache() override = default; | |
53 | ||
54 | static const char* Type() { return "SecondaryCache"; } | |
55 | static Status CreateFromString(const ConfigOptions& config_options, | |
56 | const std::string& id, | |
57 | std::shared_ptr<SecondaryCache>* result); | |
58 | ||
59 | // Insert the given value into this cache. Ownership of `value` is | |
60 | // transferred to the callee, who is reponsible for deleting the value | |
61 | // with helper->del_cb if del_cb is not nullptr. Unlike Cache::Insert(), | |
62 | // the callee is responsible for such cleanup even in case of non-OK | |
63 | // Status. | |
64 | // Typically, the value is not saved directly but the implementation | |
65 | // uses the SaveToCallback provided by helper to extract value's | |
66 | // persistable data (typically uncompressed block), which will be written | |
67 | // to this tier. The implementation may or may not write it to cache | |
68 | // depending on the admission control policy, even if the return status | |
69 | // is success (OK). | |
70 | // | |
71 | // If the implementation is asynchronous or otherwise uses `value` after | |
72 | // the call returns, then InsertSaved() must be overridden not to rely on | |
73 | // Insert(). For example, there could be a "holding area" in memory where | |
74 | // Lookup() might return the same parsed value back. But more typically, if | |
75 | // the implementation only uses `value` for getting persistable data during | |
76 | // the call, then the default implementation of `InsertSaved()` suffices. | |
77 | virtual Status Insert(const Slice& key, void* value, | |
78 | const Cache::CacheItemHelper* helper) = 0; | |
79 | ||
80 | // Insert a value from its saved/persistable data (typically uncompressed | |
81 | // block), as if generated by SaveToCallback/SizeCallback. This can be used | |
82 | // in "warming up" the cache from some auxiliary source, and like Insert() | |
83 | // may or may not write it to cache depending on the admission control | |
84 | // policy, even if the return status is success. | |
85 | // | |
86 | // The default implementation assumes synchronous, non-escaping Insert(), | |
87 | // wherein `value` is not used after return of Insert(). See Insert(). | |
88 | virtual Status InsertSaved(const Slice& key, const Slice& saved); | |
89 | ||
90 | // Lookup the data for the given key in this cache. The create_cb | |
91 | // will be used to create the object. The handle returned may not be | |
92 | // ready yet, unless wait=true, in which case Lookup() will block until | |
93 | // the handle is ready. | |
94 | // | |
95 | // advise_erase is a hint from the primary cache indicating that the handle | |
96 | // will be cached there, so the secondary cache is advised to drop it from | |
97 | // the cache as an optimization. To use this feature, SupportForceErase() | |
98 | // needs to return true. | |
99 | // This hint can also be safely ignored. | |
100 | // | |
101 | // is_in_sec_cache is to indicate whether the handle is possibly erased | |
102 | // from the secondary cache after the Lookup. | |
103 | virtual std::unique_ptr<SecondaryCacheResultHandle> Lookup( | |
104 | const Slice& key, const Cache::CreateCallback& create_cb, bool wait, | |
105 | bool advise_erase, bool& is_in_sec_cache) = 0; | |
106 | ||
107 | // Indicate whether a handle can be erased in this secondary cache. | |
108 | [[nodiscard]] virtual bool SupportForceErase() const = 0; | |
109 | ||
110 | // At the discretion of the implementation, erase the data associated | |
111 | // with key. | |
112 | virtual void Erase(const Slice& key) = 0; | |
113 | ||
114 | // Wait for a collection of handles to become ready. | |
115 | virtual void WaitAll(std::vector<SecondaryCacheResultHandle*> handles) = 0; | |
116 | ||
117 | // Set the maximum configured capacity of the cache. | |
118 | // When the new capacity is less than the old capacity and the existing usage | |
119 | // is greater than new capacity, the implementation will do its best job to | |
120 | // purge the released entries from the cache in order to lower the usage. | |
121 | // | |
122 | // The derived class can make this function no-op and return NotSupported(). | |
123 | virtual Status SetCapacity(size_t /* capacity */) { | |
124 | return Status::NotSupported(); | |
125 | } | |
126 | ||
127 | // The derived class can make this function no-op and return NotSupported(). | |
128 | virtual Status GetCapacity(size_t& /* capacity */) { | |
129 | return Status::NotSupported(); | |
130 | } | |
131 | }; | |
132 | ||
133 | } // namespace ROCKSDB_NAMESPACE |