Add AccountHash to RefreshEvent

Different accounts might have same inboxes with same MailboxHashes. Use
the hash of the account's name to differentiate.
memfd
Manos Pitsidianakis 2020-05-10 22:05:04 +03:00
parent eb701695f7
commit 8648b229ad
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
8 changed files with 211 additions and 84 deletions

View File

@ -204,7 +204,7 @@ impl Backends {
}
}
#[derive(Debug)]
#[derive(Debug, Clone)]
pub enum RefreshEventKind {
Update(EnvelopeHash, Box<Envelope>),
/// Rename(old_hash, new_hash)
@ -216,16 +216,22 @@ pub enum RefreshEventKind {
Failure(MeliError),
}
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct RefreshEvent {
hash: MailboxHash,
mailbox_hash: MailboxHash,
account_hash: AccountHash,
kind: RefreshEventKind,
}
impl RefreshEvent {
pub fn hash(&self) -> MailboxHash {
self.hash
pub fn mailbox_hash(&self) -> MailboxHash {
self.mailbox_hash
}
pub fn account_hash(&self) -> AccountHash {
self.account_hash
}
pub fn kind(self) -> RefreshEventKind {
/* consumes self! */
self.kind
@ -245,6 +251,12 @@ impl RefreshEventConsumer {
}
}
impl fmt::Debug for RefreshEventConsumer {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "RefreshEventConsumer")
}
}
pub struct NotifyFn(Box<dyn Fn(MailboxHash) -> () + Send + Sync>);
impl fmt::Debug for NotifyFn {
@ -555,6 +567,7 @@ pub fn mailbox_default() -> Mailbox {
})
}
pub type AccountHash = u64;
pub type MailboxHash = u64;
pub type Mailbox = Box<dyn BackendMailbox + Send + Sync>;

View File

@ -36,9 +36,9 @@ pub mod managesieve;
use crate::async_workers::{Async, AsyncBuilder, AsyncStatus, WorkContext};
use crate::backends::BackendOp;
use crate::backends::MailboxHash;
use crate::backends::RefreshEvent;
use crate::backends::RefreshEventKind::{self, *};
use crate::backends::{AccountHash, MailboxHash};
use crate::backends::{BackendMailbox, MailBackend, Mailbox, RefreshEventConsumer};
use crate::conf::AccountSettings;
use crate::email::*;
@ -120,12 +120,26 @@ macro_rules! get_conf_val {
#[derive(Debug)]
pub struct UIDStore {
account_hash: AccountHash,
uidvalidity: Arc<Mutex<HashMap<MailboxHash, UID>>>,
hash_index: Arc<Mutex<HashMap<EnvelopeHash, (UID, MailboxHash)>>>,
uid_index: Arc<Mutex<HashMap<UID, EnvelopeHash>>>,
byte_cache: Arc<Mutex<HashMap<UID, EnvelopeCache>>>,
}
impl Default for UIDStore {
fn default() -> Self {
UIDStore {
account_hash: 0,
uidvalidity: Default::default(),
hash_index: Default::default(),
uid_index: Default::default(),
byte_cache: Default::default(),
}
}
}
#[derive(Debug)]
pub struct ImapType {
account_name: String,
@ -323,6 +337,11 @@ impl MailBackend for ImapType {
let main_conn = self.connection.clone();
let uid_store = self.uid_store.clone();
let account_name = self.account_name.clone();
let account_hash = {
let mut hasher = DefaultHasher::new();
hasher.write(self.account_name.as_bytes());
hasher.finish()
};
let w = AsyncBuilder::new();
let closure = move |work_context: WorkContext| {
let thread = std::thread::current();
@ -330,7 +349,8 @@ impl MailBackend for ImapType {
Ok(conn) => conn,
Err(err) => {
sender.send(RefreshEvent {
hash: mailbox_hash,
account_hash,
mailbox_hash,
kind: RefreshEventKind::Failure(err.clone()),
});
@ -350,6 +370,7 @@ impl MailBackend for ImapType {
.send((thread.id(), "refresh".to_string()))
.unwrap();
watch::examine_updates(
account_hash,
&inbox,
&sender,
&mut conn,
@ -374,6 +395,11 @@ impl MailBackend for ImapType {
let main_conn = self.connection.clone();
let is_online = self.online.clone();
let uid_store = self.uid_store.clone();
let account_hash = {
let mut hasher = DefaultHasher::new();
hasher.write(self.account_name.as_bytes());
hasher.finish()
};
let handle = std::thread::Builder::new()
.name(format!("{} imap connection", self.account_name.as_str(),))
.spawn(move || {
@ -397,6 +423,7 @@ impl MailBackend for ImapType {
sender,
work_context,
tag_index,
account_hash,
};
if has_idle {
idle(kit).ok().take();
@ -881,6 +908,15 @@ impl ImapType {
Err(MeliError::new("Account is uninitialised.")),
)));
let connection = ImapConnection::new_connection(&server_conf, online.clone());
let account_hash = {
let mut hasher = DefaultHasher::new();
hasher.write(s.name.as_bytes());
hasher.finish()
};
let uid_store: Arc<UIDStore> = Arc::new(UIDStore {
account_hash,
..UIDStore::default()
});
Ok(Box::new(ImapType {
account_name: s.name().to_string(),
@ -892,12 +928,7 @@ impl ImapType {
tag_index: Arc::new(RwLock::new(Default::default())),
mailboxes: Arc::new(RwLock::new(Default::default())),
connection: Arc::new(Mutex::new(connection)),
uid_store: Arc::new(UIDStore {
uidvalidity: Default::default(),
hash_index: Default::default(),
uid_index: Default::default(),
byte_cache: Default::default(),
}),
uid_store,
}))
}

View File

@ -24,6 +24,7 @@ use std::sync::{Arc, Mutex, RwLock};
/// Arguments for IMAP watching functions
pub struct ImapWatchKit {
pub account_hash: AccountHash,
pub conn: ImapConnection,
pub is_online: Arc<Mutex<(Instant, Result<()>)>>,
pub main_conn: Arc<Mutex<ImapConnection>>,
@ -35,13 +36,14 @@ pub struct ImapWatchKit {
}
macro_rules! exit_on_error {
($sender:expr, $mailbox_hash:ident, $work_context:ident, $thread_id:ident, $($result:expr)+) => {
($sender:expr, $account_hash:ident, $mailbox_hash:ident, $work_context:ident, $thread_id:ident, $($result:expr)+) => {
$(if let Err(e) = $result {
debug!("failure: {}", e.to_string());
$work_context.set_status.send(($thread_id, e.to_string())).unwrap();
$work_context.finished.send($thread_id).unwrap();
$sender.send(RefreshEvent {
hash: $mailbox_hash,
account_hash: $account_hash,
mailbox_hash: $mailbox_hash,
kind: RefreshEventKind::Failure(e.clone()),
});
Err(e)
@ -60,6 +62,7 @@ pub fn poll_with_examine(kit: ImapWatchKit) -> Result<()> {
sender,
work_context,
tag_index,
account_hash,
} = kit;
loop {
if super::try_lock(&is_online)?.1.is_ok() {
@ -86,6 +89,7 @@ pub fn poll_with_examine(kit: ImapWatchKit) -> Result<()> {
))
.unwrap();
examine_updates(
account_hash,
mailbox,
&sender,
&mut conn,
@ -113,6 +117,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
sender,
work_context,
tag_index,
account_hash,
} = kit;
loop {
if super::try_lock(&is_online)?.1.is_ok() {
@ -138,7 +143,8 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
.send((thread_id, err.to_string()))
.unwrap();
sender.send(RefreshEvent {
hash: 0,
account_hash,
mailbox_hash: 0,
kind: RefreshEventKind::Failure(err.clone()),
});
return Err(err);
@ -148,6 +154,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
let mut response = String::with_capacity(8 * 1024);
exit_on_error!(
sender,
account_hash,
mailbox_hash,
work_context,
thread_id,
@ -165,7 +172,8 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
if let Some(v) = uidvalidities.get_mut(&mailbox_hash) {
if *v != ok.uidvalidity {
sender.send(RefreshEvent {
hash: mailbox_hash,
account_hash,
mailbox_hash,
kind: RefreshEventKind::Rescan,
});
*prev_exists = 0;
@ -178,11 +186,13 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
}
} else {
sender.send(RefreshEvent {
hash: mailbox_hash,
account_hash,
mailbox_hash,
kind: RefreshEventKind::Rescan,
});
sender.send(RefreshEvent {
hash: mailbox_hash,
account_hash,
mailbox_hash,
kind: RefreshEventKind::Failure(MeliError::new(format!(
"Unknown mailbox: {} {}",
mailbox.path(),
@ -202,6 +212,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
}
exit_on_error!(
sender,
account_hash,
mailbox_hash,
work_context,
thread_id,
@ -224,6 +235,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
let mut main_conn_lck = super::try_lock(&main_conn)?;
exit_on_error!(
sender,
account_hash,
mailbox_hash,
work_context,
thread_id,
@ -250,10 +262,12 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
.unwrap();
exit_on_error!(
sender,
account_hash,
mailbox_hash,
work_context,
thread_id,
examine_updates(
account_hash,
mailbox,
&sender,
&mut conn,
@ -282,6 +296,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
/* UID SEARCH RECENT */
exit_on_error!(
sender,
account_hash,
mailbox_hash,
work_context,
thread_id,
@ -300,6 +315,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
Ok(v) => {
exit_on_error!(
sender,
account_hash,
mailbox_hash,
work_context,
thread_id,
@ -358,7 +374,8 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
*mailbox.exists.lock().unwrap() += 1;
sender.send(RefreshEvent {
hash: mailbox_hash,
account_hash,
mailbox_hash,
kind: Create(Box::new(env)),
});
}
@ -410,6 +427,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
if n > *prev_exists {
exit_on_error!(
sender,
account_hash,
mailbox_hash,
work_context,
thread_id,
@ -475,7 +493,8 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
*mailbox.unseen.lock().unwrap() += 1;
}
sender.send(RefreshEvent {
hash: mailbox_hash,
account_hash,
mailbox_hash,
kind: Create(Box::new(env)),
});
}
@ -503,6 +522,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
debug!("fetch {} {:?}", msg_seq, flags);
exit_on_error!(
sender,
account_hash,
mailbox_hash,
work_context,
thread_id,
@ -524,7 +544,8 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
if let Some(uid) = v.pop() {
if let Some(env_hash) = uid_store.uid_index.lock().unwrap().get(&uid) {
sender.send(RefreshEvent {
hash: mailbox_hash,
account_hash,
mailbox_hash,
kind: NewFlags(*env_hash, flags),
});
}
@ -551,7 +572,8 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
.unwrap();
work_context.finished.send(thread_id).unwrap();
sender.send(RefreshEvent {
hash: mailbox_hash,
account_hash,
mailbox_hash,
kind: RefreshEventKind::Failure(MeliError::new(format!(
"IDLE connection dropped: {}",
&err
@ -561,6 +583,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
}
pub fn examine_updates(
account_hash: AccountHash,
mailbox: &ImapMailbox,
sender: &RefreshEventConsumer,
conn: &mut ImapConnection,
@ -574,6 +597,7 @@ pub fn examine_updates(
let mut response = String::with_capacity(8 * 1024);
exit_on_error!(
sender,
account_hash,
mailbox_hash,
work_context,
thread_id,
@ -589,7 +613,8 @@ pub fn examine_updates(
if let Some(v) = uidvalidities.get_mut(&mailbox_hash) {
if *v != ok.uidvalidity {
sender.send(RefreshEvent {
hash: mailbox_hash,
account_hash,
mailbox_hash,
kind: RefreshEventKind::Rescan,
});
/*
@ -601,11 +626,13 @@ pub fn examine_updates(
}
} else {
sender.send(RefreshEvent {
hash: mailbox_hash,
account_hash,
mailbox_hash,
kind: RefreshEventKind::Rescan,
});
sender.send(RefreshEvent {
hash: mailbox_hash,
account_hash,
mailbox_hash,
kind: RefreshEventKind::Failure(MeliError::new(format!(
"Unknown mailbox: {} {}",
mailbox.path(),
@ -621,6 +648,7 @@ pub fn examine_updates(
/* UID SEARCH RECENT */
exit_on_error!(
sender,
account_hash,
mailbox_hash,
work_context,
thread_id,
@ -637,6 +665,7 @@ pub fn examine_updates(
Ok(v) => {
exit_on_error!(
sender,
account_hash,
mailbox_hash,
work_context,
thread_id,
@ -687,7 +716,8 @@ pub fn examine_updates(
*mailbox.unseen.lock().unwrap() += 1;
}
sender.send(RefreshEvent {
hash: mailbox_hash,
account_hash,
mailbox_hash,
kind: Create(Box::new(env)),
});
}
@ -713,6 +743,7 @@ pub fn examine_updates(
debug!("exists {}", n);
exit_on_error!(
sender,
account_hash,
mailbox_hash,
work_context,
thread_id,
@ -761,7 +792,8 @@ pub fn examine_updates(
*mailbox.unseen.lock().unwrap() += 1;
}
sender.send(RefreshEvent {
hash: mailbox_hash,
account_hash,
mailbox_hash,
kind: Create(Box::new(env)),
});
}

View File

@ -199,6 +199,11 @@ impl MailBackend for MaildirType {
) -> Result<Async<()>> {
let w = AsyncBuilder::new();
let cache_dir = xdg::BaseDirectories::with_profile("meli", &self.name).unwrap();
let account_hash = {
let mut hasher = DefaultHasher::default();
hasher.write(self.name.as_bytes());
hasher.finish()
};
let handle = {
let mailbox: &MaildirMailbox = &self.mailboxes[&mailbox_hash];
@ -277,7 +282,8 @@ impl MailBackend for MaildirType {
bincode::serialize_into(writer, &e).unwrap();
}
sender.send(RefreshEvent {
hash: mailbox_hash,
account_hash,
mailbox_hash,
kind: Create(Box::new(e)),
});
} else {
@ -290,7 +296,8 @@ impl MailBackend for MaildirType {
}
}
for ev in current_hashes.into_iter().map(|h| RefreshEvent {
hash: mailbox_hash,
account_hash,
mailbox_hash,
kind: Remove(h),
}) {
sender.send(ev);
@ -299,7 +306,8 @@ impl MailBackend for MaildirType {
};
if let Err(err) = thunk(&sender) {
sender.send(RefreshEvent {
hash: mailbox_hash,
account_hash,
mailbox_hash,
kind: Failure(err),
});
}
@ -314,6 +322,11 @@ impl MailBackend for MaildirType {
) -> Result<std::thread::ThreadId> {
let (tx, rx) = channel();
let mut watcher = watcher(tx, Duration::from_secs(2)).unwrap();
let account_hash = {
let mut hasher = DefaultHasher::default();
hasher.write(self.name.as_bytes());
hasher.finish()
};
let root_path = self.path.to_path_buf();
watcher.watch(&root_path, RecursiveMode::Recursive).unwrap();
let cache_dir = xdg::BaseDirectories::with_profile("meli", &self.name).unwrap();
@ -385,7 +398,8 @@ impl MailBackend for MaildirType {
}
*mailbox_counts[&mailbox_hash].1.lock().unwrap() += 1;
sender.send(RefreshEvent {
hash: mailbox_hash,
account_hash,
mailbox_hash,
kind: Create(Box::new(env)),
});
}
@ -425,7 +439,8 @@ impl MailBackend for MaildirType {
) {
mailbox_index.lock().unwrap().insert(env.hash(),mailbox_hash);
sender.send(RefreshEvent {
hash: mailbox_hash,
account_hash,
mailbox_hash,
kind: Create(Box::new(env)),
});
}
@ -451,7 +466,8 @@ impl MailBackend for MaildirType {
/* Send Write notice */
sender.send(RefreshEvent {
hash: mailbox_hash,
account_hash,
mailbox_hash,
kind: Update(old_hash, Box::new(env)),
});
}
@ -500,7 +516,8 @@ impl MailBackend for MaildirType {
});
sender.send(RefreshEvent {
hash: mailbox_hash,
account_hash,
mailbox_hash,
kind: Remove(hash),
});
}
@ -530,7 +547,8 @@ impl MailBackend for MaildirType {
e.modified = Some(PathMod::Hash(new_hash));
});
sender.send(RefreshEvent {
hash: get_path_hash!(dest),
account_hash,
mailbox_hash: get_path_hash!(dest),
kind: Rename(old_hash, new_hash),
});
if !was_seen && is_seen {
@ -588,7 +606,8 @@ impl MailBackend for MaildirType {
}
*mailbox_counts[&mailbox_hash].1.lock().unwrap() += 1;
sender.send(RefreshEvent {
hash: mailbox_hash,
account_hash,
mailbox_hash,
kind: Create(Box::new(env)),
});
continue;
@ -600,7 +619,8 @@ impl MailBackend for MaildirType {
*mailbox_counts[&mailbox_hash].0.lock().unwrap() += 1;
}
sender.send(RefreshEvent {
hash: get_path_hash!(dest),
account_hash,
mailbox_hash: get_path_hash!(dest),
kind: Rename(old_hash, new_hash),
});
debug!("contains_new_key");
@ -608,7 +628,8 @@ impl MailBackend for MaildirType {
/* Maybe a re-read should be triggered here just to be safe.
sender.send(RefreshEvent {
hash: get_path_hash!(dest),
account_hash,
mailbox_hash: get_path_hash!(dest),
kind: Rescan,
});
*/

View File

@ -41,8 +41,9 @@ use memmap::{Mmap, Protection};
use nom::{IResult, Needed};
extern crate notify;
use self::notify::{watcher, DebouncedEvent, RecursiveMode, Watcher};
use std::collections::HashMap;
use std::collections::hash_map::{DefaultHasher, HashMap};
use std::fs::File;
use std::hash::Hasher;
use std::io::BufReader;
use std::io::Read;
use std::os::unix::io::AsRawFd;
@ -386,6 +387,7 @@ pub fn mbox_parse(
/// Mbox backend
#[derive(Debug, Default)]
pub struct MboxType {
account_name: String,
path: PathBuf,
index: Arc<Mutex<HashMap<EnvelopeHash, (Offset, Length)>>>,
mailboxes: Arc<Mutex<HashMap<MailboxHash, MboxMailbox>>>,
@ -461,13 +463,15 @@ impl MailBackend for MboxType {
.map_err(MeliError::new)?;
debug!("watching {:?}", f.path.as_path());
}
let account_hash = {
let mut hasher = DefaultHasher::new();
hasher.write(self.account_name.as_bytes());
hasher.finish()
};
let index = self.index.clone();
let mailboxes = self.mailboxes.clone();
let handle = std::thread::Builder::new()
.name(format!(
"watching {}",
self.path.file_name().unwrap().to_str().unwrap()
))
.name(format!("watching {}", self.account_name,))
.spawn(move || {
// Move `watcher` in the closure's scope so that it doesn't get dropped.
let _watcher = watcher;
@ -521,14 +525,16 @@ impl MailBackend for MboxType {
{
for env in envelopes {
sender.send(RefreshEvent {
hash: mailbox_hash,
account_hash,
mailbox_hash,
kind: RefreshEventKind::Create(Box::new(env)),
});
}
}
} else {
sender.send(RefreshEvent {
hash: mailbox_hash,
account_hash,
mailbox_hash,
kind: RefreshEventKind::Rescan,
});
}
@ -547,7 +553,8 @@ impl MailBackend for MboxType {
{
let mailbox_hash = get_path_hash!(&pathbuf);
sender.send(RefreshEvent {
hash: mailbox_hash,
account_hash,
mailbox_hash,
kind: RefreshEventKind::Failure(MeliError::new(format!(
"mbox mailbox {} was removed.",
pathbuf.display()
@ -560,7 +567,8 @@ impl MailBackend for MboxType {
if mailboxes.lock().unwrap().values().any(|f| &f.path == &src) {
let mailbox_hash = get_path_hash!(&src);
sender.send(RefreshEvent {
hash: mailbox_hash,
account_hash,
mailbox_hash,
kind: RefreshEventKind::Failure(MeliError::new(format!(
"mbox mailbox {} was renamed to {}.",
src.display(),
@ -572,9 +580,10 @@ impl MailBackend for MboxType {
}
/* Trigger rescan of mailboxes */
DebouncedEvent::Rescan => {
for h in mailboxes.lock().unwrap().keys() {
for &mailbox_hash in mailboxes.lock().unwrap().keys() {
sender.send(RefreshEvent {
hash: *h,
account_hash,
mailbox_hash,
kind: RefreshEventKind::Rescan,
});
}
@ -628,6 +637,7 @@ impl MboxType {
)));
}
let ret = MboxType {
account_name: s.name().to_string(),
path,
..Default::default()
};

View File

@ -109,6 +109,7 @@ pub struct NotmuchDb {
index: Arc<RwLock<HashMap<EnvelopeHash, CString>>>,
tag_index: Arc<RwLock<BTreeMap<u64, String>>>,
path: PathBuf,
account_name: String,
save_messages_to: Option<PathBuf>,
}
@ -238,6 +239,7 @@ impl NotmuchDb {
mailboxes: Arc::new(RwLock::new(mailboxes)),
save_messages_to: None,
account_name: s.name().to_string(),
}))
}
@ -435,6 +437,11 @@ impl MailBackend for NotmuchDb {
watcher.watch(&self.path, RecursiveMode::Recursive).unwrap();
let path = self.path.clone();
let lib = self.lib.clone();
let account_hash = {
let mut hasher = DefaultHasher::new();
hasher.write(self.account_name.as_bytes());
hasher.finish()
};
{
let database = NotmuchDb::new_connection(path.as_path(), lib.clone(), false)?;
let mut revision_uuid_lck = self.revision_uuid.write().unwrap();
@ -450,10 +457,7 @@ impl MailBackend for NotmuchDb {
let revision_uuid = self.revision_uuid.clone();
let handle = std::thread::Builder::new()
.name(format!(
"watching {}",
self.path.file_name().unwrap().to_str().unwrap()
))
.name(format!("watching {}", self.account_name))
.spawn(move || {
let _watcher = watcher;
let c = move || -> std::result::Result<(), MeliError> {
@ -484,7 +488,8 @@ impl MailBackend for NotmuchDb {
if let Err(err) = c() {
sender.send(RefreshEvent {
hash: 0,
account_hash,
mailbox_hash: 0,
kind: Failure(err.into()),
});
}

View File

@ -30,7 +30,7 @@ Input is received in the main loop from threads which listen on the stdin for us
use super::*;
use crate::plugins::PluginManager;
use melib::backends::{MailboxHash, NotifyFn};
use melib::backends::{AccountHash, MailboxHash, NotifyFn};
use crossbeam::channel::{unbounded, Receiver, Sender};
use smallvec::SmallVec;
@ -89,7 +89,7 @@ impl InputHandler {
/// A context container for loaded settings, accounts, UI changes, etc.
pub struct Context {
pub accounts: Vec<Account>,
pub mailbox_hashes: HashMap<MailboxHash, usize>,
pub account_hashes: HashMap<AccountHash, usize>,
pub settings: Settings,
pub runtime_settings: Settings,
@ -132,7 +132,6 @@ impl Context {
pub fn is_online(&mut self, account_pos: usize) -> Result<()> {
let Context {
ref mut accounts,
ref mut mailbox_hashes,
ref mut replies,
..
} = self;
@ -146,7 +145,6 @@ impl Context {
mailbox_node.hash,
accounts[account_pos][&mailbox_node.hash].name()
);
mailbox_hashes.insert(mailbox_node.hash, account_pos);
}
/* Account::watch() needs
* - work_controller to pass `work_context` to the watcher threads and then add them
@ -246,6 +244,7 @@ impl State {
let cols = termsize.0 as usize;
let rows = termsize.1 as usize;
let mut account_hashes = HashMap::with_capacity_and_hasher(1, Default::default());
let work_controller = WorkController::new(sender.clone());
let accounts: Vec<Account> = {
let mut file_accs = settings
@ -259,6 +258,14 @@ impl State {
.enumerate()
.map(|(index, (n, a_s))| {
let sender = sender.clone();
let account_hash = {
use std::collections::hash_map::DefaultHasher;
use std::hash::Hasher;
let mut hasher = DefaultHasher::new();
hasher.write(n.as_bytes());
hasher.finish()
};
account_hashes.insert(account_hash, index);
Account::new(
index,
n.to_string(),
@ -268,7 +275,10 @@ impl State {
sender.clone(),
NotifyFn::new(Box::new(move |f: MailboxHash| {
sender
.send(ThreadEvent::UIEvent(UIEvent::WorkerProgress(f)))
.send(ThreadEvent::UIEvent(UIEvent::WorkerProgress(
account_hash,
f,
)))
.unwrap();
})),
)
@ -315,8 +325,7 @@ impl State {
context: Context {
accounts,
mailbox_hashes: HashMap::with_capacity_and_hasher(1, Default::default()),
account_hashes,
settings: settings.clone(),
runtime_settings: settings,
dirty_areas: VecDeque::with_capacity(5),
@ -362,25 +371,31 @@ impl State {
* and startup a thread to remind us to poll it every now and then till it's finished.
*/
pub fn refresh_event(&mut self, event: RefreshEvent) {
let hash = event.hash();
if let Some(&idxa) = self.context.mailbox_hashes.get(&hash) {
if self.context.accounts[idxa].load(hash).is_err() {
self.context.replies.push_back(UIEvent::from(event));
return;
}
let Context {
ref mut accounts, ..
} = &mut self.context;
if let Some(notification) = accounts[idxa].reload(event, hash) {
if let UIEvent::Notification(_, _, _) = notification {
self.rcv_event(UIEvent::MailboxUpdate((idxa, hash)));
let account_hash = event.account_hash();
let mailbox_hash = event.mailbox_hash();
if let Some(&idxa) = self.context.account_hashes.get(&account_hash) {
if self.context.accounts[idxa]
.mailbox_entries
.contains_key(&mailbox_hash)
{
if self.context.accounts[idxa].load(mailbox_hash).is_err() {
self.context.replies.push_back(UIEvent::from(event));
return;
}
let Context {
ref mut accounts, ..
} = &mut self.context;
if let Some(notification) = accounts[idxa].reload(event, mailbox_hash) {
if let UIEvent::Notification(_, _, _) = notification {
self.rcv_event(UIEvent::MailboxUpdate((idxa, mailbox_hash)));
}
self.rcv_event(notification);
}
} else {
if let melib::backends::RefreshEventKind::Failure(err) = event.kind() {
debug!(err);
}
self.rcv_event(notification);
}
} else {
if let melib::backends::RefreshEventKind::Failure(err) = event.kind() {
debug!(err);
}
}
}
@ -915,8 +930,8 @@ impl State {
self.child = Some(child);
return;
}
UIEvent::WorkerProgress(mailbox_hash) => {
if let Some(&account_idx) = self.context.mailbox_hashes.get(&mailbox_hash) {
UIEvent::WorkerProgress(account_hash, mailbox_hash) => {
if let Some(&account_idx) = self.context.account_hashes.get(&account_hash) {
let _ = self.context.accounts[account_idx].load(mailbox_hash);
}
return;

View File

@ -38,7 +38,7 @@ pub use self::helpers::*;
use super::execute::Action;
use super::terminal::*;
use melib::backends::MailboxHash;
use melib::backends::{AccountHash, MailboxHash};
use melib::{EnvelopeHash, RefreshEvent};
use nix::unistd::Pid;
use std;
@ -115,7 +115,7 @@ pub enum UIEvent {
MailboxCreate((usize, MailboxHash)),
AccountStatusChange(usize),
ComponentKill(Uuid),
WorkerProgress(MailboxHash),
WorkerProgress(AccountHash, MailboxHash),
StartupCheck(MailboxHash),
RefreshEvent(Box<RefreshEvent>),
EnvelopeUpdate(EnvelopeHash),