1mod legacy;
6
7pub use legacy::*;
8
9use crate::checksum::Checksums;
11use crate::log::error;
12use crate::lsm_tree::types::{
13 FuzzyHash, Item, ItemRef, LayerKey, MergeType, OrdLowerBound, OrdUpperBound, RangeKey,
14 SortByU64, Value,
15};
16use crate::object_store::extent_record::{
17 ExtentKey, ExtentKeyPartitionIterator, ExtentKeyV32, ExtentValue, ExtentValueV38,
18};
19use crate::serialized_types::{Migrate, Versioned, migrate_nodefault, migrate_to_version};
20use fprint::TypeFingerprint;
21use fxfs_crypto::{WrappedKey, WrappingKeyId};
22use fxfs_unicode::CasefoldString;
23use serde::{Deserialize, Serialize};
24use std::collections::BTreeMap;
25use std::default::Default;
26use std::hash::Hash;
27use std::time::{Duration, SystemTime, UNIX_EPOCH};
28
29pub type ObjectDescriptor = ObjectDescriptorV32;
31
32#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, TypeFingerprint)]
33#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
34pub enum ObjectDescriptorV32 {
35 File,
37 Directory,
39 Volume,
41 Symlink,
43}
44
45pub type ProjectProperty = ProjectPropertyV32;
47
48#[derive(
49 Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize, TypeFingerprint,
50)]
51#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
52pub enum ProjectPropertyV32 {
53 Limit,
55 Usage,
57}
58
59pub type ObjectKeyData = ObjectKeyDataV43;
60
61#[derive(
62 Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize, TypeFingerprint,
63)]
64#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
65pub enum ObjectKeyDataV43 {
66 Object,
69 Keys,
71 Attribute(u64, AttributeKeyV32),
73 Child { name: String },
75 GraveyardEntry { object_id: u64 },
77 Project { project_id: u64, property: ProjectPropertyV32 },
81 ExtendedAttribute { name: Vec<u8> },
84 GraveyardAttributeEntry { object_id: u64, attribute_id: u64 },
86 EncryptedCasefoldChild(EncryptedCasefoldChild),
91 CasefoldChild { name: CasefoldString },
94 EncryptedChild(EncryptedChild),
96}
97
98#[derive(
99 Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize, TypeFingerprint,
100)]
101#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
102pub struct EncryptedCasefoldChild {
103 pub hash_code: u32,
104 pub name: Vec<u8>,
105}
106
107#[derive(
108 Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize, TypeFingerprint,
109)]
110#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
111pub struct EncryptedChild(pub Vec<u8>);
112
113pub type AttributeKey = AttributeKeyV32;
114
115#[derive(
116 Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize, TypeFingerprint,
117)]
118#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
119pub enum AttributeKeyV32 {
120 Attribute,
122 Extent(ExtentKeyV32),
123}
124
125pub type ObjectKey = ObjectKeyV43;
127
128#[derive(
129 Clone,
130 Debug,
131 Eq,
132 Ord,
133 Hash,
134 PartialEq,
135 PartialOrd,
136 Serialize,
137 Deserialize,
138 TypeFingerprint,
139 Versioned,
140)]
141#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
142pub struct ObjectKeyV43 {
143 pub object_id: u64,
145 pub data: ObjectKeyDataV43,
147}
148
149impl SortByU64 for ObjectKey {
150 fn get_leading_u64(&self) -> u64 {
151 self.object_id
152 }
153}
154
155impl ObjectKey {
156 pub fn object(object_id: u64) -> Self {
158 Self { object_id: object_id, data: ObjectKeyData::Object }
159 }
160
161 pub fn keys(object_id: u64) -> Self {
163 Self { object_id, data: ObjectKeyData::Keys }
164 }
165
166 pub fn attribute(object_id: u64, attribute_id: u64, key: AttributeKey) -> Self {
168 Self { object_id, data: ObjectKeyData::Attribute(attribute_id, key) }
169 }
170
171 pub fn extent(object_id: u64, attribute_id: u64, range: std::ops::Range<u64>) -> Self {
173 Self {
174 object_id,
175 data: ObjectKeyData::Attribute(
176 attribute_id,
177 AttributeKey::Extent(ExtentKey::new(range)),
178 ),
179 }
180 }
181
182 pub fn from_extent(object_id: u64, attribute_id: u64, extent: ExtentKey) -> Self {
184 Self {
185 object_id,
186 data: ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(extent)),
187 }
188 }
189
190 pub fn child(object_id: u64, name: &str, casefold: bool) -> Self {
192 if casefold {
193 Self { object_id, data: ObjectKeyData::CasefoldChild { name: name.into() } }
194 } else {
195 Self { object_id, data: ObjectKeyData::Child { name: name.into() } }
196 }
197 }
198
199 pub fn encrypted_child(object_id: u64, name: Vec<u8>, hash_code: Option<u32>) -> Self {
209 if let Some(hash_code) = hash_code {
210 Self {
211 object_id,
212 data: ObjectKeyData::EncryptedCasefoldChild(EncryptedCasefoldChild {
213 hash_code,
214 name,
215 }),
216 }
217 } else {
218 Self { object_id, data: ObjectKeyData::EncryptedChild(EncryptedChild(name)) }
219 }
220 }
221
222 pub fn graveyard_entry(graveyard_object_id: u64, object_id: u64) -> Self {
224 Self { object_id: graveyard_object_id, data: ObjectKeyData::GraveyardEntry { object_id } }
225 }
226
227 pub fn graveyard_attribute_entry(
229 graveyard_object_id: u64,
230 object_id: u64,
231 attribute_id: u64,
232 ) -> Self {
233 Self {
234 object_id: graveyard_object_id,
235 data: ObjectKeyData::GraveyardAttributeEntry { object_id, attribute_id },
236 }
237 }
238
239 pub fn project_limit(object_id: u64, project_id: u64) -> Self {
241 Self {
242 object_id,
243 data: ObjectKeyData::Project { project_id, property: ProjectProperty::Limit },
244 }
245 }
246
247 pub fn project_usage(object_id: u64, project_id: u64) -> Self {
249 Self {
250 object_id,
251 data: ObjectKeyData::Project { project_id, property: ProjectProperty::Usage },
252 }
253 }
254
255 pub fn extended_attribute(object_id: u64, name: Vec<u8>) -> Self {
256 Self { object_id, data: ObjectKeyData::ExtendedAttribute { name } }
257 }
258
259 pub fn key_for_merge_into(&self) -> Self {
262 if let Self {
263 object_id,
264 data: ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(e)),
265 } = self
266 {
267 Self::attribute(*object_id, *attribute_id, AttributeKey::Extent(e.key_for_merge_into()))
268 } else {
269 self.clone()
270 }
271 }
272}
273
274impl OrdUpperBound for ObjectKey {
275 fn cmp_upper_bound(&self, other: &ObjectKey) -> std::cmp::Ordering {
276 self.object_id.cmp(&other.object_id).then_with(|| match (&self.data, &other.data) {
277 (
278 ObjectKeyData::Attribute(left_attr_id, AttributeKey::Extent(left_extent)),
279 ObjectKeyData::Attribute(right_attr_id, AttributeKey::Extent(right_extent)),
280 ) => left_attr_id.cmp(right_attr_id).then(left_extent.cmp_upper_bound(right_extent)),
281 _ => self.data.cmp(&other.data),
282 })
283 }
284}
285
286impl OrdLowerBound for ObjectKey {
287 fn cmp_lower_bound(&self, other: &ObjectKey) -> std::cmp::Ordering {
288 self.object_id.cmp(&other.object_id).then_with(|| match (&self.data, &other.data) {
289 (
290 ObjectKeyData::Attribute(left_attr_id, AttributeKey::Extent(left_extent)),
291 ObjectKeyData::Attribute(right_attr_id, AttributeKey::Extent(right_extent)),
292 ) => left_attr_id.cmp(right_attr_id).then(left_extent.cmp_lower_bound(right_extent)),
293 _ => self.data.cmp(&other.data),
294 })
295 }
296}
297
298impl LayerKey for ObjectKey {
299 fn merge_type(&self) -> MergeType {
300 match self.data {
303 ObjectKeyData::Object
304 | ObjectKeyData::Keys
305 | ObjectKeyData::Attribute(..)
306 | ObjectKeyData::Child { .. }
307 | ObjectKeyData::EncryptedChild(_)
308 | ObjectKeyData::EncryptedCasefoldChild(_)
309 | ObjectKeyData::CasefoldChild { .. }
310 | ObjectKeyData::GraveyardEntry { .. }
311 | ObjectKeyData::GraveyardAttributeEntry { .. }
312 | ObjectKeyData::Project { property: ProjectProperty::Limit, .. }
313 | ObjectKeyData::ExtendedAttribute { .. } => MergeType::OptimizedMerge,
314 ObjectKeyData::Project { property: ProjectProperty::Usage, .. } => MergeType::FullMerge,
315 }
316 }
317
318 fn next_key(&self) -> Option<Self> {
319 match self.data {
320 ObjectKeyData::Attribute(_, AttributeKey::Extent(_)) => {
321 let mut key = self.clone();
322 if let ObjectKey {
323 data: ObjectKeyData::Attribute(_, AttributeKey::Extent(ExtentKey { range })),
324 ..
325 } = &mut key
326 {
327 *range = range.end..range.end + 1;
331 }
332 Some(key)
333 }
334 _ => None,
335 }
336 }
337
338 fn search_key(&self) -> Self {
339 if let Self {
340 object_id,
341 data: ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(e)),
342 } = self
343 {
344 Self::attribute(*object_id, *attribute_id, AttributeKey::Extent(e.search_key()))
345 } else {
346 self.clone()
347 }
348 }
349}
350
351impl RangeKey for ObjectKey {
352 fn overlaps(&self, other: &Self) -> bool {
353 if self.object_id != other.object_id {
354 return false;
355 }
356 match (&self.data, &other.data) {
357 (
358 ObjectKeyData::Attribute(left_attr_id, AttributeKey::Extent(left_key)),
359 ObjectKeyData::Attribute(right_attr_id, AttributeKey::Extent(right_key)),
360 ) if *left_attr_id == *right_attr_id => {
361 left_key.range.end > right_key.range.start
362 && left_key.range.start < right_key.range.end
363 }
364 (a, b) => a == b,
365 }
366 }
367}
368
369pub enum ObjectKeyFuzzyHashIterator {
370 ExtentKey(u64, u64, ExtentKeyPartitionIterator),
371 NotExtentKey(Option<u64>),
372}
373
374impl Iterator for ObjectKeyFuzzyHashIterator {
375 type Item = u64;
376
377 fn next(&mut self) -> Option<Self::Item> {
378 match self {
379 Self::ExtentKey(oid, attr_id, extent_keys) => extent_keys.next().map(|range| {
380 let key = ObjectKey::extent(*oid, *attr_id, range);
381 crate::stable_hash::stable_hash(key)
382 }),
383 Self::NotExtentKey(hash) => hash.take(),
384 }
385 }
386}
387
388impl FuzzyHash for ObjectKey {
389 fn fuzzy_hash(&self) -> impl Iterator<Item = u64> {
390 match &self.data {
391 ObjectKeyData::Attribute(attr_id, AttributeKey::Extent(extent)) => {
392 ObjectKeyFuzzyHashIterator::ExtentKey(
393 self.object_id,
394 *attr_id,
395 extent.fuzzy_hash_partition(),
396 )
397 }
398 _ => {
399 let hash = crate::stable_hash::stable_hash(self);
400 ObjectKeyFuzzyHashIterator::NotExtentKey(Some(hash))
401 }
402 }
403 }
404
405 fn is_range_key(&self) -> bool {
406 match &self.data {
407 ObjectKeyData::Attribute(_, AttributeKey::Extent(_)) => true,
408 _ => false,
409 }
410 }
411}
412
413pub type Timestamp = TimestampV49;
415
416#[derive(
417 Copy,
418 Clone,
419 Debug,
420 Default,
421 Eq,
422 PartialEq,
423 Ord,
424 PartialOrd,
425 Serialize,
426 Deserialize,
427 TypeFingerprint,
428)]
429#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
430pub struct TimestampV49 {
431 nanos: u64,
432}
433
434impl Timestamp {
435 const NSEC_PER_SEC: u64 = 1_000_000_000;
436
437 pub fn now() -> Self {
438 SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or(Duration::ZERO).into()
439 }
440
441 pub const fn zero() -> Self {
442 Self { nanos: 0 }
443 }
444
445 pub const fn from_nanos(nanos: u64) -> Self {
446 Self { nanos }
447 }
448
449 pub fn from_secs_and_nanos(secs: u64, nanos: u32) -> Self {
450 let Some(secs_in_nanos) = secs.checked_mul(Self::NSEC_PER_SEC) else {
451 error!("Fxfs doesn't support dates past 2554-07-21");
452 return Self { nanos: u64::MAX };
453 };
454 let Some(nanos) = secs_in_nanos.checked_add(nanos as u64) else {
455 error!("Fxfs doesn't support dates past 2554-07-21");
456 return Self { nanos: u64::MAX };
457 };
458 Self { nanos }
459 }
460
461 pub fn as_nanos(&self) -> u64 {
464 self.nanos
465 }
466
467 pub fn subsec_nanos(&self) -> u32 {
469 (self.nanos % Self::NSEC_PER_SEC) as u32
470 }
471
472 pub fn as_secs(&self) -> u64 {
475 self.nanos / Self::NSEC_PER_SEC
476 }
477}
478
479impl From<std::time::Duration> for Timestamp {
480 fn from(duration: std::time::Duration) -> Self {
481 Self::from_secs_and_nanos(duration.as_secs(), duration.subsec_nanos())
482 }
483}
484
485impl From<Timestamp> for std::time::Duration {
486 fn from(timestamp: Timestamp) -> std::time::Duration {
487 Duration::from_nanos(timestamp.nanos)
488 }
489}
490
491pub type ObjectKind = ObjectKindV49;
492
493#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, TypeFingerprint)]
494#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
495pub enum ObjectKindV49 {
496 File {
497 refs: u64,
499 },
500 Directory {
501 sub_dirs: u64,
503 wrapping_key_id: Option<WrappingKeyId>,
506 casefold: bool,
509 },
510 Graveyard,
511 Symlink {
512 refs: u64,
514 link: Box<[u8]>,
517 },
518 EncryptedSymlink {
519 refs: u64,
521 link: Box<[u8]>,
526 },
527}
528
529pub type PosixAttributes = PosixAttributesV32;
532
533#[derive(Clone, Debug, Copy, Default, Serialize, Deserialize, PartialEq, TypeFingerprint)]
534#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
535pub struct PosixAttributesV32 {
536 pub mode: u32,
538 pub uid: u32,
540 pub gid: u32,
542 pub rdev: u64,
544}
545
546pub type ObjectAttributes = ObjectAttributesV49;
550
551#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, TypeFingerprint)]
552#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
553pub struct ObjectAttributesV49 {
554 pub creation_time: TimestampV49,
556 pub modification_time: TimestampV49,
558 pub project_id: u64,
560 pub posix_attributes: Option<PosixAttributesV32>,
562 pub allocated_size: u64,
564 pub access_time: TimestampV49,
566 pub change_time: TimestampV49,
568}
569
570pub type ExtendedAttributeValue = ExtendedAttributeValueV32;
571
572#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, TypeFingerprint)]
573#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
574pub enum ExtendedAttributeValueV32 {
575 Inline(Vec<u8>),
578 AttributeId(u64),
581}
582
583pub type ChildValue = ChildValueV32;
585
586#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, TypeFingerprint)]
587#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
588pub struct ChildValueV32 {
589 pub object_id: u64,
591 pub object_descriptor: ObjectDescriptorV32,
593}
594
595pub type RootDigest = RootDigestV33;
596
597#[derive(
598 Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize, TypeFingerprint,
599)]
600#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
601pub enum RootDigestV33 {
602 Sha256([u8; 32]),
603 Sha512(Vec<u8>),
604}
605
606pub type FsverityMetadata = FsverityMetadataV50;
607
608#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TypeFingerprint, Versioned)]
609#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
610pub enum FsverityMetadataV50 {
611 Internal(RootDigestV33, Vec<u8>),
613 F2fs(std::ops::Range<u64>),
615}
616
617pub type EncryptionKey = EncryptionKeyV49;
618pub type EncryptionKeyV49 = fxfs_crypto::EncryptionKey;
619
620pub type EncryptionKeys = EncryptionKeysV49;
621
622#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TypeFingerprint)]
623#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
624pub struct EncryptionKeysV49(Vec<(u64, EncryptionKeyV49)>);
625
626impl EncryptionKeys {
627 pub fn get(&self, id: u64) -> Option<&EncryptionKey> {
628 self.0.iter().find_map(|(i, key)| (*i == id).then_some(key))
629 }
630
631 pub fn insert(&mut self, id: u64, key: EncryptionKey) {
632 self.0.push((id, key))
633 }
634
635 pub fn remove(&mut self, id: u64) -> Option<EncryptionKey> {
636 if let Some(ix) = self.0.iter().position(|(k, _)| *k == id) {
637 Some(self.0.remove(ix).1)
638 } else {
639 None
640 }
641 }
642}
643
644impl From<EncryptionKeys> for BTreeMap<u64, WrappedKey> {
645 fn from(keys: EncryptionKeys) -> Self {
646 keys.0.into_iter().map(|(id, key)| (id, key.into())).collect()
647 }
648}
649
650impl From<Vec<(u64, EncryptionKey)>> for EncryptionKeys {
651 fn from(value: Vec<(u64, EncryptionKey)>) -> Self {
652 Self(value)
653 }
654}
655
656impl std::ops::Deref for EncryptionKeys {
657 type Target = Vec<(u64, EncryptionKey)>;
658 fn deref(&self) -> &Self::Target {
659 &self.0
660 }
661}
662
663pub type ObjectValue = ObjectValueV50;
667impl Value for ObjectValue {
668 const DELETED_MARKER: Self = Self::None;
669}
670
671#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, TypeFingerprint, Versioned)]
672#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
673pub enum ObjectValueV50 {
674 None,
678 Some,
681 Object { kind: ObjectKindV49, attributes: ObjectAttributesV49 },
683 Keys(EncryptionKeysV49),
685 Attribute { size: u64, has_overwrite_extents: bool },
687 Extent(ExtentValueV38),
689 Child(ChildValueV32),
691 Trim,
695 BytesAndNodes { bytes: i64, nodes: i64 },
697 ExtendedAttribute(ExtendedAttributeValueV32),
700 VerifiedAttribute { size: u64, fsverity_metadata: FsverityMetadataV50 },
703}
704
705impl ObjectValue {
706 pub fn file(
708 refs: u64,
709 allocated_size: u64,
710 creation_time: Timestamp,
711 modification_time: Timestamp,
712 access_time: Timestamp,
713 change_time: Timestamp,
714 project_id: u64,
715 posix_attributes: Option<PosixAttributes>,
716 ) -> ObjectValue {
717 ObjectValue::Object {
718 kind: ObjectKind::File { refs },
719 attributes: ObjectAttributes {
720 creation_time,
721 modification_time,
722 project_id,
723 posix_attributes,
724 allocated_size,
725 access_time,
726 change_time,
727 },
728 }
729 }
730 pub fn keys(encryption_keys: EncryptionKeys) -> ObjectValue {
731 ObjectValue::Keys(encryption_keys)
732 }
733 pub fn attribute(size: u64, has_overwrite_extents: bool) -> ObjectValue {
735 ObjectValue::Attribute { size, has_overwrite_extents }
736 }
737 pub fn verified_attribute(size: u64, fsverity_metadata: FsverityMetadata) -> ObjectValue {
739 ObjectValue::VerifiedAttribute { size, fsverity_metadata }
740 }
741 pub fn extent(device_offset: u64, key_id: u64) -> ObjectValue {
743 ObjectValue::Extent(ExtentValue::new_raw(device_offset, key_id))
744 }
745 pub fn extent_with_checksum(
747 device_offset: u64,
748 checksum: Checksums,
749 key_id: u64,
750 ) -> ObjectValue {
751 ObjectValue::Extent(ExtentValue::with_checksum(device_offset, checksum, key_id))
752 }
753 pub fn deleted_extent() -> ObjectValue {
755 ObjectValue::Extent(ExtentValue::deleted_extent())
756 }
757 pub fn child(object_id: u64, object_descriptor: ObjectDescriptor) -> ObjectValue {
759 ObjectValue::Child(ChildValue { object_id, object_descriptor })
760 }
761 pub fn symlink(
763 link: impl Into<Box<[u8]>>,
764 creation_time: Timestamp,
765 modification_time: Timestamp,
766 project_id: u64,
767 ) -> ObjectValue {
768 ObjectValue::Object {
769 kind: ObjectKind::Symlink { refs: 1, link: link.into() },
770 attributes: ObjectAttributes {
771 creation_time,
772 modification_time,
773 project_id,
774 ..Default::default()
775 },
776 }
777 }
778 pub fn encrypted_symlink(
780 link: impl Into<Box<[u8]>>,
781 creation_time: Timestamp,
782 modification_time: Timestamp,
783 project_id: u64,
784 ) -> ObjectValue {
785 ObjectValue::Object {
786 kind: ObjectKind::EncryptedSymlink { refs: 1, link: link.into() },
787 attributes: ObjectAttributes {
788 creation_time,
789 modification_time,
790 project_id,
791 ..Default::default()
792 },
793 }
794 }
795 pub fn inline_extended_attribute(value: impl Into<Vec<u8>>) -> ObjectValue {
796 ObjectValue::ExtendedAttribute(ExtendedAttributeValue::Inline(value.into()))
797 }
798 pub fn extended_attribute(attribute_id: u64) -> ObjectValue {
799 ObjectValue::ExtendedAttribute(ExtendedAttributeValue::AttributeId(attribute_id))
800 }
801}
802
803pub type ObjectItem = ObjectItemV50;
804pub type ObjectItemV50 = Item<ObjectKeyV43, ObjectValueV50>;
805
806impl ObjectItem {
807 pub fn is_tombstone(&self) -> bool {
808 matches!(
809 self,
810 Item {
811 key: ObjectKey { data: ObjectKeyData::Object, .. },
812 value: ObjectValue::None,
813 ..
814 }
815 )
816 }
817}
818
819impl<'a> From<ItemRef<'a, ObjectKey, ObjectValue>>
821 for Option<(u64, u64, &'a ExtentKey, &'a ExtentValue)>
822{
823 fn from(item: ItemRef<'a, ObjectKey, ObjectValue>) -> Self {
824 match item {
825 ItemRef {
826 key:
827 ObjectKey {
828 object_id,
829 data:
830 ObjectKeyData::Attribute(
831 attribute_id, AttributeKey::Extent(extent_key),
833 ),
834 },
835 value: ObjectValue::Extent(extent_value),
836 ..
837 } => Some((*object_id, *attribute_id, extent_key, extent_value)),
838 _ => None,
839 }
840 }
841}
842
843pub type FxfsKey = FxfsKeyV49;
844pub type FxfsKeyV49 = fxfs_crypto::FxfsKey;
845
846#[cfg(test)]
847mod tests {
848 use super::{ObjectKey, ObjectKeyV43, TimestampV49};
849 use crate::lsm_tree::types::{
850 FuzzyHash as _, LayerKey, OrdLowerBound, OrdUpperBound, RangeKey,
851 };
852 use std::cmp::Ordering;
853 use std::ops::Add;
854 use std::time::{Duration, SystemTime, UNIX_EPOCH};
855
856 #[test]
861 fn test_hash_stability() {
862 assert_eq!(
866 &ObjectKeyV43::object(100).fuzzy_hash().collect::<Vec<_>>()[..],
867 &[11885326717398844384]
868 );
869 assert_eq!(
870 &ObjectKeyV43::extent(1, 0, 0..2 * 1024 * 1024).fuzzy_hash().collect::<Vec<_>>()[..],
871 &[11090579907097549012, 2814892992701560424]
872 );
873 }
874
875 #[test]
876 fn test_next_key() {
877 let next_key = ObjectKey::extent(1, 0, 0..100).next_key().unwrap();
878 assert_eq!(ObjectKey::extent(1, 0, 101..200).cmp_lower_bound(&next_key), Ordering::Greater);
879 assert_eq!(ObjectKey::extent(1, 0, 100..200).cmp_lower_bound(&next_key), Ordering::Equal);
880 assert_eq!(ObjectKey::extent(1, 0, 100..101).cmp_lower_bound(&next_key), Ordering::Equal);
881 assert_eq!(ObjectKey::extent(1, 0, 99..100).cmp_lower_bound(&next_key), Ordering::Less);
882 assert_eq!(ObjectKey::extent(1, 0, 0..100).cmp_upper_bound(&next_key), Ordering::Less);
883 assert_eq!(ObjectKey::extent(1, 0, 99..100).cmp_upper_bound(&next_key), Ordering::Less);
884 assert_eq!(ObjectKey::extent(1, 0, 100..101).cmp_upper_bound(&next_key), Ordering::Equal);
885 assert_eq!(ObjectKey::extent(1, 0, 100..200).cmp_upper_bound(&next_key), Ordering::Greater);
886 assert_eq!(ObjectKey::extent(1, 0, 50..101).cmp_upper_bound(&next_key), Ordering::Equal);
887 assert_eq!(ObjectKey::extent(1, 0, 50..200).cmp_upper_bound(&next_key), Ordering::Greater);
888 }
889 #[test]
890 fn test_range_key() {
891 assert!(ObjectKeyV43::extent(1, 0, 0..2 * 1024 * 1024).is_range_key());
894 assert!(!ObjectKeyV43::object(100).is_range_key());
895
896 assert_eq!(ObjectKey::object(1).overlaps(&ObjectKey::object(1)), true);
897 assert_eq!(ObjectKey::object(1).overlaps(&ObjectKey::object(2)), false);
898 assert_eq!(ObjectKey::extent(1, 0, 0..100).overlaps(&ObjectKey::object(1)), false);
899 assert_eq!(ObjectKey::object(1).overlaps(&ObjectKey::extent(1, 0, 0..100)), false);
900 assert_eq!(
901 ObjectKey::extent(1, 0, 0..100).overlaps(&ObjectKey::extent(2, 0, 0..100)),
902 false
903 );
904 assert_eq!(
905 ObjectKey::extent(1, 0, 0..100).overlaps(&ObjectKey::extent(1, 1, 0..100)),
906 false
907 );
908 assert_eq!(
909 ObjectKey::extent(1, 0, 0..100).overlaps(&ObjectKey::extent(1, 0, 0..100)),
910 true
911 );
912
913 assert_eq!(
914 ObjectKey::extent(1, 0, 0..50).overlaps(&ObjectKey::extent(1, 0, 49..100)),
915 true
916 );
917 assert_eq!(
918 ObjectKey::extent(1, 0, 49..100).overlaps(&ObjectKey::extent(1, 0, 0..50)),
919 true
920 );
921
922 assert_eq!(
923 ObjectKey::extent(1, 0, 0..50).overlaps(&ObjectKey::extent(1, 0, 50..100)),
924 false
925 );
926 assert_eq!(
927 ObjectKey::extent(1, 0, 50..100).overlaps(&ObjectKey::extent(1, 0, 0..50)),
928 false
929 );
930 }
931
932 #[test]
933 fn test_timestamp() {
934 fn compare_time(std_time: Duration) {
935 let ts_time: TimestampV49 = std_time.into();
936 assert_eq!(<TimestampV49 as Into<Duration>>::into(ts_time), std_time);
937 assert_eq!(ts_time.subsec_nanos(), std_time.subsec_nanos());
938 assert_eq!(ts_time.as_secs(), std_time.as_secs());
939 assert_eq!(ts_time.as_nanos() as u128, std_time.as_nanos());
940 }
941 compare_time(Duration::from_nanos(0));
942 compare_time(Duration::from_nanos(u64::MAX));
943 compare_time(SystemTime::now().duration_since(UNIX_EPOCH).unwrap());
944
945 let ts: TimestampV49 = Duration::from_secs(u64::MAX - 1).into();
946 assert_eq!(ts.nanos, u64::MAX);
947
948 let ts: TimestampV49 = (Duration::from_nanos(u64::MAX).add(Duration::from_nanos(1))).into();
949 assert_eq!(ts.nanos, u64::MAX);
950 }
951}