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 #include "table/persistent_cache_helper.h"
7 #include "table/block_based/block_based_table_reader.h"
8 #include "table/format.h"
9 
10 namespace ROCKSDB_NAMESPACE {
11 
InsertRawPage(const PersistentCacheOptions & cache_options,const BlockHandle & handle,const char * data,const size_t size)12 void PersistentCacheHelper::InsertRawPage(
13     const PersistentCacheOptions& cache_options, const BlockHandle& handle,
14     const char* data, const size_t size) {
15   assert(cache_options.persistent_cache);
16   assert(cache_options.persistent_cache->IsCompressed());
17 
18   // construct the page key
19   char cache_key[BlockBasedTable::kMaxCacheKeyPrefixSize + kMaxVarint64Length];
20   auto key = BlockBasedTable::GetCacheKey(cache_options.key_prefix.c_str(),
21                                           cache_options.key_prefix.size(),
22                                           handle, cache_key);
23   // insert content to cache
24   cache_options.persistent_cache->Insert(key, data, size);
25 }
26 
InsertUncompressedPage(const PersistentCacheOptions & cache_options,const BlockHandle & handle,const BlockContents & contents)27 void PersistentCacheHelper::InsertUncompressedPage(
28     const PersistentCacheOptions& cache_options, const BlockHandle& handle,
29     const BlockContents& contents) {
30   assert(cache_options.persistent_cache);
31   assert(!cache_options.persistent_cache->IsCompressed());
32   // Precondition:
33   // (1) content is cacheable
34   // (2) content is not compressed
35 
36   // construct the page key
37   char cache_key[BlockBasedTable::kMaxCacheKeyPrefixSize + kMaxVarint64Length];
38   auto key = BlockBasedTable::GetCacheKey(cache_options.key_prefix.c_str(),
39                                           cache_options.key_prefix.size(),
40                                           handle, cache_key);
41   // insert block contents to page cache
42   cache_options.persistent_cache->Insert(key, contents.data.data(),
43                                          contents.data.size());
44 }
45 
LookupRawPage(const PersistentCacheOptions & cache_options,const BlockHandle & handle,std::unique_ptr<char[]> * raw_data,const size_t raw_data_size)46 Status PersistentCacheHelper::LookupRawPage(
47     const PersistentCacheOptions& cache_options, const BlockHandle& handle,
48     std::unique_ptr<char[]>* raw_data, const size_t raw_data_size) {
49 #ifdef NDEBUG
50   (void)raw_data_size;
51 #endif
52   assert(cache_options.persistent_cache);
53   assert(cache_options.persistent_cache->IsCompressed());
54 
55   // construct the page key
56   char cache_key[BlockBasedTable::kMaxCacheKeyPrefixSize + kMaxVarint64Length];
57   auto key = BlockBasedTable::GetCacheKey(cache_options.key_prefix.c_str(),
58                                           cache_options.key_prefix.size(),
59                                           handle, cache_key);
60   // Lookup page
61   size_t size;
62   Status s = cache_options.persistent_cache->Lookup(key, raw_data, &size);
63   if (!s.ok()) {
64     // cache miss
65     RecordTick(cache_options.statistics, PERSISTENT_CACHE_MISS);
66     return s;
67   }
68 
69   // cache hit
70   assert(raw_data_size == handle.size() + kBlockTrailerSize);
71   assert(size == raw_data_size);
72   RecordTick(cache_options.statistics, PERSISTENT_CACHE_HIT);
73   return Status::OK();
74 }
75 
LookupUncompressedPage(const PersistentCacheOptions & cache_options,const BlockHandle & handle,BlockContents * contents)76 Status PersistentCacheHelper::LookupUncompressedPage(
77     const PersistentCacheOptions& cache_options, const BlockHandle& handle,
78     BlockContents* contents) {
79   assert(cache_options.persistent_cache);
80   assert(!cache_options.persistent_cache->IsCompressed());
81   if (!contents) {
82     // We shouldn't lookup in the cache. Either
83     // (1) Nowhere to store
84     return Status::NotFound();
85   }
86 
87   // construct the page key
88   char cache_key[BlockBasedTable::kMaxCacheKeyPrefixSize + kMaxVarint64Length];
89   auto key = BlockBasedTable::GetCacheKey(cache_options.key_prefix.c_str(),
90                                           cache_options.key_prefix.size(),
91                                           handle, cache_key);
92   // Lookup page
93   std::unique_ptr<char[]> data;
94   size_t size;
95   Status s = cache_options.persistent_cache->Lookup(key, &data, &size);
96   if (!s.ok()) {
97     // cache miss
98     RecordTick(cache_options.statistics, PERSISTENT_CACHE_MISS);
99     return s;
100   }
101 
102   // please note we are potentially comparing compressed data size with
103   // uncompressed data size
104   assert(handle.size() <= size);
105 
106   // update stats
107   RecordTick(cache_options.statistics, PERSISTENT_CACHE_HIT);
108   // construct result and return
109   *contents = BlockContents(std::move(data), size);
110   return Status::OK();
111 }
112 
113 }  // namespace ROCKSDB_NAMESPACE
114