Skip to content

Removed 'mutable containers' functionality. #102

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 26, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Parse/Internal/Object/PFObjectPrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,6 @@
///--------------------------------------
#pragma mark - Data helpers
///--------------------------------------
- (void)checkForChangesToMutableContainers;
- (void)rebuildEstimatedData;

///--------------------------------------
Expand Down
8 changes: 0 additions & 8 deletions Parse/Internal/PFInternalUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,5 @@
+ (NSArray *)arrayBySplittingArray:(NSArray *)array withMaximumComponentsPerSegment:(NSUInteger)components;

+ (id)_stringWithFormat:(NSString *)format arguments:(NSArray *)arguments;
@end

@interface PFJSONCacheItem : NSObject

@property (nonatomic, copy, readonly) NSString *hashValue;

- (instancetype)initWithObject:(id)object;
+ (PFJSONCacheItem *)cacheFromObject:(id)object;

@end
29 changes: 0 additions & 29 deletions Parse/Internal/PFInternalUtils.m
Original file line number Diff line number Diff line change
Expand Up @@ -269,32 +269,3 @@ + (id)_stringWithFormat:(NSString *)format arguments:(NSArray *)arguments {
}

@end

// A PFJSONCacheItem is a pairing of a json string with its hash value.
// This is used by our mutable container checking.
@implementation PFJSONCacheItem

- (instancetype)initWithObject:(id)object {
self = [super init];
if (!self) return nil;

NSObject *encoded = [[PFPointerOrLocalIdObjectEncoder objectEncoder] encodeObject:object];
NSData *jsonData = [PFJSONSerialization dataFromJSONObject:encoded];
_hashValue = PFMD5HashFromData(jsonData);

return self;
}

- (BOOL)isEqual:(id)otherCache {
if (![otherCache isKindOfClass:[PFJSONCacheItem class]]) {
return NO;
}

return [self.hashValue isEqualToString:[otherCache hashValue]];
}

+ (PFJSONCacheItem *)cacheFromObject:(id)object {
return [[PFJSONCacheItem alloc] initWithObject:object];
}

@end
103 changes: 1 addition & 102 deletions Parse/PFObject.m
Original file line number Diff line number Diff line change
Expand Up @@ -79,25 +79,6 @@ static void PFObjectAssertValueIsKindOfValidClass(id object) {
PFParameterAssert(NO, @"PFObject values may not have class: %@", [object class]);
}

/*!
Checks if a class is a of container kind to be used as a value for PFObject.
*/
static BOOL PFObjectValueIsKindOfMutableContainerClass(id object) {
static NSArray *classes;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
classes = @[ [NSDictionary class], [NSArray class], [PFACL class], [PFGeoPoint class] ];
});

for (Class class in classes) {
if ([object isKindOfClass:class]) {
return YES;
}
}

return NO;
}

@interface PFObject () <PFObjectPrivateSubclass> {
// A lock for accessing any of the internal state of this object.
// Guards basically all of the variables below.
Expand All @@ -111,9 +92,6 @@ @interface PFObject () <PFObjectPrivateSubclass> {
// TODO (grantland): Derive this off the EventuallyPins as opposed to +/- count.
NSUInteger _deletingEventuallyCount;

// A dictionary that maps id (objects) => PFJSONCache
NSMutableDictionary *hashedObjectsCache;

NSString *localId;

// This queue is used to guarantee the order of *Eventually commands
Expand Down Expand Up @@ -656,7 +634,6 @@ - (BFTask *)_saveChildrenInBackgroundWithCurrentUser:(PFUser *)currentUser sessi

- (BOOL)isDirty:(BOOL)considerChildren {
@synchronized (lock) {
[self checkForChangesToMutableContainers];
if (self._state.deleted || dirty || [self _hasChanges]) {
return YES;
}
Expand All @@ -683,7 +660,6 @@ - (BOOL)_areChildrenDirty:(NSMutableSet *)seenObjects {
[seenObjects addObject:self];

@synchronized(lock) {
[self checkpointAllMutableContainers];
if (self._state.deleted || dirty || [self _hasChanges]) {
return YES;
}
Expand All @@ -702,62 +678,6 @@ - (BOOL)_areChildrenDirty:(NSMutableSet *)seenObjects {
}
}

///--------------------------------------
#pragma mark - Mutable container management
///--------------------------------------

- (void)checkpointAllMutableContainers {
@synchronized (lock) {
[_estimatedData enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) {
[self checkpointMutableContainer:obj];
}];
}
}

- (void)checkpointMutableContainer:(id)object {
@synchronized (lock) {
if (PFObjectValueIsKindOfMutableContainerClass(object)) {
[hashedObjectsCache setObject:[PFJSONCacheItem cacheFromObject:object]
forKey:[NSValue valueWithNonretainedObject:object]];
}
}
}

- (void)checkForChangesToMutableContainer:(id)object forKey:(NSString *)key {
@synchronized (lock) {
// If this is a mutable container, we should check its contents.
if (PFObjectValueIsKindOfMutableContainerClass(object)) {
PFJSONCacheItem *oldCacheItem = [hashedObjectsCache objectForKey:[NSValue valueWithNonretainedObject:object]];
if (!oldCacheItem) {
[NSException raise:NSInternalInconsistencyException
format:@"PFObject contains container item that isn't cached."];
} else {
PFJSONCacheItem *newCacheItem = [PFJSONCacheItem cacheFromObject:object];
if (![oldCacheItem isEqual:newCacheItem]) {
// A mutable container changed out from under us. Treat it as a set operation.
[self setObject:object forKey:key];
}
}
} else {
[hashedObjectsCache removeObjectForKey:[NSValue valueWithNonretainedObject:object]];
}
}
}

- (void)checkForChangesToMutableContainers {
@synchronized (lock) {
NSMutableArray *unexaminedCacheKeys = [[hashedObjectsCache allKeys] mutableCopy];
NSDictionary *reachableData = _estimatedData.dictionaryRepresentation;
[reachableData enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
[unexaminedCacheKeys removeObject:[NSValue valueWithNonretainedObject:obj]];
[self checkForChangesToMutableContainer:obj forKey:key];
}];

// Remove unchecked cache entries.
[hashedObjectsCache removeObjectsForKeys:unexaminedCacheKeys];
}
}

///--------------------------------------
#pragma mark - Data Availability
///--------------------------------------
Expand Down Expand Up @@ -962,7 +882,6 @@ - (NSDictionary *)RESTDictionaryWithObjectEncoder:(PFEncoder *)objectEncoder
PFObjectState *state = nil;
NSUInteger deletingEventuallyCount = 0;
@synchronized (lock) {
[self checkForChangesToMutableContainers];
state = self._state;
operationQueue = [[NSArray alloc] initWithArray:operationSetQueue copyItems:YES];
deletingEventuallyCount = _deletingEventuallyCount;
Expand Down Expand Up @@ -1106,15 +1025,11 @@ - (void)mergeFromRESTDictionary:(NSDictionary *)object withDecoder:(PFDecoder *)
if ([key isEqualToString:PFObjectACLRESTKey]) {
PFACL *acl = [PFACL ACLWithDictionary:obj];
[state setServerDataObject:acl forKey:PFObjectACLRESTKey];
[self checkpointMutableContainer:acl];
return;
}

// Should be decoded
id decodedObject = [decoder decodeObject:obj];
if (PFObjectValueIsKindOfMutableContainerClass(decodedObject)) {
[self checkpointMutableContainer:decodedObject];
}
[state setServerDataObject:decodedObject forKey:key];
}];
if (state.updatedAt == nil && state.createdAt != nil) {
Expand All @@ -1133,7 +1048,6 @@ - (void)mergeFromRESTDictionary:(NSDictionary *)object withDecoder:(PFDecoder *)
}
}
[self rebuildEstimatedData];
[self checkpointAllMutableContainers];
}
}

Expand Down Expand Up @@ -1233,8 +1147,6 @@ - (BFTask *)_enqueueSaveEventuallyOperationAsync:(PFOperationSet *)operationSet
- (NSMutableDictionary *)_convertToDictionaryForSaving:(PFOperationSet *)changes
withObjectEncoder:(PFEncoder *)encoder {
@synchronized (lock) {
[self checkForChangesToMutableContainers];

NSMutableDictionary *serialized = [NSMutableDictionary dictionary];
[changes enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
serialized[key] = obj;
Expand All @@ -1249,12 +1161,11 @@ - (NSMutableDictionary *)_convertToDictionaryForSaving:(PFOperationSet *)changes
*/
- (void)performOperation:(PFFieldOperation *)operation forKey:(NSString *)key {
@synchronized (lock) {
id newValue = [_estimatedData applyFieldOperation:operation forKey:key];
[_estimatedData applyFieldOperation:operation forKey:key];

PFFieldOperation *oldOperation = [[self unsavedChanges] objectForKey:key];
PFFieldOperation *newOperation = [operation mergeWithPrevious:oldOperation];
[[self unsavedChanges] setObject:newOperation forKey:key];
[self checkpointMutableContainer:newValue];
[_availableKeys addObject:key];
}
}
Expand Down Expand Up @@ -1320,7 +1231,6 @@ - (PFObject *)mergeFromObject:(PFObject *)other {
state.updatedAt = other.updatedAt;
state.serverData = [other._state.serverData mutableCopy];
self._state = state;
[self checkpointAllMutableContainers];

dirty = NO;

Expand All @@ -1331,13 +1241,11 @@ - (PFObject *)mergeFromObject:(PFObject *)other {

- (void)_mergeAfterFetchWithResult:(NSDictionary *)result decoder:(PFDecoder *)decoder completeData:(BOOL)completeData {
@synchronized (lock) {
[self checkForChangesToMutableContainers];
[self _mergeFromServerWithResult:result decoder:decoder completeData:completeData];
if (completeData) {
[self removeOldKeysAfterFetch:result];
}
[self rebuildEstimatedData];
[self checkpointAllMutableContainers];
}
}

Expand Down Expand Up @@ -1366,16 +1274,12 @@ - (void)_mergeAfterSaveWithResult:(NSDictionary *)result decoder:(PFDecoder *)de
PFOperationSet *operationsForNextSave = operationSetQueue[0];
[operationsForNextSave mergeOperationSet:operationsBeforeSave];
} else {
// Merge the data from the save and the data from the server into serverData.
[self checkForChangesToMutableContainers];

PFMutableObjectState *state = [self._state mutableCopy];
[state applyOperationSet:operationsBeforeSave];
self._state = state;

[self _mergeFromServerWithResult:result decoder:decoder completeData:NO];
[self rebuildEstimatedData];
[self checkpointAllMutableContainers];
}
}
}
Expand Down Expand Up @@ -1409,7 +1313,6 @@ - (void)_mergeFromServerWithResult:(NSDictionary *)result decoder:(PFDecoder *)d
} else if ([key isEqualToString:PFObjectACLRESTKey]) {
PFACL *acl = [PFACL ACLWithDictionary:obj];
[state setServerDataObject:acl forKey:key];
[self checkpointMutableContainer:acl];
} else {
[state setServerDataObject:[decoder decodeObject:obj] forKey:key];
}
Expand Down Expand Up @@ -1699,7 +1602,6 @@ - (instancetype)init {
_estimatedData = [PFObjectEstimatedData estimatedDataFromServerData:_pfinternal_state.serverData
operationSetQueue:operationSetQueue];
_availableKeys = [NSMutableSet set];
hashedObjectsCache = [[NSMutableDictionary alloc] init];
self.taskQueue = [[PFTaskQueue alloc] init];
_eventuallyTaskQueue = [[PFTaskQueue alloc] init];

Expand Down Expand Up @@ -2067,7 +1969,6 @@ - (BOOL)isDirty {

- (BOOL)isDirtyForKey:(NSString *)key {
@synchronized (lock) {
[self checkForChangesToMutableContainer:_estimatedData[key] forKey:key];
return !![[self unsavedChanges] objectForKey:key];
}
}
Expand Down Expand Up @@ -2312,7 +2213,6 @@ - (void)revert {
[_availableKeys intersectSet:persistentKeys];

[self rebuildEstimatedData];
[self checkpointAllMutableContainers];
}
}
}
Expand All @@ -2323,7 +2223,6 @@ - (void)revertObjectForKey:(NSString *)key {
[[self unsavedChanges] removeObjectForKey:key];
[self rebuildEstimatedData];
[_availableKeys removeObject:key];
[self checkpointAllMutableContainers];
}
}
}
Expand Down
3 changes: 0 additions & 3 deletions Parse/PFUser.m
Original file line number Diff line number Diff line change
Expand Up @@ -499,14 +499,11 @@ - (BFTask *)signUpAsync:(BFTask *)toAwait {

PFConsistencyAssert(!isCurrentUser, @"Attempt to merge currentUser with itself.");

[self checkForChangesToMutableContainers];
@synchronized ([currentUser lock]) {
NSString *oldUsername = [currentUser.username copy];
NSString *oldPassword = [currentUser.password copy];
NSArray *oldAnonymousData = currentUser.authData[PFAnonymousUserAuthenticationType];

[currentUser checkForChangesToMutableContainers];

// Move the changes to this object over to the currentUser object.
PFOperationSet *selfOperations = operationSetQueue[0];
[operationSetQueue removeAllObjects];
Expand Down