From 2d3f49d64d2f4fc28efc4c2786679e3d0be88ace Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Thu, 11 Jun 2020 11:41:08 +0300 Subject: [PATCH] imap: index by (MailboxHash, UID) instead of just UID Mailboxes can share UIDs. --- melib/src/backends/imap.rs | 16 ++++++--- melib/src/backends/imap/untagged.rs | 27 +++++++++++---- melib/src/backends/imap/watch.rs | 51 ++++++++++++++++++++++++----- 3 files changed, 75 insertions(+), 19 deletions(-) diff --git a/melib/src/backends/imap.rs b/melib/src/backends/imap.rs index e3d75f6c..abb73000 100644 --- a/melib/src/backends/imap.rs +++ b/melib/src/backends/imap.rs @@ -126,7 +126,7 @@ pub struct UIDStore { cache_headers: bool, uidvalidity: Arc>>, hash_index: Arc>>, - uid_index: Arc>>, + uid_index: Arc>>, byte_cache: Arc>>, tag_index: Arc>>, @@ -264,7 +264,11 @@ impl MailBackend for ImapType { .lock() .unwrap() .insert(env.hash(), (uid, mailbox_hash)); - uid_store.uid_index.lock().unwrap().insert(uid, env.hash()); + uid_store + .uid_index + .lock() + .unwrap() + .insert((mailbox_hash, uid), env.hash()); payload.push(env); } debug!("sending cached payload for {}", mailbox_hash); @@ -378,7 +382,11 @@ impl MailBackend for ImapType { .lock() .unwrap() .insert(env.hash(), (uid, mailbox_hash)); - uid_store.uid_index.lock().unwrap().insert(uid, env.hash()); + uid_store + .uid_index + .lock() + .unwrap() + .insert((mailbox_hash, uid), env.hash()); envelopes.push((uid, env)); } exists = @@ -924,7 +932,7 @@ impl MailBackend for ImapType { .split_whitespace() .map(usize::from_str) .filter_map(std::result::Result::ok) - .filter_map(|uid| uid_index.get(&uid)) + .filter_map(|uid| uid_index.get(&(mailbox_hash, uid))) .map(|env_hash_ref| *env_hash_ref), )); } diff --git a/melib/src/backends/imap/untagged.rs b/melib/src/backends/imap/untagged.rs index 30c5dad2..52646936 100644 --- a/melib/src/backends/imap/untagged.rs +++ b/melib/src/backends/imap/untagged.rs @@ -100,7 +100,13 @@ impl ImapConnection { uid, flags, body, .. } in v { - if self.uid_store.uid_index.lock().unwrap().contains_key(&uid) { + if self + .uid_store + .uid_index + .lock() + .unwrap() + .contains_key(&(mailbox_hash, uid)) + { continue 'fetch_responses; } if let Ok(mut env) = Envelope::from_bytes( @@ -116,7 +122,7 @@ impl ImapConnection { .uid_index .lock() .unwrap() - .insert(uid, env.hash()); + .insert((mailbox_hash, uid), env.hash()); if let Some((_, keywords)) = flags { let mut tag_lck = self.uid_store.tag_index.write().unwrap(); for f in keywords { @@ -185,7 +191,12 @@ impl ImapConnection { } in v { *mailbox.exists.lock().unwrap() += 1; - if !self.uid_store.uid_index.lock().unwrap().contains_key(&uid) + if !self + .uid_store + .uid_index + .lock() + .unwrap() + .contains_key(&(mailbox_hash, uid)) { if let Ok(mut env) = Envelope::from_bytes( body.unwrap(), @@ -200,7 +211,7 @@ impl ImapConnection { .uid_index .lock() .unwrap() - .insert(uid, env.hash()); + .insert((mailbox_hash, uid), env.hash()); debug!( "Create event {} {} {}", env.hash(), @@ -271,8 +282,12 @@ impl ImapConnection { { Ok(mut v) => { if let Some(uid) = v.pop() { - if let Some(env_hash) = - self.uid_store.uid_index.lock().unwrap().get(&uid) + if let Some(env_hash) = self + .uid_store + .uid_index + .lock() + .unwrap() + .get(&(mailbox_hash, uid)) { self.uid_store .refresh_events diff --git a/melib/src/backends/imap/watch.rs b/melib/src/backends/imap/watch.rs index d4dcf4ea..2cacb6e2 100644 --- a/melib/src/backends/imap/watch.rs +++ b/melib/src/backends/imap/watch.rs @@ -331,7 +331,12 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> { .unwrap(); ctr += 1; *mailbox.exists.lock().unwrap() += 1; - if !uid_store.uid_index.lock().unwrap().contains_key(&uid) { + if !uid_store + .uid_index + .lock() + .unwrap() + .contains_key(&(mailbox_hash, uid)) + { if let Ok(mut env) = Envelope::from_bytes( body.unwrap(), flags.as_ref().map(|&(f, _)| f), @@ -345,7 +350,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> { .uid_index .lock() .unwrap() - .insert(uid, env.hash()); + .insert((mailbox_hash, uid), env.hash()); debug!( "Create event {} {} {}", env.hash(), @@ -460,7 +465,12 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> { format!("parsing {}/{} envelopes..", ctr, len), )) .unwrap(); - if uid_store.uid_index.lock().unwrap().contains_key(&uid) { + if uid_store + .uid_index + .lock() + .unwrap() + .contains_key(&(mailbox_hash, uid)) + { ctr += 1; continue 'fetch_responses_b; } @@ -474,7 +484,11 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> { .lock() .unwrap() .insert(env.hash(), (uid, mailbox_hash)); - uid_store.uid_index.lock().unwrap().insert(uid, env.hash()); + uid_store + .uid_index + .lock() + .unwrap() + .insert((mailbox_hash, uid), env.hash()); if let Some((_, keywords)) = flags { let mut tag_lck = uid_store.tag_index.write().unwrap(); for f in keywords { @@ -552,7 +566,12 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> { { Ok(mut v) => { 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(&(mailbox_hash, uid)) + { conn.add_refresh_event(RefreshEvent { account_hash, mailbox_hash, @@ -696,7 +715,12 @@ pub fn examine_updates( .. } in v { - if uid_store.uid_index.lock().unwrap().contains_key(&uid) { + if uid_store + .uid_index + .lock() + .unwrap() + .contains_key(&(mailbox_hash, uid)) + { continue 'fetch_responses_c; } if let Ok(mut env) = Envelope::from_bytes( @@ -712,7 +736,7 @@ pub fn examine_updates( .uid_index .lock() .unwrap() - .insert(uid, env.hash()); + .insert((mailbox_hash, uid), env.hash()); debug!( "Create event {} {} {}", env.hash(), @@ -790,7 +814,12 @@ pub fn examine_updates( uid, flags, body, .. } in v { - if uid_store.uid_index.lock().unwrap().contains_key(&uid) { + if uid_store + .uid_index + .lock() + .unwrap() + .contains_key(&(mailbox_hash, uid)) + { continue 'fetch_responses_a; } if let Ok(mut env) = @@ -801,7 +830,11 @@ pub fn examine_updates( .lock() .unwrap() .insert(env.hash(), (uid, mailbox_hash)); - uid_store.uid_index.lock().unwrap().insert(uid, env.hash()); + uid_store + .uid_index + .lock() + .unwrap() + .insert((mailbox_hash, uid), env.hash()); if let Some((_, keywords)) = flags { let mut tag_lck = uid_store.tag_index.write().unwrap(); for f in keywords {