Fixed race condition when syncing huge amount of deleted messages using AS

pull/20/head
Ludovic Marcotte 2014-03-06 14:16:08 -05:00
parent 0cea36df2e
commit 31ace947cb
3 changed files with 62 additions and 30 deletions

View File

@ -571,24 +571,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
case ActiveSyncMailFolder:
default:
{
NSMutableArray *addedOrChangedMessages;
SOGoMailObject *mailObject;
NSString *uid, *command;
NSDictionary *aMessage;
NSArray *allMessages;
int deleted_count;
allMessages = [theCollection syncTokenFieldsWithProperties: nil matchingSyncToken: theSyncKey fromDate: theFilterType];
addedOrChangedMessages = [NSMutableArray array];
deleted_count = 0;
// Check for the WindowSize.
// FIXME: we should eventually check for modseq and slice the maximum
// amount of messages returned to ensure we don't have the same
// modseq accross contiguous boundaries
max = [allMessages count];
if (max > theWindowSize)
{
max = theWindowSize;
more_available = YES;
}
// We first check the number of deleted messages we have
// We do NOT honor the window size here as it seems to be
// impossible to get the modseq of an expunged message so
// we can't iterate in the list of deleted messages.
for (i = 0; i < max; i++)
{
aMessage = [allMessages objectAtIndex: i];
@ -601,31 +604,53 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[s appendString: @"<Delete xmlns=\"AirSync:\">"];
[s appendFormat: @"<ServerId xmlns=\"AirSync:\">%@</ServerId>", uid];
[s appendString: @"</Delete>"];
deleted_count++;
}
else
{
if ([command isEqualToString: @"added"])
[s appendString: @"<Add xmlns=\"AirSync:\">"];
else
[s appendString: @"<Change xmlns=\"AirSync:\">"];
mailObject = [theCollection lookupName: uid
inContext: context
acquire: 0];
[s appendFormat: @"<ServerId xmlns=\"AirSync:\">%@</ServerId>", uid];
[s appendString: @"<ApplicationData xmlns=\"AirSync:\">"];
[s appendString: [mailObject activeSyncRepresentationInContext: context]];
[s appendString: @"</ApplicationData>"];
if ([command isEqualToString: @"added"])
[s appendString: @"</Add>"];
else
[s appendString: @"</Change>"];
[addedOrChangedMessages addObject: aMessage];
}
}
// We then "pad" with our added/changed messages. We ALWAYS
// at least return one if available
max = [addedOrChangedMessages count];
for (i = 0; i < max; i++)
{
aMessage = [addedOrChangedMessages objectAtIndex: i];
uid = [[[aMessage allKeys] lastObject] stringValue];
command = [[aMessage allValues] lastObject];
if ([command isEqualToString: @"added"])
[s appendString: @"<Add xmlns=\"AirSync:\">"];
else
[s appendString: @"<Change xmlns=\"AirSync:\">"];
mailObject = [theCollection lookupName: uid
inContext: context
acquire: 0];
[s appendFormat: @"<ServerId xmlns=\"AirSync:\">%@</ServerId>", uid];
[s appendString: @"<ApplicationData xmlns=\"AirSync:\">"];
[s appendString: [mailObject activeSyncRepresentationInContext: context]];
[s appendString: @"</ApplicationData>"];
if ([command isEqualToString: @"added"])
[s appendString: @"</Add>"];
else
[s appendString: @"</Change>"];
// We check if we must stop padding
if (i+1+deleted_count > theWindowSize)
{
more_available = YES;
break;
}
}
//
if (more_available)
{

1
NEWS
View File

@ -14,6 +14,7 @@ Bug fixes
- fixed encoding of mail folder name when creating a subfolder (#2637)
- fixed returned date format for email messages in Active Sync
- fixed missing 'name part' in address for email messages in Active Sync
- fixed race condition when syncing huge amount of deleted messages over Active Sync
2.2.0 (2014-02-24)
------------------

View File

@ -1940,8 +1940,11 @@ static NSString *defaultUserID = @"anyone";
uid = [theId intValue];
result = [[imap4 client] fetchModseqForUid: uid];
modseq = [[[[result objectForKey: @"RawResponse"] objectForKey: @"fetch"] objectForKey: @"modseq"] intValue];
tag = [NSString stringWithFormat: @"%d-%d", uid, modseq-1];
if (modseq < 1)
modseq = 1;
tag = [NSString stringWithFormat: @"%d-%d", uid, modseq];
}
return tag;
@ -1999,7 +2002,7 @@ static NSString *defaultUserID = @"anyone";
// Check updated items
//
//
// . uid fetch 1:* (FLAGS) (changedsince 171)
// . uid fetch 1:* (UID) (changedsince 171)
//
// To get the modseq of a specific message:
//
@ -2101,11 +2104,14 @@ static NSString *defaultUserID = @"anyone";
// We fetch deleted ones
if (highestmodseq > 0)
{
id uid;
uids = [self fetchUIDsOfVanishedItems: highestmodseq];
for (i = 0; i < [uids count]; i++)
{
d = [NSDictionary dictionaryWithObject: @"deleted" forKey: [uids objectAtIndex: i]];
uid = [uids objectAtIndex: i];
d = [NSDictionary dictionaryWithObject: @"deleted" forKey: uid];
[allTokens addObject: d];
}
}