diff --git a/ChangeLog b/ChangeLog index 8d62d80a1..a53adaf2f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,25 @@ 2012-03-12 Wolfgang Sourdeau + * OpenChange/MAPIStoreGCSFolder.m (-componentQualifier): now + provided by the parent class itself. + (-contentComponentQualifier): new method that returns a qualifier + that translated to "c_content like '%BEGIN:XXX%'". This is a hack + to work-around the fact that calendar folders may content both + vevent and vtodo and that c_component, being part of the quick + table, is no longer available when a record is deleted. + (-synchroniseCache): update version values for deleted records + too, by taking into account the fact that their c_version value + might still be 0. Make use of contentComponentQualifier above. + Remove the modified records from the SOGoGCSFolder cache. + (-getDeletedKeysFromChangeNumber:andCN:inTableType:): wander the + list of deleted records and no longer increase the change number, + as this is now done from "synchroniseCache". Also, handle the case + were deleted records might already have been reported by comparing + their change number to the one provided as parameter. The + resulting change number is now guaranteed to be the highest one. + (-component): new subclassable method that returns a string + matching the folder's handled component. + * OpenChange/MAPIStoreFolder.m (-getPidTagLocalCommitTimeMax:inMemCtx:): returns MAPISTORE_ERR_NOT_FOUND if the resulting date is nil. diff --git a/OpenChange/MAPIStoreCalendarFolder.m b/OpenChange/MAPIStoreCalendarFolder.m index f2ec0a4dd..7b40d9735 100644 --- a/OpenChange/MAPIStoreCalendarFolder.m +++ b/OpenChange/MAPIStoreCalendarFolder.m @@ -49,17 +49,9 @@ return [MAPIStoreCalendarMessageTable tableForContainer: self]; } -- (EOQualifier *) componentQualifier +- (NSString *) component { - static EOQualifier *componentQualifier = nil; - - if (!componentQualifier) - componentQualifier - = [[EOKeyValueQualifier alloc] initWithKey: @"c_component" - operatorSelector: EOQualifierOperatorEqual - value: @"vevent"]; - - return componentQualifier; + return @"vevent"; } - (MAPIStoreMessage *) createMessage diff --git a/OpenChange/MAPIStoreContactsFolder.m b/OpenChange/MAPIStoreContactsFolder.m index 6485a3af8..49c26df90 100644 --- a/OpenChange/MAPIStoreContactsFolder.m +++ b/OpenChange/MAPIStoreContactsFolder.m @@ -45,18 +45,9 @@ return [MAPIStoreContactsMessageTable tableForContainer: self]; } -- (EOQualifier *) componentQualifier +- (NSString *) component { - static EOQualifier *componentQualifier = nil; - - /* TODO: we need to support vlist as well */ - if (!componentQualifier) - componentQualifier - = [[EOKeyValueQualifier alloc] initWithKey: @"c_component" - operatorSelector: EOQualifierOperatorEqual - value: @"vcard"]; - - return componentQualifier; + return @"vcard"; } - (MAPIStoreMessage *) createMessage diff --git a/OpenChange/MAPIStoreGCSFolder.h b/OpenChange/MAPIStoreGCSFolder.h index 91ec334fd..d87c9c63c 100644 --- a/OpenChange/MAPIStoreGCSFolder.h +++ b/OpenChange/MAPIStoreGCSFolder.h @@ -36,6 +36,7 @@ { SOGoMAPIFSMessage *versionsMessage; NSArray *activeUserRoles; + EOQualifier *componentQualifier; } /* synchronisation */ @@ -50,9 +51,12 @@ - (NSArray *) activeUserRoles; +- (EOQualifier *) componentQualifier; +- (EOQualifier *) contentComponentQualifier; + /* subclasses */ - (EOQualifier *) aclQualifier; -- (EOQualifier *) componentQualifier; +- (NSString *) component; @end diff --git a/OpenChange/MAPIStoreGCSFolder.m b/OpenChange/MAPIStoreGCSFolder.m index 3c41b7f1b..6a4298b2b 100644 --- a/OpenChange/MAPIStoreGCSFolder.m +++ b/OpenChange/MAPIStoreGCSFolder.m @@ -48,8 +48,15 @@ #include #include +static Class NSNumberK; + @implementation MAPIStoreGCSFolder ++ (void) initialize +{ + NSNumberK = [NSNumber class]; +} + - (id) initWithSOGoObject: (id) newSOGoObject inContainer: (MAPIStoreObject *) newContainer { @@ -72,6 +79,7 @@ { [versionsMessage release]; [activeUserRoles release]; + [componentQualifier release]; [super dealloc]; } @@ -207,17 +215,15 @@ - (NSDate *) lastMessageModificationTime { + NSDate *value; NSNumber *ti; - NSDate *value = nil; ti = [[versionsMessage properties] - objectForKey: @"SyncLastSynchronisationDate"]; + objectForKey: @"SyncLastModificationDate"]; if (ti) value = [NSDate dateWithTimeIntervalSince1970: [ti doubleValue]]; else - value = [NSDate date]; - - [self logWithFormat: @"lastMessageModificationTime: %@", value]; + value = nil; return value; } @@ -283,13 +289,41 @@ [changeList setObject: globCnt forKey: guid]; } +- (EOQualifier *) componentQualifier +{ + if (!componentQualifier) + componentQualifier + = [[EOKeyValueQualifier alloc] initWithKey: @"c_component" + operatorSelector: EOQualifierOperatorEqual + value: [self component]]; + + return componentQualifier; +} + +- (EOQualifier *) contentComponentQualifier +{ + EOQualifier *contentComponentQualifier; + NSString *likeString; + + likeString = [NSString stringWithFormat: @"%%BEGIN:%@%%", + [[self component] uppercaseString]]; + contentComponentQualifier = [[EOKeyValueQualifier alloc] + initWithKey: @"c_content" + operatorSelector: EOQualifierOperatorLike + value: likeString]; + [contentComponentQualifier autorelease]; + + return contentComponentQualifier; +} + - (BOOL) synchroniseCache { BOOL rc = YES, foundChange = NO; uint64_t newChangeNum; NSData *changeKey; NSString *cName; - NSNumber *ti, *changeNumber, *lastModificationDate, *cVersion, *cLastModified; + NSNumber *ti, *changeNumber, *lastModificationDate, *cVersion, + *cLastModified, *cDeleted; EOFetchSpecification *fs; EOQualifier *searchQualifier, *fetchQualifier; NSUInteger count, max; @@ -304,7 +338,7 @@ if (!fields) fields = [[NSArray alloc] initWithObjects: @"c_name", @"c_version", @"c_lastmodified", - nil]; + @"c_deleted", nil]; if (!sortOrdering) { @@ -313,26 +347,7 @@ [sortOrdering retain]; } - now = [NSCalendarDate date]; - - currentProperties = [[versionsMessage properties] mutableCopy]; - if (!currentProperties) - currentProperties = [NSMutableDictionary new]; - [currentProperties autorelease]; - messages = [currentProperties objectForKey: @"Messages"]; - if (!messages) - { - messages = [NSMutableDictionary new]; - [currentProperties setObject: messages forKey: @"Messages"]; - [messages release]; - } - mapping = [currentProperties objectForKey: @"VersionMapping"]; - if (!mapping) - { - mapping = [NSMutableDictionary new]; - [currentProperties setObject: mapping forKey: @"VersionMapping"]; - [mapping release]; - } + currentProperties = [versionsMessage properties]; lastModificationDate = [currentProperties objectForKey: @"SyncLastModificationDate"]; if (lastModificationDate) @@ -342,8 +357,9 @@ operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo value: lastModificationDate]; fetchQualifier = [[EOAndQualifier alloc] - initWithQualifiers: - searchQualifier, [self componentQualifier], nil]; + initWithQualifiers: searchQualifier, + [self contentComponentQualifier], + nil]; [fetchQualifier autorelease]; [searchQualifier release]; } @@ -355,21 +371,40 @@ fetchSpecificationWithEntityName: [ocsFolder folderName] qualifier: fetchQualifier sortOrderings: [NSArray arrayWithObject: sortOrdering]]; - fetchResults = [ocsFolder fetchFields: fields fetchSpecification: fs]; + fetchResults = [ocsFolder fetchFields: fields + fetchSpecification: fs + ignoreDeleted: NO]; max = [fetchResults count]; if (max > 0) { + messages = [currentProperties objectForKey: @"Messages"]; + if (!messages) + { + messages = [NSMutableDictionary new]; + [currentProperties setObject: messages forKey: @"Messages"]; + [messages release]; + } + mapping = [currentProperties objectForKey: @"VersionMapping"]; + if (!mapping) + { + mapping = [NSMutableDictionary new]; + [currentProperties setObject: mapping forKey: @"VersionMapping"]; + [mapping release]; + } + ldb_transaction_start([[self context] connectionInfo]->oc_ctx); for (count = 0; count < max; count++) { result = [fetchResults objectAtIndex: count]; cName = [result objectForKey: @"c_name"]; - cVersion = [result objectForKey: @"c_version"]; + cDeleted = [result objectForKey: @"c_deleted"]; + if ([cDeleted isKindOfClass: NSNumberK] && [cDeleted intValue]) + cVersion = [NSNumber numberWithInt: -1]; + else + cVersion = [result objectForKey: @"c_version"]; cLastModified = [result objectForKey: @"c_lastmodified"]; - [sogoObject removeChildRecordWithName: cName]; - messageEntry = [messages objectForKey: cName]; if (!messageEntry) { @@ -377,9 +412,12 @@ [messages setObject: messageEntry forKey: cName]; [messageEntry release]; } + if (![[messageEntry objectForKey: @"c_version"] isEqual: cVersion]) { + [sogoObject removeChildRecordWithName: cName]; + foundChange = YES; newChangeNum = [[self context] getNewChangeNumber]; @@ -405,6 +443,7 @@ if (foundChange) { + now = [NSCalendarDate date]; ti = [NSNumber numberWithDouble: [now timeIntervalSince1970]]; [currentProperties setObject: ti forKey: @"SyncLastSynchronisationDate"]; @@ -529,9 +568,9 @@ NSArray *deletedKeys, *deletedCNames, *records; NSNumber *changeNumNbr, *lastModified; NSString *cName; - NSDictionary *versionProperties; - NSMutableDictionary *messages, *mapping; - uint64_t newChangeNum = 0; + NSDictionary *versionProperties, *messageEntry; + NSMutableDictionary *messages; + uint64_t maxChangeNum = changeNum, currentChangeNum; EOAndQualifier *fetchQualifier; EOKeyValueQualifier *cDeletedQualifier, *cLastModifiedQualifier; EOFetchSpecification *fs; @@ -576,28 +615,28 @@ ignoreDeleted: NO]; deletedCNames = [records objectsForKey: @"c_name" notFoundMarker: nil]; max = [deletedCNames count]; - if (max > 0) + for (count = 0; count < max; count++) { - mapping = [versionProperties objectForKey: @"VersionsMapping"]; - for (count = 0; count < max; count++) + cName = [deletedCNames objectAtIndex: count]; + [sogoObject removeChildRecordWithName: cName]; + messageEntry = [messages objectForKey: cName]; + if (messageEntry) { - cName = [deletedCNames objectAtIndex: count]; - if ([messages objectForKey: cName]) + currentChangeNum + = [[messageEntry objectForKey: @"version"] + unsignedLongLongValue]; + if (MAPICNCompare (changeNum, currentChangeNum) + == NSOrderedAscending) { - [messages removeObjectForKey: cName]; [(NSMutableArray *) deletedKeys addObject: cName]; - newChangeNum = [[self context] getNewChangeNumber]; + if (MAPICNCompare (maxChangeNum, currentChangeNum) + == NSOrderedAscending) + maxChangeNum = currentChangeNum; } } - if (newChangeNum) - { - changeNumNbr - = [NSNumber numberWithUnsignedLongLong: newChangeNum]; - [mapping setObject: lastModified forKey: changeNumNbr]; - *cnNbr = changeNumNbr; - [versionsMessage save]; - } } + if (maxChangeNum != changeNum) + *cnNbr = [NSNumber numberWithUnsignedLongLong: maxChangeNum]; } } else @@ -642,7 +681,7 @@ return nil; } -- (EOQualifier *) componentQualifier +- (NSString *) component { [self subclassResponsibility: _cmd]; diff --git a/OpenChange/MAPIStoreTasksFolder.m b/OpenChange/MAPIStoreTasksFolder.m index 323bdf6e8..888daf2a8 100644 --- a/OpenChange/MAPIStoreTasksFolder.m +++ b/OpenChange/MAPIStoreTasksFolder.m @@ -48,17 +48,9 @@ return [MAPIStoreTasksMessageTable tableForContainer: self]; } -- (EOQualifier *) componentQualifier +- (NSString *) component { - static EOQualifier *componentQualifier = nil; - - if (!componentQualifier) - componentQualifier - = [[EOKeyValueQualifier alloc] initWithKey: @"c_component" - operatorSelector: EOQualifierOperatorEqual - value: @"vtodo"]; - - return componentQualifier; + return @"vtodo"; } - (MAPIStoreMessage *) createMessage