From b75d953ed3c3af1de67dc7cba2d23ba6f70e82fb Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Wed, 11 Dec 2024 16:12:49 +0100 Subject: [PATCH] Implement `MigratableKVStore` for `FilesystemStore` We implement the new interface on `FilesystemStore`, in particular `list_all_keys`. --- lightning-persister/src/fs_store.rs | 70 ++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/lightning-persister/src/fs_store.rs b/lightning-persister/src/fs_store.rs index 73f2685db21..e15ba539d0a 100644 --- a/lightning-persister/src/fs_store.rs +++ b/lightning-persister/src/fs_store.rs @@ -1,7 +1,7 @@ //! Objects related to [`FilesystemStore`] live here. use crate::utils::{check_namespace_key_validity, is_valid_kvstore_str}; -use lightning::util::persist::KVStore; +use lightning::util::persist::{KVStore, MigratableKVStore}; use std::collections::HashMap; use std::fs; @@ -404,6 +404,74 @@ fn get_key_from_dir_entry(p: &Path, base_path: &Path) -> Result Result, lightning::io::Error> { + let prefixed_dest = self.data_dir.clone(); + if !prefixed_dest.exists() { + return Ok(Vec::new()); + } + + let mut keys = Vec::new(); + + 'primary_loop: for primary_entry in fs::read_dir(&prefixed_dest)? { + let primary_entry = primary_entry?; + let primary_path = primary_entry.path(); + + if dir_entry_is_key(&primary_path)? { + let primary_namespace = "".to_string(); + let secondary_namespace = "".to_string(); + let key = get_key_from_dir_entry(&primary_path, &prefixed_dest)?; + keys.push((primary_namespace, secondary_namespace, key)); + continue 'primary_loop; + } + + // The primary_entry is actually also a directory. + 'secondary_loop: for secondary_entry in fs::read_dir(&primary_path)? { + let secondary_entry = secondary_entry?; + let secondary_path = secondary_entry.path(); + + if dir_entry_is_key(&secondary_path)? { + let primary_namespace = get_key_from_dir_entry(&primary_path, &prefixed_dest)?; + let secondary_namespace = "".to_string(); + let key = get_key_from_dir_entry(&secondary_path, &primary_path)?; + keys.push((primary_namespace, secondary_namespace, key)); + continue 'secondary_loop; + } + + // The secondary_entry is actually also a directory. + for tertiary_entry in fs::read_dir(&secondary_path)? { + let tertiary_entry = tertiary_entry?; + let tertiary_path = tertiary_entry.path(); + + if dir_entry_is_key(&tertiary_path)? { + let primary_namespace = + get_key_from_dir_entry(&primary_path, &prefixed_dest)?; + let secondary_namespace = + get_key_from_dir_entry(&secondary_path, &primary_path)?; + let key = get_key_from_dir_entry(&tertiary_path, &secondary_path)?; + keys.push((primary_namespace, secondary_namespace, key)); + } else { + debug_assert!( + false, + "Failed to list keys of path {:?}: only two levels of namespaces are supported", + tertiary_path.to_str() + ); + let msg = format!( + "Failed to list keys of path {:?}: only two levels of namespaces are supported", + tertiary_path.to_str() + ); + return Err(lightning::io::Error::new( + lightning::io::ErrorKind::Other, + msg, + )); + } + } + } + } + Ok(keys) + } +} + #[cfg(test)] mod tests { use super::*;