java/com.sap.sailing.domain.tractracadapter.persistence/src/com/sap/sailing/domain/tractracadapter/persistence/impl/TracTracConnectivityParamsHandler.java
... ...
@@ -3,6 +3,7 @@ package com.sap.sailing.domain.tractracadapter.persistence.impl;
3 3
import java.io.IOException;
4 4
import java.net.MalformedURLException;
5 5
import java.net.URI;
6
+import java.net.URISyntaxException;
6 7
import java.net.URL;
7 8
import java.util.HashMap;
8 9
import java.util.Map;
... ...
@@ -24,6 +25,8 @@ import com.sap.sse.common.impl.MillisecondsDurationImpl;
24 25
import com.sap.sse.common.impl.MillisecondsTimePoint;
25 26
import com.sap.sse.security.SecurityService;
26 27
import com.sap.sse.security.SessionUtils;
28
+import com.tractrac.model.lib.api.event.CreateModelException;
29
+import com.tractrac.util.lib.api.exceptions.TimeOutException;
27 30
28 31
/**
29 32
* Handles mapping TracTrac connectivity parameters from and to a map with {@link String} keys. The
... ...
@@ -139,7 +142,7 @@ public class TracTracConnectivityParamsHandler extends AbstractRaceTrackingConne
139 142
}
140 143
141 144
private void updatePersistentTracTracConfiguration(RaceTrackingConnectivityParametersImpl params)
142
- throws MalformedURLException, IOException, ParseException {
145
+ throws MalformedURLException, IOException, ParseException, CreateModelException, URISyntaxException, TimeOutException {
143 146
final String jsonURL = params.getTractracRace().getParameterSet().getParameter("eventJSON");
144 147
final String creatorName = SessionUtils.getPrincipal().toString();
145 148
final TracTracConfigurationImpl tracTracConfiguration = new TracTracConfigurationImpl(creatorName, params.getTractracRace().getEvent().getName(), jsonURL,
java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java
... ...
@@ -65,6 +65,7 @@ import com.tractrac.model.lib.api.route.IControlPoint;
65 65
import com.tractrac.subscription.lib.api.IEventSubscriber;
66 66
import com.tractrac.subscription.lib.api.IRaceSubscriber;
67 67
import com.tractrac.subscription.lib.api.SubscriberInitializationException;
68
+import com.tractrac.util.lib.api.exceptions.TimeOutException;
68 69
69 70
import difflib.PatchFailedException;
70 71
... ...
@@ -152,8 +153,8 @@ public interface DomainFactory {
152 153
WindStore windStore, TrackedRegattaRegistry trackedRegattaRegistry, RaceLogAndTrackedRaceResolver raceLogResolver,
153 154
LeaderboardGroupResolver leaderboardGroupResolver,
154 155
RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds,
155
- RaceTrackingHandler raceTrackingHandler)
156
- throws URISyntaxException, SubscriberInitializationException, IOException, InterruptedException;
156
+ RaceTrackingHandler raceTrackingHandler) throws URISyntaxException, SubscriberInitializationException,
157
+ IOException, InterruptedException, CreateModelException, TimeOutException;
157 158
158 159
/**
159 160
* Same as {@link #createRaceTracker(URL, URI, URI, URI, TimePoint, TimePoint, WindStore, TrackedRegattaRegistry)},
... ...
@@ -165,7 +166,7 @@ public interface DomainFactory {
165 166
RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds,
166 167
RaceTrackingHandler raceTrackingHandler)
167 168
throws MalformedURLException, FileNotFoundException, URISyntaxException, CreateModelException,
168
- SubscriberInitializationException, IOException, InterruptedException;
169
+ SubscriberInitializationException, IOException, InterruptedException, TimeOutException;
169 170
170 171
BoatClass getOrCreateBoatClass(String competitorClassName);
171 172
java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java
... ...
@@ -116,6 +116,7 @@ import com.tractrac.model.lib.api.route.IControlPoint;
116 116
import com.tractrac.subscription.lib.api.IEventSubscriber;
117 117
import com.tractrac.subscription.lib.api.IRaceSubscriber;
118 118
import com.tractrac.subscription.lib.api.SubscriberInitializationException;
119
+import com.tractrac.util.lib.api.exceptions.TimeOutException;
119 120
120 121
import difflib.PatchFailedException;
121 122
... ...
@@ -645,7 +646,8 @@ public class DomainFactoryImpl implements DomainFactory {
645 646
try {
646 647
raceDefinition = raceTrackingHandler.createRaceDefinition(trackedRegatta.getRegatta(), raceName, course, boatClass, competitorsAndBoats, raceId);
647 648
} catch (RuntimeException exception) {
648
- final String reasonForNotAddingRaceToRegatta = "Error while creating race " + raceDefinition + " for regatta " + trackedRegatta.getRegatta();
649
+ final String reasonForNotAddingRaceToRegatta = "Error while creating race " + raceDefinition
650
+ + " for regatta " + trackedRegatta.getRegatta() + ": " + exception.getMessage();
649 651
errorWhileTryingToTrackRace(trackedRegatta, raceDefinitionSetToUpdate, raceDefinition, reasonForNotAddingRaceToRegatta);
650 652
}
651 653
} else {
... ...
@@ -1029,7 +1031,7 @@ public class DomainFactoryImpl implements DomainFactory {
1029 1031
LeaderboardGroupResolver leaderboardGroupResolver,
1030 1032
RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds,
1031 1033
RaceTrackingHandler raceTrackingHandler)
1032
- throws URISyntaxException, SubscriberInitializationException, IOException, InterruptedException {
1034
+ throws URISyntaxException, SubscriberInitializationException, IOException, InterruptedException, CreateModelException, TimeOutException {
1033 1035
return new TracTracRaceTrackerImpl(this, raceLogStore, regattaLogStore, windStore, trackedRegattaRegistry,
1034 1036
raceLogResolver, leaderboardGroupResolver, connectivityParams, timeoutInMilliseconds, raceTrackingHandler);
1035 1037
}
... ...
@@ -1040,7 +1042,7 @@ public class DomainFactoryImpl implements DomainFactory {
1040 1042
LeaderboardGroupResolver leaderboardGroupResolver,
1041 1043
RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds,
1042 1044
RaceTrackingHandler raceTrackingHandler) throws URISyntaxException, CreateModelException,
1043
- SubscriberInitializationException, IOException, InterruptedException {
1045
+ SubscriberInitializationException, IOException, InterruptedException, TimeOutException {
1044 1046
return new TracTracRaceTrackerImpl(regatta, this, raceLogStore, regattaLogStore, windStore, trackedRegattaRegistry,
1045 1047
raceLogResolver, leaderboardGroupResolver, connectivityParams, timeoutInMilliseconds, raceTrackingHandler);
1046 1048
}
java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/RaceTrackingConnectivityParametersImpl.java
... ...
@@ -25,6 +25,7 @@ import com.tractrac.model.lib.api.ModelLocator;
25 25
import com.tractrac.model.lib.api.event.CreateModelException;
26 26
import com.tractrac.model.lib.api.event.IRace;
27 27
import com.tractrac.subscription.lib.api.SubscriberInitializationException;
28
+import com.tractrac.util.lib.api.exceptions.TimeOutException;
28 29
29 30
public class RaceTrackingConnectivityParametersImpl extends AbstractRaceTrackingConnectivityParameters {
30 31
... ...
@@ -49,7 +50,6 @@ public class RaceTrackingConnectivityParametersImpl extends AbstractRaceTracking
49 50
private final String raceVisibility;
50 51
private final boolean useInternalMarkPassingAlgorithm;
51 52
private final boolean preferReplayIfAvailable;
52
- private final transient IRace tractracRace;
53 53
private final int timeoutInMillis;
54 54
private final boolean useOfficialEventsToUpdateRaceLog;
55 55
... ...
@@ -78,11 +78,7 @@ public class RaceTrackingConnectivityParametersImpl extends AbstractRaceTracking
78 78
this.useOfficialEventsToUpdateRaceLog = useOfficialEventsToUpdateRaceLog;
79 79
this.paramURL = paramURL;
80 80
this.timeoutInMillis = timeoutInMillis;
81
- if (timeoutInMillis == -1) {
82
- this.tractracRace = ModelLocator.getEventFactory().createRace(new URI(paramURL.toString()));
83
- } else {
84
- this.tractracRace = ModelLocator.getEventFactory().createRace(new URI(paramURL.toString()), timeoutInMillis);
85
- }
81
+ final IRace tractracRace = getTractracRace();
86 82
if (preferReplayIfAvailable && isReplayRace(tractracRace) &&
87 83
(!Util.equalsWithNull(liveURI, tractracRace.getLiveURI()) || !Util.equalsWithNull(storedURI, tractracRace.getStoredURI()))) {
88 84
logger.info("Replay format available and preferred for race " + tractracRace.getName()
... ...
@@ -114,8 +110,14 @@ public class RaceTrackingConnectivityParametersImpl extends AbstractRaceTracking
114 110
return tractracRace.getStoredURI() != null && tractracRace.getStoredURI().toString().toLowerCase().endsWith(".mtb");
115 111
}
116 112
117
- public IRace getTractracRace() {
118
- return tractracRace;
113
+ public IRace getTractracRace() throws CreateModelException, URISyntaxException, TimeOutException {
114
+ final IRace result;
115
+ if (getTimeoutInMillis() == -1) {
116
+ result = ModelLocator.getEventFactory().createRace(new URI(paramURL.toString()));
117
+ } else {
118
+ result = ModelLocator.getEventFactory().createRace(new URI(paramURL.toString()), getTimeoutInMillis());
119
+ }
120
+ return result;
119 121
}
120 122
121 123
@Override
... ...
@@ -127,7 +129,7 @@ public class RaceTrackingConnectivityParametersImpl extends AbstractRaceTracking
127 129
public RaceTracker createRaceTracker(TrackedRegattaRegistry trackedRegattaRegistry, WindStore windStore,
128 130
RaceLogAndTrackedRaceResolver raceLogResolver, LeaderboardGroupResolver leaderboardGroupResolver,
129 131
long timeoutInMilliseconds, RaceTrackingHandler raceTrackingHandler) throws URISyntaxException,
130
- CreateModelException, SubscriberInitializationException, IOException, InterruptedException {
132
+ CreateModelException, SubscriberInitializationException, IOException, InterruptedException, TimeOutException {
131 133
RaceTracker tracker = domainFactory.createRaceTracker(raceLogStore, regattaLogStore, windStore,
132 134
trackedRegattaRegistry, raceLogResolver, leaderboardGroupResolver, this, timeoutInMilliseconds,
133 135
raceTrackingHandler);
java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracRaceTrackerImpl.java
... ...
@@ -56,6 +56,7 @@ import com.sap.sse.common.Duration;
56 56
import com.sap.sse.common.TimePoint;
57 57
import com.sap.sse.common.Util;
58 58
import com.sap.sse.util.impl.ThreadFactoryWithPriority;
59
+import com.tractrac.model.lib.api.event.CreateModelException;
59 60
import com.tractrac.model.lib.api.event.DataSource;
60 61
import com.tractrac.model.lib.api.event.ICompetitor;
61 62
import com.tractrac.model.lib.api.event.IEvent;
... ...
@@ -71,6 +72,7 @@ import com.tractrac.subscription.lib.api.event.IConnectionStatusListener;
71 72
import com.tractrac.subscription.lib.api.event.ILiveDataEvent;
72 73
import com.tractrac.subscription.lib.api.event.IStoredDataEvent;
73 74
import com.tractrac.subscription.lib.api.race.IRacesListener;
75
+import com.tractrac.util.lib.api.exceptions.TimeOutException;
74 76
75 77
public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl
76 78
implements IConnectionStatusListener, TracTracRaceTracker, DynamicRaceDefinitionSet, TrackingDataLoader {
... ...
@@ -270,11 +272,12 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl
270 272
* you expect things to have loaded; see also
271 273
* {@link RaceTracker#TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS}.
272 274
*/
273
- TracTracRaceTrackerImpl(DomainFactory domainFactory, RaceLogStore raceLogStore,
274
- RegattaLogStore regattaLogStore, WindStore windStore, TrackedRegattaRegistry trackedRegattaRegistry,
275
- RaceLogAndTrackedRaceResolver raceLogResolver, LeaderboardGroupResolver leaderboardGroupResolver, RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds,
276
- RaceTrackingHandler raceTrackingHandler)
277
- throws URISyntaxException, SubscriberInitializationException, IOException, InterruptedException {
275
+ TracTracRaceTrackerImpl(DomainFactory domainFactory, RaceLogStore raceLogStore, RegattaLogStore regattaLogStore,
276
+ WindStore windStore, TrackedRegattaRegistry trackedRegattaRegistry,
277
+ RaceLogAndTrackedRaceResolver raceLogResolver, LeaderboardGroupResolver leaderboardGroupResolver,
278
+ RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds,
279
+ RaceTrackingHandler raceTrackingHandler) throws URISyntaxException, SubscriberInitializationException,
280
+ IOException, InterruptedException, CreateModelException, TimeOutException {
278 281
this(/* regatta */ null, domainFactory, raceLogStore, regattaLogStore, windStore, trackedRegattaRegistry,
279 282
raceLogResolver, leaderboardGroupResolver, connectivityParams, timeoutInMilliseconds,
280 283
raceTrackingHandler);
... ...
@@ -299,7 +302,7 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl
299 302
RaceLogAndTrackedRaceResolver raceLogResolver, LeaderboardGroupResolver leaderboardGroupResolver,
300 303
RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds,
301 304
RaceTrackingHandler raceTrackingHandler)
302
- throws URISyntaxException, SubscriberInitializationException, IOException, InterruptedException {
305
+ throws URISyntaxException, SubscriberInitializationException, IOException, InterruptedException, CreateModelException, TimeOutException {
303 306
super(connectivityParams);
304 307
final URL paramURL = connectivityParams.getParamURL();
305 308
final URI liveURI = connectivityParams.getLiveURI();
java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRegattaRegistry.java
... ...
@@ -102,11 +102,15 @@ public interface TrackedRegattaRegistry {
102 102
* example, if tracking for a regatta shall be started early, so as to enable race officials to see the course
103 103
* geometry and wind data for the first race of the day, then especially in self-service scenarios there may be late
104 104
* competitors registrations that happen after tracking has been started. These competitors, depending on how the
105
- * connector in use works, may make it into the regatta's leaderboard, but not into the {@link RaceDefinition}.
106
- * This would be unfortunate as those competitors then would remain invisible until the race is reloaded.<p>
105
+ * connector in use works, may make it into the regatta's leaderboard, but not into the {@link RaceDefinition}. This
106
+ * would be unfortunate as those competitors then would remain invisible until the race is reloaded.
107
+ * <p>
107 108
*
108 109
* See also <a href="https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=5219">bug 5219</a> for a discussion.
109
- * @return
110
+ *
111
+ * @return {@code null} if it was not possible to re-load the race, either because the regatta doesn't allow for it,
112
+ * or because the connectivity parameters were not found; a {@link RaceHandle} for the re-started race
113
+ * otherwise.
110 114
*/
111 115
RaceHandle updateRaceCompetitors(Regatta regatta, RaceDefinition race) throws Exception;
112 116
}
java/com.sap.sailing.server.gateway/webservices/api/v2/leaderboardGetDoc.html
... ...
@@ -71,7 +71,8 @@ There is also the 'ALL' shortcut constant which can be used to get all available
71 71
</tr>
72 72
<tr>
73 73
<td>&nbsp;</td>
74
- <td>raceDetails [Default = RACE_GAP_TO_LEADER_IN_SECONDS, RACE_AVERAGE_SPEED_OVER_GROUND_IN_KNOTS, RACE_CURRENT_SPEED_OVER_GROUND_IN_KNOTS, RACE_DISTANCE_TO_COMPETITOR_FARTHEST_AHEAD_IN_METERS, CURRENT_LEG]</td>
74
+ <td>raceDetails [Default = RACE_GAP_TO_LEADER_IN_SECONDS, RACE_AVERAGE_SPEED_OVER_GROUND_IN_KNOTS, RACE_CURRENT_SPEED_OVER_GROUND_IN_KNOTS, RACE_DISTANCE_TO_COMPETITOR_FARTHEST_AHEAD_IN_METERS, CURRENT_LEG];
75
+ use "ALL" to get all detail types supported.</td>
75 76
</tr>
76 77
<tr>
77 78
<td>&nbsp;</td>
java/com.sap.sailing.server.test/.settings/org.eclipse.core.resources.prefs
... ...
@@ -1,2 +1,3 @@
1 1
eclipse.preferences.version=1
2
+encoding//src/com/sap/sailing/server/test/AutomaticRetrackUponCompetitorSetChangeTest.java=UTF-8
2 3
encoding//src/com/sap/sailing/server/util/ShardingLeaderBoardEncodingTest.java=UTF-8
java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/AutomaticRetrackUponCompetitorSetChangeTest.java
... ...
@@ -0,0 +1,183 @@
1
+package com.sap.sailing.server.test;
2
+
3
+import static org.junit.Assert.assertEquals;
4
+import static org.junit.Assert.assertNotNull;
5
+import static org.junit.Assert.assertNotSame;
6
+import static org.junit.Assert.fail;
7
+import static org.mockito.Mockito.mock;
8
+import static org.mockito.Mockito.when;
9
+
10
+import java.net.URI;
11
+import java.net.URL;
12
+import java.util.Arrays;
13
+import java.util.Collections;
14
+import java.util.GregorianCalendar;
15
+import java.util.TimeZone;
16
+import java.util.UUID;
17
+
18
+import org.mockito.Matchers;
19
+import org.junit.After;
20
+import org.junit.Before;
21
+import org.junit.Test;
22
+import org.osgi.framework.BundleContext;
23
+
24
+import com.sap.sailing.domain.base.Competitor;
25
+import com.sap.sailing.domain.base.CompetitorAndBoatStore;
26
+import com.sap.sailing.domain.base.DomainFactory;
27
+import com.sap.sailing.domain.base.RaceDefinition;
28
+import com.sap.sailing.domain.base.Regatta;
29
+import com.sap.sailing.domain.base.impl.DomainFactoryImpl;
30
+import com.sap.sailing.domain.common.CompetitorRegistrationType;
31
+import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
32
+import com.sap.sailing.domain.common.RegattaName;
33
+import com.sap.sailing.domain.common.dto.FleetDTO;
34
+import com.sap.sailing.domain.leaderboard.impl.LowPoint;
35
+import com.sap.sailing.domain.persistence.DomainObjectFactory;
36
+import com.sap.sailing.domain.persistence.MongoObjectFactory;
37
+import com.sap.sailing.domain.persistence.PersistenceFactory;
38
+import com.sap.sailing.domain.persistence.media.MediaDBFactory;
39
+import com.sap.sailing.domain.racelog.RaceLogAndTrackedRaceResolver;
40
+import com.sap.sailing.domain.racelog.impl.EmptyRaceLogStore;
41
+import com.sap.sailing.domain.racelog.tracking.EmptySensorFixStore;
42
+import com.sap.sailing.domain.ranking.OneDesignRankingMetric;
43
+import com.sap.sailing.domain.regattalog.impl.EmptyRegattaLogStore;
44
+import com.sap.sailing.domain.test.AbstractTracTracLiveTest;
45
+import com.sap.sailing.domain.tracking.RaceHandle;
46
+import com.sap.sailing.domain.tracking.RaceTracker;
47
+import com.sap.sailing.domain.tracking.RaceTrackingConnectivityParameters;
48
+import com.sap.sailing.domain.tracking.RaceTrackingHandler.DefaultRaceTrackingHandler;
49
+import com.sap.sailing.domain.tracking.TrackedRace;
50
+import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
51
+import com.sap.sailing.server.impl.RacingEventServiceImpl;
52
+import com.sap.sailing.server.impl.RacingEventServiceImpl.ConstructorParameters;
53
+import com.sap.sailing.server.interfaces.RacingEventService;
54
+import com.sap.sailing.server.operationaltransformation.CreateTrackedRace;
55
+import com.sap.sailing.server.operationaltransformation.UpdateSeries;
56
+import com.sap.sailing.server.testsupport.SecurityBundleTestWrapper;
57
+import com.sap.sse.common.Color;
58
+import com.sap.sse.common.Util;
59
+import com.sap.sse.common.impl.MillisecondsTimePoint;
60
+import com.sap.sse.mongodb.MongoDBService;
61
+import com.sap.sse.replication.FullyInitializedReplicableTracker;
62
+import com.sap.sse.replication.OperationExecutionListener;
63
+import com.sap.sse.replication.OperationWithResult;
64
+import com.sap.sse.security.SecurityService;
65
+
66
+/**
67
+ * See also bug 5219 (https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=5219).
68
+ *
69
+ * @author Axel Uhl (D043530)
70
+ *
71
+ */
72
+public class AutomaticRetrackUponCompetitorSetChangeTest {
73
+ private TrackedRace trackedRace;
74
+ private RegattaAndRaceIdentifier raceIdentifier;
75
+ private RaceHandle racesHandle;
76
+ private final boolean[] notifier = new boolean[1];
77
+ private RaceTrackingConnectivityParameters trackingParams;
78
+ private RacingEventServiceImpl service;
79
+ private MongoDBService mongoDBService;
80
+ private MongoObjectFactory mongoObjectFactory;
81
+
82
+ @Before
83
+ public void setUp() throws Exception {
84
+ final BundleContext contextMock = mock(BundleContext.class);
85
+ when(contextMock.createFilter(Matchers.anyObject())).thenReturn(null);
86
+ mongoDBService = MongoDBService.INSTANCE;
87
+ mongoDBService.getDB().drop();
88
+ mongoObjectFactory = PersistenceFactory.INSTANCE.getMongoObjectFactory(mongoDBService);
89
+ final SecurityService securityService = new SecurityBundleTestWrapper().initializeSecurityServiceForTesting();
90
+ service = new RacingEventServiceImpl((final RaceLogAndTrackedRaceResolver raceLogResolver)-> {
91
+ return new ConstructorParameters() {
92
+ private final DomainFactory baseDomainFactory = new DomainFactoryImpl(raceLogResolver);
93
+ @Override public DomainObjectFactory getDomainObjectFactory() { return PersistenceFactory.INSTANCE.getDomainObjectFactory(mongoDBService, baseDomainFactory); }
94
+ @Override public MongoObjectFactory getMongoObjectFactory() { return mongoObjectFactory; }
95
+ @Override public DomainFactory getBaseDomainFactory() { return baseDomainFactory; }
96
+ @Override public CompetitorAndBoatStore getCompetitorAndBoatStore() { return getBaseDomainFactory().getCompetitorAndBoatStore(); }
97
+ };
98
+ }, MediaDBFactory.INSTANCE.getMediaDB(mongoDBService), EmptyWindStore.INSTANCE,
99
+ EmptySensorFixStore.INSTANCE, null, null, /* sailingNotificationService */ null,
100
+ /* trackedRaceStatisticsCache */ null, /* restoreTrackedRaces */ false,
101
+ /* security service tracker */ new FullyInitializedReplicableTracker<SecurityService>(contextMock, (String) "class", null, null) {
102
+ @Override
103
+ public SecurityService getInitializedService(long timeoutInMillis) throws InterruptedException {
104
+ return securityService;
105
+ }
106
+ }, /* sharedSailingData */ null, /* replicationServiceTracker */ null,
107
+ /* scoreCorrectionProviderServiceTracker */ null, /* resultUrlRegistryServiceTracker */ null);
108
+ URL paramURL = new URL("http://event.tractrac.com/events/event_20150818_Bundesliga/4c54e750-27c2-0133-5064-60a44ce903c3.txt");
109
+ URI liveURI = AbstractTracTracLiveTest.getLiveURI();
110
+ URI storedURI = new URI("http://event.tractrac.com/events/event_20150818_Bundesliga/datafiles/4c54e750-27c2-0133-5064-60a44ce903c3.mtb");
111
+ URI courseDesignUpdateURI = AbstractTracTracLiveTest.getCourseDesignUpdateURI();
112
+ String tracTracUsername = AbstractTracTracLiveTest.getTracTracUsername();
113
+ String tracTracPassword = AbstractTracTracLiveTest.getTracTracPassword();
114
+ GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
115
+ cal.set(2015, 8, 22, 9, 23, 57);
116
+ MillisecondsTimePoint startOfTracking = new MillisecondsTimePoint(cal.getTimeInMillis());
117
+ cal.set(2015, 8, 22, 15, 26, 34);
118
+ MillisecondsTimePoint endOfTracking = new MillisecondsTimePoint(cal.getTimeInMillis());
119
+ service.addOperationExecutionListener(new OperationExecutionListener<RacingEventService>() {
120
+ @Override
121
+ public <T> void executed(OperationWithResult<RacingEventService, T> operation) {
122
+ if (operation instanceof CreateTrackedRace) {
123
+ synchronized (notifier) {
124
+ notifier[0] = true;
125
+ notifier.notifyAll();
126
+ }
127
+ }
128
+ }
129
+ });
130
+ trackingParams = new com.sap.sailing.domain.tractracadapter.impl.DomainFactoryImpl(service.getBaseDomainFactory())
131
+ .createTrackingConnectivityParameters(paramURL, liveURI, storedURI, courseDesignUpdateURI,
132
+ startOfTracking, endOfTracking, /* delayToLiveInMillis */
133
+ 0l, /* offsetToStartTimeOfSimulatedRace */null, /*ignoreTracTracMarkPassings*/ false, EmptyRaceLogStore.INSTANCE,
134
+ EmptyRegattaLogStore.INSTANCE, tracTracUsername, tracTracPassword, "", "", /* trackWind */ false, /* correctWindDirectionByMagneticDeclination */ false,
135
+ /* preferReplayIfAvailable */ false, /* timeoutInMillis */ (int) RaceTracker.TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS, /* useOfficialEventsToUpdateRaceLog */ false);
136
+ }
137
+
138
+ private void startTracking() throws Exception {
139
+ final Regatta regatta = service.createRegatta("Test regatta", "J/70",
140
+ /* canBoatsOfCompetitorsChangePerRace==true because it's a league race we're using for this test */ true,
141
+ CompetitorRegistrationType.CLOSED, /* registrationLinkSecret */ null,
142
+ /* startDate */ null, /* endDate */ null, UUID.randomUUID(),
143
+ /* start with no series */ Collections.emptySet(),
144
+ /* persistent */ true, new LowPoint(), /* defaultCourseAreaId */ UUID.randomUUID(),
145
+ /* buoyZoneRadiusInHullLengths */ 2., /* useStartTimeInference */ false, /* controlTrackingFromStartAndFinishTimes */ false,
146
+ /* autoRestartTrackingUponCompetitorSetChange */ true, /* rankingMetricConstructor */ OneDesignRankingMetric::new);
147
+ final RegattaName regattaIdentifier = new RegattaName(regatta.getName());
148
+ service.apply(new UpdateSeries(regattaIdentifier, "Default", "Default", /* isMedal */ false, /* isFleetsCanRunInParallel */ false,
149
+ /* resultDiscardingThresholds */ null, /* startsWithZeroScore */ false, /* firstColumnIsNonDiscardableCarryForward */ false,
150
+ /* hasSplitFleetContiguousScoring */ false, /* maximumNumberOfDiscards */ null,
151
+ Arrays.asList(new FleetDTO("Red", 0, Color.RED), new FleetDTO("Green", 0, Color.GREEN), new FleetDTO("Blue", 0, Color.BLUE))));
152
+ racesHandle = service.addRace(/* regattaToAddTo */ regattaIdentifier, trackingParams, /* timeoutInMilliseconds */ 60000,
153
+ new DefaultRaceTrackingHandler());
154
+ // wait for the race to show up
155
+ RaceDefinition race = racesHandle.getRace(RaceTracker.TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS);
156
+ if (race == null) {
157
+ fail("Waiting for tracked race timed out");
158
+ }
159
+ raceIdentifier = racesHandle.getRaceTracker().getRaceIdentifier();
160
+ trackedRace = service.getTrackedRace(raceIdentifier);
161
+ }
162
+
163
+ @Test
164
+ public void testStartTrackingAndRetrack() throws Exception {
165
+ startTracking();
166
+ final RaceDefinition race = trackedRace.getRace();
167
+ Iterable<Competitor> masterCompetitors = race.getCompetitors();
168
+ assertEquals(Util.size(masterCompetitors), 6);
169
+ final RaceHandle newHandle = service.updateRaceCompetitors(trackedRace.getTrackedRegatta().getRegatta(), race);
170
+ final RaceDefinition newRace = newHandle.getRace(RaceTracker.TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS);
171
+ assertNotNull(newRace);
172
+ assertEquals(race.getId(), newRace.getId());
173
+ assertNotSame(race, newRace);
174
+ racesHandle = newHandle; // ensure that tearDown tears down the correct tracker
175
+ }
176
+
177
+ @After
178
+ public void tearDown() throws Exception {
179
+ if (racesHandle != null) {
180
+ racesHandle.getRaceTracker().stop(/* preemptive */ false);
181
+ }
182
+ }
183
+}
java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java
... ...
@@ -2760,7 +2760,8 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
2760 2760
final RaceTrackingConnectivityParameters connectivityParams = connectivityParametersByRace.get(race);
2761 2761
if (connectivityParams != null) {
2762 2762
removeRace(regatta, race);
2763
- result = addRace(regatta.getRegattaIdentifier(), connectivityParams, RaceTracker.TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS);
2763
+ result = addRace(regatta.getRegattaIdentifier(), connectivityParams, RaceTracker.TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS,
2764
+ new DefaultRaceTrackingHandler()); // no need for ownership setting here because we're only "re-tracking" an existing race
2764 2765
} else {
2765 2766
result = null;
2766 2767
logger.warning("Unable to update race competitors for race "+race+" in regatta "+regatta+
java/com.sap.sse.gwt/.project
... ...
@@ -10,6 +10,16 @@
10 10
<arguments>
11 11
</arguments>
12 12
</buildCommand>
13
+ <buildCommand>
14
+ <name>org.eclipse.pde.ManifestBuilder</name>
15
+ <arguments>
16
+ </arguments>
17
+ </buildCommand>
18
+ <buildCommand>
19
+ <name>org.eclipse.pde.SchemaBuilder</name>
20
+ <arguments>
21
+ </arguments>
22
+ </buildCommand>
13 23
<buildCommand>
14 24
<name>com.gwtplugins.gdt.eclipse.core.webAppProjectValidator</name>
15 25
<arguments>
java/com.sap.sse.gwt/GWT xdStorage Sample SDM.launch
... ...
@@ -51,6 +51,7 @@
51 51
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.gwtplugins.gwt.eclipse.core.moduleClasspathProvider"/>
52 52
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
53 53
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
54
+<stringAttribute key="org.eclipse.jdt.launching.MODULE_NAME" value="com.sap.sse.gwt"/>
54 55
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-style PRETTY -incremental -workDir &quot;${project_loc:com.sap.sse.gwt}/.tmp/gwt-work&quot; -war &quot;${project_loc:com.sap.sse.gwt}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort 9877 -startupUrl /gwt-base/StorageMessagingTest.html -startupUrl /gwt-base/StorageMessaging.html com.sap.sse.gwt.StorageMessaging com.sap.sse.gwt.StorageMessagingTest"/>
55 56
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sse.gwt"/>
56 57
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XX:+UseG1GC -XX:+UseStringDeduplication -Dgwt.watchFileChanges=false -Xmx2048m -Dgwt-usearchives=false -Dgwt.persistentunitcache=false"/>
java/com.sap.sse.gwt/META-INF/MANIFEST.MF
... ...
@@ -59,11 +59,9 @@ Export-Package: com.google.gwt.user.client.rpc.core.java.util,
59 59
com.sap.sse.gwt.client.useragent,
60 60
com.sap.sse.gwt.client.xdstorage,
61 61
com.sap.sse.gwt.common,
62
- com.sap.sse.gwt.dispatch.client,
63 62
com.sap.sse.gwt.dispatch.client.system,
64 63
com.sap.sse.gwt.dispatch.client.system.batching,
65 64
com.sap.sse.gwt.dispatch.client.system.caching,
66
- com.sap.sse.gwt.dispatch.client.system.routing,
67 65
com.sap.sse.gwt.dispatch.client.transport.gwtrpc,
68 66
com.sap.sse.gwt.dispatch.servlets,
69 67
com.sap.sse.gwt.dispatch.shared.caching,
... ...
@@ -73,7 +71,6 @@ Export-Package: com.google.gwt.user.client.rpc.core.java.util,
73 71
com.sap.sse.gwt.resources,
74 72
com.sap.sse.gwt.server,
75 73
com.sap.sse.gwt.server.filestorage,
76
- com.sap.sse.gwt.server.replication,
77 74
com.sap.sse.gwt.settings,
78 75
com.sap.sse.gwt.shared,
79 76
com.sap.sse.gwt.shared.filestorage,
wiki/howto/onboarding.md
... ...
@@ -114,6 +114,7 @@ The primary Git repository for the project is hosted on sapsailing.com. It is mi
114 114
4. On clear workspace additional steps should be performed once:
115 115
1. Run "GWT Dashboards SDM" launch configuration. After successful start, launch configuration can be stopped.
116 116
2. Run "GWT Security SDM" launch configuration. After successful start, launch configuration can be stopped.
117
+ 3. Run "GWT xdStorage Sample SDM" launch configuration. After successful start, launch configuration can be stopped.
117 118
5. Run the Race Analysis Suite
118 119
* Start the MongoDB (cd /somePathTo MongoDB/mongodb/bin; rm c:/data/SAP/sailing/mongodb/mongod.lock; ./mongod --dbpath c:/data/SAP/sailing/mongodb)
119 120
* Start the appropriate Eclipse launch configuration (e.g. 'Sailing Server (no Proxy)') You´ll find this in the debug dropdown