melib/Collection: put all fields behind a mutex

async
Manos Pitsidianakis 2020-07-21 07:53:38 +03:00
parent 1112ef4717
commit 0882dbbad0
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
8 changed files with 255 additions and 119 deletions

View File

@ -60,12 +60,19 @@ impl DerefMut for EnvelopeRefMut<'_> {
}
}
#[derive(Debug, Clone, Default)]
#[derive(Debug, Clone)]
pub struct Collection {
pub envelopes: Arc<RwLock<HashMap<EnvelopeHash, Envelope>>>,
pub threads: HashMap<MailboxHash, Threads>,
sent_mailbox: Option<MailboxHash>,
pub mailboxes: HashMap<MailboxHash, HashSet<EnvelopeHash>>,
pub message_id_index: Arc<RwLock<HashMap<Vec<u8>, EnvelopeHash>>>,
pub threads: Arc<RwLock<HashMap<MailboxHash, Threads>>>,
sent_mailbox: Arc<RwLock<Option<MailboxHash>>>,
pub mailboxes: Arc<RwLock<HashMap<MailboxHash, HashSet<EnvelopeHash>>>>,
}
impl Default for Collection {
fn default() -> Self {
Self::new()
}
}
/*
@ -89,15 +96,26 @@ impl Drop for Collection {
*/
impl Collection {
pub fn new(envelopes: HashMap<EnvelopeHash, Envelope>) -> Collection {
let threads = HashMap::with_capacity_and_hasher(16, Default::default());
let mailboxes = HashMap::with_capacity_and_hasher(16, Default::default());
pub fn new() -> Collection {
let message_id_index = Arc::new(RwLock::new(HashMap::with_capacity_and_hasher(
16,
Default::default(),
)));
let threads = Arc::new(RwLock::new(HashMap::with_capacity_and_hasher(
16,
Default::default(),
)));
let mailboxes = Arc::new(RwLock::new(HashMap::with_capacity_and_hasher(
16,
Default::default(),
)));
Collection {
envelopes: Arc::new(RwLock::new(envelopes)),
envelopes: Arc::new(RwLock::new(Default::default())),
message_id_index,
threads,
mailboxes,
sent_mailbox: None,
sent_mailbox: Arc::new(RwLock::new(None)),
}
}
@ -112,14 +130,19 @@ impl Collection {
pub fn remove(&mut self, envelope_hash: EnvelopeHash, mailbox_hash: MailboxHash) {
debug!("DEBUG: Removing {}", envelope_hash);
self.envelopes.write().unwrap().remove(&envelope_hash);
self.mailboxes.entry(mailbox_hash).and_modify(|m| {
m.remove(&envelope_hash);
});
self.threads
self.mailboxes
.write()
.unwrap()
.entry(mailbox_hash)
.and_modify(|m| {
m.remove(&envelope_hash);
});
let mut threads_lck = self.threads.write().unwrap();
threads_lck
.entry(mailbox_hash)
.or_default()
.remove(envelope_hash);
for (h, t) in self.threads.iter_mut() {
for (h, t) in threads_lck.iter_mut() {
if *h == mailbox_hash {
continue;
}
@ -137,15 +160,19 @@ impl Collection {
return false;
}
let mut envelope = self.envelopes.write().unwrap().remove(&old_hash).unwrap();
self.mailboxes.entry(mailbox_hash).and_modify(|m| {
m.remove(&old_hash);
m.insert(new_hash);
});
self.mailboxes
.write()
.unwrap()
.entry(mailbox_hash)
.and_modify(|m| {
m.remove(&old_hash);
m.insert(new_hash);
});
envelope.set_hash(new_hash);
self.envelopes.write().unwrap().insert(new_hash, envelope);
let mut threads_lck = self.threads.write().unwrap();
{
if self
.threads
if threads_lck
.entry(mailbox_hash)
.or_default()
.update_envelope(&self.envelopes, old_hash, new_hash)
@ -155,11 +182,11 @@ impl Collection {
}
}
/* envelope is not in threads, so insert it */
self.threads
threads_lck
.entry(mailbox_hash)
.or_default()
.insert(&mut self.envelopes, new_hash);
for (h, t) in self.threads.iter_mut() {
for (h, t) in threads_lck.iter_mut() {
if *h == mailbox_hash {
continue;
}
@ -178,7 +205,7 @@ impl Collection {
mailbox_hash: MailboxHash,
sent_mailbox: Option<MailboxHash>,
) -> Option<SmallVec<[MailboxHash; 8]>> {
self.sent_mailbox = sent_mailbox;
*self.sent_mailbox.write().unwrap() = sent_mailbox;
let &mut Collection {
ref mut threads,
@ -188,17 +215,19 @@ impl Collection {
..
} = self;
if !threads.contains_key(&mailbox_hash) {
threads.insert(mailbox_hash, Threads::new(new_envelopes.len()));
mailboxes.insert(mailbox_hash, new_envelopes.keys().cloned().collect());
let mut threads_lck = threads.write().unwrap();
let mut mailboxes_lck = mailboxes.write().unwrap();
if !threads_lck.contains_key(&mailbox_hash) {
threads_lck.insert(mailbox_hash, Threads::new(new_envelopes.len()));
mailboxes_lck.insert(mailbox_hash, new_envelopes.keys().cloned().collect());
for (h, e) in new_envelopes {
envelopes.write().unwrap().insert(h, e);
}
} else {
mailboxes.entry(mailbox_hash).and_modify(|m| {
mailboxes_lck.entry(mailbox_hash).and_modify(|m| {
m.extend(new_envelopes.keys().cloned());
});
threads.entry(mailbox_hash).and_modify(|t| {
threads_lck.entry(mailbox_hash).and_modify(|t| {
let mut ordered_hash_set =
new_envelopes.keys().cloned().collect::<Vec<EnvelopeHash>>();
ordered_hash_set.sort_by(|a, b| {
@ -218,14 +247,19 @@ impl Collection {
}
let mut ret = SmallVec::new();
let keys = threads.keys().cloned().collect::<Vec<MailboxHash>>();
let keys = threads_lck.keys().cloned().collect::<Vec<MailboxHash>>();
for t_fh in keys {
if t_fh == mailbox_hash {
continue;
}
if sent_mailbox.map(|f| f == mailbox_hash).unwrap_or(false) {
if sent_mailbox
.read()
.unwrap()
.map(|f| f == mailbox_hash)
.unwrap_or(false)
{
let envelopes_lck = envelopes.read().unwrap();
let mut ordered_hash_set = threads[&mailbox_hash]
let mut ordered_hash_set = threads_lck[&mailbox_hash]
.hash_set
.iter()
.cloned()
@ -239,16 +273,24 @@ impl Collection {
drop(envelopes_lck);
let mut updated = false;
for h in ordered_hash_set {
updated |= threads.entry(t_fh).or_default().insert_reply(envelopes, h);
updated |= threads_lck
.entry(t_fh)
.or_default()
.insert_reply(envelopes, h);
}
if updated {
ret.push(t_fh);
}
continue;
}
if sent_mailbox.map(|f| f == t_fh).unwrap_or(false) {
if sent_mailbox
.read()
.unwrap()
.map(|f| f == t_fh)
.unwrap_or(false)
{
let envelopes_lck = envelopes.read().unwrap();
let mut ordered_hash_set = threads[&t_fh]
let mut ordered_hash_set = threads_lck[&t_fh]
.hash_set
.iter()
.cloned()
@ -262,7 +304,7 @@ impl Collection {
drop(envelopes_lck);
let mut updated = false;
for h in ordered_hash_set {
updated |= threads
updated |= threads_lck
.entry(mailbox_hash)
.or_default()
.insert_reply(envelopes, h);
@ -288,24 +330,30 @@ impl Collection {
let old_env = self.envelopes.write().unwrap().remove(&old_hash).unwrap();
envelope.set_thread(old_env.thread());
let new_hash = envelope.hash();
self.mailboxes.entry(mailbox_hash).and_modify(|m| {
m.remove(&old_hash);
m.insert(new_hash);
});
self.mailboxes
.write()
.unwrap()
.entry(mailbox_hash)
.and_modify(|m| {
m.remove(&old_hash);
m.insert(new_hash);
});
self.envelopes.write().unwrap().insert(new_hash, envelope);
let mut threads_lck = self.threads.write().unwrap();
if self
.sent_mailbox
.read()
.unwrap()
.map(|f| f == mailbox_hash)
.unwrap_or(false)
{
for (_, t) in self.threads.iter_mut() {
for (_, t) in threads_lck.iter_mut() {
t.update_envelope(&self.envelopes, old_hash, new_hash)
.unwrap_or(());
}
}
{
if self
.threads
if threads_lck
.entry(mailbox_hash)
.or_default()
.update_envelope(&self.envelopes, old_hash, new_hash)
@ -315,11 +363,11 @@ impl Collection {
}
}
/* envelope is not in threads, so insert it */
self.threads
threads_lck
.entry(mailbox_hash)
.or_default()
.insert(&mut self.envelopes, new_hash);
for (h, t) in self.threads.iter_mut() {
for (h, t) in threads_lck.iter_mut() {
if *h == mailbox_hash {
continue;
}
@ -330,19 +378,21 @@ impl Collection {
}
pub fn update_flags(&mut self, env_hash: EnvelopeHash, mailbox_hash: MailboxHash) {
let mut threads_lck = self.threads.write().unwrap();
if self
.sent_mailbox
.read()
.unwrap()
.map(|f| f == mailbox_hash)
.unwrap_or(false)
{
for (_, t) in self.threads.iter_mut() {
for (_, t) in threads_lck.iter_mut() {
t.update_envelope(&self.envelopes, env_hash, env_hash)
.unwrap_or(());
}
}
{
if self
.threads
if threads_lck
.entry(mailbox_hash)
.or_default()
.update_envelope(&self.envelopes, env_hash, env_hash)
@ -352,11 +402,11 @@ impl Collection {
}
}
/* envelope is not in threads, so insert it */
self.threads
threads_lck
.entry(mailbox_hash)
.or_default()
.insert(&mut self.envelopes, env_hash);
for (h, t) in self.threads.iter_mut() {
for (h, t) in threads_lck.iter_mut() {
if *h == mailbox_hash {
continue;
}
@ -368,16 +418,24 @@ impl Collection {
pub fn insert(&mut self, envelope: Envelope, mailbox_hash: MailboxHash) -> bool {
let hash = envelope.hash();
self.mailboxes.entry(mailbox_hash).and_modify(|m| {
m.insert(hash);
});
self.mailboxes
.write()
.unwrap()
.entry(mailbox_hash)
.and_modify(|m| {
m.insert(hash);
});
self.envelopes.write().unwrap().insert(hash, envelope);
self.threads
.write()
.unwrap()
.entry(mailbox_hash)
.or_default()
.insert(&mut self.envelopes, hash);
if self
.sent_mailbox
.read()
.unwrap()
.map(|f| f == mailbox_hash)
.unwrap_or(false)
{
@ -388,7 +446,7 @@ impl Collection {
pub fn insert_reply(&mut self, env_hash: EnvelopeHash) {
debug_assert!(self.envelopes.read().unwrap().contains_key(&env_hash));
for (_, t) in self.threads.iter_mut() {
for (_, t) in self.threads.write().unwrap().iter_mut() {
t.insert_reply(&mut self.envelopes, env_hash);
}
}
@ -403,27 +461,45 @@ impl Collection {
EnvelopeRefMut { guard, env_hash }
}
pub fn get_threads(&'_ self, hash: MailboxHash) -> RwRef<'_, MailboxHash, Threads> {
let guard = self.threads.read().unwrap();
RwRef { guard, hash }
}
pub fn get_mailbox(
&'_ self,
hash: MailboxHash,
) -> RwRef<'_, MailboxHash, HashSet<EnvelopeHash>> {
let guard = self.mailboxes.read().unwrap();
RwRef { guard, hash }
}
pub fn contains_key(&self, env_hash: &EnvelopeHash) -> bool {
self.envelopes.read().unwrap().contains_key(env_hash)
}
pub fn new_mailbox(&mut self, mailbox_hash: MailboxHash) {
if !self.mailboxes.contains_key(&mailbox_hash) {
self.mailboxes.insert(mailbox_hash, Default::default());
self.threads.insert(mailbox_hash, Threads::default());
let mut mailboxes_lck = self.mailboxes.write().unwrap();
if !mailboxes_lck.contains_key(&mailbox_hash) {
mailboxes_lck.insert(mailbox_hash, Default::default());
self.threads
.write()
.unwrap()
.insert(mailbox_hash, Threads::default());
}
}
}
impl Index<&MailboxHash> for Collection {
type Output = HashSet<EnvelopeHash>;
fn index(&self, index: &MailboxHash) -> &HashSet<EnvelopeHash> {
&self.mailboxes[index]
}
pub struct RwRef<'g, K: std::cmp::Eq + std::hash::Hash, V> {
guard: RwLockReadGuard<'g, HashMap<K, V>>,
hash: K,
}
impl IndexMut<&MailboxHash> for Collection {
fn index_mut(&mut self, index: &MailboxHash) -> &mut HashSet<EnvelopeHash> {
self.mailboxes.get_mut(index).unwrap()
impl<K: std::cmp::Eq + std::hash::Hash, V> Deref for RwRef<'_, K, V> {
type Target = V;
fn deref(&self) -> &V {
self.guard.get(&self.hash).unwrap()
}
}

View File

@ -148,9 +148,13 @@ pub trait MailListingTrait: ListingTrait {
let account = &mut context.accounts[account_pos];
let mut envs_to_set: SmallVec<[EnvelopeHash; 8]> = SmallVec::new();
let mailbox_hash = self.coordinates().1;
for (_, h) in account.collection.threads[&mailbox_hash].thread_group_iter(thread_hash) {
for (_, h) in account
.collection
.get_threads(mailbox_hash)
.thread_group_iter(thread_hash)
{
envs_to_set.push(
account.collection.threads[&mailbox_hash].thread_nodes()[&h]
account.collection.get_threads(mailbox_hash).thread_nodes()[&h]
.message()
.unwrap(),
);
@ -1209,7 +1213,7 @@ impl Component for Listing {
MailboxStatus::Available | MailboxStatus::Parsing(_, _) => format!(
"Mailbox: {}, Messages: {}, New: {}",
account[&mailbox_hash].ref_mailbox.name(),
account.collection[&mailbox_hash].len(),
account.collection.get_mailbox(mailbox_hash).len(),
account[&mailbox_hash]
.ref_mailbox
.count()

View File

@ -247,7 +247,9 @@ impl MailListingTrait for CompactListing {
}
}
let threads = &context.accounts[self.cursor_pos.0].collection.threads[&self.cursor_pos.1];
let threads = context.accounts[self.cursor_pos.0]
.collection
.get_threads(self.cursor_pos.1);
let mut roots = threads.roots();
threads.group_inner_sort_by(
&mut roots,
@ -276,7 +278,7 @@ impl MailListingTrait for CompactListing {
) {
let account = &context.accounts[self.cursor_pos.0];
let threads = &account.collection.threads[&self.cursor_pos.1];
let threads = account.collection.get_threads(self.cursor_pos.1);
self.order.clear();
self.length = 0;
let mut rows = Vec::with_capacity(1024);
@ -341,7 +343,7 @@ impl MailListingTrait for CompactListing {
}
}
let entry_strings = self.make_entry_string(&root_envelope, context, threads, thread);
let entry_strings = self.make_entry_string(&root_envelope, context, &threads, thread);
row_widths.1.push(
entry_strings
.date
@ -462,7 +464,7 @@ impl ListingTrait for CompactListing {
let thread_hash = self.get_thread_under_cursor(idx);
let account = &context.accounts[self.cursor_pos.0];
let threads = &account.collection.threads[&self.cursor_pos.1];
let threads = account.collection.get_threads(self.cursor_pos.1);
let thread = threads.thread_ref(thread_hash);
let row_attr = row_attr!(
@ -685,7 +687,7 @@ impl ListingTrait for CompactListing {
}
let account = &context.accounts[self.cursor_pos.0];
let threads = &account.collection.threads[&self.cursor_pos.1];
let threads = account.collection.get_threads(self.cursor_pos.1);
for r in 0..cmp::min(self.length - top_idx, rows) {
let thread_hash = self.get_thread_under_cursor(r + top_idx);
let row_attr = row_attr!(
@ -767,7 +769,7 @@ impl ListingTrait for CompactListing {
let account = &context.accounts[self.cursor_pos.0];
match results {
Ok(results) => {
let threads = &account.collection.threads[&self.cursor_pos.1];
let threads = account.collection.get_threads(self.cursor_pos.1);
for env_hash in results {
if !account.collection.contains_key(&env_hash) {
continue;
@ -971,7 +973,7 @@ impl CompactListing {
fn update_line(&mut self, context: &Context, thread_hash: ThreadHash) {
let account = &context.accounts[self.cursor_pos.0];
let threads = &account.collection.threads[&self.cursor_pos.1];
let threads = account.collection.get_threads(self.cursor_pos.1);
let thread = threads.thread_ref(thread_hash);
let thread_node_hash = threads.thread_group_iter(thread_hash).next().unwrap().1;
if let Some(env_hash) = threads.thread_nodes()[&thread_node_hash].message() {
@ -993,7 +995,7 @@ impl CompactListing {
self.color_cache.odd
};
let envelope: EnvelopeRef = account.collection.get_env(env_hash);
let strings = self.make_entry_string(&envelope, context, threads, thread_hash);
let strings = self.make_entry_string(&envelope, context, &threads, thread_hash);
drop(envelope);
let columns = &mut self.data_columns.columns;
let min_width = (
@ -1136,7 +1138,7 @@ impl CompactListing {
);
let account = &context.accounts[self.cursor_pos.0];
let threads = &account.collection.threads[&self.cursor_pos.1];
let threads = account.collection.get_threads(self.cursor_pos.1);
for ((idx, (thread_hash, root_env_hash)), strings) in
self.rows.iter().skip(start).take(end - start + 1)
@ -1309,7 +1311,7 @@ impl CompactListing {
let account = &context.accounts[self.cursor_pos.0];
match results {
Ok(results) => {
let threads = &account.collection.threads[&self.cursor_pos.1];
let threads = account.collection.get_threads(self.cursor_pos.1);
for env_hash in results {
if !account.collection.contains_key(&env_hash) {
continue;
@ -1497,6 +1499,8 @@ impl Component for CompactListing {
account
.collection
.threads
.write()
.unwrap()
.entry(self.cursor_pos.1)
.and_modify(|threads| {
let is_snoozed = threads.thread_ref(thread).snoozed();
@ -1526,7 +1530,7 @@ impl Component for CompactListing {
}
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
let account = &context.accounts[self.cursor_pos.0];
let threads = &account.collection.threads[&self.cursor_pos.1];
let threads = account.collection.get_threads(self.cursor_pos.1);
if !account.collection.contains_key(&new_hash) {
return false;
}
@ -1536,6 +1540,7 @@ impl Component for CompactListing {
}
let thread: ThreadHash =
threads.find_group(threads.thread_nodes()[&new_env_thread_node_hash].group);
drop(threads);
if self.order.contains_key(&thread) {
self.row_updates.push(thread);
}
@ -1553,7 +1558,7 @@ impl Component for CompactListing {
}
UIEvent::EnvelopeUpdate(ref env_hash) => {
let account = &context.accounts[self.cursor_pos.0];
let threads = &account.collection.threads[&self.cursor_pos.1];
let threads = account.collection.get_threads(self.cursor_pos.1);
if !account.collection.contains_key(&env_hash) {
return false;
}
@ -1563,6 +1568,7 @@ impl Component for CompactListing {
}
let thread: ThreadHash =
threads.find_group(threads.thread_nodes()[&new_env_thread_node_hash].group);
drop(threads);
if self.order.contains_key(&thread) {
self.row_updates.push(thread);
}

View File

@ -152,7 +152,9 @@ impl MailListingTrait for ConversationsListing {
}
}
let threads = &context.accounts[self.cursor_pos.0].collection.threads[&self.cursor_pos.1];
let threads = context.accounts[self.cursor_pos.0]
.collection
.get_threads(self.cursor_pos.1);
self.all_threads.clear();
let mut roots = threads.roots();
threads.group_inner_sort_by(
@ -183,7 +185,7 @@ impl MailListingTrait for ConversationsListing {
) {
let account = &context.accounts[self.cursor_pos.0];
let threads = &account.collection.threads[&self.cursor_pos.1];
let threads = account.collection.get_threads(self.cursor_pos.1);
self.order.clear();
self.selection.clear();
self.length = 0;
@ -255,8 +257,13 @@ impl MailListingTrait for ConversationsListing {
}
}
let strings =
self.make_entry_string(root_envelope, context, &from_address_list, threads, thread);
let strings = self.make_entry_string(
root_envelope,
context,
&from_address_list,
&threads,
thread,
);
max_entry_columns = std::cmp::max(
max_entry_columns,
strings.flag.len()
@ -436,7 +443,7 @@ impl ListingTrait for ConversationsListing {
let thread_hash = self.get_thread_under_cursor(idx);
let account = &context.accounts[self.cursor_pos.0];
let threads = &account.collection.threads[&self.cursor_pos.1];
let threads = account.collection.get_threads(self.cursor_pos.1);
let thread = threads.thread_ref(thread_hash);
let fg_color = if thread.unseen() > 0 {
@ -717,7 +724,7 @@ impl ListingTrait for ConversationsListing {
let account = &context.accounts[self.cursor_pos.0];
match results {
Ok(results) => {
let threads = &account.collection.threads[&self.cursor_pos.1];
let threads = account.collection.get_threads(self.cursor_pos.1);
for env_hash in results {
if !account.collection.contains_key(&env_hash) {
continue;
@ -952,7 +959,7 @@ impl ConversationsListing {
fn update_line(&mut self, context: &Context, thread_hash: ThreadHash) {
let account = &context.accounts[self.cursor_pos.0];
let threads = &account.collection.threads[&self.cursor_pos.1];
let threads = account.collection.get_threads(self.cursor_pos.1);
let thread = threads.thread_ref(thread_hash);
let thread_node_hash = threads.thread_group_iter(thread_hash).next().unwrap().1;
let idx: usize = self.order[&thread_hash];
@ -989,8 +996,13 @@ impl ConversationsListing {
}
}
let envelope: EnvelopeRef = account.collection.get_env(env_hash);
let strings =
self.make_entry_string(&envelope, context, &from_address_list, threads, thread_hash);
let strings = self.make_entry_string(
&envelope,
context,
&from_address_list,
&threads,
thread_hash,
);
drop(envelope);
/* draw flags */
let (x, _) = write_string_to_grid(
@ -1236,7 +1248,7 @@ impl Component for ConversationsListing {
}
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
let account = &context.accounts[self.cursor_pos.0];
let threads = &account.collection.threads[&self.cursor_pos.1];
let threads = account.collection.get_threads(self.cursor_pos.1);
if !account.collection.contains_key(&new_hash) {
return false;
}
@ -1246,6 +1258,7 @@ impl Component for ConversationsListing {
}
let thread: ThreadHash =
threads.find_group(threads.thread_nodes()[&env_thread_node_hash].group);
drop(threads);
if self.order.contains_key(&thread) {
self.row_updates.push(thread);
}
@ -1257,7 +1270,7 @@ impl Component for ConversationsListing {
}
UIEvent::EnvelopeUpdate(ref env_hash) => {
let account = &context.accounts[self.cursor_pos.0];
let threads = &account.collection.threads[&self.cursor_pos.1];
let threads = account.collection.get_threads(self.cursor_pos.1);
if !account.collection.contains_key(&env_hash) {
return false;
}
@ -1267,6 +1280,7 @@ impl Component for ConversationsListing {
}
let thread: ThreadHash =
threads.find_group(threads.thread_nodes()[&env_thread_node_hash].group);
drop(threads);
if self.order.contains_key(&thread) {
self.row_updates.push(thread);
}
@ -1315,6 +1329,8 @@ impl Component for ConversationsListing {
account
.collection
.threads
.write()
.unwrap()
.entry(self.cursor_pos.1)
.and_modify(|threads| {
let is_snoozed = threads.thread_ref(thread).snoozed();

View File

@ -169,7 +169,9 @@ impl MailListingTrait for PlainListing {
return;
}
}
self.local_collection = context.accounts[self.cursor_pos.0].collection[&self.cursor_pos.1]
self.local_collection = context.accounts[self.cursor_pos.0]
.collection
.get_mailbox(self.cursor_pos.1)
.iter()
.cloned()
.collect();
@ -178,8 +180,9 @@ impl MailListingTrait for PlainListing {
.envelopes
.read()
.unwrap();
self.thread_node_hashes = context.accounts[self.cursor_pos.0].collection
[&self.cursor_pos.1]
self.thread_node_hashes = context.accounts[self.cursor_pos.0]
.collection
.get_mailbox(self.cursor_pos.1)
.iter()
.map(|h| (*h, env_lck[h].thread()))
.collect();
@ -232,7 +235,7 @@ impl MailListingTrait for PlainListing {
items: Box<dyn Iterator<Item = ThreadHash>>,
) {
let account = &context.accounts[self.cursor_pos.0];
let threads = &account.collection.threads[&self.cursor_pos.1];
let threads = account.collection.get_threads(self.cursor_pos.1);
let roots = items
.filter_map(|r| threads.groups[&r].root().map(|r| r.root))
.collect::<_>();
@ -1218,7 +1221,10 @@ impl Component for PlainListing {
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
let account = &context.accounts[self.cursor_pos.0];
if !account.collection.contains_key(new_hash)
|| !account.collection[&self.cursor_pos.1].contains(new_hash)
|| !account
.collection
.get_mailbox(self.cursor_pos.1)
.contains(new_hash)
{
return false;
}
@ -1244,7 +1250,10 @@ impl Component for PlainListing {
UIEvent::EnvelopeUpdate(ref env_hash) => {
let account = &context.accounts[self.cursor_pos.0];
if !account.collection.contains_key(env_hash)
|| !account.collection[&self.cursor_pos.1].contains(env_hash)
|| !account
.collection
.get_mailbox(self.cursor_pos.1)
.contains(env_hash)
{
return false;
}

View File

@ -121,7 +121,9 @@ impl MailListingTrait for ThreadListing {
return;
}
}
let threads = &context.accounts[self.cursor_pos.0].collection.threads[&self.cursor_pos.1];
let threads = context.accounts[self.cursor_pos.0]
.collection
.get_threads(self.cursor_pos.1);
let mut roots = threads.roots();
threads.group_inner_sort_by(
&mut roots,
@ -141,7 +143,7 @@ impl MailListingTrait for ThreadListing {
items: Box<dyn Iterator<Item = ThreadHash>>,
) {
let account = &context.accounts[self.cursor_pos.0];
let threads = &account.collection.threads[&self.cursor_pos.1];
let threads = account.collection.get_threads(self.cursor_pos.1);
self.length = 0;
self.order.clear();
let default_cell = {
@ -226,7 +228,7 @@ impl MailListingTrait for ThreadListing {
idx,
indentation,
thread_node_hash,
threads,
&threads,
&indentations,
has_sibling,
is_root,
@ -1164,7 +1166,6 @@ impl Component for ThreadListing {
}
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
let account = &context.accounts[self.cursor_pos.0];
let threads = &account.collection.threads[&self.cursor_pos.1];
if !account.collection.contains_key(&new_hash) {
return false;
}
@ -1188,7 +1189,6 @@ impl Component for ThreadListing {
}
UIEvent::EnvelopeUpdate(ref env_hash) => {
let account = &context.accounts[self.cursor_pos.0];
let threads = &account.collection.threads[&self.cursor_pos.1];
if !account.collection.contains_key(env_hash) {
return false;
}

View File

@ -161,7 +161,7 @@ impl ThreadView {
fn initiate(&mut self, expanded_hash: Option<ThreadNodeHash>, context: &Context) {
let account = &context.accounts[self.coordinates.0];
let threads = &account.collection.threads[&self.coordinates.1];
let threads = account.collection.get_threads(self.coordinates.1);
if !threads.groups.contains_key(&self.thread_group) {
return;
@ -648,7 +648,7 @@ impl ThreadView {
let y = if self.dirty {
clear_area(grid, area, crate::conf::value(context, "theme_default"));
let account = &context.accounts[self.coordinates.0];
let threads = &account.collection.threads[&self.coordinates.1];
let threads = account.collection.get_threads(self.coordinates.1);
let thread_root = threads
.thread_group_iter(self.thread_group)
.next()
@ -751,7 +751,7 @@ impl ThreadView {
let y = {
clear_area(grid, area, crate::conf::value(context, "theme_default"));
let account = &context.accounts[self.coordinates.0];
let threads = &account.collection.threads[&self.coordinates.1];
let threads = account.collection.get_threads(self.coordinates.1);
let thread_root = threads
.thread_group_iter(self.thread_group)
.next()

View File

@ -726,7 +726,10 @@ impl Account {
RefreshEventKind::Create(envelope) => {
let env_hash = envelope.hash();
if self.collection.contains_key(&env_hash)
&& self.collection[&mailbox_hash].contains(&env_hash)
&& self
.collection
.get_mailbox(mailbox_hash)
.contains(&env_hash)
{
return None;
}
@ -770,10 +773,13 @@ impl Account {
let thread = {
let thread_hash = self.collection.get_env(env_hash).thread();
self.collection.threads[&mailbox_hash]
.find_group(self.collection.threads[&mailbox_hash][&thread_hash].group)
self.collection.get_threads(mailbox_hash).find_group(
self.collection.get_threads(mailbox_hash)[&thread_hash].group,
)
};
if self.collection.threads[&mailbox_hash]
if self
.collection
.get_threads(mailbox_hash)
.thread_ref(thread)
.snoozed()
{
@ -797,8 +803,9 @@ impl Account {
RefreshEventKind::Remove(env_hash) => {
let thread_hash = {
let thread_hash = self.collection.get_env(env_hash).thread();
self.collection.threads[&mailbox_hash]
.find_group(self.collection.threads[&mailbox_hash][&thread_hash].group)
self.collection.get_threads(mailbox_hash).find_group(
self.collection.get_threads(mailbox_hash)[&thread_hash].group,
)
};
#[cfg(feature = "sqlite3")]
{
@ -1006,7 +1013,12 @@ impl Account {
None => {
return match self.mailbox_entries[&mailbox_hash].status {
MailboxStatus::Available | MailboxStatus::Parsing(_, _)
if self.collection.mailboxes.contains_key(&mailbox_hash) =>
if self
.collection
.mailboxes
.read()
.unwrap()
.contains_key(&mailbox_hash) =>
{
Ok(())
}
@ -1157,7 +1169,12 @@ impl Account {
}
if self.mailbox_entries[&mailbox_hash].status.is_available()
|| (self.mailbox_entries[&mailbox_hash].status.is_parsing()
&& self.collection.mailboxes.contains_key(&mailbox_hash))
&& self
.collection
.mailboxes
.read()
.unwrap()
.contains_key(&mailbox_hash))
{
Ok(())
} else {
@ -1346,10 +1363,6 @@ impl Account {
})
}
pub fn thread(&self, h: ThreadNodeHash, f: MailboxHash) -> &ThreadNode {
&self.collection.threads[&f].thread_nodes()[&h]
}
pub fn mailbox_operation(
&mut self,
op: crate::execute::actions::MailboxOperation,
@ -1417,9 +1430,13 @@ impl Account {
);
self.collection
.threads
.write()
.unwrap()
.insert(mailbox_hash, Threads::default());
self.collection
.mailboxes
.write()
.unwrap()
.insert(mailbox_hash, Default::default());
build_mailboxes_order(
&mut self.tree,
@ -1451,7 +1468,11 @@ impl Account {
if self.sent_mailbox == Some(mailbox_hash) {
self.sent_mailbox = None;
}
self.collection.threads.remove(&mailbox_hash);
self.collection
.threads
.write()
.unwrap()
.remove(&mailbox_hash);
let deleted_mailbox = self.mailbox_entries.remove(&mailbox_hash).unwrap();
/* if deleted mailbox had parent, we need to update its children field */
if let Some(parent_hash) = deleted_mailbox.ref_mailbox.parent() {
@ -1461,7 +1482,11 @@ impl Account {
parent.ref_mailbox = mailboxes.remove(&parent_hash).unwrap();
});
}
self.collection.mailboxes.remove(&mailbox_hash);
self.collection
.mailboxes
.write()
.unwrap()
.remove(&mailbox_hash);
build_mailboxes_order(
&mut self.tree,
&self.mailbox_entries,
@ -1576,7 +1601,7 @@ impl Account {
let mut ret = SmallVec::new();
let envelopes = self.collection.envelopes.read().unwrap();
for &env_hash in self.collection[&mailbox_hash].iter() {
for &env_hash in self.collection.get_mailbox(mailbox_hash).iter() {
let envelope = &envelopes[&env_hash];
if envelope.subject().contains(&search_term) {
ret.push(env_hash);