Skip to content

Commit d7ebca1

Browse files
committed
Add single-monitor read function.
Adds a public function that only reads a single monitor, so that customers can list monitors themselves, and then parallelize reading them with updates from storage.
1 parent 5783f8e commit d7ebca1

File tree

1 file changed

+73
-48
lines changed

1 file changed

+73
-48
lines changed

lightning/src/util/persist.rs

+73-48
Original file line numberDiff line numberDiff line change
@@ -324,8 +324,9 @@ where
324324
///
325325
/// # Reading channel state from storage
326326
///
327-
/// Channel state is reconstructed by calling [`Self::read_channel_monitors_with_updates`]. Please
328-
/// see that function's documentation for more information.
327+
/// Channel state is reconstructed by calling
328+
/// [`MonitorUpdatingPersister::read_channel_monitors_with_updates`]. Please see that function's
329+
/// documentation for more information.
329330
///
330331
/// # Pruning stale channel updates
331332
///
@@ -335,7 +336,9 @@ where
335336
/// will complete. However, stale updates are not a problem for data integrity, since updates are
336337
/// only read that are higher than the stored [`ChannelMonitor`]'s update_id.
337338
///
338-
/// To keep storage usage in check, the [`Self::cleanup_stale_updates`] function as needed.
339+
/// If you have many stale updates stored (such as after a crash with pending lazy deletes), and
340+
/// would like to get rid of them, consider using the
341+
/// [`MonitorUpdatingPersister::cleanup_stale_updates`] function.
339342
pub struct MonitorUpdatingPersister<K: Deref, L: Deref, ES: Deref + Clone, SP: Deref + Clone>
340343
where
341344
K::Target: KVStore,
@@ -382,16 +385,13 @@ where
382385
}
383386
}
384387

385-
/// Reads channel monitors, along with any stored updates for them.
388+
/// Reads all stored channel monitors, along with any stored updates for them.
386389
///
387390
/// # EXTREMELY IMPORTANT
388391
/// It is extremely important that your [`KVStore::read`] implementation uses the
389-
/// [`io::ErrorKind::NotFound`] variant correctly: that is, when a file is not found, and _only_
390-
/// in that circumstance (not when there is really a permissions error, for example). This is
391-
/// because this function does not list updates. Instead, it lists all monitors, and then using
392-
/// their stored `update_id`, synthesizes update storage keys, and tries them in sequence until
393-
/// one is not found. All _other_ errors will be bubbled up in this function's [`io::Result`].
394-
pub fn read_channel_monitors_with_updates<B: Deref, F: Deref + Clone>(
392+
/// [`io::ErrorKind::NotFound`] variant correctly. For more information, please refer to
393+
/// [`MonitorUpdatingPersister::read_channel_monitor_with_updates`].
394+
pub fn read_all_channel_monitors_with_updates<B: Deref, F: Deref + Clone>(
395395
&self, broadcaster: &B, fee_estimator: F,
396396
) -> io::Result<Vec<(BlockHash, ChannelMonitor<<SP::Target as SignerProvider>::Signer>)>>
397397
where
@@ -405,31 +405,59 @@ where
405405
CHANNEL_MONITOR_PERSISTENCE_SUB_NAMESPACE,
406406
)?;
407407
let mut res = Vec::with_capacity(monitor_list.len());
408-
// for each monitor...
409-
for maybe_monitor_name in monitor_list.into_iter().map(MonitorName::new) {
410-
let monitor_name = maybe_monitor_name?;
411-
// ...parse the monitor
412-
let (block_hash, monitor) = self.read_monitor(&monitor_name)?;
413-
// ...parse and apply the updates with an id higher than the monitor.
414-
let mut current_update_id = monitor.get_latest_update_id();
415-
loop {
416-
current_update_id = match current_update_id.checked_add(1) {
417-
Some(next_update_id) => next_update_id,
418-
None => break,
419-
};
420-
let update_name = UpdateName::from(current_update_id);
421-
let update = match self.read_monitor_update(&monitor_name, &update_name) {
422-
Ok(update) => update,
423-
Err(err) if err.kind() == io::ErrorKind::NotFound => {
424-
// We can't find any more updates, so we are done.
425-
break;
426-
}
427-
Err(err) => return Err(err),
428-
};
408+
for monitor_key in monitor_list {
409+
res.push(self.read_channel_monitor_with_updates(
410+
broadcaster,
411+
&fee_estimator,
412+
monitor_key,
413+
)?)
414+
}
415+
Ok(res)
416+
}
417+
418+
/// Read a single channel monitor, along with any stored updates for it.
419+
///
420+
/// # EXTREMELY IMPORTANT
421+
/// It is extremely important that your [`KVStore::read`] implementation uses the
422+
/// [`io::ErrorKind::NotFound`] variant correctly: that is, when a file is not found, and _only_
423+
/// in that circumstance (not when there is really a permissions error, for example). This is
424+
/// because this function does not list updates. Instead, it reads the monitor, and using its
425+
/// stored `update_id`, synthesizes update storage keys, and tries them in sequence until one is
426+
/// not found. All _other_ errors will be bubbled up in this function's [`io::Result`].
427+
///
428+
/// # Parallelizing
429+
/// Loading a large number of monitors will be faster if done in parallel. You can use this
430+
/// function to accomplish this. Take care to limit the number of parallel readers.
431+
pub fn read_channel_monitor_with_updates<B: Deref, F: Deref + Clone>(
432+
&self, broadcaster: &B, fee_estimator: &F, monitor_key: String,
433+
) -> io::Result<(BlockHash, ChannelMonitor<<SP::Target as SignerProvider>::Signer>)>
434+
where
435+
ES::Target: EntropySource + Sized,
436+
SP::Target: SignerProvider + Sized,
437+
B::Target: BroadcasterInterface,
438+
F::Target: FeeEstimator,
439+
{
440+
let monitor_name = MonitorName::new(monitor_key)?;
441+
let (block_hash, monitor) = self.read_monitor(&monitor_name)?;
442+
let mut current_update_id = monitor.get_latest_update_id();
443+
loop {
444+
current_update_id = match current_update_id.checked_add(1) {
445+
Some(next_update_id) => next_update_id,
446+
None => break,
447+
};
448+
let update_name = UpdateName::from(current_update_id);
449+
let update = match self.read_monitor_update(&monitor_name, &update_name) {
450+
Ok(update) => update,
451+
Err(err) if err.kind() == io::ErrorKind::NotFound => {
452+
// We can't find any more updates, so we are done.
453+
break;
454+
}
455+
Err(err) => return Err(err),
456+
};
429457

430-
monitor
431-
.update_monitor(&update, broadcaster, fee_estimator.clone(), &self.logger)
432-
.map_err(|e| {
458+
monitor
459+
.update_monitor(&update, broadcaster, fee_estimator.clone(), &self.logger)
460+
.map_err(|e| {
433461
log_error!(
434462
self.logger,
435463
"Monitor update failed. monitor: {} update: {} reason: {:?}",
@@ -439,11 +467,8 @@ where
439467
);
440468
io::Error::new(io::ErrorKind::Other, "Monitor update failed")
441469
})?;
442-
}
443-
// ...push the result into the return vec
444-
res.push((block_hash, monitor))
445470
}
446-
Ok(res)
471+
Ok((block_hash, monitor))
447472
}
448473

449474
/// Read a channel monitor.
@@ -519,7 +544,7 @@ fn read_monitor(
519544
/// Cleans up stale updates for all monitors.
520545
///
521546
/// This function works by first listing all monitors, and then for each of them, listing all
522-
/// updates. The updates which have an update_id less than or equal to than the stored monitor
547+
/// updates. The updates that have an update_id less than or equal to than the stored monitor
523548
/// are deleted. The deletion can either be lazy or non-lazy based on the `lazy` flag; this will
524549
/// be passed to [`KVStore::remove`].
525550
pub fn cleanup_stale_updates(&self, lazy: bool) -> io::Result<()> {
@@ -564,7 +589,7 @@ where
564589
SP::Target: SignerProvider + Sized,
565590
{
566591
/// Persists a new channel. This means writing the entire monitor to the
567-
/// provided [`KVStore`].
592+
/// parametrized [`KVStore`].
568593
fn persist_new_channel(
569594
&self, funding_txo: OutPoint, monitor: &ChannelMonitor<ChannelSigner>,
570595
_monitor_update_call_id: MonitorUpdateId,
@@ -667,7 +692,7 @@ where
667692
}
668693

669694

670-
/// Persists a channel update, writing only the update to the provided [`KVStore`] if possible.
695+
/// Persists a channel update, writing only the update to the parameterized [`KVStore`] if possible.
671696
///
672697
/// In some cases, this will forward to [`MonitorUpdatingPersister::persist_new_channel`]:
673698
///
@@ -918,19 +943,19 @@ mod tests {
918943
// Check that the persisted channel data is empty before any channels are
919944
// open.
920945
let mut persisted_chan_data_0 = persister_0
921-
.read_channel_monitors_with_updates(&broadcaster_0, &chanmon_cfgs[0].fee_estimator)
946+
.read_all_channel_monitors_with_updates(&broadcaster_0, &chanmon_cfgs[0].fee_estimator)
922947
.unwrap();
923948
assert_eq!(persisted_chan_data_0.len(), 0);
924949
let mut persisted_chan_data_1 = persister_1
925-
.read_channel_monitors_with_updates(&broadcaster_1, &chanmon_cfgs[1].fee_estimator)
950+
.read_all_channel_monitors_with_updates(&broadcaster_1, &chanmon_cfgs[1].fee_estimator)
926951
.unwrap();
927952
assert_eq!(persisted_chan_data_1.len(), 0);
928953

929954
// Helper to make sure the channel is on the expected update ID.
930955
macro_rules! check_persisted_data {
931956
($expected_update_id: expr) => {
932957
persisted_chan_data_0 = persister_0
933-
.read_channel_monitors_with_updates(
958+
.read_all_channel_monitors_with_updates(
934959
&broadcaster_0,
935960
&chanmon_cfgs[0].fee_estimator,
936961
)
@@ -940,7 +965,7 @@ mod tests {
940965
assert_eq!(mon.get_latest_update_id(), $expected_update_id);
941966
}
942967
persisted_chan_data_1 = persister_1
943-
.read_channel_monitors_with_updates(
968+
.read_all_channel_monitors_with_updates(
944969
&broadcaster_1,
945970
&chanmon_cfgs[1].fee_estimator,
946971
)
@@ -1027,7 +1052,7 @@ mod tests {
10271052

10281053
// Make sure the expected number of stale updates is present.
10291054
let persisted_chan_data = persister_0
1030-
.read_channel_monitors_with_updates(&broadcaster_0, &chanmon_cfgs[0].fee_estimator)
1055+
.read_all_channel_monitors_with_updates(&broadcaster_0, &chanmon_cfgs[0].fee_estimator)
10311056
.unwrap();
10321057
let (_, monitor) = &persisted_chan_data[0];
10331058
let monitor_name = MonitorName::from(monitor.get_funding_txo().0);
@@ -1168,7 +1193,7 @@ mod tests {
11681193
// Check that the persisted channel data is empty before any channels are
11691194
// open.
11701195
let persisted_chan_data = persister_0
1171-
.read_channel_monitors_with_updates(&broadcaster_0, &chanmon_cfgs[0].fee_estimator)
1196+
.read_all_channel_monitors_with_updates(&broadcaster_0, &chanmon_cfgs[0].fee_estimator)
11721197
.unwrap();
11731198
assert_eq!(persisted_chan_data.len(), 0);
11741199

@@ -1181,7 +1206,7 @@ mod tests {
11811206

11821207
// Get the monitor and make a fake stale update at update_id=1 (lowest height of an update possible)
11831208
let persisted_chan_data = persister_0
1184-
.read_channel_monitors_with_updates(&broadcaster_0, &chanmon_cfgs[0].fee_estimator)
1209+
.read_all_channel_monitors_with_updates(&broadcaster_0, &chanmon_cfgs[0].fee_estimator)
11851210
.unwrap();
11861211
let (_, monitor) = &persisted_chan_data[0];
11871212
let monitor_name = MonitorName::from(monitor.get_funding_txo().0);

0 commit comments

Comments
 (0)