Use a Mutex to protect the URI storage

get_uri()/set_uri() can be called at any time from any thread, only
all other methods of Source/Sink are guaranteed to be called by only
a single thread at a time.
This commit is contained in:
Sebastian Dröge 2016-05-23 20:29:01 +03:00
parent 2d4dd7a218
commit 8514d46092
3 changed files with 45 additions and 24 deletions

View file

@ -21,13 +21,14 @@ use std::path::PathBuf;
use url::Url;
use std::io::Write;
use std::sync::Mutex;
use utils::*;
use rssink::*;
#[derive(Debug)]
pub struct FileSink {
location: Option<PathBuf>,
location: Mutex<Option<PathBuf>>,
file: Option<File>,
position: u64,
}
@ -37,7 +38,7 @@ unsafe impl Send for FileSink {}
impl FileSink {
fn new() -> FileSink {
FileSink { location: None, file: None, position: 0 }
FileSink { location: Mutex::new(None), file: None, position: 0 }
}
fn new_source() -> Box<Sink> {
@ -53,7 +54,8 @@ impl Sink for FileSink {
fn set_uri(&mut self, uri_str: Option<&str>) -> bool {
match uri_str {
None => {
self.location = None;
let mut location = self.location.lock().unwrap();
*location = None;
return true;
},
Some(ref uri_str) => {
@ -62,18 +64,21 @@ impl Sink for FileSink {
Ok(u) => {
match u.to_file_path().ok() {
Some(p) => {
self.location = Some(p);
let mut location = self.location.lock().unwrap();
*location = Some(p);
return true;
},
None => {
self.location = None;
let mut location = self.location.lock().unwrap();
*location = None;
println_err!("Unsupported file URI '{}'", uri_str);
return false;
}
}
},
Err(err) => {
self.location = None;
let mut location = self.location.lock().unwrap();
*location = None;
println_err!("Failed to parse URI '{}': {}", uri_str, err);
return false;
}
@ -83,7 +88,8 @@ impl Sink for FileSink {
}
fn get_uri(&self) -> Option<String> {
self.location.as_ref()
let location = self.location.lock().unwrap();
(*location).as_ref()
.map(|l| Url::from_file_path(l).ok())
.and_then(|i| i) // join()
.map(|u| u.into_string())
@ -93,7 +99,8 @@ impl Sink for FileSink {
self.file = None;
self.position = 0;
match self.location {
let location = self.location.lock().unwrap();
match *location {
None => return false,
Some(ref location) => {
match File::create(location.as_path()) {

View file

@ -19,6 +19,7 @@ use std::u64;
use std::io::{Read, Seek, SeekFrom};
use std::fs::File;
use std::path::PathBuf;
use std::sync::Mutex;
use url::Url;
use std::io::Write;
@ -28,7 +29,7 @@ use rssource::*;
#[derive(Debug)]
pub struct FileSrc {
location: Option<PathBuf>,
location: Mutex<Option<PathBuf>>,
file: Option<File>,
position: u64,
}
@ -38,7 +39,7 @@ unsafe impl Send for FileSrc {}
impl FileSrc {
fn new() -> FileSrc {
FileSrc { location: None, file: None, position: 0 }
FileSrc { location: Mutex::new(None), file: None, position: 0 }
}
fn new_source() -> Box<Source> {
@ -54,7 +55,8 @@ impl Source for FileSrc {
fn set_uri(&mut self, uri_str: Option<&str>) -> bool {
match uri_str {
None => {
self.location = None;
let mut location = self.location.lock().unwrap();
*location = None;
return true;
},
Some(ref uri_str) => {
@ -63,18 +65,21 @@ impl Source for FileSrc {
Ok(u) => {
match u.to_file_path().ok() {
Some(p) => {
self.location = Some(p);
let mut location = self.location.lock().unwrap();
*location = Some(p);
return true;
},
None => {
self.location = None;
let mut location = self.location.lock().unwrap();
*location = None;
println_err!("Unsupported file URI '{}'", uri_str);
return false;
}
}
},
Err(err) => {
self.location = None;
let mut location = self.location.lock().unwrap();
*location = None;
println_err!("Failed to parse URI '{}': {}", uri_str, err);
return false;
}
@ -84,7 +89,8 @@ impl Source for FileSrc {
}
fn get_uri(&self) -> Option<String> {
self.location.as_ref()
let location = self.location.lock().unwrap();
(*location).as_ref()
.map(|l| Url::from_file_path(l).ok())
.and_then(|i| i) // join()
.map(|u| u.into_string())
@ -105,8 +111,9 @@ impl Source for FileSrc {
fn start(&mut self) -> bool {
self.file = None;
self.position = 0;
let location = self.location.lock().unwrap();
match self.location {
match *location {
None => return false,
Some(ref location) => {
match File::open(location.as_path()) {

View file

@ -23,13 +23,14 @@ use hyper::client::Client;
use hyper::client::response::Response;
use std::io::Write;
use std::sync::Mutex;
use utils::*;
use rssource::*;
#[derive(Debug)]
pub struct HttpSrc {
url: Option<Url>,
url: Mutex<Option<Url>>,
client: Client,
response: Option<Response>,
seekable: bool,
@ -44,7 +45,7 @@ unsafe impl Send for HttpSrc {}
impl HttpSrc {
fn new() -> HttpSrc {
HttpSrc { url: None, client: Client::new(), response: None, seekable: false, position: 0, size: u64::MAX, start: 0, stop: u64::MAX }
HttpSrc { url: Mutex::new(None), client: Client::new(), response: None, seekable: false, position: 0, size: u64::MAX, start: 0, stop: u64::MAX }
}
fn new_source() -> Box<Source> {
@ -61,7 +62,8 @@ impl HttpSrc {
self.position = 0;
self.size = u64::MAX;
match self.url {
let url = self.url.lock().unwrap();
match *url {
None => return false,
Some(ref url) => {
let mut req = self.client.get(url.clone());
@ -131,7 +133,8 @@ impl Source for HttpSrc {
match uri_str {
None => {
self.url = None;
let mut url = self.url.lock().unwrap();
*url = None;
return true;
},
Some(ref uri_str) => {
@ -140,16 +143,19 @@ impl Source for HttpSrc {
Ok(u) => {
if u.scheme() == "http" ||
u.scheme() == "https" {
self.url = Some(u);
let mut url = self.url.lock().unwrap();
*url = Some(u);
return true;
} else {
self.url = None;
let mut url = self.url.lock().unwrap();
*url = None;
println_err!("Unsupported file URI '{}'", uri_str);
return false;
}
},
Err(err) => {
self.url = None;
let mut url = self.url.lock().unwrap();
*url = None;
println_err!("Failed to parse URI '{}': {}", uri_str, err);
return false;
}
@ -159,7 +165,8 @@ impl Source for HttpSrc {
}
fn get_uri(&self) -> Option<String> {
self.url.as_ref().map(|u| String::from(u.as_str()))
let url = self.url.lock().unwrap();
(*url).as_ref().map(|u| String::from(u.as_str()))
}
fn is_seekable(&self) -> bool {