|
1 | 1 | //! Objects related to [`FilesystemStore`] live here.
|
2 | 2 | use crate::utils::{check_namespace_key_validity, is_valid_kvstore_str};
|
3 | 3 |
|
4 |
| -use lightning::util::persist::KVStore; |
| 4 | +use lightning::util::persist::{KVStore, MigratableKVStore}; |
5 | 5 |
|
6 | 6 | use std::collections::HashMap;
|
7 | 7 | use std::fs;
|
@@ -404,6 +404,74 @@ fn get_key_from_dir_entry(p: &Path, base_path: &Path) -> Result<String, lightnin
|
404 | 404 | }
|
405 | 405 | }
|
406 | 406 |
|
| 407 | +impl MigratableKVStore for FilesystemStore { |
| 408 | + fn list_all_keys(&self) -> Result<Vec<(String, String, String)>, lightning::io::Error> { |
| 409 | + let prefixed_dest = self.data_dir.clone(); |
| 410 | + if !prefixed_dest.exists() { |
| 411 | + return Ok(Vec::new()); |
| 412 | + } |
| 413 | + |
| 414 | + let mut keys = Vec::new(); |
| 415 | + |
| 416 | + 'primary_loop: for primary_entry in fs::read_dir(&prefixed_dest)? { |
| 417 | + let primary_entry = primary_entry?; |
| 418 | + let primary_path = primary_entry.path(); |
| 419 | + |
| 420 | + if dir_entry_is_key(&primary_path)? { |
| 421 | + let primary_namespace = "".to_string(); |
| 422 | + let secondary_namespace = "".to_string(); |
| 423 | + let key = get_key_from_dir_entry(&primary_path, &prefixed_dest)?; |
| 424 | + keys.push((primary_namespace, secondary_namespace, key)); |
| 425 | + continue 'primary_loop; |
| 426 | + } |
| 427 | + |
| 428 | + // The primary_entry is actually also a directory. |
| 429 | + 'secondary_loop: for secondary_entry in fs::read_dir(&primary_path)? { |
| 430 | + let secondary_entry = secondary_entry?; |
| 431 | + let secondary_path = secondary_entry.path(); |
| 432 | + |
| 433 | + if dir_entry_is_key(&secondary_path)? { |
| 434 | + let primary_namespace = get_key_from_dir_entry(&primary_path, &prefixed_dest)?; |
| 435 | + let secondary_namespace = "".to_string(); |
| 436 | + let key = get_key_from_dir_entry(&secondary_path, &primary_path)?; |
| 437 | + keys.push((primary_namespace, secondary_namespace, key)); |
| 438 | + continue 'secondary_loop; |
| 439 | + } |
| 440 | + |
| 441 | + // The secondary_entry is actually also a directory. |
| 442 | + for tertiary_entry in fs::read_dir(&secondary_path)? { |
| 443 | + let tertiary_entry = tertiary_entry?; |
| 444 | + let tertiary_path = tertiary_entry.path(); |
| 445 | + |
| 446 | + if dir_entry_is_key(&tertiary_path)? { |
| 447 | + let primary_namespace = |
| 448 | + get_key_from_dir_entry(&primary_path, &prefixed_dest)?; |
| 449 | + let secondary_namespace = |
| 450 | + get_key_from_dir_entry(&secondary_path, &primary_path)?; |
| 451 | + let key = get_key_from_dir_entry(&tertiary_path, &secondary_path)?; |
| 452 | + keys.push((primary_namespace, secondary_namespace, key)); |
| 453 | + } else { |
| 454 | + debug_assert!( |
| 455 | + false, |
| 456 | + "Failed to list keys of path {:?}: only two levels of namespaces are supported", |
| 457 | + tertiary_path.to_str() |
| 458 | + ); |
| 459 | + let msg = format!( |
| 460 | + "Failed to list keys of path {:?}: only two levels of namespaces are supported", |
| 461 | + tertiary_path.to_str() |
| 462 | + ); |
| 463 | + return Err(lightning::io::Error::new( |
| 464 | + lightning::io::ErrorKind::Other, |
| 465 | + msg, |
| 466 | + )); |
| 467 | + } |
| 468 | + } |
| 469 | + } |
| 470 | + } |
| 471 | + Ok(keys) |
| 472 | + } |
| 473 | +} |
| 474 | + |
407 | 475 | #[cfg(test)]
|
408 | 476 | mod tests {
|
409 | 477 | use super::*;
|
|
0 commit comments