chore: initial sanitized public snapshot
This commit is contained in:
@@ -0,0 +1,198 @@
|
||||
use super::{
|
||||
BtPeerInfo, BtPeerMutationResult, BtPieceAvailabilityMutationResult, BtPieceAvailabilityUpdate,
|
||||
BtPieceBlockUpdate, BtPieceMutationResult, BtRuntimeTickResult, BtTrackerInfo, CoreError,
|
||||
DownloadEngine, DownloadId, Result,
|
||||
};
|
||||
|
||||
impl DownloadEngine {
|
||||
/// Replaces the full BT peer snapshot for a download.
|
||||
pub fn apply_bt_peer_snapshot(
|
||||
&mut self,
|
||||
gid: DownloadId,
|
||||
peers: Vec<BtPeerInfo>,
|
||||
) -> Result<()> {
|
||||
let group = self.group_mut(gid)?;
|
||||
if group.bt().is_none() {
|
||||
return Err(CoreError::InvalidState(
|
||||
"bt runtime state is not initialized",
|
||||
));
|
||||
}
|
||||
let _ = group.replace_bt_peer_snapshot(peers);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Applies an incremental BT peer update to a download.
|
||||
pub fn apply_bt_peer_update(
|
||||
&mut self,
|
||||
gid: DownloadId,
|
||||
peer: BtPeerInfo,
|
||||
) -> Result<BtPeerMutationResult> {
|
||||
let group = self.group_mut(gid)?;
|
||||
if group.bt().is_none() {
|
||||
return Err(CoreError::InvalidState(
|
||||
"bt runtime state is not initialized",
|
||||
));
|
||||
}
|
||||
Ok(group.apply_bt_peer_update(peer))
|
||||
}
|
||||
|
||||
/// Applies an incremental BT piece availability update to a download.
|
||||
pub fn apply_bt_piece_availability_update(
|
||||
&mut self,
|
||||
gid: DownloadId,
|
||||
update: BtPieceAvailabilityUpdate,
|
||||
) -> Result<BtPieceAvailabilityMutationResult> {
|
||||
let group = self.group_mut(gid)?;
|
||||
if group.bt().is_none() {
|
||||
return Err(CoreError::InvalidState(
|
||||
"bt runtime state is not initialized",
|
||||
));
|
||||
}
|
||||
Ok(group.apply_bt_piece_availability_update(update))
|
||||
}
|
||||
|
||||
/// Applies an incremental BT block-completion update to a download.
|
||||
pub fn apply_bt_piece_block_update(
|
||||
&mut self,
|
||||
gid: DownloadId,
|
||||
update: BtPieceBlockUpdate,
|
||||
) -> Result<BtPieceMutationResult> {
|
||||
let group = self.group_mut(gid)?;
|
||||
if group.bt().is_none() {
|
||||
return Err(CoreError::InvalidState(
|
||||
"bt runtime state is not initialized",
|
||||
));
|
||||
}
|
||||
Ok(group.apply_bt_piece_block_update(update))
|
||||
}
|
||||
|
||||
#[expect(
|
||||
clippy::too_many_arguments,
|
||||
reason = "BT runtime tick mirrors the RPC-visible counters updated together by one event"
|
||||
)]
|
||||
/// Applies a full BT runtime tick, including byte deltas, speeds, timers, and connection count.
|
||||
pub fn apply_bt_runtime_tick(
|
||||
&mut self,
|
||||
gid: DownloadId,
|
||||
downloaded_delta: u64,
|
||||
uploaded_delta: u64,
|
||||
download_speed: u64,
|
||||
upload_speed: u64,
|
||||
share_time_delta_secs: u64,
|
||||
seeding_time_delta_secs: u64,
|
||||
seeding: bool,
|
||||
num_connections: Option<u32>,
|
||||
) -> Result<BtRuntimeTickResult> {
|
||||
let group = self.group_mut(gid)?;
|
||||
if group.bt().is_none() {
|
||||
return Err(CoreError::InvalidState(
|
||||
"bt runtime state is not initialized",
|
||||
));
|
||||
}
|
||||
Ok(group.apply_bt_runtime_tick(
|
||||
downloaded_delta,
|
||||
uploaded_delta,
|
||||
download_speed,
|
||||
upload_speed,
|
||||
share_time_delta_secs,
|
||||
seeding_time_delta_secs,
|
||||
seeding,
|
||||
num_connections,
|
||||
))
|
||||
}
|
||||
|
||||
/// Advances BT share/seeding timers to `now_unix_secs`.
|
||||
pub fn tick_bt_runtime_clock(
|
||||
&mut self,
|
||||
gid: DownloadId,
|
||||
now_unix_secs: u64,
|
||||
seeding: bool,
|
||||
) -> Result<BtRuntimeTickResult> {
|
||||
let group = self.group_mut(gid)?;
|
||||
if group.bt().is_none() {
|
||||
return Err(CoreError::InvalidState(
|
||||
"bt runtime state is not initialized",
|
||||
));
|
||||
}
|
||||
Ok(group.tick_bt_runtime_clock(now_unix_secs, seeding))
|
||||
}
|
||||
|
||||
/// Toggles BT seeding state while preserving share-runtime accounting.
|
||||
pub fn set_bt_seeding_state(
|
||||
&mut self,
|
||||
gid: DownloadId,
|
||||
seeding: bool,
|
||||
at_unix_secs: Option<u64>,
|
||||
) -> Result<BtRuntimeTickResult> {
|
||||
let group = self.group_mut(gid)?;
|
||||
if group.bt().is_none() {
|
||||
return Err(CoreError::InvalidState(
|
||||
"bt runtime state is not initialized",
|
||||
));
|
||||
}
|
||||
Ok(group.set_bt_seeding_state(seeding, at_unix_secs))
|
||||
}
|
||||
|
||||
/// Upserts a BT tracker runtime snapshot keyed by tracker URL.
|
||||
pub fn apply_bt_tracker_snapshot(
|
||||
&mut self,
|
||||
gid: DownloadId,
|
||||
tracker_url: &str,
|
||||
tracker_id: Option<String>,
|
||||
seeders: Option<u32>,
|
||||
leechers: Option<u32>,
|
||||
) -> Result<()> {
|
||||
let group = self.group_mut(gid)?;
|
||||
let bt = group.bt_mut().ok_or(CoreError::InvalidState(
|
||||
"bt runtime state is not initialized",
|
||||
))?;
|
||||
if let Some(tracker) = bt
|
||||
.trackers
|
||||
.iter_mut()
|
||||
.find(|tracker| tracker.url == tracker_url)
|
||||
{
|
||||
if let Some(tracker_id) = tracker_id {
|
||||
tracker.id = Some(tracker_id);
|
||||
}
|
||||
if seeders.is_some() {
|
||||
tracker.seeders = seeders;
|
||||
}
|
||||
if leechers.is_some() {
|
||||
tracker.leechers = leechers;
|
||||
}
|
||||
} else {
|
||||
bt.trackers.push(BtTrackerInfo {
|
||||
url: tracker_url.to_owned(),
|
||||
tier: None,
|
||||
id: tracker_id,
|
||||
seeders,
|
||||
leechers,
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Records BT byte deltas and timer deltas without changing live speed counters.
|
||||
pub fn record_bt_runtime_tick(
|
||||
&mut self,
|
||||
gid: DownloadId,
|
||||
downloaded_delta: u64,
|
||||
uploaded_delta: u64,
|
||||
share_time_delta_secs: u64,
|
||||
seeding_time_delta_secs: u64,
|
||||
seeding: bool,
|
||||
) -> Result<()> {
|
||||
let _ = self.apply_bt_runtime_tick(
|
||||
gid,
|
||||
downloaded_delta,
|
||||
uploaded_delta,
|
||||
0,
|
||||
0,
|
||||
share_time_delta_secs,
|
||||
seeding_time_delta_secs,
|
||||
seeding,
|
||||
None,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user