mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-09 13:50:57 +00:00
changed getOrCreateRaceDefinition such that TracTrac connector creates RaceDefinition and TrackedRace;
The problem was that AbstractReceiverWithQueue.getTrackedRace(Race race) waited for the RaceDefinition and started fetching the TrackedRace immediately after it was unblocked by the notifyAll that happened upon creating the RaceDefinition. At this point the RaceCourseReceiver may not have had issued the creation of the TrackedRace. Hence, the lookup of the TrackedRace may have failed, resulting in events being dropped instead of having gotten added to the TrackedRace.
This commit is contained in:
1 parent
e3548080eb
commit
90d887be9a
4 files changed
+45
-13
No files matched your search
+19
-5
@@ -72,9 +72,9 @@ public interface DomainFactory {
|
||||
Team getOrCreateTeam(String name, Nationality nationality);
|
||||
|
||||
/**
|
||||
* Fetch a race definition previously created by a call to {@link #getOrCreateRaceDefinition(Race, Course)}. If no such
|
||||
* Fetch a race definition previously created by a call to {@link #getOrCreateRaceDefinitionAndTrackedRace}. If no such
|
||||
* race definition was created so far, the call blocks until such a definition is provided by a call to
|
||||
* {@link #getOrCreateRaceDefinition(Race, Course)}.
|
||||
* {@link #getOrCreateRaceDefinitionAndTrackedRace}.
|
||||
*/
|
||||
RaceDefinition getAndWaitForRaceDefinition(Race race);
|
||||
|
||||
@@ -132,7 +132,22 @@ public interface DomainFactory {
|
||||
Iterable<Receiver> getUpdateReceivers(DynamicTrackedEvent trackedEvent, Event tractracEvent, WindStore windStore,
|
||||
DynamicRaceDefinitionSet raceDefinitionSetToUpdate);
|
||||
|
||||
RaceDefinition getOrCreateRaceDefinition(Race race, Course course);
|
||||
/**
|
||||
* Creates a {@link RaceDefinition} from a TracTrac {@link Race} and a domain {@link Course} definition. The
|
||||
* resulting {@link RaceDefinition} is <em>not</em> added to any {@link com.sap.sailing.domain.base.Event} yet. It
|
||||
* is added to the internal race cache. The corresponding {@link TrackedRace} object is also created, and the
|
||||
* notification of threads waiting on the race cache such as a blocking {@link #getAndWaitForRaceDefinition(Race)}
|
||||
* happens only <em>after</em> the tracked race has been created. This ensures that waiters for the
|
||||
* {@link RaceDefinition} are guaranteed to obtain a valid, non-<code>null</code> tracked race already immediately
|
||||
* after the notification was sent.
|
||||
*
|
||||
* @param raceDefinitionSetToUpdate
|
||||
* if not <code>null</code>, after creating the {@link TrackedRace}, the {@link RaceDefinition} is
|
||||
* {@link DynamicRaceDefinitionSet#addRaceDefinition(RaceDefinition) added} to that object.
|
||||
*/
|
||||
Pair<RaceDefinition, TrackedRace> getOrCreateRaceDefinitionAndTrackedRace(TrackedEvent trackedEvent, Race race,
|
||||
Course course, WindStore windStore, long millisecondsOverWhichToAverageWind,
|
||||
DynamicRaceDefinitionSet raceDefinitionSetToUpdate);
|
||||
|
||||
/**
|
||||
* The record may be for a single buoy or a gate. If for a gate, the
|
||||
@@ -172,7 +187,7 @@ public interface DomainFactory {
|
||||
|
||||
/**
|
||||
* Fetch the race definition for <code>race</code>. If the race definition hasn't been created yet, the call blocks
|
||||
* until such a definition is provided by a call to {@link #getOrCreateRaceDefinition(Race, Course)}. If
|
||||
* until such a definition is provided by a call to {@link #getOrCreateRaceDefinitionAndTrackedRace}. If
|
||||
* <code>timeoutInMilliseconds</code> milliseconds have passed and the race definition is found not to have shown up
|
||||
* until then, <code>null</code> is returned. The unblocking may be deferred even beyond
|
||||
* <code>timeoutInMilliseconds</code> in case no modifications happen on the set of races cached by this factory.
|
||||
@@ -193,7 +208,6 @@ public interface DomainFactory {
|
||||
* if the {@link TrackedRace} that was removed from the {@link TrackedEvent} was the last one, the
|
||||
* {@link TrackedEvent} is removed such that {@link #getOrCreateTrackedEvent(com.sap.sailing.domain.base.Event)}
|
||||
* will have to create a new one.
|
||||
* @param trackedEventRegistry TODO
|
||||
*/
|
||||
void removeRace(Event tractracEvent, Race tractracRace, TrackedEventRegistry trackedEventRegistry);
|
||||
|
||||
|
||||
+18
-6
@@ -45,6 +45,7 @@ import com.sap.sailing.domain.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.TrackedEvent;
|
||||
import com.sap.sailing.domain.tracking.TrackedEventRegistry;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.WindStore;
|
||||
import com.sap.sailing.domain.tracking.WindTrack;
|
||||
import com.sap.sailing.domain.tracking.impl.GPSFixMovingImpl;
|
||||
@@ -326,24 +327,35 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public RaceDefinition getOrCreateRaceDefinition(Race race, Course course) {
|
||||
public Pair<RaceDefinition, TrackedRace> getOrCreateRaceDefinitionAndTrackedRace(TrackedEvent trackedEvent,
|
||||
Race race, Course course, WindStore windStore, long millisecondsOverWhichToAverageWind,
|
||||
DynamicRaceDefinitionSet raceDefinitionSetToUpdate) {
|
||||
synchronized (raceCache) {
|
||||
RaceDefinition result = raceCache.get(race);
|
||||
if (result == null) {
|
||||
RaceDefinition raceDefinition = raceCache.get(race);
|
||||
if (raceDefinition == null) {
|
||||
Pair<List<Competitor>, BoatClass> competitorsAndDominantBoatClass = getCompetitorsAndDominantBoatClass(race);
|
||||
result = new RaceDefinitionImpl(race.getName(), course, competitorsAndDominantBoatClass.getB(),
|
||||
raceDefinition = new RaceDefinitionImpl(race.getName(), course, competitorsAndDominantBoatClass.getB(),
|
||||
competitorsAndDominantBoatClass.getA());
|
||||
TrackedRace trackedRace = createTrackedRace(trackedEvent, raceDefinition, windStore, millisecondsOverWhichToAverageWind, raceDefinitionSetToUpdate);
|
||||
synchronized (raceCache) {
|
||||
raceCache.put(race, result);
|
||||
raceCache.put(race, raceDefinition);
|
||||
raceCache.notifyAll();
|
||||
}
|
||||
return new Pair<RaceDefinition, TrackedRace>(raceDefinition, trackedRace);
|
||||
} else {
|
||||
throw new RuntimeException("Race "+race.getName()+" already exists");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private TrackedRace createTrackedRace(TrackedEvent trackedEvent, RaceDefinition race, WindStore windStore,
|
||||
long millisecondsOverWhichToAverageWind, DynamicRaceDefinitionSet raceDefinitionSetToUpdate) {
|
||||
return trackedEvent.createTrackedRace(race,
|
||||
windStore, millisecondsOverWhichToAverageWind,
|
||||
/* time over which to average speed: */ race.getBoatClass().getApproximateManeuverDurationInMilliseconds(),
|
||||
raceDefinitionSetToUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<List<Competitor>, BoatClass> getCompetitorsAndDominantBoatClass(Race race) {
|
||||
List<CompetitorClass> competitorClasses = new ArrayList<CompetitorClass>();
|
||||
|
||||
+3
@@ -92,6 +92,9 @@ public class MarkPassingReceiver extends AbstractReceiverWithQueue<RaceCompetito
|
||||
}
|
||||
trackedRace.updateMarkPassings(getDomainFactory().getOrCreateCompetitor(event.getA().getCompetitor()),
|
||||
markPassings);
|
||||
} else {
|
||||
logger.warning("Couldn't find tracked race for race " + event.getA().getRace().getName()
|
||||
+ ". Dropping mark passing event " + event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-2
@@ -12,8 +12,10 @@ import com.sap.sailing.domain.base.Event;
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
import com.sap.sailing.domain.tracking.DynamicRaceDefinitionSet;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedEvent;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.WindStore;
|
||||
import com.sap.sailing.domain.tractracadapter.DomainFactory;
|
||||
import com.sap.sailing.util.Util.Pair;
|
||||
import com.sap.sailing.util.Util.Triple;
|
||||
import com.tractrac.clientmodule.Race;
|
||||
import com.tractrac.clientmodule.Route;
|
||||
@@ -91,11 +93,12 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue<Route, RouteDa
|
||||
} else {
|
||||
logger.log(Level.INFO, "Received course for non-existing race "+event.getC().getName()+". Creating RaceDefinition.");
|
||||
// create race definition
|
||||
RaceDefinition raceDefinition = getDomainFactory().getOrCreateRaceDefinition(event.getC(), course);
|
||||
Pair<RaceDefinition, TrackedRace> raceDefinitionAndTrackedRace = getDomainFactory().getOrCreateRaceDefinitionAndTrackedRace(
|
||||
getTrackedEvent(), event.getC(), course, windStore, millisecondsOverWhichToAverageWind, raceDefinitionSetToUpdate);
|
||||
// add race only if boat class matches
|
||||
RaceDefinition raceDefinition = raceDefinitionAndTrackedRace.getA();
|
||||
if (raceDefinition.getBoatClass() == getTrackedEvent().getEvent().getBoatClass()) {
|
||||
getTrackedEvent().getEvent().addRace(raceDefinition);
|
||||
createTrackedRace(raceDefinition);
|
||||
} else {
|
||||
logger.warning("Not adding race "+raceDefinition+" to event "+getTrackedEvent().getEvent()+
|
||||
" because boat class "+raceDefinition.getBoatClass()+" doesn't match event's boat class "+
|
||||
|
||||
Reference in new issue
Block a user