compressed_secondary_cache.h 5.3 KB

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