Merge pull request #219 from zentyal/ejhernandez/mult-cn-restriction

Manage multiple Change Number restrictions
This commit is contained in:
Jesús García Sáez 2015-12-22 17:14:53 +01:00
commit 966d13c5b6
7 changed files with 157 additions and 23 deletions

View file

@ -109,18 +109,70 @@
return self;
}
- (NSString *) description
{
id key, value;
NSEnumerator *propEnumerator;
NSMutableString *description;
description = [NSMutableString stringWithFormat: @"%@ %@. Properties: {", NSStringFromClass ([self class]),
[self url]];
propEnumerator = [properties keyEnumerator];
while ((key = [propEnumerator nextObject]))
{
uint32_t proptag = 0;
if ([key isKindOfClass: [NSString class]] && [(NSString *)key intValue] > 0)
proptag = [(NSString *)key intValue];
else if ([key isKindOfClass: [NSNumber class]])
proptag = [key unsignedLongValue];
if (proptag > 0)
{
const char *propTagName = get_proptag_name ([key unsignedLongValue]);
NSString *propName;
if (propTagName)
propName = [NSString stringWithCString: propTagName
encoding: NSUTF8StringEncoding];
else
propName = [NSString stringWithFormat: @"0x%.4x", [key unsignedLongValue]];
[description appendFormat: @"'%@': ", propName];
}
else
[description appendFormat: @"'%@': ", key];
value = [properties objectForKey: key];
[description appendFormat: @"%@ (%@), ", value, NSStringFromClass ([value class])];
}
[description appendString: @"}\n"];
return description;
}
- (uint64_t) objectVersion
{
NSNumber *versionNbr;
/* Return the global counter from CN structure.
See [MS-OXCFXICS] Section 2.2.2.1 */
NSNumber *versionNbr, *cn;
uint64_t objectVersion;
[(SOGoMAPIDBMessage *) sogoObject reloadIfNeeded];
versionNbr = [properties objectForKey: @"version"];
versionNbr = [properties objectForKey: @"version_number"];
if (versionNbr)
objectVersion = (([versionNbr unsignedLongLongValue] >> 16)
& 0x0000ffffffffffffLL);
objectVersion = exchange_globcnt ([versionNbr unsignedLongLongValue]);
else
objectVersion = ULLONG_MAX;
{
/* Old version which stored the CN structure not useful for searching */
cn = [properties objectForKey: @"version"];
if (cn)
objectVersion = (([cn unsignedLongLongValue] >> 16)
& 0x0000ffffffffffffLL);
else
objectVersion = ULLONG_MAX;
}
return objectVersion;
}
@ -283,13 +335,19 @@
[properties setObject: attachmentParts forKey: @"attachments"];
newVersion = [[self context] getNewChangeNumber];
newVersion = exchange_globcnt ((newVersion >> 16) & 0x0000ffffffffffffLL);
[properties setObject: [NSNumber numberWithUnsignedLongLong: newVersion]
forKey: @"version"];
forKey: @"version_number"];
/* Remove old version */
[properties removeObjectForKey: @"version"];
/* Update PredecessorChangeList accordingly */
[self _updatePredecessorChangeList];
[self logWithFormat: @"%d props in dict", [properties count]];
// [self logWithFormat: @"Saving %@", [self description]];
// [self logWithFormat: @"%d props in dict", [properties count]];
[sogoObject save];
}

View file

@ -61,14 +61,15 @@ static Class MAPIStoreDBMessageK = Nil;
if ((uint32_t) res->ulPropTag == PidTagChangeNumber)
{
SEL operator;
value = NSObjectFromMAPISPropValue (&res->lpProp);
cVersion = exchange_globcnt (([value unsignedLongLongValue] >> 16)
& 0x0000ffffffffffffLL);
version = [NSNumber numberWithUnsignedLongLong: cVersion];
//[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
[self logWithFormat: @" version: %.16lx", cVersion];
*qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"version"
operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo
operator = [self operatorFromRestrictionOperator: res->relop];
*qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"version_number"
operatorSelector: operator
value: version];
[*qualifier autorelease];
rc = MAPIRestrictionStateNeedsEval;

View file

@ -681,12 +681,12 @@ static Class NSNumberK;
- (NSNumber *) lastModifiedFromMessageChangeNumber: (NSString *) changeNumber
{
NSDictionary *mapping;
NSNumber *modseq;
NSNumber *lastModified;
mapping = [[versionsMessage properties] objectForKey: @"VersionMapping"];
modseq = [mapping objectForKey: changeNumber];
lastModified = [mapping objectForKey: changeNumber];
return modseq;
return lastModified;
}
- (NSString *) changeNumberForMessageWithKey: (NSString *) messageKey

View file

@ -27,6 +27,7 @@
#import <Foundation/NSString.h>
#import <NGExtensions/NSObject+Logs.h>
#import <NGExtensions/NSObject+Values.h>
#import <EOControl/EOFetchSpecification.h>
#import <EOControl/EOQualifier.h>
@ -38,7 +39,6 @@
#import "MAPIStoreTypes.h"
#import "MAPIStoreGCSFolder.h"
#import "MAPIStoreGCSMessageTable.h"
#undef DEBUG
@ -89,21 +89,31 @@
if (res->ulPropTag == PidTagChangeNumber)
{
NSString *changeNumber;
value = NSObjectFromMAPISPropValue (&res->lpProp);
changeNumber = [NSString stringWithUnsignedLongLong: [(NSNumber *)value unsignedLongLongValue]];
lastModified = [(MAPIStoreGCSFolder *)
container lastModifiedFromMessageChangeNumber: value];
container lastModifiedFromMessageChangeNumber: changeNumber];
//[self logWithFormat: @"change number from oxcfxics: %.16lx", [value unsignedLongLongValue]];
//[self logWithFormat: @" c_lastmodified: %@", lastModified];
if (lastModified)
{
SEL operator;
operator = [self operatorFromRestrictionOperator: res->relop];
*qualifier = [[EOKeyValueQualifier alloc] initWithKey: @"c_lastmodified"
operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo
operatorSelector: operator
value: lastModified];
[*qualifier autorelease];
rc = MAPIRestrictionStateNeedsEval;
}
else
rc = MAPIRestrictionStateAlwaysTrue;
{
[self logWithFormat: @"No last modified found for: 0x%.16"PRIx64". Then no restriction applied",
[value unsignedLongLongValue]];
rc = MAPIRestrictionStateAlwaysTrue;
}
}
else
{

View file

@ -74,6 +74,7 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
#include <util/attr.h>
#include <libmapi/libmapi.h>
#include <libmapiproxy.h>
#include <limits.h>
#include <mapistore/mapistore.h>
#include <mapistore/mapistore_errors.h>
@ -257,6 +258,67 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
return MAPISTORE_SUCCESS;
}
- (EOQualifier *) simplifyQualifier: (EOQualifier *) qualifier
{
/* Hack: Reduce the number of MODSEQ constraints to a single one as
we assume the difference among MODSEQs will be small enough to
return a small number of UIDs.
This is the only case we do simplify:
MODSEQ >= x | MODSEQ >= y | MODSEQ >= z => MODSEQ >= min(x,y,z)
*/
if (qualifier && [qualifier isKindOfClass: [EOOrQualifier class]])
{
EOQualifier *simplifiedQualifier;
NSArray *quals;
NSNumber *minModseq;
NSUInteger i, count;
quals = [(EOOrQualifier *)qualifier qualifiers];
count = [quals count];
if (count < 2)
return qualifier;
minModseq = [NSNumber numberWithUnsignedLongLong: ULLONG_MAX];
for (i = 0; i < count; i++)
{
EOQualifier *subQualifier;
subQualifier = [quals objectAtIndex: i];
if ([subQualifier isKindOfClass: [EOAndQualifier class]]
&& [[(EOAndQualifier *)subQualifier qualifiers] count] == 1)
subQualifier = [[(EOAndQualifier *)subQualifier qualifiers] objectAtIndex: 0];
if ([subQualifier isKindOfClass: [EOKeyValueQualifier class]]
&& [[(EOKeyValueQualifier *)subQualifier key] isEqualToString: @"MODSEQ"])
{
NSNumber *value;
value = (NSNumber *)[(EOKeyValueQualifier *)subQualifier value];
if ([minModseq compare: value] == NSOrderedDescending
&& [value unsignedLongLongValue] > 0)
minModseq = (NSNumber *)[(EOKeyValueQualifier *)subQualifier value];
}
else
return qualifier;
}
if ([minModseq unsignedLongLongValue] > 0 && [minModseq unsignedLongLongValue] < ULLONG_MAX)
{
simplifiedQualifier = [[EOKeyValueQualifier alloc]
initWithKey: @"MODSEQ"
operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo
value: minModseq];
[simplifiedQualifier autorelease];
return simplifiedQualifier;
}
}
return qualifier;
}
- (EOQualifier *) nonDeletedQualifier
{
static EOQualifier *nonDeletedQualifier = nil;
@ -281,7 +343,7 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
andSortOrderings: (NSArray *) sortOrderings
{
NSArray *uidKeys;
EOQualifier *fetchQualifier;
EOQualifier *fetchQualifier, *simplifiedQualifier;
if ([self ensureFolderExists])
{
@ -290,9 +352,10 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
if (qualifier)
{
simplifiedQualifier = [self simplifyQualifier: qualifier];
fetchQualifier
= [[EOAndQualifier alloc] initWithQualifiers:
[self nonDeletedQualifier], qualifier,
[self nonDeletedQualifier], simplifiedQualifier,
nil];
[fetchQualifier autorelease];
}

View file

@ -181,8 +181,8 @@ static Class MAPIStoreMailMessageK, NSDataK, NSStringK;
else
{
/* Ignore other operations as IMAP only support MODSEQ >= X */
[self warnWithFormat: @"Ignoring %@ as only supported operators are > and >=",
[self operatorFromRestrictionOperator: res->relop]];
[self warnWithFormat: @"Ignoring '%@' as only supported operators are > and >=",
NSStringFromSelector ([self operatorFromRestrictionOperator: res->relop])];
rc = MAPIRestrictionStateAlwaysTrue;
}
}

View file

@ -197,6 +197,7 @@ static Class MAPIStoreFolderK;
inMemCtx: (TALLOC_CTX *) memCtx
{
int rc;
struct mapistore_connection_info *connInfo;
uint64_t obVersion;
obVersion = [self objectVersion];
@ -204,8 +205,9 @@ static Class MAPIStoreFolderK;
rc = MAPISTORE_ERR_NOT_FOUND;
else
{
connInfo = [[self context] connectionInfo];
*data = MAPILongLongValue (memCtx, ((obVersion << 16)
| 0x0001));
| connInfo->repl_id));
rc = MAPISTORE_SUCCESS;
}