1use crate::checksum::{Checksums, ChecksumsV38};
8use crate::lsm_tree::types::{OrdLowerBound, OrdUpperBound};
9use crate::round::{round_down, round_up};
10use bit_vec::BitVec;
11use fprint::TypeFingerprint;
12use serde::{Deserialize, Serialize};
13use std::cmp::{max, min};
14use std::hash::Hash;
15use std::ops::Range;
16
17pub const DEFAULT_DATA_ATTRIBUTE_ID: u64 = 0;
19
20pub const BLOB_MERKLE_ATTRIBUTE_ID: u64 = 1;
24
25pub const FSVERITY_MERKLE_ATTRIBUTE_ID: u64 = 2;
28
29pub type ExtentKey = ExtentKeyV32;
32
33#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize, TypeFingerprint)]
34#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
35pub struct ExtentKeyV32 {
36 pub range: Range<u64>,
37}
38
39const EXTENT_HASH_BUCKET_SIZE: u64 = 1 * 1024 * 1024;
40
41pub struct ExtentKeyPartitionIterator {
42 range: Range<u64>,
43}
44
45impl Iterator for ExtentKeyPartitionIterator {
46 type Item = Range<u64>;
47
48 fn next(&mut self) -> Option<Self::Item> {
49 if self.range.start >= self.range.end {
50 None
51 } else {
52 let start = self.range.start;
53 self.range.start = start.saturating_add(EXTENT_HASH_BUCKET_SIZE);
54 let end = std::cmp::min(self.range.start, self.range.end);
55 Some(start..end)
56 }
57 }
58}
59
60impl ExtentKey {
61 pub fn new(range: std::ops::Range<u64>) -> Self {
63 Self { range }
64 }
65
66 pub fn overlap(&self, other: &ExtentKey) -> Option<Range<u64>> {
68 if self.range.end <= other.range.start || self.range.start >= other.range.end {
69 None
70 } else {
71 Some(max(self.range.start, other.range.start)..min(self.range.end, other.range.end))
72 }
73 }
74
75 pub fn search_key(&self) -> Self {
82 assert_ne!(self.range.start, self.range.end);
83 ExtentKey::search_key_from_offset(self.range.start)
84 }
85
86 pub fn search_key_from_offset(offset: u64) -> Self {
89 Self { range: 0..offset + 1 }
90 }
91
92 pub fn key_for_merge_into(&self) -> Self {
99 Self { range: 0..self.range.start }
100 }
101
102 pub fn fuzzy_hash_partition(&self) -> ExtentKeyPartitionIterator {
104 ExtentKeyPartitionIterator {
105 range: round_down(self.range.start, EXTENT_HASH_BUCKET_SIZE)
106 ..round_up(self.range.end, EXTENT_HASH_BUCKET_SIZE).unwrap_or(u64::MAX),
107 }
108 }
109}
110
111impl OrdUpperBound for ExtentKey {
116 fn cmp_upper_bound(&self, other: &ExtentKey) -> std::cmp::Ordering {
117 self.range.end.cmp(&other.range.end)
124 }
125}
126
127impl OrdLowerBound for ExtentKey {
128 fn cmp_lower_bound(&self, other: &ExtentKey) -> std::cmp::Ordering {
131 self.range.start.cmp(&other.range.start)
132 }
133}
134
135impl Ord for ExtentKey {
136 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
137 self.range.start.cmp(&other.range.start).then(self.range.end.cmp(&other.range.end))
141 }
142}
143
144impl PartialOrd for ExtentKey {
145 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
146 Some(self.cmp(other))
147 }
148}
149
150pub type ExtentMode = ExtentModeV38;
152
153#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, TypeFingerprint)]
154pub enum ExtentModeV38 {
155 Raw,
159 Cow(ChecksumsV38),
162 OverwritePartial(BitVec),
167 Overwrite,
171}
172
173#[cfg(fuzz)]
174impl<'a> arbitrary::Arbitrary<'a> for ExtentMode {
175 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
176 Ok(match u.int_in_range(0..=3)? {
177 0 => ExtentMode::Raw,
178 1 => ExtentMode::Cow(u.arbitrary()?),
179 2 => ExtentMode::OverwritePartial(BitVec::from_bytes(u.arbitrary()?)),
180 3 => ExtentMode::Overwrite,
181 _ => unreachable!(),
182 })
183 }
184}
185
186pub type ExtentValue = ExtentValueV38;
189
190#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, TypeFingerprint)]
191#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
192pub enum ExtentValueV38 {
193 None,
196 Some { device_offset: u64, mode: ExtentModeV38, key_id: u64 },
200}
201
202impl ExtentValue {
203 pub fn new(device_offset: u64, mode: ExtentMode, key_id: u64) -> ExtentValue {
204 ExtentValue::Some { device_offset, mode, key_id }
205 }
206
207 pub fn new_raw(device_offset: u64, key_id: u64) -> ExtentValue {
208 Self::new(device_offset, ExtentMode::Raw, key_id)
209 }
210
211 pub fn with_checksum(device_offset: u64, checksums: Checksums, key_id: u64) -> ExtentValue {
213 Self::new(device_offset, ExtentMode::Cow(checksums), key_id)
214 }
215
216 pub fn blank_overwrite_extent(
218 device_offset: u64,
219 num_blocks: usize,
220 key_id: u64,
221 ) -> ExtentValue {
222 Self::new(
223 device_offset,
224 ExtentMode::OverwritePartial(BitVec::from_elem(num_blocks, false)),
225 key_id,
226 )
227 }
228
229 pub fn initialized_overwrite_extent(device_offset: u64, key_id: u64) -> ExtentValue {
231 Self::new(device_offset, ExtentMode::Overwrite, key_id)
232 }
233
234 pub fn deleted_extent() -> ExtentValue {
236 ExtentValue::None
237 }
238
239 pub fn is_deleted(&self) -> bool {
240 if let ExtentValue::None = self { true } else { false }
241 }
242
243 pub fn offset_by(&self, amount: u64, extent_len: u64) -> Self {
246 match self {
247 ExtentValue::None => Self::deleted_extent(),
248 ExtentValue::Some { device_offset, mode, key_id } => {
249 let mode = match mode {
250 ExtentMode::Raw => ExtentMode::Raw,
251 ExtentMode::Cow(checksums) => {
252 if checksums.len() > 0 {
253 let index = (amount / (extent_len / checksums.len() as u64)) as usize;
254 ExtentMode::Cow(checksums.offset_by(index))
255 } else {
256 ExtentMode::Cow(Checksums::fletcher(Vec::new()))
257 }
258 }
259 ExtentMode::Overwrite => ExtentMode::Overwrite,
260 ExtentMode::OverwritePartial(bitmap) => {
261 debug_assert!(bitmap.len() > 0);
262 let index = (amount / (extent_len / bitmap.len() as u64)) as usize;
263 ExtentMode::OverwritePartial(bitmap.clone().split_off(index))
264 }
265 };
266 ExtentValue::Some { device_offset: device_offset + amount, mode, key_id: *key_id }
267 }
268 }
269 }
270
271 pub fn shrunk(&self, original_len: u64, new_len: u64) -> Self {
273 match self {
274 ExtentValue::None => Self::deleted_extent(),
275 ExtentValue::Some { device_offset, mode, key_id } => {
276 let mode = match mode {
277 ExtentMode::Raw => ExtentMode::Raw,
278 ExtentMode::Cow(checksums) => {
279 if checksums.len() > 0 {
280 let len = (new_len / (original_len / checksums.len() as u64)) as usize;
281 ExtentMode::Cow(checksums.shrunk(len))
282 } else {
283 ExtentMode::Cow(Checksums::fletcher(Vec::new()))
284 }
285 }
286 ExtentMode::Overwrite => ExtentMode::Overwrite,
287 ExtentMode::OverwritePartial(bitmap) => {
288 debug_assert!(bitmap.len() > 0);
289 let len = (new_len / (original_len / bitmap.len() as u64)) as usize;
290 let mut new_bitmap = bitmap.clone();
291 new_bitmap.truncate(len);
292 ExtentMode::OverwritePartial(new_bitmap)
293 }
294 };
295 ExtentValue::Some { device_offset: *device_offset, mode, key_id: *key_id }
296 }
297 }
298 }
299}
300
301#[cfg(test)]
302mod tests {
303 use super::{ExtentKey, ExtentMode, ExtentValue};
304 use crate::checksum::Checksums;
305 use crate::lsm_tree::types::{OrdLowerBound, OrdUpperBound};
306 use crate::object_store::VOLUME_DATA_KEY_ID;
307 use bit_vec::BitVec;
308 use std::cmp::Ordering;
309
310 #[test]
311 fn test_extent_cmp() {
312 let extent = ExtentKey::new(100..150);
313 assert_eq!(extent.cmp_upper_bound(&ExtentKey::new(0..100)), Ordering::Greater);
314 assert_eq!(extent.cmp_upper_bound(&ExtentKey::new(0..110)), Ordering::Greater);
315 assert_eq!(extent.cmp_upper_bound(&ExtentKey::new(0..150)), Ordering::Equal);
316 assert_eq!(extent.cmp_upper_bound(&ExtentKey::new(99..150)), Ordering::Equal);
317 assert_eq!(extent.cmp_upper_bound(&ExtentKey::new(100..150)), Ordering::Equal);
318 assert_eq!(extent.cmp_upper_bound(&ExtentKey::new(0..151)), Ordering::Less);
319 assert_eq!(extent.cmp_upper_bound(&ExtentKey::new(100..151)), Ordering::Less);
320 assert_eq!(extent.cmp_upper_bound(&ExtentKey::new(150..1000)), Ordering::Less);
321 }
322
323 #[test]
324 fn test_extent_cmp_lower_bound() {
325 let extent = ExtentKey::new(100..150);
326 assert_eq!(extent.cmp_lower_bound(&ExtentKey::new(0..100)), Ordering::Greater);
327 assert_eq!(extent.cmp_lower_bound(&ExtentKey::new(0..110)), Ordering::Greater);
328 assert_eq!(extent.cmp_lower_bound(&ExtentKey::new(0..150)), Ordering::Greater);
329 assert_eq!(extent.cmp_lower_bound(&ExtentKey::new(0..1000)), Ordering::Greater);
330 assert_eq!(extent.cmp_lower_bound(&ExtentKey::new(99..1000)), Ordering::Greater);
331 assert_eq!(extent.cmp_lower_bound(&ExtentKey::new(100..150)), Ordering::Equal);
332 assert_eq!(extent.cmp_lower_bound(&ExtentKey::new(100..1000)), Ordering::Equal);
334 assert_eq!(extent.cmp_lower_bound(&ExtentKey::new(101..102)), Ordering::Less);
335 }
336
337 #[test]
338 fn test_extent_search_and_insertion_key() {
339 let extent = ExtentKey::new(100..150);
340 assert_eq!(extent.search_key(), ExtentKey::new(0..101));
341 assert_eq!(extent.cmp_lower_bound(&extent.search_key()), Ordering::Greater);
342 assert_eq!(extent.cmp_upper_bound(&extent.search_key()), Ordering::Greater);
343 assert_eq!(extent.key_for_merge_into(), ExtentKey::new(0..100));
344 assert_eq!(extent.cmp_lower_bound(&extent.key_for_merge_into()), Ordering::Greater);
345 }
346
347 #[test]
348 fn extent_value_offset_by() {
349 assert_eq!(ExtentValue::None.offset_by(1024, 2048), ExtentValue::None);
350 assert_eq!(
351 ExtentValue::new_raw(1024, VOLUME_DATA_KEY_ID).offset_by(0, 2048),
352 ExtentValue::new_raw(1024, VOLUME_DATA_KEY_ID)
353 );
354 assert_eq!(
355 ExtentValue::new_raw(1024, VOLUME_DATA_KEY_ID).offset_by(1024, 2048),
356 ExtentValue::new_raw(2048, VOLUME_DATA_KEY_ID)
357 );
358 assert_eq!(
359 ExtentValue::new_raw(1024, VOLUME_DATA_KEY_ID).offset_by(2048, 2048),
360 ExtentValue::new_raw(3072, VOLUME_DATA_KEY_ID)
361 );
362
363 let make_checksums = |range: std::ops::Range<u64>| Checksums::fletcher(range.collect());
364
365 assert_eq!(
367 ExtentValue::with_checksum(1024, make_checksums(0..8), VOLUME_DATA_KEY_ID)
368 .offset_by(0, 2048),
369 ExtentValue::with_checksum(1024, make_checksums(0..8), VOLUME_DATA_KEY_ID)
370 );
371 assert_eq!(
372 ExtentValue::with_checksum(1024, make_checksums(0..8), VOLUME_DATA_KEY_ID)
373 .offset_by(1024, 2048),
374 ExtentValue::with_checksum(2048, make_checksums(4..8), VOLUME_DATA_KEY_ID)
375 );
376 assert_eq!(
377 ExtentValue::with_checksum(1024, make_checksums(0..8), VOLUME_DATA_KEY_ID)
378 .offset_by(2048, 2048),
379 ExtentValue::with_checksum(3072, Checksums::fletcher(Vec::new()), VOLUME_DATA_KEY_ID)
380 );
381
382 let make_bitmap = |cut, length| {
385 let mut begin_bitmap = BitVec::from_elem(cut, false);
386 let mut end_bitmap = BitVec::from_elem(length - cut, true);
387 begin_bitmap.append(&mut end_bitmap);
388 ExtentMode::OverwritePartial(begin_bitmap)
389 };
390 let make_extent =
391 |device_offset, mode| ExtentValue::Some { device_offset, mode, key_id: 0 };
392
393 assert_eq!(
394 make_extent(1024, make_bitmap(1, 8)).offset_by(0, 2048),
395 make_extent(1024, make_bitmap(1, 8))
396 );
397 assert_eq!(
398 make_extent(1024, make_bitmap(5, 8)).offset_by(1024, 2048),
399 make_extent(2048, make_bitmap(1, 4))
400 );
401 assert_eq!(
402 make_extent(1024, make_bitmap(0, 8)).offset_by(2048, 2048),
403 make_extent(3072, ExtentMode::OverwritePartial(BitVec::new()))
404 );
405
406 assert_eq!(
407 make_extent(1024, ExtentMode::Overwrite).offset_by(0, 2048),
408 make_extent(1024, ExtentMode::Overwrite)
409 );
410 assert_eq!(
411 make_extent(1024, ExtentMode::Overwrite).offset_by(1024, 2048),
412 make_extent(2048, ExtentMode::Overwrite)
413 );
414 assert_eq!(
415 make_extent(1024, ExtentMode::Overwrite).offset_by(2048, 2048),
416 make_extent(3072, ExtentMode::Overwrite)
417 );
418 }
419
420 #[test]
421 fn extent_value_shrunk() {
422 assert_eq!(ExtentValue::None.shrunk(2048, 1024), ExtentValue::None);
423 assert_eq!(
424 ExtentValue::new_raw(1024, VOLUME_DATA_KEY_ID).shrunk(2048, 2048),
425 ExtentValue::new_raw(1024, VOLUME_DATA_KEY_ID)
426 );
427 assert_eq!(
428 ExtentValue::new_raw(1024, VOLUME_DATA_KEY_ID).shrunk(2048, 1024),
429 ExtentValue::new_raw(1024, VOLUME_DATA_KEY_ID)
430 );
431 assert_eq!(
432 ExtentValue::new_raw(1024, VOLUME_DATA_KEY_ID).shrunk(2048, 0),
433 ExtentValue::new_raw(1024, VOLUME_DATA_KEY_ID)
434 );
435
436 let make_checksums = |range: std::ops::Range<u64>| Checksums::fletcher(range.collect());
437
438 assert_eq!(
440 ExtentValue::with_checksum(1024, make_checksums(0..8), VOLUME_DATA_KEY_ID)
441 .shrunk(2048, 2048),
442 ExtentValue::with_checksum(1024, make_checksums(0..8), VOLUME_DATA_KEY_ID)
443 );
444 assert_eq!(
445 ExtentValue::with_checksum(1024, make_checksums(0..8), VOLUME_DATA_KEY_ID)
446 .shrunk(2048, 1024),
447 ExtentValue::with_checksum(1024, make_checksums(0..4), VOLUME_DATA_KEY_ID)
448 );
449 assert_eq!(
450 ExtentValue::with_checksum(1024, make_checksums(0..8), VOLUME_DATA_KEY_ID)
451 .shrunk(2048, 0),
452 ExtentValue::with_checksum(1024, Checksums::fletcher(Vec::new()), VOLUME_DATA_KEY_ID)
453 );
454
455 let make_bitmap = |cut, length| {
458 let mut begin_bitmap = BitVec::from_elem(cut, false);
459 let mut end_bitmap = BitVec::from_elem(length - cut, true);
460 begin_bitmap.append(&mut end_bitmap);
461 ExtentMode::OverwritePartial(begin_bitmap)
462 };
463 let make_extent =
464 |device_offset, mode| ExtentValue::Some { device_offset, mode, key_id: 0 };
465
466 assert_eq!(
467 make_extent(1024, make_bitmap(1, 8)).shrunk(2048, 2048),
468 make_extent(1024, make_bitmap(1, 8))
469 );
470 assert_eq!(
471 make_extent(1024, make_bitmap(3, 8)).shrunk(2048, 1024),
472 make_extent(1024, make_bitmap(3, 4))
473 );
474 assert_eq!(
475 make_extent(1024, make_bitmap(0, 8)).shrunk(2048, 0),
476 make_extent(1024, ExtentMode::OverwritePartial(BitVec::new()))
477 );
478
479 assert_eq!(
480 make_extent(1024, ExtentMode::Overwrite).shrunk(2048, 2048),
481 make_extent(1024, ExtentMode::Overwrite)
482 );
483 assert_eq!(
484 make_extent(1024, ExtentMode::Overwrite).shrunk(2048, 1024),
485 make_extent(1024, ExtentMode::Overwrite)
486 );
487 assert_eq!(
488 make_extent(1024, ExtentMode::Overwrite).shrunk(2048, 0),
489 make_extent(1024, ExtentMode::Overwrite)
490 );
491 }
492}