From 457f3c8f54d98db7e1e5aacf12a77a8ef6a8ce08 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 3 Dec 2018 17:39:55 -0800 Subject: [PATCH] Break out PathMap from RbxSession --- server/src/lib.rs | 3 +- server/src/path_map.rs | 73 +++++++++++++++++++++++++++++++++ server/src/rbx_session.rs | 86 ++++----------------------------------- 3 files changed, 84 insertions(+), 78 deletions(-) create mode 100644 server/src/path_map.rs diff --git a/server/src/lib.rs b/server/src/lib.rs index 536f781b..4945f343 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -10,11 +10,12 @@ extern crate tempfile; // pub mod roblox_studio; pub mod commands; pub mod fs_watcher; +pub mod imfs; pub mod message_queue; +pub mod path_map; pub mod project; pub mod rbx_session; pub mod session; pub mod session_id; -pub mod imfs; pub mod web; pub mod web_util; \ No newline at end of file diff --git a/server/src/path_map.rs b/server/src/path_map.rs new file mode 100644 index 00000000..ef60c6c7 --- /dev/null +++ b/server/src/path_map.rs @@ -0,0 +1,73 @@ +use std::{ + path::{Path, PathBuf}, + collections::{HashMap, HashSet}, +}; + +#[derive(Debug)] +struct PathMapNode { + value: T, + children: HashSet, +} + +/// A map from paths to instance IDs, with a bit of additional data that enables +/// removing a path and all of its child paths from the tree in constant time. +#[derive(Debug)] +pub struct PathMap { + nodes: HashMap>, +} + +impl PathMap { + pub fn new() -> PathMap { + PathMap { + nodes: HashMap::new(), + } + } + + pub fn get(&self, path: &Path) -> Option<&T> { + self.nodes.get(path).map(|v| &v.value) + } + + pub fn insert(&mut self, path: PathBuf, value: T) { + if let Some(parent_path) = path.parent() { + if let Some(parent) = self.nodes.get_mut(parent_path) { + parent.children.insert(path.to_path_buf()); + } + } + + self.nodes.insert(path, PathMapNode { + value, + children: HashSet::new(), + }); + } + + pub fn remove(&mut self, root_path: &Path) -> Option { + if let Some(parent_path) = root_path.parent() { + if let Some(parent) = self.nodes.get_mut(parent_path) { + parent.children.remove(root_path); + } + } + + let mut root_node = match self.nodes.remove(root_path) { + Some(node) => node, + None => return None, + }; + + let root_value = root_node.value; + let mut to_visit: Vec = root_node.children.drain().collect(); + + while let Some(path) = to_visit.pop() { + match self.nodes.remove(&path) { + Some(mut node) => { + for child in node.children.drain() { + to_visit.push(child); + } + }, + None => { + warn!("Consistency issue; tried to remove {} but it was already removed", path.display()); + }, + } + } + + Some(root_value) + } +} \ No newline at end of file diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 3fc2fd4b..13925d48 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -1,6 +1,6 @@ use std::{ - collections::{HashMap, HashSet}, - path::{Path, PathBuf}, + collections::HashMap, + path::Path, sync::{Arc, Mutex}, str, }; @@ -11,80 +11,12 @@ use crate::{ project::{Project, ProjectNode, InstanceProjectNode}, message_queue::{Message, MessageQueue}, imfs::{Imfs, ImfsItem, ImfsFile}, + path_map::PathMap, }; -#[derive(Debug)] -struct PathIdNode { - id: RbxId, - children: HashSet, -} - -/// A map from paths to instance IDs, with a bit of additional data that enables -/// removing a path and all of its child paths from the tree in constant time. -#[derive(Debug)] -struct PathIdTree { - nodes: HashMap, -} - -impl PathIdTree { - pub fn new() -> PathIdTree { - PathIdTree { - nodes: HashMap::new(), - } - } - - pub fn get_id(&self, path: &Path) -> Option { - self.nodes.get(path).map(|v| v.id) - } - - pub fn insert(&mut self, path: &Path, id: RbxId) { - if let Some(parent_path) = path.parent() { - if let Some(parent) = self.nodes.get_mut(parent_path) { - parent.children.insert(path.to_path_buf()); - } - } - - self.nodes.insert(path.to_path_buf(), PathIdNode { - id, - children: HashSet::new(), - }); - } - - pub fn remove(&mut self, root_path: &Path) -> Option { - if let Some(parent_path) = root_path.parent() { - if let Some(parent) = self.nodes.get_mut(parent_path) { - parent.children.remove(root_path); - } - } - - let mut root_node = match self.nodes.remove(root_path) { - Some(node) => node, - None => return None, - }; - - let root_id = root_node.id; - let mut to_visit: Vec = root_node.children.drain().collect(); - - while let Some(path) = to_visit.pop() { - match self.nodes.remove(&path) { - Some(mut node) => { - for child in node.children.drain() { - to_visit.push(child); - } - }, - None => { - warn!("Consistency issue; tried to remove {} but it was already removed", path.display()); - }, - } - } - - Some(root_id) - } -} - pub struct RbxSession { tree: RbxTree, - path_id_tree: PathIdTree, + path_id_tree: PathMap, ids_to_project_paths: HashMap, message_queue: Arc, imfs: Arc>, @@ -177,15 +109,15 @@ pub fn construct_oneoff_tree(project: &Project, imfs: &Imfs) -> RbxTree { struct ConstructContext<'a> { tree: Option, imfs: &'a Imfs, - path_id_tree: PathIdTree, + path_id_tree: PathMap, ids_to_project_paths: HashMap, } fn construct_initial_tree( project: &Project, imfs: &Imfs, -) -> (RbxTree, PathIdTree, HashMap) { - let path_id_tree = PathIdTree::new(); +) -> (RbxTree, PathMap, HashMap) { + let path_id_tree = PathMap::new(); let ids_to_project_paths = HashMap::new(); let mut context = ConstructContext { @@ -320,7 +252,7 @@ fn construct_sync_point_node( let id = insert_or_create_tree(context, parent_instance_id, instance); - context.path_id_tree.insert(&file.path, id); + context.path_id_tree.insert(file.path.clone(), id); id }, @@ -337,7 +269,7 @@ fn construct_sync_point_node( }; let id = insert_or_create_tree(context, parent_instance_id, instance); - context.path_id_tree.insert(&directory.path, id); + context.path_id_tree.insert(directory.path.clone(), id); id };