Merge remote-tracking branch 'origin/master' into mark-rounding-inference

This commit is contained in:
Nicolas committed 2014-05-15 01:12:13 +02:00
commit 3ee3c00a14
15 files changed
+491 -311

No files matched your search

@@ -6,6 +6,8 @@ import java.util.List;
import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.Venue;
import com.sap.sailing.util.impl.LockUtil;
import com.sap.sailing.util.impl.NamedReentrantReadWriteLock;
public class VenueImpl implements Venue {
private static final long serialVersionUID = 6854152040737643290L;
@@ -16,25 +18,43 @@ public class VenueImpl implements Venue {
* "NATO alphabet" (Alpha, Bravo, Charlie, ...).
*/
private final List<CourseArea> courseAreas;
private final NamedReentrantReadWriteLock courseAreasLock;
public VenueImpl(String name) {
this.name = name;
courseAreas = new ArrayList<CourseArea>();
courseAreasLock = new NamedReentrantReadWriteLock("Course Areas for venue "+name, /* fair */ false);
}
@Override
public Iterable<CourseArea> getCourseAreas() {
return Collections.unmodifiableList(courseAreas);
LockUtil.lockForRead(courseAreasLock);
try {
return Collections.unmodifiableList(courseAreas);
} finally {
LockUtil.unlockAfterRead(courseAreasLock);
}
}
@Override
public void addCourseArea(CourseArea courseArea) {
courseAreas.add(courseArea);
LockUtil.lockForWrite(courseAreasLock);
try {
courseAreas.add(courseArea);
} finally {
LockUtil.unlockAfterWrite(courseAreasLock);
}
}
@Override
public void removeCourseArea(CourseArea courseArea) {
courseAreas.remove(courseArea);
LockUtil.lockForWrite(courseAreasLock);
try {
courseAreas.remove(courseArea);
} finally {
LockUtil.unlockAfterWrite(courseAreasLock);
}
}
@Override
@@ -48,7 +48,7 @@ public class DummyTrackedRegattaRegistry implements TrackedRegattaRegistry {
}
@Override
public boolean isRaceBeingTracked(RaceDefinition r) {
public boolean isRaceBeingTracked(Regatta regattaContext, RaceDefinition r) {
return false;
}
@@ -140,7 +140,7 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest {
return null;
}
@Override
public boolean isRaceBeingTracked(RaceDefinition r) {
public boolean isRaceBeingTracked(Regatta regattaContext, RaceDefinition r) {
return true;
}
@Override
@@ -4,12 +4,16 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import org.junit.Ignore;
import org.junit.Test;
import com.sap.sailing.domain.test.measurements.Measurement;
import com.sap.sailing.domain.test.measurements.MeasurementCase;
import com.sap.sailing.domain.test.measurements.MeasurementXMLFile;
import com.sap.sailing.util.impl.LockUtil;
import com.sap.sailing.util.impl.NamedReentrantReadWriteLock;
@@ -52,17 +56,46 @@ public class LockTraceTest {
assertFalse(lock.getReaders().contains(Thread.currentThread()));
assertEquals(0, lock.getReadHoldCount());
}
@Test
public void testReentrantWriteLockingWithInBetweenReadLocking() {
NamedReentrantReadWriteLock lock = new NamedReentrantReadWriteLock("testReentrantWriteLockingWithInBetweenReadLocking-Lock", /* fair */ false);
LockUtil.lockForWrite(lock);
assertTrue(lock.getWriter() == Thread.currentThread());
LockUtil.lockForRead(lock); // reentrant read while holding write
assertTrue(lock.getReaders().contains(Thread.currentThread()));
LockUtil.lockForWrite(lock); // reentrant write
assertTrue(lock.getWriter() == Thread.currentThread());
assertTrue(lock.getReaders().contains(Thread.currentThread()));
LockUtil.unlockAfterRead(lock);
assertFalse(lock.getReaders().contains(Thread.currentThread()));
assertEquals(0, lock.getReadHoldCount());
assertTrue(lock.getWriter() == Thread.currentThread());
assertFalse(lock.getReaders().contains(Thread.currentThread()));
assertEquals(0, lock.getReadHoldCount());
LockUtil.unlockAfterWrite(lock);
assertTrue(lock.getWriter() == Thread.currentThread());
LockUtil.unlockAfterWrite(lock);
assertFalse(lock.getWriter() == Thread.currentThread());
}
@Test
public void testLockingPerformance() {
public void testLockingPerformance() throws IOException {
NamedReentrantReadWriteLock lock = new NamedReentrantReadWriteLock("Lock", /* fair */ true);
long start = System.currentTimeMillis();
for (int i=0; i<100000; i++) {
final int count = 100000;
for (int i=0; i<count; i++) {
LockUtil.lockForRead(lock);
LockUtil.unlockAfterRead(lock);
LockUtil.lockForWrite(lock);
LockUtil.unlockAfterWrite(lock);
}
MeasurementXMLFile performanceReport = new MeasurementXMLFile(this.getClass());
MeasurementCase performanceReportCase = performanceReport.addCase(getClass().getSimpleName());
performanceReportCase.addMeasurement(new Measurement("Obtaining and releasing "+count+" read and write locks in ms",
System.currentTimeMillis()-start));
performanceReport.write();
System.out.println("Took "+(System.currentTimeMillis()-start)+"ms");
}
@@ -35,11 +35,9 @@ import com.sap.sailing.domain.tracking.impl.GPSFixMovingImpl;
public class MarkPassingCalculatorPerformanceTest extends AbstractMockedRaceMarkPassingTest {
private static LinkedHashMap<String, Long> result = new LinkedHashMap<>();
private static String className;
public MarkPassingCalculatorPerformanceTest() {
super();
className = getClass().getName();
}
protected Random rnd = new Random();
@@ -47,7 +45,7 @@ public class MarkPassingCalculatorPerformanceTest extends AbstractMockedRaceMark
@AfterClass
public static void createXMLFile() throws IOException {
MeasurementXMLFile performanceReport = new MeasurementXMLFile("TEST-MarkPassingCaculatorPerformanceTest.xml", "MarkPassingCaculatorPerformanceTest", className);
MeasurementXMLFile performanceReport = new MeasurementXMLFile(MarkPassingCalculatorPerformanceTest.class);
for (String key : result.keySet()) {
MeasurementCase performanceReportCase = performanceReport.addCase(key);
performanceReportCase.addMeasurement(new Measurement(key, result.get(key)));
@@ -27,6 +27,10 @@ public class MeasurementXMLFile {
private final Set<MeasurementCase> cases;
private final String testClassName;
public MeasurementXMLFile(Class<?> testClass) {
this("TEST-"+testClass.getSimpleName()+".xml", testClass.getSimpleName(), testClass.getName());
}
public MeasurementXMLFile(String reportFileName, String testSuiteName, String testClassName) {
this.reportFileName = reportFileName;
this.testSuiteName = testSuiteName;
@@ -21,5 +21,4 @@ public interface RaceDefinition extends Named, WithID {
Course getCourse();
Iterable<Competitor> getCompetitors();
}
@@ -112,7 +112,8 @@ public class DomainFactoryImpl extends SharedDomainFactoryImpl implements Domain
// Optional: Getting the places of the race
PlacemarkOrderDTO racePlaces = withGeoLocationData ? getRacePlaces(trackedRace) : null;
TrackedRaceDTO trackedRaceDTO = createTrackedRaceDTO(trackedRace);
RaceDTO raceDTO = new RaceDTO(raceIdentifier, trackedRaceDTO, trackedRegattaRegistry.isRaceBeingTracked(trackedRace.getRace()));
RaceDTO raceDTO = new RaceDTO(raceIdentifier, trackedRaceDTO, trackedRegattaRegistry.isRaceBeingTracked(
trackedRace.getTrackedRegatta().getRegatta(), trackedRace.getRace()));
raceDTO.places = racePlaces;
updateRaceDTOWithTrackedRaceData(trackedRace, raceDTO);
return raceDTO;
@@ -44,7 +44,7 @@ public interface TrackedRegattaRegistry {
*/
Regatta getRememberedRegattaForRace(Serializable raceID);
boolean isRaceBeingTracked(RaceDefinition r);
boolean isRaceBeingTracked(Regatta regattaContext, RaceDefinition r);
/**
* Stops all {@link RaceTracker}s currently tracking <code>race</code>. Note that if the same tracker also may have
@@ -900,7 +900,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
trackedRaceDTO = getBaseDomainFactory().createTrackedRaceDTO(trackedRace);
}
RaceWithCompetitorsDTO raceDTO = new RaceWithCompetitorsDTO(raceIdentifier, convertToCompetitorDTOs(r.getCompetitors()),
trackedRaceDTO, getService().isRaceBeingTracked(r));
trackedRaceDTO, getService().isRaceBeingTracked(regatta, r));
if (trackedRace != null) {
getBaseDomainFactory().updateRaceDTOWithTrackedRaceData(trackedRace, raceDTO);
}
@@ -15,6 +15,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentSkipListSet;
import org.junit.Before;
import org.junit.Test;
@@ -50,7 +51,7 @@ public class RaceTrackerStartStopTest {
private RacingEventServiceImplMock racingEventService;
private Regatta regatta;
private BoatClass boatClass;
private Set<RaceTracker> raceTrackerSet = new HashSet<RaceTracker>();
private ConcurrentSkipListSet<RaceTracker> raceTrackerSet = new ConcurrentSkipListSet<RaceTracker>();
private RaceDefinition raceDef1;
private RaceDefinition raceDef2;
@@ -66,10 +67,10 @@ public class RaceTrackerStartStopTest {
boatClass = new BoatClassImpl(BOATCLASSNAME, /* typicallyStartsUpwind */ true);
regatta = new RegattaImpl(EmptyRaceLogStore.INSTANCE, EVENTNAME, boatClass, /* trackedRegattaRegistry */ null,
DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), UUID.randomUUID(), null);
racingEventService.getEventsByName().put(EVENTNAME, regatta);
racingEventService.getRegattasByName().put(EVENTNAME, regatta);
TrackedRegatta trackedRegatta1 = racingEventService.getOrCreateTrackedRegatta(regatta);
racingEventService.getEventsByNameMap().put(EVENTNAME, regatta);
raceTrackerSet = new HashSet<RaceTracker>();
racingEventService.getRegattasByName().put(EVENTNAME, regatta);
raceTrackerSet = new ConcurrentSkipListSet<RaceTracker>();
raceDef1 = new RaceDefinitionImpl(RACENAME1, new CourseImpl("Course1", new ArrayList<Waypoint>()), boatClass, new ArrayList<Competitor>());
raceDef2 = new RaceDefinitionImpl(RACENAME2, new CourseImpl("Course2", new ArrayList<Waypoint>()), boatClass, new ArrayList<Competitor>());
raceDef3 = new RaceDefinitionImpl(RACENAME3, new CourseImpl("Course3", new ArrayList<Waypoint>()), boatClass, new ArrayList<Competitor>());
@@ -100,7 +101,7 @@ public class RaceTrackerStartStopTest {
raceTrackerSet.add(raceTracker1);
raceTrackerSet.add(raceTracker2);
raceTrackerSet.add(raceTracker3);
racingEventService.getRaceTrackersByEventMap().put(regatta, raceTrackerSet);
racingEventService.getRaceTrackersByRegattaMap().put(regatta, raceTrackerSet);
racingEventService.getRaceTrackersByIDMap().put(trackerID1, raceTracker1);
racingEventService.getRaceTrackersByIDMap().put(trackerID2, raceTracker2);
racingEventService.getRaceTrackersByIDMap().put(trackerID3, raceTracker3);
@@ -136,8 +137,8 @@ public class RaceTrackerStartStopTest {
assertFalse(racingEventService.getRaceTrackersByIDMap().containsValue(raceTracker3));
// The RaceTrakcersByEvent map should contain a tracker with a set of RaceDefinitions, containing the
// raceDefinition1
assertEquals(1, racingEventService.getRaceTrackersByEventMap().size());
Iterator<RaceTracker> raceTrackerIter = racingEventService.getRaceTrackersByEventMap().get(regatta).iterator();
assertEquals(1, racingEventService.getRaceTrackersByRegattaMap().size());
Iterator<RaceTracker> raceTrackerIter = racingEventService.getRaceTrackersByRegattaMap().get(regatta).iterator();
while (raceTrackerIter.hasNext()) {
RaceTracker currentTracker = raceTrackerIter.next();
assertSame(raceTracker1, currentTracker);
@@ -165,9 +166,9 @@ public class RaceTrackerStartStopTest {
}
assertFalse(foundTrackedRaceForRaceDef2);
// The trackers map should still contain the raceTrackers
assertTrue(racingEventService.getRaceTrackersByEventMap().get(regatta).contains(raceTracker1));
assertTrue(racingEventService.getRaceTrackersByEventMap().get(regatta).contains(raceTracker2));
assertTrue(racingEventService.getRaceTrackersByEventMap().get(regatta).contains(raceTracker3));
assertTrue(racingEventService.getRaceTrackersByRegattaMap().get(regatta).contains(raceTracker1));
assertTrue(racingEventService.getRaceTrackersByRegattaMap().get(regatta).contains(raceTracker2));
assertTrue(racingEventService.getRaceTrackersByRegattaMap().get(regatta).contains(raceTracker3));
// The raceTrackerMap should still contain the raceTrackers. These raceTracker should not contain the raceDefinition raceDef2 anymore
assertTrue(racingEventService.getRaceTrackersByIDMap().containsValue(raceTracker1));
assertTrue(racingEventService.getRaceTrackersByIDMap().containsValue(raceTracker2));
@@ -193,9 +194,9 @@ public class RaceTrackerStartStopTest {
racingEventService.removeRace(regatta, raceDef1);
racingEventService.removeRace(regatta, raceDef2);
// The event map should still contain the raceTrackers except of raceTracker1 and raceTracker2
assertFalse(racingEventService.getRaceTrackersByEventMap().get(regatta).contains(raceTracker1));
assertFalse(racingEventService.getRaceTrackersByEventMap().get(regatta).contains(raceTracker2));
assertTrue(racingEventService.getRaceTrackersByEventMap().get(regatta).contains(raceTracker3));
assertFalse(racingEventService.getRaceTrackersByRegattaMap().get(regatta).contains(raceTracker1));
assertFalse(racingEventService.getRaceTrackersByRegattaMap().get(regatta).contains(raceTracker2));
assertTrue(racingEventService.getRaceTrackersByRegattaMap().get(regatta).contains(raceTracker3));
// The RaceTrackerByID map should still contain raceTracker3, but not raceTracker1 and raceTracker2 anymore
assertFalse(racingEventService.getRaceTrackersByIDMap().containsValue(raceTracker1));
assertFalse(racingEventService.getRaceTrackersByIDMap().containsValue(raceTracker2));
@@ -1,7 +1,7 @@
package com.sap.sailing.server.test;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentSkipListSet;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.common.impl.DataImportProgressImpl;
@@ -22,11 +22,7 @@ public class RacingEventServiceImplMock extends RacingEventServiceImpl {
lock.addProgress(dataImportProgressImpl.getOperationId(), dataImportProgressImpl);
}
public Map<String, Regatta> getEventsByNameMap() {
return regattasByName;
}
public Map<Regatta, Set<RaceTracker>> getRaceTrackersByEventMap() {
public Map<Regatta, ConcurrentSkipListSet<RaceTracker>> getRaceTrackersByRegattaMap() {
return raceTrackersByRegatta;
}
@@ -34,7 +30,7 @@ public class RacingEventServiceImplMock extends RacingEventServiceImpl {
return raceTrackersByID;
}
public Map<String, Regatta> getEventsByName() {
public Map<String, Regatta> getRegattasByName() {
return regattasByName;
}
@@ -269,6 +269,9 @@ class MediaLibrary {
}
}
/**
* Returns a non-live copy of the media tracks
*/
Collection<MediaTrack> allTracks() {
readLock.lock();
try {
File diff suppressed because it is too large. Load diff
+10
View File
@@ -4,6 +4,16 @@ Our default Hudson runs on http://hudson.sapsailing.com. If you need access, ple
It is good practice to set up a new Hudson job for major branches that require solid testing before being merged into the master branch. The entry page at http://hudson.sapsailing.com explains how to do this. It basically comes down to copying a template job and adjusting the branch name. As easy as that :-)
## Collecting measurements using Hudson/Jenkins
If you have a test case that measures something, such as performance or level of fulfillment or any other numeric measure, you can have Hudson/Jenkins plot it. In your test case, use the class `com.sap.sailing.domain.test.measurements.MeasurementXMLFile` and add performance cases to which you add measurements, e.g., as follows:
<pre>
MeasurementXMLFile performanceReport = new MeasurementXMLFile(getClass());
MeasurementCase performanceReportCase = performanceReport.addCase(getClass().getSimpleName());
performanceReportCase.addMeasurement(new Measurement("My Measurement", theNumberIMeasured));
performanceReport.write();
</pre>
## In case you'd like to set up your own Hudson/Jenkins
Initially we had trouble with Jenkins and the GIT plug-in. However, https://issues.jenkins-ci.org/browse/JENKINS-13381?focusedCommentId=196689&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-196689 explains that installing the Credentials plugin into Jenkins may help. Basically, what is needed over and above a plain Jenkins installation are the following plug-ins: