diff --git a/src/java/com/threerings/whirled/data/SceneUpdate.java b/src/java/com/threerings/whirled/data/SceneUpdate.java
index 16be7b0b..87651393 100644
--- a/src/java/com/threerings/whirled/data/SceneUpdate.java
+++ b/src/java/com/threerings/whirled/data/SceneUpdate.java
@@ -33,20 +33,18 @@ import com.threerings.util.ActionScript;
import com.threerings.whirled.Log;
/**
- * Used to encapsulate updates to scenes in such a manner that updates can
- * be stored persistently and sent to clients to update their own local
- * copies of scenes.
+ * Used to encapsulate updates to scenes in such a manner that updates can be stored persistently
+ * and sent to clients to update their own local copies of scenes.
*/
public class SceneUpdate
implements Streamable, Cloneable
{
/**
- * Initializes this scene update such that it will operate on a scene
- * with the specified target scene and version number.
+ * Initializes this scene update such that it will operate on a scene with the specified target
+ * scene and version number.
*
* @param targetId the id of the scene on which we are to operate.
- * @param targetVersion the version of the scene on which we are to
- * operate.
+ * @param targetVersion the version of the scene on which we are to operate.
*/
public void init (int targetId, int targetVersion)
{
@@ -71,43 +69,48 @@ public class SceneUpdate
}
/**
- * Called to ensure that the scene is in the appropriate state prior
- * to applying the update.
+ * Returns the amount by which this update increments the scene version.
+ */
+ public int getVersionIncrement ()
+ {
+ return 1;
+ }
+
+ /**
+ * Called to ensure that the scene is in the appropriate state prior to applying the update.
*
- * @exception IllegalStateException thrown if the update cannot be
- * applied to the scene because it is not in a valid state
- * (appropriate previous updates were not applied, it's the wrong kind
- * of scene, etc.).
+ * @exception IllegalStateException thrown if the update cannot be applied to the scene because
+ * it is not in a valid state (appropriate previous updates were not applied, it's the wrong
+ * kind of scene, etc.).
*/
public void validate (SceneModel model)
throws IllegalStateException
{
if (model.sceneId != _targetId) {
- String errmsg = "Wrong target scene, expected id " +
- _targetId + " got id " + model.sceneId;
+ String errmsg = "Wrong target scene, expected id " + _targetId +
+ " got id " + model.sceneId;
throw new IllegalStateException(errmsg);
}
if (model.version != _targetVersion) {
- String errmsg = "Target scene not proper version, expected " +
- _targetVersion + " got " + model.version;
+ String errmsg = "Target scene not proper version, expected " + _targetVersion +
+ " got " + model.version;
throw new IllegalStateException(errmsg);
}
}
/**
- * Applies this update to the specified scene model. Derived classes
- * will want to override this method and apply updates of their own,
- * being sure to call super.apply.
+ * Applies this update to the specified scene model. Derived classes will want to override this
+ * method and apply updates of their own, being sure to call super.apply.
*/
public void apply (SceneModel model)
{
// increment the version; disallowing integer overflow
- model.version = Math.max(_targetVersion + 1, model.version);
+ model.version = Math.max(_targetVersion + getVersionIncrement(), model.version);
// sanity check for the amazing two billion updates
if (model.version == _targetVersion) {
- Log.warning("Egads! This scene has been updated two billion " +
- "times [model=" + model + ", update=" + this + "].");
+ Log.warning("Egads! This scene has been updated two billion times [model=" + model +
+ ", update=" + this + "].");
}
}
@@ -138,10 +141,9 @@ public class SceneUpdate
}
/**
- * Serializes the bare representation of this instance without the scene id
- * and version fields. Useful when storing updates in a database where the
- * scene id and version fields are stored in separate columns and the rest
- * if the representation is contained in an opaque blob.
+ * Serializes the bare representation of this instance without the scene id and version fields.
+ * Useful when storing updates in a database where the scene id and version fields are stored
+ * in separate columns and the rest if the representation is contained in an opaque blob.
*/
@ActionScript(omit=true)
public void persistTo (ObjectOutputStream out)
@@ -156,8 +158,7 @@ public class SceneUpdate
}
/**
- * Unserializes this instance from the bare representation created by
- * {@link #persistTo}.
+ * Unserializes this instance from the bare representation created by {@link #persistTo}.
*/
@ActionScript(omit=true)
public void unpersistFrom (ObjectInputStream in)
@@ -182,8 +183,7 @@ public class SceneUpdate
}
/**
- * An extensible mechanism for generating a string representation of
- * this instance.
+ * An extensible mechanism for generating a string representation of this instance.
*/
@ActionScript(name="toStringBuilder")
protected void toString (StringBuilder buf)
diff --git a/src/java/com/threerings/whirled/server/SceneManager.java b/src/java/com/threerings/whirled/server/SceneManager.java
index e8a72e71..d4900224 100644
--- a/src/java/com/threerings/whirled/server/SceneManager.java
+++ b/src/java/com/threerings/whirled/server/SceneManager.java
@@ -149,8 +149,7 @@ public class SceneManager extends PlaceManager
WhirledServer.invoker.postUnit(new Invoker.Unit() {
public boolean invoke () {
try {
- _screg.getSceneRepository().applyAndRecordUpdate(
- _scene.getSceneModel(), update);
+ _screg.getSceneRepository().applyAndRecordUpdate(_scene.getSceneModel(), update);
} catch (PersistenceException pe) {
Log.warning("Failed to apply scene update " + update + ".");
Log.logStackTrace(pe);
diff --git a/src/java/com/threerings/whirled/util/UpdateList.java b/src/java/com/threerings/whirled/util/UpdateList.java
index eacdad4f..662e459d 100644
--- a/src/java/com/threerings/whirled/util/UpdateList.java
+++ b/src/java/com/threerings/whirled/util/UpdateList.java
@@ -21,7 +21,9 @@
package com.threerings.whirled.util;
-import java.util.ArrayList;
+import java.util.List;
+
+import com.google.common.collect.Lists;
import com.threerings.whirled.Log;
import com.threerings.whirled.data.SceneUpdate;
@@ -31,77 +33,66 @@ import com.threerings.whirled.data.SceneUpdate;
*/
public class UpdateList
{
- public UpdateList ()
- {
- _updates = new ArrayList();
- }
-
/**
- * Adds an update to this list. The update must follow appropriately
- * the chain of updates established by the updates already in the list
- * (meaning it must operate on one version higher than the most recent
- * update already in the list).
+ * Adds an update to this list. The update must follow appropriately the chain of updates
+ * established by the updates already in the list (meaning it must operate on one version
+ * higher than the most recent update already in the list).
*/
public void addUpdate (SceneUpdate update)
{
- if (_minVersion == -1) {
- // this is our first update, so we initialize our min version
- _minVersion = update.getSceneVersion();
-
- } else {
- int gotVersion = update.getSceneVersion();
- int expVersion = _minVersion + _updates.size();
- if (gotVersion > expVersion) {
- Log.warning("Update continuity broken, flushing list " +
- "[got=" + update + ", expect=" + expVersion +
- ", ucount=" + _updates.size() + "].");
- // flush out our old updates and start anew from here
- _updates.clear();
- _minVersion = expVersion;
-
- } else if (gotVersion < expVersion) {
- // we somehow got an update that's older than updates we
- // already have? wick wick wack
- String errmsg = "Invalid update version " +
- "[want=" + expVersion + ", got=" + update + "]";
- throw new IllegalArgumentException(errmsg);
- }
+ // if this is our first update, great, we let it in with no questions asked
+ if (_updates.isEmpty()) {
+ _updates.add(update);
+ return;
}
+
+ // otherwise make sure this update conforms to our update sequence
+ SceneUpdate last = _updates.get(_updates.size()-1);
+ int expVersion = last.getSceneVersion() + last.getVersionIncrement();
+ int gotVersion = update.getSceneVersion();
+ if (gotVersion > expVersion) {
+ Log.warning("Update continuity broken, flushing list [got=" + update +
+ ", expect=" + expVersion + ", ucount=" + _updates.size() + "].");
+ _updates.clear(); // flush out our old updates, fall through and add this one
+
+ } else if (gotVersion < expVersion) {
+ // we somehow got an update that's older than updates we already have?
+ String errmsg = "Invalid update version [want=" + expVersion + ", got=" + update + "]";
+ throw new IllegalArgumentException(errmsg);
+ }
+
_updates.add(update);
}
/**
- * Returns all of the updates that should be applied to a scene with
- * the specified version to bring it up to date. null is
- * returned if the scene's version is older than the oldest update in
- * our list, in which case it cannot be brought up to date by applying
- * updates from this list.
+ * Returns all of the updates that should be applied to a scene with the specified version to
+ * bring it up to date. null is returned if the scene's version is older than the
+ * oldest update in our list, in which case it cannot be brought up to date by applying updates
+ * from this list.
*/
public SceneUpdate[] getUpdates (int fromVersion)
{
- if (_minVersion == -1 || fromVersion < _minVersion) {
- return null;
+ List updates = Lists.newArrayList();
+ for (SceneUpdate update : _updates) {
+ if (update.getSceneVersion() >= fromVersion) {
+ updates.add(update);
+ }
}
-
- int offset = fromVersion - _minVersion;
- int ucount = _updates.size() - offset;
- SceneUpdate[] updates = new SceneUpdate[ucount];
- for (int ii = 0; ii < ucount; ii++) {
- updates[ii] = (SceneUpdate)_updates.get(ii+offset);
- }
- return updates;
+ return updates.toArray(new SceneUpdate[updates.size()]);
}
/**
- * Returns true if the supplied actual scene version is in accordance
- * with the updates contained in this list.
+ * Returns true if the supplied actual scene version is in accordance with the updates
+ * contained in this list.
*/
public boolean validate (int sceneVersion)
{
- return ((_minVersion == -1) || // we have no updates
- (_minVersion + _updates.size() == sceneVersion));
+ if (_updates.size() == 0) {
+ return true;
+ }
+ SceneUpdate last = _updates.get(_updates.size()-1);
+ return sceneVersion == (last.getSceneVersion() + last.getVersionIncrement());
}
- protected ArrayList _updates;
- protected int _minVersion = -1;
+ protected List _updates = Lists.newArrayList();
}