[geary/wip/726368-uids] If local UIDs are out of the remote's UIDNEXT range, detach all



commit 522c36c76ba711abddaa7981434ca0b43db82cbc
Author: Jim Nelson <jim yorba org>
Date:   Fri Mar 14 12:35:09 2014 -0700

    If local UIDs are out of the remote's UIDNEXT range, detach all
    
    Normal use of the folder will recreate the UIDs.

 src/engine/imap-db/imap-db-folder.vala             |    6 ---
 .../imap-engine/imap-engine-minimal-folder.vala    |   37 +++++++++++++++++---
 src/engine/imap/command/imap-message-set.vala      |    7 ++++
 3 files changed, 39 insertions(+), 11 deletions(-)
---
diff --git a/src/engine/imap-db/imap-db-folder.vala b/src/engine/imap-db/imap-db-folder.vala
index 44a0769..ad4c08f 100644
--- a/src/engine/imap-db/imap-db-folder.vala
+++ b/src/engine/imap-db/imap-db-folder.vala
@@ -746,12 +746,6 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
             
             stmt.exec(cancellable);
             
-            Db.Statement update_stmt = cx.prepare(
-                "UPDATE FolderTable SET unread_count = 0 WHERE id=?");
-            update_stmt.bind_rowid(0, folder_id);
-            
-            update_stmt.exec(cancellable);
-            
             return Db.TransactionOutcome.COMMIT;
         }, cancellable);
     }
diff --git a/src/engine/imap-engine/imap-engine-minimal-folder.vala 
b/src/engine/imap-engine/imap-engine-minimal-folder.vala
index 45c1aa1..70caa6f 100644
--- a/src/engine/imap-engine/imap-engine-minimal-folder.vala
+++ b/src/engine/imap-engine/imap-engine-minimal-folder.vala
@@ -103,6 +103,21 @@ private class Geary.ImapEngine.MinimalFolder : Geary.AbstractFolder, Geary.Folde
         return (remote_count >= 0) ? remote_count : last_seen_remote_count;
     }
     
+    // used by normalize_folders() during the normalization process; should not be used elsewhere
+    private async void detach_all_emails_async(Cancellable? cancellable) throws Error {
+        Gee.List<Email>? all = yield local_folder.list_email_by_id_async(null, -1,
+            Geary.Email.Field.NONE, ImapDB.Folder.ListFlags.NONE, cancellable);
+        
+        yield local_folder.detach_all_emails_async(cancellable);
+        
+        if (all != null && all.size > 0) {
+            Gee.List<EmailIdentifier> ids =
+                traverse<Email>(all).map<EmailIdentifier>((email) => email.id).to_array_list();
+            notify_email_removed(ids);
+            notify_email_count_changed(0, Folder.CountChangeReason.REMOVED);
+        }
+    }
+    
     private async bool normalize_folders(Geary.Imap.Folder remote_folder, Geary.Folder.OpenFlags open_flags,
         Cancellable? cancellable) throws Error {
         debug("%s: Begin normalizing remote and local folders", to_string());
@@ -139,7 +154,7 @@ private class Geary.ImapEngine.MinimalFolder : Geary.AbstractFolder, Geary.Folde
                 local_properties.uid_validity.value.to_string(),
                 remote_properties.uid_validity.value.to_string());
             
-            yield local_folder.detach_all_emails_async(cancellable);
+            yield detach_all_emails_async(cancellable);
             
             return true;
         }
@@ -184,6 +199,22 @@ private class Geary.ImapEngine.MinimalFolder : Geary.AbstractFolder, Geary.Folde
         if (is_dirty)
             debug("%s: %d remove markers found, folder is dirty", to_string(), already_marked_ids.size);
         
+        // a full normalize works from the highest possible UID on the remote and work down to the lowest 
UID on
+        // the local; this covers all messages appended since last seen as well as any removed
+        Imap.UID last_uid = remote_properties.uid_next.previous(true);
+        
+        // if either local UID is out of range of the current highest UID, then something very wrong
+        // has occurred; the only recourse is to wipe all associations and start over
+        if (local_earliest_id.uid.compare_to(last_uid) > 0 || local_latest_id.uid.compare_to(last_uid) > 0) {
+            debug("%s: Local UID(s) higher than remote UIDNEXT, detaching all email: %s/%s remote=%s",
+                to_string(), local_earliest_id.uid.to_string(), local_latest_id.uid.to_string(),
+                last_uid.to_string());
+            
+            yield detach_all_emails_async(cancellable);
+            
+            return true;
+        }
+        
         // if UIDNEXT has changed, that indicates messages have been appended (and possibly removed)
         int64 uidnext_diff = remote_properties.uid_next.value - local_properties.uid_next.value;
         
@@ -200,10 +231,6 @@ private class Geary.ImapEngine.MinimalFolder : Geary.AbstractFolder, Geary.Folde
             return true;
         }
         
-        // a full normalize works from the highest possible UID on the remote and work down to the lowest 
UID on
-        // the local; this covers all messages appended since last seen as well as any removed
-        Imap.UID last_uid = remote_properties.uid_next.previous(true);
-        
         // if the difference in UIDNEXT values equals the difference in message count, then only
         // an append could have happened, so only pull in the new messages ... note that this is not 
foolproof,
         // as UIDs are not guaranteed to increase by 1; however, this is a standard implementation practice,
diff --git a/src/engine/imap/command/imap-message-set.vala b/src/engine/imap/command/imap-message-set.vala
index 88129b2..9dc7f38 100644
--- a/src/engine/imap/command/imap-message-set.vala
+++ b/src/engine/imap/command/imap-message-set.vala
@@ -67,6 +67,13 @@ public class Geary.Imap.MessageSet : BaseObject {
         assert(low.value > 0);
         assert(high.value > 0);
         
+        // corrent ordering
+        if (low.value > high.value) {
+            UID swap = low;
+            low = high;
+            high = swap;
+        }
+        
         if (low.equal_to(high))
             value = low.serialize();
         else


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]