Skip to content

Commit 91794f5

Browse files
committed
make internal nodes also contains values
Signed-off-by: Arshdeep54 <balarsh535@gmail.com>
1 parent f719efa commit 91794f5

File tree

5 files changed

+101
-151
lines changed

5 files changed

+101
-151
lines changed

src/btree/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66
- https://www.cloudcentric.dev/implementing-a-b-tree-in-go/
77
- https://youtu.be/7MqaHGWRS3E?si=6INHVHPWdd6J6pgu
88
- https://nimrodshn.medium.com/writing-a-storage-engine-in-rust-writing-a-persistent-btree-part-1-916b6f3e2934
9+
- https://planetscale.com/blog/btrees-and-database-indexes

src/btree/mod.rs

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -91,15 +91,11 @@ impl Btree {
9191
.take()
9292
.expect("Called split_root on an empty tree.");
9393

94+
let (mid_item, new_node) = old_root.split(&mut self.pager).unwrap();
9495
let new_root_id = self.pager.allocate_page().unwrap();
9596
let mut new_root = Node::new(new_root_id);
9697

97-
let (mid_item, new_node) = old_root.split(&mut self.pager).unwrap();
98-
let nav_item = Item {
99-
key: mid_item.key,
100-
val: String::new(), // Internal nodes don't store values
101-
};
102-
new_root.insert_item_at(0, nav_item);
98+
new_root.insert_item_at(0, mid_item);
10399
new_root.insert_child_at(0, *old_root);
104100
new_root.insert_child_at(1, new_node);
105101
self.root = Some(Box::new(new_root));
@@ -117,16 +113,8 @@ impl Btree {
117113
let (pos, found) = current_node.search(key);
118114

119115
if found {
120-
if current_node.is_leaf() {
121-
let val = &current_node.items[pos as usize].val;
122-
return Ok(val.clone());
123-
} else {
124-
current_node_opt = current_node
125-
.children
126-
.get(pos as usize + 1)
127-
.map(|boxed_node| &**boxed_node);
128-
continue;
129-
}
116+
let val = &current_node.items[pos as usize].val;
117+
return Ok(val.clone());
130118
}
131119

132120
current_node_opt = current_node

src/btree/node.rs

Lines changed: 14 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -80,16 +80,7 @@ impl Node {
8080
insert_pos += 1;
8181
}
8282

83-
let item_to_insert = if !self.is_leaf() {
84-
Item {
85-
key: item.key,
86-
val: String::new(),
87-
}
88-
} else {
89-
item
90-
};
91-
92-
self.items.insert(insert_pos, item_to_insert);
83+
self.items.insert(insert_pos, item);
9384
self.num_items += 1;
9485
}
9586

@@ -141,17 +132,7 @@ impl Node {
141132

142133
if self.children[pos as usize].num_items >= MAX_ITEMS {
143134
let (mid_item, new_node) = self.children[pos as usize].split(pager).unwrap();
144-
145-
if !self.is_leaf() {
146-
let nav_item = Item {
147-
key: mid_item.key,
148-
val: String::new(),
149-
};
150-
self.insert_item_at(pos, nav_item);
151-
} else {
152-
self.insert_item_at(pos, mid_item);
153-
}
154-
135+
self.insert_item_at(pos, mid_item);
155136
self.insert_child_at(pos + 1, new_node);
156137

157138
let condition = item.key - self.items[pos as usize].key;
@@ -196,9 +177,8 @@ impl Node {
196177

197178
let mut all_items = Vec::new();
198179
all_items.extend(original_items);
199-
all_items.extend(next_child.items);
200180
all_items.push(separator);
201-
181+
all_items.extend(next_child.items);
202182
all_items.sort_by_key(|item| item.key);
203183
child.items = all_items;
204184

@@ -214,27 +194,20 @@ impl Node {
214194
let (left, right) = self.children.split_at_mut(pos as usize);
215195
let sibling = &mut left[left.len() - 1];
216196
let child = &mut right[0];
217-
218197
let sibling_item = sibling.items.pop().unwrap();
219198

220199
let parent_item = self.items[pos as usize - 1].clone();
221200

222-
self.items[pos as usize - 1] = Item {
223-
key: sibling_item.key,
224-
val: String::new(),
225-
};
201+
self.items[pos as usize - 1] = sibling_item;
226202

227-
if child.is_leaf() {
228-
child.items.insert(0, sibling_item);
229-
} else {
230-
child.items.insert(0, parent_item);
231-
}
203+
child.items.insert(0, parent_item);
232204

233205
if !sibling.is_leaf() {
234206
if let Some(last_child) = sibling.children.pop() {
235207
child.children.insert(0, last_child);
236208
}
237209
}
210+
238211
sibling.num_items -= 1;
239212
child.num_items += 1;
240213

@@ -253,16 +226,9 @@ impl Node {
253226

254227
let parent_item = self.items[pos as usize].clone();
255228

256-
self.items[pos as usize] = Item {
257-
key: sibling_item.key,
258-
val: String::new(),
259-
};
229+
self.items[pos as usize] = sibling_item;
260230

261-
if child.is_leaf() {
262-
child.items.push(sibling_item);
263-
} else {
264-
child.items.push(parent_item);
265-
}
231+
child.items.push(parent_item);
266232

267233
if !sibling.is_leaf() {
268234
if let Some(first_child) = sibling.children.first().cloned() {
@@ -289,12 +255,10 @@ impl Node {
289255
items: self.items.clone(),
290256
}
291257
} else {
292-
let keys = self.items.iter().map(|it| it.key).collect();
293-
let children = self.children.iter().map(|c| c.id).collect();
294258
Page::Internal {
295259
id: self.id,
296-
keys,
297-
children,
260+
items: self.items.clone(),
261+
children: self.children.iter().map(|c| c.id).collect(),
298262
}
299263
}
300264
}
@@ -313,22 +277,15 @@ impl Node {
313277
}
314278
Page::Internal {
315279
id,
316-
keys,
317-
children: child_ids,
280+
items,
281+
children,
318282
} => {
319-
let items: Vec<Item> = keys
320-
.iter()
321-
.map(|k| Item {
322-
key: *k,
323-
val: String::new(),
324-
})
325-
.collect();
326283
let num_items = items.len() as i32;
327-
let num_children = child_ids.len() as i32;
284+
let num_children = children.len() as i32;
328285

329286
Node {
330287
id: *id,
331-
items,
288+
items: items.clone(),
332289
children: Vec::new(),
333290
num_items,
334291
num_children,

src/btree/paging.rs

Lines changed: 31 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pub type PageID = u32;
1010
pub enum Page {
1111
Internal {
1212
id: PageID,
13-
keys: Vec<i32>,
13+
items: Vec<Item>,
1414
children: Vec<PageID>,
1515
},
1616
Leaf {
@@ -81,17 +81,28 @@ impl Pager {
8181
let mut buf = vec![0u8; self.page_size];
8282
let page_id: u32;
8383
match page {
84-
Page::Internal { id, keys, children } => {
84+
Page::Internal {
85+
id,
86+
items,
87+
children,
88+
} => {
8589
page_id = *id;
8690

8791
buf[0] = 1; // 1-> internal type
88-
let key_count = keys.len() as u32;
89-
buf[1..5].copy_from_slice(&key_count.to_le_bytes()); // next 4 bytes-> keycount in little endian format
92+
let items_count = items.len() as u32;
93+
buf[1..5].copy_from_slice(&items_count.to_le_bytes());
9094

9195
let mut offset = 5;
92-
for k in keys {
93-
buf[offset..offset + 4].copy_from_slice(&k.to_le_bytes());
96+
for item in items {
97+
buf[offset..offset + 4].copy_from_slice(&item.key.to_le_bytes());
98+
offset += 4;
99+
100+
let val_bytes = item.val.as_bytes();
101+
let len = val_bytes.len() as u32;
102+
buf[offset..offset + 4].copy_from_slice(&len.to_le_bytes());
94103
offset += 4;
104+
buf[offset..offset + len as usize].copy_from_slice(val_bytes);
105+
offset += len as usize;
95106
}
96107

97108
for c in children {
@@ -127,9 +138,7 @@ impl Pager {
127138
self.file.write_all(&buf)?;
128139
Ok(())
129140
}
130-
}
131141

132-
impl Pager {
133142
pub fn read_page(&mut self, page_id: PageID) -> Result<Page> {
134143
let mut buf = vec![0u8; self.page_size];
135144
self.file.seek(std::io::SeekFrom::Start(
@@ -139,45 +148,26 @@ impl Pager {
139148

140149
let page_type = buf[0];
141150
if page_type == 1 {
142-
let keycount = u32::from_le_bytes(buf[1..5].try_into().unwrap());
143-
144-
if keycount > ((self.page_size - 5) / 8) as u32 {
145-
return Err(std::io::Error::new(
146-
std::io::ErrorKind::InvalidData,
147-
format!(
148-
"Invalid key count: {} (max allowed: {})",
149-
keycount,
150-
(self.page_size - 5) / 8
151-
),
152-
));
153-
}
151+
let items_count = u32::from_le_bytes(buf[1..5].try_into().unwrap());
154152

155153
let mut offset = 5;
154+
let mut items = Vec::with_capacity(items_count as usize);
156155

157-
let mut keys = Vec::with_capacity(keycount as usize);
158-
for _ in 0..keycount {
159-
if offset + 4 > self.page_size {
160-
return Err(std::io::Error::new(
161-
std::io::ErrorKind::InvalidData,
162-
"Buffer overflow while reading keys",
163-
));
164-
}
156+
for _ in 0..items_count {
157+
let key = i32::from_le_bytes(buf[offset..offset + 4].try_into().unwrap());
158+
offset += 4;
165159

166-
keys.push(i32::from_le_bytes(
167-
buf[offset..offset + 4].try_into().unwrap(),
168-
));
160+
let val_len =
161+
u32::from_le_bytes(buf[offset..offset + 4].try_into().unwrap()) as usize;
169162
offset += 4;
170-
}
163+
let val = String::from_utf8_lossy(&buf[offset..offset + val_len]).to_string();
164+
offset += val_len;
171165

172-
let mut children = Vec::with_capacity((keycount + 1) as usize);
173-
for _ in 0..=keycount {
174-
if offset + 4 > self.page_size {
175-
return Err(std::io::Error::new(
176-
std::io::ErrorKind::InvalidData,
177-
"Buffer overflow while reading children",
178-
));
179-
}
166+
items.push(Item { key, val });
167+
}
180168

169+
let mut children = Vec::with_capacity((items_count + 1) as usize);
170+
for _ in 0..=items_count {
181171
children.push(u32::from_le_bytes(
182172
buf[offset..offset + 4].try_into().unwrap(),
183173
));
@@ -186,58 +176,21 @@ impl Pager {
186176

187177
Ok(Page::Internal {
188178
id: page_id,
189-
keys,
179+
items,
190180
children,
191181
})
192182
} else if page_type == 0 {
193183
let items_count = u32::from_le_bytes(buf[1..5].try_into().unwrap());
194-
195-
if items_count > ((self.page_size - 5) / 20) as u32 {
196-
return Err(std::io::Error::new(
197-
std::io::ErrorKind::InvalidData,
198-
format!(
199-
"Invalid items count: {} (max allowed: {})",
200-
items_count,
201-
(self.page_size - 5) / 20
202-
),
203-
));
204-
}
205-
206184
let mut items = Vec::with_capacity(items_count as usize);
207185
let mut offset = 5;
208186

209187
for _ in 0..items_count {
210-
if offset + 4 > self.page_size {
211-
return Err(std::io::Error::new(
212-
std::io::ErrorKind::InvalidData,
213-
"Buffer overflow while reading item key",
214-
));
215-
}
216-
217188
let key = i32::from_le_bytes(buf[offset..offset + 4].try_into().unwrap());
218189
offset += 4;
219190

220-
if offset + 4 > self.page_size {
221-
return Err(std::io::Error::new(
222-
std::io::ErrorKind::InvalidData,
223-
"Buffer overflow while reading value length",
224-
));
225-
}
226-
227191
let val_len =
228192
u32::from_le_bytes(buf[offset..offset + 4].try_into().unwrap()) as usize;
229193
offset += 4;
230-
231-
if val_len > self.page_size || offset + val_len > self.page_size {
232-
return Err(std::io::Error::new(
233-
std::io::ErrorKind::InvalidData,
234-
format!(
235-
"Invalid value length: {} (buffer size: {})",
236-
val_len, self.page_size
237-
),
238-
));
239-
}
240-
241194
let val = String::from_utf8_lossy(&buf[offset..offset + val_len]).to_string();
242195
offset += val_len;
243196

0 commit comments

Comments
 (0)