Use NSString instances as keys rather than NSNumber, to work around a performance issue with GNUstep < 1.24

maint-2.0.2
Wolfgang Sourdeau 2012-10-09 16:39:24 -04:00
parent c9dad4cab6
commit 5b7cbb6350
3 changed files with 52 additions and 56 deletions

View File

@ -44,9 +44,9 @@
/* synchronisation & versioning */ /* synchronisation & versioning */
- (BOOL) synchroniseCache; - (BOOL) synchroniseCache;
- (NSNumber *) modseqFromMessageChangeNumber: (NSNumber *) changeNum; - (NSNumber *) modseqFromMessageChangeNumber: (NSString *) changeNum;
- (NSNumber *) messageUIDFromMessageKey: (NSString *) messageKey; - (NSString *) messageUIDFromMessageKey: (NSString *) messageKey;
- (NSNumber *) changeNumberForMessageUID: (NSNumber *) messageUid; - (NSString *) changeNumberForMessageUID: (NSString *) messageUid;
- (void) setChangeKey: (NSData *) changeKey - (void) setChangeKey: (NSData *) changeKey
forMessageWithKey: (NSString *) messageKey; forMessageWithKey: (NSString *) messageKey;
- (NSData *) changeKeyForMessageWithKey: (NSString *) messageKey; - (NSData *) changeKeyForMessageWithKey: (NSString *) messageKey;

View File

@ -32,6 +32,7 @@
#import <EOControl/EOQualifier.h> #import <EOControl/EOQualifier.h>
#import <EOControl/EOSortOrdering.h> #import <EOControl/EOSortOrdering.h>
#import <NGExtensions/NSObject+Logs.h> #import <NGExtensions/NSObject+Logs.h>
#import <NGExtensions/NSObject+Values.h>
#import <NGExtensions/NSString+misc.h> #import <NGExtensions/NSString+misc.h>
#import <NGImap4/NGImap4Connection.h> #import <NGImap4/NGImap4Connection.h>
#import <NGImap4/NGImap4Client.h> #import <NGImap4/NGImap4Client.h>
@ -507,8 +508,9 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
{ {
BOOL rc = YES; BOOL rc = YES;
uint64_t newChangeNum; uint64_t newChangeNum;
NSNumber *ti, *changeNumber, *modseq, *initialLastModseq, *lastModseq, NSNumber *ti, *modseq, *initialLastModseq, *lastModseq,
*nextModseq, *uid; *nextModseq;
NSString *changeNumber, *uid;
uint64_t lastModseqNbr; uint64_t lastModseqNbr;
EOQualifier *kvQualifier, *searchQualifier; EOQualifier *kvQualifier, *searchQualifier;
NSArray *uids; NSArray *uids;
@ -520,6 +522,10 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
NSCalendarDate *now; NSCalendarDate *now;
BOOL foundChange = NO; BOOL foundChange = NO;
/* NOTE: we are using NSString instance for "uid" and "changeNumber" because
NSNumber proved to give very bad performances when used as NSDictionary
keys with GNUstep 1.22.1. The bug seems to be solved with 1.24 but many
distros still ship an older version. */
now = [NSCalendarDate date]; now = [NSCalendarDate date];
[now setTimeZone: utcTZ]; [now setTimeZone: utcTZ];
@ -584,10 +590,10 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
for (count = 0; count < max; count++) for (count = 0; count < max; count++)
{ {
result = [fetchResults objectAtIndex: count]; result = [fetchResults objectAtIndex: count];
uid = [result objectForKey: @"uid"]; uid = [[result objectForKey: @"uid"] stringValue];
modseq = [result objectForKey: @"modseq"]; modseq = [result objectForKey: @"modseq"];
newChangeNum = [[self context] getNewChangeNumber]; newChangeNum = [[self context] getNewChangeNumber];
changeNumber = [NSNumber numberWithUnsignedLongLong: newChangeNum]; changeNumber = [NSString stringWithUnsignedLongLong: newChangeNum];
messageEntry = [NSMutableDictionary new]; messageEntry = [NSMutableDictionary new];
[messages setObject: messageEntry forKey: uid]; [messages setObject: messageEntry forKey: uid];
@ -627,7 +633,7 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
if ([messages objectForKey: uid]) if ([messages objectForKey: uid])
{ {
newChangeNum = [[self context] getNewChangeNumber]; newChangeNum = [[self context] getNewChangeNumber];
changeNumber = [NSNumber numberWithUnsignedLongLong: newChangeNum]; changeNumber = [NSString stringWithUnsignedLongLong: newChangeNum];
[messages removeObjectForKey: uid]; [messages removeObjectForKey: uid];
[self logWithFormat: @"removed message entry for uid %@", uid]; [self logWithFormat: @"removed message entry for uid %@", uid];
} }
@ -651,7 +657,7 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
return rc; return rc;
} }
- (NSNumber *) modseqFromMessageChangeNumber: (NSNumber *) changeNum - (NSNumber *) modseqFromMessageChangeNumber: (NSString *) changeNum
{ {
NSDictionary *mapping; NSDictionary *mapping;
NSNumber *modseq; NSNumber *modseq;
@ -662,28 +668,24 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
return modseq; return modseq;
} }
- (NSNumber *) messageUIDFromMessageKey: (NSString *) messageKey - (NSString *) messageUIDFromMessageKey: (NSString *) messageKey
{ {
NSNumber *messageUid; NSString *messageUid;
NSString *uidString;
NSRange dotRange; NSRange dotRange;
dotRange = [messageKey rangeOfString: @".eml"]; dotRange = [messageKey rangeOfString: @".eml"];
if (dotRange.location != NSNotFound) if (dotRange.location != NSNotFound)
{ messageUid = [messageKey substringToIndex: dotRange.location];
uidString = [messageKey substringToIndex: dotRange.location];
messageUid = [NSNumber numberWithInt: [uidString intValue]];
}
else else
messageUid = nil; messageUid = nil;
return messageUid; return messageUid;
} }
- (NSNumber *) changeNumberForMessageUID: (NSNumber *) messageUid - (NSString *) changeNumberForMessageUID: (NSString *) messageUid
{ {
NSDictionary *messages; NSDictionary *messages;
NSNumber *changeNumber; NSString *changeNumber;
messages = [[versionsMessage properties] objectForKey: @"Messages"]; messages = [[versionsMessage properties] objectForKey: @"Messages"];
changeNumber = [[messages objectForKey: messageUid] changeNumber = [[messages objectForKey: messageUid]
@ -695,9 +697,8 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
- (void) setChangeKey: (NSData *) changeKey - (void) setChangeKey: (NSData *) changeKey
forMessageWithKey: (NSString *) messageKey forMessageWithKey: (NSString *) messageKey
{ {
NSMutableDictionary *messages; NSMutableDictionary *messages, *messageEntry;
NSMutableDictionary *messageEntry; NSString *messageUid;
NSNumber *messageUid;
messageUid = [self messageUIDFromMessageKey: messageKey]; messageUid = [self messageUIDFromMessageKey: messageKey];
messages = [[versionsMessage properties] objectForKey: @"Messages"]; messages = [[versionsMessage properties] objectForKey: @"Messages"];
@ -712,8 +713,7 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
- (NSData *) changeKeyForMessageWithKey: (NSString *) messageKey - (NSData *) changeKeyForMessageWithKey: (NSString *) messageKey
{ {
NSDictionary *messages, *changeKeyDict; NSDictionary *messages, *changeKeyDict;
NSString *guid; NSString *guid, *messageUid;
NSNumber *messageUid;
NSData *globCnt, *changeKey = nil; NSData *globCnt, *changeKey = nil;
messageUid = [self messageUIDFromMessageKey: messageKey]; messageUid = [self messageUIDFromMessageKey: messageKey];
@ -738,8 +738,7 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
NSMutableArray *changeKeys; NSMutableArray *changeKeys;
NSUInteger count, max; NSUInteger count, max;
NSData *changeKey; NSData *changeKey;
NSString *guid; NSString *guid, *messageUid;
NSNumber *messageUid;
NSData *globCnt; NSData *globCnt;
messageUid = [self messageUIDFromMessageKey: messageKey]; messageUid = [self messageUIDFromMessageKey: messageKey];
@ -779,26 +778,27 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
inTableType: (uint8_t) tableType inTableType: (uint8_t) tableType
{ {
NSArray *deletedKeys, *deletedUIDs; NSArray *deletedKeys, *deletedUIDs;
NSNumber *changeNumber; NSString *changeNumber;
uint64_t modseq; uint64_t modseq;
NSDictionary *versionProperties; NSDictionary *versionProperties;
if (tableType == MAPISTORE_MESSAGE_TABLE) if (tableType == MAPISTORE_MESSAGE_TABLE)
{ {
changeNumber = [NSNumber numberWithUnsignedLongLong: changeNum]; changeNumber = [NSString stringWithUnsignedLongLong: changeNum];
modseq = [[self modseqFromMessageChangeNumber: changeNumber] modseq = [[self modseqFromMessageChangeNumber: changeNumber]
unsignedLongLongValue]; unsignedLongLongValue];
if (modseq > 0) if (modseq > 0)
{ {
deletedUIDs = [(SOGoMailFolder *) sogoObject deletedUIDs = [(SOGoMailFolder *) sogoObject
fetchUIDsOfVanishedItems: modseq]; fetchUIDsOfVanishedItems: modseq];
deletedKeys = [deletedUIDs stringsWithFormat: @"%@.eml"]; deletedKeys = [deletedUIDs stringsWithFormat: @"%@.eml"];
if ([deletedUIDs count] > 0) if ([deletedUIDs count] > 0)
{ {
versionProperties = [versionsMessage properties]; versionProperties = [versionsMessage properties];
changeNumber = [versionProperties changeNumber = [versionProperties
objectForKey: @"SyncLastDeleteChangeNumber"]; objectForKey: @"SyncLastDeleteChangeNumber"];
*cnNbr = changeNumber; *cnNbr = [NSNumber numberWithUnsignedLongLong:
[changeNumber unsignedLongLongValue]];
[versionsMessage save]; [versionsMessage save];
} }
} }
@ -920,9 +920,9 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
{ {
NGImap4Connection *connection; NGImap4Connection *connection;
NGImap4Client *client; NGImap4Client *client;
NSString *sourceFolderName, *targetFolderName, *messageURL, *messageKey, *v; NSString *sourceFolderName, *targetFolderName, *messageURL, *messageKey,
*uid, *v;
NSMutableArray *uids, *oldMessageURLs; NSMutableArray *uids, *oldMessageURLs;
NSNumber *uid;
NSArray *destUIDs; NSArray *destUIDs;
MAPIStoreMapping *mapping; MAPIStoreMapping *mapping;
NSDictionary *result; NSDictionary *result;
@ -1169,13 +1169,11 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
{ {
MAPIStoreMailMessage *message; MAPIStoreMailMessage *message;
NSData *rawBodyData; NSData *rawBodyData;
NSNumber *messageUID;
message = [super lookupMessage: messageKey]; message = [super lookupMessage: messageKey];
if (message) if (message)
{ {
messageUID = [self messageUIDFromMessageKey: messageKey]; rawBodyData = [bodyData objectForKey: messageKey];
rawBodyData = [bodyData objectForKey: messageUID];
if (rawBodyData) if (rawBodyData)
[message setBodyContentFromRawData: rawBodyData]; [message setBodyContentFromRawData: rawBodyData];
} }
@ -1248,8 +1246,7 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
NSMutableDictionary *keyAssoc; NSMutableDictionary *keyAssoc;
NSDictionary *response; NSDictionary *response;
NSUInteger count, max; NSUInteger count, max;
NSString *messageKey, *bodyPartKey; NSString *messageKey, *messageUid, *bodyPartKey;
NSNumber *messageUID;
NGImap4Client *client; NGImap4Client *client;
NSArray *fetch; NSArray *fetch;
NSData *bodyContent; NSData *bodyContent;
@ -1265,16 +1262,13 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
for (count = 0; count < max; count++) for (count = 0; count < max; count++)
{ {
messageKey = [keys objectAtIndex: count]; messageKey = [keys objectAtIndex: count];
messageUID = [self messageUIDFromMessageKey: messageKey]; message = [self lookupMessage: messageKey];
if (messageUID) if (message)
{ {
message = [self lookupMessage: messageKey]; bodyPartKey = [message bodyContentPartKey];
if (message) [bodyPartKeys addObject: bodyPartKey];
{ messageUid = [self messageUIDFromMessageKey: messageKey];
bodyPartKey = [message bodyContentPartKey]; [keyAssoc setObject: bodyPartKey forKey: messageUid];
[bodyPartKeys addObject: bodyPartKey];
[keyAssoc setObject: bodyPartKey forKey: messageUID];
}
} }
} }
@ -1287,16 +1281,17 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
for (count = 0; count < max; count++) for (count = 0; count < max; count++)
{ {
response = [fetch objectAtIndex: count]; response = [fetch objectAtIndex: count];
messageUID = [response objectForKey: @"uid"]; messageUid = [[response objectForKey: @"uid"] stringValue];
if (messageUID) bodyPartKey = [keyAssoc objectForKey: messageUid];
if (bodyPartKey)
{ {
bodyPartKey = [keyAssoc objectForKey: messageUID]; bodyContent = [[response objectForKey: bodyPartKey]
if (bodyPartKey) objectForKey: @"data"];
if (bodyContent)
{ {
bodyContent = [[response objectForKey: bodyPartKey] messageKey = [NSString stringWithFormat: @"%@.eml",
objectForKey: @"data"]; messageUid];
if (bodyContent) [bodyData setObject: bodyContent forKey: messageKey];
[bodyData setObject: bodyContent forKey: messageUID];
} }
} }
} }

View File

@ -26,6 +26,7 @@
#import <Foundation/NSDictionary.h> #import <Foundation/NSDictionary.h>
#import <Foundation/NSException.h> #import <Foundation/NSException.h>
#import <NGExtensions/NSObject+Logs.h> #import <NGExtensions/NSObject+Logs.h>
#import <NGExtensions/NSObject+Values.h>
#import <NGImap4/NGImap4Client.h> #import <NGImap4/NGImap4Client.h>
#import <NGImap4/NGImap4Connection.h> #import <NGImap4/NGImap4Connection.h>
#import <NGImap4/NGImap4EnvelopeAddress.h> #import <NGImap4/NGImap4EnvelopeAddress.h>
@ -366,21 +367,21 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
- (uint64_t) objectVersion - (uint64_t) objectVersion
{ {
uint64_t version = ULLONG_MAX; uint64_t version = ULLONG_MAX;
NSNumber *uid, *changeNumber; NSString *uid, *changeNumber;
uid = [(MAPIStoreMailFolder *) uid = [(MAPIStoreMailFolder *)
container messageUIDFromMessageKey: [self nameInContainer]]; container messageUIDFromMessageKey: [self nameInContainer]];
if (uid) if (uid)
{ {
changeNumber = [(MAPIStoreMailFolder *) container changeNumber = [(MAPIStoreMailFolder *) container
changeNumberForMessageUID: uid]; changeNumberForMessageUID: uid];
if (!changeNumber) if (!changeNumber)
{ {
[self warnWithFormat: @"attempting to get change number" [self warnWithFormat: @"attempting to get change number"
@" by synchronising folder..."]; @" by synchronising folder..."];
[(MAPIStoreMailFolder *) container synchroniseCache]; [(MAPIStoreMailFolder *) container synchroniseCache];
changeNumber = [(MAPIStoreMailFolder *) container changeNumber = [(MAPIStoreMailFolder *) container
changeNumberForMessageUID: uid]; changeNumberForMessageUID: uid];
if (changeNumber) if (changeNumber)
[self logWithFormat: @"got one"]; [self logWithFormat: @"got one"];
else else