pub struct DownloadState {
pub config_path: PathBuf,
/* private fields */
}Expand description
On-disk state for an in-progress download, backing resume support.
DownloadState pairs a PartialDownloadStateInner (the persisted config,
whose fields may be absent if the .fd file predates them) with the path of
the .fd file and a dirty flag. It is the bridge between a saved .fd file
and a fresh crate::PartialConfig handed to
crate::resume: DownloadState::merge_config folds the
loaded progress into the new request so a resumed download continues from the
correct byte offset instead of restarting from zero.
DownloadState derefs to PartialDownloadStateInner, so the saved url,
etag, last_modified, config and size are reachable directly.
The inner state is wrapped in an Arc<Mutex<PartialDownloadStateInner>> to
provide a single source of truth shared between the engine loop, the
internal progress reporter, and any other readers/writers.
DownloadState is cheaply Cloneable: the clone shares the same inner state
and the same dirty flag (both behind Arc), so a download driver can hand a
clone to a background task that performs the periodic disk persist without
blocking the engine event loop.
Fields§
§config_path: PathBufImplementations§
Source§impl DownloadState
impl DownloadState
Sourcepub fn lock_inner(&self) -> MutexGuard<'_, PartialDownloadStateInner>
pub fn lock_inner(&self) -> MutexGuard<'_, PartialDownloadStateInner>
Returns a reference to the shared inner state, locked for reading.
Prefer this over the previous Deref-based field access.
Returns a clone of the shared Arc<Mutex<PartialDownloadStateInner>>,
for sharing the authoritative state with other tasks
(e.g. the internal progress reporter).
Sourcepub fn new(
url: &Url,
url_info: &UrlInfo,
config: &PartialConfig,
config_path: &Path,
) -> Self
pub fn new( url: &Url, url_info: &UrlInfo, config: &PartialConfig, config_path: &Path, ) -> Self
Build a fresh, dirty download state from the initial prefetch metadata.
url and url_info come from the prefetch step, config is the
caller-provided PartialConfig, and config_path is where the .fd
file will be written. The returned state is marked dirty so the first
DownloadState::store persists it.
Sourcepub async fn load(config_path: &Path) -> Result<Self, StateError>
pub async fn load(config_path: &Path) -> Result<Self, StateError>
Load a download state from disk.
§Errors
Returns an error if the file cannot be read or deserialized.
Sourcepub async fn store(&self) -> Result<(), StateError>
pub async fn store(&self) -> Result<(), StateError>
Persist the download state to disk.
This serializes a snapshot of the shared inner state and atomically
replaces the .fd file. It does not consult or clear the dirty flag;
callers decide when to persist (typically via DownloadState::take_dirty
on a fixed cadence, off the engine event loop). Safe to call from a
background task because the heavy safe_replace (disk write + fsync) runs
after the inner lock is released.
§Errors
Returns an error if serializing or writing the state fails.
Sourcepub fn take_dirty(&self) -> bool
pub fn take_dirty(&self) -> bool
Consume the dirty flag (swap to clean) and report whether it was dirty.
Used by the engine loop on a fixed cadence: a true return means “a
persist is due, hand the work to a background task”. Because the flag is
an Arc<AtomicBool> shared with any clones, the background task and the
loop observe the same flag.
Sourcepub fn mark_dirty(&self)
pub fn mark_dirty(&self)
Mark the state dirty so the next persist cycle rewrites the .fd.
Call this when a mutation lands (e.g. progress or identity changed) and
when a background DownloadState::store fails and should be retried.
Sourcepub fn update<F: FnOnce(&mut PartialDownloadStateInner) -> R, R>(
&self,
cb: F,
) -> R
pub fn update<F: FnOnce(&mut PartialDownloadStateInner) -> R, R>( &self, cb: F, ) -> R
Apply a mutation to the inner partial state and mark it dirty.
Any change made through cb (e.g. updating etag/last_modified or the
nested config) schedules the next DownloadState::store.
Sourcepub fn validate(&self, info: &UrlInfo) -> Result<(), StateError>
pub fn validate(&self, info: &UrlInfo) -> Result<(), StateError>
Check whether the server-side file is still the same one this state was saved for, so a resumed download continues from the correct offset.
The comparison requires the recorded size to match and (unless both
sides are missing identity headers) the FileId (etag +
last_modified) to be equal. Resumable downloads also require the
server to support range requests.
§Errors
Sourcepub fn get_progress(&self) -> Vec<ProgressEntry> ⓘ
pub fn get_progress(&self) -> Vec<ProgressEntry> ⓘ
Return the list of byte ranges already written to the .part file.
This is the authoritative on-disk progress. It is empty for a brand new
download and grows as DownloadState::merge_progress is called.
Sourcepub fn get_elapsed(&self) -> Duration
pub fn get_elapsed(&self) -> Duration
Total active download time accumulated so far, across all prior resume
runs. Duration::ZERO when nothing has been recorded yet.
Sourcepub fn snapshot(&self) -> ResumeInfo
pub fn snapshot(&self) -> ResumeInfo
产出一份只读快照,供 UI 等只读消费者读取进度元数据,而无需持有内部 MutexGuard。
与 DownloadState::lock_inner 不同,这里返回的是拥有所有权的 ResumeInfo,
调用方可以随意读取 url / size / progress / elapsed,不会触及引擎内部的并发原语。
Sourcepub fn set_elapsed(&self, elapsed: Duration)
pub fn set_elapsed(&self, elapsed: Duration)
Set the total accumulated active download time (absolute, not additive).
Called by the download driver as time accrues, so the value persisted on
the next DownloadState::store reflects the full session. Marks the
state dirty.
Sourcepub fn merge_progress(&self, range: ProgressEntry)
pub fn merge_progress(&self, range: ProgressEntry)
Merge a freshly-written byte range into the recorded progress.
The progress list is the authoritative set of on-disk ranges; new ranges are merged, de-duplicated and normalized. Marks the state dirty.
Sourcepub fn merge_config(&self, partial_config: &PartialConfig)
pub fn merge_config(&self, partial_config: &PartialConfig)
Fold a freshly-built PartialConfig into this loaded state for resume.
This is the key bridge that preserves download progress across a resume:
the ranges already recorded in self.config.downloaded_chunk are merged
into partial_config first, so that even if partial_config starts from
an empty progress list the resumed download keeps the already-downloaded
bytes. partial_config is then layered on top via
inherit_from, and the merged result replaces the stored
config. Marks the state dirty.
Sourcepub fn refresh_identity(&self, url: &Url, info: &UrlInfo)
pub fn refresh_identity(&self, url: &Url, info: &UrlInfo)
Refresh the recorded state for a new download session.
Two fields are refreshed on every (re)start of a download:
- The durable initial URL. The URL stored in the
.fdis the caller’s initial URL — the one passed todownload/resume. When the caller supplies a new URL (theSomecase) it takes priority and replaces any previously recorded URL, so a laterresume(None)still re-resolves the resource the caller actually wants. When the URL is itself read back from the.fd(aresume(None)), this assignment is a no-op. - The content identity headers (etag/last-modified/size), refreshed to the fresh server values from the current prefetch.
The redirect target (info.final_url) is deliberately never persisted:
such links are usually temporary signed/CDN URLs that expire, so writing one
into the .fd would poison the next resume. The download part targets
info.final_url directly for range requests, which also avoids a redirect
round-trip on every range request.
Sourcepub fn file_id(&self) -> FileId
pub fn file_id(&self) -> FileId
Reconstruct the identity of the file this state was saved for.
Returns a FileId from the stored etag / last_modified. Missing
headers collapse to None, which makes DownloadState::validate treat
“no identity on either side” as a match.
Sourcepub fn tmp_path(&self) -> PathBuf
pub fn tmp_path(&self) -> PathBuf
Path of the partial (.part) output file paired with this state.
Derived from config_path by swapping the extension to .part.
Sourcepub async fn part_shortfall(&self, tmp_path: &Path) -> Option<(u64, u64)>
pub async fn part_shortfall(&self, tmp_path: &Path) -> Option<(u64, u64)>
Measure tmp_path against the progress recorded in this state.
Returns Some((actual_size, recorded_size)) when the file is shorter
than the highest recorded offset — the state claims bytes that are not
on disk, so resuming from it would leave that span filled with zeros
that are never fetched.
Returns None when the file is long enough, is not a regular file, or
cannot be inspected; those cases surface later when the sink is built.
Trait Implementations§
Source§impl Clone for DownloadState
impl Clone for DownloadState
Source§fn clone(&self) -> DownloadState
fn clone(&self) -> DownloadState
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more