mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-07-07 13:41:35 +00:00
Merge branch 'rust_master' into libp2p_0_20
# Conflicts: # .github/workflows/ci.yml # Cargo.toml # core/Cargo.toml # examples/distributed-key-value-store.rs # misc/multistream-select/Cargo.toml # muxers/mplex/Cargo.toml # protocols/deflate/Cargo.toml # protocols/gossipsub/Cargo.toml # protocols/identify/Cargo.toml # protocols/kad/src/behaviour.rs # protocols/kad/src/behaviour/test.rs # protocols/kad/src/kbucket.rs # protocols/kad/src/kbucket/bucket.rs # protocols/kad/src/lib.rs # protocols/kad/src/query.rs # protocols/kad/src/query/peers/closest.rs # protocols/mdns/Cargo.toml # protocols/ping/Cargo.toml # protocols/secio/Cargo.toml # transports/tcp/Cargo.toml # transports/uds/Cargo.toml
This commit is contained in:
@ -21,10 +21,10 @@
|
||||
mod peers;
|
||||
|
||||
use peers::PeersIterState;
|
||||
use peers::closest::{ClosestPeersIter, ClosestPeersIterConfig};
|
||||
use peers::closest::{ClosestPeersIterConfig, ClosestPeersIter, disjoint::ClosestDisjointPeersIter};
|
||||
use peers::fixed::FixedPeersIter;
|
||||
|
||||
use crate::K_VALUE;
|
||||
use crate::{ALPHA_VALUE, K_VALUE};
|
||||
use crate::kbucket::{Key, KeyBytes};
|
||||
use either::Either;
|
||||
use fnv::FnvHashMap;
|
||||
@ -113,7 +113,7 @@ impl<TInner> QueryPool<TInner> {
|
||||
{
|
||||
assert!(!self.queries.contains_key(&id));
|
||||
// TODO: why not alpha?
|
||||
let parallelism = self.config.replication_factor.get();
|
||||
let parallelism = self.config.replication_factor;
|
||||
|
||||
let (swamp, weighted) = peers.into_iter().partition::<Vec<_>, _>(|p| p.weight == 0);
|
||||
let swamp = swamp.into_iter().map(|p| p.peer_id.into_preimage());
|
||||
@ -143,7 +143,8 @@ impl<TInner> QueryPool<TInner> {
|
||||
I: IntoIterator<Item = WeightedPeer>
|
||||
{
|
||||
let cfg = ClosestPeersIterConfig {
|
||||
num_results: self.config.replication_factor.get(),
|
||||
num_results: self.config.replication_factor,
|
||||
parallelism: self.config.parallelism,
|
||||
.. ClosestPeersIterConfig::default()
|
||||
};
|
||||
|
||||
@ -151,8 +152,15 @@ impl<TInner> QueryPool<TInner> {
|
||||
let swamp = swamp.into_iter().map(|p| p.peer_id);
|
||||
let weighted = weighted.into_iter().map(|p| p.peer_id);
|
||||
|
||||
let weighted_iter = QueryPeerIter::Closest(ClosestPeersIter::with_config(cfg.clone(), target.clone(), weighted));
|
||||
let swamp_iter = QueryPeerIter::Closest(ClosestPeersIter::with_config(cfg, target, swamp));
|
||||
let weighted_iter = if self.config.disjoint_query_paths {
|
||||
QueryPeerIter::ClosestDisjoint(
|
||||
ClosestDisjointPeersIter::with_config(cfg, target, peers),
|
||||
)
|
||||
} else {
|
||||
QueryPeerIter::Closest(ClosestPeersIter::with_config(cfg.clone(), target.clone(), weighted));
|
||||
let swamp_iter = QueryPeerIter::Closest(ClosestPeersIter::with_config(cfg, target, swamp))
|
||||
};
|
||||
|
||||
let query = Query::new(id, weighted_iter, swamp_iter, inner);
|
||||
self.queries.insert(id, query);
|
||||
}
|
||||
@ -233,15 +241,34 @@ pub struct QueryId(usize);
|
||||
/// The configuration for queries in a `QueryPool`.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct QueryConfig {
|
||||
/// Timeout of a single query.
|
||||
///
|
||||
/// See [`crate::behaviour::KademliaConfig::set_query_timeout`] for details.
|
||||
pub timeout: Duration,
|
||||
|
||||
/// The replication factor to use.
|
||||
///
|
||||
/// See [`crate::behaviour::KademliaConfig::set_replication_factor`] for details.
|
||||
pub replication_factor: NonZeroUsize,
|
||||
|
||||
/// Allowed level of parallelism for iterative queries.
|
||||
///
|
||||
/// See [`crate::behaviour::KademliaConfig::set_parallelism`] for details.
|
||||
pub parallelism: NonZeroUsize,
|
||||
|
||||
/// Whether to use disjoint paths on iterative lookups.
|
||||
///
|
||||
/// See [`crate::behaviour::KademliaConfig::disjoint_query_paths`] for details.
|
||||
pub disjoint_query_paths: bool,
|
||||
}
|
||||
|
||||
impl Default for QueryConfig {
|
||||
fn default() -> Self {
|
||||
QueryConfig {
|
||||
timeout: Duration::from_secs(60),
|
||||
replication_factor: NonZeroUsize::new(K_VALUE.get()).expect("K_VALUE > 0")
|
||||
replication_factor: NonZeroUsize::new(K_VALUE.get()).expect("K_VALUE > 0"),
|
||||
parallelism: ALPHA_VALUE,
|
||||
disjoint_query_paths: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -263,6 +290,7 @@ pub struct Query<TInner> {
|
||||
/// The peer selection strategies that can be used by queries.
|
||||
enum QueryPeerIter {
|
||||
Closest(ClosestPeersIter),
|
||||
ClosestDisjoint(ClosestDisjointPeersIter),
|
||||
Fixed(FixedPeersIter)
|
||||
}
|
||||
|
||||
@ -291,6 +319,7 @@ impl<TInner> Query<TInner> {
|
||||
|
||||
let updated_weighted = match &mut self.weighted_iter {
|
||||
QueryPeerIter::Closest(iter) => iter.on_failure(peer),
|
||||
QueryPeerIter::ClosestDisjoint(iter) => iter.on_failure(peer),
|
||||
QueryPeerIter::Fixed(iter) => iter.on_failure(peer),
|
||||
};
|
||||
|
||||
@ -310,6 +339,7 @@ impl<TInner> Query<TInner> {
|
||||
|
||||
let updated_swamp = match &mut self.swamp_iter {
|
||||
QueryPeerIter::Closest(iter) => iter.on_success(peer, swamp.into_iter().map(|p| p.peer_id)),
|
||||
QueryPeerIter::ClosestDisjoint(iter) => iter.on_success(peer, new_peers),
|
||||
QueryPeerIter::Fixed(iter) => iter.on_success(peer),
|
||||
};
|
||||
|
||||
@ -332,6 +362,7 @@ impl<TInner> Query<TInner> {
|
||||
|
||||
let swamp_waiting = match &self.swamp_iter {
|
||||
QueryPeerIter::Closest(iter) => iter.is_waiting(peer),
|
||||
QueryPeerIter::ClosestDisjoint(iter) => iter.is_waiting(peer),
|
||||
QueryPeerIter::Fixed(iter) => iter.is_waiting(peer)
|
||||
};
|
||||
|
||||
@ -347,6 +378,7 @@ impl<TInner> Query<TInner> {
|
||||
// First query weighted iter
|
||||
let weighted_state = match &mut self.weighted_iter {
|
||||
QueryPeerIter::Closest(iter) => iter.next(now),
|
||||
QueryPeerIter::ClosestDisjoint(iter) => iter.next(now),
|
||||
QueryPeerIter::Fixed(iter) => iter.next()
|
||||
};
|
||||
|
||||
@ -377,6 +409,34 @@ impl<TInner> Query<TInner> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Tries to (gracefully) finish the query prematurely, providing the peers
|
||||
/// that are no longer of interest for further progress of the query.
|
||||
///
|
||||
/// A query may require that in order to finish gracefully a certain subset
|
||||
/// of peers must be contacted. E.g. in the case of disjoint query paths a
|
||||
/// query may only finish gracefully if every path contacted a peer whose
|
||||
/// response permits termination of the query. The given peers are those for
|
||||
/// which this is considered to be the case, i.e. for which a termination
|
||||
/// condition is satisfied.
|
||||
///
|
||||
/// Returns `true` if the query did indeed finish, `false` otherwise. In the
|
||||
/// latter case, a new attempt at finishing the query may be made with new
|
||||
/// `peers`.
|
||||
///
|
||||
/// A finished query immediately stops yielding new peers to contact and
|
||||
/// will be reported by [`QueryPool::poll`] via
|
||||
/// [`QueryPoolState::Finished`].
|
||||
pub fn try_finish<'a, I>(&mut self, peers: I) -> bool
|
||||
where
|
||||
I: IntoIterator<Item = &'a PeerId>
|
||||
{
|
||||
match &mut self.peer_iter {
|
||||
QueryPeerIter::Closest(iter) => { iter.finish(); true },
|
||||
QueryPeerIter::ClosestDisjoint(iter) => iter.finish_paths(peers),
|
||||
QueryPeerIter::Fixed(iter) => { iter.finish(); true }
|
||||
}
|
||||
}
|
||||
|
||||
/// Finishes the query prematurely.
|
||||
///
|
||||
/// A finished query immediately stops yielding new peers to contact and will be
|
||||
@ -384,6 +444,7 @@ impl<TInner> Query<TInner> {
|
||||
pub fn finish(&mut self) {
|
||||
match &mut self.weighted_iter {
|
||||
QueryPeerIter::Closest(iter) => iter.finish(),
|
||||
QueryPeerIter::ClosestDisjoint(iter) => iter.finish(),
|
||||
QueryPeerIter::Fixed(iter) => iter.finish()
|
||||
};
|
||||
|
||||
@ -405,6 +466,7 @@ impl<TInner> Query<TInner> {
|
||||
|
||||
let swamp_finished = match &self.swamp_iter {
|
||||
QueryPeerIter::Closest(iter) => iter.is_finished(),
|
||||
QueryPeerIter::ClosestDisjoint(iter) => iter.is_finished(),
|
||||
QueryPeerIter::Fixed(iter) => iter.is_finished()
|
||||
};
|
||||
|
||||
@ -414,7 +476,8 @@ impl<TInner> Query<TInner> {
|
||||
/// Consumes the query, producing the final `QueryResult`.
|
||||
pub fn into_result(self) -> QueryResult<TInner, impl Iterator<Item = PeerId>> {
|
||||
let weighted = match self.weighted_iter {
|
||||
QueryPeerIter::Closest(iter) => Either::Left(iter.into_result()),
|
||||
QueryPeerIter::Closest(iter) => Either::Left(Either::Left(iter.into_result())),
|
||||
QueryPeerIter::ClosestDisjoint(iter) => Either::Left(Either::Right(iter.into_result())),
|
||||
QueryPeerIter::Fixed(iter) => Either::Right(iter.into_result())
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user