From a8b716fbaa87f617781565963ecd3594fe455475 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20J=2E=20Hern=C3=A1ndez=20Blasco?= Date: Wed, 19 Nov 2014 00:23:16 +0100 Subject: [PATCH] oc: sync old messages as last resort if there are not in cache This is happening when the lastModSeq is greater than the modseq from an old message and that message is not in cache. This is used as last resort before crashing and it is only used in objectVersion as it is the first place to call on sync. Other related properties would work. --- OpenChange/MAPIStoreMailFolder.h | 1 + OpenChange/MAPIStoreMailFolder.m | 64 +++++++++++++++++++++++++++++++ OpenChange/MAPIStoreMailMessage.m | 16 +++++++- 3 files changed, 79 insertions(+), 2 deletions(-) diff --git a/OpenChange/MAPIStoreMailFolder.h b/OpenChange/MAPIStoreMailFolder.h index 0a01476fe..2263f955b 100644 --- a/OpenChange/MAPIStoreMailFolder.h +++ b/OpenChange/MAPIStoreMailFolder.h @@ -46,6 +46,7 @@ - (BOOL) synchroniseCache; - (void) synchronizeUpdatedFolder: (NSNumber *) lastModseq withMapping: (NSMutableDictionary *) mapping; +- (BOOL) synchroniseCacheForUID: (NSString *) messageUID; - (NSNumber *) modseqFromMessageChangeNumber: (NSString *) changeNum; - (NSString *) messageUIDFromMessageKey: (NSString *) messageKey; - (NSString *) changeNumberForMessageUID: (NSString *) messageUid; diff --git a/OpenChange/MAPIStoreMailFolder.m b/OpenChange/MAPIStoreMailFolder.m index c9e168d81..2d4a20fbb 100644 --- a/OpenChange/MAPIStoreMailFolder.m +++ b/OpenChange/MAPIStoreMailFolder.m @@ -734,6 +734,70 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data) talloc_free(local_mem_ctx); } +- (BOOL) synchroniseCacheForUID: (NSString *) messageUID +{ + /* Try to synchronise old UIDs in versions.plist cache using an + specific UID. It returns a boolean indicating if the + synchronisation were done. + + It should be used as last resort, keeping synchroniseCache to main + sync entry point. + */ + NSMutableDictionary *currentProperties, *messages, *messageEntry, *mapping; + NSArray *fetchResults; + uint64_t changeNumber; + NSDictionary *result; + NSNumber *modseq; + NSString *changeNumberStr; + NSData *changeKey; + + [versionsMessage reloadIfNeeded]; + currentProperties = [versionsMessage properties]; + messages = [currentProperties objectForKey: @"Messages"]; + messageEntry = [messages objectForKey: messageUID]; + if (!messageEntry) + { + [messages removeObjectForKey: messageUID]; + changeNumber = [[self context] getNewChangeNumber]; + fetchResults = [(NSDictionary *) [sogoObject fetchUIDs: [NSArray arrayWithObject: messageUID] + parts: [NSArray arrayWithObject: @"modseq"]] + objectForKey: @"fetch"]; + if ([fetchResults count] == 1) + { + result = [fetchResults objectAtIndex: 0]; + modseq = [result objectForKey: @"modseq"]; + changeNumberStr = [NSString stringWithUnsignedLongLong: changeNumber]; + + /* Create new message entry in Messages dict */ + messageEntry = [NSMutableDictionary new]; + [messages setObject: messageEntry forKey: messageUID]; + [messageEntry release]; + + /* Store the modseq and change number */ + [messageEntry setObject: modseq forKey: @"modseq"]; + [messageEntry setObject: changeNumberStr forKey: @"version"]; + + /* Store the change key */ + changeKey = [self getReplicaKeyFromGlobCnt: changeNumber >> 16]; + [self _setChangeKey: changeKey forMessageEntry: messageEntry]; + + /* Store the changeNumber -> modseq mapping */ + mapping = [currentProperties objectForKey: @"VersionMapping"]; + [mapping setObject: modseq forKey: changeNumberStr]; + + /* Save the message */ + [versionsMessage save]; + return YES; + } + else + { + return NO; + } + } + /* If message entry exists, then synchroniseCache did its job */ + return YES; +} + - (NSNumber *) modseqFromMessageChangeNumber: (NSString *) changeNum { NSDictionary *mapping; diff --git a/OpenChange/MAPIStoreMailMessage.m b/OpenChange/MAPIStoreMailMessage.m index c64f60c22..f2ab615a1 100644 --- a/OpenChange/MAPIStoreMailMessage.m +++ b/OpenChange/MAPIStoreMailMessage.m @@ -369,6 +369,7 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data) { uint64_t version = ULLONG_MAX; NSString *uid, *changeNumber; + BOOL synced; uid = [(MAPIStoreMailFolder *) container messageUIDFromMessageKey: [self nameInContainer]]; @@ -387,8 +388,19 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data) [self logWithFormat: @"got one"]; else { - [self errorWithFormat: @"still nothing. We crash!"]; - abort(); + [self warnWithFormat: @"attempting to get change number" + @" by synchronising this specific message..."]; + synced = [(MAPIStoreMailFolder *) container synchroniseCacheForUID: uid]; + if (synced) + { + changeNumber = [(MAPIStoreMailFolder *) container + changeNumberForMessageUID: uid]; + } + else + { + [self errorWithFormat: @"still nothing. We crash!"]; + abort(); + } } } version = [changeNumber unsignedLongLongValue] >> 16;