am 66ac290b: Fix a bug causing duplicate messages to be added

* commit '66ac290b353302256e85d319c0ce623277dfdad3':
  Fix a bug causing duplicate messages to be added
This commit is contained in:
Martin Hibdon 2013-08-12 18:44:56 -07:00 committed by Android Git Automerger
commit b2947f4702

View File

@ -68,6 +68,8 @@ import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Set;
public class ImapService extends Service {
// TODO get these from configurations or settings.
@ -195,11 +197,12 @@ public class ImapService extends Service {
private static final int COLUMN_FLAG_LOADED = 3;
private static final int COLUMN_SERVER_ID = 4;
private static final int COLUMN_FLAGS = 7;
private static final int COLUMN_TIMESTAMP = 8;
private static final String[] PROJECTION = new String[] {
EmailContent.RECORD_ID,
MessageColumns.FLAG_READ, MessageColumns.FLAG_FAVORITE, MessageColumns.FLAG_LOADED,
SyncColumns.SERVER_ID, MessageColumns.MAILBOX_KEY, MessageColumns.ACCOUNT_KEY,
MessageColumns.FLAGS
MessageColumns.FLAGS, MessageColumns.TIMESTAMP
};
final long mId;
@ -208,6 +211,7 @@ public class ImapService extends Service {
final int mFlagLoaded;
final String mServerId;
final int mFlags;
final long mTimestamp;
public LocalMessageInfo(Cursor c) {
mId = c.getLong(COLUMN_ID);
@ -216,6 +220,7 @@ public class ImapService extends Service {
mFlagLoaded = c.getInt(COLUMN_FLAG_LOADED);
mServerId = c.getString(COLUMN_SERVER_ID);
mFlags = c.getInt(COLUMN_FLAGS);
mTimestamp = c.getLong(COLUMN_TIMESTAMP);
// Note: mailbox key and account key not needed - they are projected for the SELECT
}
}
@ -498,12 +503,20 @@ public class ImapService extends Service {
// 8. Get the all of the local messages within the sync window, and create
// an index of the uids.
// It's important that we only get local messages that are inside our sync window.
// In a later step, we will delete any messages that are in localMessageMap but
// are not in our remote message list.
// The IMAP query for messages ignores time, and only looks at the date part of the endDate.
// So if we query for messages since Aug 11 at 3:00 PM, we can get messages from any time
// on Aug 11. Our IMAP query results can include messages up to 24 hours older than endDate,
// or up to 25 hours older at a daylight savings transition.
// It is important that we have the Id of any local message that could potentially be
// returned by the IMAP query, or we will create duplicate copies of the same messages.
// So we will increase our local query range by this much.
// Note that this complicates deletion: It's not okay to delete anything that is in the
// localMessageMap but not in the remote result, because we know that we may be getting
// Ids of local messages that are outside the IMAP query window.
Cursor localUidCursor = null;
HashMap<String, LocalMessageInfo> localMessageMap = new HashMap<String, LocalMessageInfo>();
try {
final long queryEndDate = endDate - DateUtils.DAY_IN_MILLIS - DateUtils.HOUR_IN_MILLIS;
localUidCursor = resolver.query(
EmailContent.Message.CONTENT_URI,
LocalMessageInfo.PROJECTION,
@ -513,7 +526,7 @@ public class ImapService extends Service {
new String[] {
String.valueOf(account.mId),
String.valueOf(mailbox.mId),
String.valueOf(endDate) },
String.valueOf(queryEndDate) },
null);
while (localUidCursor.moveToNext()) {
LocalMessageInfo info = new LocalMessageInfo(localUidCursor);
@ -626,29 +639,30 @@ public class ImapService extends Service {
}
// 13. Remove messages that are in the local store and in the current sync window,
// but no longer on the remote store.
final HashSet<String> localUidsToDelete = new HashSet<String>(localMessageMap.keySet());
localUidsToDelete.removeAll(remoteUidMap.keySet());
// but no longer on the remote store. Note that localMessageMap can contain messages
// that are not actually in our sync window. We need to check the timestamp to ensure
// that it is before deleting.
for (final LocalMessageInfo info : localMessageMap.values()) {
// If this message is inside our sync window, and we cannot find it in our list
// of remote messages, then we know it's been deleted from the server.
if (info.mTimestamp >= endDate && !remoteUidMap.containsKey(info.mServerId)) {
// Delete associated data (attachment files)
// Attachment & Body records are auto-deleted when we delete the Message record
AttachmentUtilities.deleteAllAttachmentFiles(context, account.mId, info.mId);
for (String uidToDelete : localUidsToDelete) {
LocalMessageInfo infoToDelete = localMessageMap.get(uidToDelete);
// Delete the message itself
Uri uriToDelete = ContentUris.withAppendedId(
EmailContent.Message.CONTENT_URI, info.mId);
resolver.delete(uriToDelete, null, null);
// Delete associated data (attachment files)
// Attachment & Body records are auto-deleted when we delete the Message record
AttachmentUtilities.deleteAllAttachmentFiles(context, account.mId, infoToDelete.mId);
// Delete the message itself
Uri uriToDelete = ContentUris.withAppendedId(
EmailContent.Message.CONTENT_URI, infoToDelete.mId);
resolver.delete(uriToDelete, null, null);
// Delete extra rows (e.g. synced or deleted)
Uri syncRowToDelete = ContentUris.withAppendedId(
EmailContent.Message.UPDATED_CONTENT_URI, infoToDelete.mId);
resolver.delete(syncRowToDelete, null, null);
Uri deletERowToDelete = ContentUris.withAppendedId(
EmailContent.Message.UPDATED_CONTENT_URI, infoToDelete.mId);
resolver.delete(deletERowToDelete, null, null);
// Delete extra rows (e.g. synced or deleted)
Uri syncRowToDelete = ContentUris.withAppendedId(
EmailContent.Message.UPDATED_CONTENT_URI, info.mId);
resolver.delete(syncRowToDelete, null, null);
Uri deletERowToDelete = ContentUris.withAppendedId(
EmailContent.Message.UPDATED_CONTENT_URI, info.mId);
resolver.delete(deletERowToDelete, null, null);
}
}
loadUnsyncedMessages(context, account, remoteFolder, unsyncedMessages, mailbox);