use std::sync::{atomic::AtomicUsize, Arc};
use super::*;
pub(crate) fn open_tree<'a>(
context: Context,
name: Vec<u8>,
tx: &'a Tx,
) -> Result<Tree> {
loop {
match context.pagecache.meta_pid_for_name(&name, tx) {
Ok(root_id) => {
return Ok(Tree {
tree_id: name,
context: context.clone(),
subscriptions: Arc::new(Subscriptions::default()),
root: Arc::new(AtomicUsize::new(root_id)),
});
}
Err(Error::CollectionNotFound(_)) => {}
Err(other) => return Err(other),
}
let leaf = Frag::Base(Node {
data: Data::Leaf(vec![]),
next: None,
lo: vec![].into(),
hi: vec![].into(),
});
let (leaf_id, leaf_ptr) = context.pagecache.allocate(leaf, &tx)?;
trace!(
"allocated pid {} for leaf in new_tree for namespace {:?}",
leaf_id,
name
);
let root_index_vec = vec![(vec![0].into(), leaf_id)];
let root = Frag::Base(Node {
data: Data::Index(root_index_vec),
next: None,
lo: vec![].into(),
hi: vec![].into(),
});
let (root_id, root_ptr) = context.pagecache.allocate(root, &tx)?;
debug!("allocated pid {} for root of new_tree {:?}", root_id, name);
let res = context.pagecache.cas_root_in_meta(
name.clone(),
None,
Some(root_id),
tx,
)?;
if res.is_err() {
context
.pagecache
.free(root_id, root_ptr, tx)?
.expect("could not free allocated page");
context
.pagecache
.free(leaf_id, leaf_ptr, tx)?
.expect("could not free allocated page");
continue;
}
return Ok(Tree {
tree_id: name,
subscriptions: Arc::new(Subscriptions::default()),
context: context.clone(),
root: Arc::new(AtomicUsize::new(root_id)),
});
}
}