melib: remove argument from MailBackend operation()

The operation() method on the MailBackend trait returns a trait object
that can read or modify an Envelope directly from the backend. This is
used to get eg the envelope's text, or set flags. It has two arguments,
envelope hash and folder hash.

Only the Maildir backend needed the latter argument, and it can be replaced with a dictionary to match envelope hashes to folder hashes within the Maildir backend.
sql
Manos Pitsidianakis 2019-11-03 13:12:28 +02:00
parent 0a606a71d1
commit d926cadc4d
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
5 changed files with 34 additions and 25 deletions

View File

@ -176,7 +176,7 @@ pub enum FolderOperation {
type NewFolderName = String; type NewFolderName = String;
pub trait MailBackend: ::std::fmt::Debug { pub trait MailBackend: ::std::fmt::Debug + Send + Sync {
fn is_online(&self) -> bool; fn is_online(&self) -> bool;
fn get(&mut self, folder: &Folder) -> Async<Result<Vec<Envelope>>>; fn get(&mut self, folder: &Folder) -> Async<Result<Vec<Envelope>>>;
fn watch( fn watch(
@ -185,7 +185,7 @@ pub trait MailBackend: ::std::fmt::Debug {
work_context: WorkContext, work_context: WorkContext,
) -> Result<std::thread::ThreadId>; ) -> Result<std::thread::ThreadId>;
fn folders(&self) -> FnvHashMap<FolderHash, Folder>; fn folders(&self) -> FnvHashMap<FolderHash, Folder>;
fn operation(&self, hash: EnvelopeHash, folder_hash: FolderHash) -> Box<dyn BackendOp>; fn operation(&self, hash: EnvelopeHash) -> Box<dyn BackendOp>;
fn save(&self, bytes: &[u8], folder: &str, flags: Option<Flag>) -> Result<()>; fn save(&self, bytes: &[u8], folder: &str, flags: Option<Flag>) -> Result<()>;
fn folder_operation(&mut self, _path: &str, _op: FolderOperation) -> Result<()> { fn folder_operation(&mut self, _path: &str, _op: FolderOperation) -> Result<()> {

View File

@ -259,7 +259,7 @@ impl MailBackend for ImapType {
.collect() .collect()
} }
fn operation(&self, hash: EnvelopeHash, _folder_hash: FolderHash) -> Box<dyn BackendOp> { fn operation(&self, hash: EnvelopeHash) -> Box<dyn BackendOp> {
let (uid, folder_hash) = self.hash_index.lock().unwrap()[&hash]; let (uid, folder_hash) = self.hash_index.lock().unwrap()[&hash];
Box::new(ImapOp::new( Box::new(ImapOp::new(
uid, uid,

View File

@ -114,7 +114,7 @@ pub type HashIndexes = Arc<Mutex<FnvHashMap<FolderHash, HashIndex>>>;
pub struct MaildirType { pub struct MaildirType {
name: String, name: String,
folders: FnvHashMap<FolderHash, MaildirFolder>, folders: FnvHashMap<FolderHash, MaildirFolder>,
//folder_index: FnvHashMap<FolderHash, usize>, folder_index: Arc<Mutex<FnvHashMap<EnvelopeHash, FolderHash>>>,
hash_indexes: HashIndexes, hash_indexes: HashIndexes,
path: PathBuf, path: PathBuf,
} }
@ -207,6 +207,7 @@ impl MailBackend for MaildirType {
let cache_dir = xdg::BaseDirectories::with_profile("meli", &self.name).unwrap(); let cache_dir = xdg::BaseDirectories::with_profile("meli", &self.name).unwrap();
debug!("watching {:?}", root_path); debug!("watching {:?}", root_path);
let hash_indexes = self.hash_indexes.clone(); let hash_indexes = self.hash_indexes.clone();
let folder_index = self.folder_index.clone();
let handle = thread::Builder::new() let handle = thread::Builder::new()
.name("folder watch".to_string()) .name("folder watch".to_string())
.spawn(move || { .spawn(move || {
@ -255,6 +256,7 @@ impl MailBackend for MaildirType {
&cache_dir, &cache_dir,
file_name, file_name,
) { ) {
folder_index.lock().unwrap().insert(env.hash(),folder_hash);
debug!( debug!(
"Create event {} {} {}", "Create event {} {} {}",
env.hash(), env.hash(),
@ -300,6 +302,7 @@ impl MailBackend for MaildirType {
&cache_dir, &cache_dir,
file_name, file_name,
) { ) {
folder_index.lock().unwrap().insert(env.hash(),folder_hash);
sender.send(RefreshEvent { sender.send(RefreshEvent {
hash: folder_hash, hash: folder_hash,
kind: Create(Box::new(env)), kind: Create(Box::new(env)),
@ -398,6 +401,7 @@ impl MailBackend for MaildirType {
hash: get_path_hash!(dest), hash: get_path_hash!(dest),
kind: Rename(old_hash, new_hash), kind: Rename(old_hash, new_hash),
}); });
folder_index.lock().unwrap().insert(new_hash,get_path_hash!(dest) );
index_lock.insert(new_hash, dest.into()); index_lock.insert(new_hash, dest.into());
continue; continue;
} else if !index_lock.contains_key(&new_hash) } else if !index_lock.contains_key(&new_hash)
@ -434,6 +438,7 @@ impl MailBackend for MaildirType {
&cache_dir, &cache_dir,
file_name, file_name,
) { ) {
folder_index.lock().unwrap().insert(env.hash(),folder_hash);
debug!( debug!(
"Create event {} {} {}", "Create event {} {} {}",
env.hash(), env.hash(),
@ -477,8 +482,12 @@ impl MailBackend for MaildirType {
Ok(handle.thread().id()) Ok(handle.thread().id())
} }
fn operation(&self, hash: EnvelopeHash, folder_hash: FolderHash) -> Box<dyn BackendOp> { fn operation(&self, hash: EnvelopeHash) -> Box<dyn BackendOp> {
Box::new(MaildirOp::new(hash, self.hash_indexes.clone(), folder_hash)) Box::new(MaildirOp::new(
hash,
self.hash_indexes.clone(),
self.folder_index.lock().unwrap()[&hash],
))
} }
fn save(&self, bytes: &[u8], folder: &str, flags: Option<Flag>) -> Result<()> { fn save(&self, bytes: &[u8], folder: &str, flags: Option<Flag>) -> Result<()> {
@ -663,6 +672,7 @@ impl MaildirType {
name: settings.name().to_string(), name: settings.name().to_string(),
folders, folders,
hash_indexes, hash_indexes,
folder_index: Default::default(),
path: root_path, path: root_path,
} }
} }
@ -689,6 +699,7 @@ impl MaildirType {
let name = format!("parsing {:?}", folder.name()); let name = format!("parsing {:?}", folder.name());
let root_path = self.path.to_path_buf(); let root_path = self.path.to_path_buf();
let map = self.hash_indexes.clone(); let map = self.hash_indexes.clone();
let folder_index = self.folder_index.clone();
let closure = move |work_context: crate::async_workers::WorkContext| { let closure = move |work_context: crate::async_workers::WorkContext| {
let name = name.clone(); let name = name.clone();
@ -698,6 +709,7 @@ impl MaildirType {
.unwrap(); .unwrap();
let root_path = root_path.clone(); let root_path = root_path.clone();
let map = map.clone(); let map = map.clone();
let folder_index = folder_index.clone();
let tx = tx.clone(); let tx = tx.clone();
let cache_dir = cache_dir.clone(); let cache_dir = cache_dir.clone();
let path = path.clone(); let path = path.clone();
@ -737,6 +749,7 @@ impl MaildirType {
let cache_dir = cache_dir.clone(); let cache_dir = cache_dir.clone();
let tx = tx.clone(); let tx = tx.clone();
let map = map.clone(); let map = map.clone();
let folder_index = folder_index.clone();
let root_path = root_path.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();
@ -746,6 +759,7 @@ impl MaildirType {
for c in chunk.chunks(size) { for c in chunk.chunks(size) {
//thread::yield_now(); //thread::yield_now();
let map = map.clone(); let map = map.clone();
let folder_index = folder_index.clone();
let len = c.len(); let len = c.len();
for file in c { for file in c {
/* Check if we have a cache file with this email's /* Check if we have a cache file with this email's
@ -768,6 +782,10 @@ impl MaildirType {
let map = map.entry(folder_hash).or_default(); let map = map.entry(folder_hash).or_default();
let hash = env.hash(); let hash = env.hash();
map.insert(hash, file.clone().into()); map.insert(hash, file.clone().into());
folder_index
.lock()
.unwrap()
.insert(hash, folder_hash);
local_r.push(env); local_r.push(env);
continue; continue;
} }
@ -784,6 +802,10 @@ impl MaildirType {
folder_hash, folder_hash,
)); ));
if let Some(e) = Envelope::from_token(op, hash) { if let Some(e) = Envelope::from_token(op, hash) {
folder_index
.lock()
.unwrap()
.insert(e.hash(), folder_hash);
if let Ok(cached) = if let Ok(cached) =
cache_dir.place_cache_file(file_name) cache_dir.place_cache_file(file_name)
{ {

View File

@ -537,7 +537,7 @@ impl MailBackend for MboxType {
.map(|(h, f)| (*h, f.clone() as Folder)) .map(|(h, f)| (*h, f.clone() as Folder))
.collect() .collect()
} }
fn operation(&self, hash: EnvelopeHash, _folder_hash: FolderHash) -> Box<dyn BackendOp> { fn operation(&self, hash: EnvelopeHash) -> Box<dyn BackendOp> {
let (offset, length) = { let (offset, length) = {
let index = self.index.lock().unwrap(); let index = self.index.lock().unwrap();
index[&hash] index[&hash]

View File

@ -740,25 +740,12 @@ impl Account {
self.collection.contains_key(&h) self.collection.contains_key(&h)
} }
pub fn operation(&self, h: EnvelopeHash) -> Box<dyn BackendOp> { pub fn operation(&self, h: EnvelopeHash) -> Box<dyn BackendOp> {
for mailbox in self.folders.values() { let operation = self.backend.operation(h);
match mailbox { if self.settings.account.read_only() {
MailboxEntry::Available(ref m) | MailboxEntry::Parsing(ref m, _, _) => { ReadOnlyOp::new(operation)
if m.envelopes.contains(&h) { } else {
let operation = self.backend.operation(h, m.folder.hash()); operation
if self.settings.account.read_only() {
return ReadOnlyOp::new(operation);
} else {
return operation;
}
}
}
_ => {}
}
} }
debug!("didn't find {}", h);
debug!(&self.folders);
//debug!(&self.collection.envelopes);
unreachable!()
} }
pub fn thread(&self, h: ThreadHash, f: FolderHash) -> &ThreadNode { pub fn thread(&self, h: ThreadHash, f: FolderHash) -> &ThreadNode {