From f05e112040331a483ac8f48fa825f86e8660c404 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn-Michael=20Miehe?= <40151420+ldericher@users.noreply.github.com> Date: Fri, 13 Jun 2025 17:03:25 +0000 Subject: [PATCH] [wip] retry chunks - make `Chunk` lifetime agnostic by using a raw pointer - add `fn Uploading::rewind` - add `fn AppState::{next_chunk, is_done}` --- src/appstate.rs | 47 +++++++++++++++++++++++++++++-------------- src/file/chunk.rs | 22 +++++++++++--------- src/file/uploading.rs | 15 ++++++++++++-- 3 files changed, 57 insertions(+), 27 deletions(-) diff --git a/src/appstate.rs b/src/appstate.rs index 155fc35..979f03f 100644 --- a/src/appstate.rs +++ b/src/appstate.rs @@ -8,11 +8,13 @@ use console::style; use indicatif::{ProgressBar, ProgressStyle}; use log::{debug, warn}; +use crate::file::Chunk; + use super::{ cachefile::CacheFile, cli::Cli, file::{self, FileTrait}, - sharry::{self, Client, ClientError}, + sharry::{self, Client}, }; pub struct AppState { @@ -112,31 +114,32 @@ impl AppState { } } - pub fn upload_chunk(&mut self) -> sharry::Result { + fn next_chunk(&mut self) -> io::Result> { let Some(mut uploading) = self.inner.pop_file(&self.http) else { self.inner .share_notify(&self.http) .unwrap_or_else(|e| warn!("Failed to notify the share: {e}")); - return Ok(true); + return Ok(None); }; debug!("{uploading:?}"); self.get_or_create_progressbar(&uploading); - let chunk = uploading - .read(&mut self.buffer) - .map_err(ClientError::from)?; + let chunk = uploading.read(&mut self.buffer); + self.inner.push_file(uploading); + let chunk = chunk?; debug!("{chunk:?}"); - self.http.file_patch( - chunk.get_patch_uri(), - self.inner.alias_id(), - chunk.get_offset(), - chunk.get_data(), - )?; + Ok(Some(chunk)) + } + + fn is_done(&mut self) -> bool { + let Some(uploading) = self.inner.pop_file(&self.http) else { + return true; + }; match uploading.check_eof() { Ok(uploading) => { @@ -148,15 +151,29 @@ impl AppState { drop(bar); self.inner.push_file(uploading); - Ok(false) } Err(path) => { debug!("Finished {:?}!", path.display()); self.finish_progressbar(); - - Ok(self.inner.is_empty()) } } + + self.inner.is_empty() + } + + pub fn upload_chunk(&mut self) -> sharry::Result { + let Some(chunk) = self.next_chunk()? else { + return Ok(true); + }; + + self.http.file_patch( + chunk.get_patch_uri(), + self.inner.alias_id(), + chunk.get_offset(), + unsafe { chunk.get_data() }, + )?; + + Ok(self.is_done()) } pub fn file_names(&self) -> Vec<&str> { diff --git a/src/file/chunk.rs b/src/file/chunk.rs index 8f69dd2..8cf3c49 100644 --- a/src/file/chunk.rs +++ b/src/file/chunk.rs @@ -1,23 +1,25 @@ use std::fmt; -pub struct Chunk<'t> { - data: &'t [u8], - patch_uri: &'t str, +pub struct Chunk { + data: *const [u8], + patch_uri: String, offset: u64, } -impl fmt::Debug for Chunk<'_> { +impl fmt::Debug for Chunk { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Chunk") .field("patch_uri", &self.patch_uri) .field("offset", &self.offset) - .field("data.len()", &self.data.len()) + .field("data_len", &self.data.len()) .finish_non_exhaustive() } } -impl<'t> Chunk<'t> { - pub fn new(data: &'t [u8], patch_uri: &'t str, offset: u64) -> Self { +impl Chunk { + pub fn new(data: &[u8], patch_uri: String, offset: u64) -> Self { + let data: *const [u8] = data as *const [u8]; + Self { data, patch_uri, @@ -25,8 +27,8 @@ impl<'t> Chunk<'t> { } } - pub fn get_data(&self) -> &[u8] { - self.data + pub unsafe fn get_data(&self) -> &[u8] { + unsafe { &*self.data } } pub fn get_length(&self) -> u64 { @@ -39,7 +41,7 @@ impl<'t> Chunk<'t> { } pub fn get_patch_uri(&self) -> &str { - self.patch_uri + &self.patch_uri } pub fn get_offset(&self) -> u64 { diff --git a/src/file/uploading.rs b/src/file/uploading.rs index 26a83e7..2831bcd 100644 --- a/src/file/uploading.rs +++ b/src/file/uploading.rs @@ -13,6 +13,7 @@ pub struct Uploading { path: PathBuf, size: u64, patch_uri: String, + last_offset: Option, offset: u64, } @@ -34,6 +35,7 @@ impl Uploading { path, size, patch_uri, + last_offset: None, offset: 0, } } @@ -42,7 +44,15 @@ impl Uploading { self.offset } - pub fn read<'t>(&'t mut self, buf: &'t mut [u8]) -> io::Result> { + pub fn rewind(self) -> Option { + self.last_offset.map(|last_offset| Self { + last_offset: None, + offset: last_offset, + ..self + }) + } + + pub fn read(&mut self, buf: &mut [u8]) -> io::Result { let mut f = fs::File::open(&self.path)?; f.seek(SeekFrom::Start(self.offset))?; @@ -55,7 +65,8 @@ impl Uploading { )); } - let chunk = Chunk::new(&buf[..read_len], &self.patch_uri, self.offset); + let chunk = Chunk::new(&buf[..read_len], self.patch_uri.clone(), self.offset); + self.last_offset = Some(self.offset); self.offset += chunk.get_length(); Ok(chunk)