diff --git a/ActiveSync/SOGoActiveSyncDispatcher+Sync.m b/ActiveSync/SOGoActiveSyncDispatcher+Sync.m index 1f317cfde..48f2b10b6 100644 --- a/ActiveSync/SOGoActiveSyncDispatcher+Sync.m +++ b/ActiveSync/SOGoActiveSyncDispatcher+Sync.m @@ -531,6 +531,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - (void) processSyncGetChanges: (id ) theDocumentElement inCollection: (id) theCollection withWindowSize: (unsigned int) theWindowSize + withMaxSyncResponseSize: (unsigned int) theMaxSyncResponseSize withSyncKey: (NSString *) theSyncKey withFolderType: (SOGoMicrosoftActiveSyncFolderType) theFolderType withFilterType: (NSCalendarDate *) theFilterType @@ -562,7 +563,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. dateCache = [folderMetadata objectForKey: @"DateCache"]; if ((theFolderType == ActiveSyncMailFolder || theFolderType == ActiveSyncEventFolder || theFolderType == ActiveSyncTaskFolder) && - !([folderMetadata objectForKey: @"MoreAvailable"]) && // previous sync operation reached the windowSize + !([folderMetadata objectForKey: @"MoreAvailable"]) && // previous sync operation reached the windowSize or maximumSyncReponseSize !([theSyncKey isEqualToString: @"-1"]) && // new sync operation theFilterType) { @@ -590,7 +591,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. softdelete_count++; } - if (softdelete_count >= theWindowSize) + if (softdelete_count >= theWindowSize || (theMaxSyncResponseSize > 0 && [s length] >= theMaxSyncResponseSize)) { [folderMetadata setObject: [NSNumber numberWithBool: YES] forKey: @"MoreAvailable"]; [self _setFolderMetadata: folderMetadata forKey: [self _getNameInCache: theCollection withType: theFolderType]]; @@ -653,7 +654,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. pool = [[NSAutoreleasePool alloc] init]; // Check for the WindowSize and slice accordingly - if (return_count >= theWindowSize) + if (return_count >= theWindowSize || (theMaxSyncResponseSize > 0 && [s length] >= theMaxSyncResponseSize)) { more_available = YES; @@ -668,7 +669,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. deleted = [[component objectForKey: @"c_deleted"] intValue]; if (!deleted && ![[component objectForKey: @"c_component"] isEqualToString: component_name]) - continue; + { + DESTROY(pool); + continue; + } uid = [[component objectForKey: @"c_name"] sanitizedServerIdWithType: theFolderType]; @@ -692,10 +696,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. if (![syncCache objectForKey: uid]) updated = NO; else if ([[component objectForKey: @"c_lastmodified"] intValue] == [[syncCache objectForKey: uid] intValue]) - continue; + { + DESTROY(pool); + continue; + } return_count++; - + sogoObject = [theCollection lookupName: [uid sanitizedServerIdWithType: theFolderType] inContext: context acquire: 0]; @@ -705,7 +712,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. else componentObject = [sogoObject component: NO secure: NO]; - // // We do NOT synchronize NEW events that are in fact, invitations // to events. This is due to the fact that Outlook 2013 creates @@ -740,8 +746,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // no need to set dateCache for Contacts if ((theFolderType == ActiveSyncEventFolder || theFolderType == ActiveSyncTaskFolder)) [dateCache setObject: [componentObject startDate] ? [componentObject startDate] : [NSCalendarDate date] forKey: uid]; // FIXME: need to set proper date for recurring events - softDelete - - [s appendString: @""]; + + [s appendString: @""]; } [s appendFormat: @"%@", uid]; @@ -829,7 +835,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. else found_in_cache = NO; - if (found_in_cache) k = j+1; else @@ -847,7 +852,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. pool = [[NSAutoreleasePool alloc] init]; // Check for the WindowSize and slice accordingly - if (return_count >= theWindowSize) + if (return_count >= theWindowSize || (theMaxSyncResponseSize > 0 && [s length] >= theMaxSyncResponseSize)) { NSString *lastSequence; more_available = YES; @@ -1047,6 +1052,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - (void) processSyncCollection: (id ) theDocumentElement inBuffer: (NSMutableString *) theBuffer changeDetected: (BOOL *) changeDetected + maxSyncResponseSize: (int) theMaxSyncResponseSize { NSString *collectionId, *realCollectionId, *syncKey, *davCollectionTag, *bodyPreferenceType, *lastServerKey; SOGoMicrosoftActiveSyncFolderType folderType; @@ -1076,7 +1082,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //[theBuffer appendFormat: @"%@", collectionId]; //[theBuffer appendFormat: @"%d", 8]; //[theBuffer appendString: @""]; - return; } @@ -1139,6 +1144,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [self processSyncGetChanges: theDocumentElement inCollection: collection withWindowSize: windowSize + withMaxSyncResponseSize: theMaxSyncResponseSize withSyncKey: syncKey withFolderType: folderType withFilterType: [NSCalendarDate dateFromFilterType: [[(id)[theDocumentElement getElementsByTagName: @"FilterType"] lastObject] textValue]] @@ -1324,9 +1330,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NSArray *allCollections; NSData *d; - int i, j, defaultInterval, heartbeatInterval, internalInterval; + int i, j, defaultInterval, heartbeatInterval, internalInterval, maxSyncResponseSize; BOOL changeDetected; + changeDetected = NO; + + maxSyncResponseSize = [[SOGoSystemDefaults sharedSystemDefaults] maximumSyncResponseSize]; + // We initialize our output buffer output = [[NSMutableString alloc] init]; @@ -1376,7 +1386,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. { aCollection = [allCollections objectAtIndex: j]; - [self processSyncCollection: aCollection inBuffer: s changeDetected: &changeDetected]; + [self processSyncCollection: aCollection + inBuffer: s + changeDetected: &changeDetected + maxSyncResponseSize: maxSyncResponseSize]; } if (changeDetected) diff --git a/Documentation/SOGoInstallationGuide.asciidoc b/Documentation/SOGoInstallationGuide.asciidoc index 36e6e65ba..08c819154 100644 --- a/Documentation/SOGoInstallationGuide.asciidoc +++ b/Documentation/SOGoInstallationGuide.asciidoc @@ -2390,6 +2390,15 @@ _SOGoMaximumPingInterval_. If not set, it defaults to `10` seconds. +|S |SOGoMaximumSyncResponseSize +|Parameter used to overwrite the maximum response size during +a Sync operation. The value is in kilobytes. Setting this to 512 +means the response size will be of 524288 bytes or less. Note that +if you set the value too low and a mail message (or any other object) +surpasses it, it will still be synced but only this item will be. + +Defaults to `0`, which means no overwrite is performed. + |S |SOGoMaximumSyncWindowSize |Parameter used to overwrite the maximum number of items returned during a Sync operation. diff --git a/NEWS b/NEWS index da7df793a..190d8d262 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,8 @@ Bug fixes Enhancements - initial support for empty sync request/response for EAS + - added the SOGoMaximumSyncResponseSize EAS configuration parameter to + support memory-limited sync response sizes 2.2.12a (2014-12-19) -------------------- diff --git a/SoObjects/SOGo/SOGoSystemDefaults.h b/SoObjects/SOGo/SOGoSystemDefaults.h index de5a140fa..7f811f208 100644 --- a/SoObjects/SOGo/SOGoSystemDefaults.h +++ b/SoObjects/SOGo/SOGoSystemDefaults.h @@ -99,6 +99,7 @@ - (int) maximumSyncInterval; - (int) internalSyncInterval; - (int) maximumSyncWindowSize; +- (int) maximumSyncResponseSize; @end diff --git a/SoObjects/SOGo/SOGoSystemDefaults.m b/SoObjects/SOGo/SOGoSystemDefaults.m index f9aa5fcc2..9fbb9ef48 100644 --- a/SoObjects/SOGo/SOGoSystemDefaults.m +++ b/SoObjects/SOGo/SOGoSystemDefaults.m @@ -636,4 +636,16 @@ _injectConfigurationFromFile (NSMutableDictionary *defaultsDict, return [self integerForKey: @"SOGoMaximumSyncWindowSize"]; } +- (int) maximumSyncResponseSize +{ + int v; + + v = [self integerForKey: @"SOGoMaximumSyncResponseSize"]; + + if (v > 0) + v = v * 1024; + + return v; +} + @end