Break out file watching into FsWatcher object

This commit is contained in:
Lucien Greathouse
2018-11-17 13:46:56 -08:00
parent 729ab25581
commit c8bb9bf2e9
3 changed files with 135 additions and 105 deletions

118
server/src/fs_watcher.rs Normal file
View File

@@ -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<Vfs>, rbx_session: &Mutex<RbxSession>, 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<RecommendedWatcher>,
}
impl FsWatcher {
pub fn start(vfs: Arc<Mutex<Vfs>>, rbx_session: Arc<Mutex<RbxSession>>) -> 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,
}
}
}

View File

@@ -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;

View File

@@ -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<Project>,
pub session_id: SessionId,
pub message_queue: Arc<MessageQueue>,
pub rbx_session: Arc<Mutex<RbxSession>>,
vfs: Arc<Mutex<Vfs>>,
watchers: Vec<RecommendedWatcher>,
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<Session> {
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,
})
}