diff --git a/ChangeLog b/ChangeLog index beb35e44e..a1ac00e99 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,11 +1,21 @@ 2011-08-12 Wolfgang Sourdeau + * SoObjects/Mailer/SOGoMailFolder.m + (-prefetchCoreInfosForMessageKeys:): new method that enables the + prefetching and caching of "core infos" for messages. + (-lookupName:inContext:acquire:): looked up messages are now fed + with their cached core infos, if present. + * SoObjects/Mailer/SOGoMailObject.m: (addFlags:, removeFlags:) release "coreInfos" rather than flagsCache, which has been obsoleted. (_hasFlag:): make use of "coreInfos" to fetch the flags since most of the time the other infos will be fetch for the same object, bringing a 30ms speedup per message. + (-setCoreInfos): new accessor that enables setting coreInfos from + an external object. + (+initialize): coreInfoKeys was renamed to SOGoMailCoreInfoKeys + and has now been published. * OpenChange/MAPIStoreTable.m (-setHandleId:): only register the table in the notification cache if the provided handle id is not diff --git a/SoObjects/Mailer/SOGoMailFolder.h b/SoObjects/Mailer/SOGoMailFolder.h index 4fb2cac76..798e69163 100644 --- a/SoObjects/Mailer/SOGoMailFolder.h +++ b/SoObjects/Mailer/SOGoMailFolder.h @@ -35,7 +35,7 @@ The SOGoMailFolder maps to an IMAP4 folder from NGImap4. */ -@class NSData, NSArray, NSException, NSMutableArray; +@class NSData, NSArray, NSException, NSMutableArray, NSMutableDictionary; @class NGImap4MailboxInfo; @class WOResponse; @@ -44,11 +44,14 @@ NSMutableArray *filenames; NSString *folderType; NSDictionary *mailboxACL; + NSMutableDictionary *prefetchedInfos; } - (NSString *) absoluteImap4Name; /* messages */ +- (void) prefetchCoreInfosForMessageKeys: (NSArray *) keys; + - (NSArray *) toOneRelationshipKeys; - (NSArray *) toManyRelationshipKeys; diff --git a/SoObjects/Mailer/SOGoMailFolder.m b/SoObjects/Mailer/SOGoMailFolder.m index 5dd8568f3..08fe06e61 100644 --- a/SoObjects/Mailer/SOGoMailFolder.m +++ b/SoObjects/Mailer/SOGoMailFolder.m @@ -46,6 +46,7 @@ #import #import +#import #import #import #import @@ -123,6 +124,7 @@ static NSString *defaultUserID = @"anyone"; { [self _adjustOwner]; mailboxACL = nil; + prefetchedInfos = nil; } return self; @@ -133,6 +135,7 @@ static NSString *defaultUserID = @"anyone"; [filenames release]; [folderType release]; [mailboxACL release]; + [prefetchedInfos release]; [super dealloc]; } @@ -265,6 +268,43 @@ static NSString *defaultUserID = @"anyone"; } /* messages */ +- (void) prefetchCoreInfosForMessageKeys: (NSArray *) keys +{ + NSDictionary *infos; + NSMutableArray *uids; + NSUInteger count, max, keyLength; + NSString *key; + + if (!SOGoMailCoreInfoKeys) + { + /* ensure SOGoMailCoreInfoKeys is initialized */ + [SOGoMailObject class]; + } + + [prefetchedInfos release]; + + max = [keys count]; + if (max > 0) + { + uids = [NSMutableArray arrayWithCapacity: max]; + for (count = 0; count < max; count++) + { + key = [keys objectAtIndex: count]; + if ([key hasSuffix: @".eml"]) + { + keyLength = [key length]; + [uids addObject: [key substringToIndex: keyLength - 4]]; + } + } + infos = (NSDictionary *) [self fetchUIDs: uids parts: SOGoMailCoreInfoKeys]; + + prefetchedInfos = [[NSMutableDictionary alloc] initWithCapacity: max]; + [prefetchedInfos setObjects: [infos objectForKey: @"fetch"] + forKeys: uids]; + } + else + prefetchedInfos = nil; +} - (NSException *) deleteUIDs: (NSArray *) uids useTrashFolder: (BOOL *) withTrash @@ -700,7 +740,7 @@ static NSString *defaultUserID = @"anyone"; inContext: (id)_ctx acquire: (BOOL) _acquire { - NSString *folderName, *fullFolderName, *className; + NSString *folderName, *fullFolderName, *className, *uid; SOGoMailAccount *mailAccount; id obj; @@ -736,7 +776,11 @@ static NSString *defaultUserID = @"anyone"; } else if (isdigit ([_key characterAtIndex: 0]) && [[self imap4Connection] doesMailboxExistAtURL: [self imap4URL]]) - obj = [SOGoMailObject objectWithName: _key inContainer: self]; + { + obj = [SOGoMailObject objectWithName: _key inContainer: self]; + uid = [_key substringToIndex: [_key length] - 4]; + [obj setCoreInfos: [prefetchedInfos objectForKey: uid]]; + } } if (!obj && _acquire) diff --git a/SoObjects/Mailer/SOGoMailObject.h b/SoObjects/Mailer/SOGoMailObject.h index 148d8cf85..34ed172de 100644 --- a/SoObjects/Mailer/SOGoMailObject.h +++ b/SoObjects/Mailer/SOGoMailObject.h @@ -48,6 +48,8 @@ @class NGImap4Envelope; @class NGImap4EnvelopeAddress; +NSArray *SOGoMailCoreInfoKeys; + @interface SOGoMailObject : SOGoMailBaseObject { id coreInfos; @@ -63,6 +65,7 @@ - (BOOL) doesMailExist; - (id) fetchCoreInfos; // TODO: what does it do? +- (void) setCoreInfos: (NSDictionary *) newCoreInfos; - (NGImap4Envelope *) envelope; - (NSString *) subject; diff --git a/SoObjects/Mailer/SOGoMailObject.m b/SoObjects/Mailer/SOGoMailObject.m index 6dcda1741..8faf74c47 100644 --- a/SoObjects/Mailer/SOGoMailObject.m +++ b/SoObjects/Mailer/SOGoMailObject.m @@ -62,7 +62,7 @@ @implementation SOGoMailObject -static NSArray *coreInfoKeys = nil; +NSArray *SOGoMailCoreInfoKeys = nil; static NSString *mailETag = nil; static BOOL heavyDebug = NO; static BOOL debugOn = NO; @@ -71,15 +71,16 @@ static BOOL debugSoParts = NO; + (void) initialize { - if (!coreInfoKeys) + if (!SOGoMailCoreInfoKeys) { /* Note: see SOGoMailManager.m for allowed IMAP4 keys */ - coreInfoKeys = [[NSArray alloc] initWithObjects: - @"FLAGS", @"ENVELOPE", @"BODYSTRUCTURE", - @"RFC822.SIZE", - @"RFC822.HEADER", - // not yet supported: @"INTERNALDATE", - nil]; + SOGoMailCoreInfoKeys + = [[NSArray alloc] initWithObjects: + @"FLAGS", @"ENVELOPE", @"BODYSTRUCTURE", + @"RFC822.SIZE", + @"RFC822.HEADER", + // not yet supported: @"INTERNALDATE", + nil]; /* The following disabled code should not be needed, except if we use annotations (see davEntityTag below) */ @@ -219,7 +220,7 @@ static BOOL debugSoParts = NO; if (!coreInfos) { - msgs = [self fetchParts: coreInfoKeys]; // returns dict + msgs = [self fetchParts: SOGoMailCoreInfoKeys]; // returns dict if (heavyDebug) [self logWithFormat: @"M: %@", msgs]; msgs = [msgs valueForKey: @"fetch"]; @@ -231,6 +232,11 @@ static BOOL debugSoParts = NO; return coreInfos; } +- (void) setCoreInfos: (NSDictionary *) newCoreInfos +{ + ASSIGN (coreInfos, newCoreInfos); +} + - (id) bodyStructure { id body;