Add AccountHash to RefreshEvent
Different accounts might have same inboxes with same MailboxHashes. Use the hash of the account's name to differentiate.memfd
parent
eb701695f7
commit
8648b229ad
|
@ -204,7 +204,7 @@ impl Backends {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum RefreshEventKind {
|
pub enum RefreshEventKind {
|
||||||
Update(EnvelopeHash, Box<Envelope>),
|
Update(EnvelopeHash, Box<Envelope>),
|
||||||
/// Rename(old_hash, new_hash)
|
/// Rename(old_hash, new_hash)
|
||||||
|
@ -216,16 +216,22 @@ pub enum RefreshEventKind {
|
||||||
Failure(MeliError),
|
Failure(MeliError),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct RefreshEvent {
|
pub struct RefreshEvent {
|
||||||
hash: MailboxHash,
|
mailbox_hash: MailboxHash,
|
||||||
|
account_hash: AccountHash,
|
||||||
kind: RefreshEventKind,
|
kind: RefreshEventKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RefreshEvent {
|
impl RefreshEvent {
|
||||||
pub fn hash(&self) -> MailboxHash {
|
pub fn mailbox_hash(&self) -> MailboxHash {
|
||||||
self.hash
|
self.mailbox_hash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn account_hash(&self) -> AccountHash {
|
||||||
|
self.account_hash
|
||||||
|
}
|
||||||
|
|
||||||
pub fn kind(self) -> RefreshEventKind {
|
pub fn kind(self) -> RefreshEventKind {
|
||||||
/* consumes self! */
|
/* consumes self! */
|
||||||
self.kind
|
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>);
|
pub struct NotifyFn(Box<dyn Fn(MailboxHash) -> () + Send + Sync>);
|
||||||
|
|
||||||
impl fmt::Debug for NotifyFn {
|
impl fmt::Debug for NotifyFn {
|
||||||
|
@ -555,6 +567,7 @@ pub fn mailbox_default() -> Mailbox {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type AccountHash = u64;
|
||||||
pub type MailboxHash = u64;
|
pub type MailboxHash = u64;
|
||||||
pub type Mailbox = Box<dyn BackendMailbox + Send + Sync>;
|
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::async_workers::{Async, AsyncBuilder, AsyncStatus, WorkContext};
|
||||||
use crate::backends::BackendOp;
|
use crate::backends::BackendOp;
|
||||||
use crate::backends::MailboxHash;
|
|
||||||
use crate::backends::RefreshEvent;
|
use crate::backends::RefreshEvent;
|
||||||
use crate::backends::RefreshEventKind::{self, *};
|
use crate::backends::RefreshEventKind::{self, *};
|
||||||
|
use crate::backends::{AccountHash, MailboxHash};
|
||||||
use crate::backends::{BackendMailbox, MailBackend, Mailbox, RefreshEventConsumer};
|
use crate::backends::{BackendMailbox, MailBackend, Mailbox, RefreshEventConsumer};
|
||||||
use crate::conf::AccountSettings;
|
use crate::conf::AccountSettings;
|
||||||
use crate::email::*;
|
use crate::email::*;
|
||||||
|
@ -120,12 +120,26 @@ macro_rules! get_conf_val {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct UIDStore {
|
pub struct UIDStore {
|
||||||
|
account_hash: AccountHash,
|
||||||
uidvalidity: Arc<Mutex<HashMap<MailboxHash, UID>>>,
|
uidvalidity: Arc<Mutex<HashMap<MailboxHash, UID>>>,
|
||||||
hash_index: Arc<Mutex<HashMap<EnvelopeHash, (UID, MailboxHash)>>>,
|
hash_index: Arc<Mutex<HashMap<EnvelopeHash, (UID, MailboxHash)>>>,
|
||||||
uid_index: Arc<Mutex<HashMap<UID, EnvelopeHash>>>,
|
uid_index: Arc<Mutex<HashMap<UID, EnvelopeHash>>>,
|
||||||
|
|
||||||
byte_cache: Arc<Mutex<HashMap<UID, EnvelopeCache>>>,
|
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)]
|
#[derive(Debug)]
|
||||||
pub struct ImapType {
|
pub struct ImapType {
|
||||||
account_name: String,
|
account_name: String,
|
||||||
|
@ -323,6 +337,11 @@ impl MailBackend for ImapType {
|
||||||
let main_conn = self.connection.clone();
|
let main_conn = self.connection.clone();
|
||||||
let uid_store = self.uid_store.clone();
|
let uid_store = self.uid_store.clone();
|
||||||
let account_name = self.account_name.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 w = AsyncBuilder::new();
|
||||||
let closure = move |work_context: WorkContext| {
|
let closure = move |work_context: WorkContext| {
|
||||||
let thread = std::thread::current();
|
let thread = std::thread::current();
|
||||||
|
@ -330,7 +349,8 @@ impl MailBackend for ImapType {
|
||||||
Ok(conn) => conn,
|
Ok(conn) => conn,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: mailbox_hash,
|
account_hash,
|
||||||
|
mailbox_hash,
|
||||||
kind: RefreshEventKind::Failure(err.clone()),
|
kind: RefreshEventKind::Failure(err.clone()),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -350,6 +370,7 @@ impl MailBackend for ImapType {
|
||||||
.send((thread.id(), "refresh".to_string()))
|
.send((thread.id(), "refresh".to_string()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
watch::examine_updates(
|
watch::examine_updates(
|
||||||
|
account_hash,
|
||||||
&inbox,
|
&inbox,
|
||||||
&sender,
|
&sender,
|
||||||
&mut conn,
|
&mut conn,
|
||||||
|
@ -374,6 +395,11 @@ impl MailBackend for ImapType {
|
||||||
let main_conn = self.connection.clone();
|
let main_conn = self.connection.clone();
|
||||||
let is_online = self.online.clone();
|
let is_online = self.online.clone();
|
||||||
let uid_store = self.uid_store.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()
|
let handle = std::thread::Builder::new()
|
||||||
.name(format!("{} imap connection", self.account_name.as_str(),))
|
.name(format!("{} imap connection", self.account_name.as_str(),))
|
||||||
.spawn(move || {
|
.spawn(move || {
|
||||||
|
@ -397,6 +423,7 @@ impl MailBackend for ImapType {
|
||||||
sender,
|
sender,
|
||||||
work_context,
|
work_context,
|
||||||
tag_index,
|
tag_index,
|
||||||
|
account_hash,
|
||||||
};
|
};
|
||||||
if has_idle {
|
if has_idle {
|
||||||
idle(kit).ok().take();
|
idle(kit).ok().take();
|
||||||
|
@ -881,6 +908,15 @@ impl ImapType {
|
||||||
Err(MeliError::new("Account is uninitialised.")),
|
Err(MeliError::new("Account is uninitialised.")),
|
||||||
)));
|
)));
|
||||||
let connection = ImapConnection::new_connection(&server_conf, online.clone());
|
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 {
|
Ok(Box::new(ImapType {
|
||||||
account_name: s.name().to_string(),
|
account_name: s.name().to_string(),
|
||||||
|
@ -892,12 +928,7 @@ impl ImapType {
|
||||||
tag_index: Arc::new(RwLock::new(Default::default())),
|
tag_index: Arc::new(RwLock::new(Default::default())),
|
||||||
mailboxes: Arc::new(RwLock::new(Default::default())),
|
mailboxes: Arc::new(RwLock::new(Default::default())),
|
||||||
connection: Arc::new(Mutex::new(connection)),
|
connection: Arc::new(Mutex::new(connection)),
|
||||||
uid_store: Arc::new(UIDStore {
|
uid_store,
|
||||||
uidvalidity: Default::default(),
|
|
||||||
hash_index: Default::default(),
|
|
||||||
uid_index: Default::default(),
|
|
||||||
byte_cache: Default::default(),
|
|
||||||
}),
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ use std::sync::{Arc, Mutex, RwLock};
|
||||||
|
|
||||||
/// Arguments for IMAP watching functions
|
/// Arguments for IMAP watching functions
|
||||||
pub struct ImapWatchKit {
|
pub struct ImapWatchKit {
|
||||||
|
pub account_hash: AccountHash,
|
||||||
pub conn: ImapConnection,
|
pub conn: ImapConnection,
|
||||||
pub is_online: Arc<Mutex<(Instant, Result<()>)>>,
|
pub is_online: Arc<Mutex<(Instant, Result<()>)>>,
|
||||||
pub main_conn: Arc<Mutex<ImapConnection>>,
|
pub main_conn: Arc<Mutex<ImapConnection>>,
|
||||||
|
@ -35,13 +36,14 @@ pub struct ImapWatchKit {
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! exit_on_error {
|
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 {
|
$(if let Err(e) = $result {
|
||||||
debug!("failure: {}", e.to_string());
|
debug!("failure: {}", e.to_string());
|
||||||
$work_context.set_status.send(($thread_id, e.to_string())).unwrap();
|
$work_context.set_status.send(($thread_id, e.to_string())).unwrap();
|
||||||
$work_context.finished.send($thread_id).unwrap();
|
$work_context.finished.send($thread_id).unwrap();
|
||||||
$sender.send(RefreshEvent {
|
$sender.send(RefreshEvent {
|
||||||
hash: $mailbox_hash,
|
account_hash: $account_hash,
|
||||||
|
mailbox_hash: $mailbox_hash,
|
||||||
kind: RefreshEventKind::Failure(e.clone()),
|
kind: RefreshEventKind::Failure(e.clone()),
|
||||||
});
|
});
|
||||||
Err(e)
|
Err(e)
|
||||||
|
@ -60,6 +62,7 @@ pub fn poll_with_examine(kit: ImapWatchKit) -> Result<()> {
|
||||||
sender,
|
sender,
|
||||||
work_context,
|
work_context,
|
||||||
tag_index,
|
tag_index,
|
||||||
|
account_hash,
|
||||||
} = kit;
|
} = kit;
|
||||||
loop {
|
loop {
|
||||||
if super::try_lock(&is_online)?.1.is_ok() {
|
if super::try_lock(&is_online)?.1.is_ok() {
|
||||||
|
@ -86,6 +89,7 @@ pub fn poll_with_examine(kit: ImapWatchKit) -> Result<()> {
|
||||||
))
|
))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
examine_updates(
|
examine_updates(
|
||||||
|
account_hash,
|
||||||
mailbox,
|
mailbox,
|
||||||
&sender,
|
&sender,
|
||||||
&mut conn,
|
&mut conn,
|
||||||
|
@ -113,6 +117,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
|
||||||
sender,
|
sender,
|
||||||
work_context,
|
work_context,
|
||||||
tag_index,
|
tag_index,
|
||||||
|
account_hash,
|
||||||
} = kit;
|
} = kit;
|
||||||
loop {
|
loop {
|
||||||
if super::try_lock(&is_online)?.1.is_ok() {
|
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()))
|
.send((thread_id, err.to_string()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: 0,
|
account_hash,
|
||||||
|
mailbox_hash: 0,
|
||||||
kind: RefreshEventKind::Failure(err.clone()),
|
kind: RefreshEventKind::Failure(err.clone()),
|
||||||
});
|
});
|
||||||
return Err(err);
|
return Err(err);
|
||||||
|
@ -148,6 +154,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
|
||||||
let mut response = String::with_capacity(8 * 1024);
|
let mut response = String::with_capacity(8 * 1024);
|
||||||
exit_on_error!(
|
exit_on_error!(
|
||||||
sender,
|
sender,
|
||||||
|
account_hash,
|
||||||
mailbox_hash,
|
mailbox_hash,
|
||||||
work_context,
|
work_context,
|
||||||
thread_id,
|
thread_id,
|
||||||
|
@ -165,7 +172,8 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
|
||||||
if let Some(v) = uidvalidities.get_mut(&mailbox_hash) {
|
if let Some(v) = uidvalidities.get_mut(&mailbox_hash) {
|
||||||
if *v != ok.uidvalidity {
|
if *v != ok.uidvalidity {
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: mailbox_hash,
|
account_hash,
|
||||||
|
mailbox_hash,
|
||||||
kind: RefreshEventKind::Rescan,
|
kind: RefreshEventKind::Rescan,
|
||||||
});
|
});
|
||||||
*prev_exists = 0;
|
*prev_exists = 0;
|
||||||
|
@ -178,11 +186,13 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: mailbox_hash,
|
account_hash,
|
||||||
|
mailbox_hash,
|
||||||
kind: RefreshEventKind::Rescan,
|
kind: RefreshEventKind::Rescan,
|
||||||
});
|
});
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: mailbox_hash,
|
account_hash,
|
||||||
|
mailbox_hash,
|
||||||
kind: RefreshEventKind::Failure(MeliError::new(format!(
|
kind: RefreshEventKind::Failure(MeliError::new(format!(
|
||||||
"Unknown mailbox: {} {}",
|
"Unknown mailbox: {} {}",
|
||||||
mailbox.path(),
|
mailbox.path(),
|
||||||
|
@ -202,6 +212,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
|
||||||
}
|
}
|
||||||
exit_on_error!(
|
exit_on_error!(
|
||||||
sender,
|
sender,
|
||||||
|
account_hash,
|
||||||
mailbox_hash,
|
mailbox_hash,
|
||||||
work_context,
|
work_context,
|
||||||
thread_id,
|
thread_id,
|
||||||
|
@ -224,6 +235,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
|
||||||
let mut main_conn_lck = super::try_lock(&main_conn)?;
|
let mut main_conn_lck = super::try_lock(&main_conn)?;
|
||||||
exit_on_error!(
|
exit_on_error!(
|
||||||
sender,
|
sender,
|
||||||
|
account_hash,
|
||||||
mailbox_hash,
|
mailbox_hash,
|
||||||
work_context,
|
work_context,
|
||||||
thread_id,
|
thread_id,
|
||||||
|
@ -250,10 +262,12 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
exit_on_error!(
|
exit_on_error!(
|
||||||
sender,
|
sender,
|
||||||
|
account_hash,
|
||||||
mailbox_hash,
|
mailbox_hash,
|
||||||
work_context,
|
work_context,
|
||||||
thread_id,
|
thread_id,
|
||||||
examine_updates(
|
examine_updates(
|
||||||
|
account_hash,
|
||||||
mailbox,
|
mailbox,
|
||||||
&sender,
|
&sender,
|
||||||
&mut conn,
|
&mut conn,
|
||||||
|
@ -282,6 +296,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
|
||||||
/* UID SEARCH RECENT */
|
/* UID SEARCH RECENT */
|
||||||
exit_on_error!(
|
exit_on_error!(
|
||||||
sender,
|
sender,
|
||||||
|
account_hash,
|
||||||
mailbox_hash,
|
mailbox_hash,
|
||||||
work_context,
|
work_context,
|
||||||
thread_id,
|
thread_id,
|
||||||
|
@ -300,6 +315,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
|
||||||
Ok(v) => {
|
Ok(v) => {
|
||||||
exit_on_error!(
|
exit_on_error!(
|
||||||
sender,
|
sender,
|
||||||
|
account_hash,
|
||||||
mailbox_hash,
|
mailbox_hash,
|
||||||
work_context,
|
work_context,
|
||||||
thread_id,
|
thread_id,
|
||||||
|
@ -358,7 +374,8 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
|
||||||
*mailbox.exists.lock().unwrap() += 1;
|
*mailbox.exists.lock().unwrap() += 1;
|
||||||
|
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: mailbox_hash,
|
account_hash,
|
||||||
|
mailbox_hash,
|
||||||
kind: Create(Box::new(env)),
|
kind: Create(Box::new(env)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -410,6 +427,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
|
||||||
if n > *prev_exists {
|
if n > *prev_exists {
|
||||||
exit_on_error!(
|
exit_on_error!(
|
||||||
sender,
|
sender,
|
||||||
|
account_hash,
|
||||||
mailbox_hash,
|
mailbox_hash,
|
||||||
work_context,
|
work_context,
|
||||||
thread_id,
|
thread_id,
|
||||||
|
@ -475,7 +493,8 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
|
||||||
*mailbox.unseen.lock().unwrap() += 1;
|
*mailbox.unseen.lock().unwrap() += 1;
|
||||||
}
|
}
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: mailbox_hash,
|
account_hash,
|
||||||
|
mailbox_hash,
|
||||||
kind: Create(Box::new(env)),
|
kind: Create(Box::new(env)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -503,6 +522,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
|
||||||
debug!("fetch {} {:?}", msg_seq, flags);
|
debug!("fetch {} {:?}", msg_seq, flags);
|
||||||
exit_on_error!(
|
exit_on_error!(
|
||||||
sender,
|
sender,
|
||||||
|
account_hash,
|
||||||
mailbox_hash,
|
mailbox_hash,
|
||||||
work_context,
|
work_context,
|
||||||
thread_id,
|
thread_id,
|
||||||
|
@ -524,7 +544,8 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
|
||||||
if let Some(uid) = v.pop() {
|
if let Some(uid) = v.pop() {
|
||||||
if let Some(env_hash) = uid_store.uid_index.lock().unwrap().get(&uid) {
|
if let Some(env_hash) = uid_store.uid_index.lock().unwrap().get(&uid) {
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: mailbox_hash,
|
account_hash,
|
||||||
|
mailbox_hash,
|
||||||
kind: NewFlags(*env_hash, flags),
|
kind: NewFlags(*env_hash, flags),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -551,7 +572,8 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
work_context.finished.send(thread_id).unwrap();
|
work_context.finished.send(thread_id).unwrap();
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: mailbox_hash,
|
account_hash,
|
||||||
|
mailbox_hash,
|
||||||
kind: RefreshEventKind::Failure(MeliError::new(format!(
|
kind: RefreshEventKind::Failure(MeliError::new(format!(
|
||||||
"IDLE connection dropped: {}",
|
"IDLE connection dropped: {}",
|
||||||
&err
|
&err
|
||||||
|
@ -561,6 +583,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn examine_updates(
|
pub fn examine_updates(
|
||||||
|
account_hash: AccountHash,
|
||||||
mailbox: &ImapMailbox,
|
mailbox: &ImapMailbox,
|
||||||
sender: &RefreshEventConsumer,
|
sender: &RefreshEventConsumer,
|
||||||
conn: &mut ImapConnection,
|
conn: &mut ImapConnection,
|
||||||
|
@ -574,6 +597,7 @@ pub fn examine_updates(
|
||||||
let mut response = String::with_capacity(8 * 1024);
|
let mut response = String::with_capacity(8 * 1024);
|
||||||
exit_on_error!(
|
exit_on_error!(
|
||||||
sender,
|
sender,
|
||||||
|
account_hash,
|
||||||
mailbox_hash,
|
mailbox_hash,
|
||||||
work_context,
|
work_context,
|
||||||
thread_id,
|
thread_id,
|
||||||
|
@ -589,7 +613,8 @@ pub fn examine_updates(
|
||||||
if let Some(v) = uidvalidities.get_mut(&mailbox_hash) {
|
if let Some(v) = uidvalidities.get_mut(&mailbox_hash) {
|
||||||
if *v != ok.uidvalidity {
|
if *v != ok.uidvalidity {
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: mailbox_hash,
|
account_hash,
|
||||||
|
mailbox_hash,
|
||||||
kind: RefreshEventKind::Rescan,
|
kind: RefreshEventKind::Rescan,
|
||||||
});
|
});
|
||||||
/*
|
/*
|
||||||
|
@ -601,11 +626,13 @@ pub fn examine_updates(
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: mailbox_hash,
|
account_hash,
|
||||||
|
mailbox_hash,
|
||||||
kind: RefreshEventKind::Rescan,
|
kind: RefreshEventKind::Rescan,
|
||||||
});
|
});
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: mailbox_hash,
|
account_hash,
|
||||||
|
mailbox_hash,
|
||||||
kind: RefreshEventKind::Failure(MeliError::new(format!(
|
kind: RefreshEventKind::Failure(MeliError::new(format!(
|
||||||
"Unknown mailbox: {} {}",
|
"Unknown mailbox: {} {}",
|
||||||
mailbox.path(),
|
mailbox.path(),
|
||||||
|
@ -621,6 +648,7 @@ pub fn examine_updates(
|
||||||
/* UID SEARCH RECENT */
|
/* UID SEARCH RECENT */
|
||||||
exit_on_error!(
|
exit_on_error!(
|
||||||
sender,
|
sender,
|
||||||
|
account_hash,
|
||||||
mailbox_hash,
|
mailbox_hash,
|
||||||
work_context,
|
work_context,
|
||||||
thread_id,
|
thread_id,
|
||||||
|
@ -637,6 +665,7 @@ pub fn examine_updates(
|
||||||
Ok(v) => {
|
Ok(v) => {
|
||||||
exit_on_error!(
|
exit_on_error!(
|
||||||
sender,
|
sender,
|
||||||
|
account_hash,
|
||||||
mailbox_hash,
|
mailbox_hash,
|
||||||
work_context,
|
work_context,
|
||||||
thread_id,
|
thread_id,
|
||||||
|
@ -687,7 +716,8 @@ pub fn examine_updates(
|
||||||
*mailbox.unseen.lock().unwrap() += 1;
|
*mailbox.unseen.lock().unwrap() += 1;
|
||||||
}
|
}
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: mailbox_hash,
|
account_hash,
|
||||||
|
mailbox_hash,
|
||||||
kind: Create(Box::new(env)),
|
kind: Create(Box::new(env)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -713,6 +743,7 @@ pub fn examine_updates(
|
||||||
debug!("exists {}", n);
|
debug!("exists {}", n);
|
||||||
exit_on_error!(
|
exit_on_error!(
|
||||||
sender,
|
sender,
|
||||||
|
account_hash,
|
||||||
mailbox_hash,
|
mailbox_hash,
|
||||||
work_context,
|
work_context,
|
||||||
thread_id,
|
thread_id,
|
||||||
|
@ -761,7 +792,8 @@ pub fn examine_updates(
|
||||||
*mailbox.unseen.lock().unwrap() += 1;
|
*mailbox.unseen.lock().unwrap() += 1;
|
||||||
}
|
}
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: mailbox_hash,
|
account_hash,
|
||||||
|
mailbox_hash,
|
||||||
kind: Create(Box::new(env)),
|
kind: Create(Box::new(env)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,6 +199,11 @@ impl MailBackend for MaildirType {
|
||||||
) -> Result<Async<()>> {
|
) -> Result<Async<()>> {
|
||||||
let w = AsyncBuilder::new();
|
let w = AsyncBuilder::new();
|
||||||
let cache_dir = xdg::BaseDirectories::with_profile("meli", &self.name).unwrap();
|
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 handle = {
|
||||||
let mailbox: &MaildirMailbox = &self.mailboxes[&mailbox_hash];
|
let mailbox: &MaildirMailbox = &self.mailboxes[&mailbox_hash];
|
||||||
|
@ -277,7 +282,8 @@ impl MailBackend for MaildirType {
|
||||||
bincode::serialize_into(writer, &e).unwrap();
|
bincode::serialize_into(writer, &e).unwrap();
|
||||||
}
|
}
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: mailbox_hash,
|
account_hash,
|
||||||
|
mailbox_hash,
|
||||||
kind: Create(Box::new(e)),
|
kind: Create(Box::new(e)),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -290,7 +296,8 @@ impl MailBackend for MaildirType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for ev in current_hashes.into_iter().map(|h| RefreshEvent {
|
for ev in current_hashes.into_iter().map(|h| RefreshEvent {
|
||||||
hash: mailbox_hash,
|
account_hash,
|
||||||
|
mailbox_hash,
|
||||||
kind: Remove(h),
|
kind: Remove(h),
|
||||||
}) {
|
}) {
|
||||||
sender.send(ev);
|
sender.send(ev);
|
||||||
|
@ -299,7 +306,8 @@ impl MailBackend for MaildirType {
|
||||||
};
|
};
|
||||||
if let Err(err) = thunk(&sender) {
|
if let Err(err) = thunk(&sender) {
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: mailbox_hash,
|
account_hash,
|
||||||
|
mailbox_hash,
|
||||||
kind: Failure(err),
|
kind: Failure(err),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -314,6 +322,11 @@ impl MailBackend for MaildirType {
|
||||||
) -> Result<std::thread::ThreadId> {
|
) -> Result<std::thread::ThreadId> {
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
let mut watcher = watcher(tx, Duration::from_secs(2)).unwrap();
|
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();
|
let root_path = self.path.to_path_buf();
|
||||||
watcher.watch(&root_path, RecursiveMode::Recursive).unwrap();
|
watcher.watch(&root_path, RecursiveMode::Recursive).unwrap();
|
||||||
let cache_dir = xdg::BaseDirectories::with_profile("meli", &self.name).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;
|
*mailbox_counts[&mailbox_hash].1.lock().unwrap() += 1;
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: mailbox_hash,
|
account_hash,
|
||||||
|
mailbox_hash,
|
||||||
kind: Create(Box::new(env)),
|
kind: Create(Box::new(env)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -425,7 +439,8 @@ impl MailBackend for MaildirType {
|
||||||
) {
|
) {
|
||||||
mailbox_index.lock().unwrap().insert(env.hash(),mailbox_hash);
|
mailbox_index.lock().unwrap().insert(env.hash(),mailbox_hash);
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: mailbox_hash,
|
account_hash,
|
||||||
|
mailbox_hash,
|
||||||
kind: Create(Box::new(env)),
|
kind: Create(Box::new(env)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -451,7 +466,8 @@ impl MailBackend for MaildirType {
|
||||||
/* Send Write notice */
|
/* Send Write notice */
|
||||||
|
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: mailbox_hash,
|
account_hash,
|
||||||
|
mailbox_hash,
|
||||||
kind: Update(old_hash, Box::new(env)),
|
kind: Update(old_hash, Box::new(env)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -500,7 +516,8 @@ impl MailBackend for MaildirType {
|
||||||
});
|
});
|
||||||
|
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: mailbox_hash,
|
account_hash,
|
||||||
|
mailbox_hash,
|
||||||
kind: Remove(hash),
|
kind: Remove(hash),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -530,7 +547,8 @@ impl MailBackend for MaildirType {
|
||||||
e.modified = Some(PathMod::Hash(new_hash));
|
e.modified = Some(PathMod::Hash(new_hash));
|
||||||
});
|
});
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: get_path_hash!(dest),
|
account_hash,
|
||||||
|
mailbox_hash: get_path_hash!(dest),
|
||||||
kind: Rename(old_hash, new_hash),
|
kind: Rename(old_hash, new_hash),
|
||||||
});
|
});
|
||||||
if !was_seen && is_seen {
|
if !was_seen && is_seen {
|
||||||
|
@ -588,7 +606,8 @@ impl MailBackend for MaildirType {
|
||||||
}
|
}
|
||||||
*mailbox_counts[&mailbox_hash].1.lock().unwrap() += 1;
|
*mailbox_counts[&mailbox_hash].1.lock().unwrap() += 1;
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: mailbox_hash,
|
account_hash,
|
||||||
|
mailbox_hash,
|
||||||
kind: Create(Box::new(env)),
|
kind: Create(Box::new(env)),
|
||||||
});
|
});
|
||||||
continue;
|
continue;
|
||||||
|
@ -600,7 +619,8 @@ impl MailBackend for MaildirType {
|
||||||
*mailbox_counts[&mailbox_hash].0.lock().unwrap() += 1;
|
*mailbox_counts[&mailbox_hash].0.lock().unwrap() += 1;
|
||||||
}
|
}
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: get_path_hash!(dest),
|
account_hash,
|
||||||
|
mailbox_hash: get_path_hash!(dest),
|
||||||
kind: Rename(old_hash, new_hash),
|
kind: Rename(old_hash, new_hash),
|
||||||
});
|
});
|
||||||
debug!("contains_new_key");
|
debug!("contains_new_key");
|
||||||
|
@ -608,7 +628,8 @@ impl MailBackend for MaildirType {
|
||||||
|
|
||||||
/* Maybe a re-read should be triggered here just to be safe.
|
/* Maybe a re-read should be triggered here just to be safe.
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: get_path_hash!(dest),
|
account_hash,
|
||||||
|
mailbox_hash: get_path_hash!(dest),
|
||||||
kind: Rescan,
|
kind: Rescan,
|
||||||
});
|
});
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -41,8 +41,9 @@ use memmap::{Mmap, Protection};
|
||||||
use nom::{IResult, Needed};
|
use nom::{IResult, Needed};
|
||||||
extern crate notify;
|
extern crate notify;
|
||||||
use self::notify::{watcher, DebouncedEvent, RecursiveMode, Watcher};
|
use self::notify::{watcher, DebouncedEvent, RecursiveMode, Watcher};
|
||||||
use std::collections::HashMap;
|
use std::collections::hash_map::{DefaultHasher, HashMap};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
use std::hash::Hasher;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
|
@ -386,6 +387,7 @@ pub fn mbox_parse(
|
||||||
/// Mbox backend
|
/// Mbox backend
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct MboxType {
|
pub struct MboxType {
|
||||||
|
account_name: String,
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
index: Arc<Mutex<HashMap<EnvelopeHash, (Offset, Length)>>>,
|
index: Arc<Mutex<HashMap<EnvelopeHash, (Offset, Length)>>>,
|
||||||
mailboxes: Arc<Mutex<HashMap<MailboxHash, MboxMailbox>>>,
|
mailboxes: Arc<Mutex<HashMap<MailboxHash, MboxMailbox>>>,
|
||||||
|
@ -461,13 +463,15 @@ impl MailBackend for MboxType {
|
||||||
.map_err(MeliError::new)?;
|
.map_err(MeliError::new)?;
|
||||||
debug!("watching {:?}", f.path.as_path());
|
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 index = self.index.clone();
|
||||||
let mailboxes = self.mailboxes.clone();
|
let mailboxes = self.mailboxes.clone();
|
||||||
let handle = std::thread::Builder::new()
|
let handle = std::thread::Builder::new()
|
||||||
.name(format!(
|
.name(format!("watching {}", self.account_name,))
|
||||||
"watching {}",
|
|
||||||
self.path.file_name().unwrap().to_str().unwrap()
|
|
||||||
))
|
|
||||||
.spawn(move || {
|
.spawn(move || {
|
||||||
// Move `watcher` in the closure's scope so that it doesn't get dropped.
|
// Move `watcher` in the closure's scope so that it doesn't get dropped.
|
||||||
let _watcher = watcher;
|
let _watcher = watcher;
|
||||||
|
@ -521,14 +525,16 @@ impl MailBackend for MboxType {
|
||||||
{
|
{
|
||||||
for env in envelopes {
|
for env in envelopes {
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: mailbox_hash,
|
account_hash,
|
||||||
|
mailbox_hash,
|
||||||
kind: RefreshEventKind::Create(Box::new(env)),
|
kind: RefreshEventKind::Create(Box::new(env)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: mailbox_hash,
|
account_hash,
|
||||||
|
mailbox_hash,
|
||||||
kind: RefreshEventKind::Rescan,
|
kind: RefreshEventKind::Rescan,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -547,7 +553,8 @@ impl MailBackend for MboxType {
|
||||||
{
|
{
|
||||||
let mailbox_hash = get_path_hash!(&pathbuf);
|
let mailbox_hash = get_path_hash!(&pathbuf);
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: mailbox_hash,
|
account_hash,
|
||||||
|
mailbox_hash,
|
||||||
kind: RefreshEventKind::Failure(MeliError::new(format!(
|
kind: RefreshEventKind::Failure(MeliError::new(format!(
|
||||||
"mbox mailbox {} was removed.",
|
"mbox mailbox {} was removed.",
|
||||||
pathbuf.display()
|
pathbuf.display()
|
||||||
|
@ -560,7 +567,8 @@ impl MailBackend for MboxType {
|
||||||
if mailboxes.lock().unwrap().values().any(|f| &f.path == &src) {
|
if mailboxes.lock().unwrap().values().any(|f| &f.path == &src) {
|
||||||
let mailbox_hash = get_path_hash!(&src);
|
let mailbox_hash = get_path_hash!(&src);
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: mailbox_hash,
|
account_hash,
|
||||||
|
mailbox_hash,
|
||||||
kind: RefreshEventKind::Failure(MeliError::new(format!(
|
kind: RefreshEventKind::Failure(MeliError::new(format!(
|
||||||
"mbox mailbox {} was renamed to {}.",
|
"mbox mailbox {} was renamed to {}.",
|
||||||
src.display(),
|
src.display(),
|
||||||
|
@ -572,9 +580,10 @@ impl MailBackend for MboxType {
|
||||||
}
|
}
|
||||||
/* Trigger rescan of mailboxes */
|
/* Trigger rescan of mailboxes */
|
||||||
DebouncedEvent::Rescan => {
|
DebouncedEvent::Rescan => {
|
||||||
for h in mailboxes.lock().unwrap().keys() {
|
for &mailbox_hash in mailboxes.lock().unwrap().keys() {
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: *h,
|
account_hash,
|
||||||
|
mailbox_hash,
|
||||||
kind: RefreshEventKind::Rescan,
|
kind: RefreshEventKind::Rescan,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -628,6 +637,7 @@ impl MboxType {
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
let ret = MboxType {
|
let ret = MboxType {
|
||||||
|
account_name: s.name().to_string(),
|
||||||
path,
|
path,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
|
@ -109,6 +109,7 @@ pub struct NotmuchDb {
|
||||||
index: Arc<RwLock<HashMap<EnvelopeHash, CString>>>,
|
index: Arc<RwLock<HashMap<EnvelopeHash, CString>>>,
|
||||||
tag_index: Arc<RwLock<BTreeMap<u64, String>>>,
|
tag_index: Arc<RwLock<BTreeMap<u64, String>>>,
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
|
account_name: String,
|
||||||
save_messages_to: Option<PathBuf>,
|
save_messages_to: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,6 +239,7 @@ impl NotmuchDb {
|
||||||
|
|
||||||
mailboxes: Arc::new(RwLock::new(mailboxes)),
|
mailboxes: Arc::new(RwLock::new(mailboxes)),
|
||||||
save_messages_to: None,
|
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();
|
watcher.watch(&self.path, RecursiveMode::Recursive).unwrap();
|
||||||
let path = self.path.clone();
|
let path = self.path.clone();
|
||||||
let lib = self.lib.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 database = NotmuchDb::new_connection(path.as_path(), lib.clone(), false)?;
|
||||||
let mut revision_uuid_lck = self.revision_uuid.write().unwrap();
|
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 revision_uuid = self.revision_uuid.clone();
|
||||||
|
|
||||||
let handle = std::thread::Builder::new()
|
let handle = std::thread::Builder::new()
|
||||||
.name(format!(
|
.name(format!("watching {}", self.account_name))
|
||||||
"watching {}",
|
|
||||||
self.path.file_name().unwrap().to_str().unwrap()
|
|
||||||
))
|
|
||||||
.spawn(move || {
|
.spawn(move || {
|
||||||
let _watcher = watcher;
|
let _watcher = watcher;
|
||||||
let c = move || -> std::result::Result<(), MeliError> {
|
let c = move || -> std::result::Result<(), MeliError> {
|
||||||
|
@ -484,7 +488,8 @@ impl MailBackend for NotmuchDb {
|
||||||
|
|
||||||
if let Err(err) = c() {
|
if let Err(err) = c() {
|
||||||
sender.send(RefreshEvent {
|
sender.send(RefreshEvent {
|
||||||
hash: 0,
|
account_hash,
|
||||||
|
mailbox_hash: 0,
|
||||||
kind: Failure(err.into()),
|
kind: Failure(err.into()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
69
src/state.rs
69
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 super::*;
|
||||||
use crate::plugins::PluginManager;
|
use crate::plugins::PluginManager;
|
||||||
use melib::backends::{MailboxHash, NotifyFn};
|
use melib::backends::{AccountHash, MailboxHash, NotifyFn};
|
||||||
|
|
||||||
use crossbeam::channel::{unbounded, Receiver, Sender};
|
use crossbeam::channel::{unbounded, Receiver, Sender};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
@ -89,7 +89,7 @@ impl InputHandler {
|
||||||
/// A context container for loaded settings, accounts, UI changes, etc.
|
/// A context container for loaded settings, accounts, UI changes, etc.
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
pub accounts: Vec<Account>,
|
pub accounts: Vec<Account>,
|
||||||
pub mailbox_hashes: HashMap<MailboxHash, usize>,
|
pub account_hashes: HashMap<AccountHash, usize>,
|
||||||
pub settings: Settings,
|
pub settings: Settings,
|
||||||
|
|
||||||
pub runtime_settings: Settings,
|
pub runtime_settings: Settings,
|
||||||
|
@ -132,7 +132,6 @@ impl Context {
|
||||||
pub fn is_online(&mut self, account_pos: usize) -> Result<()> {
|
pub fn is_online(&mut self, account_pos: usize) -> Result<()> {
|
||||||
let Context {
|
let Context {
|
||||||
ref mut accounts,
|
ref mut accounts,
|
||||||
ref mut mailbox_hashes,
|
|
||||||
ref mut replies,
|
ref mut replies,
|
||||||
..
|
..
|
||||||
} = self;
|
} = self;
|
||||||
|
@ -146,7 +145,6 @@ impl Context {
|
||||||
mailbox_node.hash,
|
mailbox_node.hash,
|
||||||
accounts[account_pos][&mailbox_node.hash].name()
|
accounts[account_pos][&mailbox_node.hash].name()
|
||||||
);
|
);
|
||||||
mailbox_hashes.insert(mailbox_node.hash, account_pos);
|
|
||||||
}
|
}
|
||||||
/* Account::watch() needs
|
/* Account::watch() needs
|
||||||
* - work_controller to pass `work_context` to the watcher threads and then add them
|
* - 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 cols = termsize.0 as usize;
|
||||||
let rows = termsize.1 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 work_controller = WorkController::new(sender.clone());
|
||||||
let accounts: Vec<Account> = {
|
let accounts: Vec<Account> = {
|
||||||
let mut file_accs = settings
|
let mut file_accs = settings
|
||||||
|
@ -259,6 +258,14 @@ impl State {
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(index, (n, a_s))| {
|
.map(|(index, (n, a_s))| {
|
||||||
let sender = sender.clone();
|
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(
|
Account::new(
|
||||||
index,
|
index,
|
||||||
n.to_string(),
|
n.to_string(),
|
||||||
|
@ -268,7 +275,10 @@ impl State {
|
||||||
sender.clone(),
|
sender.clone(),
|
||||||
NotifyFn::new(Box::new(move |f: MailboxHash| {
|
NotifyFn::new(Box::new(move |f: MailboxHash| {
|
||||||
sender
|
sender
|
||||||
.send(ThreadEvent::UIEvent(UIEvent::WorkerProgress(f)))
|
.send(ThreadEvent::UIEvent(UIEvent::WorkerProgress(
|
||||||
|
account_hash,
|
||||||
|
f,
|
||||||
|
)))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
})),
|
})),
|
||||||
)
|
)
|
||||||
|
@ -315,8 +325,7 @@ impl State {
|
||||||
|
|
||||||
context: Context {
|
context: Context {
|
||||||
accounts,
|
accounts,
|
||||||
mailbox_hashes: HashMap::with_capacity_and_hasher(1, Default::default()),
|
account_hashes,
|
||||||
|
|
||||||
settings: settings.clone(),
|
settings: settings.clone(),
|
||||||
runtime_settings: settings,
|
runtime_settings: settings,
|
||||||
dirty_areas: VecDeque::with_capacity(5),
|
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.
|
* 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) {
|
pub fn refresh_event(&mut self, event: RefreshEvent) {
|
||||||
let hash = event.hash();
|
let account_hash = event.account_hash();
|
||||||
if let Some(&idxa) = self.context.mailbox_hashes.get(&hash) {
|
let mailbox_hash = event.mailbox_hash();
|
||||||
if self.context.accounts[idxa].load(hash).is_err() {
|
if let Some(&idxa) = self.context.account_hashes.get(&account_hash) {
|
||||||
self.context.replies.push_back(UIEvent::from(event));
|
if self.context.accounts[idxa]
|
||||||
return;
|
.mailbox_entries
|
||||||
}
|
.contains_key(&mailbox_hash)
|
||||||
let Context {
|
{
|
||||||
ref mut accounts, ..
|
if self.context.accounts[idxa].load(mailbox_hash).is_err() {
|
||||||
} = &mut self.context;
|
self.context.replies.push_back(UIEvent::from(event));
|
||||||
|
return;
|
||||||
if let Some(notification) = accounts[idxa].reload(event, hash) {
|
}
|
||||||
if let UIEvent::Notification(_, _, _) = notification {
|
let Context {
|
||||||
self.rcv_event(UIEvent::MailboxUpdate((idxa, hash)));
|
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);
|
self.child = Some(child);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
UIEvent::WorkerProgress(mailbox_hash) => {
|
UIEvent::WorkerProgress(account_hash, mailbox_hash) => {
|
||||||
if let Some(&account_idx) = self.context.mailbox_hashes.get(&mailbox_hash) {
|
if let Some(&account_idx) = self.context.account_hashes.get(&account_hash) {
|
||||||
let _ = self.context.accounts[account_idx].load(mailbox_hash);
|
let _ = self.context.accounts[account_idx].load(mailbox_hash);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -38,7 +38,7 @@ pub use self::helpers::*;
|
||||||
use super::execute::Action;
|
use super::execute::Action;
|
||||||
use super::terminal::*;
|
use super::terminal::*;
|
||||||
|
|
||||||
use melib::backends::MailboxHash;
|
use melib::backends::{AccountHash, MailboxHash};
|
||||||
use melib::{EnvelopeHash, RefreshEvent};
|
use melib::{EnvelopeHash, RefreshEvent};
|
||||||
use nix::unistd::Pid;
|
use nix::unistd::Pid;
|
||||||
use std;
|
use std;
|
||||||
|
@ -115,7 +115,7 @@ pub enum UIEvent {
|
||||||
MailboxCreate((usize, MailboxHash)),
|
MailboxCreate((usize, MailboxHash)),
|
||||||
AccountStatusChange(usize),
|
AccountStatusChange(usize),
|
||||||
ComponentKill(Uuid),
|
ComponentKill(Uuid),
|
||||||
WorkerProgress(MailboxHash),
|
WorkerProgress(AccountHash, MailboxHash),
|
||||||
StartupCheck(MailboxHash),
|
StartupCheck(MailboxHash),
|
||||||
RefreshEvent(Box<RefreshEvent>),
|
RefreshEvent(Box<RefreshEvent>),
|
||||||
EnvelopeUpdate(EnvelopeHash),
|
EnvelopeUpdate(EnvelopeHash),
|
||||||
|
|
Loading…
Reference in New Issue