blob_index.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  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 <sstream>
  7. #include <string>
  8. #include "rocksdb/compression_type.h"
  9. #include "util/coding.h"
  10. #include "util/compression.h"
  11. #include "util/string_util.h"
  12. namespace ROCKSDB_NAMESPACE {
  13. // BlobIndex is a pointer to the blob and metadata of the blob. The index is
  14. // stored in base DB as ValueType::kTypeBlobIndex.
  15. // There are three types of blob index:
  16. //
  17. // kInlinedTTL:
  18. // +------+------------+---------------+
  19. // | type | expiration | value |
  20. // +------+------------+---------------+
  21. // | char | varint64 | variable size |
  22. // +------+------------+---------------+
  23. //
  24. // kBlob:
  25. // +------+-------------+----------+----------+-------------+
  26. // | type | file number | offset | size | compression |
  27. // +------+-------------+----------+----------+-------------+
  28. // | char | varint64 | varint64 | varint64 | char |
  29. // +------+-------------+----------+----------+-------------+
  30. //
  31. // kBlobTTL:
  32. // +------+------------+-------------+----------+----------+-------------+
  33. // | type | expiration | file number | offset | size | compression |
  34. // +------+------------+-------------+----------+----------+-------------+
  35. // | char | varint64 | varint64 | varint64 | varint64 | char |
  36. // +------+------------+-------------+----------+----------+-------------+
  37. //
  38. // There isn't a kInlined (without TTL) type since we can store it as a plain
  39. // value (i.e. ValueType::kTypeValue).
  40. class BlobIndex {
  41. public:
  42. enum class Type : unsigned char {
  43. kInlinedTTL = 0,
  44. kBlob = 1,
  45. kBlobTTL = 2,
  46. kUnknown = 3,
  47. };
  48. BlobIndex() : type_(Type::kUnknown) {}
  49. BlobIndex(const BlobIndex&) = default;
  50. BlobIndex& operator=(const BlobIndex&) = default;
  51. bool IsInlined() const { return type_ == Type::kInlinedTTL; }
  52. bool HasTTL() const {
  53. return type_ == Type::kInlinedTTL || type_ == Type::kBlobTTL;
  54. }
  55. uint64_t expiration() const {
  56. assert(HasTTL());
  57. return expiration_;
  58. }
  59. const Slice& value() const {
  60. assert(IsInlined());
  61. return value_;
  62. }
  63. uint64_t file_number() const {
  64. assert(!IsInlined());
  65. return file_number_;
  66. }
  67. uint64_t offset() const {
  68. assert(!IsInlined());
  69. return offset_;
  70. }
  71. uint64_t size() const {
  72. assert(!IsInlined());
  73. return size_;
  74. }
  75. CompressionType compression() const {
  76. assert(!IsInlined());
  77. return compression_;
  78. }
  79. Status DecodeFrom(Slice slice) {
  80. const char* kErrorMessage = "Error while decoding blob index";
  81. assert(slice.size() > 0);
  82. type_ = static_cast<Type>(*slice.data());
  83. if (type_ >= Type::kUnknown) {
  84. return Status::Corruption(kErrorMessage,
  85. "Unknown blob index type: " +
  86. std::to_string(static_cast<char>(type_)));
  87. }
  88. slice = Slice(slice.data() + 1, slice.size() - 1);
  89. if (HasTTL()) {
  90. if (!GetVarint64(&slice, &expiration_)) {
  91. return Status::Corruption(kErrorMessage, "Corrupted expiration");
  92. }
  93. }
  94. if (IsInlined()) {
  95. value_ = slice;
  96. } else {
  97. if (GetVarint64(&slice, &file_number_) && GetVarint64(&slice, &offset_) &&
  98. GetVarint64(&slice, &size_) && slice.size() == 1) {
  99. compression_ = static_cast<CompressionType>(*slice.data());
  100. } else {
  101. return Status::Corruption(kErrorMessage, "Corrupted blob offset");
  102. }
  103. }
  104. return Status::OK();
  105. }
  106. std::string DebugString(bool output_hex) const {
  107. std::ostringstream oss;
  108. if (IsInlined()) {
  109. oss << "[inlined blob] value:" << value_.ToString(output_hex);
  110. } else {
  111. oss << "[blob ref] file:" << file_number_ << " offset:" << offset_
  112. << " size:" << size_
  113. << " compression: " << CompressionTypeToString(compression_);
  114. }
  115. if (HasTTL()) {
  116. oss << " exp:" << expiration_;
  117. }
  118. return oss.str();
  119. }
  120. static void EncodeInlinedTTL(std::string* dst, uint64_t expiration,
  121. const Slice& value) {
  122. assert(dst != nullptr);
  123. dst->clear();
  124. dst->reserve(1 + kMaxVarint64Length + value.size());
  125. dst->push_back(static_cast<char>(Type::kInlinedTTL));
  126. PutVarint64(dst, expiration);
  127. dst->append(value.data(), value.size());
  128. }
  129. static void EncodeBlob(std::string* dst, uint64_t file_number,
  130. uint64_t offset, uint64_t size,
  131. CompressionType compression) {
  132. assert(dst != nullptr);
  133. dst->clear();
  134. dst->reserve(kMaxVarint64Length * 3 + 2);
  135. dst->push_back(static_cast<char>(Type::kBlob));
  136. PutVarint64(dst, file_number);
  137. PutVarint64(dst, offset);
  138. PutVarint64(dst, size);
  139. dst->push_back(static_cast<char>(compression));
  140. }
  141. static void EncodeBlobTTL(std::string* dst, uint64_t expiration,
  142. uint64_t file_number, uint64_t offset,
  143. uint64_t size, CompressionType compression) {
  144. assert(dst != nullptr);
  145. dst->clear();
  146. dst->reserve(kMaxVarint64Length * 4 + 2);
  147. dst->push_back(static_cast<char>(Type::kBlobTTL));
  148. PutVarint64(dst, expiration);
  149. PutVarint64(dst, file_number);
  150. PutVarint64(dst, offset);
  151. PutVarint64(dst, size);
  152. dst->push_back(static_cast<char>(compression));
  153. }
  154. private:
  155. Type type_ = Type::kUnknown;
  156. uint64_t expiration_ = 0;
  157. Slice value_;
  158. uint64_t file_number_ = 0;
  159. uint64_t offset_ = 0;
  160. uint64_t size_ = 0;
  161. CompressionType compression_ = kNoCompression;
  162. };
  163. } // namespace ROCKSDB_NAMESPACE