From c8bb9bf2e9df080172607881f9b72e8fb9a97316 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 17 Nov 2018 13:46:56 -0800 Subject: [PATCH] Break out file watching into FsWatcher object --- server/src/fs_watcher.rs | 118 ++++++++++++++++++++++++++++++++++++++ server/src/lib.rs | 1 + server/src/session.rs | 121 ++++++--------------------------------- 3 files changed, 135 insertions(+), 105 deletions(-) create mode 100644 server/src/fs_watcher.rs diff --git a/server/src/fs_watcher.rs b/server/src/fs_watcher.rs new file mode 100644 index 00000000..13a79027 --- /dev/null +++ b/server/src/fs_watcher.rs @@ -0,0 +1,118 @@ +use std::{ + sync::{mpsc, Arc, Mutex}, + time::Duration, + thread, +}; + +use notify::{ + self, + DebouncedEvent, + RecommendedWatcher, + RecursiveMode, + Watcher, +}; + +use crate::{ + vfs::Vfs, + rbx_session::RbxSession, +}; + +const WATCH_TIMEOUT: Duration = Duration::from_millis(100); + +fn handle_event(vfs: &Mutex, rbx_session: &Mutex, event: DebouncedEvent) { + match event { + DebouncedEvent::Create(path) => { + { + let mut vfs = vfs.lock().unwrap(); + vfs.path_created(&path).unwrap(); + } + + { + let mut rbx_session = rbx_session.lock().unwrap(); + rbx_session.path_created(&path); + } + }, + DebouncedEvent::Write(path) => { + { + let mut vfs = vfs.lock().unwrap(); + vfs.path_updated(&path).unwrap(); + } + + { + let mut rbx_session = rbx_session.lock().unwrap(); + rbx_session.path_updated(&path); + } + }, + DebouncedEvent::Remove(path) => { + { + let mut vfs = vfs.lock().unwrap(); + vfs.path_removed(&path).unwrap(); + } + + { + let mut rbx_session = rbx_session.lock().unwrap(); + rbx_session.path_removed(&path); + } + }, + DebouncedEvent::Rename(from_path, to_path) => { + { + let mut vfs = vfs.lock().unwrap(); + vfs.path_moved(&from_path, &to_path).unwrap(); + } + + { + let mut rbx_session = rbx_session.lock().unwrap(); + rbx_session.path_renamed(&from_path, &to_path); + } + }, + _ => {}, + } +} + +/// Watches for changes on the filesystem and links together the in-memory +/// filesystem and in-memory Roblox tree. +pub struct FsWatcher { + #[allow(unused)] + watchers: Vec, +} + +impl FsWatcher { + pub fn start(vfs: Arc>, rbx_session: Arc>) -> FsWatcher { + let mut watchers = Vec::new(); + + { + let vfs_temp = vfs.lock().unwrap(); + + for root_path in vfs_temp.get_roots() { + let (watch_tx, watch_rx) = mpsc::channel(); + + let mut watcher = notify::watcher(watch_tx, WATCH_TIMEOUT) + .expect("Could not create `notify` watcher"); + + watcher.watch(root_path, RecursiveMode::Recursive) + .expect("Could not watch directory"); + + watchers.push(watcher); + + let vfs = Arc::clone(&vfs); + let rbx_session = Arc::clone(&rbx_session); + let root_path = root_path.clone(); + + thread::spawn(move || { + info!("Watcher thread ({}) started", root_path.display()); + loop { + match watch_rx.recv() { + Ok(event) => handle_event(&vfs, &rbx_session, event), + Err(_) => break, + }; + } + info!("Watcher thread ({}) stopped", root_path.display()); + }); + } + } + + FsWatcher { + watchers, + } + } +} \ No newline at end of file diff --git a/server/src/lib.rs b/server/src/lib.rs index ca15e9a3..117aa841 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -14,6 +14,7 @@ extern crate tempfile; // pub mod roblox_studio; pub mod commands; +pub mod fs_watcher; pub mod message_queue; pub mod project; pub mod rbx_session; diff --git a/server/src/session.rs b/server/src/session.rs index f072fdd9..fd51dd4f 100644 --- a/server/src/session.rs +++ b/server/src/session.rs @@ -1,16 +1,6 @@ use std::{ - sync::{Arc, Mutex, mpsc}, - thread, + sync::{Arc, Mutex}, io, - time::Duration, -}; - -use notify::{ - self, - DebouncedEvent, - RecommendedWatcher, - RecursiveMode, - Watcher, }; use crate::{ @@ -19,17 +9,15 @@ use crate::{ vfs::Vfs, session_id::SessionId, rbx_session::RbxSession, + fs_watcher::FsWatcher, }; -const WATCH_TIMEOUT_MS: u64 = 100; - pub struct Session { pub project: Arc, pub session_id: SessionId, pub message_queue: Arc, pub rbx_session: Arc>, - vfs: Arc>, - watchers: Vec, + fs_watcher: FsWatcher, } fn add_sync_points(vfs: &mut Vfs, project_node: &ProjectNode) -> io::Result<()> { @@ -49,15 +37,14 @@ fn add_sync_points(vfs: &mut Vfs, project_node: &ProjectNode) -> io::Result<()> impl Session { pub fn new(project: Project) -> io::Result { + let mut vfs = Vfs::new(); + + add_sync_points(&mut vfs, &project.tree) + .expect("Could not add sync points when starting new Rojo session"); + + let vfs = Arc::new(Mutex::new(vfs)); let project = Arc::new(project); let message_queue = Arc::new(MessageQueue::new()); - let vfs = Arc::new(Mutex::new(Vfs::new())); - - { - let mut vfs = vfs.lock().unwrap(); - add_sync_points(&mut vfs, &project.tree) - .expect("Could not add sync points when starting new Rojo session"); - } let rbx_session = Arc::new(Mutex::new(RbxSession::new( Arc::clone(&project), @@ -65,95 +52,19 @@ impl Session { Arc::clone(&message_queue), ))); - let mut watchers = Vec::new(); - - { - let vfs_temp = vfs.lock().unwrap(); - - for root in vfs_temp.get_roots() { - info!("Watching path {}", root.display()); - - let (watch_tx, watch_rx) = mpsc::channel(); - - let mut watcher = notify::watcher(watch_tx, Duration::from_millis(WATCH_TIMEOUT_MS)).unwrap(); - - watcher.watch(root, RecursiveMode::Recursive) - .expect("Could not watch directory"); - - watchers.push(watcher); - - let vfs = Arc::clone(&vfs); - let rbx_session = Arc::clone(&rbx_session); - - thread::spawn(move || { - loop { - match watch_rx.recv() { - Ok(event) => { - match event { - DebouncedEvent::Create(path) => { - { - let mut vfs = vfs.lock().unwrap(); - vfs.path_created(&path).unwrap(); - } - - { - let mut rbx_session = rbx_session.lock().unwrap(); - rbx_session.path_created(&path); - } - }, - DebouncedEvent::Write(path) => { - { - let mut vfs = vfs.lock().unwrap(); - vfs.path_updated(&path).unwrap(); - } - - { - let mut rbx_session = rbx_session.lock().unwrap(); - rbx_session.path_updated(&path); - } - }, - DebouncedEvent::Remove(path) => { - { - let mut vfs = vfs.lock().unwrap(); - vfs.path_removed(&path).unwrap(); - } - - { - let mut rbx_session = rbx_session.lock().unwrap(); - rbx_session.path_removed(&path); - } - }, - DebouncedEvent::Rename(from_path, to_path) => { - { - let mut vfs = vfs.lock().unwrap(); - vfs.path_moved(&from_path, &to_path).unwrap(); - } - - { - let mut rbx_session = rbx_session.lock().unwrap(); - rbx_session.path_renamed(&from_path, &to_path); - } - }, - _ => {}, - }; - }, - Err(_) => break, - }; - } - info!("Watcher thread stopped"); - }); - } - } + let fs_watcher = FsWatcher::start( + Arc::clone(&vfs), + Arc::clone(&rbx_session), + ); let session_id = SessionId::new(); Ok(Session { - session_id, - rbx_session, project, + session_id, message_queue, - vfs, - watchers, + rbx_session, + fs_watcher, }) }