From c8e6ea51bba91e861898bc8c3ebf7b62868bdaad Mon Sep 17 00:00:00 2001 From: rabite Date: Mon, 27 Jan 2020 17:39:42 +0100 Subject: further speed up creation of Files --- src/file_browser.rs | 67 ++++++++-------- src/files.rs | 215 ++++++++-------------------------------------------- src/listview.rs | 4 +- 3 files changed, 65 insertions(+), 221 deletions(-) diff --git a/src/file_browser.rs b/src/file_browser.rs index 1ed031e..9361dce 100644 --- a/src/file_browser.rs +++ b/src/file_browser.rs @@ -476,22 +476,20 @@ impl FileBrowser { self.prev_cwd = Some(self.cwd.clone()); self.cwd = dir.clone(); + let file_source = FileSource::Path(self.cwd.clone()); - let main_async_widget = self.main_async_widget_mut()?; - main_async_widget.change_to(move |stale: &Stale, core| { - let (selected_file, files) = cache.get_files(&dir, stale.clone())?; - let files = files.run_sync()?; + let main_async_widget = self.main_async_widget_mut()?; + main_async_widget.change_to(move |stale: &Stale, core| { + let view = ListView::builder(core, file_source) + .meta_all() + .prerender() + .with_cache(cache) + .with_stale(stale.clone()) + .build()?; - let mut list = ListView::new(&core, files); + Ok(view) + }).log(); - list.content.meta_set_fresh().log(); - list.content.meta_all(); - - if let Some(file) = selected_file { - list.select_file(&file); - } - Ok(list) - }).log(); if let Ok(grand_parent) = self.cwd()?.parent_as_file() { self.left_widget_goto(&grand_parent).log(); @@ -505,27 +503,28 @@ impl FileBrowser { } pub fn left_widget_goto(&mut self, dir: &File) -> HResult<()> { - // Check if we're in the correct directory already and return - // if we are - let left_dir = &self.left_widget()?.content.directory; - if self.left_widget().is_ok() && left_dir == dir { - return Ok(()); - } - - let cache = self.fs_cache.clone(); - let dir = dir.clone(); - - let left_async_widget = self.left_async_widget_mut()?; - left_async_widget.change_to(move |stale, core| { - let cached_files = cache.get_files(&dir, stale.clone())?; - let (_, files) = cached_files; - - let files = files.run_sync()?; - - let list = ListView::new(&core, files); - Ok(list) - })?; - Ok(()) + // Check if we're in the correct directory already and return + // if we are + let left_dir = &self.left_widget()?.content.directory; + if self.left_widget().is_ok() && left_dir == dir { + return Ok(()); + } + + let cache = self.fs_cache.clone(); + let file_source = FileSource::Path(dir.clone()); + let left_async_widget = self.left_async_widget_mut()?; + left_async_widget.change_to(move |stale, core| { + let view = ListView::builder(core, file_source) + .meta_all() + .prerender() + .with_cache(cache) + .with_stale(stale.clone()) + .build()?; + + Ok(view) + }).log(); + + Ok(()) } pub fn go_back(&mut self) -> HResult<()> { diff --git a/src/files.rs b/src/files.rs index 90e2bb5..25592de 100644 --- a/src/files.rs +++ b/src/files.rs @@ -344,8 +344,7 @@ impl Files { None } else { let file = File::new_from_direntry(file, - Some(dirty_meta.clone()), - stale.clone()); + Some(dirty_meta.clone())); Some(file) } }) @@ -470,7 +469,7 @@ impl Files { } match (a.meta(), b.meta()) { - (Ok(a_meta), Ok(b_meta)) => { + (Some(a_meta), Some(b_meta)) => { match a_meta.size() == b_meta.size() { true => compare_str(&b.name, &a.name), false => b_meta.size() @@ -496,7 +495,7 @@ impl Files { } match (a.meta(), b.meta()) { - (Ok(a_meta), Ok(b_meta)) => { + (Some(a_meta), Some(b_meta)) => { match a_meta.mtime() == b_meta.mtime() { true => compare_str(&b.name, &a.name), false => b_meta.mtime() @@ -621,59 +620,22 @@ impl Files { } pub fn meta_all_sync(&mut self) -> HResult<()> { + let mut same = true; + for file in self.iter_files_mut() { if !file.meta_processed { file.meta_sync().log(); + same = false; } } - self.set_dirty(); - Ok(()) - } - - pub fn meta_all(&mut self) { - let len = self.len(); - self.meta_upto(len, None); - self.dirty_meta.set_dirty(); - self.meta_set_fresh().log(); - } - - pub fn meta_upto(&mut self, to: usize, sender: Option>) { - let meta_files = if self.meta_upto > Some(to) { - self.meta_upto.unwrap() - } else { - if to > self.len() { - self.len() - } else { - to - } - }; - - if self.meta_upto >= Some(meta_files) && !self.dirty_meta.is_dirty() { return } - - self.set_dirty(); - self.dirty_meta.set_clean(); - let meta_pool = make_pool(sender.clone()); - - for file in self.iter_files_mut() - .take(meta_files) { - if !file.meta_processed { - file.take_meta(&meta_pool).ok(); - } - if file.is_dir() { - file.take_dirsize(&meta_pool).ok(); - } + if !same { + self.set_dirty(); } - self.meta_upto = Some(meta_files); - } - - pub fn meta_set_fresh(&self) -> HResult<()> { - self.iter_files().nth(0)?.meta.set_fresh()?; Ok(()) } - pub fn set_filter(&mut self, filter: Option) { self.filter = filter; @@ -771,10 +733,10 @@ pub struct File { pub path: PathBuf, pub hidden: bool, pub kind: Kind, - pub dirsize: Option>, + pub dirsize: Option, pub target: Option, pub color: Option, - pub meta: Async, + pub meta: Option, pub dirty_meta: Option, pub meta_processed: bool, pub selected: bool, @@ -787,19 +749,15 @@ impl File { path: PathBuf, dirty_meta: Option) -> File { let hidden = name.starts_with("."); - let meta = File::make_async_meta(&path, dirty_meta.clone(), None); - let dirsize = if path.is_dir() { - Some(File::make_async_dirsize(&path, dirty_meta.clone(), None)) - } else { None }; File { name: name.to_string(), hidden: hidden, kind: if path.is_dir() { Kind::Directory } else { Kind::File }, path: path, - dirsize: dirsize, + dirsize: None, target: None, - meta: meta, + meta: None, meta_processed: false, dirty_meta: dirty_meta, color: None, @@ -810,26 +768,17 @@ impl File { pub fn new_with_stale(name: &str, path: PathBuf, - dirty_meta: Option, - stale: Stale) -> File { + dirty_meta: Option) -> File { let hidden = name.starts_with("."); - let meta = File::make_async_meta(&path, - dirty_meta.clone(), - Some(stale.clone())); - let dirsize = if path.is_dir() { - Some(File::make_async_dirsize(&path, - dirty_meta.clone(), - Some(stale))) - } else { None }; File { name: name.to_string(), hidden: hidden, kind: if path.is_dir() { Kind::Directory } else { Kind::File }, path: path, - dirsize: dirsize, + dirsize: None, target: None, - meta: meta, + meta: None, meta_processed: false, dirty_meta: dirty_meta, color: None, @@ -839,8 +788,7 @@ impl File { } pub fn new_from_direntry(direntry: std::fs::DirEntry, - dirty_meta: Option, - stale: Stale) -> File { + dirty_meta: Option) -> File { let path = direntry.path(); let name = direntry.file_name() .to_string_lossy() @@ -855,25 +803,14 @@ impl File { _ => Kind::Placeholder }; - let meta = File::make_async_meta(&path, - dirty_meta.clone(), - Some(stale.clone())); - - let dirsize = match kind { - Kind::Directory => Some(File::make_async_dirsize(&path, - dirty_meta.clone(), - Some(stale.clone()))), - _ => None - }; - File { name: name, hidden: hidden, kind: kind, path: path, - dirsize: dirsize, + dirsize: None, target: None, - meta: meta, + meta: None, meta_processed: false, dirty_meta: dirty_meta, color: None, @@ -907,104 +844,24 @@ impl File { } pub fn meta_sync(&mut self) -> HResult<()> { - let stale = self.meta.get_stale(); - let meta = std::fs::metadata(&self.path)?; - self.meta = Async::new_with_value(meta); - self.meta.put_stale(stale); + let meta = std::fs::symlink_metadata(&self.path)?; + self.meta = Some(meta); self.process_meta().log(); if self.is_dir() { - let dirsize = self.dirsize - .take() - .map(|s| s.run_sync())??; - self.dirsize = Some(Async::new_with_value(dirsize)); - } - - Ok(()) - } - - pub fn make_async_meta(path: &PathBuf, - dirty_meta: Option, - stale_preview: Option) -> Async { - let path = path.clone(); - - let mut meta = Async::new(move |stale: &Stale| { - if stale.is_stale()? { HError::stale()? } - Ok(std::fs::symlink_metadata(&path)?) - }); - - stale_preview.map(|s| meta.put_stale(s)); - - dirty_meta.map(|mut d| - meta.on_ready(move |_,_| { - d.set_dirty(); - - Ok(()) - }).log() - ); - meta - } - - pub fn make_async_dirsize(path: &PathBuf, - dirty_meta: Option, - stale_preview: Option) -> Async { - let path = path.clone(); - - let mut dirsize = Async::new(move |stale: &Stale| { - if stale.is_stale()? { HError::stale()? } - Ok(std::fs::read_dir(&path)?.count()) - }); - - stale_preview.map(|s| dirsize.put_stale(s)); - - dirty_meta.map(|mut d| - dirsize.on_ready(move |_,_| { - d.set_dirty(); - - Ok(()) - }).log() - ); - dirsize - } - - pub fn meta(&self) -> HResult<&Metadata> { - Ok(self.meta.get()?) - } - - fn take_dirsize(&mut self, - pool: &ThreadPool) -> HResult<()> { - let dirsize = self.dirsize.as_mut()?; - if let Ok(_) = dirsize.value { return Ok(()) } - - if !dirsize.is_running() && !dirsize.is_ready() { - dirsize.run_pooled(Some(&*pool))?; - } - - if dirsize.is_ready() { - dirsize.pull_async()?; + let dirsize = std::fs::read_dir(&self.path)?.count(); + self.dirsize = Some(dirsize); } Ok(()) } - pub fn take_meta(&mut self, - pool: &ThreadPool) -> HResult<()> { - if self.meta_processed { return Ok(()) } - - if !self.meta.is_running() && !self.meta.is_ready() { - self.meta.run_pooled(Some(&*pool))?; - } - - if self.meta.is_ready() { - self.meta.pull_async()?; - self.process_meta()?; - } - - Ok(()) + pub fn meta(&self) -> Option<&Metadata> { + self.meta.as_ref() } pub fn process_meta(&mut self) -> HResult<()> { - if let Ok(meta) = self.meta.get() { + if let Some(ref meta) = self.meta { let color = self.get_color(&meta); let target = if meta.file_type().is_symlink() { self.path.read_link().ok() @@ -1019,18 +876,7 @@ impl File { pub fn reload_meta(&mut self) -> HResult<()> { self.meta_processed = false; - self.meta = File::make_async_meta(&self.path, - self.dirty_meta.clone(), - None); - self.meta.run()?; - - if self.dirsize.is_some() { - self.dirsize = Some(File::make_async_dirsize(&self.path, - self.dirty_meta.clone(), - None)); - self.dirsize.as_mut()?.run()?; - } - Ok(()) + self.meta_sync() } fn get_color(&self, meta: &std::fs::Metadata) -> Option { @@ -1042,7 +888,7 @@ impl File { pub fn calculate_size(&self) -> HResult<(u32, &str)> { if let Some(ref dirsize) = self.dirsize { - return Ok((*dirsize.value.as_ref().unwrap_or(&0) as u32, "")) + return Ok((*dirsize as u32, "")) } @@ -1073,7 +919,6 @@ impl File { // Fix crash in tree_magic when called on non-regular file // Also fix crash when a file doesn't exist any more self.meta() - .ok() .and_then(|meta| { if meta.is_file() && self.path.exists() { let mime = tree_magic::from_filepath(&self.path); @@ -1239,7 +1084,7 @@ impl File { } pub fn pretty_user(&self) -> Option { - if self.meta().is_err() { return None } + if self.meta().is_none() { return None } let uid = self.meta().unwrap().uid(); let file_user = users::get_user_by_uid(uid)?; let cur_user = users::get_current_username()?; @@ -1252,7 +1097,7 @@ impl File { } pub fn pretty_group(&self) -> Option { - if self.meta().is_err() { return None } + if self.meta().is_none() { return None } let gid = self.meta().unwrap().gid(); let file_group = users::get_group_by_gid(gid)?; let cur_group = users::get_current_groupname()?; @@ -1265,7 +1110,7 @@ impl File { } pub fn pretty_mtime(&self) -> Option { - if self.meta().is_err() { return None } + if self.meta().is_none() { return None } let time: chrono::DateTime = chrono::Local.timestamp(self.meta().unwrap().mtime(), 0); Some(time.format("%F %R").to_string()) diff --git a/src/listview.rs b/src/listview.rs index 3a70820..4222787 100644 --- a/src/listview.rs +++ b/src/listview.rs @@ -108,7 +108,7 @@ impl Listable for ListView { .cloned() .unwrap_or_default(); - if !file.meta.value.is_ok() { + if file.meta.is_none() { file.meta_sync().log(); } @@ -311,7 +311,7 @@ impl FileListBuilder { pub fn build(self) -> HResult> { let c = &self.cache; let s = self.stale.clone(); - let mut files = match self.source { + let files = match self.source { FileSource::Files(f) => Ok(f), FileSource::Path(f) => { c.as_ref() -- cgit v1.2.3