Skip to content

Commit 132d9cc

Browse files
committed
Skip stale fs store artifacts
The exhaustive filesystem store listing treated leftover temp and trash files as namespace directories after identifying them as non-keys. Skip those artifacts before recursing so migrations can ignore crash leftovers.
1 parent 3d94ac7 commit 132d9cc

2 files changed

Lines changed: 40 additions & 5 deletions

File tree

lightning-persister/src/fs_store/common.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,9 @@ impl FilesystemStoreState {
653653
'primary_loop: for primary_entry in fs::read_dir(prefixed_dest)? {
654654
let primary_entry = primary_entry?;
655655
let primary_path = primary_entry.path();
656+
if dir_entry_is_store_artifact(&primary_path) {
657+
continue 'primary_loop;
658+
}
656659

657660
if dir_entry_is_key(&primary_entry)? {
658661
let primary_namespace = String::new();
@@ -666,6 +669,9 @@ impl FilesystemStoreState {
666669
'secondary_loop: for secondary_entry in fs::read_dir(&primary_path)? {
667670
let secondary_entry = secondary_entry?;
668671
let secondary_path = secondary_entry.path();
672+
if dir_entry_is_store_artifact(&secondary_path) {
673+
continue 'secondary_loop;
674+
}
669675

670676
if dir_entry_is_key(&secondary_entry)? {
671677
let primary_namespace = get_key_from_dir_entry_path(
@@ -683,6 +689,9 @@ impl FilesystemStoreState {
683689
for tertiary_entry in fs::read_dir(&secondary_path)? {
684690
let tertiary_entry = tertiary_entry?;
685691
let tertiary_path = tertiary_entry.path();
692+
if dir_entry_is_store_artifact(&tertiary_path) {
693+
continue;
694+
}
686695

687696
if dir_entry_is_key(&tertiary_entry)? {
688697
let primary_namespace = get_key_from_dir_entry_path(
@@ -720,20 +729,24 @@ impl FilesystemStoreState {
720729
}
721730
}
722731

732+
fn dir_entry_is_store_artifact(path: &Path) -> bool {
733+
path.extension()
734+
.and_then(|ext| ext.to_str())
735+
.map_or(false, |ext| ext == "tmp" || ext == "trash")
736+
}
737+
723738
pub(crate) fn dir_entry_is_key(dir_entry: &fs::DirEntry) -> Result<bool, lightning::io::Error> {
724739
let p = dir_entry.path();
725-
if let Some(ext) = p.extension() {
740+
if dir_entry_is_store_artifact(&p) {
726741
#[cfg(target_os = "windows")]
727742
{
728743
// Clean up any trash files lying around.
729-
if ext == "trash" {
744+
if p.extension().and_then(|ext| ext.to_str()) == Some("trash") {
730745
fs::remove_file(p).ok();
731746
return Ok(false);
732747
}
733748
}
734-
if ext == "tmp" {
735-
return Ok(false);
736-
}
749+
return Ok(false);
737750
}
738751

739752
let file_type = dir_entry.file_type()?;

lightning-persister/src/fs_store/v1.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,28 @@ mod tests {
199199
do_test_data_migration(&mut source_store, &mut target_store);
200200
}
201201

202+
#[test]
203+
fn list_all_keys_skips_leftover_store_artifacts() {
204+
let mut temp_path = std::env::temp_dir();
205+
temp_path.push("test_list_all_keys_skips_leftover_store_artifacts");
206+
let fs_store = FilesystemStore::new(temp_path.clone());
207+
fs_store.write("primary", "secondary", "key", vec![1]).unwrap();
208+
209+
fs::write(temp_path.join("top_level.0.tmp"), b"stale").unwrap();
210+
fs::write(temp_path.join("top_level.0.trash"), b"stale").unwrap();
211+
212+
let primary_path = temp_path.join("primary");
213+
fs::write(primary_path.join("primary_level.0.tmp"), b"stale").unwrap();
214+
fs::write(primary_path.join("primary_level.0.trash"), b"stale").unwrap();
215+
216+
let secondary_path = primary_path.join("secondary");
217+
fs::write(secondary_path.join("secondary_level.0.tmp"), b"stale").unwrap();
218+
fs::write(secondary_path.join("secondary_level.0.trash"), b"stale").unwrap();
219+
220+
let keys = fs_store.list_all_keys().unwrap();
221+
assert_eq!(keys, vec![("primary".to_string(), "secondary".to_string(), "key".to_string())]);
222+
}
223+
202224
#[test]
203225
fn test_if_monitors_is_not_dir() {
204226
let store = FilesystemStore::new("test_monitors_is_not_dir".into());

0 commit comments

Comments
 (0)