blob_index.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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. #ifndef ROCKSDB_LITE
  7. #include <sstream>
  8. #include <string>
  9. #include "rocksdb/options.h"
  10. #include "util/coding.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. bool IsInlined() const { return type_ == Type::kInlinedTTL; }
  50. bool HasTTL() const {
  51. return type_ == Type::kInlinedTTL || type_ == Type::kBlobTTL;
  52. }
  53. uint64_t expiration() const {
  54. assert(HasTTL());
  55. return expiration_;
  56. }
  57. const Slice& value() const {
  58. assert(IsInlined());
  59. return value_;
  60. }
  61. uint64_t file_number() const {
  62. assert(!IsInlined());
  63. return file_number_;
  64. }
  65. uint64_t offset() const {
  66. assert(!IsInlined());
  67. return offset_;
  68. }
  69. uint64_t size() const {
  70. assert(!IsInlined());
  71. return size_;
  72. }
  73. Status DecodeFrom(Slice slice) {
  74. static const std::string kErrorMessage = "Error while decoding blob index";
  75. assert(slice.size() > 0);
  76. type_ = static_cast<Type>(*slice.data());
  77. if (type_ >= Type::kUnknown) {
  78. return Status::Corruption(
  79. kErrorMessage,
  80. "Unknown blob index type: " + ToString(static_cast<char>(type_)));
  81. }
  82. slice = Slice(slice.data() + 1, slice.size() - 1);
  83. if (HasTTL()) {
  84. if (!GetVarint64(&slice, &expiration_)) {
  85. return Status::Corruption(kErrorMessage, "Corrupted expiration");
  86. }
  87. }
  88. if (IsInlined()) {
  89. value_ = slice;
  90. } else {
  91. if (GetVarint64(&slice, &file_number_) && GetVarint64(&slice, &offset_) &&
  92. GetVarint64(&slice, &size_) && slice.size() == 1) {
  93. compression_ = static_cast<CompressionType>(*slice.data());
  94. } else {
  95. return Status::Corruption(kErrorMessage, "Corrupted blob offset");
  96. }
  97. }
  98. return Status::OK();
  99. }
  100. std::string DebugString(bool output_hex) const {
  101. std::ostringstream oss;
  102. if (IsInlined()) {
  103. oss << "[inlined blob] value:" << value_.ToString(output_hex);
  104. } else {
  105. oss << "[blob ref] file:" << file_number_ << " offset:" << offset_
  106. << " size:" << size_;
  107. }
  108. if (HasTTL()) {
  109. oss << " exp:" << expiration_;
  110. }
  111. return oss.str();
  112. }
  113. static void EncodeInlinedTTL(std::string* dst, uint64_t expiration,
  114. const Slice& value) {
  115. assert(dst != nullptr);
  116. dst->clear();
  117. dst->reserve(1 + kMaxVarint64Length + value.size());
  118. dst->push_back(static_cast<char>(Type::kInlinedTTL));
  119. PutVarint64(dst, expiration);
  120. dst->append(value.data(), value.size());
  121. }
  122. static void EncodeBlob(std::string* dst, uint64_t file_number,
  123. uint64_t offset, uint64_t size,
  124. CompressionType compression) {
  125. assert(dst != nullptr);
  126. dst->clear();
  127. dst->reserve(kMaxVarint64Length * 3 + 2);
  128. dst->push_back(static_cast<char>(Type::kBlob));
  129. PutVarint64(dst, file_number);
  130. PutVarint64(dst, offset);
  131. PutVarint64(dst, size);
  132. dst->push_back(static_cast<char>(compression));
  133. }
  134. static void EncodeBlobTTL(std::string* dst, uint64_t expiration,
  135. uint64_t file_number, uint64_t offset,
  136. uint64_t size, CompressionType compression) {
  137. assert(dst != nullptr);
  138. dst->clear();
  139. dst->reserve(kMaxVarint64Length * 4 + 2);
  140. dst->push_back(static_cast<char>(Type::kBlobTTL));
  141. PutVarint64(dst, expiration);
  142. PutVarint64(dst, file_number);
  143. PutVarint64(dst, offset);
  144. PutVarint64(dst, size);
  145. dst->push_back(static_cast<char>(compression));
  146. }
  147. private:
  148. Type type_ = Type::kUnknown;
  149. uint64_t expiration_ = 0;
  150. Slice value_;
  151. uint64_t file_number_ = 0;
  152. uint64_t offset_ = 0;
  153. uint64_t size_ = 0;
  154. CompressionType compression_ = kNoCompression;
  155. };
  156. } // namespace ROCKSDB_NAMESPACE
  157. #endif // ROCKSDB_LITE