Merge pull request #88 from greatest-ape/work-2022-08-06

Use regular IndexMap for PeerMap; replace PeerStatus with is_seeder bool in udp
This commit is contained in:
Joakim Frostegård 2022-08-07 16:54:35 +02:00 committed by GitHub
commit 1097a9d068
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 65 additions and 39 deletions

1
Cargo.lock generated
View file

@ -68,6 +68,7 @@ dependencies = [
"hashbrown 0.12.3", "hashbrown 0.12.3",
"hex", "hex",
"hwloc", "hwloc",
"indexmap",
"indexmap-amortized", "indexmap-amortized",
"libc", "libc",
"log", "log",

View file

@ -24,6 +24,7 @@ duplicate = "0.4"
git-testament = "0.2" git-testament = "0.2"
hashbrown = "0.12" hashbrown = "0.12"
hex = "0.4" hex = "0.4"
indexmap = "1"
indexmap-amortized = "1" indexmap-amortized = "1"
libc = "0.2" libc = "0.2"
log = "0.4" log = "0.4"

View file

@ -13,6 +13,9 @@ pub mod privileges;
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
pub mod rustls_config; pub mod rustls_config;
/// IndexMap using AHash hasher
pub type IndexMap<K, V> = indexmap::IndexMap<K, V, RandomState>;
/// Amortized IndexMap using AHash hasher /// Amortized IndexMap using AHash hasher
pub type AmortizedIndexMap<K, V> = indexmap_amortized::IndexMap<K, V, RandomState>; pub type AmortizedIndexMap<K, V> = indexmap_amortized::IndexMap<K, V, RandomState>;
@ -104,7 +107,7 @@ impl Drop for PanicSentinel {
#[inline] #[inline]
pub fn extract_response_peers<K, V, R, F>( pub fn extract_response_peers<K, V, R, F>(
rng: &mut impl Rng, rng: &mut impl Rng,
peer_map: &AmortizedIndexMap<K, V>, peer_map: &IndexMap<K, V>,
max_num_peers_to_take: usize, max_num_peers_to_take: usize,
sender_peer_map_key: K, sender_peer_map_key: K,
peer_conversion_function: F, peer_conversion_function: F,

View file

@ -16,7 +16,7 @@ use rand::SeedableRng;
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
use aquatic_common::access_list::{create_access_list_cache, AccessListArcSwap, AccessListCache}; use aquatic_common::access_list::{create_access_list_cache, AccessListArcSwap, AccessListCache};
use aquatic_common::{extract_response_peers, PanicSentinel}; use aquatic_common::{extract_response_peers, IndexMap, PanicSentinel};
use aquatic_common::{AmortizedIndexMap, CanonicalSocketAddr}; use aquatic_common::{AmortizedIndexMap, CanonicalSocketAddr};
use aquatic_common::{SecondsSinceServerStart, ServerStartInstant, ValidUntil}; use aquatic_common::{SecondsSinceServerStart, ServerStartInstant, ValidUntil};
use aquatic_http_protocol::common::*; use aquatic_http_protocol::common::*;
@ -78,7 +78,7 @@ pub struct PeerMapKey<I: Ip> {
pub ip_or_key: Either<I, SmartString<LazyCompact>>, pub ip_or_key: Either<I, SmartString<LazyCompact>>,
} }
pub type PeerMap<I> = AmortizedIndexMap<PeerMapKey<I>, Peer<I>>; pub type PeerMap<I> = IndexMap<PeerMapKey<I>, Peer<I>>;
pub struct TorrentData<I: Ip> { pub struct TorrentData<I: Ip> {
pub peers: PeerMap<I>, pub peers: PeerMap<I>,

View file

@ -1,6 +1,8 @@
use std::net::{Ipv4Addr, Ipv6Addr}; use std::net::{Ipv4Addr, Ipv6Addr};
use aquatic_common::{AmortizedIndexMap, SecondsSinceServerStart, ServerStartInstant, ValidUntil}; use aquatic_common::{
AmortizedIndexMap, IndexMap, SecondsSinceServerStart, ServerStartInstant, ValidUntil,
};
use aquatic_http_protocol::common::{AnnounceEvent, InfoHash, PeerId}; use aquatic_http_protocol::common::{AnnounceEvent, InfoHash, PeerId};
use aquatic_http_protocol::response::ResponsePeer; use aquatic_http_protocol::response::ResponsePeer;
@ -55,7 +57,7 @@ pub struct PeerMapKey<I: Ip> {
pub ip_address: I, pub ip_address: I,
} }
pub type PeerMap<I> = AmortizedIndexMap<PeerMapKey<I>, Peer<I>>; pub type PeerMap<I> = IndexMap<PeerMapKey<I>, Peer<I>>;
pub struct TorrentData<I: Ip> { pub struct TorrentData<I: Ip> {
pub peers: PeerMap<I>, pub peers: PeerMap<I>,

View file

@ -17,7 +17,7 @@ use aquatic_udp_protocol::*;
use crate::common::*; use crate::common::*;
use crate::config::Config; use crate::config::Config;
use storage::{Peer, TorrentMap, TorrentMaps}; use storage::{TorrentMap, TorrentMaps};
pub fn run_swarm_worker( pub fn run_swarm_worker(
_sentinel: PanicSentinel, _sentinel: PanicSentinel,
@ -145,16 +145,17 @@ fn handle_announce_request<I: Ip>(
) )
}; };
let peer = Peer {
ip_address: peer_ip,
port: request.port,
status: PeerStatus::from_event_and_bytes_left(request.event, request.bytes_left),
valid_until: peer_valid_until,
};
let torrent_data = torrents.0.entry(request.info_hash).or_default(); let torrent_data = torrents.0.entry(request.info_hash).or_default();
torrent_data.update_peer(request.peer_id, peer); let peer_status = PeerStatus::from_event_and_bytes_left(request.event, request.bytes_left);
torrent_data.update_peer(
request.peer_id,
peer_ip,
request.port,
peer_status,
peer_valid_until,
);
let response_peers = let response_peers =
torrent_data.extract_response_peers(rng, request.peer_id, max_num_peers_to_take); torrent_data.extract_response_peers(rng, request.peer_id, max_num_peers_to_take);

View file

@ -2,6 +2,7 @@ use std::net::Ipv4Addr;
use std::net::Ipv6Addr; use std::net::Ipv6Addr;
use std::sync::Arc; use std::sync::Arc;
use aquatic_common::IndexMap;
use aquatic_common::SecondsSinceServerStart; use aquatic_common::SecondsSinceServerStart;
use aquatic_common::ServerStartInstant; use aquatic_common::ServerStartInstant;
use aquatic_common::{ use aquatic_common::{
@ -19,15 +20,15 @@ use crate::config::Config;
use super::create_torrent_scrape_statistics; use super::create_torrent_scrape_statistics;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Peer<I: Ip> { struct Peer<I: Ip> {
pub ip_address: I, ip_address: I,
pub port: Port, port: Port,
pub status: PeerStatus, is_seeder: bool,
pub valid_until: ValidUntil, valid_until: ValidUntil,
} }
impl<I: Ip> Peer<I> { impl<I: Ip> Peer<I> {
pub fn to_response_peer(&self) -> ResponsePeer<I> { fn to_response_peer(&self) -> ResponsePeer<I> {
ResponsePeer { ResponsePeer {
ip_address: self.ip_address, ip_address: self.ip_address,
port: self.port, port: self.port,
@ -35,7 +36,7 @@ impl<I: Ip> Peer<I> {
} }
} }
pub type PeerMap<I> = AmortizedIndexMap<PeerId, Peer<I>>; type PeerMap<I> = IndexMap<PeerId, Peer<I>>;
pub struct TorrentData<I: Ip> { pub struct TorrentData<I: Ip> {
peers: PeerMap<I>, peers: PeerMap<I>,
@ -44,14 +45,35 @@ pub struct TorrentData<I: Ip> {
} }
impl<I: Ip> TorrentData<I> { impl<I: Ip> TorrentData<I> {
pub fn update_peer(&mut self, peer_id: PeerId, peer: Peer<I>) { pub fn update_peer(
let opt_removed_peer = match peer.status { &mut self,
peer_id: PeerId,
ip_address: I,
port: Port,
status: PeerStatus,
valid_until: ValidUntil,
) {
let opt_removed_peer = match status {
PeerStatus::Leeching => { PeerStatus::Leeching => {
let peer = Peer {
ip_address,
port,
is_seeder: false,
valid_until,
};
self.num_leechers += 1; self.num_leechers += 1;
self.peers.insert(peer_id, peer) self.peers.insert(peer_id, peer)
} }
PeerStatus::Seeding => { PeerStatus::Seeding => {
let peer = Peer {
ip_address,
port,
is_seeder: true,
valid_until,
};
self.num_seeders += 1; self.num_seeders += 1;
self.peers.insert(peer_id, peer) self.peers.insert(peer_id, peer)
@ -59,14 +81,14 @@ impl<I: Ip> TorrentData<I> {
PeerStatus::Stopped => self.peers.remove(&peer_id), PeerStatus::Stopped => self.peers.remove(&peer_id),
}; };
match opt_removed_peer.map(|peer| peer.status) { match opt_removed_peer.map(|peer| peer.is_seeder) {
Some(PeerStatus::Leeching) => { Some(true) => {
self.num_leechers -= 1; self.num_leechers -= 1;
} }
Some(PeerStatus::Seeding) => { Some(false) => {
self.num_seeders -= 1; self.num_seeders -= 1;
} }
_ => {} None => {}
} }
} }
@ -106,15 +128,11 @@ impl<I: Ip> TorrentData<I> {
if peer.valid_until.valid(now) { if peer.valid_until.valid(now) {
true true
} else { } else {
match peer.status { if peer.is_seeder {
PeerStatus::Seeding => { self.num_seeders -= 1;
self.num_seeders -= 1; } else {
} self.num_leechers -= 1;
PeerStatus::Leeching => { }
self.num_leechers -= 1;
}
_ => (),
};
false false
} }
@ -264,7 +282,7 @@ mod tests {
Peer { Peer {
ip_address: Ipv4Addr::from(i.to_be_bytes()), ip_address: Ipv4Addr::from(i.to_be_bytes()),
port: Port(1), port: Port(1),
status: PeerStatus::Leeching, is_seeder: false,
valid_until: ValidUntil::new(ServerStartInstant::new(), 0), valid_until: ValidUntil::new(ServerStartInstant::new(), 0),
} }
} }

View file

@ -13,7 +13,7 @@ use hashbrown::HashMap;
use rand::{rngs::SmallRng, SeedableRng}; use rand::{rngs::SmallRng, SeedableRng};
use aquatic_common::{ use aquatic_common::{
extract_response_peers, AmortizedIndexMap, PanicSentinel, SecondsSinceServerStart, extract_response_peers, AmortizedIndexMap, IndexMap, PanicSentinel, SecondsSinceServerStart,
ServerStartInstant, ServerStartInstant,
}; };
use aquatic_ws_protocol::*; use aquatic_ws_protocol::*;
@ -53,7 +53,7 @@ struct Peer {
pub valid_until: ValidUntil, pub valid_until: ValidUntil,
} }
type PeerMap = AmortizedIndexMap<PeerId, Peer>; type PeerMap = IndexMap<PeerId, Peer>;
struct TorrentData { struct TorrentData {
pub peers: PeerMap, pub peers: PeerMap,