@@ -10,7 +10,7 @@ use std::io::Write;
1010use std:: ops:: Deref ;
1111#[ cfg( unix) ]
1212use std:: os:: unix:: fs:: OpenOptionsExt ;
13- use std:: path:: Path ;
13+ use std:: path:: { Path , PathBuf } ;
1414use std:: sync:: { Arc , RwLock } ;
1515
1616use bdk_chain:: indexer:: keychain_txout:: ChangeSet as BdkIndexerChangeSet ;
@@ -26,14 +26,16 @@ use lightning::routing::scoring::{
2626 ChannelLiquidities , ProbabilisticScorer , ProbabilisticScoringDecayParameters ,
2727} ;
2828use lightning:: util:: persist:: {
29- KVStore , KVStoreSync , KVSTORE_NAMESPACE_KEY_ALPHABET , KVSTORE_NAMESPACE_KEY_MAX_LEN ,
30- NETWORK_GRAPH_PERSISTENCE_KEY , NETWORK_GRAPH_PERSISTENCE_PRIMARY_NAMESPACE ,
31- NETWORK_GRAPH_PERSISTENCE_SECONDARY_NAMESPACE , OUTPUT_SWEEPER_PERSISTENCE_KEY ,
32- OUTPUT_SWEEPER_PERSISTENCE_PRIMARY_NAMESPACE , OUTPUT_SWEEPER_PERSISTENCE_SECONDARY_NAMESPACE ,
33- SCORER_PERSISTENCE_KEY , SCORER_PERSISTENCE_PRIMARY_NAMESPACE ,
34- SCORER_PERSISTENCE_SECONDARY_NAMESPACE ,
29+ migrate_kv_store_data , KVStore , KVStoreSync , KVSTORE_NAMESPACE_KEY_ALPHABET ,
30+ KVSTORE_NAMESPACE_KEY_MAX_LEN , NETWORK_GRAPH_PERSISTENCE_KEY ,
31+ NETWORK_GRAPH_PERSISTENCE_PRIMARY_NAMESPACE , NETWORK_GRAPH_PERSISTENCE_SECONDARY_NAMESPACE ,
32+ OUTPUT_SWEEPER_PERSISTENCE_KEY , OUTPUT_SWEEPER_PERSISTENCE_PRIMARY_NAMESPACE ,
33+ OUTPUT_SWEEPER_PERSISTENCE_SECONDARY_NAMESPACE , SCORER_PERSISTENCE_KEY ,
34+ SCORER_PERSISTENCE_PRIMARY_NAMESPACE , SCORER_PERSISTENCE_SECONDARY_NAMESPACE ,
3535} ;
3636use lightning:: util:: ser:: { Readable , ReadableArgs , Writeable } ;
37+ use lightning_persister:: fs_store:: v1:: FilesystemStore ;
38+ use lightning_persister:: fs_store:: v2:: { FilesystemStoreV2 , FilesystemStoreV2Error } ;
3739use lightning_types:: string:: PrintableString ;
3840
3941use super :: * ;
@@ -48,7 +50,7 @@ use crate::payment::PendingPaymentDetails;
4850use crate :: peer_store:: PeerStore ;
4951use crate :: types:: { Broadcaster , DynStore , KeysManager , Sweeper } ;
5052use crate :: wallet:: ser:: { ChangeSetDeserWrapper , ChangeSetSerWrapper } ;
51- use crate :: { Error , EventQueue , NodeMetrics , PaymentDetails } ;
53+ use crate :: { BuildError , Error , EventQueue , NodeMetrics , PaymentDetails } ;
5254
5355pub const EXTERNAL_PATHFINDING_SCORES_CACHE_KEY : & str = "external_pathfinding_scores_cache" ;
5456
@@ -709,6 +711,42 @@ where
709711 Ok ( res)
710712}
711713
714+ /// Opens a [`FilesystemStoreV2`], automatically migrating from v1 format if necessary.
715+ ///
716+ /// If the directory contains v1 data (files at the top level), the data is migrated to v2 format
717+ /// in a temporary directory, the original is renamed to `fs_store_v1_backup`, and the migrated
718+ /// directory is moved into place.
719+ pub ( crate ) fn open_or_migrate_fs_store (
720+ storage_dir_path : PathBuf ,
721+ ) -> Result < FilesystemStoreV2 , BuildError > {
722+ match FilesystemStoreV2 :: new ( storage_dir_path. clone ( ) ) {
723+ Ok ( store) => Ok ( store) ,
724+ Err ( FilesystemStoreV2Error :: V1DataDetected ( _) ) => {
725+ // The directory contains v1 data, migrate to v2.
726+ let mut v1_store = FilesystemStore :: new ( storage_dir_path. clone ( ) ) ;
727+
728+ let mut v2_dir = storage_dir_path. clone ( ) ;
729+ v2_dir. set_file_name ( "fs_store_v2_migrating" ) ;
730+ fs:: create_dir_all ( v2_dir. clone ( ) ) . map_err ( |_| BuildError :: StoragePathAccessFailed ) ?;
731+ let mut v2_store = FilesystemStoreV2 :: new ( v2_dir. clone ( ) )
732+ . map_err ( |_| BuildError :: KVStoreSetupFailed ) ?;
733+
734+ migrate_kv_store_data ( & mut v1_store, & mut v2_store)
735+ . map_err ( |_| BuildError :: KVStoreSetupFailed ) ?;
736+
737+ // Swap directories: rename v1 out of the way, move v2 into place.
738+ let mut backup_dir = storage_dir_path. clone ( ) ;
739+ backup_dir. set_file_name ( "fs_store_v1_backup" ) ;
740+ fs:: rename ( & storage_dir_path, & backup_dir)
741+ . map_err ( |_| BuildError :: KVStoreSetupFailed ) ?;
742+ fs:: rename ( & v2_dir, & storage_dir_path) . map_err ( |_| BuildError :: KVStoreSetupFailed ) ?;
743+
744+ FilesystemStoreV2 :: new ( storage_dir_path) . map_err ( |_| BuildError :: KVStoreSetupFailed )
745+ } ,
746+ Err ( _) => Err ( BuildError :: KVStoreSetupFailed ) ,
747+ }
748+ }
749+
712750#[ cfg( test) ]
713751mod tests {
714752 use super :: read_or_generate_seed_file;
0 commit comments