mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-14 19:27:01 -04:00
Merge PR #1076
This commit is contained in:
commit
a681a3c667
2 files changed
+36
-8
No files matched your search
@@ -94,20 +94,20 @@ impl DiskCache {
|
||||
if std::fs::create_dir_all(parent).is_err() {
|
||||
return;
|
||||
}
|
||||
// know the current total before adding (the first scan must not count this file twice)
|
||||
let _ = self.size();
|
||||
// Serialize the file replacement and its size accounting. A repeated render of
|
||||
// the same key replaces its JPEG; it must not count as another cache entry.
|
||||
let mut total = self.total.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let used = total.get_or_insert_with(|| self.scan().iter().map(|f| f.1).sum());
|
||||
let old_len = std::fs::metadata(&p).map_or(0, |m| m.len());
|
||||
let tmp = p.with_extension(format!("tmp{:?}", std::thread::current().id()).replace(['(', ')'], ""));
|
||||
if std::fs::write(&tmp, &bytes).is_err() || std::fs::rename(&tmp, &p).is_err() {
|
||||
let _ = std::fs::remove_file(&tmp);
|
||||
return;
|
||||
}
|
||||
self.writes.fetch_add(1, Ordering::Relaxed);
|
||||
let over = {
|
||||
let mut t = self.total.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let total = t.get_or_insert(0);
|
||||
*total += bytes.len() as u64;
|
||||
*total > self.budget()
|
||||
};
|
||||
*used = used.saturating_sub(old_len).saturating_add(bytes.len() as u64);
|
||||
let over = *used > self.budget();
|
||||
drop(total);
|
||||
if over {
|
||||
self.prune();
|
||||
}
|
||||
|
||||
@@ -123,6 +123,34 @@ fn disk_cache_roundtrip_and_prune() {
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn disk_cache_overwrite_accounts_for_replaced_jpeg_only_once() {
|
||||
let dir = temp_dir("overwrite");
|
||||
let cache = DiskCache::new(&dir, 1 << 20);
|
||||
let (a, b) = (hash_bytes(b"overwrite-a"), hash_bytes(b"overwrite-b"));
|
||||
let first = gradient(80, 60, 4);
|
||||
cache.put(a, &first);
|
||||
cache.put(b, &gradient(80, 60, 7));
|
||||
let initial = cache.size();
|
||||
|
||||
// Re-rendering the same key used to double-count bytes although the
|
||||
// replacement occupied exactly the same pathname on disk.
|
||||
cache.put(a, &first);
|
||||
assert_eq!(cache.size(), initial);
|
||||
assert!(cache.get(b).is_some());
|
||||
|
||||
// A replacement with a different encoded size must also update the total.
|
||||
cache.put(a, &gradient(120, 90, 9));
|
||||
let path = |key: Hash128| {
|
||||
let hex = key.to_string();
|
||||
dir.join(&hex[..2]).join(format!("{hex}.jpg"))
|
||||
};
|
||||
let actual = std::fs::metadata(path(a)).unwrap().len() + std::fs::metadata(path(b)).unwrap().len();
|
||||
assert_eq!(cache.size(), actual);
|
||||
cache.clear();
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn preview_cache_memory_then_disk() {
|
||||
let dir = temp_dir("pc");
|
||||
|
||||
Reference in new issue
Block a user