/src/rocksdb/db/kv_checksum.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2020-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 | | // This file contains classes containing fields to protect individual entries. |
7 | | // The classes are named "ProtectionInfo<suffix>", where <suffix> indicates the |
8 | | // combination of fields that are covered. Each field has a single letter |
9 | | // abbreviation as follows. |
10 | | // |
11 | | // K = key |
12 | | // V = value |
13 | | // O = optype aka value type |
14 | | // S = seqno |
15 | | // C = CF ID |
16 | | // |
17 | | // Then, for example, a class that protects an entry consisting of key, value, |
18 | | // optype, and CF ID (i.e., a `WriteBatch` entry) would be named |
19 | | // `ProtectionInfoKVOC`. |
20 | | // |
21 | | // The `ProtectionInfo.*` classes are templated on the integer type used to hold |
22 | | // the XOR of hashes for each field. Only unsigned integer types are supported, |
23 | | // and the maximum supported integer width is 64 bits. When the integer type is |
24 | | // narrower than the hash values, we lop off the most significant bits to make |
25 | | // them fit. |
26 | | // |
27 | | // The `ProtectionInfo.*` classes are all intended to be non-persistent. We do |
28 | | // not currently make the byte order consistent for integer fields before |
29 | | // hashing them, so the resulting values are endianness-dependent. |
30 | | |
31 | | #pragma once |
32 | | |
33 | | #include <type_traits> |
34 | | |
35 | | #include "db/dbformat.h" |
36 | | #include "rocksdb/types.h" |
37 | | #include "util/hash.h" |
38 | | |
39 | | namespace ROCKSDB_NAMESPACE { |
40 | | |
41 | | template <typename T> |
42 | | class ProtectionInfo; |
43 | | template <typename T> |
44 | | class ProtectionInfoKVO; |
45 | | template <typename T> |
46 | | class ProtectionInfoKVOC; |
47 | | template <typename T> |
48 | | class ProtectionInfoKVOS; |
49 | | template <typename T> |
50 | | class ProtectionInfoKV; |
51 | | |
52 | | // Aliases for 64-bit protection infos. |
53 | | using ProtectionInfo64 = ProtectionInfo<uint64_t>; |
54 | | using ProtectionInfoKVO64 = ProtectionInfoKVO<uint64_t>; |
55 | | using ProtectionInfoKVOC64 = ProtectionInfoKVOC<uint64_t>; |
56 | | using ProtectionInfoKVOS64 = ProtectionInfoKVOS<uint64_t>; |
57 | | |
58 | | template <typename T> |
59 | | class ProtectionInfo { |
60 | | public: |
61 | 14.7k | ProtectionInfo() = default; |
62 | | |
63 | | Status GetStatus() const; |
64 | | ProtectionInfoKVO<T> ProtectKVO(const Slice& key, const Slice& value, |
65 | | ValueType op_type) const; |
66 | | ProtectionInfoKVO<T> ProtectKVO(const SliceParts& key, |
67 | | const SliceParts& value, |
68 | | ValueType op_type) const; |
69 | | ProtectionInfoKV<T> ProtectKV(const Slice& key, const Slice& value) const; |
70 | | |
71 | | private: |
72 | | friend class ProtectionInfoKVO<T>; |
73 | | friend class ProtectionInfoKVOS<T>; |
74 | | friend class ProtectionInfoKVOC<T>; |
75 | | friend class ProtectionInfoKV<T>; |
76 | | |
77 | | // Each field is hashed with an independent value so we can catch fields being |
78 | | // swapped. Per the `NPHash64()` docs, using consecutive seeds is a pitfall, |
79 | | // and we should instead vary our seeds by a large odd number. This value by |
80 | | // which we increment (0xD28AAD72F49BD50B) was taken from |
81 | | // `head -c8 /dev/urandom | hexdump`, run repeatedly until it yielded an odd |
82 | | // number. The values are computed manually since the Windows C++ compiler |
83 | | // complains about the overflow when adding constants. |
84 | | static const uint64_t kSeedK = 0; |
85 | | static const uint64_t kSeedV = 0xD28AAD72F49BD50B; |
86 | | static const uint64_t kSeedO = 0xA5155AE5E937AA16; |
87 | | static const uint64_t kSeedS = 0x77A00858DDD37F21; |
88 | | static const uint64_t kSeedC = 0x4A2AB5CBD26F542C; |
89 | | |
90 | 78.4k | ProtectionInfo(T val) : val_(val) { |
91 | 78.4k | static_assert(sizeof(ProtectionInfo<T>) == sizeof(T), ""); |
92 | 78.4k | } |
93 | | |
94 | 80.7k | T GetVal() const { return val_; } |
95 | 2.28k | void SetVal(T val) { val_ = val; } |
96 | | |
97 | 0 | void Encode(uint8_t len, char* dst) const { |
98 | 0 | assert(sizeof(val_) >= len); |
99 | 0 | switch (len) { |
100 | 0 | case 1: |
101 | 0 | dst[0] = static_cast<uint8_t>(val_); |
102 | 0 | break; |
103 | 0 | case 2: |
104 | 0 | EncodeFixed16(dst, static_cast<uint16_t>(val_)); |
105 | 0 | break; |
106 | 0 | case 4: |
107 | 0 | EncodeFixed32(dst, static_cast<uint32_t>(val_)); |
108 | 0 | break; |
109 | 0 | case 8: |
110 | 0 | EncodeFixed64(dst, static_cast<uint64_t>(val_)); |
111 | 0 | break; |
112 | 0 | default: |
113 | 0 | assert(false); |
114 | 0 | } |
115 | 0 | } |
116 | | |
117 | 0 | bool Verify(uint8_t len, const char* checksum_ptr) const { |
118 | 0 | assert(sizeof(val_) >= len); |
119 | 0 | switch (len) { |
120 | 0 | case 1: |
121 | 0 | return static_cast<uint8_t>(checksum_ptr[0]) == |
122 | 0 | static_cast<uint8_t>(val_); |
123 | 0 | case 2: |
124 | 0 | return DecodeFixed16(checksum_ptr) == static_cast<uint16_t>(val_); |
125 | 0 | case 4: |
126 | 0 | return DecodeFixed32(checksum_ptr) == static_cast<uint32_t>(val_); |
127 | 0 | case 8: |
128 | 0 | return DecodeFixed64(checksum_ptr) == static_cast<uint64_t>(val_); |
129 | 0 | default: |
130 | 0 | assert(false); |
131 | 0 | return false; |
132 | 0 | } |
133 | 0 | } |
134 | | |
135 | | T val_ = 0; |
136 | | }; |
137 | | |
138 | | template <typename T> |
139 | | class ProtectionInfoKVO { |
140 | | public: |
141 | 0 | ProtectionInfoKVO() = default; |
142 | | |
143 | | ProtectionInfo<T> StripKVO(const Slice& key, const Slice& value, |
144 | | ValueType op_type) const; |
145 | | ProtectionInfo<T> StripKVO(const SliceParts& key, const SliceParts& value, |
146 | | ValueType op_type) const; |
147 | | |
148 | | ProtectionInfoKVOC<T> ProtectC(ColumnFamilyId column_family_id) const; |
149 | | ProtectionInfoKVOS<T> ProtectS(SequenceNumber sequence_number) const; |
150 | | |
151 | | void UpdateK(const Slice& old_key, const Slice& new_key); |
152 | | void UpdateK(const SliceParts& old_key, const SliceParts& new_key); |
153 | | void UpdateV(const Slice& old_value, const Slice& new_value); |
154 | | void UpdateV(const SliceParts& old_value, const SliceParts& new_value); |
155 | | void UpdateO(ValueType old_op_type, ValueType new_op_type); |
156 | | |
157 | | // Encode this protection info into `len` bytes and stores them in `dst`. |
158 | 0 | void Encode(uint8_t len, char* dst) const { info_.Encode(len, dst); } |
159 | | // Verify this protection info against the protection info encoded by Encode() |
160 | | // at the first `len` bytes of `checksum_ptr`. |
161 | | // Returns true iff the verification is successful. |
162 | 0 | bool Verify(uint8_t len, const char* checksum_ptr) const { |
163 | 0 | return info_.Verify(len, checksum_ptr); |
164 | 0 | } |
165 | | |
166 | | private: |
167 | | friend class ProtectionInfo<T>; |
168 | | friend class ProtectionInfoKVOS<T>; |
169 | | friend class ProtectionInfoKVOC<T>; |
170 | | |
171 | 68.6k | explicit ProtectionInfoKVO(T val) : info_(val) { |
172 | 68.6k | static_assert(sizeof(ProtectionInfoKVO<T>) == sizeof(T), ""); |
173 | 68.6k | } |
174 | | |
175 | 66.0k | T GetVal() const { return info_.GetVal(); } |
176 | 2.28k | void SetVal(T val) { info_.SetVal(val); } |
177 | | |
178 | | ProtectionInfo<T> info_; |
179 | | }; |
180 | | |
181 | | template <typename T> |
182 | | class ProtectionInfoKVOC { |
183 | | public: |
184 | 0 | ProtectionInfoKVOC() = default; |
185 | | |
186 | | ProtectionInfoKVO<T> StripC(ColumnFamilyId column_family_id) const; |
187 | | |
188 | | void UpdateK(const Slice& old_key, const Slice& new_key) { |
189 | | kvo_.UpdateK(old_key, new_key); |
190 | | } |
191 | 0 | void UpdateK(const SliceParts& old_key, const SliceParts& new_key) { |
192 | 0 | kvo_.UpdateK(old_key, new_key); |
193 | 0 | } |
194 | | void UpdateV(const Slice& old_value, const Slice& new_value) { |
195 | | kvo_.UpdateV(old_value, new_value); |
196 | | } |
197 | 0 | void UpdateV(const SliceParts& old_value, const SliceParts& new_value) { |
198 | 0 | kvo_.UpdateV(old_value, new_value); |
199 | 0 | } |
200 | | void UpdateO(ValueType old_op_type, ValueType new_op_type) { |
201 | | kvo_.UpdateO(old_op_type, new_op_type); |
202 | | } |
203 | | void UpdateC(ColumnFamilyId old_column_family_id, |
204 | | ColumnFamilyId new_column_family_id); |
205 | | |
206 | | void Encode(uint8_t len, char* dst) const { kvo_.Encode(len, dst); } |
207 | | bool Verify(uint8_t len, const char* checksum_ptr) const { |
208 | | return kvo_.Verify(len, checksum_ptr); |
209 | | } |
210 | | |
211 | | private: |
212 | | friend class ProtectionInfoKVO<T>; |
213 | | |
214 | 14.7k | explicit ProtectionInfoKVOC(T val) : kvo_(val) { |
215 | 14.7k | static_assert(sizeof(ProtectionInfoKVOC<T>) == sizeof(T), ""); |
216 | 14.7k | } |
217 | | |
218 | 14.7k | T GetVal() const { return kvo_.GetVal(); } |
219 | | void SetVal(T val) { kvo_.SetVal(val); } |
220 | | |
221 | | ProtectionInfoKVO<T> kvo_; |
222 | | }; |
223 | | |
224 | | template <typename T> |
225 | | class ProtectionInfoKVOS { |
226 | | public: |
227 | | ProtectionInfoKVOS() = default; |
228 | | |
229 | | ProtectionInfoKVO<T> StripS(SequenceNumber sequence_number) const; |
230 | | |
231 | | void UpdateK(const Slice& old_key, const Slice& new_key) { |
232 | | kvo_.UpdateK(old_key, new_key); |
233 | | } |
234 | | void UpdateK(const SliceParts& old_key, const SliceParts& new_key) { |
235 | | kvo_.UpdateK(old_key, new_key); |
236 | | } |
237 | 0 | void UpdateV(const Slice& old_value, const Slice& new_value) { |
238 | 0 | kvo_.UpdateV(old_value, new_value); |
239 | 0 | } |
240 | | void UpdateV(const SliceParts& old_value, const SliceParts& new_value) { |
241 | | kvo_.UpdateV(old_value, new_value); |
242 | | } |
243 | 2.28k | void UpdateO(ValueType old_op_type, ValueType new_op_type) { |
244 | 2.28k | kvo_.UpdateO(old_op_type, new_op_type); |
245 | 2.28k | } |
246 | | void UpdateS(SequenceNumber old_sequence_number, |
247 | | SequenceNumber new_sequence_number); |
248 | | |
249 | 0 | void Encode(uint8_t len, char* dst) const { kvo_.Encode(len, dst); } |
250 | 0 | bool Verify(uint8_t len, const char* checksum_ptr) const { |
251 | 0 | return kvo_.Verify(len, checksum_ptr); |
252 | 0 | } |
253 | | |
254 | | private: |
255 | | friend class ProtectionInfoKVO<T>; |
256 | | |
257 | 14.7k | explicit ProtectionInfoKVOS(T val) : kvo_(val) { |
258 | 14.7k | static_assert(sizeof(ProtectionInfoKVOS<T>) == sizeof(T), ""); |
259 | 14.7k | } |
260 | | |
261 | 9.82k | T GetVal() const { return kvo_.GetVal(); } |
262 | 0 | void SetVal(T val) { kvo_.SetVal(val); } |
263 | | |
264 | | ProtectionInfoKVO<T> kvo_; |
265 | | }; |
266 | | |
267 | | template <typename T> |
268 | | class ProtectionInfoKV { |
269 | | public: |
270 | | ProtectionInfoKV() = default; |
271 | | |
272 | 0 | void Encode(uint8_t len, char* dst) const { info_.Encode(len, dst); } |
273 | 0 | bool Verify(uint8_t len, const char* checksum_ptr) const { |
274 | 0 | return info_.Verify(len, checksum_ptr); |
275 | 0 | } |
276 | | |
277 | | private: |
278 | | friend class ProtectionInfo<T>; |
279 | | |
280 | 0 | explicit ProtectionInfoKV(T val) : info_(val) { |
281 | 0 | static_assert(sizeof(ProtectionInfoKV<T>) == sizeof(T)); |
282 | 0 | } |
283 | | |
284 | | ProtectionInfo<T> info_; |
285 | | }; |
286 | | |
287 | | template <typename T> |
288 | 9.82k | Status ProtectionInfo<T>::GetStatus() const { |
289 | 9.82k | if (val_ != 0) { |
290 | 0 | return Status::Corruption("ProtectionInfo mismatch"); |
291 | 0 | } |
292 | 9.82k | return Status::OK(); |
293 | 9.82k | } |
294 | | |
295 | | template <typename T> |
296 | | ProtectionInfoKVO<T> ProtectionInfo<T>::ProtectKVO(const Slice& key, |
297 | | const Slice& value, |
298 | 14.7k | ValueType op_type) const { |
299 | 14.7k | T val = GetVal(); |
300 | 14.7k | val = val ^ static_cast<T>(GetSliceNPHash64(key, ProtectionInfo<T>::kSeedK)); |
301 | 14.7k | val = |
302 | 14.7k | val ^ static_cast<T>(GetSliceNPHash64(value, ProtectionInfo<T>::kSeedV)); |
303 | 14.7k | val = val ^ |
304 | 14.7k | static_cast<T>(NPHash64(reinterpret_cast<char*>(&op_type), |
305 | 14.7k | sizeof(op_type), ProtectionInfo<T>::kSeedO)); |
306 | 14.7k | return ProtectionInfoKVO<T>(val); |
307 | 14.7k | } |
308 | | |
309 | | template <typename T> |
310 | | ProtectionInfoKVO<T> ProtectionInfo<T>::ProtectKVO(const SliceParts& key, |
311 | | const SliceParts& value, |
312 | 0 | ValueType op_type) const { |
313 | 0 | T val = GetVal(); |
314 | 0 | val = val ^ |
315 | 0 | static_cast<T>(GetSlicePartsNPHash64(key, ProtectionInfo<T>::kSeedK)); |
316 | 0 | val = val ^ |
317 | 0 | static_cast<T>(GetSlicePartsNPHash64(value, ProtectionInfo<T>::kSeedV)); |
318 | 0 | val = val ^ |
319 | 0 | static_cast<T>(NPHash64(reinterpret_cast<char*>(&op_type), |
320 | 0 | sizeof(op_type), ProtectionInfo<T>::kSeedO)); |
321 | 0 | return ProtectionInfoKVO<T>(val); |
322 | 0 | } |
323 | | |
324 | | template <typename T> |
325 | | ProtectionInfoKV<T> ProtectionInfo<T>::ProtectKV(const Slice& key, |
326 | 0 | const Slice& value) const { |
327 | 0 | T val = GetVal(); |
328 | 0 | val = val ^ static_cast<T>(GetSliceNPHash64(key, ProtectionInfo<T>::kSeedK)); |
329 | 0 | val = |
330 | 0 | val ^ static_cast<T>(GetSliceNPHash64(value, ProtectionInfo<T>::kSeedV)); |
331 | 0 | return ProtectionInfoKV<T>(val); |
332 | 0 | } |
333 | | |
334 | | template <typename T> |
335 | | void ProtectionInfoKVO<T>::UpdateK(const Slice& old_key, const Slice& new_key) { |
336 | | T val = GetVal(); |
337 | | val = val ^ |
338 | | static_cast<T>(GetSliceNPHash64(old_key, ProtectionInfo<T>::kSeedK)); |
339 | | val = val ^ |
340 | | static_cast<T>(GetSliceNPHash64(new_key, ProtectionInfo<T>::kSeedK)); |
341 | | SetVal(val); |
342 | | } |
343 | | |
344 | | template <typename T> |
345 | | void ProtectionInfoKVO<T>::UpdateK(const SliceParts& old_key, |
346 | 0 | const SliceParts& new_key) { |
347 | 0 | T val = GetVal(); |
348 | 0 | val = val ^ static_cast<T>( |
349 | 0 | GetSlicePartsNPHash64(old_key, ProtectionInfo<T>::kSeedK)); |
350 | 0 | val = val ^ static_cast<T>( |
351 | 0 | GetSlicePartsNPHash64(new_key, ProtectionInfo<T>::kSeedK)); |
352 | 0 | SetVal(val); |
353 | 0 | } |
354 | | |
355 | | template <typename T> |
356 | | void ProtectionInfoKVO<T>::UpdateV(const Slice& old_value, |
357 | 0 | const Slice& new_value) { |
358 | 0 | T val = GetVal(); |
359 | 0 | val = val ^ |
360 | 0 | static_cast<T>(GetSliceNPHash64(old_value, ProtectionInfo<T>::kSeedV)); |
361 | 0 | val = val ^ |
362 | 0 | static_cast<T>(GetSliceNPHash64(new_value, ProtectionInfo<T>::kSeedV)); |
363 | 0 | SetVal(val); |
364 | 0 | } |
365 | | |
366 | | template <typename T> |
367 | | void ProtectionInfoKVO<T>::UpdateV(const SliceParts& old_value, |
368 | 0 | const SliceParts& new_value) { |
369 | 0 | T val = GetVal(); |
370 | 0 | val = val ^ static_cast<T>( |
371 | 0 | GetSlicePartsNPHash64(old_value, ProtectionInfo<T>::kSeedV)); |
372 | 0 | val = val ^ static_cast<T>( |
373 | 0 | GetSlicePartsNPHash64(new_value, ProtectionInfo<T>::kSeedV)); |
374 | 0 | SetVal(val); |
375 | 0 | } |
376 | | |
377 | | template <typename T> |
378 | | void ProtectionInfoKVO<T>::UpdateO(ValueType old_op_type, |
379 | 2.28k | ValueType new_op_type) { |
380 | 2.28k | T val = GetVal(); |
381 | 2.28k | val = val ^ static_cast<T>(NPHash64(reinterpret_cast<char*>(&old_op_type), |
382 | 2.28k | sizeof(old_op_type), |
383 | 2.28k | ProtectionInfo<T>::kSeedO)); |
384 | 2.28k | val = val ^ static_cast<T>(NPHash64(reinterpret_cast<char*>(&new_op_type), |
385 | 2.28k | sizeof(new_op_type), |
386 | 2.28k | ProtectionInfo<T>::kSeedO)); |
387 | 2.28k | SetVal(val); |
388 | 2.28k | } |
389 | | |
390 | | template <typename T> |
391 | | ProtectionInfo<T> ProtectionInfoKVO<T>::StripKVO(const Slice& key, |
392 | | const Slice& value, |
393 | 9.82k | ValueType op_type) const { |
394 | 9.82k | T val = GetVal(); |
395 | 9.82k | val = val ^ static_cast<T>(GetSliceNPHash64(key, ProtectionInfo<T>::kSeedK)); |
396 | 9.82k | val = |
397 | 9.82k | val ^ static_cast<T>(GetSliceNPHash64(value, ProtectionInfo<T>::kSeedV)); |
398 | 9.82k | val = val ^ |
399 | 9.82k | static_cast<T>(NPHash64(reinterpret_cast<char*>(&op_type), |
400 | 9.82k | sizeof(op_type), ProtectionInfo<T>::kSeedO)); |
401 | 9.82k | return ProtectionInfo<T>(val); |
402 | 9.82k | } |
403 | | |
404 | | template <typename T> |
405 | | ProtectionInfo<T> ProtectionInfoKVO<T>::StripKVO(const SliceParts& key, |
406 | | const SliceParts& value, |
407 | | ValueType op_type) const { |
408 | | T val = GetVal(); |
409 | | val = val ^ |
410 | | static_cast<T>(GetSlicePartsNPHash64(key, ProtectionInfo<T>::kSeedK)); |
411 | | val = val ^ |
412 | | static_cast<T>(GetSlicePartsNPHash64(value, ProtectionInfo<T>::kSeedV)); |
413 | | val = val ^ |
414 | | static_cast<T>(NPHash64(reinterpret_cast<char*>(&op_type), |
415 | | sizeof(op_type), ProtectionInfo<T>::kSeedO)); |
416 | | return ProtectionInfo<T>(val); |
417 | | } |
418 | | |
419 | | template <typename T> |
420 | | ProtectionInfoKVOC<T> ProtectionInfoKVO<T>::ProtectC( |
421 | 14.7k | ColumnFamilyId column_family_id) const { |
422 | 14.7k | T val = GetVal(); |
423 | 14.7k | val = val ^ static_cast<T>(NPHash64( |
424 | 14.7k | reinterpret_cast<char*>(&column_family_id), |
425 | 14.7k | sizeof(column_family_id), ProtectionInfo<T>::kSeedC)); |
426 | 14.7k | return ProtectionInfoKVOC<T>(val); |
427 | 14.7k | } |
428 | | |
429 | | template <typename T> |
430 | | ProtectionInfoKVO<T> ProtectionInfoKVOC<T>::StripC( |
431 | 14.7k | ColumnFamilyId column_family_id) const { |
432 | 14.7k | T val = GetVal(); |
433 | 14.7k | val = val ^ static_cast<T>(NPHash64( |
434 | 14.7k | reinterpret_cast<char*>(&column_family_id), |
435 | 14.7k | sizeof(column_family_id), ProtectionInfo<T>::kSeedC)); |
436 | 14.7k | return ProtectionInfoKVO<T>(val); |
437 | 14.7k | } |
438 | | |
439 | | template <typename T> |
440 | | void ProtectionInfoKVOC<T>::UpdateC(ColumnFamilyId old_column_family_id, |
441 | | ColumnFamilyId new_column_family_id) { |
442 | | T val = GetVal(); |
443 | | val = val ^ static_cast<T>(NPHash64( |
444 | | reinterpret_cast<char*>(&old_column_family_id), |
445 | | sizeof(old_column_family_id), ProtectionInfo<T>::kSeedC)); |
446 | | val = val ^ static_cast<T>(NPHash64( |
447 | | reinterpret_cast<char*>(&new_column_family_id), |
448 | | sizeof(new_column_family_id), ProtectionInfo<T>::kSeedC)); |
449 | | SetVal(val); |
450 | | } |
451 | | |
452 | | template <typename T> |
453 | | ProtectionInfoKVOS<T> ProtectionInfoKVO<T>::ProtectS( |
454 | 14.7k | SequenceNumber sequence_number) const { |
455 | 14.7k | T val = GetVal(); |
456 | 14.7k | val = val ^ static_cast<T>(NPHash64(reinterpret_cast<char*>(&sequence_number), |
457 | 14.7k | sizeof(sequence_number), |
458 | 14.7k | ProtectionInfo<T>::kSeedS)); |
459 | 14.7k | return ProtectionInfoKVOS<T>(val); |
460 | 14.7k | } |
461 | | |
462 | | template <typename T> |
463 | | ProtectionInfoKVO<T> ProtectionInfoKVOS<T>::StripS( |
464 | 9.82k | SequenceNumber sequence_number) const { |
465 | 9.82k | T val = GetVal(); |
466 | 9.82k | val = val ^ static_cast<T>(NPHash64(reinterpret_cast<char*>(&sequence_number), |
467 | 9.82k | sizeof(sequence_number), |
468 | 9.82k | ProtectionInfo<T>::kSeedS)); |
469 | 9.82k | return ProtectionInfoKVO<T>(val); |
470 | 9.82k | } |
471 | | |
472 | | template <typename T> |
473 | | void ProtectionInfoKVOS<T>::UpdateS(SequenceNumber old_sequence_number, |
474 | 0 | SequenceNumber new_sequence_number) { |
475 | 0 | T val = GetVal(); |
476 | 0 | val = val ^ static_cast<T>(NPHash64( |
477 | 0 | reinterpret_cast<char*>(&old_sequence_number), |
478 | 0 | sizeof(old_sequence_number), ProtectionInfo<T>::kSeedS)); |
479 | 0 | val = val ^ static_cast<T>(NPHash64( |
480 | 0 | reinterpret_cast<char*>(&new_sequence_number), |
481 | 0 | sizeof(new_sequence_number), ProtectionInfo<T>::kSeedS)); |
482 | 0 | SetVal(val); |
483 | 0 | } |
484 | | } // namespace ROCKSDB_NAMESPACE |