[geary/wip/713150-conversations] Small fixes, optimizations
- From: Jim Nelson <jnelson src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/713150-conversations] Small fixes, optimizations
- Date: Fri, 27 Feb 2015 21:20:48 +0000 (UTC)
commit ef9160e8c1ae765bbb239c16d461c4b9f983f264
Author: Jim Nelson <jim yorba org>
Date: Fri Feb 27 13:20:36 2015 -0800
Small fixes, optimizations
src/engine/app/app-conversation-monitor.vala | 170 +++++++++++++-------------
src/engine/imap-db/imap-db-folder.vala | 8 +-
2 files changed, 92 insertions(+), 86 deletions(-)
---
diff --git a/src/engine/app/app-conversation-monitor.vala b/src/engine/app/app-conversation-monitor.vala
index f44b2ae..2092389 100644
--- a/src/engine/app/app-conversation-monitor.vala
+++ b/src/engine/app/app-conversation-monitor.vala
@@ -464,6 +464,8 @@ public class Geary.App.ConversationMonitor : BaseObject {
Logging.debug(Logging.Flag.CONVERSATIONS, "[%s] ConversationMonitor::process_email: %d emails",
folder.to_string(), email_ids.size);
+ // Convert EmailIdentifiers into associations (groupings) of EmailIdentifiers with all known
+ // paths
Gee.Collection<AssociatedEmails>? associations = null;
try {
associations = yield folder.account.local_search_associated_emails_async(
@@ -479,71 +481,8 @@ public class Geary.App.ConversationMonitor : BaseObject {
Gee.HashSet<Conversation> added = new Gee.HashSet<Conversation>();
Gee.HashMultiMap<Conversation, Email> appended = new Gee.HashMultiMap<Conversation, Email>();
-
- foreach (AssociatedEmails association in associations) {
- // get all conversations for these emails (possible for multiple conversations to be
- // started and then coalesce as new emails come in)
- Gee.HashSet<Conversation> existing = new Gee.HashSet<Conversation>();
- foreach (EmailIdentifier associated_id in association.email_ids) {
- Conversation? conversation = all_email_id_to_conversation[associated_id];
- if (conversation != null)
- existing.add(conversation);
-
- // only add to primary map if identifier is part of the original set of arguments
- // and they're from this folder and not another one
- if (email_ids.contains(associated_id) && path.equal_to(folder.path))
- primary_email_id_to_conversation[associated_id] = conversation;
- }
-
- // Create or pick conversation for these emails
- Conversation conversation;
- switch (existing.size) {
- case 0:
- conversation = new Conversation(this);
- break;
-
- case 1:
- conversation = traverse<Conversation>(existing).first();
- break;
-
- default:
- // TODO
- conversation = merge_conversations(existing);
- break;
- }
-
- // trim down the email identifiers we already have emails for
- Gee.HashSet<EmailIdentifier> trimmed_ids = traverse<EmailIdentifier>(association.email_ids)
- .filter(id => !all_email_id_to_conversation.has_key(id))
- .to_hash_set();
-
- // load remaining emails for the conversation objects
- Gee.Collection<Email>? emails = null;
- try {
- emails = yield folder.account.local_list_email_async(trimmed_ids, required_fields,
- cancellable);
- } catch (Error err) {
- debug("Unable to list local account email: %s", err.message);
- }
-
- if (emails == null || emails.size == 0)
- continue;
-
- // add all emails and each known path(s) to the Conversation and EmailIdentifier mapping
- foreach (Email email in emails) {
- conversation.add(email, association.known_paths[email.id]);
- all_email_id_to_conversation[email.id] = conversation;
- }
-
- // if new, added, otherwise appended (if not already added)
- if (!conversations.contains(conversation)) {
- conversations.add(conversation);
- added.add(conversation);
- } else if (!added.contains(conversation)) {
- foreach (Email email in emails)
- appended.set(conversation, email);
- }
- }
+ foreach (AssociatedEmails association in associations)
+ yield process_association_async(association, path, email_ids, added, appended, cancellable);
debug("%d added conversations, %d appended", added.size, appended.size);
@@ -559,6 +498,84 @@ public class Geary.App.ConversationMonitor : BaseObject {
folder.to_string(), email_ids.size);
}
+ private async void process_association_async(AssociatedEmails association, FolderPath path,
+ Gee.Collection<EmailIdentifier> original_email_ids, Gee.Set<Conversation> added,
+ Gee.MultiMap<Conversation, Email> appended, Cancellable? cancellable) {
+ // get all conversations for these emails (possible for multiple conversations to be
+ // started and then coalesce as new emails come in) and see if any are known to be in this
+ // folder
+ bool any_in_folder = false;
+ Gee.HashSet<Conversation> existing = new Gee.HashSet<Conversation>();
+ foreach (EmailIdentifier associated_id in association.email_ids) {
+ Conversation? conversation = all_email_id_to_conversation[associated_id];
+ if (conversation != null)
+ existing.add(conversation);
+
+ // track if any of the messages are known to be in this folder
+ if (association.known_paths[associated_id].contains(folder.path))
+ any_in_folder = true;
+
+ // only add to primary map if identifier is part of the original set of arguments
+ // and they're from this folder and not another one
+ if (original_email_ids.contains(associated_id) && path.equal_to(folder.path))
+ primary_email_id_to_conversation[associated_id] = conversation;
+ }
+
+ // if these are out-of-folder emails, only add to conversations if any email
+ // in them are associated with this folder and are not known to any other conversations
+ if (!path.equal_to(folder.path) && existing.size == 0 && !any_in_folder)
+ return;
+
+ // Create or pick conversation for these emails
+ Conversation conversation;
+ switch (existing.size) {
+ case 0:
+ conversation = new Conversation(this);
+ break;
+
+ case 1:
+ conversation = traverse<Conversation>(existing).first();
+ break;
+
+ default:
+ // TODO
+ conversation = merge_conversations(existing);
+ break;
+ }
+
+ // trim down the email identifiers we already have emails for
+ Gee.HashSet<EmailIdentifier> trimmed_ids = traverse<EmailIdentifier>(association.email_ids)
+ .filter(id => !all_email_id_to_conversation.has_key(id))
+ .to_hash_set();
+
+ // load remaining emails for the conversation objects
+ Gee.Collection<Email>? emails = null;
+ try {
+ emails = yield folder.account.local_list_email_async(trimmed_ids, required_fields,
+ cancellable);
+ } catch (Error err) {
+ debug("Unable to list local account email: %s", err.message);
+ }
+
+ if (emails == null || emails.size == 0)
+ return;
+
+ // add all emails and each known path(s) to the Conversation and EmailIdentifier mapping
+ foreach (Email email in emails) {
+ conversation.add(email, association.known_paths[email.id]);
+ all_email_id_to_conversation[email.id] = conversation;
+ }
+
+ // if new, added, otherwise appended (if not already added)
+ if (!conversations.contains(conversation)) {
+ conversations.add(conversation);
+ added.add(conversation);
+ } else if (!added.contains(conversation)) {
+ foreach (Email email in emails)
+ appended.set(conversation, email);
+ }
+ }
+
// TODO
private Conversation merge_conversations(Gee.Set<Conversation> conversations) {
breakpoint();
@@ -728,9 +745,6 @@ public class Geary.App.ConversationMonitor : BaseObject {
int initial_message_count = get_email_count();
- debug("FILLWINDOW: min_window_count=%d conversations=%d message_count=%d", min_window_count,
- conversations.size, initial_message_count);
-
// only do local-load if the Folder isn't completely opened, otherwise this operation
// will block other (more important) operations while it waits for the folder to
// remote-open
@@ -753,31 +767,19 @@ public class Geary.App.ConversationMonitor : BaseObject {
Geary.EmailIdentifier? low_id = yield get_lowest_email_id_async(null);
if (low_id != null && !is_insert) {
- // Load at least as many messages as remianing conversations.
- int num_to_load = min_window_count - conversations.size;
- if (num_to_load < WINDOW_FILL_MESSAGE_COUNT)
- num_to_load = WINDOW_FILL_MESSAGE_COUNT;
+ // Load at least as many messages as remaining conversations.
+ int num_to_load = Numeric.int_floor(min_window_count - conversations.size,
+ WINDOW_FILL_MESSAGE_COUNT);
- debug("FILLWINDOW: low_id=%s num_to_load=%d", low_id.to_string(), num_to_load);
yield load_by_id_async(low_id, num_to_load, Email.Field.NONE, flags, cancellable_monitor);
} else {
// No existing messages or an insert invalidated our existing list,
// need to start from scratch.
- debug("FILLWINDOW: low_id=%s is_insert=%s min_window_count=%d",
- (low_id != null) ? low_id.to_string() : "(null)", is_insert.to_string(),
- min_window_count);
yield load_by_id_async(null, min_window_count, Email.Field.NONE, flags, cancellable_monitor);
}
// Run again to make sure we're full unless we ran out of messages.
- int final_message_count = get_email_count();
- if (final_message_count != initial_message_count) {
- debug("FILLWINDOW: Schedule refill: final=%d initial=%d (%d in folder, %d found)",
- final_message_count, initial_message_count,
- folder.properties.email_total, primary_email_id_to_conversation.size);
+ if (get_email_count() != initial_message_count)
operation_queue.add(new FillWindowOperation(this, false));
- } else {
- debug("FILLWINDOW: Completed");
- }
}
}
diff --git a/src/engine/imap-db/imap-db-folder.vala b/src/engine/imap-db/imap-db-folder.vala
index 38499ae..87a80ce 100644
--- a/src/engine/imap-db/imap-db-folder.vala
+++ b/src/engine/imap-db/imap-db-folder.vala
@@ -317,10 +317,9 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
StringBuilder sql = new StringBuilder("""
SELECT MessageLocationTable.message_id, ordering, remove_marker
FROM MessageLocationTable
+ WHERE folder_id = ?
""");
- sql.append("WHERE folder_id = ? ");
-
if (oldest_to_newest)
sql.append("AND ordering >= ? ");
else
@@ -331,9 +330,14 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
else
sql.append("ORDER BY ordering DESC ");
+ if (count != int.MAX)
+ sql.append("LIMIT ? ");
+
Db.Statement stmt = cx.prepare(sql.str);
stmt.bind_rowid(0, folder_id);
stmt.bind_int64(1, start_uid.value);
+ if (count != int.MAX)
+ stmt.bind_int(2, count);
locations = do_results_to_locations(stmt.exec(cancellable), count, flags, cancellable);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]