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