See ChangeLog

Monotone-Parent: cd39fe0df424d1e5afd5dcfa4b1c94ad707fed24
Monotone-Revision: fc9e1cf3f4988bae25443b6d072add3f344d30f0

Monotone-Author: ludovic@Sophos.ca
Monotone-Date: 2012-04-24T11:47:32
maint-2.0.2
Ludovic Marcotte 2012-04-24 11:47:32 +00:00
parent f9d34ea6ec
commit c774314b1b
8 changed files with 61 additions and 26 deletions

View File

@ -1,3 +1,13 @@
2012-04-24 Ludovic Marcotte <lmarcotte@inverse.ca>
* SOPE/GDLContentStore/GCSFolder.m (-writeContent:toName:baseVersion:):
We now keep track of the saved version for all callers. Also updated
all callers to reflect that change.
* SoObjects/Appointments/SOGoAppointmentObject.m (-PUTAction:)
Took some of the logic from SOGoContentObject's -PUTAction: to
avoid etag mismatches.
2012-04-23 Ludovic Marcotte <lmarcotte@inverse.ca>
* SoObjects/Appointments/SOGoAppointmentObject.m: We now

View File

@ -118,7 +118,7 @@
- (NSException *) writeContent: (NSString *) _content
toName: (NSString *) _name
baseVersion: (unsigned int) _baseVersion;
baseVersion: (unsigned int *) _baseVersion;
- (NSException *) writeContent: (NSString *) _content
toName: (NSString *) _name;
- (NSException *) deleteContentWithName: (NSString *) _name;

View File

@ -882,7 +882,7 @@ andAttribute: (EOAttribute *)_attribute
- (NSException *) writeContent: (NSString *) _content
toName: (NSString *) _name
baseVersion: (unsigned int) _baseVersion
baseVersion: (unsigned int *) _baseVersion
{
EOAdaptorChannel *storeChannel, *quickChannel;
NSMutableDictionary *quickRow, *contentRow;
@ -939,8 +939,8 @@ andAttribute: (EOAttribute *)_attribute
/* check whether sequence matches */
/* use version = 0 to override check */
if (_baseVersion == 0
|| _baseVersion == [storedVersion unsignedIntValue])
if (*_baseVersion == 0
|| *_baseVersion == [storedVersion unsignedIntValue])
{
/* extract quick info */
extractor = [folderInfo quickExtractor];
@ -1040,16 +1040,16 @@ andAttribute: (EOAttribute *)_attribute
error = (hasUpdateDelegate
? [storeChannel updateRowX: contentRow
describedByQualifier: [self _qualifierUsingWhereColumn: @"c_name" isEqualTo: _name
andColumn: (_baseVersion != 0 ? (id)@"c_version" : (id)nil)
isEqualTo: (_baseVersion != 0 ? [NSNumber numberWithUnsignedInt:_baseVersion] : (NSNumber *)nil)
andColumn: (*_baseVersion != 0 ? (id)@"c_version" : (id)nil)
isEqualTo: (*_baseVersion != 0 ? [NSNumber numberWithUnsignedInt: *_baseVersion] : (NSNumber *)nil)
entity: storeTableEntity
withAdaptor: [[storeChannel adaptorContext] adaptor]]]
: [storeChannel evaluateExpressionX: [self _generateUpdateStatementForRow: contentRow
adaptor: [[storeChannel adaptorContext] adaptor]
tableName:[self storeTableName]
whereColumn: @"c_name" isEqualTo: _name
andColumn: (_baseVersion != 0 ? (id)@"c_version" : (id)nil)
isEqualTo: (_baseVersion != 0 ? [NSNumber numberWithUnsignedInt: _baseVersion] : (NSNumber *)nil)]]);
andColumn: (*_baseVersion != 0 ? (id)@"c_version" : (id)nil)
isEqualTo: (*_baseVersion != 0 ? [NSNumber numberWithUnsignedInt: *_baseVersion] : (NSNumber *)nil)]]);
}
if (error)
@ -1063,6 +1063,9 @@ andAttribute: (EOAttribute *)_attribute
}
else
{
if (!isNewRecord)
*_baseVersion += 1;
[[storeChannel adaptorContext] commitTransaction];
[[quickChannel adaptorContext] commitTransaction];
}
@ -1082,7 +1085,7 @@ andAttribute: (EOAttribute *)_attribute
else /* version mismatch (concurrent update) */
error = [self errorVersionMismatchBetweenStoredVersion:
[storedVersion unsignedIntValue]
andExpectedVersion: _baseVersion];
andExpectedVersion: *_baseVersion];
}
else
error = [NSException exceptionWithName:@"GCSStoreException"
@ -1100,7 +1103,8 @@ andAttribute: (EOAttribute *)_attribute
- (NSException *)writeContent:(NSString *)_content toName:(NSString *)_name {
/* this method does not check for concurrent writes */
return [self writeContent:_content toName:_name baseVersion:0];
unsigned int v = 0;
return [self writeContent:_content toName:_name baseVersion:&v];
}
- (NSException *)deleteContentWithName:(NSString *)_name {

View File

@ -1658,11 +1658,13 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
- (id) PUTAction: (WOContext *) _ctx
{
NSException *ex;
NSString *etag;
NSArray *roles;
WORequest *rq;
id response;
unsigned int baseVersion;
rq = [_ctx request];
roles = [[context activeUser] rolesForObject: self inContext: context];
@ -1961,9 +1963,27 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
}
}
// This will save the event into the database and also handle
// E-Tags properly, as well as content versioning.
response = [super PUTAction: _ctx];
// We must NOT invoke [super PUTAction:] here as it'll resave
// the content string and we could have etag mismatches.
response = [_ctx response];
baseVersion = (isNew ? 0 : version);
ex = [self saveContentString: [rq contentAsString]
baseVersion: baseVersion];
if (ex)
response = (WOResponse *) ex;
else
{
if (isNew)
[response setStatus: 201 /* Created */];
else
[response setStatus: 204 /* No Content */];
etag = [self davEntityTag];
if (etag)
[response setHeader: etag forKey: @"etag"];
}
return response;
}

View File

@ -1,14 +1,15 @@
/*
Copyright (C) 2006-2012 Inverse inc.
Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
This file is part of SOGo.
OGo is free software; you can redistribute it and/or modify it under
SOGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
SOGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.

View File

@ -1,6 +1,6 @@
/* SOGoContactGCSEntry.h - this file is part of SOGo
*
* Copyright (C) 2006-2011 Inverse inc.
* Copyright (C) 2006-2012 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*

View File

@ -209,7 +209,7 @@
{
ex = [folder writeContent: newContent
toName: nameInContainer
baseVersion: newVersion];
baseVersion: &version];
if (ex)
[self errorWithFormat:@"write failed: %@", ex];
}
@ -225,7 +225,7 @@
- (NSException *) saveContentString: (NSString *) newContent
{
return [self saveContentString: newContent baseVersion: 0];
return [self saveContentString: newContent baseVersion: version];
}
/* actions */
@ -347,8 +347,6 @@
response = (WOResponse *) error;
else
{
if (!isNew)
version++;
response = [_ctx response];
/* setup response */

View File

@ -1,6 +1,6 @@
/* SOGoToolRestore.m - this file is part of SOGo
*
* Copyright (C) 2009-2010 Inverse inc.
* Copyright (C) 2009-2012 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -346,14 +346,16 @@ typedef enum SOGoToolRestoreMode {
- (BOOL) restoreRecords: (NSArray *) records
ofFolder: (GCSFolder *) gcsFolder
{
BOOL rc;
NSDictionary *existingRecords, *currentRecord;
NSString *cName, *cContent;
NSException *ex;
int count, max;
int count, max, version;
BOOL rc;
if (records)
{
version = 0;
rc = YES;
existingRecords = [self fetchExistingRecordsFromFolder: gcsFolder];
max = [records count];
@ -366,7 +368,7 @@ typedef enum SOGoToolRestoreMode {
NSLog (@"restoring record '%@'", cName);
cContent = [currentRecord objectForKey: @"c_content"];
ex = [gcsFolder writeContent: cContent toName: cName
baseVersion: 0];
baseVersion: &version];
}
}
}