blob_log_format.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  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. // Log format information shared by reader and writer.
  7. #pragma once
  8. #include <memory>
  9. #include <utility>
  10. #include "rocksdb/options.h"
  11. #include "rocksdb/slice.h"
  12. #include "rocksdb/status.h"
  13. #include "rocksdb/types.h"
  14. namespace ROCKSDB_NAMESPACE {
  15. constexpr uint32_t kMagicNumber = 2395959; // 0x00248f37
  16. constexpr uint32_t kVersion1 = 1;
  17. using ExpirationRange = std::pair<uint64_t, uint64_t>;
  18. // clang-format off
  19. // Format of blob log file header (30 bytes):
  20. //
  21. // +--------------+---------+---------+-------+-------------+-------------------+
  22. // | magic number | version | cf id | flags | compression | expiration range |
  23. // +--------------+---------+---------+-------+-------------+-------------------+
  24. // | Fixed32 | Fixed32 | Fixed32 | char | char | Fixed64 Fixed64 |
  25. // +--------------+---------+---------+-------+-------------+-------------------+
  26. //
  27. // List of flags:
  28. // has_ttl: Whether the file contain TTL data.
  29. //
  30. // Expiration range in the header is a rough range based on
  31. // blob_db_options.ttl_range_secs.
  32. // clang-format on
  33. struct BlobLogHeader {
  34. static constexpr size_t kSize = 30;
  35. BlobLogHeader() = default;
  36. BlobLogHeader(uint32_t _column_family_id, CompressionType _compression,
  37. bool _has_ttl, const ExpirationRange& _expiration_range)
  38. : column_family_id(_column_family_id),
  39. compression(_compression),
  40. has_ttl(_has_ttl),
  41. expiration_range(_expiration_range) {}
  42. uint32_t version = kVersion1;
  43. uint32_t column_family_id = 0;
  44. CompressionType compression = kNoCompression;
  45. bool has_ttl = false;
  46. ExpirationRange expiration_range;
  47. void EncodeTo(std::string* dst);
  48. Status DecodeFrom(Slice slice);
  49. };
  50. // clang-format off
  51. // Format of blob log file footer (32 bytes):
  52. //
  53. // +--------------+------------+-------------------+------------+
  54. // | magic number | blob count | expiration range | footer CRC |
  55. // +--------------+------------+-------------------+------------+
  56. // | Fixed32 | Fixed64 | Fixed64 + Fixed64 | Fixed32 |
  57. // +--------------+------------+-------------------+------------+
  58. //
  59. // The footer will be presented only when the blob file is properly closed.
  60. //
  61. // Unlike the same field in file header, expiration range in the footer is the
  62. // range of smallest and largest expiration of the data in this file.
  63. // clang-format on
  64. struct BlobLogFooter {
  65. static constexpr size_t kSize = 32;
  66. uint64_t blob_count = 0;
  67. ExpirationRange expiration_range = std::make_pair(0, 0);
  68. uint32_t crc = 0;
  69. void EncodeTo(std::string* dst);
  70. Status DecodeFrom(Slice slice);
  71. };
  72. // clang-format off
  73. // Blob record format (32 bytes header + key + value):
  74. //
  75. // +------------+--------------+------------+------------+----------+---------+-----------+
  76. // | key length | value length | expiration | header CRC | blob CRC | key | value |
  77. // +------------+--------------+------------+------------+----------+---------+-----------+
  78. // | Fixed64 | Fixed64 | Fixed64 | Fixed32 | Fixed32 | key len | value len |
  79. // +------------+--------------+------------+------------+----------+---------+-----------+
  80. //
  81. // If file has has_ttl = false, expiration field is always 0, and the blob
  82. // doesn't has expiration.
  83. //
  84. // Also note that if compression is used, value is compressed value and value
  85. // length is compressed value length.
  86. //
  87. // Header CRC is the checksum of (key_len + val_len + expiration), while
  88. // blob CRC is the checksum of (key + value).
  89. //
  90. // We could use variable length encoding (Varint64) to save more space, but it
  91. // make reader more complicated.
  92. // clang-format on
  93. struct BlobLogRecord {
  94. // header include fields up to blob CRC
  95. static constexpr size_t kHeaderSize = 32;
  96. // Note that the offset field of BlobIndex actually points to the blob value
  97. // as opposed to the start of the blob record. The following method can
  98. // be used to calculate the adjustment needed to read the blob record header.
  99. static constexpr uint64_t CalculateAdjustmentForRecordHeader(
  100. uint64_t key_size) {
  101. return key_size + kHeaderSize;
  102. }
  103. uint64_t key_size = 0;
  104. uint64_t value_size = 0;
  105. uint64_t expiration = 0;
  106. uint32_t header_crc = 0;
  107. uint32_t blob_crc = 0;
  108. Slice key;
  109. Slice value;
  110. std::unique_ptr<char[]> key_buf;
  111. std::unique_ptr<char[]> value_buf;
  112. uint64_t record_size() const { return kHeaderSize + key_size + value_size; }
  113. void EncodeHeaderTo(std::string* dst);
  114. Status DecodeHeaderFrom(Slice src);
  115. Status CheckBlobCRC() const;
  116. };
  117. // Checks whether a blob offset is potentially valid or not.
  118. inline bool IsValidBlobOffset(uint64_t value_offset, uint64_t key_size,
  119. uint64_t value_size, uint64_t file_size) {
  120. if (value_offset <
  121. BlobLogHeader::kSize + BlobLogRecord::kHeaderSize + key_size) {
  122. return false;
  123. }
  124. if (value_offset + value_size + BlobLogFooter::kSize > file_size) {
  125. return false;
  126. }
  127. return true;
  128. }
  129. } // namespace ROCKSDB_NAMESPACE