fixed PartialKey

- removed unnecessary/old code
- PartialKey id is no longer Optional, since that made no sense.
- lazily compare partialkey to key (probably not needed but looks neater)
This commit is contained in:
Janis 2023-04-12 17:19:08 +02:00
parent 6dd58e3b65
commit 43a92bedcf
5 changed files with 39 additions and 87 deletions

View file

@ -23,8 +23,8 @@ pub enum KnownObjectId {
QuotaTree,
UuidTree,
FreeSpaceTree,
RootINode = 0x100,
__LastFreeId = u64::MAX - 256,
// RootINode = 0x100, // first free id, always the root inode of a fs
// __LastFreeId = u64::MAX - 256, // last free id
DataRelocTree = u64::MAX - 9,
TreeReloc = u64::MAX - 8,
TreeLog = u64::MAX - 7,

View file

@ -16,8 +16,12 @@ pub struct PartialKey {
}
impl PartialKey {
pub fn new(id: Option<KnownObjectId>, ty: Option<ObjectType>, offset: Option<u64>) -> Self {
Self { id, ty, offset }
pub fn new(id: KnownObjectId, ty: Option<ObjectType>, offset: Option<u64>) -> Self {
Self {
id: Some(id),
ty,
offset,
}
}
}
@ -65,25 +69,18 @@ mod partial_key_tests {
0x8dbfc2d2, // crc of "default"
);
let pkey = PartialKey::new(
Some(KnownObjectId::ChunkTree),
Some(ObjectType::DirItem),
None,
);
let pkey = PartialKey::new(KnownObjectId::ChunkTree, Some(ObjectType::DirItem), None);
assert_eq!(pkey.partial_cmp(&key), None);
let pkey = PartialKey::new(
Some(KnownObjectId::ChunkTree),
KnownObjectId::ChunkTree,
Some(ObjectType::DirItem),
Some(0xdeadbeef),
);
assert_ne!(pkey.partial_cmp(&key), Some(core::cmp::Ordering::Equal));
let pkey = PartialKey::new(None, Some(ObjectType::DirItem), Some(0xdeadbeef));
assert_ne!(pkey.partial_cmp(&key), None);
let pkey = PartialKey::new(
Some(KnownObjectId::ChunkTree),
KnownObjectId::ChunkTree,
Some(ObjectType::DirItem),
Some(0x8dbfc2d2),
);
@ -98,25 +95,18 @@ mod partial_key_tests {
0x8dbfc2d2, // crc of "default"
);
let pkey = PartialKey::new(
Some(KnownObjectId::ChunkTree),
Some(ObjectType::DirItem),
None,
);
let pkey = PartialKey::new(KnownObjectId::ChunkTree, Some(ObjectType::DirItem), None);
assert!(pkey.eq(&key));
let pkey = PartialKey::new(
Some(KnownObjectId::ChunkTree),
KnownObjectId::ChunkTree,
Some(ObjectType::DirItem),
Some(0xdeadbeef),
);
assert!(!pkey.eq(&key));
let pkey = PartialKey::new(None, Some(ObjectType::DirItem), Some(0xdeadbeef));
assert!(!pkey.eq(&key));
let pkey = PartialKey::new(
Some(KnownObjectId::ChunkTree),
KnownObjectId::ChunkTree,
Some(ObjectType::DirItem),
Some(0x8dbfc2d2),
);

View file

@ -869,21 +869,6 @@ impl NodeHandle {
.expect("idx out of bounds")
}
pub fn advance_sideways(self) -> NodeHandleAdvanceResult {
let header = self.node.inner.header();
if header.nritems.get() >= self.idx + 1 {
NodeHandleAdvanceResult::Ascend
} else {
match &self.node.inner {
BTreeNode::Internal(_) => NodeHandleAdvanceResult::Next(Self {
idx: self.idx + 1,
..self
}),
_ => unreachable!(),
}
}
}
pub fn find_key_rev<K: PartialEq<Key> + PartialOrd<Key>>(self, key: &K) -> SearchResult {
match &self.node.inner {
BTreeNode::Internal(node) => {
@ -934,12 +919,6 @@ impl NodeHandle {
}
BTreeNode::Leaf(node) => {
for (i, child) in node.items.iter().enumerate() {
// if key < &child.key {
// return SearchResult::Leaf(NodeHandle {
// node: self.clone(),
// idx: if i == 0 { 0 } else { i as u32 - 1 },
// });
// } else
if key.eq(&child.key) {
return SearchResult::Leaf(NodeHandle {
idx: i as u32,
@ -1075,20 +1054,20 @@ impl NodeHandle {
/// key lookup that will find the first key that matches the present items in this partial key
pub struct PartialKey {
pub id: Option<KnownObjectId>,
pub id: KnownObjectId,
pub ty: Option<ObjectType>,
pub offset: Option<u64>,
}
impl PartialKey {
pub fn new(id: Option<KnownObjectId>, ty: Option<ObjectType>, offset: Option<u64>) -> Self {
pub fn new(id: KnownObjectId, ty: Option<ObjectType>, offset: Option<u64>) -> Self {
Self { id, ty, offset }
}
}
impl PartialEq<Key> for PartialKey {
fn eq(&self, other: &Key) -> bool {
self.id.map(|id| id == other.id()).unwrap_or(true)
self.id == other.id()
&& self.ty.map(|ty| ty == other.ty()).unwrap_or(true)
&& self
.offset
@ -1100,17 +1079,15 @@ impl PartialEq<Key> for PartialKey {
/// compares Self to a key, by comparing each item with the element in key if present, and skipping to the next item if missing.
impl PartialOrd<Key> for PartialKey {
fn partial_cmp(&self, other: &Key) -> Option<core::cmp::Ordering> {
let id = self.id.and_then(|id| id.partial_cmp(&other.id()));
let ty = self.ty.and_then(|ty| ty.partial_cmp(&other.ty()));
let offset = self
.offset
.and_then(|offset| offset.partial_cmp(&other.offset.get()));
match id {
Some(core::cmp::Ordering::Equal) | None => match ty {
Some(core::cmp::Ordering::Equal) | None => offset,
ord => ord,
},
match self.id.partial_cmp(&other.id()) {
Some(core::cmp::Ordering::Equal) | None => {
match self.ty.and_then(|ty| ty.partial_cmp(&other.ty())) {
Some(core::cmp::Ordering::Equal) | None => self
.offset
.and_then(|offset| offset.partial_cmp(&other.offset.get())),
ord => ord,
}
}
ord => ord,
}
}
@ -1130,25 +1107,18 @@ mod partial_key_tests {
0x8dbfc2d2, // crc of "default"
);
let pkey = PartialKey::new(
Some(KnownObjectId::ChunkTree),
Some(ObjectType::DirItem),
None,
);
let pkey = PartialKey::new(KnownObjectId::ChunkTree, Some(ObjectType::DirItem), None);
assert_eq!(pkey.partial_cmp(&key), None);
let pkey = PartialKey::new(
Some(KnownObjectId::ChunkTree),
KnownObjectId::ChunkTree,
Some(ObjectType::DirItem),
Some(0xdeadbeef),
);
assert_ne!(pkey.partial_cmp(&key), Some(core::cmp::Ordering::Equal));
let pkey = PartialKey::new(None, Some(ObjectType::DirItem), Some(0xdeadbeef));
assert_ne!(pkey.partial_cmp(&key), None);
let pkey = PartialKey::new(
Some(KnownObjectId::ChunkTree),
KnownObjectId::ChunkTree,
Some(ObjectType::DirItem),
Some(0x8dbfc2d2),
);
@ -1163,25 +1133,18 @@ mod partial_key_tests {
0x8dbfc2d2, // crc of "default"
);
let pkey = PartialKey::new(
Some(KnownObjectId::ChunkTree),
Some(ObjectType::DirItem),
None,
);
let pkey = PartialKey::new(KnownObjectId::ChunkTree, Some(ObjectType::DirItem), None);
assert!(pkey.eq(&key));
let pkey = PartialKey::new(
Some(KnownObjectId::ChunkTree),
KnownObjectId::ChunkTree,
Some(ObjectType::DirItem),
Some(0xdeadbeef),
);
assert!(!pkey.eq(&key));
let pkey = PartialKey::new(None, Some(ObjectType::DirItem), Some(0xdeadbeef));
assert!(!pkey.eq(&key));
let pkey = PartialKey::new(
Some(KnownObjectId::ChunkTree),
KnownObjectId::ChunkTree,
Some(ObjectType::DirItem),
Some(0x8dbfc2d2),
);

View file

@ -400,7 +400,7 @@ impl<R: super::Read> Fs<R> {
&self,
inode: &INode,
) -> Result<impl Iterator<Item = DirItemEntry> + '_> {
let key = PartialKey::new(Some(inode.id()), Some(ObjectType::DirIndex), None);
let key = PartialKey::new(inode.id(), Some(ObjectType::DirIndex), None);
let children = self.fs_root.find_range(&key)?;
@ -496,7 +496,7 @@ impl<R: super::Read> Fs<R> {
fn find_inode_child(&self, parent_inode: u64, child: &[u8]) -> Result<Option<DirItemEntry>> {
let crc = calculate_crc32c(0xfffffffe, child);
let key = PartialKey::new(
Some(parent_inode.into()),
parent_inode.into(),
Some(ObjectType::DirItem),
Some(crc as u64),
);
@ -527,8 +527,7 @@ impl<R: super::Read> Fs<R> {
pub fn get_inode_extents(&self, inode_id: u64) -> Result<Vec<(u64, ExtentData)>> {
if let Some(dir_entry) = self.get_inode_dir_index(inode_id)? {
if dir_entry.item().ty() == DirItemType::RegFile {
let key =
PartialKey::new(Some(inode_id.into()), Some(ObjectType::ExtentData), None);
let key = PartialKey::new(inode_id.into(), Some(ObjectType::ExtentData), None);
let extents = self.fs_root.find_range(&key)?;
@ -705,7 +704,7 @@ impl<R: super::Read> Fs<R> {
}
fn find_inode_ref(&self, inode_id: u64) -> Result<Option<(Item, INodeRefEntry)>> {
let key = PartialKey::new(Some(inode_id.into()), Some(ObjectType::INodeRef), None);
let key = PartialKey::new(inode_id.into(), Some(ObjectType::INodeRef), None);
match self.fs_root.entry(&key)? {
super::tree::entry::Entry::Occupied(entry) => {
@ -724,7 +723,7 @@ impl<R: super::Read> Fs<R> {
) -> Result<Option<DirItemEntry>> {
//let crc = calculate_crc32c(0xfffffffe, &inoderef.name());
let key = PartialKey::new(
Some(parent_inode.into()),
parent_inode.into(),
Some(ObjectType::DirIndex),
Some(inoderef.item().index.get()),
);
@ -843,7 +842,7 @@ mod tests {
let fs = v2.default_subvolume().expect("default subvol");
let search_key = PartialKey::new(
Some(fs.root_item.root_dirid.get().into()),
fs.root_item.root_dirid.get().into(),
Some(ObjectType::DirIndex),
None,
);

View file

@ -104,7 +104,7 @@ fn get_inode_items() -> Result<()> {
let v2 = open_filesystem()?;
let fs = v2.default_subvolume().expect("default subvol");
let search_key = PartialKey::new(Some(fs.root_dir_id()), Some(ObjectType::DirIndex), None);
let search_key = PartialKey::new(fs.root_dir_id(), Some(ObjectType::DirIndex), None);
// with range