Seems alright now

This commit is contained in:
Igor Katson 2023-11-25 00:54:21 +00:00
parent 17b243921d
commit fa97dedb98
No known key found for this signature in database
GPG key ID: B4EC22B66D61A3F5
5 changed files with 50 additions and 31 deletions

View file

@ -87,6 +87,16 @@ impl ChunkTracker {
self.needed_pieces.set(index.get() as usize, false) self.needed_pieces.set(index.get() as usize, false)
} }
pub fn calc_have_bytes(&self) -> u64 {
self.have
.iter_ones()
.filter_map(|piece_id| {
let piece_id = self.lengths.validate_piece_index(piece_id as u32)?;
Some(self.lengths.piece_length(piece_id) as u64)
})
.sum()
}
pub fn iter_needed_pieces(&self) -> impl Iterator<Item = usize> + '_ { pub fn iter_needed_pieces(&self) -> impl Iterator<Item = usize> + '_ {
self.priority_piece_ids self.priority_piece_ids
.iter() .iter()

View file

@ -167,9 +167,7 @@ pub struct TorrentStateLive {
files: Vec<Arc<Mutex<File>>>, files: Vec<Arc<Mutex<File>>>,
filenames: Vec<PathBuf>, filenames: Vec<PathBuf>,
// TODO: why the hell do we need these here, remove it. initially_needed_bytes: u64,
needed_bytes: u64,
have_plus_needed_bytes: u64,
stats: AtomicStats, stats: AtomicStats,
lengths: Lengths, lengths: Lengths,
@ -213,8 +211,7 @@ impl TorrentStateLive {
have_bytes: AtomicU64::new(have_bytes), have_bytes: AtomicU64::new(have_bytes),
..Default::default() ..Default::default()
}, },
needed_bytes, initially_needed_bytes: needed_bytes,
have_plus_needed_bytes: needed_bytes + have_bytes,
lengths, lengths,
peer_semaphore: Semaphore::new(128), peer_semaphore: Semaphore::new(128),
peer_queue_tx, peer_queue_tx,
@ -454,7 +451,7 @@ impl TorrentStateLive {
FileOps::new(&self.meta.info, &self.files, &self.lengths) FileOps::new(&self.meta.info, &self.files, &self.lengths)
} }
pub fn initially_needed(&self) -> u64 { pub fn initially_needed(&self) -> u64 {
self.needed_bytes self.initially_needed_bytes
} }
pub(crate) fn lock_read( pub(crate) fn lock_read(
@ -518,7 +515,7 @@ impl TorrentStateLive {
.load(Ordering::Acquire) .load(Ordering::Acquire)
} }
pub fn get_have_bytes(&self) -> u64 { pub fn get_approx_have_bytes(&self) -> u64 {
self.stats.have_bytes.load(Ordering::Relaxed) self.stats.have_bytes.load(Ordering::Relaxed)
} }
@ -527,7 +524,7 @@ impl TorrentStateLive {
} }
pub fn get_left_to_download_bytes(&self) -> u64 { pub fn get_left_to_download_bytes(&self) -> u64 {
self.needed_bytes - self.get_downloaded_bytes() self.initially_needed_bytes - self.get_downloaded_bytes()
} }
fn maybe_transmit_haves(&self, index: ValidPieceIndex) { fn maybe_transmit_haves(&self, index: ValidPieceIndex) {
@ -601,15 +598,15 @@ impl TorrentStateLive {
pub fn stats_snapshot(&self) -> StatsSnapshot { pub fn stats_snapshot(&self) -> StatsSnapshot {
use Ordering::*; use Ordering::*;
let downloaded_bytes = self.stats.downloaded_and_checked_bytes.load(Relaxed); let downloaded_bytes = self.stats.downloaded_and_checked_bytes.load(Relaxed);
let remaining = self.needed_bytes - downloaded_bytes; let remaining = self.initially_needed_bytes - downloaded_bytes;
StatsSnapshot { StatsSnapshot {
have_bytes: self.stats.have_bytes.load(Relaxed), have_bytes: self.stats.have_bytes.load(Relaxed),
downloaded_and_checked_bytes: downloaded_bytes, downloaded_and_checked_bytes: downloaded_bytes,
downloaded_and_checked_pieces: self.stats.downloaded_and_checked_pieces.load(Relaxed), downloaded_and_checked_pieces: self.stats.downloaded_and_checked_pieces.load(Relaxed),
fetched_bytes: self.stats.fetched_bytes.load(Relaxed), fetched_bytes: self.stats.fetched_bytes.load(Relaxed),
uploaded_bytes: self.stats.uploaded_bytes.load(Relaxed), uploaded_bytes: self.stats.uploaded_bytes.load(Relaxed),
total_bytes: self.have_plus_needed_bytes, total_bytes: self.lengths.total_length(),
initially_needed_bytes: self.needed_bytes, initially_needed_bytes: self.initially_needed_bytes,
remaining_bytes: remaining, remaining_bytes: remaining,
total_piece_download_ms: self.stats.total_piece_download_ms.load(Relaxed), total_piece_download_ms: self.stats.total_piece_download_ms.load(Relaxed),
peer_stats: self.peers.stats(), peer_stats: self.peers.stats(),
@ -653,16 +650,22 @@ impl TorrentStateLive {
let filenames = self.filenames.clone(); let filenames = self.filenames.clone();
let mut chunk_tracker = g
.chunks
.take()
.context("bug: pausing already paused torrent")?;
for piece_id in g.inflight_pieces.keys().copied() {
chunk_tracker.mark_piece_broken(piece_id);
}
let have_bytes = chunk_tracker.calc_have_bytes();
// g.chunks; // g.chunks;
Ok(TorrentStatePaused { Ok(TorrentStatePaused {
info: self.meta.clone(), info: self.meta.clone(),
files, files,
filenames, filenames,
chunk_tracker: g chunk_tracker,
.chunks have_bytes,
.take()
.context("bug: pausing already paused torrent")?,
have_bytes: self.get_have_bytes(),
}) })
} }
} }
@ -765,7 +768,7 @@ impl<'a> PeerConnectionHandler for &'a PeerHandler {
} }
fn get_have_bytes(&self) -> u64 { fn get_have_bytes(&self) -> u64 {
self.state.get_have_bytes() self.state.get_approx_have_bytes()
} }
} }

File diff suppressed because one or more lines are too long

View file

@ -8,6 +8,8 @@
<!-- Include Bootstrap CSS --> <!-- Include Bootstrap CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"
integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous" /> integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css"
integrity="sha384-4LISF5TTJX/fLmGSxO53rV4miRxdg84mZsxmO8Rx5jGtp/LbrixFETvWa5a6sESd" crossorigin="anonymous">
<script type="module" crossorigin src="app.js"></script> <script type="module" crossorigin src="app.js"></script>
</head> </head>

View file

@ -1,7 +1,7 @@
import { MouseEventHandler, StrictMode, createContext, useContext, useEffect, useRef, useState } from 'react'; import { MouseEventHandler, StrictMode, createContext, useContext, useEffect, useRef, useState } from 'react';
import ReactDOM from 'react-dom/client'; import ReactDOM from 'react-dom/client';
import { ProgressBar, Button, Container, Row, Col, Alert, Modal, Form, Spinner, Table } from 'react-bootstrap'; import { ProgressBar, Button, Container, Row, Col, Alert, Modal, Form, Spinner, Table } from 'react-bootstrap';
import { AddTorrentResponse, TorrentDetails, TorrentFile, TorrentId, TorrentStats, ErrorDetails, API, STATE_INITIALIZING, STATE_LIVE } from './api'; import { AddTorrentResponse, TorrentDetails, TorrentFile, TorrentId, TorrentStats, ErrorDetails, API, STATE_INITIALIZING, STATE_LIVE, STATE_PAUSED } from './api';
interface Error { interface Error {
text: string, text: string,
@ -161,7 +161,7 @@ const TorrentRow: React.FC<{
const progressPercentage = error ? 100 : (progressBytes / totalBytes) * 100; const progressPercentage = error ? 100 : (progressBytes / totalBytes) * 100;
const isAnimated = (state == STATE_INITIALIZING || state == STATE_LIVE) && !finished; const isAnimated = (state == STATE_INITIALIZING || state == STATE_LIVE) && !finished;
const progressLabel = error ? 'Error' : `${progressPercentage.toFixed(2)}%`; const progressLabel = error ? 'Error' : `${progressPercentage.toFixed(2)}%`;
const progressBarVariant = error ? 'danger' : finished ? 'success' : 'info'; const progressBarVariant = error ? 'danger' : finished ? 'success' : 'primary';
const formatPeersString = () => { const formatPeersString = () => {
let peer_stats = statsResponse?.live?.snapshot.peer_stats; let peer_stats = statsResponse?.live?.snapshot.peer_stats;
@ -206,8 +206,12 @@ const TorrentRow: React.FC<{
{statsResponse ? {statsResponse ?
<> <>
<Column label="Size">{`${formatBytes(totalBytes)} `}</Column> <Column label="Size">{`${formatBytes(totalBytes)} `}</Column>
<Column size={2} label="Progress"> <Column size={2} label={state == STATE_PAUSED ? 'Progress (PAUSED)' : 'Progress'}>
<ProgressBar now={progressPercentage} label={progressLabel} animated={isAnimated} variant={progressBarVariant} /> <ProgressBar
now={progressPercentage}
label={progressLabel}
animated={isAnimated}
variant={progressBarVariant} />
</Column> </Column>
<Column size={2} label="Down Speed">{formatDownloadSped()}</Column> <Column size={2} label="Down Speed">{formatDownloadSped()}</Column>
<Column label="ETA">{getCompletionETA(statsResponse)}</Column> <Column label="ETA">{getCompletionETA(statsResponse)}</Column>