bplustree 0.1.0

Concurrent in-memory B+ Tree featuring optimistic lock coupling
Documentation
use crate::{BPlusTree, Node, InternalNode, LeafNode};
use crate::latch::HybridLatch;
use smallvec::smallvec;
use crossbeam_epoch::Atomic;

use serde::Deserialize;
use std::sync::atomic::AtomicUsize;

type DefaultNode<K, V> = Node<K, V, 128, 256>;

#[derive(Deserialize, Debug)]
struct Edge {
    key: String,
    child: TreeNode
}

#[derive(Deserialize, Debug)]
struct Value {
    key: String,
    value: u64
}

#[derive(Deserialize, Debug)]
#[serde(untagged)]
enum TreeNode {
    Internal {
        edges: Vec<Edge>,
        upper_edge: Box<Option<TreeNode>>,
        lower_fence: Option<String>,
        upper_fence: Option<String>,
        sample_key: Option<String>
    },
    Leaf {
        values: Vec<Value>,
        lower_fence: Option<String>,
        upper_fence: Option<String>,
        sample_key: Option<String>
    }
}

#[derive(Deserialize, Debug)]
struct Tree {
    root: TreeNode,
    height: usize
}

fn translate_node(tree_node: TreeNode) -> Atomic<HybridLatch<DefaultNode<String, u64>>> {
    match tree_node {
        TreeNode::Internal { edges, upper_edge, lower_fence, upper_fence, sample_key } => {
            let mut out_keys = smallvec![];
            let mut out_edges = smallvec![];
            for edge in edges {
                out_keys.push(edge.key);
                out_edges.push(translate_node(edge.child));
            }

            let out_upper_edge = upper_edge.map(|tn| translate_node(tn));

            return Atomic::new(HybridLatch::new(Node::Internal(
                        InternalNode {
                            len: out_keys.len() as u16,
                            keys: out_keys,
                            edges: out_edges,
                            upper_edge: out_upper_edge,
                            lower_fence,
                            upper_fence,
                            sample_key
                        }
            )))
        }
        TreeNode::Leaf { values, lower_fence, upper_fence, sample_key } => {
            let mut out_keys = smallvec![];
            let mut out_values = smallvec![];
            for value in values {
                out_keys.push(value.key);
                out_values.push(value.value);
            }

            return Atomic::new(HybridLatch::new(Node::Leaf(
                        LeafNode {
                            len: out_keys.len() as u16,
                            keys: out_keys,
                            values: out_values,
                            lower_fence,
                            upper_fence,
                            sample_key
                        }
            )))
        }
    }
}

pub fn sample_tree<P: AsRef<std::path::Path>>(path: P) -> BPlusTree<String, u64> {
    let file = std::fs::File::open(path).expect("failed to find file");
    let tree: Tree = serde_json::from_reader(file).unwrap();
    let translated = translate_node(tree.root);
    BPlusTree {
        root: HybridLatch::new(translated),
        height: AtomicUsize::new(tree.height)
    }
}