/src/rocksdb/db/blob/blob_source.h
Line | Count | Source |
1 | | // Copyright (c) Meta Platforms, Inc. and affiliates. |
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 | | #pragma once |
7 | | |
8 | | #include <cinttypes> |
9 | | #include <memory> |
10 | | |
11 | | #include "cache/cache_key.h" |
12 | | #include "cache/typed_cache.h" |
13 | | #include "db/blob/blob_contents.h" |
14 | | #include "db/blob/blob_file_cache.h" |
15 | | #include "db/blob/blob_read_request.h" |
16 | | #include "rocksdb/cache.h" |
17 | | #include "rocksdb/rocksdb_namespace.h" |
18 | | #include "table/block_based/cachable_entry.h" |
19 | | #include "util/autovector.h" |
20 | | |
21 | | namespace ROCKSDB_NAMESPACE { |
22 | | |
23 | | struct ImmutableOptions; |
24 | | struct MutableCFOptions; |
25 | | class Status; |
26 | | class FilePrefetchBuffer; |
27 | | class Slice; |
28 | | |
29 | | // BlobSource is a class that provides universal access to blobs, regardless of |
30 | | // whether they are in the blob cache, secondary cache, or (remote) storage. |
31 | | // Depending on user settings, it always fetch blobs from multi-tier cache and |
32 | | // storage with minimal cost. |
33 | | class BlobSource { |
34 | | public: |
35 | | // NOTE: db_id, db_session_id, and blob_file_cache are saved by reference or |
36 | | // pointer. |
37 | | BlobSource(const ImmutableOptions& immutable_options, |
38 | | const MutableCFOptions& mutable_cf_options, |
39 | | const std::string& db_id, const std::string& db_session_id, |
40 | | BlobFileCache* blob_file_cache); |
41 | | |
42 | | BlobSource(const BlobSource&) = delete; |
43 | | BlobSource& operator=(const BlobSource&) = delete; |
44 | | |
45 | | ~BlobSource(); |
46 | | |
47 | | // Read a blob from the underlying cache or one blob file. |
48 | | // |
49 | | // If successful, returns ok and sets "*value" to the newly retrieved |
50 | | // uncompressed blob. If there was an error while fetching the blob, sets |
51 | | // "*value" to empty and returns a non-ok status. |
52 | | // |
53 | | // Note: For consistency, whether the blob is found in the cache or on disk, |
54 | | // sets "*bytes_read" to the size of on-disk (possibly compressed) blob |
55 | | // record. |
56 | | Status GetBlob(const ReadOptions& read_options, const Slice& user_key, |
57 | | uint64_t file_number, uint64_t offset, uint64_t file_size, |
58 | | uint64_t value_size, CompressionType compression_type, |
59 | | FilePrefetchBuffer* prefetch_buffer, PinnableSlice* value, |
60 | | uint64_t* bytes_read); |
61 | | |
62 | | // Read multiple blobs from the underlying cache or blob file(s). |
63 | | // |
64 | | // If successful, returns ok and sets "result" in the elements of "blob_reqs" |
65 | | // to the newly retrieved uncompressed blobs. If there was an error while |
66 | | // fetching one of blobs, sets its "result" to empty and sets its |
67 | | // corresponding "status" to a non-ok status. |
68 | | // |
69 | | // Note: |
70 | | // - The main difference between this function and MultiGetBlobFromOneFile is |
71 | | // that this function can read multiple blobs from multiple blob files. |
72 | | // |
73 | | // - For consistency, whether the blob is found in the cache or on disk, sets |
74 | | // "*bytes_read" to the total size of on-disk (possibly compressed) blob |
75 | | // records. |
76 | | void MultiGetBlob(const ReadOptions& read_options, |
77 | | autovector<BlobFileReadRequests>& blob_reqs, |
78 | | uint64_t* bytes_read); |
79 | | |
80 | | // Read multiple blobs from the underlying cache or one blob file. |
81 | | // |
82 | | // If successful, returns ok and sets "result" in the elements of "blob_reqs" |
83 | | // to the newly retrieved uncompressed blobs. If there was an error while |
84 | | // fetching one of blobs, sets its "result" to empty and sets its |
85 | | // corresponding "status" to a non-ok status. |
86 | | // |
87 | | // Note: |
88 | | // - The main difference between this function and MultiGetBlob is that this |
89 | | // function is only used for the case where the demanded blobs are stored in |
90 | | // one blob file. MultiGetBlob will call this function multiple times if the |
91 | | // demanded blobs are stored in multiple blob files. |
92 | | // |
93 | | // - For consistency, whether the blob is found in the cache or on disk, sets |
94 | | // "*bytes_read" to the total size of on-disk (possibly compressed) blob |
95 | | // records. |
96 | | void MultiGetBlobFromOneFile(const ReadOptions& read_options, |
97 | | uint64_t file_number, uint64_t file_size, |
98 | | autovector<BlobReadRequest>& blob_reqs, |
99 | | uint64_t* bytes_read); |
100 | | |
101 | | inline Status GetBlobFileReader( |
102 | | const ReadOptions& read_options, uint64_t blob_file_number, |
103 | 0 | CacheHandleGuard<BlobFileReader>* blob_file_reader) { |
104 | 0 | return blob_file_cache_->GetBlobFileReader(read_options, blob_file_number, |
105 | 0 | blob_file_reader); |
106 | 0 | } |
107 | | |
108 | 0 | inline Cache* GetBlobCache() const { return blob_cache_.get(); } |
109 | | |
110 | | bool TEST_BlobInCache(uint64_t file_number, uint64_t file_size, |
111 | | uint64_t offset, size_t* charge = nullptr) const; |
112 | | |
113 | | // For TypedSharedCacheInterface |
114 | | void Create(BlobContents** out, const char* buf, size_t size, |
115 | | MemoryAllocator* alloc); |
116 | | |
117 | | using SharedCacheInterface = |
118 | | FullTypedSharedCacheInterface<BlobContents, BlobContentsCreator>; |
119 | | using TypedHandle = SharedCacheInterface::TypedHandle; |
120 | | |
121 | | private: |
122 | | Status GetBlobFromCache(const Slice& cache_key, |
123 | | CacheHandleGuard<BlobContents>* cached_blob) const; |
124 | | |
125 | | Status PutBlobIntoCache(const Slice& cache_key, |
126 | | std::unique_ptr<BlobContents>* blob, |
127 | | CacheHandleGuard<BlobContents>* cached_blob) const; |
128 | | |
129 | | static void PinCachedBlob(CacheHandleGuard<BlobContents>* cached_blob, |
130 | | PinnableSlice* value); |
131 | | |
132 | | static void PinOwnedBlob(std::unique_ptr<BlobContents>* owned_blob, |
133 | | PinnableSlice* value); |
134 | | |
135 | | TypedHandle* GetEntryFromCache(const Slice& key) const; |
136 | | |
137 | | Status InsertEntryIntoCache(const Slice& key, BlobContents* value, |
138 | | TypedHandle** cache_handle, |
139 | | Cache::Priority priority) const; |
140 | | |
141 | | inline CacheKey GetCacheKey(uint64_t file_number, uint64_t /*file_size*/, |
142 | 0 | uint64_t offset) const { |
143 | 0 | OffsetableCacheKey base_cache_key(db_id_, db_session_id_, file_number); |
144 | 0 | return base_cache_key.WithOffset(offset); |
145 | 0 | } |
146 | | |
147 | | const std::string& db_id_; |
148 | | const std::string& db_session_id_; |
149 | | |
150 | | Statistics* statistics_; |
151 | | |
152 | | // A cache to store blob file reader. |
153 | | BlobFileCache* blob_file_cache_; |
154 | | |
155 | | // A cache to store uncompressed blobs. |
156 | | mutable SharedCacheInterface blob_cache_; |
157 | | |
158 | | // The control option of how the cache tiers will be used. Currently rocksdb |
159 | | // support block/blob cache (volatile tier) and secondary cache (this tier |
160 | | // isn't strictly speaking a non-volatile tier since the compressed cache in |
161 | | // this tier is in volatile memory). |
162 | | const CacheTier lowest_used_cache_tier_; |
163 | | }; |
164 | | |
165 | | } // namespace ROCKSDB_NAMESPACE |