Should be working ok now

This commit is contained in:
Igor Katson 2023-11-24 14:08:02 +00:00
parent 5e728fc67b
commit afbf2a76b9
No known key found for this signature in database
GPG key ID: B4EC22B66D61A3F5
8 changed files with 197 additions and 105 deletions

View file

@ -29,8 +29,8 @@ fn ensure_file_length(file: &File, length: u64) -> anyhow::Result<()> {
}
pub struct TorrentStateInitializing {
meta: Arc<ManagedTorrentInfo>,
only_files: Option<Vec<usize>>,
pub(crate) meta: Arc<ManagedTorrentInfo>,
pub(crate) only_files: Option<Vec<usize>>,
}
impl TorrentStateInitializing {

View file

@ -64,7 +64,7 @@ use futures::{stream::FuturesUnordered, StreamExt};
use librqbit_core::{
id20::Id20,
lengths::{ChunkInfo, Lengths, ValidPieceIndex},
speed_estimator::{SpeedEstimator},
speed_estimator::SpeedEstimator,
torrent_metainfo::TorrentMetaV1Info,
};
use parking_lot::{Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};
@ -88,7 +88,7 @@ use crate::{
peer_connection::{
PeerConnection, PeerConnectionHandler, PeerConnectionOptions, WriterRequest,
},
spawn_utils::{spawn},
spawn_utils::spawn,
tracker_comms::{TrackerError, TrackerRequest, TrackerRequestEvent, TrackerResponse},
type_aliases::{PeerHandle, BF},
};
@ -157,14 +157,13 @@ pub struct TorrentStateLive {
}
impl TorrentStateLive {
#[allow(clippy::too_many_arguments)]
pub(crate) fn new(paused: TorrentStatePaused) -> Arc<Self> {
let (peer_queue_tx, peer_queue_rx) = unbounded_channel();
let speed_estimator = SpeedEstimator::new(5);
let have_bytes = paused.chunk_tracker.get_have_bytes();
let needed_bytes = paused.chunk_tracker.get_needed_bytes();
let have_bytes = paused.have_bytes;
let needed_bytes = paused.needed_bytes;
let lengths = *paused.chunk_tracker.get_lengths();
let state = Arc::new(TorrentStateLive {
@ -560,6 +559,10 @@ impl TorrentStateLive {
}
self.finished_notify.notified().await;
}
pub fn pause(&self) -> anyhow::Result<TorrentStatePaused> {
bail!("pause not implemented yet")
}
}
struct PeerHandlerLocked {

View file

@ -4,11 +4,12 @@ pub mod paused;
pub mod utils;
use std::net::SocketAddr;
use std::path::Path;
use std::path::PathBuf;
use std::sync::Arc;
use std::time::Duration;
use std::{path::Path};
use anyhow::bail;
use anyhow::Context;
use buffers::ByteString;
use librqbit_core::id20::Id20;
@ -18,20 +19,38 @@ use librqbit_core::torrent_metainfo::TorrentMetaV1Info;
pub use live::*;
use parking_lot::RwLock;
use tokio_stream::StreamExt;
use tracing::trace_span;
use url::Url;
use crate::spawn_utils::{BlockingSpawner};
use crate::spawn_utils::spawn;
use crate::spawn_utils::BlockingSpawner;
use initializing::TorrentStateInitializing;
use self::paused::TorrentStatePaused;
pub enum ManagedTorrentState {
Initializing(TorrentStateInitializing),
Initializing(Arc<TorrentStateInitializing>),
Paused(TorrentStatePaused),
Live(Arc<TorrentStateLive>),
Error(anyhow::Error),
// This is used when swapping between states, outside world should never see it.
None,
}
impl ManagedTorrentState {
fn assert_paused(self) -> TorrentStatePaused {
match self {
Self::Paused(paused) => paused,
_ => panic!("Expected paused state"),
}
}
fn take(&mut self) -> Self {
std::mem::replace(self, Self::None)
}
}
pub(crate) struct ManagedTorrentLocked {
@ -58,6 +77,7 @@ pub struct ManagedTorrentInfo {
pub struct ManagedTorrent {
pub info: Arc<ManagedTorrentInfo>,
only_files: Option<Vec<usize>>,
locked: RwLock<ManagedTorrentLocked>,
}
@ -70,13 +90,8 @@ impl ManagedTorrent {
self.info.info_hash
}
pub(crate) fn add_peer(&self, _peer: SocketAddr) -> bool {
todo!()
}
pub fn only_files(&self) -> Option<Vec<usize>> {
// self.locked.write().only_files.clone()
todo!()
self.only_files.clone()
}
pub fn with_state<R>(&self, f: impl FnOnce(&ManagedTorrentState) -> R) -> R {
@ -91,6 +106,91 @@ impl ManagedTorrent {
}
}
pub fn start(
self: &Arc<Self>,
initial_peers: Vec<SocketAddr>,
peer_rx: Option<impl StreamExt<Item = SocketAddr> + Unpin + Send + Sync + 'static>,
) -> anyhow::Result<()> {
let mut g = self.locked.write();
match &g.state {
ManagedTorrentState::Live(_) => {
bail!("torrent is already live");
}
ManagedTorrentState::Initializing(init) => {
let init = init.clone();
let t = self.clone();
spawn(trace_span!("initialize_and_start"), async move {
match init.check().await {
Ok(paused) => {
let live = TorrentStateLive::new(paused);
t.locked.write().state = ManagedTorrentState::Live(live.clone());
let live = Arc::downgrade(&live);
spawn(trace_span!("peer_adder"), async move {
{
let live: Arc<TorrentStateLive> =
live.upgrade().context("no longer live")?;
for peer in initial_peers {
live.add_peer_if_not_seen(peer);
}
}
if let Some(mut peer_rx) = peer_rx {
while let Some(peer) = peer_rx.next().await {
live.upgrade()
.context("no longer live")?
.add_peer_if_not_seen(peer);
}
}
Ok(())
});
Ok(())
}
Err(err) => {
let result = anyhow::anyhow!("{:?}", err);
t.locked.write().state = ManagedTorrentState::Error(err);
Err(result)
}
}
});
Ok(())
}
ManagedTorrentState::Paused(_) => {
let paused = g.state.take().assert_paused();
let live = TorrentStateLive::new(paused);
g.state = ManagedTorrentState::Live(live);
Ok(())
}
ManagedTorrentState::Error(_) => {
bail!("starting torrents from error state not implemented")
}
ManagedTorrentState::None => bail!("bug: torrent is in empty state"),
}
}
pub fn pause(&self) -> anyhow::Result<()> {
let mut g = self.locked.write();
match &g.state {
ManagedTorrentState::Live(live) => {
let paused = live.pause()?;
g.state = ManagedTorrentState::Paused(paused);
Ok(())
}
ManagedTorrentState::Initializing(_) => {
bail!("torrent is initializing, can't pause");
}
ManagedTorrentState::Paused(_) => {
bail!("torrent is already paused");
}
ManagedTorrentState::Error(_) => {
bail!("can't pause torrent in error state")
}
ManagedTorrentState::None => bail!("bug: torrent is in empty state"),
}
}
pub async fn wait_until_completed(&self) -> anyhow::Result<()> {
// TODO: rewrite
self.live()
@ -191,8 +291,12 @@ impl ManagedTorrentBuilder {
overwrite: self.overwrite,
},
});
let initializing = TorrentStateInitializing::new(info.clone(), self.only_files);
let initializing = Arc::new(TorrentStateInitializing::new(
info.clone(),
self.only_files.clone(),
));
Arc::new(ManagedTorrent {
only_files: self.only_files,
locked: RwLock::new(ManagedTorrentLocked {
state: ManagedTorrentState::Initializing(initializing),
}),

View file

@ -14,3 +14,12 @@ pub struct TorrentStatePaused {
pub(crate) have_bytes: u64,
pub(crate) needed_bytes: u64,
}
// impl TorrentStatePaused {
// pub fn get_have_bytes(&self) -> u64 {
// self.have_bytes
// }
// pub fn get_needed_bytes(&self) -> u64 {
// self.needed_bytes
// }
// }