imap: index by (MailboxHash, UID) instead of just UID

Mailboxes can share UIDs.
memfd
Manos Pitsidianakis 2020-06-11 11:41:08 +03:00
parent 55948dd7c2
commit 2d3f49d64d
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
3 changed files with 75 additions and 19 deletions

View File

@ -126,7 +126,7 @@ pub struct UIDStore {
cache_headers: bool,
uidvalidity: Arc<Mutex<HashMap<MailboxHash, UID>>>,
hash_index: Arc<Mutex<HashMap<EnvelopeHash, (UID, MailboxHash)>>>,
uid_index: Arc<Mutex<HashMap<UID, EnvelopeHash>>>,
uid_index: Arc<Mutex<HashMap<(MailboxHash, UID), EnvelopeHash>>>,
byte_cache: Arc<Mutex<HashMap<UID, EnvelopeCache>>>,
tag_index: Arc<RwLock<BTreeMap<u64, String>>>,
@ -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),
));
}

View File

@ -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

View File

@ -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 {