|
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 | use lightning::util::string::PrintableString;
|
6 | 6 |
|
7 | 7 | use std::collections::HashMap;
|
@@ -425,6 +425,72 @@ fn get_key_from_dir_entry(p: &Path, base_path: &Path) -> Result<String, lightnin
|
425 | 425 | }
|
426 | 426 | }
|
427 | 427 |
|
| 428 | +impl MigratableKVStore for FilesystemStore { |
| 429 | + fn list_all_keys(&self) -> Result<Vec<(String, String, String)>, lightning::io::Error> { |
| 430 | + let prefixed_dest = &self.data_dir; |
| 431 | + if !prefixed_dest.exists() { |
| 432 | + return Ok(Vec::new()); |
| 433 | + } |
| 434 | + |
| 435 | + let mut keys = Vec::new(); |
| 436 | + |
| 437 | + 'primary_loop: for primary_entry in fs::read_dir(prefixed_dest)? { |
| 438 | + let primary_path = primary_entry?.path(); |
| 439 | + |
| 440 | + if dir_entry_is_key(&primary_path)? { |
| 441 | + let primary_namespace = String::new(); |
| 442 | + let secondary_namespace = String::new(); |
| 443 | + let key = get_key_from_dir_entry(&primary_path, prefixed_dest)?; |
| 444 | + keys.push((primary_namespace, secondary_namespace, key)); |
| 445 | + continue 'primary_loop; |
| 446 | + } |
| 447 | + |
| 448 | + // The primary_entry is actually also a directory. |
| 449 | + 'secondary_loop: for secondary_entry in fs::read_dir(&primary_path)? { |
| 450 | + let secondary_path = secondary_entry?.path(); |
| 451 | + |
| 452 | + if dir_entry_is_key(&secondary_path)? { |
| 453 | + let primary_namespace = get_key_from_dir_entry(&primary_path, prefixed_dest)?; |
| 454 | + let secondary_namespace = String::new(); |
| 455 | + let key = get_key_from_dir_entry(&secondary_path, &primary_path)?; |
| 456 | + keys.push((primary_namespace, secondary_namespace, key)); |
| 457 | + continue 'secondary_loop; |
| 458 | + } |
| 459 | + |
| 460 | + // The secondary_entry is actually also a directory. |
| 461 | + for tertiary_entry in fs::read_dir(&secondary_path)? { |
| 462 | + let tertiary_entry = tertiary_entry?; |
| 463 | + let tertiary_path = tertiary_entry.path(); |
| 464 | + |
| 465 | + if dir_entry_is_key(&tertiary_path)? { |
| 466 | + let primary_namespace = |
| 467 | + get_key_from_dir_entry(&primary_path, prefixed_dest)?; |
| 468 | + let secondary_namespace = |
| 469 | + get_key_from_dir_entry(&secondary_path, &primary_path)?; |
| 470 | + let key = get_key_from_dir_entry(&tertiary_path, &secondary_path)?; |
| 471 | + keys.push((primary_namespace, secondary_namespace, key)); |
| 472 | + } else { |
| 473 | + debug_assert!( |
| 474 | + false, |
| 475 | + "Failed to list keys of path {}: only two levels of namespaces are supported", |
| 476 | + PrintableString(tertiary_path.to_str().unwrap_or_default()) |
| 477 | + ); |
| 478 | + let msg = format!( |
| 479 | + "Failed to list keys of path {}: only two levels of namespaces are supported", |
| 480 | + PrintableString(tertiary_path.to_str().unwrap_or_default()) |
| 481 | + ); |
| 482 | + return Err(lightning::io::Error::new( |
| 483 | + lightning::io::ErrorKind::Other, |
| 484 | + msg, |
| 485 | + )); |
| 486 | + } |
| 487 | + } |
| 488 | + } |
| 489 | + } |
| 490 | + Ok(keys) |
| 491 | + } |
| 492 | +} |
| 493 | + |
428 | 494 | #[cfg(test)]
|
429 | 495 | mod tests {
|
430 | 496 | use super::*;
|
|
0 commit comments