diff options
author | Lars Wirzenius <liw@liw.fi> | 2021-04-23 14:22:39 +0300 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2021-04-23 14:22:39 +0300 |
commit | ca61af01ed867e695ceb19b6975354743d6ab14a (patch) | |
tree | 356438510099cb5e130c564e747baf8b3c7107de | |
parent | cd270b969176a11d659ac8cbf81c15e7150b4b22 (diff) | |
download | summain-rs-ca61af01ed867e695ceb19b6975354743d6ab14a.tar.gz |
compute checkksum in blocking thread
-rw-r--r-- | src/bin/summain.rs | 20 | ||||
-rw-r--r-- | src/lib.rs | 34 |
2 files changed, 30 insertions, 24 deletions
diff --git a/src/bin/summain.rs b/src/bin/summain.rs index 2eb4152..2ad110b 100644 --- a/src/bin/summain.rs +++ b/src/bin/summain.rs @@ -17,16 +17,22 @@ async fn async_main() -> anyhow::Result<()> { opt.pathnames[..].sort(); let mut handles = vec![]; - for (i, filename) in opt.pathnames.iter().cloned().enumerate() { - handles.push(tokio::spawn(async move { manifest(i, filename) })); + for filename in opt.pathnames.iter().cloned() { + handles.push(tokio::spawn(async move { manifest(filename) })); } - let mut manifests = vec![]; + let mut sumhandles = vec![]; for h in handles { - manifests.push(h.await?.await?); + let mut m: ManifestEntry = h.await?.await?; + let h = tokio::task::spawn_blocking(move || match m.compute_checksum() { + Err(e) => Err(e), + Ok(_) => Ok(m), + }); + sumhandles.push(h) } - for m in manifests { + for h in sumhandles { + let m: ManifestEntry = h.await??; print!("{}", serde_yaml::to_string(&m)?); } @@ -39,8 +45,8 @@ struct Opt { pathnames: Vec<PathBuf>, } -async fn manifest(i: usize, path: PathBuf) -> anyhow::Result<ManifestEntry> { - ManifestEntry::new(i, &path) +async fn manifest(path: PathBuf) -> anyhow::Result<ManifestEntry> { + ManifestEntry::new(&path) .await .with_context(|| format!("{}", path.display())) } @@ -43,7 +43,10 @@ const BUF_SIZE: usize = 1024 * 1024; #[derive(Serialize, Debug)] pub struct ManifestEntry { #[serde(skip)] - index: usize, + is_regular: bool, + + #[serde(skip)] + filename: PathBuf, path: String, #[serde(with = "mode")] @@ -63,34 +66,36 @@ impl ManifestEntry { /// caller. This function doesn't query the system for it. /// /// The structure can be serialized using serde. - pub async fn new(i: usize, path: &Path) -> std::io::Result<Self> { + pub async fn new(path: &Path) -> std::io::Result<Self> { let m = symlink_metadata(path)?; - let hash = if m.is_file() { - let path = path.to_path_buf(); - Some(file_checksum(path).await?) - } else { - None - }; let target = if m.file_type().is_symlink() { Some(read_link(path)?) } else { None }; Ok(Self { - index: i, + is_regular: m.is_file(), + filename: path.to_path_buf(), path: path.to_string_lossy().into_owned(), mode: m.st_mode(), mtime: m.st_mtime(), mtime_nsec: m.st_mtime_nsec(), nlink: m.st_nlink(), size: if m.is_dir() { None } else { Some(m.st_size()) }, - sha256: hash, + sha256: None, target, }) } + + pub fn compute_checksum(&mut self) -> std::io::Result<()> { + if self.is_regular { + self.sha256 = Some(file_checksum(&self.filename)?); + } + Ok(()) + } } -async fn file_checksum(path: PathBuf) -> std::io::Result<String> { +fn file_checksum(path: &Path) -> std::io::Result<String> { let mut hasher = Sha256::new(); let file = File::open(path)?; @@ -101,17 +106,12 @@ async fn file_checksum(path: PathBuf) -> std::io::Result<String> { if n == 0 { break; } - hasher = tokio::task::spawn_blocking(move || update_checksum(hasher, &buf[..n])).await?; + hasher.update(&buf[..n]); } let hash = hasher.finalize(); Ok(format!("{:x}", hash)) } -fn update_checksum(mut hasher: Sha256, data: &[u8]) -> Sha256 { - hasher.update(data); - hasher -} - mod mode { use serde::{self, Serializer}; |