mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-09 20:41:10 +00:00
using TrackedRegattaRegistry.removeRace to ensure consistent duplicate race removal
Change-Id: I245828fbd6d49f36e0f1f7d240471e5ea709a481
This commit is contained in:
1 parent
de25afd906
commit
de70631ede
11 files changed
+127
-129
No files matched your search
+1
-1
@@ -1620,7 +1620,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
|
||||
DBObject key = new BasicDBObject();
|
||||
key.putAll(paramsPersistenceService.getKey(params));
|
||||
DBObject dbObject = new BasicDBObject();
|
||||
dbObject.putAll(paramsPersistenceService.mapFrom(params));
|
||||
dbObject.putAll(paramsPersistenceService.mapFrom(params)); // TODO bug 4402: should we use the Tracker ID as key here to avoid duplicates?
|
||||
collection.update(key, dbObject, /* upsert */ true, /* multi */ false, WriteConcern.SAFE);
|
||||
} catch (NoCorrespondingServiceRegisteredException e) {
|
||||
logger.log(Level.WARNING, "Couldn't find a persistence service for connectivity parameters of type "+typeIdentifier+
|
||||
|
||||
+5
@@ -47,6 +47,11 @@ public class DummyTrackedRegattaRegistry implements TrackedRegattaRegistry {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRace(Regatta regatta, RaceDefinition race)
|
||||
throws MalformedURLException, IOException, InterruptedException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRaceBeingTracked(Regatta regattaContext, RaceDefinition r) {
|
||||
return false;
|
||||
|
||||
+4
@@ -145,6 +145,10 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest {
|
||||
public void stopTracking(Regatta regatta, RaceDefinition race) throws MalformedURLException, IOException,
|
||||
InterruptedException {
|
||||
}
|
||||
@Override
|
||||
public void removeRace(Regatta regatta, RaceDefinition race)
|
||||
throws MalformedURLException, IOException, InterruptedException {
|
||||
}
|
||||
};
|
||||
LeaderboardDTO leaderboardDTO = leaderboard.getLeaderboardDTO(now, emptySet, /* addOverallDetails */ true, trackedRegattaRegistry, DomainFactory.INSTANCE, /* fillTotalPointsUncorrected */ false);
|
||||
assertNotNull(leaderboardDTO);
|
||||
|
||||
+34
-53
@@ -132,21 +132,19 @@ public interface DomainFactory {
|
||||
* Provides the capability to obtain the {@link WindTrack}s for the different wind sources. A trivial
|
||||
* implementation is {@link EmptyWindStore} which simply provides new, empty tracks. This is always
|
||||
* available but loses track of the wind, e.g., during server restarts.
|
||||
* @param timeoutInMilliseconds TODO
|
||||
*/
|
||||
TracTracRaceTracker createRaceTracker(RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, WindStore windStore, TrackedRegattaRegistry trackedRegattaRegistry,
|
||||
RaceLogResolver raceLogResolver, RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds)
|
||||
throws MalformedURLException, FileNotFoundException, URISyntaxException, CreateModelException, SubscriberInitializationException;
|
||||
throws MalformedURLException, FileNotFoundException, URISyntaxException, CreateModelException, SubscriberInitializationException, IOException, InterruptedException;
|
||||
|
||||
/**
|
||||
* Same as {@link #createRaceTracker(URL, URI, URI, URI, TimePoint, TimePoint, WindStore, TrackedRegattaRegistry)},
|
||||
* only that a predefined {@link Regatta} is used to hold the resulting races.
|
||||
* @param timeoutInMilliseconds TODO
|
||||
*/
|
||||
RaceTracker createRaceTracker(Regatta regatta, RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, WindStore windStore, TrackedRegattaRegistry trackedRegattaRegistry,
|
||||
RaceLogResolver raceLogResolver, RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds)
|
||||
throws MalformedURLException, FileNotFoundException, URISyntaxException, CreateModelException,
|
||||
SubscriberInitializationException;
|
||||
SubscriberInitializationException, IOException, InterruptedException;
|
||||
|
||||
BoatClass getOrCreateBoatClass(String competitorClassName);
|
||||
|
||||
@@ -161,7 +159,6 @@ public interface DomainFactory {
|
||||
* must have been created before through
|
||||
* {@link #getOrCreateTrackedRegatta(com.sap.sailing.domain.base.Regatta)} because otherwise the link to
|
||||
* the {@link IEvent} can't be established
|
||||
* @param timeoutInMilliseconds TODO
|
||||
* @param tokenToRetrieveAssociatedRace
|
||||
* used to update the set of{@link RaceDefinition}s received by the {@link RaceCourseReceiver} created by
|
||||
* this call
|
||||
@@ -173,47 +170,39 @@ public interface DomainFactory {
|
||||
IEventSubscriber eventSubscriber, IRaceSubscriber raceSubscriber, boolean useInternalMarkPassingAlgorithm, long timeoutInMilliseconds);
|
||||
|
||||
/**
|
||||
* Creates a {@link RaceDefinition} from a TracTrac {@link IRace} and a
|
||||
* domain {@link Course} definition. The resulting {@link RaceDefinition} is
|
||||
* added to the {@link com.sap.sailing.domain.base.Regatta} to which
|
||||
* <code>trackedRegatta</code> belongs (see
|
||||
* {@link TrackedRegatta#getRegatta()}). 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(UUID)} happens only <em>after</em>
|
||||
* the tracked race has been created and the {@link RaceDefinition} was
|
||||
* {@link com.sap.sailing.domain.base.Regatta#addRace(RaceDefinition) added}
|
||||
* to the domain event. 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, and that the {@link RaceDefinition} is already
|
||||
* {@link com.sap.sailing.domain.base.Regatta#getAllRaces() known} by its
|
||||
* containing {@link com.sap.sailing.domain.base.Regatta}.
|
||||
* Creates a {@link RaceDefinition} from a TracTrac {@link IRace} and a domain {@link Course} definition. The
|
||||
* resulting {@link RaceDefinition} is added to the {@link com.sap.sailing.domain.base.Regatta} to which
|
||||
* <code>trackedRegatta</code> belongs (see {@link TrackedRegatta#getRegatta()}). 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(UUID)} happens only <em>after</em> the
|
||||
* tracked race has been created and the {@link RaceDefinition} was
|
||||
* {@link com.sap.sailing.domain.base.Regatta#addRace(RaceDefinition) added} to the domain event. 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, and that the {@link RaceDefinition} is already
|
||||
* {@link com.sap.sailing.domain.base.Regatta#getAllRaces() known} by its containing
|
||||
* {@link com.sap.sailing.domain.base.Regatta}.
|
||||
*
|
||||
* @param raceDefinitionSetToUpdate
|
||||
* if not <code>null</code>, after creating the
|
||||
* {@link TrackedRace}, the {@link RaceDefinition} is
|
||||
* {@link DynamicRaceDefinitionSet#addRaceDefinition(RaceDefinition, DynamicTrackedRace)
|
||||
* added} to that object.
|
||||
* if not <code>null</code>, after creating the {@link TrackedRace}, the {@link RaceDefinition} is
|
||||
* {@link DynamicRaceDefinitionSet#addRaceDefinition(RaceDefinition, DynamicTrackedRace) added} to that
|
||||
* object.
|
||||
* @param runBeforeExposingRace
|
||||
* if not {@code null} then this consumer will be passed the
|
||||
* {@link DynamicTrackedRace} if it was actually created by this
|
||||
* call. This happens while still in the
|
||||
* {@code synchronized(raceCache)} block, therefore before calls
|
||||
* waiting for the race (e.g.,
|
||||
* {@link #getAndWaitForRaceDefinition(UUID)}) return the race.
|
||||
* @param tractracRace TODO
|
||||
*/
|
||||
DynamicTrackedRace getOrCreateRaceDefinitionAndTrackedRace(DynamicTrackedRegatta trackedRegatta, UUID raceId,
|
||||
String raceName, Iterable<com.sap.sailing.domain.base.Competitor> competitors, BoatClass boatClass,
|
||||
Map<Competitor, Boat> competitorBoats, Course course, Iterable<Sideline> sidelines, WindStore windStore,
|
||||
long delayToLiveInMillis, long millisecondsOverWhichToAverageWind,
|
||||
DynamicRaceDefinitionSet raceDefinitionSetToUpdate, URI courseDesignUpdateURI, UUID tracTracEventUuid,
|
||||
String tracTracUsername, String tracTracPassword, boolean ignoreTracTracMarkPassings, RaceLogResolver raceLogResolver, Consumer<DynamicTrackedRace> runBeforeExposingRace, IRace tractracRace);
|
||||
* if not {@code null} then this consumer will be passed the {@link DynamicTrackedRace} if it was
|
||||
* actually created by this call. This happens while still in the {@code synchronized(raceCache)} block,
|
||||
* therefore before calls waiting for the race (e.g., {@link #getAndWaitForRaceDefinition(UUID)}) return
|
||||
* the race.
|
||||
*/
|
||||
DynamicTrackedRace getOrCreateRaceDefinitionAndTrackedRace(DynamicTrackedRegatta trackedRegatta, UUID raceId,
|
||||
String raceName, Iterable<com.sap.sailing.domain.base.Competitor> competitors, BoatClass boatClass,
|
||||
Map<Competitor, Boat> competitorBoats, Course course, Iterable<Sideline> sidelines, WindStore windStore,
|
||||
long delayToLiveInMillis, long millisecondsOverWhichToAverageWind,
|
||||
DynamicRaceDefinitionSet raceDefinitionSetToUpdate, URI courseDesignUpdateURI, UUID tracTracEventUuid,
|
||||
String tracTracUsername, String tracTracPassword, boolean ignoreTracTracMarkPassings,
|
||||
RaceLogResolver raceLogResolver, Consumer<DynamicTrackedRace> runBeforeExposingRace, IRace tractracRace);
|
||||
|
||||
/**
|
||||
* The record may be for a single mark or a gate. If for a gate, the
|
||||
* {@link ControlPointPositionData#getIndex() index} is used to determine
|
||||
* which of its marks is affected.
|
||||
* The record may be for a single mark or a gate. If for a gate, the {@link ControlPointPositionData#getIndex()
|
||||
* index} is used to determine which of its marks is affected.
|
||||
*/
|
||||
Mark getMark(TracTracControlPoint controlPoint, int zeroBasedMarkIndex);
|
||||
|
||||
@@ -223,8 +212,6 @@ public interface DomainFactory {
|
||||
|
||||
/**
|
||||
* If the vm argument tractrac.usemarkpassings=false, the RecieverType MARKPASSINGS will not return anything
|
||||
* @param raceLogResolver TODO
|
||||
* @param timeoutInMilliseconds TODO
|
||||
*/
|
||||
Iterable<Receiver> getUpdateReceivers(DynamicTrackedRegatta trackedRegatta, IRace tractracRace, WindStore windStore,
|
||||
long delayToLiveInMillis, Simulator simulator, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, TrackedRegattaRegistry trackedRegattaRegistry,
|
||||
@@ -274,23 +261,17 @@ public interface DomainFactory {
|
||||
* {@code File}) then if this parameter is {@code true} the race will be loaded from the replay file
|
||||
* instead of the {@code storedURI}/{@code liveURI} specified. This is particularly useful for restoring
|
||||
* races if since the last connection the race was migrated to a replay file format.
|
||||
* @param timeoutInMillis TODO
|
||||
*/
|
||||
RaceTrackingConnectivityParameters createTrackingConnectivityParameters(URL paramURL, URI liveURI, URI storedURI,
|
||||
URI courseDesignUpdateURI, TimePoint startOfTracking, TimePoint endOfTracking, long delayToLiveInMillis,
|
||||
Duration offsetToStartTimeOfSimulatedRace, boolean useInternalMarkPassingAlgorithm, RaceLogStore raceLogStore, RegattaLogStore regattaLogStore,
|
||||
String tracTracUsername, String tracTracPassword, String raceStatus, String raceVisibility, boolean trackWind, boolean correctWindDirectionByMagneticDeclination,
|
||||
boolean preferReplayIfAvailable, int timeoutInMillis) throws Exception;
|
||||
|
||||
/**
|
||||
* Removes all knowledge about <code>tractracRace</code> which includes removing it from the race cache, from the
|
||||
* {@link com.sap.sailing.domain.base.Regatta} and, if a {@link TrackedRace} for the corresponding
|
||||
* {@link RaceDefinition} exists, from the {@link TrackedRegatta}. If removing the race from the event, the event is
|
||||
* removed from the event cache such that {@link #getOrCreateDefaultRegatta(IEvent, TrackedRegattaRegistry)} will have to create a new one. Similarly,
|
||||
* if the {@link TrackedRace} that was removed from the {@link TrackedRegatta} was the last one, the
|
||||
* {@link TrackedRegatta} is removed such that {@link #getOrCreateTrackedRegatta(com.sap.sailing.domain.base.Regatta)}
|
||||
* will have to create a new one.
|
||||
* Removes all knowledge about <code>tractracRace</code> from the race cache.
|
||||
*/
|
||||
void removeRace(IEvent tractracEvent, IRace tractracRace, TrackedRegattaRegistry trackedRegattaRegistry);
|
||||
RaceDefinition removeRace(IEvent tractracEvent, IRace tractracRace, Regatta regattaToLoadRaceInto, TrackedRegattaRegistry trackedRegattaRegistry);
|
||||
|
||||
/**
|
||||
* Computes an ID to use for a {@link RaceDefinition} based on the TracTrac race.
|
||||
|
||||
+22
-34
@@ -1,9 +1,7 @@
|
||||
package com.sap.sailing.domain.tractracadapter.impl;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
@@ -457,7 +455,7 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRace(IEvent tractracEvent, IRace tractracRace, TrackedRegattaRegistry trackedRegattaRegistry) {
|
||||
public RaceDefinition removeRace(IEvent tractracEvent, IRace tractracRace, Regatta regattaToLoadRaceInto, TrackedRegattaRegistry trackedRegattaRegistry) {
|
||||
RaceDefinition raceDefinition;
|
||||
synchronized (raceCache) {
|
||||
raceDefinition = getExistingRaceDefinitionForRace(tractracRace.getId());
|
||||
@@ -467,45 +465,33 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
}
|
||||
}
|
||||
if (raceDefinition != null) {
|
||||
// FIXME this only removes the race from its default regatta, not any explicit regatta
|
||||
Pair<String, BoatClass> defaultRegattaNameAndBoatClass = getDefaultRegattaNameAndBoatClass(tractracRace);
|
||||
Pair<String, String> key = new Pair<String, String>(defaultRegattaNameAndBoatClass.getA(),
|
||||
defaultRegattaNameAndBoatClass.getB() == null ? null :
|
||||
defaultRegattaNameAndBoatClass.getB().getName());
|
||||
synchronized (regattaCache) {
|
||||
Regatta regatta = regattaCache.get(key);
|
||||
final Regatta regatta;
|
||||
final Pair<String, String> key;
|
||||
if (regattaToLoadRaceInto != null) {
|
||||
regatta = regattaToLoadRaceInto;
|
||||
key = new Pair<>(regatta.getName(), regatta.getBoatClass().getName());
|
||||
} else {
|
||||
Pair<String, BoatClass> defaultRegattaNameAndBoatClass = getDefaultRegattaNameAndBoatClass(tractracRace);
|
||||
key = new Pair<String, String>(defaultRegattaNameAndBoatClass.getA(),
|
||||
defaultRegattaNameAndBoatClass.getB() == null ? null :
|
||||
defaultRegattaNameAndBoatClass.getB().getName());
|
||||
regatta = regattaCache.get(key);
|
||||
}
|
||||
if (regatta != null) {
|
||||
// The following fixes bug 202: when tracking of multiple races of the same event has been started, this may not
|
||||
// remove any race; however, the event may already have been created by another tracker whose race hasn't
|
||||
// arrived yet and therefore the races list is still empty; therefore, only remove the event if its
|
||||
// race list became empty by the removal performed here.
|
||||
int oldSize = Util.size(regatta.getAllRaces());
|
||||
regatta.removeRace(raceDefinition);
|
||||
if (oldSize > 0 && Util.size(regatta.getAllRaces()) == 0) {
|
||||
if (Util.contains(regatta.getAllRaces(), raceDefinition) && Util.size(regatta.getAllRaces()) == 1) {
|
||||
logger.info("Removing regatta "+regatta.getName()+" ("+regatta.hashCode()+") from TracTrac DomainFactoryImpl");
|
||||
regattaCache.remove(key);
|
||||
weakDefaultRegattaCache.remove(tractracRace);
|
||||
}
|
||||
TrackedRegatta trackedRegatta = trackedRegattaRegistry.getTrackedRegatta(regatta);
|
||||
if (trackedRegatta != null) {
|
||||
// see above; only remove tracked regatta if it *became* empty because of the tracked race removal here
|
||||
final int oldSizeOfTrackedRaces;
|
||||
final int newSizeOfTrackedRaces;
|
||||
trackedRegatta.lockTrackedRacesForWrite();
|
||||
try {
|
||||
oldSizeOfTrackedRaces = Util.size(trackedRegatta.getTrackedRaces());
|
||||
trackedRegatta.removeTrackedRace(raceDefinition);
|
||||
newSizeOfTrackedRaces = Util.size(trackedRegatta.getTrackedRaces());
|
||||
} finally {
|
||||
trackedRegatta.unlockTrackedRacesAfterWrite();
|
||||
}
|
||||
if (oldSizeOfTrackedRaces > 0 && newSizeOfTrackedRaces == 0) {
|
||||
trackedRegattaRegistry.removeTrackedRegatta(regatta);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return raceDefinition;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -716,17 +702,19 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public TracTracRaceTracker createRaceTracker(RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, WindStore windStore, TrackedRegattaRegistry trackedRegattaRegistry,
|
||||
RaceLogResolver raceLogResolver, RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds) throws MalformedURLException,
|
||||
FileNotFoundException, URISyntaxException, CreateModelException, SubscriberInitializationException {
|
||||
public TracTracRaceTracker createRaceTracker(RaceLogStore raceLogStore, RegattaLogStore regattaLogStore,
|
||||
WindStore windStore, TrackedRegattaRegistry trackedRegattaRegistry, RaceLogResolver raceLogResolver,
|
||||
RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds)
|
||||
throws URISyntaxException, CreateModelException, SubscriberInitializationException, IOException,
|
||||
InterruptedException {
|
||||
return new TracTracRaceTrackerImpl(this, raceLogStore, regattaLogStore, windStore, trackedRegattaRegistry, raceLogResolver, connectivityParams, timeoutInMilliseconds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RaceTracker createRaceTracker(Regatta regatta, RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, WindStore windStore,
|
||||
TrackedRegattaRegistry trackedRegattaRegistry, RaceLogResolver raceLogResolver, RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds)
|
||||
throws MalformedURLException, FileNotFoundException, URISyntaxException, CreateModelException,
|
||||
SubscriberInitializationException {
|
||||
throws URISyntaxException, CreateModelException,
|
||||
SubscriberInitializationException, IOException, InterruptedException {
|
||||
return new TracTracRaceTrackerImpl(regatta, this, raceLogStore, regattaLogStore, windStore, trackedRegattaRegistry,
|
||||
raceLogResolver, connectivityParams, timeoutInMilliseconds);
|
||||
}
|
||||
|
||||
+5
-5
@@ -1,7 +1,6 @@
|
||||
package com.sap.sailing.domain.tractracadapter.impl;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
@@ -116,9 +115,10 @@ public class RaceTrackingConnectivityParametersImpl extends AbstractRaceTracking
|
||||
|
||||
@Override
|
||||
public RaceTracker createRaceTracker(TrackedRegattaRegistry trackedRegattaRegistry, WindStore windStore,
|
||||
RaceLogResolver raceLogResolver, long timeoutInMilliseconds) throws MalformedURLException, FileNotFoundException, URISyntaxException,
|
||||
CreateModelException, SubscriberInitializationException {
|
||||
RaceTracker tracker = domainFactory.createRaceTracker(raceLogStore, regattaLogStore, windStore, trackedRegattaRegistry, raceLogResolver, this, timeoutInMilliseconds);
|
||||
RaceLogResolver raceLogResolver, long timeoutInMilliseconds) throws URISyntaxException,
|
||||
CreateModelException, SubscriberInitializationException, IOException, InterruptedException {
|
||||
RaceTracker tracker = domainFactory.createRaceTracker(raceLogStore, regattaLogStore, windStore,
|
||||
trackedRegattaRegistry, raceLogResolver, this, timeoutInMilliseconds);
|
||||
return tracker;
|
||||
}
|
||||
|
||||
|
||||
+6
-4
@@ -1,7 +1,6 @@
|
||||
package com.sap.sailing.domain.tractracadapter.impl;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -263,7 +262,7 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl
|
||||
TracTracRaceTrackerImpl(DomainFactory domainFactory, RaceLogStore raceLogStore,
|
||||
RegattaLogStore regattaLogStore, WindStore windStore, TrackedRegattaRegistry trackedRegattaRegistry,
|
||||
RaceLogResolver raceLogResolver, RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds)
|
||||
throws URISyntaxException, MalformedURLException, FileNotFoundException, SubscriberInitializationException {
|
||||
throws URISyntaxException, SubscriberInitializationException, IOException, InterruptedException {
|
||||
this(/* regatta */ null, domainFactory, raceLogStore, regattaLogStore, windStore, trackedRegattaRegistry,
|
||||
raceLogResolver, connectivityParams, timeoutInMilliseconds);
|
||||
}
|
||||
@@ -285,7 +284,7 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl
|
||||
TracTracRaceTrackerImpl(final Regatta regatta, DomainFactory domainFactory, RaceLogStore raceLogStore,
|
||||
RegattaLogStore regattaLogStore, WindStore windStore, TrackedRegattaRegistry trackedRegattaRegistry,
|
||||
RaceLogResolver raceLogResolver, RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds)
|
||||
throws URISyntaxException, MalformedURLException, FileNotFoundException, SubscriberInitializationException {
|
||||
throws URISyntaxException, SubscriberInitializationException, IOException, InterruptedException {
|
||||
super(connectivityParams);
|
||||
final URL paramURL = connectivityParams.getParamURL();
|
||||
final URI liveURI = connectivityParams.getLiveURI();
|
||||
@@ -388,7 +387,10 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl
|
||||
// removeRace may detach the domain regatta from the domain factory if that
|
||||
// removed the last race; therefore, it's important to getOrCreate the
|
||||
// domain regatta *after* calling removeRace
|
||||
domainFactory.removeRace(tractracRace.getEvent(), tractracRace, trackedRegattaRegistry);
|
||||
final RaceDefinition raceDefinition = domainFactory.removeRace(tractracRace.getEvent(), tractracRace, effectiveRegatta, trackedRegattaRegistry);
|
||||
if (raceDefinition != null) {
|
||||
trackedRegattaRegistry.removeRace(effectiveRegatta, raceDefinition);
|
||||
}
|
||||
// if regatta is still null, no previous assignment of any of the races in this TracTrac event to a Regatta was
|
||||
// found;
|
||||
// in this case, create a default regatta based on the TracTrac event data
|
||||
|
||||
+15
-6
@@ -24,7 +24,12 @@ public interface RaceTrackingConnectivityParameters {
|
||||
* Starts a {@link RaceTracker} using the connectivity parameters provided by this object. As no specific
|
||||
* {@link Regatta} is provided, this will first look up a regatta for the race from
|
||||
* {@link TrackedRegattaRegistry#getRememberedRegattaForRace(java.io.Serializable)} and if not found will look up or
|
||||
* create a default regatta based on race data such as an event name and the boat class.
|
||||
* create a default regatta based on race data such as an event name and the boat class.<p>
|
||||
*
|
||||
* If a race equal to the one being created by this call already exists in the default regatta, its tracking
|
||||
* will be stopped (if any), the {@link RaceDefinition} will be removed from the default regatta, and the
|
||||
* {@link TrackedRace} will be removed from the {@link TrackedRegatta}. All this happens by means of
|
||||
* calling {@link TrackedRegattaRegistry#removeRace(Regatta, com.sap.sailing.domain.base.RaceDefinition)}.
|
||||
*
|
||||
* @param timeoutInMilliseconds
|
||||
* gives the tracker a possibility to abort tracking the race after so many milliseconds of
|
||||
@@ -37,11 +42,15 @@ public interface RaceTrackingConnectivityParameters {
|
||||
RaceLogResolver raceLogResolver, long timeoutInMilliseconds) throws Exception;
|
||||
|
||||
/**
|
||||
* Starts a {@link RaceTracker}, associating the resulting races with the {@link Regatta} passed as argument
|
||||
* instead of using the tracker's domain factory to obtain a default {@link Regatta} object for the tracking
|
||||
* parameters. This is particularly useful if a predefined regatta with {@link Series} and {@link Fleet}s
|
||||
* is to be used.
|
||||
* @param timeoutInMilliseconds TODO
|
||||
* Starts a {@link RaceTracker}, associating the resulting races with the {@link Regatta} passed as argument instead
|
||||
* of using the tracker's domain factory to obtain a default {@link Regatta} object for the tracking parameters.
|
||||
* This is particularly useful if a predefined regatta with {@link Series} and {@link Fleet}s is to be used.
|
||||
* <p>
|
||||
*
|
||||
* If a race equal to the one being created by this call already exists in the {@code regatta}, its tracking will be
|
||||
* stopped (if any), the {@link RaceDefinition} will be removed from the default regatta, and the
|
||||
* {@link TrackedRace} will be removed from the {@link TrackedRegatta}. All this happens by means of calling
|
||||
* {@link TrackedRegattaRegistry#removeRace(Regatta, com.sap.sailing.domain.base.RaceDefinition)}.
|
||||
*/
|
||||
RaceTracker createRaceTracker(Regatta regatta, TrackedRegattaRegistry trackedRegattaRegistry, WindStore windStore,
|
||||
RaceLogResolver raceLogResolver, long timeoutInMilliseconds) throws Exception;
|
||||
|
||||
+23
@@ -4,6 +4,8 @@ import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
import com.sap.sailing.domain.base.Fleet;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
|
||||
@@ -28,6 +30,27 @@ public interface TrackedRegattaRegistry {
|
||||
*/
|
||||
DynamicTrackedRegatta getTrackedRegatta(Regatta regatta);
|
||||
|
||||
/**
|
||||
* Removes <code>race</code> and any corresponding {@link #getTrackedRace(Regatta, RaceDefinition) tracked race}
|
||||
* from this service. If it was the last {@link RaceDefinition} in its {@link Regatta} and the regatta
|
||||
* {@link Regatta#isPersistent() is not stored persistently}, the <code>regatta</code> is removed as well and will no
|
||||
* longer be returned by {@link #getAllRegattas()}. The wind tracking is stopped for <code>race</code>.
|
||||
* <p>
|
||||
*
|
||||
* Any {@link RaceTracker} for which <code>race</race> is the last race tracked that is still reachable
|
||||
* from {@link #getAllRegattas()} will be {@link RaceTracker#stop(boolean) stopped}.
|
||||
*
|
||||
* The <code>race</code> will be also removed from all leaderboards containing a column that has <code>race</code>'s
|
||||
* {@link #getTrackedRace(Regatta, RaceDefinition) corresponding} {@link TrackedRace} as its
|
||||
* {@link RaceColumn#getTrackedRace(Fleet)}.
|
||||
*
|
||||
* @param regatta
|
||||
* the regatta from which to remove the race
|
||||
* @param race
|
||||
* the race to remove
|
||||
*/
|
||||
void removeRace(Regatta regatta, RaceDefinition race) throws MalformedURLException, IOException,InterruptedException;
|
||||
|
||||
void removeTrackedRegatta(Regatta regatta);
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,7 +29,6 @@ import com.sap.sailing.domain.base.CourseArea;
|
||||
import com.sap.sailing.domain.base.DomainFactory;
|
||||
import com.sap.sailing.domain.base.Event;
|
||||
import com.sap.sailing.domain.base.EventBase;
|
||||
import com.sap.sailing.domain.base.Fleet;
|
||||
import com.sap.sailing.domain.base.LeaderboardSearchResult;
|
||||
import com.sap.sailing.domain.base.LeaderboardSearchResultBase;
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
@@ -174,27 +173,6 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch
|
||||
*/
|
||||
void stopTracking(Regatta regatta, boolean willBeRemoved) throws MalformedURLException, IOException, InterruptedException;
|
||||
|
||||
/**
|
||||
* Removes <code>race</code> and any corresponding {@link #getTrackedRace(Regatta, RaceDefinition) tracked race}
|
||||
* from this service. If it was the last {@link RaceDefinition} in its {@link Regatta} and the regatta
|
||||
* {@link Regatta#isPersistent() is not stored persistently}, the <code>regatta</code> is removed as well and will no
|
||||
* longer be returned by {@link #getAllRegattas()}. The wind tracking is stopped for <code>race</code>.
|
||||
* <p>
|
||||
*
|
||||
* Any {@link RaceTracker} for which <code>race</race> is the last race tracked that is still reachable
|
||||
* from {@link #getAllRegattas()} will be {@link RaceTracker#stop(boolean) stopped}.
|
||||
*
|
||||
* The <code>race</code> will be also removed from all leaderboards containing a column that has <code>race</code>'s
|
||||
* {@link #getTrackedRace(Regatta, RaceDefinition) corresponding} {@link TrackedRace} as its
|
||||
* {@link RaceColumn#getTrackedRace(Fleet)}.
|
||||
*
|
||||
* @param regatta
|
||||
* the regatta from which to remove the race
|
||||
* @param race
|
||||
* the race to remove
|
||||
*/
|
||||
void removeRace(Regatta regatta, RaceDefinition race) throws MalformedURLException, IOException,InterruptedException;
|
||||
|
||||
/**
|
||||
* @param port
|
||||
* the UDP port on which to listen for incoming messages from Expedition clients
|
||||
|
||||
+12
-4
@@ -2415,19 +2415,27 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
TrackedRace trackedRace = getExistingTrackedRace(regatta, race);
|
||||
if (trackedRace != null) {
|
||||
TrackedRegatta trackedRegatta = getTrackedRegatta(regatta);
|
||||
final boolean isTrackedRacesEmpty;
|
||||
final boolean isTrackedRacesBecameEmpty;
|
||||
if (trackedRegatta != null) {
|
||||
trackedRegatta.lockTrackedRacesForWrite();
|
||||
// The following fixes bug 202: when tracking of multiple races of the same event has been started, this may not
|
||||
// remove any race; however, the event may already have been created by another tracker whose race hasn't
|
||||
// arrived yet and therefore the races list is still empty; therefore, only remove the event if its
|
||||
// race list became empty by the removal performed here.
|
||||
final int oldSizeOfTrackedRaces;
|
||||
final int newSizeOfTrackedRaces;
|
||||
oldSizeOfTrackedRaces = Util.size(trackedRegatta.getTrackedRaces());
|
||||
try {
|
||||
trackedRegatta.removeTrackedRace(trackedRace);
|
||||
isTrackedRacesEmpty = Util.isEmpty(trackedRegatta.getTrackedRaces());
|
||||
newSizeOfTrackedRaces = Util.size(trackedRegatta.getTrackedRaces());
|
||||
isTrackedRacesBecameEmpty = (oldSizeOfTrackedRaces > 0 && newSizeOfTrackedRaces == 0);
|
||||
} finally {
|
||||
trackedRegatta.unlockTrackedRacesAfterWrite();
|
||||
}
|
||||
} else {
|
||||
isTrackedRacesEmpty = false;
|
||||
isTrackedRacesBecameEmpty = false;
|
||||
}
|
||||
if (isTrackedRacesEmpty) {
|
||||
if (isTrackedRacesBecameEmpty) {
|
||||
removeTrackedRegatta(regatta);
|
||||
}
|
||||
// remove tracked race from RaceColumns of regatta
|
||||
|
||||
Reference in new issue
Block a user