mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-08 05:11:04 +00:00
used separate flags and logs for loading from windStore and gpSFixStore in tracked race
This commit is contained in:
1 parent
ab6ae2429d
commit
e022fe57e0
8 files changed
+88
-39
No files matched your search
+2
-1
@@ -221,7 +221,8 @@ public class MockedTrackedRace implements DynamicTrackedRace {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(RaceChangeListener listener, boolean notifyAboutWindFixesAlreadyLoaded) {
|
||||
public void addListener(RaceChangeListener listener, boolean notifyAboutWindFixesAlreadyLoaded,
|
||||
boolean notifyAboutGPSFixesAlreadyLoaded) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
+2
-1
@@ -353,7 +353,8 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(RaceChangeListener listener, boolean notifyAboutWindFixesAlreadyLoaded) {
|
||||
public void addListener(RaceChangeListener listener, boolean notifyAboutWindFixesAlreadyLoaded,
|
||||
boolean notifyAboutGPSFixesAlreadyLoaded) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@@ -443,9 +443,12 @@ public interface TrackedRace extends Serializable {
|
||||
* tracked race. This runs synchronized with the otherwise asynchronous loading of wind tracks, triggered by the
|
||||
* constructor of the {@link TrackedRace} implementation classes. This procedure guarantees that eventually the
|
||||
* listener will have received a notification for all wind fixes, regardless of whether they were already loaded at
|
||||
* the time the listener is registered or they are loaded after the registration has completed.
|
||||
* the time the listener is registered or they are loaded after the registration has completed.<p>
|
||||
*
|
||||
* The same is true for the GPS fixes for marks and competitors.
|
||||
*/
|
||||
void addListener(RaceChangeListener listener, boolean notifyAboutWindFixesAlreadyLoaded);
|
||||
void addListener(RaceChangeListener listener, boolean notifyAboutWindFixesAlreadyLoaded,
|
||||
boolean notifyAboutGPSFixesAlreadyLoaded);
|
||||
|
||||
void removeListener(RaceChangeListener listener);
|
||||
|
||||
|
||||
+33
-9
@@ -44,6 +44,7 @@ import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.GPSFix;
|
||||
import com.sap.sailing.domain.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.tracking.GPSFixTrack;
|
||||
import com.sap.sailing.domain.tracking.GPSTrackListener;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.RaceChangeListener;
|
||||
@@ -249,16 +250,14 @@ DynamicTrackedRace, GPSTrackListener<Competitor, GPSFixMoving> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the listener wants to be notified about the wind fixes already loaded, this method will obtain the read lock
|
||||
* of the {@link #getLoadingFromStoresLock() wind loading lock}, locking against the wind loading thread which uses the
|
||||
* corresponding write lock. This ensures that either all wind fixes have been loaded already or that wind loading
|
||||
* hasn't started yet.
|
||||
*/
|
||||
@Override
|
||||
public void addListener(RaceChangeListener listener, final boolean notifyAboutWindFixesAlreadyLoaded) {
|
||||
public void addListener(RaceChangeListener listener, final boolean notifyAboutWindFixesAlreadyLoaded,
|
||||
final boolean notifyAboutGPSFixesAlreadyLoaded) {
|
||||
if (notifyAboutWindFixesAlreadyLoaded) {
|
||||
LockUtil.lockForRead(getLoadingFromStoresLock());
|
||||
LockUtil.lockForRead(getLoadingFromWindStoreLock());
|
||||
}
|
||||
if (notifyAboutGPSFixesAlreadyLoaded) {
|
||||
LockUtil.lockForRead(getLoadingFromGPSFixStoreLock());
|
||||
}
|
||||
try {
|
||||
addListener(listener);
|
||||
@@ -282,9 +281,34 @@ DynamicTrackedRace, GPSTrackListener<Competitor, GPSFixMoving> {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (notifyAboutGPSFixesAlreadyLoaded) {
|
||||
for (Mark mark : getMarks()) {
|
||||
GPSFixTrack<Mark, GPSFix> markTrack = getOrCreateTrack(mark);
|
||||
markTrack.lockForRead();
|
||||
try {
|
||||
for (GPSFix fix : markTrack.getRawFixes()) {
|
||||
listener.markPositionChanged(fix, mark);
|
||||
}
|
||||
} finally {
|
||||
markTrack.unlockAfterRead();
|
||||
}
|
||||
}
|
||||
|
||||
for (Competitor competitor : getRace().getCompetitors()) {
|
||||
GPSFixTrack<Competitor, GPSFixMoving> competitorTrack = getTrack(competitor);
|
||||
competitorTrack.lockForRead();
|
||||
try {
|
||||
for (GPSFixMoving fix : competitorTrack.getRawFixes()) {
|
||||
listener.competitorPositionChanged(fix, competitor);
|
||||
}
|
||||
} finally {
|
||||
competitorTrack.unlockAfterRead();
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (notifyAboutWindFixesAlreadyLoaded) {
|
||||
LockUtil.unlockAfterRead(getLoadingFromStoresLock());
|
||||
LockUtil.unlockAfterRead(getLoadingFromWindStoreLock());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+41
-23
@@ -230,22 +230,31 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
private enum LoadingFromStoresState { NOT_STARTED, RUNNING, FINISHED };
|
||||
|
||||
/**
|
||||
* The constructor loads wind fixes from the {@link #windStore} and GPS fixes from the {@link #gpsFixStore}
|
||||
* asynchronously. When completed, this flag is set to <code>true</code>, and all threads currently waiting on this
|
||||
* object are notified.
|
||||
* The constructor loads wind fixes from the {@link #windStore} asynchronously.
|
||||
* When completed all threads currently waiting on this object are notified.
|
||||
*/
|
||||
private LoadingFromStoresState loadingFromStoresCompleted;
|
||||
private LoadingFromStoresState loadingFromWindStoreState;
|
||||
|
||||
/**
|
||||
* @see #loadingFromWindStoreState but for GPSFixStore
|
||||
*/
|
||||
private LoadingFromStoresState loadingFromGPSFixStoreState;
|
||||
|
||||
private transient CrossTrackErrorCache crossTrackErrorCache;
|
||||
|
||||
private final GPSFixStore gpsFixStore;
|
||||
|
||||
/**
|
||||
* Wind and GPS fix loading is started in a background thread during object construction. If a client needs to
|
||||
* ensure that wind / GPS fix loading either has terminated or has not yet begun, it can obtain the read lock of
|
||||
* this lock. The wind / GPS fix loading procedure will obtain the write lock before it starts loading wind fixes.
|
||||
* Wind and loading is started in a background thread during object construction. If a client needs to
|
||||
* ensure that wind loading either has terminated or has not yet begun, it can obtain the read lock of
|
||||
* this lock. The wind loading procedure will obtain the write lock before it starts loading wind fixes.
|
||||
*/
|
||||
private final NamedReentrantReadWriteLock loadingFromStoresLock;
|
||||
private final NamedReentrantReadWriteLock loadingFromWindStoreLock;
|
||||
|
||||
/**
|
||||
* @see #loadingFromWindStoreLock but for GPSFixStore
|
||||
*/
|
||||
private final NamedReentrantReadWriteLock loadingFromGPSFixStoreLock;
|
||||
|
||||
private final Map<Iterable<MarkPassing>, NamedReentrantReadWriteLock> locksForMarkPassings;
|
||||
|
||||
@@ -257,7 +266,9 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
attachedRaceLogs = new HashMap<>();
|
||||
this.status = new TrackedRaceStatusImpl(TrackedRaceStatusEnum.PREPARED, 0.0);
|
||||
this.statusNotifier = new Object[0];
|
||||
this.loadingFromStoresLock = new NamedReentrantReadWriteLock("Loading from stores lock for tracked race "
|
||||
this.loadingFromWindStoreLock = new NamedReentrantReadWriteLock("Loading from wind store lock for tracked race "
|
||||
+ race.getName(), /* fair */ false);
|
||||
this.loadingFromGPSFixStoreLock = new NamedReentrantReadWriteLock("Loading from GPSFix store lock for tracked race "
|
||||
+ race.getName(), /* fair */ false);
|
||||
this.cacheInvalidationTimerLock = new Object();
|
||||
this.updateCount = 0;
|
||||
@@ -314,15 +325,15 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
MarkPassingByTimeComparator.INSTANCE));
|
||||
}
|
||||
markPassingsTimes = new ArrayList<Pair<Waypoint, Pair<TimePoint, TimePoint>>>();
|
||||
loadingFromStoresCompleted = LoadingFromStoresState.NOT_STARTED;
|
||||
loadingFromWindStoreState = LoadingFromStoresState.NOT_STARTED;
|
||||
// When this tracked race is to be serialized, wait for the loading from stores to complete.
|
||||
new Thread("Mongo wind loader for tracked race " + getRace().getName()) {
|
||||
@Override
|
||||
public void run() {
|
||||
LockUtil.lockForRead(getSerializationLock());
|
||||
LockUtil.lockForWrite(getLoadingFromStoresLock());
|
||||
LockUtil.lockForWrite(getLoadingFromWindStoreLock());
|
||||
synchronized (TrackedRaceImpl.this) {
|
||||
loadingFromStoresCompleted = LoadingFromStoresState.RUNNING; // indicates that the serialization lock is now safely held
|
||||
loadingFromWindStoreState = LoadingFromStoresState.RUNNING; // indicates that the serialization lock is now safely held
|
||||
TrackedRaceImpl.this.notifyAll();
|
||||
}
|
||||
try {
|
||||
@@ -335,10 +346,11 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
|
||||
} finally {
|
||||
synchronized (TrackedRaceImpl.this) {
|
||||
loadingFromStoresCompleted = LoadingFromStoresState.FINISHED;
|
||||
loadingFromWindStoreState = LoadingFromStoresState.FINISHED;
|
||||
TrackedRaceImpl.this.notifyAll();
|
||||
loadingFromWindStoreState.notifyAll();
|
||||
}
|
||||
LockUtil.unlockAfterWrite(getLoadingFromStoresLock());
|
||||
LockUtil.unlockAfterWrite(getLoadingFromWindStoreLock());
|
||||
LockUtil.unlockAfterRead(getSerializationLock());
|
||||
}
|
||||
}
|
||||
@@ -356,7 +368,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
competitorRankingsLocks = new HashMap<TimePoint, NamedReentrantReadWriteLock>();
|
||||
// now wait until wind loading has at least started; then we know that the serialization lock is safely held by the loader
|
||||
synchronized (this) {
|
||||
while (loadingFromStoresCompleted != LoadingFromStoresState.FINISHED) {
|
||||
while (loadingFromWindStoreState != LoadingFromStoresState.FINISHED) {
|
||||
try {
|
||||
this.wait();
|
||||
} catch (InterruptedException e) {
|
||||
@@ -418,7 +430,8 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
|
||||
@Override
|
||||
public synchronized void waitUntilLoadingFromStoresComplete() throws InterruptedException {
|
||||
while (loadingFromStoresCompleted != LoadingFromStoresState.FINISHED) {
|
||||
while (loadingFromWindStoreState != LoadingFromStoresState.FINISHED ||
|
||||
loadingFromGPSFixStoreState != LoadingFromStoresState.FINISHED) {
|
||||
wait();
|
||||
}
|
||||
}
|
||||
@@ -2349,15 +2362,15 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
if (raceLog != null) {
|
||||
this.attachedRaceLogs.put(raceLog.getId(), raceLog);
|
||||
// Use the new race log, that possibly contains device mappings, to load GPSFix tracks from the DB
|
||||
loadingFromStoresCompleted = LoadingFromStoresState.NOT_STARTED;
|
||||
loadingFromGPSFixStoreState = LoadingFromStoresState.NOT_STARTED;
|
||||
// When this tracked race is to be serialized, wait for the loading from stores to complete.
|
||||
new Thread("Mongo mark and competitor track loader for tracked race " + getRace().getName()) {
|
||||
@Override
|
||||
public void run() {
|
||||
LockUtil.lockForRead(getSerializationLock());
|
||||
LockUtil.lockForWrite(getLoadingFromStoresLock());
|
||||
LockUtil.lockForWrite(getLoadingFromWindStoreLock());
|
||||
synchronized (TrackedRaceImpl.this) {
|
||||
loadingFromStoresCompleted = LoadingFromStoresState.RUNNING; // indicates that the serialization
|
||||
loadingFromGPSFixStoreState = LoadingFromStoresState.RUNNING; // indicates that the serialization
|
||||
// lock is now safely held
|
||||
TrackedRaceImpl.this.notifyAll();
|
||||
}
|
||||
@@ -2378,10 +2391,11 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
|
||||
} finally {
|
||||
synchronized (TrackedRaceImpl.this) {
|
||||
loadingFromStoresCompleted = LoadingFromStoresState.FINISHED;
|
||||
loadingFromGPSFixStoreState = LoadingFromStoresState.FINISHED;
|
||||
TrackedRaceImpl.this.notifyAll();
|
||||
loadingFromGPSFixStoreState.notifyAll();
|
||||
}
|
||||
LockUtil.unlockAfterWrite(getLoadingFromStoresLock());
|
||||
LockUtil.unlockAfterWrite(getLoadingFromWindStoreLock());
|
||||
LockUtil.unlockAfterRead(getSerializationLock());
|
||||
}
|
||||
}
|
||||
@@ -2544,8 +2558,12 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
return null;
|
||||
}
|
||||
|
||||
protected NamedReentrantReadWriteLock getLoadingFromStoresLock() {
|
||||
return loadingFromStoresLock;
|
||||
protected NamedReentrantReadWriteLock getLoadingFromWindStoreLock() {
|
||||
return loadingFromWindStoreLock;
|
||||
}
|
||||
|
||||
protected NamedReentrantReadWriteLock getLoadingFromGPSFixStoreLock() {
|
||||
return loadingFromGPSFixStoreLock;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+2
-1
@@ -221,7 +221,8 @@ public class MockedTrackedRace implements DynamicTrackedRace {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(RaceChangeListener listener, boolean notifyAboutWindFixesAlreadyLoaded) {
|
||||
public void addListener(RaceChangeListener listener, boolean notifyAboutWindFixesAlreadyLoaded,
|
||||
boolean notifyAboutGPSFixesAlreadyLoaded) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -1159,7 +1159,7 @@ public class RacingEventServiceImpl implements RacingEventServiceWithTestSupport
|
||||
}
|
||||
TrackedRaceReplicator trackedRaceReplicator = new TrackedRaceReplicator(trackedRace);
|
||||
trackedRaceReplicators.put(trackedRace, trackedRaceReplicator);
|
||||
trackedRace.addListener(trackedRaceReplicator, /* fire wind already loaded */ true);
|
||||
trackedRace.addListener(trackedRaceReplicator, /* fire wind already loaded */ true, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -327,7 +327,8 @@ public class DummyTrackedRace extends TrackedRaceWithWindEssentials {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(RaceChangeListener listener, boolean notifyAboutWindFixesAlreadyLoaded) {
|
||||
public void addListener(RaceChangeListener listener, boolean notifyAboutWindFixesAlreadyLoaded,
|
||||
boolean notifyAboutGPSFixesAlreadyLoaded) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user