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