cache ranks in tracked legs for the duration of one getLeaderboardByName call and use where needed

This commit is contained in:
Axel Uhl committed 2012-07-22 01:04:31 +02:00
1 parent 9cbb07ab4b
commit d17861b61a
12 files changed
+129 -52

No files matched your search

@@ -249,7 +249,7 @@ public abstract class AbstractLeaderboardImpl implements Leaderboard, RaceColumn
* or otherwise a rank improved (lowered) by the number of disqualifications of competitors whose tracked rank is better (lower)
* than <code>rank</code>.
*/
private int improveByDisqualificationsOfBetterRankedCompetitors(RaceColumn raceColumn, TrackedRace trackedRace, TimePoint timePoint, int rank) {
private int improveByDisqualificationsOfBetterRankedCompetitors(RaceColumn raceColumn, TrackedRace trackedRace, TimePoint timePoint, int rank) throws NoWindException {
int correctedRank = rank;
List<Competitor> competitorsFromBestToWorst = trackedRace.getCompetitorsFromBestToWorst(timePoint);
int betterCompetitorRank=1;
@@ -115,6 +115,12 @@ public interface TrackedLegOfCompetitor extends Serializable {
* competitor hasn't started the leg yet.
*/
Double getGapToLeaderInSeconds(TimePoint timePoint) throws NoWindException;
/**
* If a caller already went through the effort of computing the leg's leader at <code>timePoint</code>, it
* can share this knowledge to speed up computation as compared to {@link #getGapToLeaderInSeconds(TimePoint)}.
*/
Double getGapToLeaderInSeconds(TimePoint timePoint, Competitor leaderInLegAtTimePoint) throws NoWindException;
boolean hasStartedLeg(TimePoint timePoint);
@@ -412,7 +412,7 @@ public interface TrackedRace extends Serializable {
* Returns the competitors of this tracked race, according to their ranking. Competitors whose {@link #getRank(Competitor)} is 0 will
* be sorted "worst".
*/
List<Competitor> getCompetitorsFromBestToWorst(TimePoint timePoint);
List<Competitor> getCompetitorsFromBestToWorst(TimePoint timePoint) throws NoWindException;
Distance getAverageCrossTrackError(Competitor competitor, TimePoint from, TimePoint to, boolean upwindOnly, boolean waitForLatestAnalyses) throws NoWindException;
@@ -2,10 +2,14 @@ package com.sap.sailing.domain.tracking.impl;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.NavigableSet;
import java.util.SortedSet;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.common.Distance;
import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.tracking.MarkPassing;
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
@@ -29,12 +33,20 @@ public class RaceRankComparator implements Comparator<Competitor> {
private final TrackedRace trackedRace;
private final TimePoint timePoint;
private final DummyMarkPassingWithTimePointOnly markPassingWithTimePoint;
private final Map<Competitor, Distance> windwardDistanceToGoInLegCache;
public RaceRankComparator(TrackedRace trackedRace, TimePoint timePoint) {
public RaceRankComparator(TrackedRace trackedRace, TimePoint timePoint) throws NoWindException {
super();
this.trackedRace = trackedRace;
this.timePoint = timePoint;
this.markPassingWithTimePoint = new DummyMarkPassingWithTimePointOnly(timePoint);
this.windwardDistanceToGoInLegCache = new HashMap<Competitor, Distance>();
for (Competitor competitor : trackedRace.getRace().getCompetitors()) {
final TrackedLegOfCompetitor trackedLegOfCompetitor = trackedRace.getTrackedLeg(competitor, timePoint);
if (trackedLegOfCompetitor != null) {
windwardDistanceToGoInLegCache.put(competitor, trackedLegOfCompetitor.getWindwardDistanceToGo(timePoint));
}
}
}
@Override
@@ -91,7 +103,10 @@ public class RaceRankComparator implements Comparator<Competitor> {
result = trackedRace.getRace().getCourse().getLegs().indexOf(o1Leg.getLeg()) -
trackedRace.getRace().getCourse().getLegs().indexOf(o2Leg.getLeg());
} else {
result = new WindwardToGoComparator(trackedRace.getTrackedLeg(o1Leg.getLeg()), timePoint).compare(o1Leg, o2Leg);
// competitors are in same leg; compare their windward distance to go
final Distance wwdtgO1 = windwardDistanceToGoInLegCache.get(o1);
final Distance wwdtgO2 = windwardDistanceToGoInLegCache.get(o2);
result = wwdtgO1==null?wwdtgO2==null?0:-1:wwdtgO2==null?1:wwdtgO1.compareTo(wwdtgO2);
}
}
}
@@ -399,7 +399,31 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor {
}
@Override
public Double getGapToLeaderInSeconds(TimePoint timePoint) throws NoWindException {
public Double getGapToLeaderInSeconds(TimePoint timePoint, final Competitor leaderInLegAtTimePoint)
throws NoWindException {
return getGapToLeaderInSeconds(timePoint, new LeaderGetter() {
@Override
public Competitor getLeader() {
return leaderInLegAtTimePoint;
}
});
}
private static interface LeaderGetter {
Competitor getLeader();
}
@Override
public Double getGapToLeaderInSeconds(final TimePoint timePoint) throws NoWindException {
return getGapToLeaderInSeconds(timePoint, new LeaderGetter() {
@Override
public Competitor getLeader() {
return getTrackedLeg().getLeader(timePoint);
}
});
}
private Double getGapToLeaderInSeconds(TimePoint timePoint, LeaderGetter leaderGetter) throws NoWindException {
// If the leader already completed this leg, compute the estimated arrival time at the
// end of this leg; if this leg's competitor also already finished the leg, return the
// difference between this competitor's leg completion time point and the leader's completion
@@ -444,7 +468,7 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor {
}
}
// no-one has finished this leg yet at timePoint
Competitor leader = getTrackedLeg().getLeader(timePoint);
Competitor leader = leaderGetter.getLeader();
// Maybe our competitor is the leader. Check:
if (leader == getCompetitor()) {
return 0.0; // the leader's gap to the leader
@@ -736,7 +736,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
}
@Override
public List<Competitor> getCompetitorsFromBestToWorst(TimePoint timePoint) {
public List<Competitor> getCompetitorsFromBestToWorst(TimePoint timePoint) throws NoWindException {
ReadWriteLock readWriteLock;
synchronized (competitorRankingsLocks) {
readWriteLock = competitorRankingsLocks.get(timePoint);
@@ -359,4 +359,5 @@ public interface StringMessages extends Messages {
String pleaseEnterNonEmptyUrl();
String addFragUrl();
String errorAddingFragUrl(String message);
String errorTryingToObtainLeaderboardContents(String message);
}
@@ -357,4 +357,5 @@ successfullyUpdatedFregUrls=Successrully updated FREG URL list
errorRemovingFregUrls=Error removing FREG URLs: {0}
pleaseEnterNonEmptyUrl=Please enter a non-empty URL
addFragUrl=Add FRAG Result URL
errorAddingFragUrl=Error adding FRAG URL: {0}
errorAddingFragUrl=Error adding FRAG URL: {0}
errorTyingToObtainLeaderboardContents=Error trying to obtain leaderboard contents: {0}
@@ -358,4 +358,5 @@ successfullyUpdatedFregUrls=FREG URL-Liste erfolgreich aktualisiert
errorRemovingFregUrls=Fehler beim Löschen von FREG URLs: {0}
pleaseEnterNonEmptyUrl=Bitte eine nicht-leere URL eingeben
addFragUrl=FRAG Ergebnis-URL hinzufügen
errorAddingFragUrl=Fehler beim Hinzufügen einer FREG URL: {0}
errorAddingFragUrl=Fehler beim Hinzufügen einer FREG URL: {0}
errorTyingToObtainLeaderboardContents=Fehler beim Berechnen der Ergebnisliste: {0}
@@ -591,7 +591,8 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
@Override
public void onFailure(Throwable caught) {
getErrorReporter().reportError(
"Error trying to obtain leaderboard contents: " + caught.getMessage());
stringMessages.errorTryingToObtainLeaderboardContents(caught.getMessage()),
/* silentMode */ timer.getPlayMode() == PlayModes.Live);
}
});
}
@@ -450,6 +450,25 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
result.rows = new HashMap<CompetitorDTO, LeaderboardRowDTO>();
result.hasCarriedPoints = leaderboard.hasCarriedPoints();
result.discardThresholds = leaderboard.getResultDiscardingRule().getDiscardIndexResultsStartingWithHowManyRaces();
// Computing the competitor leg ranks is expensive, especially in live mode, in case new events keep invalidating
// the ranks cache in TrackedLegImpl. Then problem then is that the sorting based on wind data is repeated for each
// competitor, leading to square effort. We therefore need to compute the leg ranks for those race where leg details
// are requested only once and pass them into getLeaderboardEntryDTO TODO
final Map<Leg, LinkedHashMap<Competitor, Integer>> legRanksCache = new HashMap<Leg, LinkedHashMap<Competitor,Integer>>();
for (final RaceColumn raceColumn : leaderboard.getRaceColumns()) {
// if details for the column are requested, cache the leg's ranks
if (namesOfRaceColumnsForWhichToLoadLegDetails != null
&& namesOfRaceColumnsForWhichToLoadLegDetails.contains(raceColumn.getName())) {
for (Fleet fleet : raceColumn.getFleets()) {
TrackedRace trackedRace = raceColumn.getTrackedRace(fleet);
if (trackedRace != null) {
for (TrackedLeg trackedLeg : trackedRace.getTrackedLegs()) {
legRanksCache.put(trackedLeg.getLeg(), trackedLeg.getRanks(timePoint));
}
}
}
}
}
for (final Competitor competitor : leaderboard.getCompetitorsFromBestToWorst(timePoint)) {
CompetitorDTO competitorDTO = getCompetitorDTO(competitor);
LeaderboardRowDTO row = new LeaderboardRowDTO();
@@ -467,7 +486,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
return getLeaderboardEntryDTO(entry, raceColumn.getTrackedRace(competitor), competitor, timePoint,
namesOfRaceColumnsForWhichToLoadLegDetails != null
&& namesOfRaceColumnsForWhichToLoadLegDetails.contains(raceColumn.getName()),
waitForLatestAnalyses);
waitForLatestAnalyses, legRanksCache);
} catch (NoWindException e) {
throw new NoWindError(e);
}
@@ -510,9 +529,11 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
* if <code>false</code>, this method is allowed to read the maneuver analysis results from a cache that
* may not reflect all data already received; otherwise, the method will always block for the latest
* cache updates to have happened before returning.
* @param legRanksCache TODO
*/
private LeaderboardEntryDTO getLeaderboardEntryDTO(Entry entry, TrackedRace trackedRace, Competitor competitor,
TimePoint timePoint, boolean addLegDetails, boolean waitForLatestAnalyses) throws NoWindException {
TimePoint timePoint, boolean addLegDetails, boolean waitForLatestAnalyses,
Map<Leg, LinkedHashMap<Competitor, Integer>> legRanksCache) throws NoWindException {
LeaderboardEntryDTO entryDTO = new LeaderboardEntryDTO();
entryDTO.race = trackedRace == null ? null : trackedRace.getRaceIdentifier();
entryDTO.netPoints = entry.getNetPoints();
@@ -522,7 +543,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
entryDTO.discarded = entry.isDiscarded();
if (addLegDetails && trackedRace != null) {
try {
RaceDetails raceDetails = getRaceDetails(trackedRace, competitor, timePoint, waitForLatestAnalyses);
RaceDetails raceDetails = getRaceDetails(trackedRace, competitor, timePoint, waitForLatestAnalyses, legRanksCache);
entryDTO.legDetails = raceDetails.getLegDetails();
entryDTO.windwardDistanceToOverallLeaderInMeters = raceDetails.getWindwardDistanceToOverallLeader() == null ? null
: raceDetails.getWindwardDistanceToOverallLeader().getMeters();
@@ -567,25 +588,25 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
* way equals the end of the tracking time, the query results will be looked up in a cache first and if not found,
* they will be stored to the cache after calculating them. A cache invalidation {@link RaceChangeListener listener}
* will be registered with the race which will be triggered for any event received by the race.
*
* @param waitForLatestAnalyses
* if <code>false</code>, this method is allowed to read the maneuver analysis results from a cache that
* may not reflect all data already received; otherwise, the method will always block for the latest
* cache updates to have happened before returning.
*/
private RaceDetails getRaceDetails(TrackedRace trackedRace, Competitor competitor, TimePoint timePoint,
boolean waitForLatestAnalyses) throws NoWindException, InterruptedException, ExecutionException {
boolean waitForLatestAnalyses, Map<Leg, LinkedHashMap<Competitor, Integer>> legRanksCache) throws NoWindException, InterruptedException, ExecutionException {
RaceDetails raceDetails;
if (trackedRace.getEndOfTracking() != null && trackedRace.getEndOfTracking().compareTo(timePoint) < 0) {
raceDetails = getRaceDetailsForEndOfTrackingFromCacheOrCalculateAndCache(trackedRace, competitor);
raceDetails = getRaceDetailsForEndOfTrackingFromCacheOrCalculateAndCache(trackedRace, competitor, legRanksCache);
} else {
raceDetails = calculateRaceDetails(trackedRace, competitor, timePoint, waitForLatestAnalyses);
raceDetails = calculateRaceDetails(trackedRace, competitor, timePoint, waitForLatestAnalyses, legRanksCache);
}
return raceDetails;
}
private RaceDetails getRaceDetailsForEndOfTrackingFromCacheOrCalculateAndCache(final TrackedRace trackedRace,
final Competitor competitor) throws NoWindException, InterruptedException, ExecutionException {
final Competitor competitor, final Map<Leg, LinkedHashMap<Competitor, Integer>> legRanksCache)
throws NoWindException, InterruptedException, ExecutionException {
final Pair<TrackedRace, Competitor> key = new Pair<TrackedRace, Competitor>(trackedRace, competitor);
RunnableFuture<RaceDetails> raceDetails;
synchronized (raceDetailsAtEndOfTrackingCache) {
@@ -595,7 +616,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
@Override
public RaceDetails call() throws Exception {
return calculateRaceDetails(trackedRace, competitor, trackedRace.getEndOfTracking(),
/* waitForLatestManeuverAnalysis */ true /* because this is done only once after end of tracking */);
/* waitForLatestManeuverAnalysis */ true /* because this is done only once after end of tracking */, legRanksCache);
}
});
raceDetailsExecutor.execute(raceDetails);
@@ -689,7 +710,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
}
private RaceDetails calculateRaceDetails(TrackedRace trackedRace, Competitor competitor, TimePoint timePoint,
boolean waitForLatestAnalyses) throws NoWindException {
boolean waitForLatestAnalyses, Map<Leg, LinkedHashMap<Competitor, Integer>> legRanksCache) throws NoWindException {
List<LegEntryDTO> legDetails;
legDetails = new ArrayList<LegEntryDTO>();
final Course course = trackedRace.getRace().getCourse();
@@ -702,7 +723,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
// immediately. Make sure we're tolerant against disappearing legs! See bug 794.
TrackedLegOfCompetitor trackedLeg = trackedRace.getTrackedLeg(competitor, leg);
if (trackedLeg != null && trackedLeg.hasStartedLeg(timePoint)) {
legEntry = createLegEntry(trackedLeg, timePoint, waitForLatestAnalyses);
legEntry = createLegEntry(trackedLeg, timePoint, waitForLatestAnalyses, legRanksCache);
} else {
legEntry = null;
}
@@ -719,7 +740,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
}
private LegEntryDTO createLegEntry(TrackedLegOfCompetitor trackedLeg, TimePoint timePoint,
boolean waitForLatestAnalyses) throws NoWindException {
boolean waitForLatestAnalyses, Map<Leg, LinkedHashMap<Competitor, Integer>> legRanksCache) throws NoWindException {
LegEntryDTO result;
if (trackedLeg == null) {
result = null;
@@ -742,8 +763,14 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
result.estimatedTimeToNextWaypointInSeconds = trackedLeg.getEstimatedTimeToNextMarkInSeconds(timePoint);
result.timeInMilliseconds = trackedLeg.getTimeInMilliSeconds(timePoint);
result.finished = trackedLeg.hasFinishedLeg(timePoint);
result.gapToLeaderInSeconds = trackedLeg.getGapToLeaderInSeconds(timePoint);
result.rank = trackedLeg.getRank(timePoint);
result.gapToLeaderInSeconds = trackedLeg.getGapToLeaderInSeconds(timePoint,
legRanksCache.get(trackedLeg.getLeg()).entrySet().iterator().next().getKey());
LinkedHashMap<Competitor, Integer> legRanks = legRanksCache.get(trackedLeg.getLeg());
if (legRanks != null) {
result.rank = legRanks.get(trackedLeg.getCompetitor());
} else {
result.rank = trackedLeg.getRank(timePoint);
}
result.started = trackedLeg.hasStartedLeg(timePoint);
Speed velocityMadeGood;
if (trackedLeg.hasFinishedLeg(timePoint)) {
@@ -1,28 +1,29 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.pde.ui.EquinoxLauncher">
<booleanAttribute key="append.args" value="true"/>
<booleanAttribute key="automaticAdd" value="false"/>
<booleanAttribute key="automaticValidate" value="false"/>
<stringAttribute key="bootstrap" value=""/>
<stringAttribute key="checked" value="[NONE]"/>
<booleanAttribute key="clearConfig" value="false"/>
<stringAttribute key="configLocation" value="${workspace_loc}/target"/>
<booleanAttribute key="default" value="true"/>
<booleanAttribute key="default_auto_start" value="true"/>
<intAttribute key="default_start_level" value="4"/>
<booleanAttribute key="includeOptional" value="true"/>
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
</listAttribute>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog -console -clean"/>
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y -Declipse.ignoreApp=true -Dosgi.noShutdown=true -Xmx2048m -Djetty.home=${project_loc:com.sap.sailing.server}/../target/configuration/jetty -Djava.util.logging.config.file=${project_loc:com.sap.sailing.server}/../target/configuration/logging_debug.properties -Dkiwo.results=${project_loc:com.sap.sailing.kiworesultimport.test}/resources"/>
<stringAttribute key="pde.version" value="3.3"/>
<booleanAttribute key="show_selected_only" value="false"/>
<stringAttribute key="target_bundles" value="com.rabbitmq.client@default:default,javax.servlet@default:default,jcl.over.slf4j@default:default,org.apache.activemq.activeio-core@default:default,org.apache.activemq.activemq-core@default:default,org.apache.activemq.kahadb@default:default,org.apache.geronimo.specs.geronimo-annotation_1.0_spec@default:default,org.apache.geronimo.specs.geronimo-j2ee-management_1.1_spec@default:default,org.apache.geronimo.specs.geronimo-jms_1.1_spec@default:default,org.eclipse.equinox.transforms.hook@default:false,org.eclipse.jetty.continuation@default:default,org.eclipse.jetty.deploy@default:default,org.eclipse.jetty.http@default:default,org.eclipse.jetty.io@default:default,org.eclipse.jetty.jmx@default:default,org.eclipse.jetty.nested@default:default,org.eclipse.jetty.osgi.boot@default:default,org.eclipse.jetty.security@default:default,org.eclipse.jetty.server@default:default,org.eclipse.jetty.servlet@default:default,org.eclipse.jetty.util@default:default,org.eclipse.jetty.webapp@default:default,org.eclipse.jetty.xml@default:default,org.eclipse.osgi.services@default:default,org.eclipse.osgi@-1:true,slf4j.api@default:default,slf4j.jdk14@default:false"/>
<booleanAttribute key="tracing" value="false"/>
<booleanAttribute key="useCustomFeatures" value="false"/>
<booleanAttribute key="useDefaultConfigArea" value="false"/>
<stringAttribute key="workspace_bundles" value="com.google.gwt.osgi@default:default,com.googlecode.java-diff-utils@default:default,com.mongodb.driver@default:default,com.sap.sailing.declination@default:default,com.sap.sailing.domain.common@default:default,com.sap.sailing.domain.persistence@default:default,com.sap.sailing.domain.swisstimingadapter.persistence@default:default,com.sap.sailing.domain.swisstimingadapter@default:default,com.sap.sailing.domain.tractracadapter.persistence@default:default,com.sap.sailing.domain.tractracadapter@default:default,com.sap.sailing.domain@default:default,com.sap.sailing.ess40.resultimport@default:default,com.sap.sailing.expeditionconnector@default:default,com.sap.sailing.freg.resultimport@default:default,com.sap.sailing.geocoding@default:default,com.sap.sailing.gwt.ui@default:default,com.sap.sailing.kiworesultimport@default:default,com.sap.sailing.mongodb@default:default,com.sap.sailing.operationaltransformation@default:default,com.sap.sailing.server.replication@default:default,com.sap.sailing.server@default:default,com.sap.sailing.udpconnector@default:default,com.sap.sailing.www.events@default:default,com.sap.sailing.www@default:default,com.sap.sailing.xcelsiusadapter@default:default,com.tractrac.clientmodule@default:default,org.json.simple@default:default,org.moxieapps.gwt.highcharts@default:default"/>
</launchConfiguration>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.pde.ui.EquinoxLauncher">
<booleanAttribute key="append.args" value="true"/>
<booleanAttribute key="automaticAdd" value="false"/>
<booleanAttribute key="automaticValidate" value="false"/>
<stringAttribute key="bootstrap" value=""/>
<stringAttribute key="checked" value="[NONE]"/>
<booleanAttribute key="clearConfig" value="false"/>
<stringAttribute key="configLocation" value="${workspace_loc}/target"/>
<booleanAttribute key="default" value="true"/>
<booleanAttribute key="default_auto_start" value="true"/>
<intAttribute key="default_start_level" value="4"/>
<booleanAttribute key="includeOptional" value="true"/>
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
</listAttribute>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/sapjvm_7"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog -console -clean"/>
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y -Declipse.ignoreApp=true -Dosgi.noShutdown=true -Xmx2048m -Djetty.home=${project_loc:com.sap.sailing.server}/../target/configuration/jetty -Djava.util.logging.config.file=${project_loc:com.sap.sailing.server}/../target/configuration/logging_debug.properties -Dkiwo.results=${project_loc:com.sap.sailing.kiworesultimport.test}/resources"/>
<stringAttribute key="pde.version" value="3.3"/>
<booleanAttribute key="show_selected_only" value="false"/>
<stringAttribute key="target_bundles" value="com.rabbitmq.client@default:default,javax.servlet@default:default,jcl.over.slf4j@default:default,org.apache.activemq.activeio-core@default:default,org.apache.activemq.activemq-core@default:default,org.apache.activemq.kahadb@default:default,org.apache.geronimo.specs.geronimo-annotation_1.0_spec@default:default,org.apache.geronimo.specs.geronimo-j2ee-management_1.1_spec@default:default,org.apache.geronimo.specs.geronimo-jms_1.1_spec@default:default,org.eclipse.equinox.transforms.hook@default:false,org.eclipse.jetty.continuation@default:default,org.eclipse.jetty.deploy@default:default,org.eclipse.jetty.http@default:default,org.eclipse.jetty.io@default:default,org.eclipse.jetty.jmx@default:default,org.eclipse.jetty.nested@default:default,org.eclipse.jetty.osgi.boot@default:default,org.eclipse.jetty.security@default:default,org.eclipse.jetty.server@default:default,org.eclipse.jetty.servlet@default:default,org.eclipse.jetty.util@default:default,org.eclipse.jetty.webapp@default:default,org.eclipse.jetty.xml@default:default,org.eclipse.osgi.services@default:default,org.eclipse.osgi@-1:true,slf4j.api@default:default,slf4j.jdk14@default:false"/>
<booleanAttribute key="tracing" value="false"/>
<booleanAttribute key="useCustomFeatures" value="false"/>
<booleanAttribute key="useDefaultConfigArea" value="false"/>
<stringAttribute key="workspace_bundles" value="com.google.gwt.osgi@default:default,com.googlecode.java-diff-utils@default:default,com.mongodb.driver@default:default,com.sap.sailing.declination@default:default,com.sap.sailing.domain.common@default:default,com.sap.sailing.domain.persistence@default:default,com.sap.sailing.domain.swisstimingadapter.persistence@default:default,com.sap.sailing.domain.swisstimingadapter@default:default,com.sap.sailing.domain.tractracadapter.persistence@default:default,com.sap.sailing.domain.tractracadapter@default:default,com.sap.sailing.domain@default:default,com.sap.sailing.ess40.resultimport@default:default,com.sap.sailing.expeditionconnector@default:default,com.sap.sailing.freg.resultimport@default:default,com.sap.sailing.geocoding@default:default,com.sap.sailing.gwt.ui@default:default,com.sap.sailing.kiworesultimport@default:default,com.sap.sailing.mongodb@default:default,com.sap.sailing.operationaltransformation@default:default,com.sap.sailing.server.replication@default:default,com.sap.sailing.server@default:default,com.sap.sailing.udpconnector@default:default,com.sap.sailing.www.events@default:default,com.sap.sailing.www@default:default,com.sap.sailing.xcelsiusadapter@default:default,com.tractrac.clientmodule@default:default,org.json.simple@default:default,org.moxieapps.gwt.highcharts@default:default"/>
</launchConfiguration>