Compare commits

..

No commits in common. "30855ed8ffed683b244135adc4f97266a5c27095" and "f05e112040331a483ac8f48fa825f86e8660c404" have entirely different histories.

4 changed files with 44 additions and 59 deletions

View file

@ -8,15 +8,19 @@ use console::style;
use indicatif::{ProgressBar, ProgressStyle};
use log::{debug, warn};
use crate::file::Chunk;
use super::{
cachefile::CacheFile,
cli::Cli,
file::{self, Chunk, FileTrait},
file::{self, FileTrait},
sharry::{self, Client},
};
pub struct AppState {
progress: RefCell<Option<ProgressBar>>,
buffer: Vec<u8>,
http: ureq::Agent,
inner: CacheFile,
}
@ -37,9 +41,10 @@ fn new_http(timeout: Option<Duration>) -> ureq::Agent {
}
impl AppState {
fn new(http: ureq::Agent, inner: CacheFile) -> Self {
fn new(chunk_size: usize, http: ureq::Agent, inner: CacheFile) -> Self {
Self {
progress: RefCell::new(None),
progress: None.into(),
buffer: vec![0; chunk_size * 1024 * 1024],
http,
inner,
}
@ -50,7 +55,11 @@ impl AppState {
.inspect_err(|e| debug!("could not resume from hash {:?}: {e}", args.get_hash()))
.ok()?;
Some(Self::new(new_http(args.get_timeout()), inner))
Some(Self::new(
args.chunk_size,
new_http(args.get_timeout()),
inner,
))
}
pub fn from_args(args: &Cli) -> sharry::Result<Self> {
@ -62,7 +71,11 @@ impl AppState {
args.get_share_request(),
)?;
Ok(Self::new(http, CacheFile::from_args(args, share_id)))
Ok(Self::new(
args.chunk_size,
http,
CacheFile::from_args(args, share_id),
))
}
fn get_or_create_progressbar(&self, uploading: &file::Uploading) -> Ref<'_, ProgressBar> {
@ -101,7 +114,7 @@ impl AppState {
}
}
fn next_chunk<'t>(&mut self, buffer: &'t mut [u8]) -> io::Result<Option<Chunk<'t>>> {
fn next_chunk(&mut self) -> io::Result<Option<Chunk>> {
let Some(mut uploading) = self.inner.pop_file(&self.http) else {
self.inner
.share_notify(&self.http)
@ -109,14 +122,15 @@ impl AppState {
return Ok(None);
};
debug!("{uploading:?}");
self.get_or_create_progressbar(&uploading);
let chunk_res = uploading.read(buffer);
let chunk = uploading.read(&mut self.buffer);
self.inner.push_file(uploading);
let chunk = chunk?;
let chunk = chunk_res?;
debug!("{chunk:?}");
Ok(Some(chunk))
@ -132,7 +146,7 @@ impl AppState {
let bar = self.get_or_create_progressbar(&uploading);
bar.set_position(uploading.get_offset());
// BUG in `indicatif` crate?
// `set_position` does not force an immediate redraw, so we also call `inc_length` here
// `set_position` does not force immediate redraw, so we also call `inc_length` here
bar.inc_length(0);
drop(bar);
@ -147,8 +161,8 @@ impl AppState {
self.inner.is_empty()
}
pub fn upload_chunk(&mut self, buffer: &mut [u8]) -> sharry::Result<bool> {
let Some(chunk) = self.next_chunk(buffer)? else {
pub fn upload_chunk(&mut self) -> sharry::Result<bool> {
let Some(chunk) = self.next_chunk()? else {
return Ok(true);
};
@ -156,24 +170,12 @@ impl AppState {
chunk.get_patch_uri(),
self.inner.alias_id(),
chunk.get_offset(),
chunk.get_data(),
unsafe { chunk.get_data() },
)?;
Ok(self.is_done())
}
pub fn rewind(mut self) -> Option<Self> {
let Some(uploading) = self.inner.pop_file(&self.http) else {
warn!("rewind called on empty queue");
return None;
};
let uploading = uploading.rewind()?;
self.inner.push_file(uploading);
Some(self)
}
pub fn file_names(&self) -> Vec<&str> {
self.inner.file_names()
}

View file

@ -1,23 +1,25 @@
use std::fmt;
pub struct Chunk<'t> {
data: &'t [u8],
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: String, 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 {

View file

@ -4,7 +4,6 @@ use std::{
path::PathBuf,
};
use log::warn;
use serde::{Deserialize, Serialize};
use super::{Chunk, FileTrait};
@ -46,20 +45,14 @@ impl Uploading {
}
pub fn rewind(self) -> Option<Self> {
match self.last_offset {
Some(last_offset) => Some(Self {
last_offset: None,
offset: last_offset,
..self
}),
None => {
warn!("attempted to rewind twice");
None
}
}
self.last_offset.map(|last_offset| Self {
last_offset: None,
offset: last_offset,
..self
})
}
pub fn read<'t>(&mut self, buf: &'t mut [u8]) -> io::Result<Chunk<'t>> {
pub fn read(&mut self, buf: &mut [u8]) -> io::Result<Chunk> {
let mut f = fs::File::open(&self.path)?;
f.seek(SeekFrom::Start(self.offset))?;

View file

@ -113,21 +113,9 @@ fn main() {
style(state.file_names().join(", ")).magenta(),
);
let mut buffer = vec![0; args.chunk_size * 1024 * 1024];
loop {
match state.upload_chunk(&mut buffer) {
Err(e) => {
// HACK handle errors better
error!("error: {e:?}");
if let Some(s) = state.rewind() {
state = s;
} else {
eprintln!("{} Failed to retry chunk!", style("Error:").red().bold());
process::exit(1);
};
}
match state.upload_chunk() {
Err(e) => error!("error: {e:?}"), // HACK handle errors better
Ok(true) => {
info!("all uploads done");
state.clear().unwrap_or_else(|e| {