blob_log_format.cc 5.1 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. //
  6. #ifndef ROCKSDB_LITE
  7. #include "utilities/blob_db/blob_log_format.h"
  8. #include "util/coding.h"
  9. #include "util/crc32c.h"
  10. namespace ROCKSDB_NAMESPACE {
  11. namespace blob_db {
  12. void BlobLogHeader::EncodeTo(std::string* dst) {
  13. assert(dst != nullptr);
  14. dst->clear();
  15. dst->reserve(BlobLogHeader::kSize);
  16. PutFixed32(dst, kMagicNumber);
  17. PutFixed32(dst, version);
  18. PutFixed32(dst, column_family_id);
  19. unsigned char flags = (has_ttl ? 1 : 0);
  20. dst->push_back(flags);
  21. dst->push_back(compression);
  22. PutFixed64(dst, expiration_range.first);
  23. PutFixed64(dst, expiration_range.second);
  24. }
  25. Status BlobLogHeader::DecodeFrom(Slice src) {
  26. static const std::string kErrorMessage =
  27. "Error while decoding blob log header";
  28. if (src.size() != BlobLogHeader::kSize) {
  29. return Status::Corruption(kErrorMessage,
  30. "Unexpected blob file header size");
  31. }
  32. uint32_t magic_number;
  33. unsigned char flags;
  34. if (!GetFixed32(&src, &magic_number) || !GetFixed32(&src, &version) ||
  35. !GetFixed32(&src, &column_family_id)) {
  36. return Status::Corruption(
  37. kErrorMessage,
  38. "Error decoding magic number, version and column family id");
  39. }
  40. if (magic_number != kMagicNumber) {
  41. return Status::Corruption(kErrorMessage, "Magic number mismatch");
  42. }
  43. if (version != kVersion1) {
  44. return Status::Corruption(kErrorMessage, "Unknown header version");
  45. }
  46. flags = src.data()[0];
  47. compression = static_cast<CompressionType>(src.data()[1]);
  48. has_ttl = (flags & 1) == 1;
  49. src.remove_prefix(2);
  50. if (!GetFixed64(&src, &expiration_range.first) ||
  51. !GetFixed64(&src, &expiration_range.second)) {
  52. return Status::Corruption(kErrorMessage, "Error decoding expiration range");
  53. }
  54. return Status::OK();
  55. }
  56. void BlobLogFooter::EncodeTo(std::string* dst) {
  57. assert(dst != nullptr);
  58. dst->clear();
  59. dst->reserve(BlobLogFooter::kSize);
  60. PutFixed32(dst, kMagicNumber);
  61. PutFixed64(dst, blob_count);
  62. PutFixed64(dst, expiration_range.first);
  63. PutFixed64(dst, expiration_range.second);
  64. crc = crc32c::Value(dst->c_str(), dst->size());
  65. crc = crc32c::Mask(crc);
  66. PutFixed32(dst, crc);
  67. }
  68. Status BlobLogFooter::DecodeFrom(Slice src) {
  69. static const std::string kErrorMessage =
  70. "Error while decoding blob log footer";
  71. if (src.size() != BlobLogFooter::kSize) {
  72. return Status::Corruption(kErrorMessage,
  73. "Unexpected blob file footer size");
  74. }
  75. uint32_t src_crc = 0;
  76. src_crc = crc32c::Value(src.data(), BlobLogFooter::kSize - sizeof(uint32_t));
  77. src_crc = crc32c::Mask(src_crc);
  78. uint32_t magic_number = 0;
  79. if (!GetFixed32(&src, &magic_number) || !GetFixed64(&src, &blob_count) ||
  80. !GetFixed64(&src, &expiration_range.first) ||
  81. !GetFixed64(&src, &expiration_range.second) || !GetFixed32(&src, &crc)) {
  82. return Status::Corruption(kErrorMessage, "Error decoding content");
  83. }
  84. if (magic_number != kMagicNumber) {
  85. return Status::Corruption(kErrorMessage, "Magic number mismatch");
  86. }
  87. if (src_crc != crc) {
  88. return Status::Corruption(kErrorMessage, "CRC mismatch");
  89. }
  90. return Status::OK();
  91. }
  92. void BlobLogRecord::EncodeHeaderTo(std::string* dst) {
  93. assert(dst != nullptr);
  94. dst->clear();
  95. dst->reserve(BlobLogRecord::kHeaderSize + key.size() + value.size());
  96. PutFixed64(dst, key.size());
  97. PutFixed64(dst, value.size());
  98. PutFixed64(dst, expiration);
  99. header_crc = crc32c::Value(dst->c_str(), dst->size());
  100. header_crc = crc32c::Mask(header_crc);
  101. PutFixed32(dst, header_crc);
  102. blob_crc = crc32c::Value(key.data(), key.size());
  103. blob_crc = crc32c::Extend(blob_crc, value.data(), value.size());
  104. blob_crc = crc32c::Mask(blob_crc);
  105. PutFixed32(dst, blob_crc);
  106. }
  107. Status BlobLogRecord::DecodeHeaderFrom(Slice src) {
  108. static const std::string kErrorMessage = "Error while decoding blob record";
  109. if (src.size() != BlobLogRecord::kHeaderSize) {
  110. return Status::Corruption(kErrorMessage,
  111. "Unexpected blob record header size");
  112. }
  113. uint32_t src_crc = 0;
  114. src_crc = crc32c::Value(src.data(), BlobLogRecord::kHeaderSize - 8);
  115. src_crc = crc32c::Mask(src_crc);
  116. if (!GetFixed64(&src, &key_size) || !GetFixed64(&src, &value_size) ||
  117. !GetFixed64(&src, &expiration) || !GetFixed32(&src, &header_crc) ||
  118. !GetFixed32(&src, &blob_crc)) {
  119. return Status::Corruption(kErrorMessage, "Error decoding content");
  120. }
  121. if (src_crc != header_crc) {
  122. return Status::Corruption(kErrorMessage, "Header CRC mismatch");
  123. }
  124. return Status::OK();
  125. }
  126. Status BlobLogRecord::CheckBlobCRC() const {
  127. uint32_t expected_crc = 0;
  128. expected_crc = crc32c::Value(key.data(), key.size());
  129. expected_crc = crc32c::Extend(expected_crc, value.data(), value.size());
  130. expected_crc = crc32c::Mask(expected_crc);
  131. if (expected_crc != blob_crc) {
  132. return Status::Corruption("Blob CRC mismatch");
  133. }
  134. return Status::OK();
  135. }
  136. } // namespace blob_db
  137. } // namespace ROCKSDB_NAMESPACE
  138. #endif // ROCKSDB_LITE