Skip to content

Commit 4b29fc5

Browse files
committed
feat: block io alloc size
1 parent cc1a137 commit 4b29fc5

3 files changed

Lines changed: 170 additions & 73 deletions

File tree

src/btree/mod.rs

Lines changed: 99 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,17 @@ use std::{
99
cmp::{self, Ordering},
1010
fmt::Debug,
1111
marker::PhantomData,
12+
path::Path,
1213
};
1314

1415
pub mod node;
1516
pub mod spec;
16-
use spec::{BTreeCell, BTreePageHeader, PageType, BTREE_PAGE_HEADER_SIZE};
17+
use spec::{
18+
BTreeBlockHeader, BTreeCell, BTreePageHeader, PageType, BTREE_BLOCK_ALLOC_SIZE,
19+
BTREE_PAGE_HEADER_SIZE,
20+
};
21+
22+
pub const MAX_BRANCHING_FACTOR: u16 = 100;
1723

1824
#[derive(Debug)]
1925
pub struct Search {
@@ -24,26 +30,67 @@ pub struct Search {
2430
pub index: Either<u16, u16>,
2531
}
2632

27-
pub struct BTree<'p, K, V> {
33+
pub struct BTree<K, V> {
2834
root: PageNumber,
2935
b: u16,
30-
io: &'p mut BlockIO,
36+
io: BlockIO,
3137

3238
_k: PhantomData<K>,
3339
_v: PhantomData<V>,
3440
}
3541

3642
impl<
37-
'p,
3843
K: Serialize + DeserializeOwned + PartialOrd + Ord + Clone + Debug,
3944
V: Serialize + DeserializeOwned + PartialOrd + Ord + Clone + Debug,
40-
> BTree<'p, K, V>
45+
> BTree<K, V>
4146
{
42-
pub fn new(io: &'p mut BlockIO, root: PageNumber, b: u16) -> Result<Self> {
47+
pub fn new<P>(block_path: P) -> Result<Self>
48+
where
49+
P: AsRef<Path>,
50+
{
51+
let io: BlockIO =
52+
BlockIO::new(block_path, BTREE_BLOCK_ALLOC_SIZE as u16).map_err(Error::IoError)?;
53+
54+
if io.exists().map_err(Error::IoError)? {
55+
Self::open_block(io)
56+
} else {
57+
Self::create_block(io)
58+
}
59+
}
60+
61+
fn open_block(mut io: BlockIO) -> Result<Self> {
62+
let bytes = io.read_alloc_data().map_err(Error::IoError)?;
63+
let block_header: BTreeBlockHeader =
64+
bincode::deserialize(&bytes).map_err(Error::SerializeError)?;
65+
4366
Ok(Self {
44-
root,
4567
io,
46-
b,
68+
root: block_header.root,
69+
b: block_header.b,
70+
_k: PhantomData,
71+
_v: PhantomData,
72+
})
73+
}
74+
75+
fn create_block(mut io: BlockIO) -> Result<Self> {
76+
let mut root: Page<BTreeCell<K, V>> = Page::create(BTREE_PAGE_HEADER_SIZE).unwrap();
77+
let metadata = BTreePageHeader::new(PageType::Leaf, None);
78+
root.write_special(&metadata.to_bytes()).unwrap();
79+
80+
io.write_page(0, &root).unwrap();
81+
82+
let block_header = BTreeBlockHeader {
83+
b: MAX_BRANCHING_FACTOR,
84+
root: 0,
85+
};
86+
87+
io.alloc_data(&bincode::serialize(&block_header).map_err(Error::SerializeError)?)
88+
.map_err(Error::IoError)?;
89+
90+
Ok(Self {
91+
io,
92+
root: 0,
93+
b: MAX_BRANCHING_FACTOR,
4794
_k: PhantomData,
4895
_v: PhantomData,
4996
})
@@ -122,15 +169,15 @@ impl<
122169
if root.is_full(self.b) {
123170
let mut splited = root.split(self.b)?;
124171

125-
let sibling_page_index = self
172+
let sibling_page_number = self
126173
.io
127174
.write_new_page(&splited.sibling_node.page)
128175
.map_err(Error::IoError)?;
129176

130177
// create new root
131178
let mut new_root = Page::<BTreeCell<K, V>>::create(BTREE_PAGE_HEADER_SIZE)?;
132179
// set sibling page index to new root right child
133-
let new_root_metadata = BTreePageHeader::new(PageType::Root, Some(sibling_page_index));
180+
let new_root_metadata = BTreePageHeader::new(PageType::Root, Some(sibling_page_number));
134181
new_root.write_special(&new_root_metadata.to_bytes())?;
135182

136183
splited.median_cell.left_child = Some(self.root);
@@ -143,7 +190,8 @@ impl<
143190
.map_err(Error::IoError)?;
144191

145192
// write new root to disk and set new root index
146-
self.root = self.io.write_new_page(&new_root).map_err(Error::IoError)?;
193+
let root_page = self.io.write_new_page(&new_root).map_err(Error::IoError)?;
194+
self.set_root(root_page)?;
147195
}
148196

149197
self.insert_non_full(self.root, key, value)
@@ -165,43 +213,43 @@ impl<
165213

166214
match node.header.kind {
167215
PageType::Internal | PageType::Root => {
168-
let page_child_index = node.child(index)?.unwrap();
216+
let page_child_page_number = node.child(index)?.unwrap();
169217

170218
let page_child: BTreeNode<K, V> = self
171219
.io
172-
.read_page(page_child_index.into())
220+
.read_page(page_child_page_number.into())
173221
.map_err(Error::IoError)?
174222
.try_into()?;
175223

176224
if !page_child.is_full(self.b) {
177-
return self.insert_non_full(page_child_index, key, value);
225+
return self.insert_non_full(page_child_page_number, key, value);
178226
}
179227

180228
let mut splited = page_child.split(self.b)?;
181229

182-
let sibling_page_index = self
230+
let sibling_page_number = self
183231
.io
184232
.write_new_page(&splited.sibling_node.page)
185233
.map_err(Error::IoError)?;
186234

187-
node.set_child(index + 1, sibling_page_index)?;
235+
node.set_child(index + 1, sibling_page_number)?;
188236

189-
splited.median_cell.left_child = Some(page_child_index);
237+
splited.median_cell.left_child = Some(page_child_page_number);
190238

191239
let median_cell_key = splited.median_cell.key.clone();
192240
node.page.insert(index, splited.median_cell)?;
193241

194242
self.io
195-
.write_page(page_child_index.into(), &splited.node.page)
243+
.write_page(page_child_page_number.into(), &splited.node.page)
196244
.map_err(Error::IoError)?;
197245

198246
self.io
199247
.write_page(page_number.into(), &node.page)
200248
.map_err(Error::IoError)?;
201249

202250
let insert_page_offset = match key.cmp(&median_cell_key) {
203-
Ordering::Less | Ordering::Equal => page_child_index,
204-
Ordering::Greater => sibling_page_index,
251+
Ordering::Less | Ordering::Equal => page_child_page_number,
252+
Ordering::Greater => sibling_page_number,
205253
};
206254

207255
self.insert_non_full(insert_page_offset, key, value)
@@ -276,18 +324,22 @@ impl<
276324
key: &K,
277325
parents: &mut Vec<PageNumber>,
278326
) -> Result<()> {
327+
// search key
279328
let search = self.search_from_subtree(key, page_number, parents)?;
280329

330+
// get searched page node
281331
let mut node: BTreeNode<K, V> = self
282332
.io
283333
.read_page(search.page.into())
284334
.map_err(Error::IoError)?
285335
.try_into()?;
286336

337+
// return if not found
287338
if search.index.is_right() {
288339
return Err(Error::NotFound(format!("key {:?}", key)));
289340
}
290341

342+
// delete cell
291343
let index = *search.index.left().unwrap();
292344
node.page.delete(index)?;
293345
let page = node.page.compact()?;
@@ -296,6 +348,7 @@ impl<
296348
.write_page(search.page.into(), &page)
297349
.map_err(Error::IoError)?;
298350

351+
// check for underflow
299352
self.borrow_if_needed(search.page, parents, key)
300353
}
301354

@@ -334,11 +387,11 @@ impl<
334387
true => index - 1,
335388
};
336389

337-
let sibling_page_index = parent.child(sibling_index)?.unwrap();
390+
let sibling_page_number = parent.child(sibling_index)?.unwrap();
338391

339392
let sibling: BTreeNode<K, V> = self
340393
.io
341-
.read_page(sibling_page_index.into())
394+
.read_page(sibling_page_number.into())
342395
.map_err(Error::IoError)?
343396
.try_into()?;
344397

@@ -350,7 +403,7 @@ impl<
350403

351404
let mut merged_node = node.merge(sibling, cell)?;
352405

353-
let merged_page_index = self
406+
let merged_page_number = self
354407
.io
355408
.write_new_page(&merged_node.page)
356409
.map_err(Error::IoError)?;
@@ -362,12 +415,12 @@ impl<
362415
.write_special(&merged_node.header.to_bytes())?;
363416

364417
self.io
365-
.write_page(merged_page_index.into(), &merged_node.page)
418+
.write_page(merged_page_number.into(), &merged_node.page)
366419
.map_err(Error::IoError)?;
367420

368-
self.root = merged_page_index
421+
self.set_root(merged_page_number)?;
369422
} else {
370-
parent.set_child(merged_node_idx, merged_page_index)?;
423+
parent.set_child(merged_node_idx, merged_page_number)?;
371424
}
372425

373426
self.io
@@ -380,30 +433,28 @@ impl<
380433

381434
Ok(())
382435
}
383-
}
384-
385-
#[cfg(test)]
386-
mod btree_tests {
387-
use super::*;
388436

389-
#[test]
390-
fn create_btree() {
391-
let mut io = BlockIO::new("test_data/btree/create_btree").unwrap();
392-
393-
let mut root: Page<BTreeCell<u32, String>> = Page::create(BTREE_PAGE_HEADER_SIZE).unwrap();
394-
let metadata = BTreePageHeader::new(PageType::Leaf, None);
395-
root.write_special(&metadata.to_bytes()).unwrap();
396-
397-
io.write_page(0, &root).unwrap();
437+
fn set_root(&mut self, page_number: PageNumber) -> Result<()> {
438+
self.root = page_number;
398439

399-
let mut btree = BTree::<u32, String>::new(&mut io, 0, 10).unwrap();
400-
401-
for i in 0..100 {
402-
btree.insert(i, i.to_string()).unwrap();
403-
}
404-
405-
btree.delete(&99).unwrap();
440+
let block_header = BTreeBlockHeader {
441+
b: MAX_BRANCHING_FACTOR,
442+
root: self.root,
443+
};
406444

407-
println!("{:?}", btree.keys())
445+
self.io
446+
.alloc_data(&bincode::serialize(&block_header).map_err(Error::SerializeError)?)
447+
.map_err(Error::IoError)?;
448+
Ok(())
408449
}
409450
}
451+
452+
// #[cfg(test)]
453+
// mod btree_tests {
454+
// use super::*;
455+
456+
// #[test]
457+
// fn create_btree() {
458+
// let mut btree = BTree::<u32, String>::new("test_data/btree").unwrap();
459+
// }
460+
// }

src/btree/spec.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
use serde::{Deserialize, Serialize};
2+
use std::mem;
23

34
use crate::page::spec::PageNumber;
45

6+
pub const BTREE_BLOCK_ALLOC_SIZE: usize = mem::size_of::<BTreeBlockHeader>();
7+
8+
#[derive(Clone, Eq, Ord, PartialEq, PartialOrd, Serialize, Deserialize, Debug)]
9+
pub struct BTreeBlockHeader {
10+
pub root: PageNumber,
11+
pub b: u16,
12+
}
13+
514
#[derive(Clone, Eq, Ord, PartialEq, PartialOrd, Serialize, Deserialize, Debug)]
615
pub struct BTreeCell<K, V> {
716
pub left_child: Option<PageNumber>,

0 commit comments

Comments
 (0)