diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractTracTracLiveTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractTracTracLiveTest.java index e4fcca8403b..9fc3ab449c3 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractTracTracLiveTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractTracTracLiveTest.java @@ -109,7 +109,6 @@ public abstract class AbstractTracTracLiveTest extends StoredTrackBasedTest { ISubscriberFactory subscriberFactory = SubscriptionLocator.getSusbcriberFactory(); if (storedUri == null) { eventSubscriber = subscriberFactory.createEventSubscriber(race.getEvent()); - eventSubscriber.start(); raceSubscriber = subscriberFactory.createRaceSubscriber(race); } else { eventSubscriber = DomainFactory.INSTANCE.getOrCreateEventSubscriber(race.getEvent(), liveUri, storedUri); @@ -141,6 +140,7 @@ public abstract class AbstractTracTracLiveTest extends StoredTrackBasedTest { for (Receiver receiver : receivers) { receiver.subscribe(); } + getEventSubscriber().start(); getRaceSubscriber().start(); } diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java index 45d9cf2790a..0a8993cfe8b 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java @@ -342,7 +342,10 @@ public interface DomainFactory { /** * Event subscribers created by this call are cached in this domain factory, using the three parameters as a compound * caching key. Event subscribers found in the cache are returned by this method. The event subscriber returned will - * already have been {@link IEventSubscriber#start() started}. + * be a wrapper around the actual {@link IEventSubscriber}, managing the {@link IEventSubscriber#start()} and {@link IEventSubscriber#stop()} + * calls such that only the first {@link IEventSubscriber#start()} call is actually forwarded to the wrapper subscriber, and only + * the last {@link IEventSubscriber#stop()} call is forwarded. This is managed by an atomic counter that keeps track of the + * start/stop invocations. */ IEventSubscriber getOrCreateEventSubscriber(IEvent tractracEvent, URI liveURI, URI storedURI); } diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java index ad83a7369b6..a1420fb19b4 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java @@ -1096,9 +1096,7 @@ public class DomainFactoryImpl implements DomainFactory { return eventSubscriberCache.computeIfAbsent(new Triple<>(tractracEvent, liveURI, storedURI), key-> { try { - final IEventSubscriber eventSubscriber = SubscriptionLocator.getSusbcriberFactory().createEventSubscriber(key.getA(), key.getB(), key.getC()); - eventSubscriber.start(); - return eventSubscriber; + return new EventSubscriberWrapper(SubscriptionLocator.getSusbcriberFactory().createEventSubscriber(key.getA(), key.getB(), key.getC())); } catch (SubscriberInitializationException e) { throw new RuntimeException(e); } diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/EventSubscriberWrapper.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/EventSubscriberWrapper.java new file mode 100644 index 00000000000..232de621220 --- /dev/null +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/EventSubscriberWrapper.java @@ -0,0 +1,120 @@ +package com.sap.sailing.domain.tractracadapter.impl; + +import java.util.concurrent.atomic.AtomicInteger; + +import com.tractrac.subscription.lib.api.IEventSubscriber; +import com.tractrac.subscription.lib.api.competitor.ICompetitorsListener; +import com.tractrac.subscription.lib.api.control.IControlsListener; +import com.tractrac.subscription.lib.api.event.IConnectionStatusListener; +import com.tractrac.subscription.lib.api.event.IEventMessageListener; +import com.tractrac.subscription.lib.api.event.IServerTimeListener; +import com.tractrac.subscription.lib.api.race.IRacesListener; +import com.tractrac.subscription.lib.api.race.IStartStopTimesChangeListener; + +/** + * A wrapper around a {@link IEventSubscriber} that can be shared across many {@link TracTracRaceTrackerImpl} instances + * that each invoke {@link #start} and {@link #stop()} symmetrically. This wrapper manages a counter (as an + * {@link AtomicInteger}) such that {@link #start} will only delegate to the instance wrapped if the counter is 0; + * likewise, {@link #stop} will delegate only if the counter goes to 0. + * + * @author Axel Uhl (d043530) + * + */ +public class EventSubscriberWrapper implements IEventSubscriber { + private final IEventSubscriber delegate; + private final AtomicInteger startCounter; + + public EventSubscriberWrapper(IEventSubscriber delegate) { + this.delegate = delegate; + startCounter = new AtomicInteger(0); + } + + @Override + public void subscribeConnectionStatus(IConnectionStatusListener listener) { + delegate.subscribeConnectionStatus(listener); + } + + @Override + public void unsubscribeConnectionStatus(IConnectionStatusListener listener) { + delegate.unsubscribeConnectionStatus(listener); + } + + @Override + public void start() { + if (startCounter.getAndIncrement() == 0) { + delegate.start(); + } + } + + @Override + public void stop() { + if (startCounter.decrementAndGet() == 0) { + delegate.stop(); + } + } + + @Override + public boolean isRunning() { + return delegate.isRunning(); + } + + @Override + public void subscribeControls(IControlsListener listener) { + delegate.subscribeControls(listener); + } + + @Override + public void unsubscribeControls(IControlsListener listener) { + delegate.unsubscribeControls(listener); + } + + @Override + public void subscribeEventTimesChanges(IStartStopTimesChangeListener listener) { + delegate.subscribeEventTimesChanges(listener); + } + + @Override + public void unsubscribeEventTimesChanges(IStartStopTimesChangeListener listener) { + delegate.unsubscribeEventTimesChanges(listener); + } + + @Override + public void subscribeEventMessages(IEventMessageListener listener) { + delegate.subscribeEventMessages(listener); + } + + @Override + public void unsubscribeEventMessages(IEventMessageListener listener) { + delegate.unsubscribeEventMessages(listener); + } + + @Override + public void subscribeServerTime(IServerTimeListener serverTimeListener) { + delegate.subscribeServerTime(serverTimeListener); + } + + @Override + public void unsubscribeServerTime(IServerTimeListener serverTimeListener) { + delegate.unsubscribeServerTime(serverTimeListener); + } + + @Override + public void subscribeRaces(IRacesListener listener) { + delegate.subscribeRaces(listener); + } + + @Override + public void unsubscribeRaces(IRacesListener listener) { + delegate.unsubscribeRaces(listener); + } + + @Override + public void subscribeCompetitors(ICompetitorsListener listener) { + delegate.subscribeCompetitors(listener); + } + + @Override + public void unsubscribeCompetitors(ICompetitorsListener listener) { + delegate.unsubscribeCompetitors(listener); + } +} diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracRaceTrackerImpl.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracRaceTrackerImpl.java index 709515fe7f5..004a2820889 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracRaceTrackerImpl.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracRaceTrackerImpl.java @@ -591,6 +591,7 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl