Skip to content

Remove mutable container tracking #108

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
Nov 6, 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
40 changes: 0 additions & 40 deletions Parse/src/main/java/com/parse/ParseJSONCacheItem.java

This file was deleted.

96 changes: 0 additions & 96 deletions Parse/src/main/java/com/parse/ParseObject.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
Expand Down Expand Up @@ -306,7 +305,6 @@ public String toString() {

// Cached State
private final Map<String, Object> estimatedData;
private final Map<Object, ParseJSONCacheItem> hashedObjects; // For mutable containers

private String localId;
private final ParseMulticastDelegate<ParseObject> saveEvent = new ParseMulticastDelegate<>();
Expand Down Expand Up @@ -383,7 +381,6 @@ public ParseObject(String theClassName) {
operationSetQueue = new LinkedList<>();
operationSetQueue.add(new ParseOperationSet());
estimatedData = new HashMap<>();
hashedObjects = new IdentityHashMap<>();

State.Init<?> builder = newStateBuilder(theClassName);
// When called from new, assume hasData for the whole object is true.
Expand Down Expand Up @@ -615,16 +612,6 @@ public Void then(Task<Void> task) throws Exception {
}
}

private void addToHashedObjects(Object object) {
synchronized (mutex) {
try {
hashedObjects.put(object, new ParseJSONCacheItem(object));
} catch (JSONException e) {
throw new IllegalArgumentException("Couldn't serialize container value to JSON.");
}
}
}

/**
* Converts a {@code ParseObject.State} to a {@code ParseObject}.
*
Expand Down Expand Up @@ -752,7 +739,6 @@ private void setState(State newState, boolean notifyIfObjectIdChanges) {
}

rebuildEstimatedData();
checkpointAllMutableContainers();
}
}

Expand Down Expand Up @@ -847,7 +833,6 @@ public void revert(String key) {
if (isDirty(key)) {
currentOperations().remove(key);
rebuildEstimatedData();
checkpointAllMutableContainers();
}
}
}
Expand All @@ -861,7 +846,6 @@ public void revert() {
if (isDirty()) {
currentOperations().clear();
rebuildEstimatedData();
checkpointAllMutableContainers();
}
}
}
Expand Down Expand Up @@ -1036,8 +1020,6 @@ protected boolean visit(Object object) {

/* package */ JSONObject toRest(
State state, List<ParseOperationSet> operationSetQueue, ParseEncoder objectEncoder) {
checkForChangesToMutableContainers();

// Public data goes in dataJSON; special fields go in objectJSON.
JSONObject json = new JSONObject();

Expand Down Expand Up @@ -1187,7 +1169,6 @@ public boolean isDirty() {

/* package */ boolean isDirty(boolean considerChildren) {
synchronized (mutex) {
checkForChangesToMutableContainers();
return (isDeleted || getObjectId() == null || hasChanges() || (considerChildren && hasDirtyChildren()));
}
}
Expand Down Expand Up @@ -1222,80 +1203,6 @@ public boolean isDirty(String key) {
}
}

//region Mutable Containers

/* package */ boolean isContainerObject(String key, Object object) {
return (object instanceof JSONObject || object instanceof JSONArray
|| object instanceof Map || object instanceof List
|| object instanceof ParseACL || object instanceof ParseGeoPoint);
}

/**
* Updates the JSON cache value for all of the values in estimatedData.
*/
private void checkpointAllMutableContainers() {
synchronized (mutex) {
for (Map.Entry<String, Object> entry : estimatedData.entrySet()) {
checkpointMutableContainer(entry.getKey(), entry.getValue());
}
}
}

/**
* Updates the JSON cache value for the given object.
*/
private void checkpointMutableContainer(String key, Object object) {
synchronized (mutex) {
if (isContainerObject(key, object)) {
addToHashedObjects(object);
}
}
}

/**
* Inspects to see if a given mutable container owned by this object has been mutated, and treats
* any mutation as a new {@link #put(String, Object)} call.
*/
private void checkForChangesToMutableContainer(String key, Object object) {
synchronized (mutex) {
if (isContainerObject(key, object)) {
ParseJSONCacheItem oldCacheItem = hashedObjects.get(object);
if (oldCacheItem == null) {
throw new IllegalArgumentException(
"ParseObject contains container item that isn't cached.");
} else {
ParseJSONCacheItem newCacheItem;
try {
newCacheItem = new ParseJSONCacheItem(object);
} catch (JSONException e) {
throw new RuntimeException(e);
}
if (!oldCacheItem.equals(newCacheItem)) {
// A mutable container changed out from under us. Treat it as a set operation.
performOperation(key, new ParseSetOperation(object));
}
}
} else {
hashedObjects.remove(object);
}
}
}

/**
* Inspects to see if any mutable container owned by this object has been mutated, and treats any
* mutation as a new {@link #put(String, Object)} call.
*/
/* package */ void checkForChangesToMutableContainers() {
synchronized (mutex) {
for (String key : estimatedData.keySet()) {
checkForChangesToMutableContainer(key, estimatedData.get(key));
}
hashedObjects.keySet().retainAll(estimatedData.values());
}
}

//endregion

/**
* Accessor to the object id. An object id is assigned as soon as an object is saved to the
* server. The combination of a className and an objectId uniquely identifies an object in your
Expand Down Expand Up @@ -2983,8 +2890,6 @@ private void rebuildEstimatedData() {
ParseFieldOperation oldOperation = currentOperations().get(key);
ParseFieldOperation newOperation = operation.mergeWithPrevious(oldOperation);
currentOperations().put(key, newOperation);

checkpointMutableContainer(key, newValue);
}
}

Expand Down Expand Up @@ -3512,7 +3417,6 @@ private ParseACL getACL(boolean mayCopy) {
if (mayCopy && ((ParseACL) acl).isShared()) {
ParseACL copy = ((ParseACL) acl).copy();
estimatedData.put(KEY_ACL, copy);
addToHashedObjects(copy);
return copy;
}
return (ParseACL) acl;
Expand Down
12 changes: 0 additions & 12 deletions Parse/src/main/java/com/parse/ParseUser.java
Original file line number Diff line number Diff line change
Expand Up @@ -194,15 +194,6 @@ boolean isKeyMutable(String key) {
}
}

@Override
boolean isContainerObject(String key, Object object) {
if (KEY_AUTH_DATA.equals(key)) {
// We're tracking dirtiness of `authData` ourselves.
return false;
}
return super.isContainerObject(key, object);
}

/**
* Whether the ParseUser has been authenticated on this device. This will be true if the ParseUser
* was obtained via a logIn or signUp method. Only an authenticated ParseUser can be saved (with
Expand Down Expand Up @@ -637,9 +628,6 @@ public Task<Void> then(Task<Void> task) throws Exception {
new IllegalArgumentException("Attempt to merge currentUser with itself."));
}

checkForChangesToMutableContainers();
user.checkForChangesToMutableContainers();

boolean isLazy = user.isLazy();
final String oldUsername = user.getUsername();
final String oldPassword = user.getPassword();
Expand Down
4 changes: 0 additions & 4 deletions Parse/src/test/java/com/parse/ParseUserTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,6 @@ public void testSignUpAsyncWithMergeInDiskAnonymousUser() throws Exception {
Task<Void> signUpTask = user.signUpAsync(Task.<Void>forResult(null));
signUpTask.waitForCompletion();

// Make sure we checkForChangesToMutableContainers
verify(currentUser, times(1)).checkForChangesToMutableContainers();
// Make sure currentUser copy changes from user
verify(currentUser, times(1)).copyChangesFrom(user);
// Make sure we update currentUser username and password
Expand Down Expand Up @@ -289,8 +287,6 @@ public void testSignUpAsyncWithMergeInDiskAnonymousUserSaveFailure() throws Exce
Task<Void> signUpTask = user.signUpAsync(Task.<Void>forResult(null));
signUpTask.waitForCompletion();

// Make sure we checkForChangesToMutableContainers
verify(partialMockCurrentUser, times(1)).checkForChangesToMutableContainers();
// Make sure we update currentUser username and password
verify(partialMockCurrentUser, times(1)).setUsername("userName");
verify(partialMockCurrentUser, times(1)).setPassword("password");
Expand Down