Fixes problem Adam reported re: flag watcher failing

Problem was due to accumulation of messages marked for removal on
local side not being (eventually) removed from MessageLocationTable.
Can happen if folder is closed before EXPUNGE server data arrives,
or if Geary is shut down or crashes before same.  Folder
normalization will deal with situation where locally removed
message was not actually removed on server.
This commit is contained in:
Jim Nelson 2012-05-31 11:57:20 -07:00
parent e8c5fc2e10
commit 85bb2ae76a
3 changed files with 32 additions and 10 deletions

View file

@ -593,28 +593,23 @@ private class Geary.GenericImapFolder : Geary.AbstractFolder {
to_string(), err.message);
}
debug("do_replay_remove_message: remote_count=%d new_remote_count=%d local_count=%d remote_position=%d local_position=%d",
remote_count, new_remote_count, local_count, remote_position, local_position);
bool marked = false;
if (owned_id != null) {
debug("do_replay_remove_message: removing from local store Email ID %s", owned_id.to_string());
try {
// Reflect change in the local store and notify subscribers
yield local_folder.remove_marked_email_async(owned_id, out marked, null);
// TODO: Should move this signal to after the remote_count has changed
if (!marked)
notify_email_removed(new Geary.Singleton<Geary.EmailIdentifier>(owned_id));
} catch (Error err2) {
debug("Unable to remove message #%d from %s: %s", remote_position, to_string(),
err2.message);
}
} else {
debug("do_replay_remove_message: remote_position=%d unknown in local store (remote_count=%d new_remote_count=%d local_position=%d local_count=%d)",
debug("do_replay_remove_message: remote_position=%d unknown in local store "
+ "(remote_count=%d new_remote_count=%d local_position=%d local_count=%d)",
remote_position, remote_count, new_remote_count, local_position, local_count);
}
// for debugging
int new_local_count = -1;
try {
new_local_count = yield local_folder.get_email_count_async();
@ -626,11 +621,16 @@ private class Geary.GenericImapFolder : Geary.AbstractFolder {
bool changed = (remote_count != new_remote_count);
remote_count = new_remote_count;
if (!marked && owned_id != null)
notify_email_removed(new Geary.Singleton<Geary.EmailIdentifier>(owned_id));
if (!marked && changed)
notify_email_count_changed(remote_count, CountChangeReason.REMOVED);
debug("do_replay_remove_message: completed for %s (remote_count=%d local_count=%d new_local_count=%d marked=%s)",
to_string(), remote_count, local_count, new_local_count, marked.to_string());
debug("do_replay_remove_message: completed for %s "
+ "(remote_count=%d local_count=%d new_local_count=%d remote_position=%d local_position=%d marked=%s)",
to_string(), remote_count, local_count, new_local_count, remote_position, local_position,
marked.to_string());
}
private void on_remote_disconnected(Geary.Folder.CloseReason reason) {

View file

@ -73,6 +73,13 @@ private class Geary.Sqlite.Folder : Object, Geary.ReferenceSemantics {
throw new EngineError.ALREADY_OPEN("%s already open", to_string());
opened = true;
// Possible some messages were marked for removal in prior session and not properly deleted
// (for example, if the EXPUNGE message didn't come back before closing the folder, or
// the app is shut down or crashes) ... folder normalization will take care of messages that
// are still in folder even if they're marked here, so go ahead and remove them from the
// location table
yield location_table.remove_all_marked_for_remove(null, folder_row.id, cancellable);
}
public async void close_async(Cancellable? cancellable = null) throws Error {

View file

@ -353,5 +353,20 @@ public class Geary.Sqlite.MessageLocationTable : Geary.Sqlite.Table {
return (bool) results.fetch_int(0);
}
public async void remove_all_marked_for_remove(Transaction? transaction, int64 folder_id,
Cancellable? cancellable) throws Error {
Transaction locked = yield obtain_lock_async(transaction,
"MessageLocationTable.remove_all_marked_for_remove", cancellable);
SQLHeavy.Query query = locked.prepare(
"DELETE FROM MessageLocationTable WHERE folder_id=? AND remove_marker=1");
query.bind_int64(0, folder_id);
yield query.execute_async(cancellable);
locked.set_commit_required();
yield release_lock_async(transaction, locked, cancellable);
}
}