Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions rustfmt.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1 @@
unstable_features = true

group_imports = "StdExternalCrate"

reorder_imports = true

imports_granularity = "Crate"
74 changes: 52 additions & 22 deletions src/internal/pack/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,41 @@ pub struct Caches {
complete_signal: Arc<AtomicBool>,
}

fn create_cache_dir(path: &Path) -> io::Result<()> {
fs::create_dir_all(path).map_err(|err| {
io::Error::new(
err.kind(),
format!(
"failed to create pack cache directory `{}`: {err}",
path.display()
),
)
})
}

impl Caches {
pub(crate) fn try_new(
mem_size: Option<usize>,
tmp_path: PathBuf,
thread_num: usize,
) -> io::Result<Self> {
// `None` means no limit, so no need to create the tmp dir
if mem_size.is_some() {
create_cache_dir(&tmp_path)?;
}

Ok(Caches {
map_offset: DashMap::new(),
hash_set: DashSet::new(),
lru_cache: Mutex::new(LruCache::new(mem_size.unwrap_or(usize::MAX))),
mem_size,
tmp_path,
path_prefixes: [const { Once::new() }; 256],
pool: Arc::new(ThreadPool::new(thread_num)),
complete_signal: Arc::new(AtomicBool::new(false)),
})
}

/// only get object from memory, not from tmp file
fn try_get(&self, hash: ObjectHash) -> Option<Arc<CacheObject>> {
let mut map = self.lru_cache.lock().unwrap();
Expand Down Expand Up @@ -115,7 +149,7 @@ impl Caches {
self.path_prefixes[hash.as_ref()[0] as usize].call_once(|| {
// Check if the directory exists, if not, create it
if !path.exists() {
fs::create_dir_all(&path).unwrap();
create_cache_dir(&path).unwrap_or_else(|err| panic!("{err}"));
}
});
path.push(hash_str);
Expand Down Expand Up @@ -147,7 +181,13 @@ impl Caches {
pub fn remove_tmp_dir(&self) {
time_it!("Remove tmp dir", {
if self.tmp_path.exists() {
fs::remove_dir_all(&self.tmp_path).unwrap(); //very slow
if let Err(err) = fs::remove_dir_all(&self.tmp_path) {
tracing::warn!(
"failed to remove pack cache temp directory `{}`: {err}",
self.tmp_path.display()
);
return;
}
// Try to remove parent .cache_temp directory if it's empty
if let Some(parent) = self.tmp_path.parent() {
let is_cache_temp = parent
Expand All @@ -173,21 +213,7 @@ impl _Cache for Caches {
where
Self: Sized,
{
// `None` means no limit, so no need to create the tmp dir
if mem_size.is_some() {
fs::create_dir_all(&tmp_path).unwrap();
}

Caches {
map_offset: DashMap::new(),
hash_set: DashSet::new(),
lru_cache: Mutex::new(LruCache::new(mem_size.unwrap_or(usize::MAX))),
mem_size,
tmp_path,
path_prefixes: [const { Once::new() }; 256],
pool: Arc::new(ThreadPool::new(thread_num)),
complete_signal: Arc::new(AtomicBool::new(false)),
}
Caches::try_new(mem_size, tmp_path, thread_num).unwrap_or_else(|err| panic!("{err}"))
}

fn get_hash(&self, offset: usize) -> Option<ObjectHash> {
Expand Down Expand Up @@ -267,7 +293,7 @@ impl _Cache for Caches {

#[cfg(test)]
mod test {
use std::{env, sync::Arc, thread};
use std::{sync::Arc, thread};

use super::*;
use crate::{
Expand All @@ -287,6 +313,12 @@ mod test {
}
}

fn test_tmp_path(name: &str) -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("target/test-cache")
.join(name)
}

/// test single-threaded cache behavior with different hash kinds and capacities
#[test]
fn test_cache_single_thread() {
Expand All @@ -307,8 +339,7 @@ mod test {
),
] {
let _guard = set_hash_kind_for_test(kind);
let source = PathBuf::from(env::current_dir().unwrap().parent().unwrap());
let tmp_path = source.clone().join(tmp_dir);
let tmp_path = test_tmp_path(tmp_dir);
if tmp_path.exists() {
fs::remove_dir_all(&tmp_path).unwrap();
}
Expand Down Expand Up @@ -345,8 +376,7 @@ mod test {
/// consider the multi-threaded scenario where different threads use different hash kinds
#[test]
fn test_cache_multi_thread_mixed_hash_kinds() {
let base = PathBuf::from(env::current_dir().unwrap().parent().unwrap());
let tmp_path = base.join("tests/.cache_tmp_mixed");
let tmp_path = test_tmp_path("mixed");
if tmp_path.exists() {
fs::remove_dir_all(&tmp_path).unwrap();
}
Expand Down
Loading
Loading