From 7885976b14748d9db4017118f6094e51a95c7cd7 Mon Sep 17 00:00:00 2001 From: Johnathan Sharratt Date: Tue, 29 Aug 2023 16:11:34 +1000 Subject: [PATCH] Fixed a blocking issue inside an async and added sha256 caching of webc files --- .../runtime/package_loader/builtin_loader.rs | 2 +- .../src/runtime/resolver/filesystem_source.rs | 5 ++-- lib/wasix/src/runtime/resolver/inputs.rs | 25 +++++++++++++++---- lib/wasix/src/runtime/resolver/web_source.rs | 5 ++-- 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/lib/wasix/src/runtime/package_loader/builtin_loader.rs b/lib/wasix/src/runtime/package_loader/builtin_loader.rs index c559c030050..0f70b4c4356 100644 --- a/lib/wasix/src/runtime/package_loader/builtin_loader.rs +++ b/lib/wasix/src/runtime/package_loader/builtin_loader.rs @@ -239,7 +239,7 @@ impl FileSystemCache { async fn lookup(&self, hash: &WebcHash) -> Result, Error> { let path = self.path(hash); - match Container::from_disk(&path) { + match tokio::task::block_in_place(|| Container::from_disk(&path)) { Ok(c) => Ok(Some(c)), Err(ContainerError::Open { error, .. }) | Err(ContainerError::Read { error, .. }) diff --git a/lib/wasix/src/runtime/resolver/filesystem_source.rs b/lib/wasix/src/runtime/resolver/filesystem_source.rs index 9be00fac897..56deefcaf2e 100644 --- a/lib/wasix/src/runtime/resolver/filesystem_source.rs +++ b/lib/wasix/src/runtime/resolver/filesystem_source.rs @@ -23,10 +23,9 @@ impl Source for FileSystemSource { _ => return Err(QueryError::Unsupported), }; - // FIXME: These two operations will block - let webc_sha256 = WebcHash::for_file(&path) + let webc_sha256 = tokio::task::block_in_place(|| WebcHash::for_file(&path)) .with_context(|| format!("Unable to hash \"{}\"", path.display()))?; - let container = Container::from_disk(&path) + let container = tokio::task::block_in_place(|| Container::from_disk(&path)) .with_context(|| format!("Unable to parse \"{}\"", path.display()))?; let url = crate::runtime::resolver::utils::url_from_file_path(&path) diff --git a/lib/wasix/src/runtime/resolver/inputs.rs b/lib/wasix/src/runtime/resolver/inputs.rs index 8fb2b7f8cb7..8a80964269f 100644 --- a/lib/wasix/src/runtime/resolver/inputs.rs +++ b/lib/wasix/src/runtime/resolver/inputs.rs @@ -1,9 +1,7 @@ use std::{ fmt::{self, Display, Formatter}, - fs::File, - io::{BufRead, BufReader}, path::{Path, PathBuf}, - str::FromStr, + str::FromStr, fs::File, io::{BufReader, BufRead, Read}, }; use anyhow::{Context, Error}; @@ -344,7 +342,19 @@ impl WebcHash { Ok(Self(hash)) } - pub fn for_file(path: impl AsRef) -> Result { + pub fn for_file(path: &PathBuf) -> Result { + // check for a hash at the file location + let path_hash = path.join(".sha256"); + if let Ok(mut file) = File::open(&path_hash) { + let mut hash = Vec::new(); + if let Ok(amt) = file.read_to_end(&mut hash) { + if amt == 32 { + return Ok(WebcHash::from_bytes(hash[0..32].try_into().unwrap())); + } + } + } + + // compute the hash let mut hasher = Sha256::default(); let mut reader = BufReader::new(File::open(path)?); @@ -359,7 +369,12 @@ impl WebcHash { } let hash = hasher.finalize().into(); - Ok(WebcHash::from_bytes(hash)) + + // write the cache of the hash to the file system + std::fs::write(path_hash, hash).ok(); + let hash = WebcHash::from_bytes(hash); + + Ok(hash) } /// Generate a new [`WebcHash`] based on the SHA-256 hash of some bytes. diff --git a/lib/wasix/src/runtime/resolver/web_source.rs b/lib/wasix/src/runtime/resolver/web_source.rs index c5234368114..e93fa3b7e84 100644 --- a/lib/wasix/src/runtime/resolver/web_source.rs +++ b/lib/wasix/src/runtime/resolver/web_source.rs @@ -240,13 +240,12 @@ impl Source for WebSource { .await .context("Unable to get the locally cached file")?; - // FIXME: this will block - let webc_sha256 = WebcHash::for_file(&local_path) + let webc_sha256 = tokio::task::block_in_place(|| WebcHash::for_file(&local_path)) .with_context(|| format!("Unable to hash \"{}\"", local_path.display()))?; // Note: We want to use Container::from_disk() rather than the bytes // our HTTP client gave us because then we can use memory-mapped files - let container = Container::from_disk(&local_path) + let container = tokio::task::block_in_place(|| Container::from_disk(&local_path)) .with_context(|| format!("Unable to load \"{}\"", local_path.display()))?; let pkg = PackageInfo::from_manifest(container.manifest()) .context("Unable to determine the package's metadata")?;