From 2ae05a6163d8b15f3d8a18a2ab713d1fbd83c505 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 18 Dec 2018 13:18:55 +0300 Subject: [PATCH] vfs crate scaffold --- Cargo.lock | 2 + crates/ra_lsp_server/src/main_loop.rs | 4 +- crates/ra_vfs/Cargo.toml | 3 + crates/ra_vfs/src/io.rs | 117 +++++++++++++------------- crates/ra_vfs/src/lib.rs | 25 +++++- crates/thread_worker/src/lib.rs | 6 +- 6 files changed, 89 insertions(+), 68 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 38307ff69c..c15955f4cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -749,8 +749,10 @@ name = "ra_vfs" version = "0.1.0" dependencies = [ "crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_worker 0.1.0", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index eab82ee859..9d3f83b4c7 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs @@ -88,8 +88,8 @@ pub fn main_loop( drop(pool); log::info!("...threadpool has finished"); - let fs_res = fs_watcher.stop(); - let ws_res = ws_watcher.stop(); + let fs_res = fs_watcher.shutdown(); + let ws_res = ws_watcher.shutdown(); main_res?; fs_res.map_err(|_| format_err!("fs watcher died"))?; diff --git a/crates/ra_vfs/Cargo.toml b/crates/ra_vfs/Cargo.toml index f8d49b3f54..9ce619a777 100644 --- a/crates/ra_vfs/Cargo.toml +++ b/crates/ra_vfs/Cargo.toml @@ -9,3 +9,6 @@ walkdir = "2.2.7" relative-path = "0.4.0" rustc-hash = "1.0" crossbeam-channel = "0.2.4" +log = "0.4.6" + +thread_worker = { path = "../thread_worker" } diff --git a/crates/ra_vfs/src/io.rs b/crates/ra_vfs/src/io.rs index f90fe0e848..ce3271d48b 100644 --- a/crates/ra_vfs/src/io.rs +++ b/crates/ra_vfs/src/io.rs @@ -6,67 +6,64 @@ use std::{ use walkdir::WalkDir; use crossbeam_channel::{Sender, Receiver}; +use thread_worker::{WorkerHandle, Worker}; -pub(crate) fn start_io() -> (JoinHandle<(), Sender<()>, Receiver()>) {} +#[derive(Debug)] +pub struct FileEvent { + pub path: PathBuf, + pub kind: FileEventKind, +} -// use crate::thread_watcher::{ThreadWatcher, Worker}; +#[derive(Debug)] +pub enum FileEventKind { + Add(String), +} -// #[derive(Debug)] -// pub struct FileEvent { -// pub path: PathBuf, -// pub kind: FileEventKind, -// } +pub fn start() -> (Worker)>, WorkerHandle) { + thread_worker::spawn::), _>( + "vfs", + 128, + |input_receiver, output_sender| { + input_receiver + .map(|path| { + log::debug!("loading {} ...", path.as_path().display()); + let events = load_root(path.as_path()); + log::debug!("... loaded {}", path.as_path().display()); + (path, events) + }) + .for_each(|it| output_sender.send(it)) + }, + ) +} -// #[derive(Debug)] -// pub enum FileEventKind { -// Add(String), -// } - -// pub fn roots_loader() -> (Worker)>, ThreadWatcher) { -// Worker::)>::spawn( -// "roots loader", -// 128, -// |input_receiver, output_sender| { -// input_receiver -// .map(|path| { -// log::debug!("loading {} ...", path.as_path().display()); -// let events = load_root(path.as_path()); -// log::debug!("... loaded {}", path.as_path().display()); -// (path, events) -// }) -// .for_each(|it| output_sender.send(it)) -// }, -// ) -// } - -// fn load_root(path: &Path) -> Vec { -// let mut res = Vec::new(); -// for entry in WalkDir::new(path) { -// let entry = match entry { -// Ok(entry) => entry, -// Err(e) => { -// log::warn!("watcher error: {}", e); -// continue; -// } -// }; -// if !entry.file_type().is_file() { -// continue; -// } -// let path = entry.path(); -// if path.extension().and_then(|os| os.to_str()) != Some("rs") { -// continue; -// } -// let text = match fs::read_to_string(path) { -// Ok(text) => text, -// Err(e) => { -// log::warn!("watcher error: {}", e); -// continue; -// } -// }; -// res.push(FileEvent { -// path: path.to_owned(), -// kind: FileEventKind::Add(text), -// }) -// } -// res -// } +fn load_root(path: &Path) -> Vec { + let mut res = Vec::new(); + for entry in WalkDir::new(path) { + let entry = match entry { + Ok(entry) => entry, + Err(e) => { + log::warn!("watcher error: {}", e); + continue; + } + }; + if !entry.file_type().is_file() { + continue; + } + let path = entry.path(); + if path.extension().and_then(|os| os.to_str()) != Some("rs") { + continue; + } + let text = match fs::read_to_string(path) { + Ok(text) => text, + Err(e) => { + log::warn!("watcher error: {}", e); + continue; + } + }; + res.push(FileEvent { + path: path.to_owned(), + kind: FileEventKind::Add(text), + }) + } + res +} diff --git a/crates/ra_vfs/src/lib.rs b/crates/ra_vfs/src/lib.rs index 8f6abadb77..b80c12058d 100644 --- a/crates/ra_vfs/src/lib.rs +++ b/crates/ra_vfs/src/lib.rs @@ -15,6 +15,7 @@ mod arena; mod io; use std::{ + thread, cmp::Reverse, path::{Path, PathBuf}, ffi::OsStr, @@ -22,7 +23,12 @@ use std::{ }; use relative_path::RelativePathBuf; -use crate::arena::{ArenaId, Arena}; +use thread_worker::{WorkerHandle, Worker}; + +use crate::{ + arena::{ArenaId, Arena}, + io::FileEvent, +}; /// `RootFilter` is a predicate that checks if a file can belong to a root struct RootFilter { @@ -76,16 +82,24 @@ struct VfsFileData { text: Arc, } -#[derive(Default)] struct Vfs { roots: Arena, files: Arena, // pending_changes: Vec, + worker: Worker)>, + worker_handle: WorkerHandle, } impl Vfs { pub fn new(mut roots: Vec) -> Vfs { - let mut res = Vfs::default(); + let (worker, worker_handle) = io::start(); + + let mut res = Vfs { + roots: Arena::default(), + files: Arena::default(), + worker, + worker_handle, + }; roots.sort_by_key(|it| Reverse(it.as_os_str().len())); @@ -104,6 +118,11 @@ impl Vfs { pub fn commit_changes(&mut self) -> Vec { unimplemented!() } + + pub fn shutdown(self) -> thread::Result<()> { + let _ = self.worker.shutdown(); + self.worker_handle.shutdown() + } } #[derive(Debug, Clone)] diff --git a/crates/thread_worker/src/lib.rs b/crates/thread_worker/src/lib.rs index e558559ef2..24d7fcce1d 100644 --- a/crates/thread_worker/src/lib.rs +++ b/crates/thread_worker/src/lib.rs @@ -30,7 +30,7 @@ where impl Worker { /// Stops the worker. Returns the message receiver to fetch results which /// have become ready before the worker is stopped. - pub fn stop(self) -> Receiver { + pub fn shutdown(self) -> Receiver { self.out } @@ -45,11 +45,11 @@ impl WorkerHandle { WorkerHandle { name, thread, - bomb: DropBomb::new(format!("WorkerHandle {} was not stopped", name)), + bomb: DropBomb::new(format!("WorkerHandle {} was not shutdown", name)), } } - pub fn stop(mut self) -> thread::Result<()> { + pub fn shutdown(mut self) -> thread::Result<()> { log::info!("waiting for {} to finish ...", self.name); let name = self.name; self.bomb.defuse();