Complete upload progress bar implementation, simplify with arc/mutex

This commit is contained in:
timvisee 2018-03-19 21:52:20 +01:00
parent 030454cc10
commit b57e85a8ec
No known key found for this signature in database
GPG key ID: 109CBA0BF74036C2
4 changed files with 29 additions and 20 deletions

View file

@ -1,6 +1,7 @@
use std::fs::File;
use std::io::BufReader;
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};
use mime_guess::{get_mime_type, Mime};
use openssl::symm::encrypt_aead;
@ -24,8 +25,7 @@ use reader::{
use file::file::File as SendFile;
use file::metadata::{Metadata, XFileMetadata};
type EncryptedReader =
ProgressReader<'static, BufReader<EncryptedFileReaderTagged>>;
type EncryptedReader = ProgressReader<BufReader<EncryptedFileReaderTagged>>;
pub type Result<T> = ::std::result::Result<T, UploadError>;
/// A file upload action to a Send server.
@ -50,7 +50,7 @@ impl Upload {
pub fn invoke(
self,
client: &Client,
reporter: Box<ProgressReporter + 'static>,
reporter: Arc<Mutex<ProgressReporter>>,
) -> Result<SendFile> {
// Create file data, generate a key
let file = FileData::from(Box::new(&self.path))?;
@ -58,8 +58,8 @@ impl Upload {
// Crpate metadata and a file reader
let metadata = self.create_metadata(&key, &file)?;
// TODO: do not use leak, as it might cause memory leaks
let reader = self.create_reader(&key, Box::leak(reporter))?;
let reader = self.create_reader(&key, reporter.clone())?;
let reader_len = reader.len().unwrap();
// Create the request to send
let req = self.create_request(
@ -69,10 +69,18 @@ impl Upload {
reader,
);
// Start the reporter
reporter.lock()
.expect("unable to start progress, failed to get lock")
.start(reader_len);
// Execute the request
let result = self.execute_request(req, client, &key);
// TODO: finish the progress bar
// Mark the reporter as finished
reporter.lock()
.expect("unable to finish progress, failed to get lock")
.finish();
result
}
@ -112,7 +120,7 @@ impl Upload {
fn create_reader(
&self,
key: &KeySet,
reporter: &'static mut ProgressReporter,
reporter: Arc<Mutex<ProgressReporter>>,
) -> Result<EncryptedReader> {
// Open the file
let file = match File::open(self.path.as_path()) {
@ -139,8 +147,7 @@ impl Upload {
.expect("failed to create progress reader");
// Initialize and attach the reporter
reporter.start(reader.len().unwrap());
reader.set_reporter(&mut *reporter);
reader.set_reporter(reporter);
Ok(reader)
}

View file

@ -7,6 +7,7 @@ use std::io::{
Error as IoError,
Read,
};
use std::sync::{Arc, Mutex};
use openssl::symm::{
Cipher,
@ -236,7 +237,7 @@ unsafe impl Send for EncryptedFileReaderTagged {}
///
/// The reader will only start producing `None` if the wrapped reader is doing
/// so.
pub struct ProgressReader<'a, R> {
pub struct ProgressReader<R> {
/// The wrapped reader.
inner: R,
@ -247,10 +248,10 @@ pub struct ProgressReader<'a, R> {
progress: u64,
/// A reporter, to report the progress status to.
reporter: Option<&'a mut ProgressReporter>,
reporter: Option<Arc<Mutex<ProgressReporter>>>,
}
impl<'a, R: Read> ProgressReader<'a, R> {
impl<R: Read> ProgressReader<R> {
/// Wrap the given reader with an exact length, in a progress reader.
pub fn new(inner: R) -> Result<Self, IoError>
where
@ -277,7 +278,7 @@ impl<'a, R: Read> ProgressReader<'a, R> {
}
/// Set the reporter to report the status to.
pub fn set_reporter(&mut self, reporter: &'a mut ProgressReporter) {
pub fn set_reporter(&mut self, reporter: Arc<Mutex<ProgressReporter>>) {
self.reporter = Some(reporter);
}
@ -287,7 +288,7 @@ impl<'a, R: Read> ProgressReader<'a, R> {
}
}
impl<'a, R: Read> Read for ProgressReader<'a, R> {
impl<R: Read> Read for ProgressReader<R> {
/// Read from the encrypted file, and then the encryption tag.
fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
// Read from the wrapped reader, increase the progress
@ -301,14 +302,16 @@ impl<'a, R: Read> Read for ProgressReader<'a, R> {
// Report
if let Some(reporter) = self.reporter.as_mut() {
reporter.progress(self.progress);
reporter.lock()
.expect("failed to update progress, unable to lock reproter")
.progress(self.progress);
}
Ok(len)
}
}
impl<'a, R: Read> ExactLengthReader for ProgressReader<'a, R> {
impl<R: Read> ExactLengthReader for ProgressReader<R> {
// Return the specified length.
fn len(&self) -> Result<u64, io::Error> {
Ok(self.len)

View file

@ -1,5 +1,5 @@
use std::path::Path;
use std::sync::Arc;
use std::sync::{Arc, Mutex};
use ffsend_api::action::upload::Upload as ApiUpload;
use ffsend_api::reqwest::Client;
@ -34,7 +34,7 @@ impl<'a> Upload<'a> {
let client = Client::new();
// Create a progress bar reporter
let bar = Box::new(ProgressBar::new());
let bar = Arc::new(Mutex::new(ProgressBar::new()));
// Execute an upload action
// TODO: do not unwrap, but return an error

View file

@ -42,7 +42,6 @@ impl ProgressReporter for ProgressBar {
fn finish(&mut self) {
self.bar.as_mut()
.expect("progress bar not yet instantiated")
// TODO: print a proper message here
.finish_print("DONE");
.finish_print("File uploaded");
}
}