moved logic for starting wind tracking to RacingEventServiceImpl.addRace(Regatta, RaceTrackingConnectivityParameters);

Change-Id: I92c7623d64569596868767ba87aa93870e5d6130
This commit is contained in:
Axel Uhl committed 2016-12-30 12:21:17 +01:00
1 parent f9b4ac7b50
commit 07b4677b8b
5 files changed
+44 -71

No files matched your search

@@ -3,6 +3,7 @@ package com.sap.sailing.domain.tracking;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -37,11 +38,6 @@ public abstract class AbstractRaceTrackerBaseImpl implements RaceTracker {
/**
* Template stop method for subclasses.
*
* @param preemptive
* @throws MalformedURLException
* @throws IOException
* @throws InterruptedException
*/
protected void onStop(boolean preemptive) throws MalformedURLException, IOException, InterruptedException {
}
@@ -58,21 +54,37 @@ public abstract class AbstractRaceTrackerBaseImpl implements RaceTracker {
@Override
public void add(RaceCreationListener listener) {
raceCreationListeners.add(listener);
final RaceDefinition race = getRace();
if (race != null) {
final RaceDefinition race;
synchronized (raceCreationListeners) {
race = getRace();
if (race == null) {
raceCreationListeners.add(listener);
}
}
if (race != null) { // listener hasn't been added above; notify immediately
listener.onRaceCreated(this);
remove(listener);
}
}
@Override
public void remove(RaceCreationListener listener) {
raceCreationListeners.remove(listener);
synchronized (raceCreationListeners) {
raceCreationListeners.remove(listener);
}
}
/**
* Notifies all {@link RaceCreationListener}s registered and removes them. Must be called
* after {@link #getRace()} has started returning a valid, non-{@code null} race.
*/
protected void notifyRaceCreationListeners() {
raceCreationListeners.forEach(l->l.onRaceCreated(this));
assert getRace() != null;
final Set<RaceCreationListener> listenersToNotify;
synchronized (raceCreationListeners) {
listenersToNotify = new HashSet<>(raceCreationListeners);
raceCreationListeners.clear();
}
listenersToNotify.forEach(l->l.onRaceCreated(this));
}
@Override
@@ -121,6 +121,13 @@ public interface RaceTracker {
*/
void remove(RaceTracker.Listener listener);
/**
* Adds a listener that will be {@link RaceCreationListener#onRaceCreated(RaceTracker) notified} when the
* {@link #getRace()} method starts returning a valid, non-{@code null} race. The listener will be notified
* immediately if {@link #getRace()} already yields a valid {@link RaceDefinition} when calling this method so
* that the listener will be notified at least once. The listener will automatically be removed after it has been
* notified.
*/
void add(RaceTracker.RaceCreationListener listener);
void remove(RaceTracker.RaceCreationListener listener);
@@ -11,6 +11,12 @@ import com.sap.sailing.domain.common.RegattaIdentifier;
public interface TrackerManager {
/**
* Creates a {@link RaceTracker} based on the {@code params}. If the {@code params} request
* {@link RaceTrackingConnectivityParameters#isTrackWind() wind tracking}, a callback is
* {@link RaceTracker#add(com.sap.sailing.domain.tracking.RaceTracker.RaceCreationListener) registered}
* with the {@link RaceTracker} that, when the race has been created by the tracker, will
* start wind tracking.
*
* @param regattaToAddTo
* if <code>null</code> or no regatta by that identifier is found, the regatta into which the race has
* previously been loaded will be looked up; if found, the race will be loaded into that regatta;
@@ -283,7 +283,6 @@ import com.sap.sailing.domain.tracking.LineDetails;
import com.sap.sailing.domain.tracking.Maneuver;
import com.sap.sailing.domain.tracking.MarkPassing;
import com.sap.sailing.domain.tracking.MarkPassingManeuver;
import com.sap.sailing.domain.tracking.RaceHandle;
import com.sap.sailing.domain.tracking.RaceTracker;
import com.sap.sailing.domain.tracking.Track;
import com.sap.sailing.domain.tracking.TrackedLeg;
@@ -1131,7 +1130,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
} else {
effectiveStoredURI = storedURI;
}
final RaceHandle raceHandle = getTracTracAdapter().addTracTracRace(getService(), regattaToAddTo,
getTracTracAdapter().addTracTracRace(getService(), regattaToAddTo,
record.getParamURL(), effectiveLiveURI == null ? null : new URI(effectiveLiveURI),
new URI(effectiveStoredURI), new URI(courseDesignUpdateURI),
new MillisecondsTimePoint(record.getTrackingStartTime().asMillis()),
@@ -1140,18 +1139,6 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
offsetToStartTimeOfSimulatedRace, useInternalMarkPassingAlgorithm, tracTracUsername,
tracTracPassword, record.getRaceStatus(), record.getRaceVisibility(), trackWind,
correctWindByDeclination);
if (trackWind) {
new Thread("Wind tracking starter for race " + record.getEventName() + "/" + record.getName()) {
public void run() {
try {
startTrackingWind(raceHandle, correctWindByDeclination,
RaceTracker.TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}.start();
}
}
}
@@ -1200,25 +1187,6 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
}
}
/**
* @param timeoutInMilliseconds
* eventually passed to {@link RaceHandle#getRace(long)}. If the race definition can be obtained within
* this timeout, wind for the race will be tracked; otherwise, the method returns without taking any
* effect.
*/
private void startTrackingWind(RaceHandle raceHandle, boolean correctByDeclination, long timeoutInMilliseconds) {
Regatta regatta = raceHandle.getRegatta();
if (regatta != null) {
RaceDefinition race = raceHandle.getRace(timeoutInMilliseconds);
if (race != null) {
getService().startTrackingWind(regatta, race, correctByDeclination);
} else {
log("RaceDefinition wasn't received within " + timeoutInMilliseconds + "ms for a race in regatta "
+ regatta.getName() + ". Aborting wait; no wind tracking for this race.");
}
}
}
@Override
public WindInfoForRaceDTO getRawWindFixes(RegattaAndRaceIdentifier raceIdentifier, Collection<WindSource> windSources) {
WindInfoForRaceDTO result = null;
@@ -2817,22 +2785,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
startList = getSwissTimingAdapter().readStartListForRace(rr.raceId, regattaResults);
}
// now read the entry list for the race from the result
final RaceHandle raceHandle = getSwissTimingAdapter().addSwissTimingRace(getService(), regattaToAddTo,
getSwissTimingAdapter().addSwissTimingRace(getService(), regattaToAddTo,
rr.raceId, rr.getName(), raceDescription, boatClass, hostname, port, startList,
getRaceLogStore(), getRegattaLogStore(),
RaceTracker.TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS, useInternalMarkPassingAlgorithm, trackWind, correctWindByDeclination);
if (trackWind) {
new Thread("Wind tracking starter for race " + rr.raceId + "/" + rr.getName()) {
public void run() {
try {
startTrackingWind(raceHandle, correctWindByDeclination,
RaceTracker.TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}.start();
}
}
}
@@ -5744,19 +5700,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
Leaderboard leaderboard = getLeaderboardByName(leaderboardName);
RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName);
Fleet fleet = raceColumn.getFleetByName(fleetName);
final RaceHandle raceHandle = getRaceLogTrackingAdapter().startTracking(getService(), leaderboard, raceColumn, fleet, trackWind, correctWindByDeclination);
if (raceHandle != null && trackWind) {
new Thread("Wind tracking starter for race " + leaderboardName + "/" + raceColumnName + "/" + fleetName) {
public void run() {
try {
startTrackingWind(raceHandle, correctWindByDeclination,
RaceTracker.TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}.start();
}
getRaceLogTrackingAdapter().startTracking(getService(), leaderboard, raceColumn, fleet, trackWind, correctWindByDeclination);
}
@Override
@@ -1463,9 +1463,13 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
} else {
cacheAndReplicateDefaultRegatta(tracker.getRegatta());
}
// TODO bug 2: we need to link the params to the TrackedRace / RaceDefinition such that when the RaceDefinition is removed using removeRace(Regatta, RaceDefinition) then we know which params to remove from the restore store again
getMongoObjectFactory().addConnectivityParametersForRaceToRestore(params);
// ensure that as soon as the RaceDefinition becomes available, the connectivity params are linked to it in connectivityParametersByRace
tracker.add((RaceTracker t) -> rememberConnectivityParametersForRace(t));
if (params.isTrackWind()) {
// start wind tracking if requested, as soon as the RaceDefinition becomes available
tracker.add((RaceTracker t) -> startTrackingWind(regattaWithName, t.getRace(), params.isCorrectWindDirectionByMagneticDeclination()));
}
} else {
logger.warning("Race tracker with ID "+trackerID+" already found; not tracking twice to avoid race duplication");
WindStore existingTrackersWindStore = tracker.getWindStore();