use crate::patch::{Change, Changes};
use crate::{NodeId, PatchId};
use ojo_multimap::MMap;
use std::collections::{BTreeMap, HashMap};
#[macro_use]
pub mod graggle;
pub mod file;
pub use self::file::File;
pub use self::graggle::{FullGraph, Graggle, LiveGraph};
use self::graggle::GraggleData;
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct INode {
n: u64,
}
#[derive(Debug, Deserialize, Serialize)]
pub(crate) struct Storage {
next_inode: u64,
contents: BTreeMap<NodeId, Vec<u8>>,
branches: BTreeMap<String, INode>,
graggles: BTreeMap<INode, GraggleData>,
pub patches: HashMap<PatchId, String>,
pub branch_patches: MMap<String, PatchId>,
pub patch_deps: MMap<PatchId, PatchId>,
pub patch_rev_deps: MMap<PatchId, PatchId>,
}
impl Storage {
pub fn new() -> Storage {
Storage {
next_inode: 0,
contents: BTreeMap::new(),
branches: BTreeMap::new(),
graggles: BTreeMap::new(),
patches: HashMap::new(),
branch_patches: MMap::new(),
patch_deps: MMap::new(),
patch_rev_deps: MMap::new(),
}
}
pub fn allocate_inode(&mut self) -> INode {
let ret = INode { n: self.next_inode };
self.next_inode += 1;
self.graggles.insert(ret, GraggleData::new());
ret
}
pub fn clone_inode(&mut self, inode: INode) -> INode {
let ret = INode { n: self.next_inode };
self.next_inode += 1;
let old_graggle = &self.graggles[&inode];
self.graggles.insert(ret, old_graggle.clone());
ret
}
pub fn contents(&self, id: &NodeId) -> &[u8] {
self.contents[id].as_slice()
}
pub fn add_contents(&mut self, id: NodeId, contents: Vec<u8>) {
use std::collections::btree_map::Entry;
match self.contents.entry(id) {
Entry::Occupied(o) => assert_eq!(o.get(), &contents, "contents mismatch"),
Entry::Vacant(v) => {
v.insert(contents);
}
}
}
pub fn remove_contents(&mut self, id: &NodeId) {
self.contents.remove(id);
}
pub fn contains_node(&self, id: &NodeId) -> bool {
self.contents.contains_key(id)
}
pub fn inode(&self, branch: &str) -> Option<INode> {
self.branches.get(branch).cloned()
}
pub fn set_inode(&mut self, branch: &str, inode: INode) -> Option<INode> {
self.branches.insert(branch.to_owned(), inode)
}
pub fn remove_inode(&mut self, branch: &str) {
self.branches.remove(branch);
}
pub fn update_cache(&mut self, inode: INode) {
let graggle = self.graggles.get_mut(&inode).unwrap();
graggle.resolve_pseudo_edges();
}
pub fn graggle(&'_ self, inode: INode) -> Graggle<'_> {
self.graggles[&inode].as_graggle()
}
pub fn remove_graggle(&mut self, inode: INode) {
self.graggles.remove(&inode);
}
pub fn set_graggle(&mut self, inode: INode, graggle: GraggleData) {
self.graggles.insert(inode, graggle);
}
pub fn branches(&self) -> impl Iterator<Item = &str> {
self.branches.keys().map(|s| s.as_str())
}
pub fn apply_changes(&mut self, inode: INode, changes: &Changes, patch: PatchId) {
let graggle = self.graggles.get_mut(&inode).unwrap();
for ch in &changes.changes {
match *ch {
Change::NewNode { ref id, .. } => {
debug!("adding node {:?}", id);
graggle.add_node(id.clone());
}
Change::DeleteNode { ref id } => {
debug!("deleting node {:?}", id);
graggle.delete_node(&id);
}
Change::NewEdge { ref src, ref dest } => {
debug!("adding edge {:?} -- {:?}", src, dest);
graggle.add_edge(src.clone(), dest.clone(), patch);
}
}
}
for ch in &changes.changes {
if let Change::NewNode {
ref id,
ref contents,
} = *ch
{
self.add_contents(id.clone(), contents.to_owned());
}
}
}
pub fn unapply_changes(&mut self, inode: INode, changes: &Changes, patch: PatchId) {
let graggle = self.graggles.get_mut(&inode).unwrap();
for ch in &changes.changes {
match *ch {
Change::DeleteNode { ref id } => {
debug!("undeleting node {:?}", id);
graggle.undelete_node(id);
}
Change::NewEdge { ref src, ref dest } => {
debug!("unadding edge {:?} -- {:?}", src, dest);
graggle.unadd_edge(src, dest, patch);
}
Change::NewNode { .. } => {}
}
}
for ch in &changes.changes {
if let Change::NewNode { ref id, .. } = *ch {
debug!("unadding node {:?}", id);
graggle.unadd_node(id);
}
}
for ch in &changes.changes {
if let Change::NewNode { ref id, .. } = *ch {
self.remove_contents(id);
}
}
}
}