Skip to content

Commit cc1a137

Browse files
committed
feat: add btree deletion
1 parent cd0ec3e commit cc1a137

6 files changed

Lines changed: 87 additions & 29 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ Cargo.lock
66

77
# Test folders
88
/test_data
9+
/example

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ serde = { version = "1.0", features = ["derive"] }
2525
bloomfilter = "1.0"
2626
fs2 = "0.4.3"
2727
bincode = "1.3.3"
28-
rand = "0.8.5"
2928

3029
[build-dependencies]
3130
hooky-rs = "1.0.0"

src/btree/mod.rs

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -248,16 +248,19 @@ impl<
248248

249249
let mut results = Vec::new();
250250

251-
for index in 0..=node.page.len() {
251+
for index in 0..node.page.len() {
252252
let child = node.child(index)?;
253253

254-
if node.page.len() / 2 == index {
255-
results.extend(node.page.values()?);
256-
}
257-
258254
if let Some(child) = child {
259255
results.extend(self.cells_from_subtree(child)?)
260256
}
257+
258+
results.extend(node.page.read(index)?);
259+
}
260+
261+
let right = node.child(node.page.len())?;
262+
if let Some(right) = right {
263+
results.extend(self.cells_from_subtree(right)?)
261264
}
262265

263266
Ok(results)
@@ -290,10 +293,10 @@ impl<
290293
let page = node.page.compact()?;
291294

292295
self.io
293-
.write_page(page_number.into(), &page)
296+
.write_page(search.page.into(), &page)
294297
.map_err(Error::IoError)?;
295298

296-
self.borrow_if_needed(page_number, parents, key)
299+
self.borrow_if_needed(search.page, parents, key)
297300
}
298301

299302
fn borrow_if_needed(
@@ -326,42 +329,56 @@ impl<
326329
Either::Left(index) => index,
327330
Either::Right(index) => index,
328331
};
332+
let sibling_index = match index > 0 {
333+
false => index + 1,
334+
true => index - 1,
335+
};
329336

330-
let sibling_index = if index > 0 { index - 1 } else { index + 1 };
331-
let mut cell = parent.page.read(sibling_index)?.unwrap();
337+
let sibling_page_index = parent.child(sibling_index)?.unwrap();
332338

333339
let sibling: BTreeNode<K, V> = self
334340
.io
335-
.read_page(cell.left_child.unwrap().into())
341+
.read_page(sibling_page_index.into())
336342
.map_err(Error::IoError)?
337343
.try_into()?;
338-
let merged_node_idx = cmp::min(index, sibling_index);
339-
340-
let mut merged_node = node.merge(sibling)?;
341344

342-
cell.left_child = merged_node.header.right_child;
345+
let merged_node_idx = cmp::min(index, sibling_index);
343346

344-
parent.page.delete(sibling_index)?;
347+
let cell = parent.page.read(merged_node_idx)?.unwrap();
348+
parent.page.delete(merged_node_idx)?;
345349
let mut parent: BTreeNode<K, V> = parent.page.compact()?.try_into()?;
346350

347-
merged_node.page.insert(merged_node_idx, cell)?;
351+
let mut merged_node = node.merge(sibling, cell)?;
348352

349353
let merged_page_index = self
350354
.io
351355
.write_new_page(&merged_node.page)
352356
.map_err(Error::IoError)?;
353357

354-
if parent.header.kind == PageType::Root && parent.page.is_empty() {
358+
if parent.is_root() && parent.page.is_empty() {
359+
merged_node.header.kind = PageType::Root;
360+
merged_node
361+
.page
362+
.write_special(&merged_node.header.to_bytes())?;
363+
364+
self.io
365+
.write_page(merged_page_index.into(), &merged_node.page)
366+
.map_err(Error::IoError)?;
367+
355368
self.root = merged_page_index
356369
} else {
357-
parent.set_child(sibling_index, merged_page_index)?;
370+
parent.set_child(merged_node_idx, merged_page_index)?;
358371
}
359372

360373
self.io
361374
.write_page(parent_index.into(), &parent.page)
362375
.map_err(Error::IoError)?;
363376

364-
self.borrow_if_needed(parents.pop().unwrap(), parents, key)
377+
if let Some(parent) = parents.pop() {
378+
self.borrow_if_needed(parent, parents, key)?;
379+
}
380+
381+
Ok(())
365382
}
366383
}
367384

src/btree/node.rs

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ impl<
3737
}
3838
}
3939

40+
pub fn is_root(&self) -> bool {
41+
self.header.kind == PageType::Root
42+
}
43+
4044
pub fn split(mut self, b: u16) -> Result<BTreeNodeSplited<K, V>> {
4145
// split page cells at the middle
4246
let mut sibling_cells = self.page.split_off(b - 1)?;
@@ -94,15 +98,52 @@ impl<
9498
Ok(())
9599
}
96100

97-
pub fn merge(mut self, mut node: Self) -> Result<Self> {
98-
let node_values = node.page.values()?;
99-
self.page.write_all(node_values)?;
101+
pub fn max_key(&mut self) -> Result<Option<K>> {
102+
if self.page.is_empty() {
103+
return Ok(None);
104+
}
105+
106+
Ok(self.page.read(self.page.len() - 1)?.map(|e| e.key))
107+
}
108+
109+
pub fn min_key(&mut self) -> Result<Option<K>> {
110+
if self.page.is_empty() {
111+
return Ok(None);
112+
}
113+
114+
Ok(self.page.read(0)?.map(|e| e.key))
115+
}
116+
117+
pub fn merge(mut self, mut other: Self, mut cell: BTreeCell<K, V>) -> Result<Self> {
118+
let new_page_header = BTreePageHeader::new(self.header.kind, None);
119+
match self.min_key()? >= other.min_key()? {
120+
// merge with left sibling node
121+
true => {
122+
cell.left_child = other.header.right_child;
123+
}
124+
// merge with right sibling node
125+
false => {
126+
cell.left_child = self.header.right_child;
127+
self.header.right_child = other.header.right_child
128+
}
129+
};
130+
131+
let node_values = self.page.values()?.into_iter();
132+
let other_values = other.page.values()?.into_iter();
133+
134+
let mut merged_values = node_values
135+
.chain(other_values)
136+
.collect::<Vec<BTreeCell<K, V>>>();
137+
138+
merged_values.push(cell);
100139

101-
self.header.right_child = node.header.right_child;
140+
merged_values.sort_by(|a, b| a.key.cmp(&b.key));
102141

103-
self.page.write_special(&self.header.to_bytes())?;
142+
let mut page: Page<BTreeCell<K, V>> = Page::create(self.page.special_size())?;
143+
page.write_all(merged_values)?;
144+
page.write_special(&new_page_header.to_bytes())?;
104145

105-
Ok(self)
146+
page.try_into()
106147
}
107148
}
108149

src/btree/spec.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ pub struct BTreeCell<K, V> {
1111

1212
pub const BTREE_PAGE_HEADER_SIZE: u16 = 9;
1313

14-
#[derive(Serialize, Deserialize, Debug)]
14+
#[derive(Serialize, Deserialize, Debug, PartialEq, PartialOrd)]
1515
pub struct BTreePageHeader {
1616
pub kind: PageType,
1717
pub right_child: Option<PageNumber>,
1818
}
1919

20-
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Copy, Clone)]
20+
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Copy, Clone, PartialOrd, Ord)]
2121
pub enum PageType {
2222
Leaf = 0,
2323
Internal = 1,

src/page.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ impl<T: Serialize + DeserializeOwned + PartialOrd + Ord + Clone> Page<T> {
437437
PAGE_HEADER_SIZE
438438
}
439439

440-
fn special_size(&self) -> u16 {
440+
pub fn special_size(&self) -> u16 {
441441
PAGE_SIZE - self.header.special
442442
}
443443

0 commit comments

Comments
 (0)