[geary/wip/721828-undo] Further work



commit 5a45ac3c7c87ee39fe736f14e32ee4f3a9b54efd
Author: Jim Nelson <jim yorba org>
Date:   Wed Jan 7 12:24:31 2015 -0800

    Further work
    
    But it's a long way to go to make this work like we want it to.

 src/engine/imap-db/imap-db-folder.vala             |   21 +++++-
 .../imap-engine/imap-engine-minimal-folder.vala    |   65 +++++++++++++++++++-
 .../replay-ops/imap-engine-move-email.vala         |   18 +++++-
 3 files changed, 97 insertions(+), 7 deletions(-)
---
diff --git a/src/engine/imap-db/imap-db-folder.vala b/src/engine/imap-db/imap-db-folder.vala
index 178fba3..1f0935e 100644
--- a/src/engine/imap-db/imap-db-folder.vala
+++ b/src/engine/imap-db/imap-db-folder.vala
@@ -732,6 +732,7 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
         Cancellable? cancellable) throws Error {
         // store in hash set for closure, which potentially modifies the collection
         Gee.HashSet<ImapDB.EmailIdentifier> id_set = traverse<ImapDB.EmailIdentifier>(ids).to_hash_set();
+        debug("LINKING %d UIDs to %s", id_set.size, to_string());
         
         int unread_count = 0;
         yield db.exec_transaction_async(Db.TransactionType.RW, (cx) => {
@@ -740,7 +741,9 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
             Gee.Iterator<ImapDB.EmailIdentifier> iter = id_set.iterator();
             while (iter.next()) {
                 ImapDB.EmailIdentifier id = iter.get();
-                if (id.uid == null) {
+                if (!id.has_uid()) {
+                    debug("\nNO UID IN LINKED ID %s", id.to_string());
+                    
                     iter.remove();
                     
                     continue;
@@ -758,6 +761,8 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
                 
                 Db.Result result = stmt.exec(cancellable);
                 if (!result.finished) {
+                    debug("\nUID %s ALREADY LINKED TO %s", id.uid.to_string(), to_string());
+                    
                     // clear remove marker, if set
                     do_mark_unmark_removed(cx, iterate<Imap.UID>(id.uid).to_array_list(), false,
                         cancellable);
@@ -776,6 +781,8 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
                 stmt.bind_bool(3, false);
                 
                 stmt.exec(cancellable);
+                
+                debug("\n%s: LINKED %s", to_string(), id.uid.to_string());
             }
             
             // Now with messages linked to folder, update unread count with ids that were linked
@@ -989,8 +996,7 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
             properties.set_status_unseen(properties.email_unread - 1);
     }
     
-    // Mark messages as removed (but not expunged) from the folder.  Marked messages are skipped
-    // on most operations unless ListFlags.INCLUDE_MARKED_REMOVED is true.  Use detach_email_async()
+    // Mark messages as removed (but not expunged) from the folder.  Use unlink_email_async()
     // to formally remove the messages from the folder.
     //
     // Returns a collection of ImapDB.EmailIdentifiers *with the UIDs set* for this folder.
@@ -1003,8 +1009,12 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
         yield db.exec_transaction_async(Db.TransactionType.RW, (cx) => {
             Gee.List<LocationIdentifier?> locs = do_get_locations_for_ids(cx, ids,
                 ListFlags.INCLUDE_MARKED_FOR_REMOVE, cancellable);
-            if (locs == null || locs.size == 0)
+            if (locs == null || locs.size == 0) {
+                debug("\n%s: NO LOCATIONS RETURNED FOR %d IDS (%s)", to_string(), ids.size,
+                    traverse<ImapDB.EmailIdentifier>(ids).first().to_string());
+                
                 return Db.TransactionOutcome.DONE;
+            }
             
             unread_count = do_get_unread_count_for_ids(cx, ids, cancellable);
             
@@ -1195,6 +1205,9 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
             
             stmt.exec(cancellable);
             
+            debug("\n%s: MARKED REMOVED=%s: %s", to_string(), mark_removed.to_string(),
+                uid.to_string());
+            
             // keep folder_id and mark_removed, replace UID each iteration
             stmt.reset(Db.ResetScope.SAVE_BINDINGS);
         }
diff --git a/src/engine/imap-engine/imap-engine-minimal-folder.vala 
b/src/engine/imap-engine/imap-engine-minimal-folder.vala
index d2a3e7a..96fd55f 100644
--- a/src/engine/imap-engine/imap-engine-minimal-folder.vala
+++ b/src/engine/imap-engine/imap-engine-minimal-folder.vala
@@ -45,6 +45,7 @@ private class Geary.ImapEngine.MinimalFolder : Geary.AbstractFolder, Geary.Folde
     private int remote_count = -1;
     private uint open_remote_timer_id = 0;
     private int reestablish_delay_msec = DEFAULT_REESTABLISH_DELAY_MSEC;
+    private Gee.HashSet<ImapDB.EmailIdentifier> predicted_ids = new Gee.HashSet<ImapDB.EmailIdentifier>();
     
     public MinimalFolder(GenericAccount account, Imap.Account remote, ImapDB.Account local,
         ImapDB.Folder local_folder, SpecialFolderType special_folder_type) {
@@ -72,11 +73,71 @@ private class Geary.ImapEngine.MinimalFolder : Geary.AbstractFolder, Geary.Folde
         local_folder.email_complete.disconnect(on_email_complete);
     }
     
-    public override void notify_email_removed(Gee.Collection<Geary.EmailIdentifier> ids) {
-        // fire base signal first
+    internal override void notify_email_removed(Gee.Collection<Geary.EmailIdentifier> ids) {
+        predicted_ids_fulfilled(ids, false);
+        
         base.notify_email_removed(ids);
     }
     
+    internal override void notify_email_appended(Gee.Collection<Geary.EmailIdentifier> ids) {
+        predicted_ids_fulfilled(ids, true);
+        
+        base.notify_email_appended(ids);
+    }
+    
+    internal override void notify_email_locally_appended(Gee.Collection<Geary.EmailIdentifier> ids) {
+        predicted_ids_fulfilled(ids, true);
+        
+        base.notify_email_locally_appended(ids);
+    }
+    
+    internal override void notify_email_inserted(Gee.Collection<Geary.EmailIdentifier> ids) {
+        predicted_ids_fulfilled(ids, true);
+        
+        base.notify_email_inserted(ids);
+    }
+    
+    internal override void notify_email_locally_inserted(Gee.Collection<Geary.EmailIdentifier> ids) {
+        predicted_ids_fulfilled(ids, true);
+        
+        base.notify_email_locally_inserted(ids);
+    }
+    
+    internal override void notify_predict_email_inserted(Gee.Collection<Geary.EmailIdentifier> ids) {
+        // Add all predicted identifiers to an internal table, indicating no UID is available yet
+        predicted_ids.add_all(traverse<Geary.EmailIdentifier>(ids)
+            .cast_object<ImapDB.EmailIdentifier>()
+            .to_array_list()
+        );
+        
+        base.notify_predict_email_inserted(ids);
+    }
+    
+    internal override void notify_unpredict_email_inserted(Gee.Collection<Geary.EmailIdentifier> ids) {
+        predicted_ids_fulfilled(ids, false);
+        
+        base.notify_unpredict_email_inserted(ids);
+    }
+    
+    private void predicted_ids_fulfilled(Gee.Collection<Geary.EmailIdentifier> ids, bool arrived) {
+        Gee.ArrayList<ImapDB.EmailIdentifier> reported_ids = traverse<Geary.EmailIdentifier>(ids)
+            .cast_object<ImapDB.EmailIdentifier>()
+            .to_array_list();
+        
+        // only want to report identifiers still waiting on; all the signals that feed into this
+        // method may report the same identifier multiple times
+        Gee.Iterator<ImapDB.EmailIdentifier> iter = reported_ids.iterator();
+        while (iter.next()) {
+            if (predicted_ids.contains(iter.get())
+                predicted_ids.remove(iter.get());
+            else
+                iter.remove();
+            
+            if (!iter.get().has_uid())
+                debug("%s: NO UID ON REPORTED ID %s", to_string(), iter.get().to_string());
+        }
+    }
+    
     public void set_special_folder_type(SpecialFolderType new_type) {
         SpecialFolderType old_type = _special_folder_type;
         _special_folder_type = new_type;
diff --git a/src/engine/imap-engine/replay-ops/imap-engine-move-email.vala 
b/src/engine/imap-engine/replay-ops/imap-engine-move-email.vala
index 4a6c61b..71ba8b6 100644
--- a/src/engine/imap-engine/replay-ops/imap-engine-move-email.vala
+++ b/src/engine/imap-engine/replay-ops/imap-engine-move-email.vala
@@ -45,8 +45,15 @@ private class Geary.ImapEngine.MoveEmail : Geary.ImapEngine.SendReplayOperation
             original_count = to_move.size;
         
         moved_ids = yield engine.local_folder.mark_removed_async(to_move, true, cancellable);
-        if (moved_ids == null || moved_ids.size == 0)
+        if (moved_ids == null || moved_ids.size == 0) {
+            debug("\n%s: not moving %d emails to %s: not found (%s)", engine.to_string(),
+                to_move.size, destination.to_string(), to_move[0].to_string());
+            
             return ReplayOperation.Status.COMPLETED;
+        }
+        
+        debug("\n%s: MARKED %d AS REMOVED (%s)", engine.to_string(), moved_ids.size,
+            traverse<ImapDB.EmailIdentifier>(moved_ids).first().to_string());
         
         engine.notify_email_removed(moved_ids);
         
@@ -79,6 +86,11 @@ private class Geary.ImapEngine.MoveEmail : Geary.ImapEngine.SendReplayOperation
         if (moved_ids.size == 0)
             return ReplayOperation.Status.COMPLETED;
         
+        //
+        // TODO: Allow for cancelling move of destination predicted id's if they're moved or removed
+        // later?
+        //
+        
         // don't use Cancellable throughout I/O operations in order to assure transaction completes
         // fully
         if (cancellable != null && cancellable.is_cancelled())
@@ -106,6 +118,8 @@ private class Geary.ImapEngine.MoveEmail : Geary.ImapEngine.SendReplayOperation
                 while (iter.next()) {
                     Imap.UID source_uid = iter.get_key();
                     if (source_uid_to_source_id.has_key(source_uid)) {
+                        debug("\nMOVE: %s -> %s", source_uid.to_string(), iter.get_value().to_string());
+                        
                         ImapDB.EmailIdentifier source_id = source_uid_to_source_id[source_uid];
                         
                         acc_ids.add(new ImapDB.EmailIdentifier(source_id.message_id, iter.get_value()));
@@ -124,6 +138,8 @@ private class Geary.ImapEngine.MoveEmail : Geary.ImapEngine.SendReplayOperation
                     // Note that this doesn't require dest_folder be open because we're going straight
                     // to the database...dest_folder will announce to its subscribers changes when
                     // normalization/notification occurs via IMAP
+                    debug("\n\n%s: LINKING TO %s: %s", engine.local_folder.to_string(), 
dest_folder.to_string(),
+                        traverse<ImapDB.EmailIdentifier>(acc_ids).first().to_string());
                     yield dest_folder.local_folder.link_multiple_emails_async(acc_ids, null);
                     destination_ids = acc_ids;
                 } catch (Error err) {


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