refactored RaceTracker such that getRace[Identifier]s() is now getRace[Identifier](), alluding to the always-singular aspect of RaceTracker/RaceHandle

Change-Id: I50d202122c3021dd2f852762688d762fb3806d99
This commit is contained in:
Axel Uhl committed 2016-12-29 18:10:36 +01:00
1 parent 19d112115b
commit 704e4e2a64
13 files changed
+92 -138

No files matched your search

@@ -7,7 +7,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -195,13 +194,13 @@ public class RaceLogRaceTracker extends AbstractRaceTrackerBaseImpl {
}
@Override
public Set<RaceDefinition> getRaces() {
return trackedRace == null ? null : Collections.singleton(trackedRace.getRace());
public RaceDefinition getRace() {
return trackedRace == null ? null : trackedRace.getRace();
}
@Override
public Set<RegattaAndRaceIdentifier> getRaceIdentifiers() {
return trackedRace == null ? null : Collections.singleton(trackedRace.getRaceIdentifier());
public RegattaAndRaceIdentifier getRaceIdentifier() {
return trackedRace == null ? null : trackedRace.getRaceIdentifier();
}
@Override
@@ -1,7 +1,5 @@
package com.sap.sailing.domain.racelogtracking.impl;
import java.util.Set;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
@@ -28,12 +26,7 @@ public class RaceLogRacesHandle implements RaceHandle {
@Override
public RaceDefinition getRace(long timeoutInMilliseconds) {
long start = System.currentTimeMillis();
Set<RaceDefinition> raceDefs = tracker.getRaces();
RaceDefinition result = null;
if (raceDefs != null && !raceDefs.isEmpty()) {
result = tracker.getRaces().iterator().next();
}
RaceDefinition result = tracker.getRace();
boolean interrupted = false;
synchronized (tracker) {
while ((timeoutInMilliseconds == -1 || System.currentTimeMillis() - start < timeoutInMilliseconds)
@@ -47,13 +40,13 @@ public class RaceLogRacesHandle implements RaceHandle {
tracker.wait(timeToWait);
}
}
result = tracker.getRaces().isEmpty() ? null : tracker.getRaces().iterator().next();
result = tracker.getRace();
} catch (InterruptedException e) {
interrupted = true;
}
}
}
return result == null ? null : result;
return result;
}
@Override
@@ -10,7 +10,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NavigableSet;
import java.util.Set;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -176,9 +175,8 @@ public class SwissTimingRaceTrackerImpl extends AbstractRaceTrackerImpl
}
@Override
public Set<RaceDefinition> getRaces() {
final Set<RaceDefinition> emptySet = Collections.emptySet();
return race==null?emptySet:Collections.singleton(race);
public RaceDefinition getRace() {
return race;
}
@Override
@@ -1,8 +1,5 @@
package com.sap.sailing.domain.swisstimingreplayadapter.impl;
import java.util.Collections;
import java.util.Set;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
@@ -48,17 +45,11 @@ public class SwissTimingReplayConnectivityParameters implements RaceTrackingConn
}
@Override
public Set<RaceDefinition> getRaces() {
public RaceDefinition getRace() {
RaceDefinition race;
try {
race = listener.getRaceDefinition(raceID, 1 /* very short timeout */);
final Set<RaceDefinition> result;
if (race == null) {
result = Collections.emptySet();
} else {
result = Collections.singleton(race);
}
return result;
return race;
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
@@ -195,7 +195,7 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl
private final Set<Receiver> receivers;
private final DomainFactory domainFactory;
private final WindStore windStore;
private final Set<RaceDefinition> races;
private RaceDefinition race;
private final DynamicTrackedRegatta trackedRegatta;
private TrackedRaceStatus lastStatus;
private Map<Object, Util.Pair<Integer, Float>> lastProgressPerID;
@@ -324,7 +324,7 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl
this.tractracEvent = tractracRace.getEvent();
this.id = createID(paramURL, liveURI, storedURI);
isLiveTracking = liveURI != null;
this.races = new HashSet<RaceDefinition>();
this.race = null; // no race received yet
this.domainFactory = domainFactory;
this.lastProgressPerID = new HashMap<>();
if (offsetToStartTimeOfSimulatedRace != null) {
@@ -375,8 +375,8 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl
public void updateRace(IRace race) {
if (Util.equalsWithNull(race, TracTracRaceTrackerImpl.this.tractracRace)) {
int delayToLiveInMillis = race.getLiveDelay()*1000;
for (RaceDefinition raceDefinition : getRaces()) {
DynamicTrackedRace trackedRace = getTrackedRegatta().getExistingTrackedRace(raceDefinition);
if (getRace() != null) {
DynamicTrackedRace trackedRace = getTrackedRegatta().getExistingTrackedRace(getRace());
if (trackedRace != null) {
trackedRace.setDelayToLiveInMillis(delayToLiveInMillis);
}
@@ -524,8 +524,8 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl
}
@Override
public Set<RaceDefinition> getRaces() {
return races;
public RaceDefinition getRace() {
return race;
}
protected void addListenersForStoredDataAndStartController(Iterable<Receiver> listenersForStoredData) {
@@ -581,8 +581,8 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl
* @see #updateStatusOfTrackedRace(DynamicTrackedRace)
*/
private void updateStatusOfTrackedRaces() {
for (RaceDefinition race : getRaces()) {
DynamicTrackedRace trackedRace = getTrackedRegatta().getExistingTrackedRace(race);
if (getRace() != null) {
DynamicTrackedRace trackedRace = getTrackedRegatta().getExistingTrackedRace(getRace());
if (trackedRace != null) {
updateStatusOfTrackedRace(trackedRace);
}
@@ -637,7 +637,7 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl
}
}
}
logger.info("Stored data progress in tracker "+getID()+" for race(s) "+getRaces()+": "+progress);
logger.info("Stored data progress in tracker "+getID()+" for race(s) "+getRace()+": "+progress);
lastStatus = new TrackedRaceStatusImpl(TrackedRaceStatusEnum.LOADING, progress);
if (progress==1.0) {
new AbstractLoadingQueueDoneCallBack(receivers) {
@@ -653,27 +653,27 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl
}
@Override
public void addRaceDefinition(RaceDefinition race, DynamicTrackedRace trackedRace) {
races.add(race);
public void addRaceDefinition(final RaceDefinition race, final DynamicTrackedRace trackedRace) {
this.race = race;
updateStatusOfTrackedRace(trackedRace);
}
@Override
public void gotLiveDataEvent(ILiveDataEvent liveDataEvent) {
logger.info("Status change in tracker "+getID()+" for race(s) "+getRaces()+": "+liveDataEvent);
logger.info("Status change in tracker "+getID()+" for race(s) "+getRace()+": "+liveDataEvent);
}
@Override
public void gotStoredDataEvent(IStoredDataEvent storedDataEvent) {
logger.info("Status change in tracker "+getID()+" for race(s) "+getRaces()+": "+storedDataEvent);
logger.info("Status change in tracker "+getID()+" for race(s) "+getRace()+": "+storedDataEvent);
switch (storedDataEvent.getType()) {
case Begin:
logger.info("Stored data begin in tracker "+getID()+" for race(s) "+getRaces());
logger.info("Stored data begin in tracker "+getID()+" for race(s) "+getRace());
lastStatus = new TrackedRaceStatusImpl(TrackedRaceStatusEnum.LOADING, 0);
updateStatusOfTrackedRaces();
break;
case End:
logger.info("Stored data end in tracker "+getID()+" for race(s) "+getRaces());
logger.info("Stored data end in tracker "+getID()+" for race(s) "+getRace());
if (isLiveTracking) {
lastStatus = new TrackedRaceStatusImpl(TrackedRaceStatusEnum.TRACKING, 1);
updateStatusOfTrackedRaces();
@@ -683,14 +683,14 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl
storedDataProgress(storedDataEvent.getProgress());
break;
case Error:
logger.warning("Error with stored data in tracker "+getID()+" for race(s) "+getRaces()+": "+storedDataEvent.getError());
logger.warning("Error with stored data in tracker "+getID()+" for race(s) "+getRace()+": "+storedDataEvent.getError());
break;
}
}
@Override
public void stopped(Object o) {
logger.info("stopped TracTrac tracking in tracker " + getID() + " for " + getRaces() + " while in status "
logger.info("stopped TracTrac tracking in tracker " + getID() + " for " + getRace() + " while in status "
+ lastStatus);
new AbstractLoadingQueueDoneCallBack(receivers) {
@Override
@@ -699,13 +699,13 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl
updateStatusOfTrackedRaces();
if (!stopped) {
try {
for (RaceDefinition race : getRaces()) {
if (getRace() != null) {
// See also bug 1517; with TracAPI we assume that when stopped(IEvent) is called by the
// TracAPI then
// all subscriptions have received all their data and it's therefore safe to stop all
// subscriptions
// at this point without missing any data.
trackedRegattaRegistry.stopTracking(regatta, race);
trackedRegattaRegistry.stopTracking(regatta, getRace());
}
} catch (InterruptedException | IOException e) {
logger.log(Level.INFO, "Interrupted while trying to stop tracker " + this, e);
@@ -1,8 +1,5 @@
package com.sap.sailing.domain.tracking;
import java.util.HashSet;
import java.util.Set;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
@@ -14,16 +11,18 @@ public abstract class AbstractRaceTrackerImpl extends AbstractRaceTrackerBaseImp
}
@Override
public Set<RegattaAndRaceIdentifier> getRaceIdentifiers() {
Set<RegattaAndRaceIdentifier> result = new HashSet<RegattaAndRaceIdentifier>();
final Set<RaceDefinition> races = getRaces();
if (races != null) {
for (RaceDefinition race : races) {
TrackedRace trackedRace = getTrackedRegatta().getTrackedRace(race);
if (trackedRace != null) {
result.add(trackedRace.getRaceIdentifier());
}
public RegattaAndRaceIdentifier getRaceIdentifier() {
final RegattaAndRaceIdentifier result;
final RaceDefinition race = getRace();
if (race != null) {
TrackedRace trackedRace = getTrackedRegatta().getTrackedRace(race);
if (trackedRace != null) {
result = trackedRace.getRaceIdentifier();
} else {
result = null;
}
} else {
result = null;
}
return result;
}
@@ -6,7 +6,7 @@ import com.sap.sailing.domain.base.RaceDefinition;
* Particularly the way the TracTrac connector was originally designed, the set of {@link RaceDefinition} objects
* received from connecting to a particular TracTrac event is not known up-front. We even wait (for historic reasons,
* because the course definition used to be immutable) for the course to be received before creating the
* {@link RaceDefinition} object. Therefore, a {@link RaceTracker#getRaces()} call needs to understand which
* {@link RaceDefinition} object. Therefore, a {@link RaceTracker#getRace()} call needs to understand which
* {@link RaceDefinition} objects were created so far.<p>
*
* This interface is used particularly by the race course receiver in the TracTrac case to update a tracker's set
@@ -3,7 +3,6 @@ package com.sap.sailing.domain.tracking;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Map;
import java.util.Set;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
@@ -13,7 +12,7 @@ import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
* Centerpiece of a tracking adapter. A tracker is responsible for receiving tracking data for one or more
* {@link RaceDefinition races} that are {@link Regatta#getAllRaces() part of} a common {@link #getRegatta() Event}. Some
* tracker architectures may not be able to deliver all data for the {@link RaceDefinition} when created or started.
* Therefore, {@link #getRaces()} may return <code>null</code> if the race information hasn't been received by the
* Therefore, {@link #getRace()} may return <code>null</code> if the race information hasn't been received by the
* tracker yet. Through the {@link RaceHandle} returned by {@link #getRaceHandle()} it is also possible to perform a
* {@link RaceHandle#getRace() blocking get} for the race tracked by this tracker.
* <p>
@@ -56,15 +55,15 @@ public interface RaceTracker {
com.sap.sailing.domain.base.Regatta getRegatta();
/**
* Returns the races being tracked by this tracker. Non-blocking call that returns <code>null</code> or an empty set
* Returns the races being tracked by this tracker. Non-blocking call that returns <code>null</code>
* if the {@link RaceDefinition} hasn't been created yet, e.g., because the course definition
* hasn't been received yet or the listener for receiving course information hasn't been registered (yet). Also
* returns races that have been removed from containing structures which may lead this tracker to no longer update
* returns a race that may have been removed from containing structures which may lead this tracker to no longer update
* their {@link TrackedRace} with new data.
*/
Set<RaceDefinition> getRaces();
RaceDefinition getRace();
Set<RegattaAndRaceIdentifier> getRaceIdentifiers();
RegattaAndRaceIdentifier getRaceIdentifier();
RaceHandle getRaceHandle();
@@ -77,7 +77,7 @@ public class TrackRaceBoatCompetitorMetadataReplicationTest extends AbstractServ
private void startTracking() throws Exception, InterruptedException {
startTrackingOnMaster();
waitForTrackRaceReplicationTrigger();
raceIdentifier = racesHandle.getRaceTracker().getRaceIdentifiers().iterator().next();
raceIdentifier = racesHandle.getRaceTracker().getRaceIdentifier();
masterTrackedRace = master.getTrackedRace(raceIdentifier);
}
@@ -95,7 +95,7 @@ public class TrackRaceReplicationTest extends AbstractServerReplicationTest {
private void startTracking() throws Exception, InterruptedException {
startTrackingOnMaster();
waitForTrackRaceReplicationTrigger();
raceIdentifier = racesHandle.getRaceTracker().getRaceIdentifiers().iterator().next();
raceIdentifier = racesHandle.getRaceTracker().getRaceIdentifier();
masterTrackedRace = master.getTrackedRace(raceIdentifier);
}
@@ -2,11 +2,11 @@ package com.sap.sailing.server.test;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Set;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.RegattaNameAndRaceName;
import com.sap.sailing.domain.tracking.AbstractRaceTrackerBaseImpl;
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
import com.sap.sailing.domain.tracking.RaceHandle;
@@ -16,20 +16,18 @@ public class RaceTrackerMock extends AbstractRaceTrackerBaseImpl {
private Long id;
private Regatta regatta;
private Set<RaceDefinition> raceDefinitions;
private RaceDefinition raceDefinition;
private boolean isTracking;
public RaceTrackerMock() {
super(null);
}
public RaceTrackerMock(Long id, Regatta regatta, Set<RaceDefinition> raceDefinitions, boolean isTracking) {
public RaceTrackerMock(Long id, Regatta regatta, RaceDefinition raceDefinition, boolean isTracking) {
super(null);
this.id = id;
this.regatta = regatta;
this.raceDefinitions = raceDefinitions;
this.raceDefinition = raceDefinition;
this.isTracking = isTracking;
}
@@ -57,8 +55,8 @@ public class RaceTrackerMock extends AbstractRaceTrackerBaseImpl {
}
@Override
public Set<RaceDefinition> getRaces() {
return raceDefinitions;
public RaceDefinition getRace() {
return raceDefinition;
}
@Override
@@ -83,8 +81,7 @@ public class RaceTrackerMock extends AbstractRaceTrackerBaseImpl {
}
@Override
public Set<RegattaAndRaceIdentifier> getRaceIdentifiers() {
// TODO Auto-generated method stub
return null;
public RegattaAndRaceIdentifier getRaceIdentifier() {
return new RegattaNameAndRaceName(getRegatta().getName(), getRace().getName());
}
}
@@ -96,18 +96,15 @@ public class RaceTrackerStartStopTest {
Set<RaceDefinition> raceDefinitionSetRace1 = new HashSet<RaceDefinition>();
raceDefinitionSetRace1.add(raceDef1);
Set<RaceDefinition> raceDefinitionSetRace2 = new HashSet<RaceDefinition>();
raceDefinitionSetRace2.add(raceDef1);
raceDefinitionSetRace2.add(raceDef2);
Set<RaceDefinition> raceDefinitionSetRace3 = new HashSet<RaceDefinition>();
raceDefinitionSetRace3.add(raceDef1);
raceDefinitionSetRace3.add(raceDef2);
raceDefinitionSetRace3.add(raceDef3);
Long trackerID1 = new Long(1);
Long trackerID2 = new Long(2);
Long trackerID3 = new Long(3);
raceTracker1 = new RaceTrackerMock(new Long(1), regatta, raceDefinitionSetRace1, true);
raceTracker2 = new RaceTrackerMock(new Long(2), regatta, raceDefinitionSetRace2, true);
raceTracker3 = new RaceTrackerMock(new Long(3), regatta, raceDefinitionSetRace3, true);
raceTracker1 = new RaceTrackerMock(new Long(1), regatta, raceDef1, true);
raceTracker2 = new RaceTrackerMock(new Long(2), regatta, raceDef2, true);
raceTracker3 = new RaceTrackerMock(new Long(3), regatta, raceDef3, true);
raceTrackerSet.add(raceTracker1);
raceTrackerSet.add(raceTracker2);
raceTrackerSet.add(raceTracker3);
@@ -194,15 +191,9 @@ public class RaceTrackerStartStopTest {
assertTrue(racingEventService.getRaceTrackersByIDMap().containsValue(raceTracker2));
assertTrue(racingEventService.getRaceTrackersByIDMap().containsValue(raceTracker3));
// The raceTracker should still exist; it shall still contain raceDef1 and raceDef2 because a tracker keeps tracking what it tracks...
assertTrue(raceTracker1.getRaces().contains(raceDef1));
assertEquals(1, raceTracker1.getRaces().size());
assertTrue(raceTracker2.getRaces().contains(raceDef1));
assertTrue(raceTracker2.getRaces().contains(raceDef2));
assertEquals(2, raceTracker2.getRaces().size());
assertTrue(raceTracker3.getRaces().contains(raceDef1));
assertTrue(raceTracker3.getRaces().contains(raceDef2));
assertTrue(raceTracker3.getRaces().contains(raceDef3));
assertEquals(3, raceTracker3.getRaces().size());
assertSame(raceTracker1.getRace(), raceDef1);
assertSame(raceTracker2.getRace(), raceDef2);
assertSame(raceTracker3.getRace(), raceDef3);
}
/**
@@ -222,8 +213,7 @@ public class RaceTrackerStartStopTest {
assertFalse(racingEventService.getRaceTrackersByIDMap().containsValue(raceTracker2));
assertTrue(racingEventService.getRaceTrackersByIDMap().containsValue(raceTracker3));
// The raceTracker 3 should exist, and it should contain all race definitions still
assertTrue(raceTracker3.getRaces().contains(raceDef3));
assertEquals(3, raceTracker3.getRaces().size());
assertSame(raceTracker3.getRace(), raceDef3);
}
}
@@ -94,6 +94,7 @@ import com.sap.sailing.domain.common.DataImportSubProgress;
import com.sap.sailing.domain.common.Distance;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.Position;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.RegattaIdentifier;
import com.sap.sailing.domain.common.RegattaName;
@@ -1229,8 +1230,8 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
Set<RaceTracker> trackers = raceTrackersByRegatta.get(regattaContext);
if (trackers != null) {
for (RaceTracker tracker : trackers) {
final Set<RaceDefinition> races = tracker.getRaces();
if (races != null && races.contains(r)) {
final RaceDefinition race = tracker.getRace();
if (race == r) {
return true;
}
}
@@ -1999,11 +2000,9 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
final Set<RaceTracker> trackersForRegatta = raceTrackersByRegatta.get(regatta);
if (trackersForRegatta != null) {
for (RaceTracker raceTracker : trackersForRegatta) {
final Set<RaceDefinition> races = raceTracker.getRaces();
if (races != null) {
for (RaceDefinition race : races) {
stopTrackingWind(regatta, race);
}
final RaceDefinition race = raceTracker.getRace();
if (race != null) {
stopTrackingWind(regatta, race);
}
raceTracker.stop(/* preemptive */false);
final Object trackerId = raceTracker.getID();
@@ -2066,7 +2065,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
ScheduledFuture<?> task = getScheduler().schedule(new Runnable() {
@Override
public void run() {
if (tracker.getRaces() == null || tracker.getRaces().isEmpty()) {
if (tracker.getRace() == null) {
try {
Regatta regatta = tracker.getRegatta();
logger.log(Level.SEVERE, "RaceDefinition for a race in regatta " + regatta.getName()
@@ -2106,8 +2105,8 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
Iterator<RaceTracker> trackerIter = trackerSet.iterator();
while (trackerIter.hasNext()) {
RaceTracker raceTracker = trackerIter.next();
if (raceTracker.getRaces() != null && raceTracker.getRaces().contains(race)) {
logger.info("Found tracker to stop for races " + raceTracker.getRaces());
if (raceTracker.getRace() == race) {
logger.info("Found tracker to stop for races " + raceTracker.getRace());
raceTracker.stop(/* preemptive */false);
trackerIter.remove();
final Object trackerId = raceTracker.getID();
@@ -2223,6 +2222,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
public void removeRace(Regatta regatta, RaceDefinition race) throws MalformedURLException, IOException,
InterruptedException {
logger.info("Removing the race " + race + "...");
// TODO bug 2, comment #7: this won't work... we need the mapping from TrackedRace or RaceDefinition to RaceTrackingConnectivityParameters
getRaceTrackerByRegattaAndRaceIdentifier(new RegattaNameAndRaceName(regatta.getName(), race.getName()),
tracker->getMongoObjectFactory().removeConnectivityParametersForRaceToRestore(tracker.getConnectivityParams()));
stopAllTrackersForWhichRaceIsLastReachable(regatta, race);
@@ -2294,40 +2294,27 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
Iterator<RaceTracker> trackerIter = raceTrackersByRegatta.get(regatta).iterator();
while (trackerIter.hasNext()) {
RaceTracker raceTracker = trackerIter.next();
if (raceTracker.getRaces() != null && raceTracker.getRaces().contains(race)) {
boolean foundReachableRace = false;
for (RaceDefinition raceTrackedByTracker : raceTracker.getRaces()) {
if (raceTrackedByTracker != race && isReachable(regatta, raceTrackedByTracker)) {
foundReachableRace = true;
break;
}
if (raceTracker.getRace() == race) {
// firstly stop the tracker
raceTracker.stop(/* preemptive */true);
// remove it from the raceTrackers by Regatta
trackerIter.remove();
final Object trackerId = raceTracker.getID();
final NamedReentrantReadWriteLock lock = lockRaceTrackersById(trackerId);
try {
raceTrackersByID.remove(trackerId);
} finally {
unlockRaceTrackersById(trackerId, lock);
}
if (!foundReachableRace) {
// firstly stop the tracker
raceTracker.stop(/* preemptive */true);
// remove it from the raceTrackers by Regatta
trackerIter.remove();
final Object trackerId = raceTracker.getID();
final NamedReentrantReadWriteLock lock = lockRaceTrackersById(trackerId);
try {
raceTrackersByID.remove(trackerId);
} finally {
unlockRaceTrackersById(trackerId, lock);
}
// if the last tracked race was removed, remove the entire regatta
if (raceTrackersByRegatta.get(regatta).isEmpty()) {
stopTracking(regatta);
}
// if the last tracked race was removed, remove the entire regatta
if (raceTrackersByRegatta.get(regatta).isEmpty()) {
stopTracking(regatta);
}
}
}
}
}
private boolean isReachable(Regatta regatta, RaceDefinition race) {
return Util.contains(regatta.getAllRaces(), race);
}
@Override
public void startTrackingWind(Regatta regatta, RaceDefinition race, boolean correctByDeclination) {
for (WindTrackerFactory windTrackerFactory : getWindTrackerFactories()) {
@@ -3611,7 +3598,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
Set<RaceTracker> raceTrackersForRegatta = raceTrackersByRegatta.get(regatta);
if (raceTrackersForRegatta != null) {
for (RaceTracker raceTracker : raceTrackersForRegatta) {
if (raceTracker.getRaceIdentifiers().contains(raceIdentifier)) {
if (Util.equalsWithNull(raceTracker.getRaceIdentifier(), raceIdentifier)) {
callback.accept(raceTracker);
return;
}
@@ -3638,12 +3625,13 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
private void notifyListenersForNewRaceTracker(RaceTracker tracker) {
LockUtil.lockForRead(raceTrackersByRegattaLock);
try {
tracker.getRaceIdentifiers().forEach((raceIdentifier) -> {
final RaceIdentifier raceIdentifier = tracker.getRaceIdentifier();
if (raceIdentifier != null) {
Set<Consumer<RaceTracker>> callbacks = getRaceTrackerCallbacks().remove(raceIdentifier);
if (callbacks != null) {
callbacks.forEach((callback) -> callback.accept(tracker));
}
});
};
} finally {
LockUtil.unlockAfterRead(raceTrackersByRegattaLock);
}