@@ -176,6 +176,53 @@ pub trait MigratableKVStore: KVStore {
176
176
fn list_all_keys ( & self ) -> Result < Vec < ( String , String , String ) > , io:: Error > ;
177
177
}
178
178
179
+ /// Migrates all data from one store to another.
180
+ ///
181
+ /// This operation assumes that `target_store` is empty, i.e., any data present under copied keys
182
+ /// might get overriden. User must ensure `source_store` is not modified during operation,
183
+ /// otherwise no consistency guarantees can be given.
184
+ ///
185
+ /// Will abort and return an error if any IO operation fails. Note that in this case the
186
+ /// `target_store` might get left in an intermediate state.
187
+ ///
188
+ /// **Caution**: Will delete all data from `source_store` if `move_data` is set.
189
+ pub fn migrate_kv_store_data < S : MigratableKVStore , T : MigratableKVStore > (
190
+ source_store : & mut S , target_store : & mut T , move_data : bool ,
191
+ ) -> Result < ( ) , io:: Error > {
192
+ let keys_to_migrate = source_store. list_all_keys ( ) ?;
193
+
194
+ // First copy over all data.
195
+ for ( primary_namespace, secondary_namespace, key) in & keys_to_migrate {
196
+ let data = source_store. read ( primary_namespace, secondary_namespace, key) ?;
197
+ target_store. write ( primary_namespace, secondary_namespace, key, & data) ?;
198
+
199
+ // Now validate what we've written.
200
+ let read_data = target_store. read ( primary_namespace, secondary_namespace, & key) ?;
201
+ if data != read_data {
202
+ let err =
203
+ io:: Error :: new ( io:: ErrorKind :: InvalidData , "Failed to validate migrated data" ) ;
204
+ return Err ( err) ;
205
+ }
206
+ }
207
+
208
+ // If we succeeded and `move_data` is set, remove all migrated keys.
209
+ if move_data {
210
+ for ( primary_namespace, secondary_namespace, key) in & keys_to_migrate {
211
+ source_store. remove ( primary_namespace, secondary_namespace, & key, false ) ?;
212
+ }
213
+
214
+ if !source_store. list_all_keys ( ) ?. is_empty ( ) {
215
+ let err = io:: Error :: new (
216
+ io:: ErrorKind :: InvalidData ,
217
+ "Source store is not empty. Was it modified during migration? This should never happen!"
218
+ ) ;
219
+ return Err ( err) ;
220
+ }
221
+ }
222
+
223
+ Ok ( ( ) )
224
+ }
225
+
179
226
/// Trait that handles persisting a [`ChannelManager`], [`NetworkGraph`], and [`WriteableScore`] to disk.
180
227
///
181
228
/// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
0 commit comments