Merge branch 'bug-1926-second'

This commit is contained in:
Frederik Petersen committed 2014-06-07 19:42:31 +02:00
commit b263074000
8 files changed
+146 -106

No files matched your search

@@ -0,0 +1,17 @@
package com.sap.sailing.domain.base.impl;
import com.sap.sailing.domain.racelog.RaceLogStore;
public class MasterDataImportInformation {
private final RaceLogStore raceLogStore;
public MasterDataImportInformation(RaceLogStore raceLogStore) {
this.raceLogStore = raceLogStore;
}
public RaceLogStore getRaceLogStore() {
return raceLogStore;
}
}
@@ -45,6 +45,21 @@ import com.sap.sailing.util.impl.RaceColumnListeners;
import com.sap.sse.common.Util;
public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListener {
/**
* Used during master data import to handle connection to correct RaceLogStore
*/
private static transient ThreadLocal<MasterDataImportInformation> ongoingMasterDataImportInformation = new ThreadLocal<MasterDataImportInformation>() {
@Override
protected MasterDataImportInformation initialValue() {
return null;
};
};
public static void setOngoingMasterDataImport(MasterDataImportInformation information) {
ongoingMasterDataImportInformation.set(information);
}
private static final Logger logger = Logger.getLogger(RegattaImpl.class.getName());
private static final long serialVersionUID = 6509564189552478869L;
private final Set<RaceDefinition> races;
@@ -165,16 +180,24 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
*/
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
ois.defaultReadObject();
raceLogStore = EmptyRaceLogStore.INSTANCE;
regattaListeners = new HashSet<RegattaListener>();
MasterDataImportInformation masterDataImportInformation = ongoingMasterDataImportInformation.get();
if (masterDataImportInformation != null) {
raceLogStore = masterDataImportInformation.getRaceLogStore();
} else {
raceLogStore = EmptyRaceLogStore.INSTANCE;
}
for (Series series : getSeries()) {
linkToRegattaAndConnectRaceLogsAndAddListeners(series);
if (series.getRaceColumns() != null) {
for (RaceColumnInSeries column : series.getRaceColumns()) {
column.setRaceLogInformation(new RaceLogInformationImpl(raceLogStore,
new RaceLogOnRegattaIdentifier(this, column.getName())));
}
} else {
logger.warning("Race Columns were null during deserialization. This should not happen.");
}
}
regattaListeners = new HashSet<RegattaListener>();
}
}
@Override
@@ -92,8 +92,7 @@ public class MasterDataResource extends AbstractSailingServerResource {
masterData.setMasterDataExportFlagOnRaceColumns(true);
// Actual start of streaming
objectOutputStream.writeObject(competitorIds);
objectOutputStream.writeObject(masterData);
writeObjects(competitorIds, masterData, objectOutputStream);
} finally {
objectOutputStream.close();
masterData.setMasterDataExportFlagOnRaceColumns(false);
@@ -114,9 +113,7 @@ public class MasterDataResource extends AbstractSailingServerResource {
objectOutputStream = new ObjectOutputStream(outputStreamWithByteCounter);
masterData.setMasterDataExportFlagOnRaceColumns(true);
// Actual start of streaming
objectOutputStream.writeObject(competitorIds);
objectOutputStream.writeObject(masterData);
writeObjects(competitorIds, masterData, objectOutputStream);
} finally {
objectOutputStream.close();
masterData.setMasterDataExportFlagOnRaceColumns(false);
@@ -134,6 +131,13 @@ public class MasterDataResource extends AbstractSailingServerResource {
return builtResponse;
}
private void writeObjects(final List<Serializable> competitorIds, final TopLevelMasterData masterData,
ObjectOutputStream objectOutputStream) throws IOException {
objectOutputStream.writeObject(competitorIds);
objectOutputStream.writeObject(getService().getAllRegattas());
objectOutputStream.writeObject(masterData);
}
private class ByteCountOutputStreamDecorator extends FilterOutputStream {
private long byteCount = 0;
@@ -12,6 +12,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -1189,6 +1190,10 @@ public class MasterDataImportTest {
Regatta regattaOnTarget = destService.getRegattaByName(TEST_REGATTA_NAME + " (" + TEST_BOAT_CLASS_NAME + ")");
Assert.assertNotNull(regattaOnTarget);
RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) leaderboardOnTarget;
Regatta regattaInLeaderboard = regattaLeaderboard.getRegatta();
Assert.assertSame(regattaOnTarget, regattaInLeaderboard);
Assert.assertEquals(courseAreaUUID, eventOnTarget.getVenue().getCourseAreas().iterator().next().getId());
RaceColumn raceColumnOnTarget = leaderboardOnTarget.getRaceColumnByName(raceColumnName);
@@ -1211,8 +1216,15 @@ public class MasterDataImportTest {
public void testMasterDataImportForRegattaDefaultProcedureAndDesigner() throws MalformedURLException, IOException,
InterruptedException, ClassNotFoundException {
RacingEventService sourceService = new RacingEventServiceImpl();
Iterable<URL> imageURLs = new HashSet<>();
Iterable<URL> videoURLs = new HashSet<>();
Event event = sourceService.createEventWithoutReplication("Test Event", new MillisecondsTimePoint(0),
new MillisecondsTimePoint(10), "testvenue", false, UUID.randomUUID(), imageURLs, videoURLs);
CourseArea defaultCourseArea = sourceService.addCourseArea(event.getId(), "ECHO", UUID.randomUUID());
Regatta regatta = sourceService.createRegatta(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME, UUID.randomUUID(),
new ArrayList<Series>(), true, new LowPoint(), null);
new ArrayList<Series>(), true, new LowPoint(), defaultCourseArea.getId());
// Let's use the setters directly because we are not testing replication
RegattaConfigurationImpl configuration = new RegattaConfigurationImpl();
configuration.setDefaultCourseDesignerMode(CourseDesignerMode.BY_MAP);
@@ -1269,6 +1281,12 @@ public class MasterDataImportTest {
// Setup source service
RacingEventService sourceService = new RacingEventServiceImpl();
Iterable<URL> imageURLs = new HashSet<>();
Iterable<URL> videoURLs = new HashSet<>();
Event event = sourceService.createEventWithoutReplication("Test Event", new MillisecondsTimePoint(0),
new MillisecondsTimePoint(10), "testvenue", false, UUID.randomUUID(), imageURLs, videoURLs);
CourseArea defaultCourseArea = sourceService.addCourseArea(event.getId(), "ECHO", UUID.randomUUID());
List<String> raceColumnNames = new ArrayList<String>();
String raceColumnName = "T1";
raceColumnNames.add(raceColumnName);
@@ -1282,8 +1300,9 @@ public class MasterDataImportTest {
fleets.add(new FleetImpl("testFleet2"));
series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService));
UUID regattaUUID = UUID.randomUUID();
Regatta regatta = sourceService.createRegatta(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME, regattaUUID, series,
true, new LowPoint(), null);
true, new LowPoint(), defaultCourseArea.getId());
for (String name : raceColumnNames) {
series.get(0).addRaceColumn(name, sourceService);
}
@@ -578,4 +578,10 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch
Iterable<RemoteSailingServerReference> getLiveRemoteServerReferences();
RemoteSailingServerReference getRemoteServerReferenceByName(String remoteServerReferenceName);
void addRegattaWithoutReplication(Regatta regatta);
void addEventWithoutReplication(Event event);
void addLeaderboardGroupWithoutReplication(LeaderboardGroup leaderboardGroup);
}
@@ -985,6 +985,14 @@ public class RacingEventServiceImpl implements RacingEventServiceWithTestSupport
return regatta;
}
@Override
public void addRegattaWithoutReplication(Regatta regatta) {
boolean wasAdded = addAndConnectRegatta(regatta.isPersistent(), regatta.getDefaultCourseArea().getId(), regatta);
if (!wasAdded) {
logger.info("Regatta with name " + regatta.getName() + " already existed, so it hasn't been added.");
}
}
@Override
public com.sap.sse.common.Util.Pair<Regatta, Boolean> getOrCreateRegattaWithoutReplication(String baseRegattaName, String boatClassName,
Serializable id, Iterable<? extends Series> series, boolean persistent, ScoringScheme scoringScheme,
@@ -994,6 +1002,14 @@ public class RacingEventServiceImpl implements RacingEventServiceWithTestSupport
CourseArea courseArea = getCourseArea(defaultCourseAreaId);
Regatta regatta = new RegattaImpl(raceLogStore, baseRegattaName, getBaseDomainFactory().getOrCreateBoatClass(
boatClassName), series, persistent, scoringScheme, id, courseArea);
boolean wasCreated = addAndConnectRegatta(persistent, defaultCourseAreaId, regatta);
if (wasCreated) {
logger.info("Created regatta " + regatta.getName() + " (" + hashCode() + ") on " + this);
}
return new com.sap.sse.common.Util.Pair<Regatta, Boolean>(regatta, wasCreated);
}
private boolean addAndConnectRegatta(boolean persistent, Serializable defaultCourseAreaId, Regatta regatta) {
boolean wasCreated = false;
// try a quick read protected by the concurrent hash map implementation
if (!regattasByName.containsKey(regatta.getName())) {
@@ -1013,7 +1029,6 @@ public class RacingEventServiceImpl implements RacingEventServiceWithTestSupport
LockUtil.unlockAfterWrite(regattasByNameLock);
}
}
logger.info("Created regatta " + regatta.getName() + " (" + hashCode() + ") on " + this);
if (persistent) {
updateStoredRegatta(regatta);
}
@@ -1024,7 +1039,7 @@ public class RacingEventServiceImpl implements RacingEventServiceWithTestSupport
}
}
}
return new com.sap.sse.common.Util.Pair<Regatta, Boolean>(regatta, wasCreated);
return wasCreated;
}
@Override
@@ -1869,6 +1884,22 @@ public class RacingEventServiceImpl implements RacingEventServiceWithTestSupport
return result;
}
@Override
public void addLeaderboardGroupWithoutReplication(LeaderboardGroup leaderboardGroup) {
LockUtil.lockForWrite(leaderboardGroupsByNameLock);
try {
String groupName = leaderboardGroup.getName();
if (leaderboardGroupsByName.containsKey(groupName)) {
throw new IllegalArgumentException("Leaderboard group with name " + groupName + " already exists");
}
leaderboardGroupsByName.put(groupName, leaderboardGroup);
leaderboardGroupsByID.put(leaderboardGroup.getId(), leaderboardGroup);
} finally {
LockUtil.unlockAfterWrite(leaderboardGroupsByNameLock);
}
mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup);
}
@Override
public void removeLeaderboardGroup(String groupName) {
final LeaderboardGroup leaderboardGroup;
@@ -2218,19 +2249,28 @@ public class RacingEventServiceImpl implements RacingEventServiceWithTestSupport
return result;
}
@Override
public void addEventWithoutReplication(Event event) {
addEvent(event);
}
@Override
public Event createEventWithoutReplication(String eventName, TimePoint startDate, TimePoint endDate, String venue,
boolean isPublic, UUID id, Iterable<URL> imageURLs, Iterable<URL> videoURLs) {
Event result = new EventImpl(eventName, startDate, endDate, venue, isPublic, id);
addEvent(result);
result.setImageURLs(imageURLs);
result.setVideoURLs(videoURLs);
return result;
}
private void addEvent(Event result) {
if (eventsById.containsKey(result.getId())) {
throw new IllegalArgumentException("Event with ID " + result.getId()
+ " already exists which is pretty surprising...");
}
eventsById.put(result.getId(), result);
mongoObjectFactory.storeEvent(result);
return result;
}
@Override
@@ -2668,4 +2708,5 @@ public class RacingEventServiceImpl implements RacingEventServiceWithTestSupport
logger.fine("Remote search on "+remoteRef+" for "+query+" took "+(System.currentTimeMillis()-start)+"ms");
return result;
}
}
@@ -10,17 +10,21 @@ import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CompetitorStore;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.ObjectInputStreamResolvingAgainstDomainFactory;
import com.sap.sailing.domain.base.impl.MasterDataImportInformation;
import com.sap.sailing.domain.base.impl.RegattaImpl;
import com.sap.sailing.domain.common.MasterDataImportObjectCreationCount;
import com.sap.sailing.domain.common.impl.MasterDataImportObjectCreationCountImpl;
import com.sap.sailing.domain.masterdataimport.TopLevelMasterData;
import com.sap.sailing.domain.persistence.MongoRaceLogStoreFactory;
import com.sap.sailing.domain.racelog.RaceLogStore;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.operationaltransformation.ImportMasterDataOperation;
public class MasterDataImporter {
private final DomainFactory baseDomainFactory;
private final RacingEventService racingEventService;
public MasterDataImporter(DomainFactory baseDomainFactory, RacingEventService racingEventService) {
this.baseDomainFactory = baseDomainFactory;
this.racingEventService = racingEventService;
@@ -33,13 +37,23 @@ public class MasterDataImporter {
racingEventService
.createOrUpdateDataImportProgressWithReplication(importOperationId, 0.03, "Reading Data", 0.5);
RaceLogStore raceLogStore = MongoRaceLogStoreFactory.INSTANCE.getMongoRaceLogStore(
racingEventService.getMongoObjectFactory(), racingEventService.getDomainObjectFactory());
RegattaImpl.setOngoingMasterDataImport(new MasterDataImportInformation(raceLogStore));
@SuppressWarnings("unchecked")
final List<Serializable> competitorIds = (List<Serializable>) objectInputStream.readObject();
if (override) {
setAllowCompetitorsDataToBeReset(competitorIds);
}
// Deserialize Regattas to make sure that Regattas are deserialized before Series
objectInputStream.readObject();
TopLevelMasterData topLevelMasterData = (TopLevelMasterData) objectInputStream.readObject();
RegattaImpl.setOngoingMasterDataImport(null);
racingEventService.createOrUpdateDataImportProgressWithReplication(importOperationId, 0.3,
"Data-Transfer Complete, Initializing Import Operation", 0.5);
@@ -61,8 +75,7 @@ public class MasterDataImporter {
UUID importOperationId, boolean override) {
MasterDataImportObjectCreationCountImpl creationCount = new MasterDataImportObjectCreationCountImpl();
ImportMasterDataOperation op = new ImportMasterDataOperation(topLevelMasterData, importOperationId, override,
creationCount,
baseDomainFactory);
creationCount, baseDomainFactory);
creationCount = racingEventService.apply(op);
racingEventService.mediaTracksImported(topLevelMasterData.getAllMediaTracks(), override);
return creationCount;
@@ -1,7 +1,6 @@
package com.sap.sailing.server.operationaltransformation;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
@@ -11,27 +10,20 @@ import java.util.Set;
import java.util.UUID;
import java.util.logging.Logger;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.common.DataImportProgress;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.ScoringSchemeType;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.MasterDataImportObjectCreationCountImpl;
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
import com.sap.sailing.domain.leaderboard.RegattaLeaderboard;
import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule;
import com.sap.sailing.domain.leaderboard.meta.LeaderboardGroupMetaLeaderboard;
import com.sap.sailing.domain.masterdataimport.TopLevelMasterData;
import com.sap.sailing.domain.masterdataimport.WindTrackMasterData;
import com.sap.sailing.domain.persistence.MongoObjectFactory;
@@ -217,44 +209,13 @@ public class ImportMasterDataOperation extends
toState.removeLeaderboardGroup(leaderboardGroup.getName());
existingLeaderboardGroup = null;
}
Leaderboard overallLeaderboardData = null;
if (existingLeaderboardGroup == null) {
overallLeaderboardData = leaderboardGroup.getOverallLeaderboard();
int[] overallLeaderboardDiscardThresholds = null;
ScoringSchemeType overallLeaderboardScoringSchemeType = null;
if (overallLeaderboardData != null) {
LeaderboardGroupMetaLeaderboard metaLeaderboard = (LeaderboardGroupMetaLeaderboard) overallLeaderboardData;
ThresholdBasedResultDiscardingRule rule = (ThresholdBasedResultDiscardingRule) metaLeaderboard
.getResultDiscardingRule();
overallLeaderboardDiscardThresholds = rule.getDiscardIndexResultsStartingWithHowManyRaces();
overallLeaderboardScoringSchemeType = metaLeaderboard.getScoringScheme().getType();
}
leaderboardGroup = toState.addLeaderboardGroup(leaderboardGroup.getId(),
leaderboardGroup.getName(), leaderboardGroup.getDescription(),
leaderboardGroup.isDisplayGroupsInReverseOrder(), leaderboardNames,
overallLeaderboardDiscardThresholds, overallLeaderboardScoringSchemeType);
toState.addLeaderboardGroupWithoutReplication(leaderboardGroup);
creationCount.addOneLeaderboardGroup(leaderboardGroup.getName());
} else {
leaderboardGroup = existingLeaderboardGroup;
logger.info(String.format("Leaderboard Group with name %1$s already exists and hasn't been overridden.",
leaderboardGroup.getName()));
}
if (leaderboardGroup.getOverallLeaderboard() != null && (override || existingLeaderboardGroup == null)) {
if (existingLeaderboardGroup != null && existingLeaderboardGroup.getOverallLeaderboard() != null) {
// remove old overall leaderboard if it existed
toState.removeLeaderboard(existingLeaderboardGroup.getOverallLeaderboard().getName());
}
Leaderboard overallLeaderboard = leaderboardGroup.getOverallLeaderboard();
for (Competitor suppressedCompetitor : overallLeaderboardData.getSuppressedCompetitors()) {
overallLeaderboard.setSuppressed(suppressedCompetitor, true);
}
for (RaceColumn column : overallLeaderboard.getRaceColumns()) {
Double explicitFactor = overallLeaderboardData.getRaceColumnByName(column.getName())
.getExplicitFactor();
toState.updateLeaderboardColumnFactor(overallLeaderboard.getName(), column.getName(), explicitFactor);
}
toState.getMongoObjectFactory().storeLeaderboardGroup(leaderboardGroup); // store changes to overall leaderboard
}
}
/**
@@ -394,18 +355,7 @@ public class ImportMasterDataOperation extends
continue;
}
}
Serializable id = regatta.getId();
Iterable<? extends Series> series = regatta.getSeries();
String baseName = regatta.getBaseName();
String boatClassName = regatta.getBoatClass().getName();
CourseArea defaultCourseArea = regatta.getDefaultCourseArea();
Serializable defaultCourseAreaId = (defaultCourseArea != null) ? defaultCourseArea.getId() : null;
ScoringSchemeType scoringSchemeType = regatta.getScoringScheme().getType();
boolean isPersistent = regatta.isPersistent();
Regatta createdRegatta = toState.getOrCreateRegattaWithoutReplication(baseName, boatClassName, id,
series, isPersistent, baseDomainFactory.createScoringScheme(scoringSchemeType),
defaultCourseAreaId).getA();
createdRegatta.setRegattaConfiguration(regatta.getRegattaConfiguration());
toState.addRegattaWithoutReplication(regatta);
Set<String> raceIdStrings = masterData.getRaceIdStringsForRegatta().get(regatta.getRegattaIdentifier());
if (raceIdStrings != null) {
for (String raceIdAsString : raceIdStrings) {
@@ -414,11 +364,11 @@ public class ImportMasterDataOperation extends
.format("Persistent regatta wasn't set for race id %1$s, because override was not turned on.",
raceIdAsString));
} else {
toState.setRegattaForRace(createdRegatta, raceIdAsString);
toState.setRegattaForRace(regatta, raceIdAsString);
}
}
}
creationCount.addOneRegatta(createdRegatta.getId().toString());
creationCount.addOneRegatta(regatta.getId().toString());
}
}
@@ -436,48 +386,15 @@ public class ImportMasterDataOperation extends
existingEvent = null;
}
if (existingEvent == null) {
String name = event.getName();
TimePoint startDate = event.getStartDate();
TimePoint endDate = event.getEndDate();
String venueName = event.getVenue().getName();
boolean isPublic = event.isPublic();
Event newEvent = toState.createEventWithoutReplication(name, startDate, endDate, venueName, isPublic, id,
event.getImageURLs(), event.getVideoURLs());
creationCount.addOneEvent(newEvent.getId().toString());
toState.addEventWithoutReplication(event);
creationCount.addOneEvent(event.getId().toString());
} else {
logger.info(String.format("Event with name %1$s already exists and hasn't been overridden.",
event.getName()));
}
Iterable<CourseArea> courseAreas = event.getVenue().getCourseAreas();
for (CourseArea courseArea : courseAreas) {
boolean alreadyExists = false;
if (existingEvent != null && existsInSet(existingEvent.getVenue().getCourseAreas(), courseArea.getId())) {
alreadyExists = true;
}
if (!alreadyExists) {
toState.addCourseAreaWithoutReplication(id, courseArea.getId(), courseArea.getName());
} else {
logger.info(String
.format("Course area with id %1$s for event with id %2$s already exists and hasn't been overridden.",
courseArea.getId(), id));
}
}
}
}
/**
* @return true if course with given id exists in <code>iterable</code>
*/
private boolean existsInSet(Iterable<CourseArea> iterable, UUID uuid) {
for (CourseArea area : iterable) {
if (area.getId() == uuid) {
return true;
}
}
return false;
}
@Override
public RacingEventServiceOperation<?> transformClientOp(RacingEventServiceOperation<?> serverOp) {
// TODO Auto-generated method stub