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