Add AccountHash to RefreshEvent
Different accounts might have same inboxes with same MailboxHashes. Use the hash of the account's name to differentiate.master
parent
eb701695f7
commit
8648b229ad
|
@ -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>;
|
||||
|
||||
|
|
|
@ -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,
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
|
@ -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)),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
*/
|
||||
|
|
|
@ -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()
|
||||
};
|
||||
|
|
|
@ -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()),
|
||||
});
|
||||
}
|
||||
|
|
43
src/state.rs
43
src/state.rs
|
@ -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,9 +371,14 @@ 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() {
|
||||
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;
|
||||
}
|
||||
|
@ -372,9 +386,9 @@ impl State {
|
|||
ref mut accounts, ..
|
||||
} = &mut self.context;
|
||||
|
||||
if let Some(notification) = accounts[idxa].reload(event, hash) {
|
||||
if let Some(notification) = accounts[idxa].reload(event, mailbox_hash) {
|
||||
if let UIEvent::Notification(_, _, _) = notification {
|
||||
self.rcv_event(UIEvent::MailboxUpdate((idxa, hash)));
|
||||
self.rcv_event(UIEvent::MailboxUpdate((idxa, mailbox_hash)));
|
||||
}
|
||||
self.rcv_event(notification);
|
||||
}
|
||||
|
@ -384,6 +398,7 @@ impl State {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_thread(&mut self, id: thread::ThreadId, name: String) {
|
||||
self.context
|
||||
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Reference in New Issue