From: Chris Mikkelson Date: Thu, 12 Sep 2024 23:36:50 +0000 (-0500) Subject: Refactor fileset X-Git-Url: https://git.mikk.net/?a=commitdiff_plain;h=75e7f2d50ac5d41777b7dd9454a1c06c6afa4146;p=mtbl-rs Refactor fileset Implement lazy loading on first use and error reporting. --- diff --git a/src/fileset.rs b/src/fileset.rs index ee5e645..36a8ea4 100644 --- a/src/fileset.rs +++ b/src/fileset.rs @@ -7,14 +7,13 @@ use crate::Result; use std::collections::HashMap; use std::path::{Path, PathBuf}; use std::sync::Mutex; -use std::time::{Duration, Instant}; +use std::time::{Duration, SystemTime}; pub struct Fileset { fs_path: PathBuf, - last_reload: Instant, + last_reload: SystemTime, reload_interval: Duration, - readers: Mutex, Instant)>>, - merger: Mutex>>>, + readers: Mutex, SystemTime)>>, } fn load_fs_file(f: impl AsRef) -> Result> { @@ -26,50 +25,67 @@ fn load_fs_file(f: impl AsRef) -> Result> { impl Fileset { pub fn new(fname: impl AsRef) -> Self { - let mut res = Self { + Self { fs_path: PathBuf::new().with_file_name(fname.as_ref()), - last_reload: Instant::now(), + last_reload: SystemTime::now() - Duration::new(2, 0), reload_interval: Duration::new(1, 0), readers: Mutex::new(HashMap::new()), - merger: Mutex::new(None), - }; - res.force_reload(); - res + } } - fn force_reload(&mut self) { - let files = load_fs_file(&self.fs_path).unwrap(); - let now = Instant::now(); + pub fn reload_interval(mut self, d: Duration) -> Self { + self.reload_interval = d; + self + } - let mut readers = self.readers.lock().unwrap(); - if self.last_reload > now { - return; + fn reload(&mut self) -> Result<()> { + let now = SystemTime::now(); + if now.duration_since(self.last_reload)? < self.reload_interval { + return Ok(()); } - files - .iter() - .map(|f| match readers.get(f) { + + let mdata = std::fs::metadata(&self.fs_path)?; + if !mdata.is_file() { + return Err(format!("{:#?} is not a regular file", &self.fs_path).into()); + } + + if mdata.modified()? <= self.last_reload { + self.last_reload = now; + return Ok(()); + } + + let files = load_fs_file(&self.fs_path)?; + + let mut readers = self.readers.lock().unwrap(); + files.iter().for_each(|f| { + match readers.get(f) { Some(_) => None, None => readers.insert(f.to_path_buf(), (crate::reader::from_file(f), now)), - }) - .count(); // must use + }; + }); let clean = readers .iter() .filter(|(_, (_, t))| *t < now) .map(|(f, _)| f.clone()) .collect::>(); + clean.iter().for_each(|f| { readers.remove(f); () }); - let mut merger = self.merger.lock().unwrap(); - merger.replace(Merger::from(readers.iter().map(|(_, (r, _))| r.clone()))); + self.last_reload = now; + Ok(()) } - fn reload(&mut self) { - if Instant::now().duration_since(self.last_reload) > self.reload_interval { - self.force_reload(); - } + pub fn readers(&mut self) -> Result>> { + self.reload()?; + let readers = self.readers.lock().unwrap(); + Ok(readers.iter().map(|(_, (r, _))| r.clone()).collect()) + } + + pub fn merger(&mut self) -> Result>> { + Ok(Merger::from(self.readers()?)) } }