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).
11 #include "cache/cache_helpers.h"
12 #include "cache/cache_key.h"
13 #include "db/blob/blob_file_cache.h"
14 #include "db/blob/blob_read_request.h"
15 #include "rocksdb/cache.h"
16 #include "rocksdb/rocksdb_namespace.h"
17 #include "table/block_based/cachable_entry.h"
18 #include "util/autovector.h"
20 namespace ROCKSDB_NAMESPACE
{
22 struct ImmutableOptions
;
24 class FilePrefetchBuffer
;
28 // BlobSource is a class that provides universal access to blobs, regardless of
29 // whether they are in the blob cache, secondary cache, or (remote) storage.
30 // Depending on user settings, it always fetch blobs from multi-tier cache and
31 // storage with minimal cost.
34 BlobSource(const ImmutableOptions
* immutable_options
,
35 const std::string
& db_id
, const std::string
& db_session_id
,
36 BlobFileCache
* blob_file_cache
);
38 BlobSource(const BlobSource
&) = delete;
39 BlobSource
& operator=(const BlobSource
&) = delete;
43 // Read a blob from the underlying cache or one blob file.
45 // If successful, returns ok and sets "*value" to the newly retrieved
46 // uncompressed blob. If there was an error while fetching the blob, sets
47 // "*value" to empty and returns a non-ok status.
49 // Note: For consistency, whether the blob is found in the cache or on disk,
50 // sets "*bytes_read" to the size of on-disk (possibly compressed) blob
52 Status
GetBlob(const ReadOptions
& read_options
, const Slice
& user_key
,
53 uint64_t file_number
, uint64_t offset
, uint64_t file_size
,
54 uint64_t value_size
, CompressionType compression_type
,
55 FilePrefetchBuffer
* prefetch_buffer
, PinnableSlice
* value
,
56 uint64_t* bytes_read
);
58 // Read multiple blobs from the underlying cache or blob file(s).
60 // If successful, returns ok and sets "result" in the elements of "blob_reqs"
61 // to the newly retrieved uncompressed blobs. If there was an error while
62 // fetching one of blobs, sets its "result" to empty and sets its
63 // corresponding "status" to a non-ok status.
66 // - The main difference between this function and MultiGetBlobFromOneFile is
67 // that this function can read multiple blobs from multiple blob files.
69 // - For consistency, whether the blob is found in the cache or on disk, sets
70 // "*bytes_read" to the total size of on-disk (possibly compressed) blob
72 void MultiGetBlob(const ReadOptions
& read_options
,
73 autovector
<BlobFileReadRequests
>& blob_reqs
,
74 uint64_t* bytes_read
);
76 // Read multiple blobs from the underlying cache or one blob file.
78 // If successful, returns ok and sets "result" in the elements of "blob_reqs"
79 // to the newly retrieved uncompressed blobs. If there was an error while
80 // fetching one of blobs, sets its "result" to empty and sets its
81 // corresponding "status" to a non-ok status.
84 // - The main difference between this function and MultiGetBlob is that this
85 // function is only used for the case where the demanded blobs are stored in
86 // one blob file. MultiGetBlob will call this function multiple times if the
87 // demanded blobs are stored in multiple blob files.
89 // - For consistency, whether the blob is found in the cache or on disk, sets
90 // "*bytes_read" to the total size of on-disk (possibly compressed) blob
92 void MultiGetBlobFromOneFile(const ReadOptions
& read_options
,
93 uint64_t file_number
, uint64_t file_size
,
94 autovector
<BlobReadRequest
>& blob_reqs
,
95 uint64_t* bytes_read
);
97 inline Status
GetBlobFileReader(
98 uint64_t blob_file_number
,
99 CacheHandleGuard
<BlobFileReader
>* blob_file_reader
) {
100 return blob_file_cache_
->GetBlobFileReader(blob_file_number
,
104 inline Cache
* GetBlobCache() const { return blob_cache_
.get(); }
106 bool TEST_BlobInCache(uint64_t file_number
, uint64_t file_size
,
107 uint64_t offset
, size_t* charge
= nullptr) const;
110 Status
GetBlobFromCache(const Slice
& cache_key
,
111 CacheHandleGuard
<BlobContents
>* cached_blob
) const;
113 Status
PutBlobIntoCache(const Slice
& cache_key
,
114 std::unique_ptr
<BlobContents
>* blob
,
115 CacheHandleGuard
<BlobContents
>* cached_blob
) const;
117 static void PinCachedBlob(CacheHandleGuard
<BlobContents
>* cached_blob
,
118 PinnableSlice
* value
);
120 static void PinOwnedBlob(std::unique_ptr
<BlobContents
>* owned_blob
,
121 PinnableSlice
* value
);
123 Cache::Handle
* GetEntryFromCache(const Slice
& key
) const;
125 Status
InsertEntryIntoCache(const Slice
& key
, BlobContents
* value
,
126 size_t charge
, Cache::Handle
** cache_handle
,
127 Cache::Priority priority
) const;
129 inline CacheKey
GetCacheKey(uint64_t file_number
, uint64_t /*file_size*/,
130 uint64_t offset
) const {
131 OffsetableCacheKey
base_cache_key(db_id_
, db_session_id_
, file_number
);
132 return base_cache_key
.WithOffset(offset
);
135 const std::string
& db_id_
;
136 const std::string
& db_session_id_
;
138 Statistics
* statistics_
;
140 // A cache to store blob file reader.
141 BlobFileCache
* blob_file_cache_
;
143 // A cache to store uncompressed blobs.
144 std::shared_ptr
<Cache
> blob_cache_
;
146 // The control option of how the cache tiers will be used. Currently rocksdb
147 // support block/blob cache (volatile tier) and secondary cache (this tier
148 // isn't strictly speaking a non-volatile tier since the compressed cache in
149 // this tier is in volatile memory).
150 const CacheTier lowest_used_cache_tier_
;
153 } // namespace ROCKSDB_NAMESPACE