mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-08 13:20:57 +00:00
updateCache methods in MediaLibrary are updating now also mediaTracksByRace
This commit is contained in:
1 parent
377a6e90ae
commit
9b4fb1ac6b
6 files changed
+86
-79
No files matched your search
+1
-1
@@ -81,7 +81,7 @@ public class MediaServiceImpl extends RemoteServiceServlet implements MediaServi
|
||||
|
||||
@Override
|
||||
public void updateRace(MediaTrack mediaTrack) {
|
||||
racingEventService().mediaTrackRaceChanged(mediaTrack);
|
||||
racingEventService().mediaTrackRacesChanged(mediaTrack);
|
||||
|
||||
}
|
||||
|
||||
|
||||
+10
-10
@@ -174,7 +174,7 @@ public class MediaLibaryTest {
|
||||
|
||||
mediaLibary.addMediaTrack(originalMediaTrack);
|
||||
|
||||
Set<MediaTrack> firstQueryResult = mediaLibary.findMediaTracksForRaceInTimeRange(queryStartTime, queryEndTime, null);
|
||||
Set<MediaTrack> firstQueryResult = mediaLibary.findMediaTracksForRace(null);
|
||||
assertThat(firstQueryResult.size(), is(1));
|
||||
|
||||
MediaTrack changedMediaTrack = new MediaTrack();
|
||||
@@ -183,10 +183,10 @@ public class MediaLibaryTest {
|
||||
changedMediaTrack.duration = new MillisecondsDurationImpl(100);
|
||||
mediaLibary.startTimeChanged(changedMediaTrack);
|
||||
|
||||
Set<MediaTrack> secondQueryResult = mediaLibary.findMediaTracksForRaceInTimeRange(queryStartTime, queryEndTime, null);
|
||||
Set<MediaTrack> secondQueryResult = mediaLibary.findMediaTracksForRace(null);
|
||||
assertThat(secondQueryResult.size(), is(0));
|
||||
|
||||
Set<MediaTrack> thirdQueryResult = mediaLibary.findMediaTracksForRaceInTimeRange(changedMediaTrack.startTime, changedMediaTrack.deriveEndTime(), null);
|
||||
Set<MediaTrack> thirdQueryResult = mediaLibary.findMediaTracksForRace(null);
|
||||
assertThat(thirdQueryResult.size(), is(1));
|
||||
|
||||
|
||||
@@ -204,12 +204,12 @@ public class MediaLibaryTest {
|
||||
|
||||
mediaLibary.addMediaTrack(mediaTrack);
|
||||
|
||||
Set<MediaTrack> firstQueryResult = mediaLibary.findMediaTracksForRaceInTimeRange(originalStartTime, originalEndTime, null);
|
||||
Set<MediaTrack> firstQueryResult = mediaLibary.findMediaTracksForRace(null);
|
||||
assertThat(firstQueryResult.size(), is(1));
|
||||
|
||||
mediaLibary.deleteMediaTrack(mediaTrack);
|
||||
|
||||
Set<MediaTrack> secondQueryResult = mediaLibary.findMediaTracksForRaceInTimeRange(originalStartTime, originalEndTime, null);
|
||||
Set<MediaTrack> secondQueryResult = mediaLibary.findMediaTracksForRace(null);
|
||||
assertThat(secondQueryResult.size(), is(0));
|
||||
|
||||
}
|
||||
@@ -225,7 +225,7 @@ public class MediaLibaryTest {
|
||||
TimePoint queryStartTime = firstMediaTrack.startTime.plus(1);
|
||||
TimePoint queryEndTime = firstMediaTrack.deriveEndTime().minus(1);
|
||||
|
||||
Set<MediaTrack> firstQueryResult = mediaLibary.findMediaTracksForRaceInTimeRange(queryStartTime, queryEndTime, null);
|
||||
Set<MediaTrack> firstQueryResult = mediaLibary.findMediaTracksForRace(null);
|
||||
assertThat(firstQueryResult.size(), is(1));
|
||||
|
||||
MediaTrack secondMediaTrack = new MediaTrack();
|
||||
@@ -234,13 +234,13 @@ public class MediaLibaryTest {
|
||||
secondMediaTrack.duration = firstMediaTrack.duration;
|
||||
mediaLibary.addMediaTrack(secondMediaTrack);
|
||||
|
||||
Set<MediaTrack> secondQueryResult = mediaLibary.findMediaTracksForRaceInTimeRange(queryStartTime, queryEndTime, null);
|
||||
Set<MediaTrack> secondQueryResult = mediaLibary.findMediaTracksForRace(null);
|
||||
assertThat(secondQueryResult.size(), is(2));
|
||||
|
||||
TimePoint uncachedStartTime = firstMediaTrack.startTime.plus(2);
|
||||
TimePoint uncachedEndTime = firstMediaTrack.deriveEndTime().minus(2);
|
||||
|
||||
Set<MediaTrack> thirdQueryResult = mediaLibary.findMediaTracksForRaceInTimeRange(uncachedStartTime, uncachedEndTime, null);
|
||||
Set<MediaTrack> thirdQueryResult = mediaLibary.findMediaTracksForRace(null);
|
||||
assertThat(thirdQueryResult.size(), is(2));
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ public class MediaLibaryTest {
|
||||
MediaTrack mediaTrack = new MediaTrack(dbId, title, url, startTime, duration, mimeType, regattasAndRaces);
|
||||
mediaLibary.addMediaTrack(mediaTrack);
|
||||
|
||||
Collection<MediaTrack> mediaTracks = mediaLibary.findMediaTracksForRaceInTimeRange(rangeStart, rangeEnd, null);
|
||||
Collection<MediaTrack> mediaTracks = mediaLibary.findMediaTracksForRace(null);
|
||||
assertThat(mediaTracks.size(), is(1));
|
||||
assertThat(mediaTracks.iterator().next().dbId, is(dbId));
|
||||
}
|
||||
@@ -271,7 +271,7 @@ public class MediaLibaryTest {
|
||||
MediaTrack mediaTrack = new MediaTrack(dbId, title, url, startTime, duration, mimeType, regattasAndRaces);
|
||||
mediaLibary.addMediaTrack(mediaTrack);
|
||||
|
||||
Collection<MediaTrack> mediaTracks = mediaLibary.findMediaTracksForRaceInTimeRange(rangeStart, rangeEnd, null);
|
||||
Collection<MediaTrack> mediaTracks = mediaLibary.findMediaTracksForRace(null);
|
||||
assertThat(mediaTracks.size(), is(0));
|
||||
}
|
||||
|
||||
|
||||
@@ -426,7 +426,7 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch
|
||||
|
||||
void mediaTrackDurationChanged(MediaTrack mediaTrack);
|
||||
|
||||
void mediaTrackRaceChanged(MediaTrack mediaTrack);
|
||||
void mediaTrackRacesChanged(MediaTrack mediaTrack);
|
||||
|
||||
void mediaTrackDeleted(MediaTrack mediaTrack);
|
||||
|
||||
|
||||
@@ -9,14 +9,11 @@ import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
import com.sap.sailing.domain.common.TimeRange;
|
||||
import com.sap.sailing.domain.common.media.MediaTrack;
|
||||
import com.sap.sailing.util.impl.LockUtil;
|
||||
import com.sap.sailing.util.impl.NamedReentrantReadWriteLock;
|
||||
@@ -35,28 +32,28 @@ class MediaLibrary {
|
||||
* result in case a MediaTrack is being removed from the library or changes values such that it needs to be removed
|
||||
* from the cache.
|
||||
*/
|
||||
private final ConcurrentMap<TimeRange, Set<MediaTrack>> cacheByInterval = new ConcurrentHashMap<TimeRange, Set<MediaTrack>>();
|
||||
|
||||
private final ConcurrentMap<RegattaAndRaceIdentifier, Set<MediaTrack>> cacheByRace = new ConcurrentHashMap<RegattaAndRaceIdentifier, Set<MediaTrack>>();
|
||||
|
||||
private final NamedReentrantReadWriteLock lock = new NamedReentrantReadWriteLock(MediaLibrary.class.getName(), /* fair */ false);
|
||||
private final ConcurrentMap<RegattaAndRaceIdentifier, Set<MediaTrack>> mediaTrackByRace = new ConcurrentHashMap<RegattaAndRaceIdentifier, Set<MediaTrack>>();
|
||||
|
||||
// /**
|
||||
// * Sort in reverse order of start time! For equal start times compare dbId to distinguish different instances.
|
||||
// */
|
||||
// private static final Comparator<MediaTrack> COMPARATOR_BY_REVERSE_STARTTIME = new Comparator<MediaTrack>() {
|
||||
//
|
||||
// @Override
|
||||
// public int compare(MediaTrack mediaTrack1, MediaTrack mediaTrack2) {
|
||||
// int result = compareDatesAllowingNull(mediaTrack2.startTime, mediaTrack1.startTime);
|
||||
// if (result == 0) {
|
||||
// return mediaTrack1.dbId.compareTo(mediaTrack2.dbId);
|
||||
// } else {
|
||||
// return result;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// };
|
||||
private final NamedReentrantReadWriteLock lock = new NamedReentrantReadWriteLock(MediaLibrary.class.getName(), /* fair */
|
||||
false);
|
||||
|
||||
// /**
|
||||
// * Sort in reverse order of start time! For equal start times compare dbId to distinguish different instances.
|
||||
// */
|
||||
// private static final Comparator<MediaTrack> COMPARATOR_BY_REVERSE_STARTTIME = new Comparator<MediaTrack>() {
|
||||
//
|
||||
// @Override
|
||||
// public int compare(MediaTrack mediaTrack1, MediaTrack mediaTrack2) {
|
||||
// int result = compareDatesAllowingNull(mediaTrack2.startTime, mediaTrack1.startTime);
|
||||
// if (result == 0) {
|
||||
// return mediaTrack1.dbId.compareTo(mediaTrack2.dbId);
|
||||
// } else {
|
||||
// return result;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// };
|
||||
|
||||
/**
|
||||
* NOTE: The implementation of this lookup using simple linear search is a trade off between development effort and
|
||||
@@ -68,44 +65,44 @@ class MediaLibrary {
|
||||
* However, considering the expected low number of media entries and the expected high rate of cache hits doesn't
|
||||
* justify providing a dedicated interval tree implementation (given that there's none readily available).
|
||||
*
|
||||
* TODO: A slight performance gain might be achieved assuming that more recent media tracks are requested more frequently
|
||||
* than older ones. Thus, sorting the list of media tracks by start time and starting linear search from the more
|
||||
* recent end might reduce loop cycles during linear search. E.g. use a SortedMap with COMPARATOR_BY_REVERSE_STARTTIME commented out above.
|
||||
* TODO: A slight performance gain might be achieved assuming that more recent media tracks are requested more
|
||||
* frequently than older ones. Thus, sorting the list of media tracks by start time and starting linear search from
|
||||
* the more recent end might reduce loop cycles during linear search. E.g. use a SortedMap with
|
||||
* COMPARATOR_BY_REVERSE_STARTTIME commented out above.
|
||||
* @param race
|
||||
* TODO
|
||||
*
|
||||
* @param startTime
|
||||
* @param endTime
|
||||
* @param race TODO
|
||||
* @return
|
||||
*/
|
||||
Set<MediaTrack> findMediaTracksForRaceInTimeRange(TimePoint startTime, TimePoint endTime, RegattaAndRaceIdentifier race) {
|
||||
Set<MediaTrack> findMediaTracksForRace(RegattaAndRaceIdentifier race) {
|
||||
|
||||
if(race != null){
|
||||
if (race != null) {
|
||||
LockUtil.lockForRead(lock);
|
||||
try{
|
||||
Set<MediaTrack> cachedMediaTracks = cacheByRace.get(race);
|
||||
if(cachedMediaTracks == null){
|
||||
|
||||
try {
|
||||
Set<MediaTrack> cachedMediaTracks = mediaTrackByRace.get(race);
|
||||
if (cachedMediaTracks == null) {
|
||||
|
||||
Set<MediaTrack> result = new HashSet<MediaTrack>();
|
||||
for (MediaTrack mediaTrack : mediaTracksByDbId.values()) {
|
||||
if(mediaTrack.isConnectedTo(race) && mediaTrack.overlapsWith(startTime, endTime)){
|
||||
if (mediaTrack.isConnectedTo(race)) {
|
||||
result.add(mediaTrack);
|
||||
}
|
||||
}
|
||||
cachedMediaTracks = cacheByRace.putIfAbsent(race, result);
|
||||
if(cachedMediaTracks != null){
|
||||
cachedMediaTracks = mediaTrackByRace.putIfAbsent(race, result);
|
||||
if (cachedMediaTracks != null) {
|
||||
return cachedMediaTracks;
|
||||
}else{
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
return cachedMediaTracks;
|
||||
}
|
||||
}finally{
|
||||
} finally {
|
||||
LockUtil.unlockAfterRead(lock);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
//else
|
||||
// else
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@@ -212,13 +209,13 @@ class MediaLibrary {
|
||||
LockUtil.unlockAfterWrite(lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void racesChanged(MediaTrack changedMediaTrack) {
|
||||
LockUtil.lockForWrite(lock);
|
||||
try {
|
||||
MediaTrack mediaTrack = mediaTracksByDbId.get(changedMediaTrack);
|
||||
if (mediaTrack != null) {
|
||||
mediaTrack.regattasAndRaces.clear();
|
||||
mediaTrack.regattasAndRaces.clear();
|
||||
mediaTrack.regattasAndRaces.addAll(changedMediaTrack.regattasAndRaces);
|
||||
updateCache_Change(mediaTrack);
|
||||
}
|
||||
@@ -231,10 +228,16 @@ class MediaLibrary {
|
||||
* To be called only under write lock!
|
||||
*/
|
||||
private void updateCache_Add(MediaTrack mediaTrack) {
|
||||
for (Entry<TimeRange, Set<MediaTrack>> cacheEntry : cacheByInterval.entrySet()) {
|
||||
TimeRange interval = cacheEntry.getKey();
|
||||
if (mediaTrack.overlapsWith(interval.from(), interval.to())) {
|
||||
cacheEntry.getValue().add(mediaTrack);
|
||||
|
||||
mediaTracksByDbId.put(mediaTrack, mediaTrack);
|
||||
|
||||
for (RegattaAndRaceIdentifier regattasAndRaces : mediaTrack.regattasAndRaces) {
|
||||
if (mediaTrackByRace.containsKey(regattasAndRaces)) {
|
||||
mediaTrackByRace.get(regattasAndRaces).add(mediaTrack);
|
||||
} else {
|
||||
Set<MediaTrack> mediaTracks = new HashSet<MediaTrack>();
|
||||
mediaTracks.add(mediaTrack);
|
||||
mediaTrackByRace.put(regattasAndRaces, mediaTracks);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -243,21 +246,25 @@ class MediaLibrary {
|
||||
* To be called only under write lock!
|
||||
*/
|
||||
private void updateCache_Change(MediaTrack mediaTrack) {
|
||||
for (Entry<TimeRange, Set<MediaTrack>> cacheEntry : cacheByInterval.entrySet()) {
|
||||
cacheEntry.getValue().remove(mediaTrack);
|
||||
TimeRange interval = cacheEntry.getKey();
|
||||
if (mediaTrack.overlapsWith(interval.from(), interval.to())) {
|
||||
cacheEntry.getValue().add(mediaTrack);
|
||||
}
|
||||
}
|
||||
updateCache_Remove(mediaTrack);
|
||||
updateCache_Add(mediaTrack);
|
||||
}
|
||||
|
||||
/**
|
||||
* To be called only under write lock!
|
||||
*/
|
||||
private void updateCache_Remove(MediaTrack mediaTrack) {
|
||||
for (Entry<TimeRange, Set<MediaTrack>> cacheEntry : cacheByInterval.entrySet()) {
|
||||
cacheEntry.getValue().remove(mediaTrack);
|
||||
|
||||
mediaTracksByDbId.remove(mediaTrack);
|
||||
|
||||
for (RegattaAndRaceIdentifier regattaAndRace : mediaTrack.regattasAndRaces) {
|
||||
Set<MediaTrack> mediaTracks = mediaTrackByRace.get(regattaAndRace);
|
||||
if(mediaTracks != null){
|
||||
mediaTracks.remove(mediaTrack);
|
||||
if(mediaTracks.size()==0){
|
||||
mediaTrackByRace.remove(regattaAndRace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,7 +298,7 @@ class MediaLibrary {
|
||||
LockUtil.lockForWrite(lock);
|
||||
try {
|
||||
mediaTracksByDbId.clear();
|
||||
cacheByInterval.clear();
|
||||
mediaTrackByRace.clear();
|
||||
} finally {
|
||||
LockUtil.unlockAfterWrite(lock);
|
||||
}
|
||||
|
||||
+4
-4
@@ -175,7 +175,7 @@ import com.sap.sailing.server.operationaltransformation.TrackRegatta;
|
||||
import com.sap.sailing.server.operationaltransformation.UpdateCompetitor;
|
||||
import com.sap.sailing.server.operationaltransformation.UpdateMarkPassings;
|
||||
import com.sap.sailing.server.operationaltransformation.UpdateMediaTrackDurationOperation;
|
||||
import com.sap.sailing.server.operationaltransformation.UpdateMediaTrackRaceOperation;
|
||||
import com.sap.sailing.server.operationaltransformation.UpdateMediaTrackRacesOperation;
|
||||
import com.sap.sailing.server.operationaltransformation.UpdateMediaTrackStartTimeOperation;
|
||||
import com.sap.sailing.server.operationaltransformation.UpdateMediaTrackTitleOperation;
|
||||
import com.sap.sailing.server.operationaltransformation.UpdateMediaTrackUrlOperation;
|
||||
@@ -2470,10 +2470,10 @@ public class RacingEventServiceImpl implements RacingEventServiceWithTestSupport
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mediaTrackRaceChanged(MediaTrack mediaTrack) {
|
||||
public void mediaTrackRacesChanged(MediaTrack mediaTrack) {
|
||||
mediaDB.updateRace(mediaTrack.dbId, mediaTrack.regattasAndRaces);
|
||||
mediaLibrary.racesChanged(mediaTrack);
|
||||
replicate(new UpdateMediaTrackRaceOperation(mediaTrack));
|
||||
replicate(new UpdateMediaTrackRacesOperation(mediaTrack));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2525,7 +2525,7 @@ public class RacingEventServiceImpl implements RacingEventServiceWithTestSupport
|
||||
} else {
|
||||
TimePoint raceStart = trackedRace.getStartOfRace() == null ? null : trackedRace.getStartOfRace();
|
||||
TimePoint raceEnd = trackedRace.getEndOfRace() == null ? null : trackedRace.getEndOfRace();
|
||||
return mediaLibrary.findMediaTracksForRaceInTimeRange(raceStart, raceEnd, trackedRace.getRaceIdentifier());
|
||||
return mediaLibrary.findMediaTracksForRace(trackedRace.getRaceIdentifier());
|
||||
}
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
|
||||
+3
-3
@@ -3,17 +3,17 @@ package com.sap.sailing.server.operationaltransformation;
|
||||
import com.sap.sailing.domain.common.media.MediaTrack;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
|
||||
public class UpdateMediaTrackRaceOperation extends AbstractMediaTrackOperation {
|
||||
public class UpdateMediaTrackRacesOperation extends AbstractMediaTrackOperation {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public UpdateMediaTrackRaceOperation(MediaTrack mediaTrack) {
|
||||
public UpdateMediaTrackRacesOperation(MediaTrack mediaTrack) {
|
||||
super(mediaTrack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void internalApplyTo(RacingEventService toState) throws Exception {
|
||||
toState.mediaTrackRaceChanged(this.mediaTrack);
|
||||
toState.mediaTrackRacesChanged(this.mediaTrack);
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user