parent
a20e7ac5c2
commit
58679db790
|
@ -48,15 +48,17 @@ use std::fs;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
use std::os::unix::ffi::OsStrExt;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::result;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
extern crate fnv;
|
extern crate fnv;
|
||||||
use self::fnv::FnvHashMap;
|
use self::fnv::{FnvHashMap, FnvHasher};
|
||||||
|
|
||||||
/// `BackendOp` implementor for Maildir
|
/// `BackendOp` implementor for Maildir
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MaildirOp {
|
pub struct MaildirOp {
|
||||||
hash_index: Arc<Mutex<FnvHashMap<u64, (usize, String)>>>,
|
hash_index: Arc<Mutex<FnvHashMap<u64, (usize, PathBuf)>>>,
|
||||||
hash: u64,
|
hash: u64,
|
||||||
slice: Option<Mmap>,
|
slice: Option<Mmap>,
|
||||||
}
|
}
|
||||||
|
@ -72,14 +74,14 @@ impl Clone for MaildirOp {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MaildirOp {
|
impl MaildirOp {
|
||||||
pub fn new(hash: u64, hash_index: Arc<Mutex<FnvHashMap<u64, (usize, String)>>>) -> Self {
|
pub fn new(hash: u64, hash_index: Arc<Mutex<FnvHashMap<u64, (usize, PathBuf)>>>) -> Self {
|
||||||
MaildirOp {
|
MaildirOp {
|
||||||
hash_index,
|
hash_index,
|
||||||
hash,
|
hash,
|
||||||
slice: None,
|
slice: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn path(&self) -> String {
|
fn path(&self) -> PathBuf {
|
||||||
let hash_index = self.hash_index.clone();
|
let hash_index = self.hash_index.clone();
|
||||||
let map = hash_index.lock().unwrap();
|
let map = hash_index.lock().unwrap();
|
||||||
map.get(&self.hash).unwrap().1.clone()
|
map.get(&self.hash).unwrap().1.clone()
|
||||||
|
@ -88,7 +90,7 @@ impl MaildirOp {
|
||||||
|
|
||||||
impl<'a> BackendOp for MaildirOp {
|
impl<'a> BackendOp for MaildirOp {
|
||||||
fn description(&self) -> String {
|
fn description(&self) -> String {
|
||||||
format!("Path of file: {}", self.path())
|
format!("Path of file: {}", self.path().display())
|
||||||
}
|
}
|
||||||
fn as_bytes(&mut self) -> Result<&[u8]> {
|
fn as_bytes(&mut self) -> Result<&[u8]> {
|
||||||
if self.slice.is_none() {
|
if self.slice.is_none() {
|
||||||
|
@ -110,6 +112,7 @@ impl<'a> BackendOp for MaildirOp {
|
||||||
fn fetch_flags(&self) -> Flag {
|
fn fetch_flags(&self) -> Flag {
|
||||||
let mut flag = Flag::default();
|
let mut flag = Flag::default();
|
||||||
let path = self.path();
|
let path = self.path();
|
||||||
|
let path = path.to_str().unwrap(); // Assume UTF-8 validity
|
||||||
if !path.contains(":2,") {
|
if !path.contains(":2,") {
|
||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
|
@ -132,6 +135,7 @@ impl<'a> BackendOp for MaildirOp {
|
||||||
|
|
||||||
fn set_flag(&mut self, envelope: &mut Envelope, f: &Flag) -> Result<()> {
|
fn set_flag(&mut self, envelope: &mut Envelope, f: &Flag) -> Result<()> {
|
||||||
let path = self.path();
|
let path = self.path();
|
||||||
|
let path = path.to_str().unwrap(); // Assume UTF-8 validity
|
||||||
let idx: usize = path
|
let idx: usize = path
|
||||||
.rfind(":2,")
|
.rfind(":2,")
|
||||||
.ok_or_else(|| MeliError::new(format!("Invalid email filename: {:?}", self)))?
|
.ok_or_else(|| MeliError::new(format!("Invalid email filename: {:?}", self)))?
|
||||||
|
@ -165,7 +169,7 @@ impl<'a> BackendOp for MaildirOp {
|
||||||
let hash = envelope.hash();
|
let hash = envelope.hash();
|
||||||
let hash_index = self.hash_index.clone();
|
let hash_index = self.hash_index.clone();
|
||||||
let mut map = hash_index.lock().unwrap();
|
let mut map = hash_index.lock().unwrap();
|
||||||
map.get_mut(&hash).unwrap().1 = new_name;
|
map.get_mut(&hash).unwrap().1 = PathBuf::from(new_name);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -175,9 +179,9 @@ impl<'a> BackendOp for MaildirOp {
|
||||||
pub struct MaildirType {
|
pub struct MaildirType {
|
||||||
name: String,
|
name: String,
|
||||||
folders: Vec<MaildirFolder>,
|
folders: Vec<MaildirFolder>,
|
||||||
hash_index: Arc<Mutex<FnvHashMap<u64, (usize, String)>>>,
|
hash_index: Arc<Mutex<FnvHashMap<u64, (usize, PathBuf)>>>,
|
||||||
|
|
||||||
path: String,
|
path: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MailBackend for MaildirType {
|
impl MailBackend for MaildirType {
|
||||||
|
@ -288,7 +292,7 @@ impl MaildirType {
|
||||||
0,
|
0,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
))),
|
))),
|
||||||
path: f.root_folder().to_string(),
|
path: PathBuf::from(f.root_folder()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn owned_folder_idx(&self, folder: &Folder) -> usize {
|
fn owned_folder_idx(&self, folder: &Folder) -> usize {
|
||||||
|
@ -302,6 +306,7 @@ impl MaildirType {
|
||||||
|
|
||||||
pub fn multicore(&mut self, cores: usize, folder: &Folder) -> Async<Result<Vec<Envelope>>> {
|
pub fn multicore(&mut self, cores: usize, folder: &Folder) -> Async<Result<Vec<Envelope>>> {
|
||||||
let mut w = AsyncBuilder::new();
|
let mut w = AsyncBuilder::new();
|
||||||
|
let root_path = self.path.to_path_buf();
|
||||||
let cache_dir = xdg::BaseDirectories::with_profile("meli", &self.name).unwrap();
|
let cache_dir = xdg::BaseDirectories::with_profile("meli", &self.name).unwrap();
|
||||||
let handle = {
|
let handle = {
|
||||||
let tx = w.tx();
|
let tx = w.tx();
|
||||||
|
@ -319,12 +324,12 @@ impl MaildirType {
|
||||||
path.push("cur");
|
path.push("cur");
|
||||||
let iter = path.read_dir()?;
|
let iter = path.read_dir()?;
|
||||||
let count = path.read_dir()?.count();
|
let count = path.read_dir()?.count();
|
||||||
let mut files: Vec<String> = Vec::with_capacity(count);
|
let mut files: Vec<PathBuf> = Vec::with_capacity(count);
|
||||||
let mut r = Vec::with_capacity(count);
|
let mut r = Vec::with_capacity(count);
|
||||||
for e in iter {
|
for e in iter {
|
||||||
let e = e.and_then(|x| {
|
let e = e.and_then(|x| {
|
||||||
let path = x.path();
|
let path = x.path();
|
||||||
Ok(path.to_str().unwrap().to_string())
|
Ok(path)
|
||||||
})?;
|
})?;
|
||||||
files.push(e);
|
files.push(e);
|
||||||
}
|
}
|
||||||
|
@ -341,6 +346,7 @@ impl MaildirType {
|
||||||
let cache_dir = cache_dir.clone();
|
let cache_dir = cache_dir.clone();
|
||||||
let mut tx = tx.clone();
|
let mut tx = tx.clone();
|
||||||
let map = map.clone();
|
let map = map.clone();
|
||||||
|
let root_path = root_path.clone();
|
||||||
let s = scope.builder().name(name.clone()).spawn(move || {
|
let s = scope.builder().name(name.clone()).spawn(move || {
|
||||||
let len = chunk.len();
|
let len = chunk.len();
|
||||||
let size = if len <= 100 { 100 } else { (len / 100) * 100 };
|
let size = if len <= 100 { 100 } else { (len / 100) * 100 };
|
||||||
|
@ -351,48 +357,42 @@ impl MaildirType {
|
||||||
let map = map.clone();
|
let map = map.clone();
|
||||||
let len = c.len();
|
let len = c.len();
|
||||||
for file in c {
|
for file in c {
|
||||||
let ri = file.rfind('/').unwrap() + 1;
|
/* Check if we have a cache file with this email's
|
||||||
let file_name = &file[ri..];
|
* filename */
|
||||||
|
let file_name = PathBuf::from(file)
|
||||||
|
.strip_prefix(&root_path)
|
||||||
|
.unwrap()
|
||||||
|
.to_path_buf();
|
||||||
if let Some(cached) =
|
if let Some(cached) =
|
||||||
cache_dir.find_cache_file(file_name)
|
cache_dir.find_cache_file(&file_name)
|
||||||
{
|
{
|
||||||
// TODO:: error checking
|
|
||||||
let reader = io::BufReader::new(
|
let reader = io::BufReader::new(
|
||||||
fs::File::open(cached).unwrap(),
|
fs::File::open(cached).unwrap(),
|
||||||
);
|
);
|
||||||
let env: Envelope = bincode::deserialize_from(reader).unwrap();
|
let result: result::Result<Envelope, _> = bincode::deserialize_from(reader);
|
||||||
{
|
if let Ok(env) = result {
|
||||||
let mut map = map.lock().unwrap();
|
let mut map = map.lock().unwrap();
|
||||||
let hash = env.hash();
|
let hash = env.hash();
|
||||||
if (*map).contains_key(&hash) {
|
if (*map).contains_key(&hash) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
(*map).insert(hash, (0, file.to_string()));
|
(*map).insert(hash, (0, file.clone()));
|
||||||
local_r.push(env);
|
local_r.push(env);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let e_copy = file.to_string();
|
|
||||||
/*
|
|
||||||
* get hash
|
|
||||||
* lock map
|
|
||||||
* see if its inside otherwise add it
|
|
||||||
* check cache
|
|
||||||
* generate Envelope
|
|
||||||
* add to local_r
|
|
||||||
*/
|
|
||||||
{
|
{
|
||||||
let mut hasher = DefaultHasher::new();
|
|
||||||
let hash = {
|
let hash = {
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
let mut f = fs::File::open(&e_copy)
|
let mut f = fs::File::open(&file)
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
panic!("Can't open {}", e_copy)
|
panic!("Can't open {}", file.display())
|
||||||
});
|
});
|
||||||
f.read_to_end(&mut buf).unwrap_or_else(|_| {
|
f.read_to_end(&mut buf).unwrap_or_else(|_| {
|
||||||
panic!("Can't read {}", e_copy)
|
panic!("Can't read {}", file.display())
|
||||||
});
|
});
|
||||||
/* Unwrap is safe since we use ? above. */
|
let mut hasher = FnvHasher::default();
|
||||||
|
hasher.write(file.as_os_str().as_bytes());
|
||||||
hasher.write(&buf);
|
hasher.write(&buf);
|
||||||
hasher.finish()
|
hasher.finish()
|
||||||
};
|
};
|
||||||
|
@ -401,9 +401,8 @@ impl MaildirType {
|
||||||
if (*map).contains_key(&hash) {
|
if (*map).contains_key(&hash) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
(*map).insert(hash, (0, e_copy));
|
(*map).insert(hash, (0, PathBuf::from(file)));
|
||||||
}
|
}
|
||||||
// TODO: Check cache
|
|
||||||
let op =
|
let op =
|
||||||
Box::new(MaildirOp::new(hash, map.clone()));
|
Box::new(MaildirOp::new(hash, map.clone()));
|
||||||
if let Some(mut e) = Envelope::from_token(op, hash)
|
if let Some(mut e) = Envelope::from_token(op, hash)
|
||||||
|
@ -411,6 +410,7 @@ impl MaildirType {
|
||||||
if let Ok(cached) =
|
if let Ok(cached) =
|
||||||
cache_dir.place_cache_file(file_name)
|
cache_dir.place_cache_file(file_name)
|
||||||
{
|
{
|
||||||
|
/* place result in cache directory */
|
||||||
let f = match fs::File::create(cached) {
|
let f = match fs::File::create(cached) {
|
||||||
Ok(f) => f,
|
Ok(f) => f,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|
Loading…
Reference in New Issue