ok?
This commit is contained in:
parent
1fdb92ba57
commit
7a12168026
3 changed files with 98 additions and 2 deletions
97
src/btree.rs
97
src/btree.rs
|
|
@ -94,6 +94,10 @@ where
|
||||||
leaf.values.push(value);
|
leaf.values.push(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.try_compensation(current_loc, leaf.clone(), &mut path) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
self.storage
|
self.storage
|
||||||
.write_node(current_loc, &Node::Leaf(leaf.clone()));
|
.write_node(current_loc, &Node::Leaf(leaf.clone()));
|
||||||
|
|
||||||
|
|
@ -103,6 +107,94 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn compensate(
|
||||||
|
mut left: LeafNode,
|
||||||
|
mut right: LeafNode,
|
||||||
|
mut parent: InternalNode,
|
||||||
|
left_loc: usize,
|
||||||
|
right_loc: usize,
|
||||||
|
) -> Option<(LeafNode, LeafNode, InternalNode)> {
|
||||||
|
if left.values.len() + right.values.len() > MAX_KEYS * 2 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut combined: Vec<(i32, Record)> = left
|
||||||
|
.keys
|
||||||
|
.into_iter()
|
||||||
|
.zip(left.values.into_iter())
|
||||||
|
.chain(right.keys.into_iter().zip(right.values.into_iter()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
combined.sort_by_key(|(k, _)| *k);
|
||||||
|
|
||||||
|
let mid = combined.len() / 2;
|
||||||
|
let left_part = &combined[..mid];
|
||||||
|
let right_part = &combined[mid..];
|
||||||
|
|
||||||
|
left.keys = left_part.iter().map(|(k, _)| *k).collect();
|
||||||
|
left.values = left_part.iter().map(|(_, v)| *v).collect();
|
||||||
|
|
||||||
|
right.keys = right_part.iter().map(|(k, _)| *k).collect();
|
||||||
|
right.values = right_part.iter().map(|(_, v)| *v).collect();
|
||||||
|
|
||||||
|
let left_idx = parent.children.iter().position(|&c| c == left_loc)?;
|
||||||
|
let right_idx = parent.children.iter().position(|&c| c == right_loc)?;
|
||||||
|
|
||||||
|
if right_idx != left_idx + 1 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent.keys[left_idx] = right.keys[0];
|
||||||
|
|
||||||
|
Some((left, right, parent))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_compensation(
|
||||||
|
&mut self,
|
||||||
|
loc: usize,
|
||||||
|
leaf: LeafNode,
|
||||||
|
path: &mut Vec<(usize, InternalNode)>,
|
||||||
|
) -> bool {
|
||||||
|
if path.is_empty() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (parent_loc, parent) = path.last().unwrap().clone();
|
||||||
|
|
||||||
|
if let Some(idx_in_parent) = parent.children.iter().position(|&c| c == loc) {
|
||||||
|
if idx_in_parent > 0 {
|
||||||
|
let left_loc = parent.children[idx_in_parent - 1];
|
||||||
|
if let Some(Node::Leaf(left_sibling)) = self.storage.read_node(left_loc) {
|
||||||
|
if let Some((new_left, new_right, new_parent)) =
|
||||||
|
Self::compensate(left_sibling, leaf.clone(), parent.clone(), left_loc, loc)
|
||||||
|
{
|
||||||
|
self.storage.write_node(left_loc, &Node::Leaf(new_left));
|
||||||
|
self.storage.write_node(loc, &Node::Leaf(new_right));
|
||||||
|
self.storage
|
||||||
|
.write_node(parent_loc, &Node::Internal(new_parent));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(right_loc) = leaf.next {
|
||||||
|
if let Some(Node::Leaf(right_sibling)) = self.storage.read_node(right_loc) {
|
||||||
|
if let Some((new_left, new_right, new_parent)) =
|
||||||
|
Self::compensate(leaf.clone(), right_sibling, parent.clone(), loc, right_loc)
|
||||||
|
{
|
||||||
|
self.storage.write_node(loc, &Node::Leaf(new_left));
|
||||||
|
self.storage.write_node(right_loc, &Node::Leaf(new_right));
|
||||||
|
self.storage
|
||||||
|
.write_node(parent_loc, &Node::Internal(new_parent));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
fn split_leaf(&mut self, loc: usize, leaf: LeafNode, path: &mut Vec<(usize, InternalNode)>) {
|
fn split_leaf(&mut self, loc: usize, leaf: LeafNode, path: &mut Vec<(usize, InternalNode)>) {
|
||||||
let mid = leaf.keys.len() / 2;
|
let mid = leaf.keys.len() / 2;
|
||||||
let new_leaf = LeafNode {
|
let new_leaf = LeafNode {
|
||||||
|
|
@ -343,7 +435,12 @@ mod tests {
|
||||||
model.insert(rec[0], rec);
|
model.insert(rec[0], rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (key, value) in model {
|
for (key, value) in model {
|
||||||
|
if tree.find(key) != Some(value) {
|
||||||
|
tree.dump_tree();
|
||||||
|
tree.storage.dump_pages();
|
||||||
|
}
|
||||||
prop_assert_eq!(tree.find(key), Some(value));
|
prop_assert_eq!(tree.find(key), Some(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
pub const DEGREE: usize = 2;
|
pub const DEGREE: usize = 2;
|
||||||
pub const MAX_KEYS: usize = 4;
|
pub const MAX_KEYS: usize = 4;
|
||||||
pub const PAGE_SIZE: usize = 512;
|
pub const PAGE_SIZE: usize = 2048;
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ fn main() {
|
||||||
|
|
||||||
fn repl(tree: &mut BPlusTree<FileStorage>) {
|
fn repl(tree: &mut BPlusTree<FileStorage>) {
|
||||||
loop {
|
loop {
|
||||||
print!("> ");
|
|
||||||
io::stdout().flush().unwrap();
|
io::stdout().flush().unwrap();
|
||||||
|
|
||||||
let mut input = String::new();
|
let mut input = String::new();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue