This commit is contained in:
Janis 2023-03-30 22:57:46 +02:00
parent cc0b4b817f
commit 33852e99b0
4 changed files with 69 additions and 190 deletions

View file

@ -1,4 +1,4 @@
#![allow(dead_code)]
//#![allow(dead_code)]
#![feature(error_in_core)]
#![cfg_attr(not(any(feature = "std", test)), no_std)]
@ -17,7 +17,7 @@ use scroll::Pread;
use thiserror::Error;
use structs::{Chunk, Key, KeyPtr, KnownObjectId, ObjectType, RootItem, Stripe, Superblock};
use tree::{PartialKey, Tree};
use tree::Tree;
extern crate alloc;
@ -350,22 +350,6 @@ impl<R: VolumeIo> Btrfs<R> {
if let Some(subvol_root) = root_tree.find_key(&key)? {
// if we found the dir entry of the "default subvol" (mharmstone nomenclature)
// we then look for the root fs tree in the root tree with the ID found in the `.location` of the dir_item only (from mharmstone)
let search_key = PartialKey::new(
Some(
subvol_root
.1
.as_dir_item()
.expect("dir item")
.first()
.expect("dir item entry")
.dir_item
.location
.id(),
),
Some(ObjectType::RootItem),
None,
);
log::info!("subvol item: {subvol_root:#?}");
let subvol_id = subvol_root
.1

View file

@ -1,3 +1,4 @@
#![allow(dead_code)]
use core::{mem::size_of, ops::Deref};
use bytemuck::{Pod, Zeroable};

View file

@ -104,7 +104,7 @@ impl<R: super::Read> Tree<R> {
&self,
key: &K,
) -> Result<Option<(Item, TreeItem)>> {
let mut node = self.root.clone();
let mut node = NodeHandle::start(self.root.clone());
loop {
let search = node.find_key(key);
@ -112,12 +112,18 @@ impl<R: super::Read> Tree<R> {
SearchResult::Leaf(a) => {
return a.parse_item();
}
SearchResult::Edge(edge) => match &edge.node.inner {
SearchResult::Edge(mut edge) => match &edge.node.inner {
BTreeNode::Internal(internal) => {
let child_ptr = internal.children.get(edge.idx as usize).expect("adsf");
let bytes = self.volume.read_keyptr(child_ptr)?;
node = Rc::new(Node::from_bytes(bytes)?);
let child = Rc::new(Node::from_bytes(bytes)?);
edge.parents.push((edge.node, edge.idx));
node = NodeHandle {
parents: edge.parents,
node: child,
idx: 0,
};
// recurse
}
BTreeNode::Leaf(_) => {
@ -368,7 +374,7 @@ impl Node {
match &self.inner {
BTreeNode::Internal(_) => Ok(None),
BTreeNode::Leaf(leaf) => {
// TODO: better error to indicate that i was out of bounds
// TODO: better error to indicate that it was out of bounds
let item = leaf.items.get(i).ok_or(Error::ReadFailed)?;
let start = size_of::<Header>() + item.offset.get() as usize;
let size = item.size.get() as usize;
@ -380,63 +386,6 @@ impl Node {
}
}
}
// TODO: move this to nodehandle
pub fn find_key<K: PartialEq<Key> + PartialOrd<Key>>(self: &Rc<Self>, key: &K) -> SearchResult {
match &self.inner {
BTreeNode::Internal(node) => {
for (i, child) in node.children.iter().enumerate() {
match key.partial_cmp(&child.key) {
Some(core::cmp::Ordering::Less) => {
return SearchResult::Edge(NodeHandle {
parents: Default::default(),
node: self.clone(),
idx: if i == 0 { 0 } else { i as u32 - 1 },
});
}
Some(core::cmp::Ordering::Equal) | None => {
return SearchResult::Edge(NodeHandle {
parents: Default::default(),
node: self.clone(),
idx: i as u32,
});
}
_ => {}
}
}
SearchResult::Edge(NodeHandle {
parents: Default::default(),
node: self.clone(),
idx: node.children.len() as u32 - 1,
})
}
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 {
parents: Default::default(),
node: self.clone(),
idx: i as u32,
});
}
}
log::debug!("key definitely not found!");
SearchResult::Edge(NodeHandle {
parents: Default::default(),
node: self.clone(),
idx: node.items.len() as u32 - 1,
})
}
}
}
}
impl<R> Range<R>
@ -455,93 +404,6 @@ where
pub fn is_empty(&self) -> bool {
return self.start == self.end;
}
pub fn init_start(&mut self) -> Result<()> {
let start = match &self.start {
RootOrEdge::Root(root) => {
match root.node.inner {
BTreeNode::Internal(_) => {
// descend until leaf
let mut advance = root.clone().advance_down();
loop {
match advance {
NodeHandleAdvanceResult::Decend { parent, child_ptr } => {
let bytes = self.volume.read_keyptr(&child_ptr)?;
let child =
NodeHandle::start(Rc::new(Node::from_bytes(bytes)?));
self.parents.push(parent);
match &child.node.inner {
BTreeNode::Internal(_) => {
// continue loop
advance = child.advance_down();
}
BTreeNode::Leaf(_) => {
break child;
}
}
}
NodeHandleAdvanceResult::Next(handle) => {
break handle;
}
NodeHandleAdvanceResult::Ascend => unreachable!(),
}
}
}
BTreeNode::Leaf(_) => root.clone(),
}
}
RootOrEdge::Edge(edge) => edge.clone(),
};
self.start = RootOrEdge::Edge(start);
Ok(())
}
pub fn advance(&mut self) -> Result<Option<()>> {
if !self.is_empty() {
let start = self.start.into_handle();
let mut advance = start.advance_down();
loop {
match advance {
NodeHandleAdvanceResult::Decend { parent, child_ptr } => {
let bytes = self.volume.read_keyptr(&child_ptr)?;
let child = NodeHandle::start(Rc::new(Node::from_bytes(bytes)?));
self.parents.push(parent);
self.start = RootOrEdge::Edge(child);
match &self.start.node.inner {
BTreeNode::Internal(_) => {
return self.advance();
}
BTreeNode::Leaf(_) => {
break;
}
}
}
NodeHandleAdvanceResult::Next(next) => {
self.start = RootOrEdge::Edge(next);
break;
}
NodeHandleAdvanceResult::Ascend => {
if let Some(last) = self.parents.pop() {
advance = NodeHandle {
idx: last.idx + 1,
..last
}
.advance_down();
} else {
return Ok(None);
}
}
}
}
Ok(Some(()))
} else {
Ok(None)
}
}
}
impl<R> Iterator for Range<R>
@ -619,6 +481,57 @@ impl NodeHandle {
}
}
pub fn find_key<K: PartialEq<Key> + PartialOrd<Key>>(self, key: &K) -> SearchResult {
match &self.node.inner {
BTreeNode::Internal(node) => {
for (i, child) in node.children.iter().enumerate() {
match key.partial_cmp(&child.key) {
Some(core::cmp::Ordering::Less) => {
return SearchResult::Edge(Self {
idx: if i == 0 { 0 } else { i as u32 - 1 },
..self
});
}
Some(core::cmp::Ordering::Equal) | None => {
return SearchResult::Edge(NodeHandle {
idx: i as u32,
..self
});
}
_ => {}
}
}
SearchResult::Edge(NodeHandle {
idx: node.children.len() as u32 - 1,
..self
})
}
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,
..self
});
}
}
log::debug!("key definitely not found!");
SearchResult::Edge(NodeHandle {
idx: node.items.len() as u32 - 1,
..self
})
}
}
}
// needs reference to volume to be able to read children key_ptrs
// this is a live reference so if in the future I want to have a &mut to something in Volume
// greppable: volume ref
@ -721,7 +634,10 @@ impl NodeHandle {
node: child,
})
}
Err(_) => Err(Self { parents, node, idx }),
Err(_) => {
log::error!("failed to read child node!");
Err(Self { parents, node, idx })
}
};
// TODO: better error or panic here? this would return self, indicating the end of the tree, even though we simply failed to retrieve the next node
@ -736,25 +652,6 @@ impl NodeHandle {
}
}
// returns the next node in ascending sequential order
pub fn advance_down(self) -> NodeHandleAdvanceResult {
let header = self.node.inner.header();
if self.idx + 1 >= header.nritems.get() {
NodeHandleAdvanceResult::Ascend
} else {
match &self.node.inner {
BTreeNode::Internal(node) => NodeHandleAdvanceResult::Decend {
parent: self.clone(),
child_ptr: *node.children.first().expect("no children in node"),
},
BTreeNode::Leaf(_) => NodeHandleAdvanceResult::Next(Self {
idx: self.idx + 1,
..self
}),
}
}
}
pub fn end(node: BoxedNode) -> Self {
let parents = Vec::with_capacity(node.inner.header().level as usize);
Self {

View file

@ -4,10 +4,7 @@ use alloc::collections::btree_map::Entry;
use alloc::{collections::BTreeMap, rc::Rc, vec, vec::Vec};
use scroll::Pread;
use crate::structs::{
Chunk, Key, KeyPtr, KnownObjectId, ObjectType, RootItem, Stripe, Superblock, TreeItem,
};
use crate::v2::tree::PartialKey;
use crate::structs::{Chunk, Key, KeyPtr, KnownObjectId, ObjectType, Stripe, Superblock, TreeItem};
use crate::{Error, Result};
use super::tree::Tree;