Skip to content

Commit

Permalink
.
Browse files Browse the repository at this point in the history
  • Loading branch information
ielashi committed Aug 15, 2023
1 parent 877d438 commit d03dac0
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 37 deletions.
57 changes: 28 additions & 29 deletions src/btreemap/node/tests.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::*;
use crate::{btreemap::allocator::Allocator, types::NULL};
use crate::btreemap::allocator::Allocator;
use proptest::collection::btree_map as pmap;
use proptest::collection::vec as pvec;
use std::cell::RefCell;
Expand All @@ -18,7 +18,7 @@ struct NodeV1Data {
#[strategy(1..1_000u32)]
max_value_size: u32,

// NOTE: A BTreeMap is used for creating the entries so that they'd be in sorted order.
// NOTE: A BTreeMap is used for creating the entries so that they're in sorted order.
#[strategy(
pmap(
pvec(0..u8::MAX, 0..#max_key_size as usize),
Expand All @@ -44,35 +44,34 @@ impl NodeV1Data {
node.push_entry(entry);
}

// If the node is an internal node, then insert some children addresses.
if self.node_type == NodeType::Internal {
for i in 0..=self.entries.len() {
node.push_child(Address::from(i as u64));
}
for child in self.children() {
node.push_child(child);
}

node
}

fn children(&self) -> Vec<Address> {
if self.node_type == NodeType::Internal {
(0..=self.entries.len())
match self.node_type {
// A leaf node doesn't have any children.
NodeType::Leaf => vec![],
// An internal node has # entries + 1 children.
// Here we generate a list of addresses.
NodeType::Internal => (0..=self.entries.len())
.map(|i| Address::from(i as u64))
.collect()
} else {
vec![]
.collect(),
}
}
}

#[derive(Arbitrary, Debug)]
struct NodeV2Data {
// FIXME: figure out proper lower bound for page size.
#[strategy(15..2_000_u32)]
#[strategy(128..10_000_u32)]
page_size: u32,
#[strategy(
pmap(
pvec(0..u8::MAX, 0..100),
pvec(0..u8::MAX, 0..100),
pvec(0..u8::MAX, 0..1000),
pvec(0..u8::MAX, 0..1000),
1..CAPACITY
)
)]
Expand All @@ -86,22 +85,21 @@ impl NodeV2Data {
for entry in self.entries.clone().into_iter() {
node.push_entry(entry);
}
// If the node is an internal node, then insert some children addresses.
if self.node_type == NodeType::Internal {
for i in 0..=self.entries.len() {
node.push_child(Address::from(i as u64));
}
for child in self.children() {
node.push_child(child);
}
node
}

fn children(&self) -> Vec<Address> {
if self.node_type == NodeType::Internal {
(0..=self.entries.len())
match self.node_type {
// A leaf node doesn't have any children.
NodeType::Leaf => vec![],
// An internal node has # entries + 1 children.
// Here we generate a list of addresses.
NodeType::Internal => (0..=self.entries.len())
.map(|i| Address::from(i as u64))
.collect()
} else {
vec![]
.collect(),
}
}
}
Expand All @@ -112,12 +110,13 @@ fn saving_and_loading_v1(node_data: NodeV1Data) {
let mem = make_memory();

// Create a new node and save it into memory.
let node = node_data.get(NULL);
let node_addr = Address::from(0);
let node = node_data.get(node_addr);
node.save_v1(&mem);

// Reload the node and double check all the entries and children are correct.
// Load the node and double check all the entries and children are correct.
let node = Node::load_v1(
NULL,
node_addr,
Version::V1 {
max_key_size: node_data.max_key_size,
max_value_size: node_data.max_value_size,
Expand Down
21 changes: 13 additions & 8 deletions src/btreemap/node/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
//! ----------------------------------------
//! Next address ↕ 8 byte
//! ----------------------------------------
//! Page contents
//! Data
//! ----------------------------------------
//! ```
//!
Expand All @@ -75,23 +75,28 @@ use crate::types::NULL;
use crate::write_u64;
use std::cmp::min;

// The offset where the address of the overflow page is present.
// Initial page
const LAYOUT_VERSION_2: u8 = 2;
const NODE_TYPE_OFFSET: usize = 4;
const NUM_ENTRIES_OFFSET: usize = 5;
const OVERFLOW_ADDRESS_OFFSET: Bytes = Bytes::new(7);
const ENTRIES_OFFSET: Bytes = Bytes::new(15); // an additional 8 bytes for the overflow pointer
const ENTRIES_OFFSET: Bytes = Bytes::new(15);

// Overflow page
const OVERFLOW_MAGIC: &[u8; 3] = b"NOF";
const PAGE_OVERFLOW_NEXT_OFFSET: Bytes = Bytes::new(3);
const PAGE_OVERFLOW_DATA_OFFSET: Bytes = Bytes::new(11); // magic + next address

// TODO: add note that page size must be > ENTRIES OFFSET
const PAGE_OVERFLOW_DATA_OFFSET: Bytes = Bytes::new(11);

const OVERFLOW_MAGIC: &[u8; 3] = b"NOF";
const LAYOUT_VERSION_2: u8 = 2;
// The minimum size a page can have.
// Rationale: a page size needs to at least store the header (15 bytes) + all the children
// addresses (88 bytes). We round that up to 128 to get a nice binary number.
const MINIMUM_PAGE_SIZE = 128;

impl<K: Storable + Ord + Clone> Node<K> {
/// Creates a new v2 node at the given address.
pub(super) fn new_v2(address: Address, node_type: NodeType, page_size: PageSize) -> Node<K> {
assert!(page_size.get() >= MINIMUM_PAGE_SIZE);

Node {
address,
node_type,
Expand Down

0 comments on commit d03dac0

Please sign in to comment.