Merge branch 'master' into racecommittee_app

This commit is contained in:
Axel Uhl committed 2014-01-22 16:37:44 +01:00
commit cef3f3fa83
6 files changed
+65 -25

No files matched your search

@@ -13,6 +13,7 @@ import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.WriteConcern;
import com.mongodb.util.JSON;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.ControlPoint;
@@ -216,7 +217,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
}
storeColumnFactors(leaderboard, dbLeaderboard);
storeLeaderboardCorrectionsAndDiscards(leaderboard, dbLeaderboard);
leaderboardCollection.update(query, dbLeaderboard, /* upsrt */ true, /* multi */ false);
leaderboardCollection.update(query, dbLeaderboard, /* upsrt */ true, /* multi */ false, WriteConcern.SAFE);
}
private void storeColumnFactors(Leaderboard leaderboard, BasicDBObject dbLeaderboard) {
@@ -350,7 +351,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
DBCollection leaderboardCollection = database.getCollection(CollectionNames.LEADERBOARDS.name());
BasicDBObject query = new BasicDBObject(FieldNames.LEADERBOARD_NAME.name(), oldName);
BasicDBObject renameUpdate = new BasicDBObject("$set", new BasicDBObject(FieldNames.LEADERBOARD_NAME.name(), newName));
leaderboardCollection.update(query, renameUpdate);
leaderboardCollection.update(query, renameUpdate, /* upsert */ true, /* multi */ false, WriteConcern.SAFE);
}
@Override
@@ -392,7 +393,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
dbLeaderboardIds.add(dbLeaderboardId);
}
dbLeaderboardGroup.put(FieldNames.LEADERBOARD_GROUP_LEADERBOARDS.name(), dbLeaderboardIds);
leaderboardGroupCollection.update(query, dbLeaderboardGroup, true, false);
leaderboardGroupCollection.update(query, dbLeaderboardGroup, true, false, WriteConcern.SAFE);
}
@Override
@@ -407,7 +408,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
DBCollection leaderboardGroupCollection = database.getCollection(CollectionNames.LEADERBOARD_GROUPS.name());
BasicDBObject query = new BasicDBObject(FieldNames.LEADERBOARD_GROUP_NAME.name(), oldName);
BasicDBObject update = new BasicDBObject("$set", new BasicDBObject(FieldNames.LEADERBOARD_GROUP_NAME.name(), newName));
leaderboardGroupCollection.update(query, update);
leaderboardGroupCollection.update(query, update, /* upsert */ true, /* multi */ false, WriteConcern.SAFE);
}
@Override
@@ -423,7 +424,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
eventDBObject.put(FieldNames.EVENT_IS_PUBLIC.name(), event.isPublic());
DBObject venueDBObject = getVenueAsDBObject(event.getVenue());
eventDBObject.put(FieldNames.VENUE.name(), venueDBObject);
eventCollection.update(query, eventDBObject, /* upsrt */ true, /* multi */ false);
eventCollection.update(query, eventDBObject, /* upsrt */ true, /* multi */ false, WriteConcern.SAFE);
}
@Override
@@ -431,7 +432,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
DBCollection eventCollection = database.getCollection(CollectionNames.EVENTS.name());
BasicDBObject query = new BasicDBObject(FieldNames.EVENT_ID.name(), id);
BasicDBObject renameUpdate = new BasicDBObject("$set", new BasicDBObject(FieldNames.EVENT_NAME.name(), newName));
eventCollection.update(query, renameUpdate);
eventCollection.update(query, renameUpdate, /* upsert */ true, /* multi */ false, WriteConcern.SAFE);
}
@Override
@@ -484,7 +485,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
dbRegatta.put(FieldNames.REGATTA_REGATTA_CONFIGURATION.name(), configurationObject);
}
regattasCollection.update(query, dbRegatta, /* upsrt */ true, /* multi */ false);
regattasCollection.update(query, dbRegatta, /* upsrt */ true, /* multi */ false, WriteConcern.SAFE);
}
@Override
@@ -546,7 +547,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
DBObject query = new BasicDBObject(FieldNames.RACE_ID_AS_STRING.name(), raceIDAsString);
DBObject entry = new BasicDBObject(FieldNames.RACE_ID_AS_STRING.name(), raceIDAsString);
entry.put(FieldNames.REGATTA_NAME.name(), regatta.getName());
regattaForRaceIDCollection.update(query, entry, /* upsrt */ true, /* multi */ false);
regattaForRaceIDCollection.update(query, entry, /* upsrt */ true, /* multi */ false, WriteConcern.SAFE);
}
@Override
@@ -900,7 +901,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
JSONObject json = competitorSerializer.serialize(competitor);
DBObject query = (DBObject) JSON.parse(competitorSerializer.getCompetitorIdQuery(competitor).toString());
DBObject entry = (DBObject) JSON.parse(json.toString());
collection.update(query, entry, /* upsrt */true, /* multi */false);
collection.update(query, entry, /* upsrt */true, /* multi */false, WriteConcern.SAFE);
}
@Override
@@ -930,7 +931,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
entryObject.put(FieldNames.CONFIGURATION_MATCHER.name(), createDeviceConfigurationMatcherObject(matcher));
entryObject.put(FieldNames.CONFIGURATION_CONFIG.name(), createDeviceConfigurationObject(configuration));
configurationsCollections.update(query, entryObject, /* upsrt */ true, /* multi */ false);
configurationsCollections.update(query, entryObject, /* upsrt */ true, /* multi */ false, WriteConcern.SAFE);
}
private DBObject createDeviceConfigurationMatcherObject(DeviceConfigurationMatcher matcher) {
@@ -135,6 +135,8 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab
LockUtil.lockForWrite(lock);
try {
competitorCache.clear();
competitorsByIdAsString.clear();
competitorsToUpdateDuringGetOrCreate.clear();
} finally {
LockUtil.unlockAfterWrite(lock);
}
@@ -3,6 +3,8 @@ package com.sap.sailing.domain.test;
import java.io.Serializable;
import java.util.Collections;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CompetitorFactory;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.BoatImpl;
import com.sap.sailing.domain.base.impl.CompetitorImpl;
@@ -21,6 +23,15 @@ public abstract class AbstractLeaderboardTest {
new BoatClassImpl("505", /* typicallyStartsUpwind */ true), /* sailID */ null));
}
public static Competitor createCompetitor(String competitorName, CompetitorFactory competitorFactory) {
return competitorFactory.getOrCreateCompetitor(123, competitorName, Color.RED, new TeamImpl("STG", Collections.singleton(
new PersonImpl(competitorName, new NationalityImpl("GER"),
/* dateOfBirth */ null, "This is famous "+competitorName)),
new PersonImpl("Rigo van Maas", new NationalityImpl("NED"),
/* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat",
new BoatClassImpl("505", /* typicallyStartsUpwind */ true), /* sailID */ null));
}
public static CompetitorImpl createCompetitor(String competitorName, Serializable id) {
return new CompetitorImpl(id, competitorName, Color.RED, new TeamImpl("STG", Collections.singleton(
new PersonImpl(competitorName, new NationalityImpl("GER"),
@@ -10,13 +10,13 @@ import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
import com.sap.sailing.server.gateway.serialization.impl.NationalityJsonSerializer;
public class NationalityJsonDeserializer implements JsonDeserializer<Nationality> {
private final SharedDomainFactory domainFactory;
private final SharedDomainFactory domainFactory;
public NationalityJsonDeserializer(SharedDomainFactory domainFactory) {
this.domainFactory = domainFactory;
}
this.domainFactory = domainFactory;
}
@Override
@Override
public Nationality deserialize(JSONObject object) throws JsonDeserializationException {
final Nationality result;
if (object == null) {
@@ -3,9 +3,11 @@ package com.sap.sailing.server.replication.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.FileNotFoundException;
import java.net.UnknownHostException;
import java.util.logging.Logger;
import org.junit.Before;
import org.junit.Test;
@@ -15,13 +17,17 @@ import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceColumnListener;
import com.sap.sailing.domain.base.impl.DomainFactoryImpl;
import com.sap.sailing.domain.base.impl.DynamicCompetitor;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.RegattaNameAndRaceName;
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.domain.leaderboard.DelayedLeaderboardCorrections;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.SettableScoreCorrection;
import com.sap.sailing.domain.leaderboard.impl.LowPoint;
import com.sap.sailing.domain.persistence.PersistenceFactory;
import com.sap.sailing.domain.persistence.media.MediaDBFactory;
@@ -40,6 +46,8 @@ import com.sap.sailing.server.replication.ReplicationMasterDescriptor;
import com.sap.sailing.server.replication.ReplicationService;
public class DelayedLeaderboardCorrectionsReplicationTest extends AbstractServerReplicationTest {
private static final Logger logger = Logger.getLogger(DelayedLeaderboardCorrectionsReplicationTest.class.getName());
private static final String Q2 = "Q2";
private ReplicationService replicaReplicator;
private ReplicationMasterDescriptor masterDescriptor;
@@ -66,8 +74,9 @@ public class DelayedLeaderboardCorrectionsReplicationTest extends AbstractServer
// then start initial load, wait until finished; then link a tracked race to leaderboard's RaceColumn on master and
// verify that on the replica it is associated to the RaceColumn as well, and the DelayedLeaderboardCorrections are
// resolved properly on the replica.
BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true);
Competitor hasso = AbstractLeaderboardTest.createCompetitor("Dr. Hasso Plattner");
final DomainFactory domainFactory = DomainFactory.INSTANCE;
BoatClass boatClass = domainFactory.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true);
DynamicCompetitor hasso = AbstractLeaderboardTest.createCompetitor("Dr. Hasso Plattner"); // don't create competitor using CompetitorStore
final DynamicTrackedRace q2YellowTrackedRace = new MockedTrackedRaceWithFixedRank(hasso, /* rank */ 1, /* started */ false, boatClass) {
private static final long serialVersionUID = 1234L;
@Override
@@ -75,7 +84,7 @@ public class DelayedLeaderboardCorrectionsReplicationTest extends AbstractServer
return new RegattaNameAndRaceName("Kieler Woche (5o5)", "Yellow Race 2");
}
};
master = createRacingEventServiceWithOneMockedTrackedRace(q2YellowTrackedRace);
master = createRacingEventServiceWithOneMockedTrackedRace(q2YellowTrackedRace, domainFactory);
final String leaderboardName = "My new leaderboard";
final int[] discardThresholds = new int[] { 19, 44 };
CreateFlexibleLeaderboard createTestLeaderboard = new CreateFlexibleLeaderboard(leaderboardName, null, discardThresholds, new LowPoint(), null);
@@ -92,11 +101,14 @@ public class DelayedLeaderboardCorrectionsReplicationTest extends AbstractServer
masterLeaderboard.getRaceColumnByName(Q2), MillisecondsTimePoint.now()));
// re-load new master from persistence
master = createRacingEventServiceWithOneMockedTrackedRace(q2YellowTrackedRace);
replica = createRacingEventServiceWithOneMockedTrackedRace(q2YellowTrackedRace);
master = createRacingEventServiceWithOneMockedTrackedRace(q2YellowTrackedRace, domainFactory);
DomainFactoryImpl replicaDomainFactory = new DomainFactoryImpl();
replica = createRacingEventServiceWithOneMockedTrackedRace(q2YellowTrackedRace, replicaDomainFactory);
final Leaderboard masterLeaderboardReloaded = master.getLeaderboardByName(leaderboardName);
assertNotNull(masterLeaderboardReloaded);
// expecting the correction to only be in the DelayedLeaderboardCorrection object but not the leaderboard itself
// expecting the correction to not be in the leaderboard because the competitor was not found in the
// domain factory's competitor store while loading and therefore the score correction could not immediately
// be applied to the leaderboard's real score correction
assertEquals(MaxPointsReason.NONE, masterLeaderboardReloaded.getMaxPointsReason(hasso,
masterLeaderboardReloaded.getRaceColumnByName(Q2), MillisecondsTimePoint.now()));
@@ -104,19 +116,30 @@ public class DelayedLeaderboardCorrectionsReplicationTest extends AbstractServer
Pair<ReplicationServiceTestImpl, ReplicationMasterDescriptor> descriptors = basicSetUp(/* dropDB */ false, master, replica);
replicaReplicator = descriptors.getA();
masterDescriptor = descriptors.getB();
// starting to replicate will clear the competitor store used by the replica in this test;
// the competitor will have to be looked up again after it was received by the replica.
replicaReplicator.startToReplicateFrom(masterDescriptor);
Thread.sleep(1000);
Leaderboard replicaLeaderboard = replica.getLeaderboardByName(leaderboardName);
assertNotNull(replicaLeaderboard);
assertNotNull(replicaLeaderboard.getRaceColumnByName(Q2));
// so far, the replica should also only have the delayed corrections:
// so far, the replica should also only have the delayed corrections since during deserializing them the
// replicatedHasso competitor was not yet known to the replica's competitor store:
assertEquals(MaxPointsReason.NONE, replicaLeaderboard.getMaxPointsReason(hasso,
replicaLeaderboard.getRaceColumnByName(Q2), MillisecondsTimePoint.now()));
Leaderboard newMasterLeaderboard = master.getLeaderboardByName(masterLeaderboard.getName());
SettableScoreCorrection newMasterScoreCorrections = newMasterLeaderboard.getScoreCorrection();
RaceColumn newMasterQ2 = newMasterLeaderboard.getRaceColumnByName(Q2);
newMasterScoreCorrections.getCompetitorsThatHaveCorrectionsIn(newMasterQ2);
assertTrue(Util.isEmpty(newMasterScoreCorrections.getCompetitorsThatHaveCorrectionsIn(newMasterQ2))); // no score corrections applied yet
// now connect the tracked race again to the leaderboard column in the re-loaded environment
master.apply(new ConnectTrackedRaceToLeaderboardColumn(masterLeaderboard.getName(), Q2, /* default fleet */
masterLeaderboard.getFleet(null).getName(), q2YellowTrackedRace.getRaceIdentifier()));
logger.info("hasso object ID hash: "+System.identityHashCode(hasso));
logger.info("got score correction for competitor "+System.identityHashCode(newMasterScoreCorrections.getCompetitorsThatHaveCorrectionsIn(newMasterQ2).iterator().next()));
assertTrue(Util.contains(newMasterScoreCorrections.getCompetitorsThatHaveCorrectionsIn(newMasterQ2), hasso)); // now score corrections must have been applied from Delayed...
// now the delayed corrections are expected to have been resolved:
assertEquals(MaxPointsReason.DNF, master.getLeaderboardByName(leaderboardName).getMaxPointsReason(hasso,
master.getLeaderboardByName(leaderboardName).getRaceColumnByName(Q2), MillisecondsTimePoint.now()));
@@ -126,8 +149,9 @@ public class DelayedLeaderboardCorrectionsReplicationTest extends AbstractServer
replicaLeaderboard.getRaceColumnByName(Q2), MillisecondsTimePoint.now()));
}
private RacingEventServiceImpl createRacingEventServiceWithOneMockedTrackedRace(final DynamicTrackedRace q2YellowTrackedRace) {
return new RacingEventServiceImpl(PersistenceFactory.INSTANCE.getDomainObjectFactory(MongoDBService.INSTANCE, DomainFactory.INSTANCE), PersistenceFactory.INSTANCE
private RacingEventServiceImpl createRacingEventServiceWithOneMockedTrackedRace(final DynamicTrackedRace q2YellowTrackedRace,
DomainFactory domainFactory) {
return new RacingEventServiceImpl(PersistenceFactory.INSTANCE.getDomainObjectFactory(MongoDBService.INSTANCE, domainFactory), PersistenceFactory.INSTANCE
.getMongoObjectFactory(MongoDBService.INSTANCE), MediaDBFactory.INSTANCE.getMediaDB(MongoDBService.INSTANCE), EmptyWindStore.INSTANCE) {
@Override
public DynamicTrackedRace getExistingTrackedRace(RegattaAndRaceIdentifier raceIdentifier) {
@@ -169,6 +169,7 @@ public class LeaderboardData extends ExportAction {
addNamedElementWithValue(raceElement, "same_day_index", sameDayGroupIndex);
raceElement.addContent(createDataConfidenceXML(raceConfidenceAndErrorMessages));
addNamedElementWithValue(raceElement, "start_type", race.getTrackedLeg(race.getRace().getCourse().getFirstLeg()).getLegType(race.getStartOfRace()).name());
addNamedElementWithValue(raceElement, "delay_to_live_in_millis", race.getDelayToLiveInMillis());
addNamedElementWithValue(raceElement, "timepoint_of_last_event_as_millis", handleValue(race.getTimePointOfLastEvent()));
@@ -180,8 +181,10 @@ public class LeaderboardData extends ExportAction {
addNamedElementWithValue(raceElement, "start_of_tracking_time_as_millis", handleValue(race.getStartOfTracking()));
addNamedElementWithValue(raceElement, "end_of_tracking_time_as_millis", handleValue(race.getEndOfTracking()));
LineLengthAndAdvantage start = race.getStartLine(race.getStartOfTracking());
addNamedElementWithValue(raceElement, "start_line_length_in_meters", start.getLength().getMeters());
addNamedElementWithValue(raceElement, "course_length_in_meters", race.getCourseLength().getMeters());
raceElement.addContent(createWindXML("wind_", race.getAverageWindSpeedWithConfidence(/*resolutionInMillis*/ 5*60*1000)));
final List<Competitor> allCompetitors = race.getCompetitorsFromBestToWorst(/*timePoint*/ race.getEndOfRace());
@@ -191,7 +194,6 @@ public class LeaderboardData extends ExportAction {
for (Competitor competitor : allCompetitors) {
Element competitorElement = createCompetitorXML(competitor, leaderboard, /*shortVersion*/ true, null);
Element competitorRaceDataElement = new Element("competitor_race_data");
LineLengthAndAdvantage start = race.getStartLine(race.getStartOfTracking());
addNamedElementWithValue(competitorRaceDataElement, "distance_to_start_line_on_race_start_in_meters", race.getDistanceToStartLine(competitor, race.getStartOfRace()).getMeters());
addNamedElementWithValue(competitorRaceDataElement, "distance_from_starboard_side_of_start_line_when_passing_start_in_meters", race.getDistanceFromStarboardSideOfStartLineWhenPassingStart(competitor).getMeters());
addNamedElementWithValue(competitorRaceDataElement, "speed_when_crossing_start_line_in_knots", race.getSpeedWhenCrossingStartLine(competitor).getKnots());