Skip to content

Commit

Permalink
Allow optimistic mirror of kbuckets with read lock only (#229)
Browse files Browse the repository at this point in the history
* Allow optimistic mirror of kbuckets with read lock only

* Publicly expose kbuckets as closure

* Add code example to docs

* fixup! Add code example to docs
  • Loading branch information
emhane authored Feb 21, 2024
1 parent 5a61b6b commit 3c0d3d7
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 1 deletion.
27 changes: 27 additions & 0 deletions src/discv5.rs
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,33 @@ impl<P: ProtocolIdentity> Discv5<P> {
.collect()
}

/// Takes a closure parameterized by type `Arc<RwLock<KBucketsTable<NodeId, Enr>>>` as
/// parameter. Caution: caller is responsible of dropping a lock taken on the kbuckets. For
/// example, a read lock can be taken on the kbuckets to optimistically view the current keys
/// in the kbuckets (optimistic since it doesn't apply pending entries, which requires a write
/// lock).
/// ```
/// use std::str::FromStr;
/// use discv5::{ConfigBuilder, Discv5, ListenConfig, Enr, enr::CombinedKey};
///
/// let sk = CombinedKey::generate_secp256k1();
/// let enr = Enr::builder().build(&sk).unwrap();
/// let config = ConfigBuilder::new(ListenConfig::default()).build();
/// let discv5: Discv5 = Discv5::new(enr, sk, config).unwrap();
///
/// let entries = discv5.with_kbuckets(|kbuckets| kbuckets
/// .read()
/// .iter_ref()
/// .map(|entry| *entry.node.key.preimage())
/// .collect::<Vec<_>>());
/// ```
pub fn with_kbuckets<F, T>(&self, f: F) -> T
where
F: FnOnce(&Arc<RwLock<KBucketsTable<NodeId, Enr>>>) -> T,
{
f(&self.kbuckets)
}

/// Requests the ENR of a node corresponding to multiaddr or multi-addr string.
///
/// Only `ed25519` and `secp256k1` key types are currently supported.
Expand Down
2 changes: 1 addition & 1 deletion src/kbucket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ where

/// Returns an iterator over all the entries in the routing table.
/// Does not add pending node to kbucket to get an iterator which
/// takes a reference instead of a mutable reference.
/// takes a mutable reference instead of a reference.
pub fn iter_ref(&self) -> impl Iterator<Item = EntryRefView<'_, TNodeId, TVal>> {
self.buckets.iter().flat_map(move |table| {
table.iter().map(move |n| EntryRefView {
Expand Down

0 comments on commit 3c0d3d7

Please sign in to comment.