cache_key.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // Copyright (c) Facebook, Inc. and its affiliates. 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 <cstdint>
  7. #include "rocksdb/rocksdb_namespace.h"
  8. #include "rocksdb/slice.h"
  9. #include "table/unique_id_impl.h"
  10. namespace ROCKSDB_NAMESPACE {
  11. class Cache;
  12. // A standard holder for fixed-size block cache keys (and for related caches).
  13. // They are created through one of these, each using its own range of values:
  14. // * CacheKey::CreateUniqueForCacheLifetime
  15. // * CacheKey::CreateUniqueForProcessLifetime
  16. // * Default ctor ("empty" cache key)
  17. // * OffsetableCacheKey->WithOffset
  18. //
  19. // The first two use atomic counters to guarantee uniqueness over the given
  20. // lifetime and the last uses a form of universally unique identifier for
  21. // uniqueness with very high probabilty (and guaranteed for files generated
  22. // during a single process lifetime).
  23. //
  24. // CacheKeys are currently used by calling AsSlice() to pass as a key to
  25. // Cache. For performance, the keys are endianness-dependent (though otherwise
  26. // portable). (Persistable cache entries are not intended to cross platforms.)
  27. class CacheKey {
  28. public:
  29. // For convenience, constructs an "empty" cache key that is never returned
  30. // by other means.
  31. inline CacheKey() : file_num_etc64_(), offset_etc64_() {}
  32. inline bool IsEmpty() const {
  33. return (file_num_etc64_ == 0) & (offset_etc64_ == 0);
  34. }
  35. // Use this cache key as a Slice (byte order is endianness-dependent)
  36. inline Slice AsSlice() const {
  37. static_assert(sizeof(*this) == 16, "Standardized on 16-byte cache key");
  38. assert(!IsEmpty());
  39. return Slice(reinterpret_cast<const char *>(this), sizeof(*this));
  40. }
  41. // Create a CacheKey that is unique among others associated with this Cache
  42. // instance. Depends on Cache::NewId. This is useful for block cache
  43. // "reservations".
  44. static CacheKey CreateUniqueForCacheLifetime(Cache *cache);
  45. // Create a CacheKey that is unique among others for the lifetime of this
  46. // process. This is useful for saving in a static data member so that
  47. // different DB instances can agree on a cache key for shared entities,
  48. // such as for CacheEntryStatsCollector.
  49. static CacheKey CreateUniqueForProcessLifetime();
  50. protected:
  51. friend class OffsetableCacheKey;
  52. CacheKey(uint64_t file_num_etc64, uint64_t offset_etc64)
  53. : file_num_etc64_(file_num_etc64), offset_etc64_(offset_etc64) {}
  54. uint64_t file_num_etc64_;
  55. uint64_t offset_etc64_;
  56. };
  57. constexpr uint8_t kCacheKeySize = static_cast<uint8_t>(sizeof(CacheKey));
  58. // A file-specific generator of cache keys, sometimes referred to as the
  59. // "base" cache key for a file because all the cache keys for various offsets
  60. // within the file are computed using simple arithmetic. The basis for the
  61. // general approach is dicussed here: https://github.com/pdillinger/unique_id
  62. // Heavily related to GetUniqueIdFromTableProperties.
  63. //
  64. // If the db_id, db_session_id, and file_number come from the file's table
  65. // properties, then the keys will be stable across DB::Open/Close, backup/
  66. // restore, import/export, etc.
  67. //
  68. // This class "is a" CacheKey only privately so that it is not misused as
  69. // a ready-to-use CacheKey.
  70. class OffsetableCacheKey : private CacheKey {
  71. public:
  72. // For convenience, constructs an "empty" cache key that should not be used.
  73. inline OffsetableCacheKey() : CacheKey() {}
  74. // Constructs an OffsetableCacheKey with the given information about a file.
  75. // This constructor never generates an "empty" base key.
  76. OffsetableCacheKey(const std::string &db_id, const std::string &db_session_id,
  77. uint64_t file_number);
  78. // Creates an OffsetableCacheKey from an SST unique ID, so that cache keys
  79. // can be derived from DB manifest data before reading the file from
  80. // storage--so that every part of the file can potentially go in a persistent
  81. // cache.
  82. //
  83. // Calling GetSstInternalUniqueId() on a db_id, db_session_id, and
  84. // file_number and passing the result to this function produces the same
  85. // base cache key as feeding those inputs directly to the constructor.
  86. //
  87. // This is a bijective transformation assuming either id is empty or
  88. // lower 64 bits is non-zero:
  89. // * Empty (all zeros) input -> empty (all zeros) output
  90. // * Lower 64 input is non-zero -> lower 64 output (file_num_etc64_) is
  91. // non-zero
  92. static OffsetableCacheKey FromInternalUniqueId(UniqueIdPtr id);
  93. // This is the inverse transformation to the above, assuming either empty
  94. // or lower 64 bits (file_num_etc64_) is non-zero. Perhaps only useful for
  95. // testing.
  96. UniqueId64x2 ToInternalUniqueId();
  97. inline bool IsEmpty() const {
  98. bool result = file_num_etc64_ == 0;
  99. assert(!(offset_etc64_ > 0 && result));
  100. return result;
  101. }
  102. // Construct a CacheKey for an offset within a file. An offset is not
  103. // necessarily a byte offset if a smaller unique identifier of keyable
  104. // offsets is used.
  105. //
  106. // This class was designed to make this hot code extremely fast.
  107. inline CacheKey WithOffset(uint64_t offset) const {
  108. assert(!IsEmpty());
  109. return CacheKey(file_num_etc64_, offset_etc64_ ^ offset);
  110. }
  111. // The "common prefix" is a shared prefix for all the returned CacheKeys.
  112. // It is specific to the file but the same for all offsets within the file.
  113. static constexpr size_t kCommonPrefixSize = 8;
  114. inline Slice CommonPrefixSlice() const {
  115. static_assert(sizeof(file_num_etc64_) == kCommonPrefixSize,
  116. "8 byte common prefix expected");
  117. assert(!IsEmpty());
  118. assert(&this->file_num_etc64_ == static_cast<const void *>(this));
  119. return Slice(reinterpret_cast<const char *>(this), kCommonPrefixSize);
  120. }
  121. };
  122. } // namespace ROCKSDB_NAMESPACE