first sketch of an implementation that can adjust a TrackedRace's course-related structures after deserialization

This commit is contained in:
Axel Uhl committed 2014-09-23 15:39:49 +02:00
1 parent c7264e3b7c
commit 9c5b268b4b
3 files changed
+75 -2

No files matched your search

@@ -18,7 +18,9 @@ package difflib;
import java.util.*;
/**
* Describes the delta between original and revised texts.
* Describes the delta between original and revised object lists. Applying the patch only uses {@link List#add(int, Object)}
* and {@link List#remove(int)} as modifying operations. In particular, no call to {@link List#set(int, Object)} needs to be
* expected.
*
* @author <a href="dm.naumenko@gmail.com">Dmitry Naumenko</a>
*/
@@ -0,0 +1,48 @@
package com.sap.sailing.domain.tracking.impl;
import java.util.AbstractList;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sse.common.Util;
public class TrackedRaceAsWaypointList extends AbstractList<Waypoint> {
private final TrackedRaceImpl trackedRace;
protected TrackedRaceAsWaypointList(TrackedRaceImpl trackedRace) {
this.trackedRace = trackedRace;
}
@Override
public Waypoint get(int index) {
final Waypoint result;
final int numberOfLegs = Util.size(trackedRace.getTrackedLegs());
if (index > numberOfLegs) {
result = null;
} else if (index == numberOfLegs) {
result = Util.get(trackedRace.getTrackedLegs(), numberOfLegs-1).getLeg().getTo();
} else {
result = Util.get(trackedRace.getTrackedLegs(), index).getLeg().getFrom();
}
return result;
}
@Override
public int size() {
return Util.size(trackedRace.getTrackedLegs())+1;
}
@Override
public void add(int index, Waypoint element) {
trackedRace.waypointAdded(index, element);
}
@Override
public Waypoint remove(int zeroBasedIndex) {
final Waypoint waypointThatGotRemoved = get(zeroBasedIndex);
if (waypointThatGotRemoved != null) {
trackedRace.waypointRemoved(zeroBasedIndex, waypointThatGotRemoved);
}
return waypointThatGotRemoved;
}
}
@@ -117,6 +117,10 @@ import com.sap.sailing.util.impl.NamedReentrantReadWriteLock;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
import difflib.DiffUtils;
import difflib.Patch;
import difflib.PatchFailedException;
public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials implements CourseListener {
private static final long serialVersionUID = -4825546964220003507L;
@@ -465,7 +469,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
* When de-serializing, a possibly remote {@link #windStore} is ignored because it is transient. Instead, an
* {@link EmptyWindStore} is used for the de-serialized instance.
*/
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException, PatchFailedException {
ois.defaultReadObject();
attachedRaceLogs = new ConcurrentHashMap<>();
markPassingsTimes = new ArrayList<com.sap.sse.common.Util.Pair<Waypoint, com.sap.sse.common.Util.Pair<TimePoint, TimePoint>>>();
@@ -480,6 +484,25 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
triggerManeuverCacheRecalculationForAllCompetitors();
logger.info("Deserialized race " + getRace().getName());
shortTimeWindCache = new ShortTimeWindCache(this, millisecondsOverWhichToAverageWind / 2);
// considering the unlikely possibility that the course and this tracked race's internal structures
// may be inconsistent, e.g., due to non-atomic serialization of course and tracked race; see bug 2223
adjustStructureToCourse();
}
/**
* When the {@link TrackedRace} object and the {@link RaceDefinition} and in particular its {@link CourseImpl} objects are not
* atomically serialized, inconsistencies may occur during de-serialization. In particular, the tracked race's leg-oriented
* structures may not consistently reflect the course's leg sequence because a course update could have happened between
* course serialization and tracked race serialization.<p>
*
* To fix this, the list of waypoints as found in this tracked race's leg-oriented structures, compared to the course's
* waypoint list, produces a patch that can be applied to this tracked race, resulting in the necessary
* {@link #waypointAdded(int, Waypoint)} and {@link #waypointRemoved(int, Waypoint)} calls.
*/
private void adjustStructureToCourse() throws PatchFailedException {
final TrackedRaceAsWaypointList trackedRaceAsWaypointList = new TrackedRaceAsWaypointList(this);
Patch<Waypoint> diff = DiffUtils.diff(getRace().getCourse().getWaypoints(), trackedRaceAsWaypointList);
diff.applyTo(trackedRaceAsWaypointList);
}
@Override