Coverage Report

Created: 2024-07-27 06:53

/src/rocksdb/cache/compressed_secondary_cache.h
Line
Count
Source (jump to first uncovered line)
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
#pragma once
7
8
#include <array>
9
#include <cstddef>
10
#include <memory>
11
12
#include "cache/cache_reservation_manager.h"
13
#include "cache/lru_cache.h"
14
#include "memory/memory_allocator_impl.h"
15
#include "rocksdb/secondary_cache.h"
16
#include "rocksdb/slice.h"
17
#include "rocksdb/status.h"
18
#include "util/compression.h"
19
#include "util/mutexlock.h"
20
21
namespace ROCKSDB_NAMESPACE {
22
23
class CompressedSecondaryCacheResultHandle : public SecondaryCacheResultHandle {
24
 public:
25
  CompressedSecondaryCacheResultHandle(Cache::ObjectPtr value, size_t size)
26
0
      : value_(value), size_(size) {}
27
  ~CompressedSecondaryCacheResultHandle() override = default;
28
29
  CompressedSecondaryCacheResultHandle(
30
      const CompressedSecondaryCacheResultHandle&) = delete;
31
  CompressedSecondaryCacheResultHandle& operator=(
32
      const CompressedSecondaryCacheResultHandle&) = delete;
33
34
0
  bool IsReady() override { return true; }
35
36
0
  void Wait() override {}
37
38
0
  Cache::ObjectPtr Value() override { return value_; }
39
40
0
  size_t Size() override { return size_; }
41
42
 private:
43
  Cache::ObjectPtr value_;
44
  size_t size_;
45
};
46
47
// The CompressedSecondaryCache is a concrete implementation of
48
// rocksdb::SecondaryCache.
49
//
50
// When a block is found from CompressedSecondaryCache::Lookup, we check whether
51
// there is a dummy block with the same key in the primary cache.
52
// 1. If the dummy block exits, we erase the block from
53
//    CompressedSecondaryCache and insert it into the primary cache.
54
// 2. If not, we just insert a dummy block into the primary cache
55
//    (charging the actual size of the block) and don not erase the block from
56
//    CompressedSecondaryCache. A standalone handle is returned to the caller.
57
//
58
// When a block is evicted from the primary cache, we check whether
59
// there is a dummy block with the same key in CompressedSecondaryCache.
60
// 1. If the dummy block exits, the block is inserted into
61
//    CompressedSecondaryCache.
62
// 2. If not, we just insert a dummy block (size 0) in CompressedSecondaryCache.
63
//
64
// Users can also cast a pointer to CompressedSecondaryCache and call methods on
65
// it directly, especially custom methods that may be added
66
// in the future.  For example -
67
// std::unique_ptr<rocksdb::SecondaryCache> cache =
68
//      NewCompressedSecondaryCache(opts);
69
// static_cast<CompressedSecondaryCache*>(cache.get())->Erase(key);
70
71
class CompressedSecondaryCache : public SecondaryCache {
72
 public:
73
  explicit CompressedSecondaryCache(
74
      const CompressedSecondaryCacheOptions& opts);
75
  ~CompressedSecondaryCache() override;
76
77
0
  const char* Name() const override { return "CompressedSecondaryCache"; }
78
79
  Status Insert(const Slice& key, Cache::ObjectPtr value,
80
                const Cache::CacheItemHelper* helper,
81
                bool force_insert) override;
82
83
  Status InsertSaved(const Slice& key, const Slice& saved, CompressionType type,
84
                     CacheTier source) override;
85
86
  std::unique_ptr<SecondaryCacheResultHandle> Lookup(
87
      const Slice& key, const Cache::CacheItemHelper* helper,
88
      Cache::CreateContext* create_context, bool /*wait*/, bool advise_erase,
89
      Statistics* stats, bool& kept_in_sec_cache) override;
90
91
0
  bool SupportForceErase() const override { return true; }
92
93
  void Erase(const Slice& key) override;
94
95
0
  void WaitAll(std::vector<SecondaryCacheResultHandle*> /*handles*/) override {}
96
97
  Status SetCapacity(size_t capacity) override;
98
99
  Status GetCapacity(size_t& capacity) override;
100
101
  Status Deflate(size_t decrease) override;
102
103
  Status Inflate(size_t increase) override;
104
105
  std::string GetPrintableOptions() const override;
106
107
0
  size_t TEST_GetUsage() { return cache_->GetUsage(); }
108
109
 private:
110
  friend class CompressedSecondaryCacheTestBase;
111
  static constexpr std::array<uint16_t, 8> malloc_bin_sizes_{
112
      128, 256, 512, 1024, 2048, 4096, 8192, 16384};
113
114
  struct CacheValueChunk {
115
    // TODO try "CacheAllocationPtr next;".
116
    CacheValueChunk* next;
117
    size_t size;
118
    // Beginning of the chunk data (MUST BE THE LAST FIELD IN THIS STRUCT!)
119
    char data[1];
120
121
0
    void Free() { delete[] reinterpret_cast<char*>(this); }
122
  };
123
124
  // Split value into chunks to better fit into jemalloc bins. The chunks
125
  // are stored in CacheValueChunk and extra charge is needed for each chunk,
126
  // so the cache charge is recalculated here.
127
  CacheValueChunk* SplitValueIntoChunks(const Slice& value,
128
                                        CompressionType compression_type,
129
                                        size_t& charge);
130
131
  // After merging chunks, the extra charge for each chunk is removed, so
132
  // the charge is recalculated.
133
  CacheAllocationPtr MergeChunksIntoValue(const void* chunks_head,
134
                                          size_t& charge);
135
136
  bool MaybeInsertDummy(const Slice& key);
137
138
  Status InsertInternal(const Slice& key, Cache::ObjectPtr value,
139
                        const Cache::CacheItemHelper* helper,
140
                        CompressionType type, CacheTier source);
141
142
  // TODO: clean up to use cleaner interfaces in typed_cache.h
143
  const Cache::CacheItemHelper* GetHelper(bool enable_custom_split_merge) const;
144
  std::shared_ptr<Cache> cache_;
145
  CompressedSecondaryCacheOptions cache_options_;
146
  mutable port::Mutex capacity_mutex_;
147
  std::shared_ptr<ConcurrentCacheReservationManager> cache_res_mgr_;
148
  bool disable_cache_;
149
};
150
151
}  // namespace ROCKSDB_NAMESPACE