mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-12 05:35:31 +00:00
Merge remote-tracking branch 'server/bug4006'
This commit is contained in:
commit
eec641bb78
52 files changed
+574
-303
No files matched your search
@@ -23,7 +23,8 @@ Require-Bundle: com.sap.sailing.domain,
|
||||
com.sap.sse.gwt.adminconsole,
|
||||
org.apache.commons.math;bundle-version="2.1.0",
|
||||
com.sap.sse.security.ui,
|
||||
com.sap.sse
|
||||
com.sap.sse,
|
||||
com.sap.sse.replication.interfaces
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Import-Package: com.sap.sse.security.shared.dto,
|
||||
javax.servlet;version="3.1.0",
|
||||
|
||||
+20
-7
@@ -15,31 +15,44 @@ import com.sap.sse.gwt.dispatch.client.transport.gwtrpc.RequestWrapper;
|
||||
import com.sap.sse.gwt.dispatch.servlets.AbstractDispatchServlet;
|
||||
import com.sap.sse.gwt.dispatch.shared.commands.Action;
|
||||
import com.sap.sse.gwt.dispatch.shared.commands.Result;
|
||||
import com.sap.sse.replication.FullyInitializedReplicableTracker;
|
||||
import com.sap.sse.replication.ReplicationService;
|
||||
import com.sap.sse.util.ServiceTrackerFactory;
|
||||
|
||||
public class DashboardDispatchServlet extends AbstractDispatchServlet<DashboardDispatchContext> {
|
||||
private static final long serialVersionUID = -245230476512348999L;
|
||||
|
||||
private final ServiceTracker<RacingEventService, RacingEventService> racingEventServiceTracker;
|
||||
private final FullyInitializedReplicableTracker<RacingEventService> racingEventServiceTracker;
|
||||
private final PolarDataService polarDataService;
|
||||
private final DashboardLiveRaceProvider dashboardLiveRaceProvider;
|
||||
private final MovingAveragesCache movingAveragesCache;
|
||||
|
||||
public DashboardDispatchServlet() {
|
||||
final BundleContext context = Activator.getDefault();
|
||||
racingEventServiceTracker = ServiceTrackerFactory.createAndOpen(context, RacingEventService.class);
|
||||
final ServiceTracker<ReplicationService, ReplicationService> replicationServiceTracker =
|
||||
ServiceTrackerFactory.createAndOpen(context, ReplicationService.class);
|
||||
racingEventServiceTracker = new FullyInitializedReplicableTracker<>(context, RacingEventService.class,
|
||||
/* customizer */ null, replicationServiceTracker);
|
||||
racingEventServiceTracker.open();
|
||||
polarDataService = getPolarDataService();
|
||||
dashboardLiveRaceProvider = new DashboardLiveRaceProvider(racingEventServiceTracker.getService());
|
||||
try {
|
||||
dashboardLiveRaceProvider = new DashboardLiveRaceProvider(racingEventServiceTracker.getInitializedService(0));
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
movingAveragesCache = new MovingAveragesCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <R extends Result, A extends Action<R, DashboardDispatchContext>> DashboardDispatchContext createDispatchContextFor(
|
||||
RequestWrapper<R, A, DashboardDispatchContext> request) {
|
||||
return new DashboardDispatchContextImpl(request.getCurrentClientTime(),
|
||||
racingEventServiceTracker.getService(),
|
||||
polarDataService, dashboardLiveRaceProvider, movingAveragesCache, request.getClientLocaleName(),
|
||||
getThreadLocalRequest());
|
||||
try {
|
||||
return new DashboardDispatchContextImpl(request.getCurrentClientTime(), racingEventServiceTracker.getInitializedService(0),
|
||||
polarDataService, dashboardLiveRaceProvider, movingAveragesCache, request.getClientLocaleName(),
|
||||
getThreadLocalRequest());
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private PolarDataService getPolarDataService() {
|
||||
|
||||
@@ -25,7 +25,8 @@ Require-Bundle: org.json.simple;bundle-version="1.1.0",
|
||||
com.sap.sse.security.common,
|
||||
com.sap.sse.security.interface,
|
||||
org.apache.shiro.core,
|
||||
org.apache.shiro.web
|
||||
org.apache.shiro.web,
|
||||
com.sap.sse.replication
|
||||
Import-Package: com.sap.sse.security.shared,
|
||||
javax.ws.rs;version="1.1.1",
|
||||
javax.ws.rs.core;version="1.1.1",
|
||||
|
||||
Regular → Executable
+11
-5
@@ -10,6 +10,8 @@ import org.osgi.util.tracker.ServiceTracker;
|
||||
|
||||
import com.sap.sailing.domain.igtimiadapter.Client;
|
||||
import com.sap.sailing.domain.igtimiadapter.IgtimiConnectionFactory;
|
||||
import com.sap.sse.replication.FullyInitializedReplicableTracker;
|
||||
import com.sap.sse.replication.ReplicationService;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
import com.sap.sse.util.ServiceTrackerFactory;
|
||||
|
||||
@@ -26,7 +28,7 @@ import com.sap.sse.util.ServiceTrackerFactory;
|
||||
public class Activator implements BundleActivator {
|
||||
private static Activator INSTANCE;
|
||||
private ServiceTracker<IgtimiConnectionFactory, IgtimiConnectionFactory> igtimiConnectionFactoryTracker;
|
||||
private ServiceTracker<SecurityService, SecurityService> securityServiceTracker;
|
||||
private FullyInitializedReplicableTracker<SecurityService> securityServiceTracker;
|
||||
|
||||
public Activator() throws ClientProtocolException, IllegalStateException, IOException, ParseException {
|
||||
}
|
||||
@@ -34,11 +36,11 @@ public class Activator implements BundleActivator {
|
||||
@Override
|
||||
public void start(final BundleContext context) throws Exception {
|
||||
INSTANCE = this;
|
||||
|
||||
igtimiConnectionFactoryTracker = ServiceTrackerFactory
|
||||
.createAndOpen(context, IgtimiConnectionFactory.class);
|
||||
|
||||
securityServiceTracker = ServiceTrackerFactory.createAndOpen(context, SecurityService.class);
|
||||
securityServiceTracker = new FullyInitializedReplicableTracker<>(context, SecurityService.class,
|
||||
/* customizer */ null, ServiceTrackerFactory.createAndOpen(context, ReplicationService.class));
|
||||
securityServiceTracker.open();
|
||||
}
|
||||
|
||||
public static Activator getInstance() throws ClientProtocolException, IllegalStateException, IOException, ParseException {
|
||||
@@ -53,7 +55,11 @@ public class Activator implements BundleActivator {
|
||||
}
|
||||
|
||||
public SecurityService getSecurityService() {
|
||||
return securityServiceTracker.getService();
|
||||
try {
|
||||
return securityServiceTracker.getInitializedService(0);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+12
-5
@@ -13,7 +13,6 @@ import org.apache.http.client.ClientProtocolException;
|
||||
import org.json.simple.parser.ParseException;
|
||||
import org.osgi.framework.BundleActivator;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.util.tracker.ServiceTracker;
|
||||
|
||||
import com.sap.sailing.domain.common.security.SecuredDomainType;
|
||||
import com.sap.sailing.domain.igtimiadapter.Account;
|
||||
@@ -23,6 +22,8 @@ import com.sap.sailing.domain.igtimiadapter.persistence.DomainObjectFactory;
|
||||
import com.sap.sailing.domain.igtimiadapter.persistence.MongoObjectFactory;
|
||||
import com.sap.sailing.domain.igtimiadapter.persistence.PersistenceFactory;
|
||||
import com.sap.sailing.domain.tracking.WindTrackerFactory;
|
||||
import com.sap.sse.replication.FullyInitializedReplicableTracker;
|
||||
import com.sap.sse.replication.ReplicationService;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
import com.sap.sse.util.ClearStateTestSupport;
|
||||
import com.sap.sse.util.ServiceTrackerFactory;
|
||||
@@ -55,7 +56,7 @@ public class Activator implements BundleActivator {
|
||||
private static final String CLIENT_REDIRECT_PORT_PROPERTY_NAME = "igtimi.client.redirect.port";
|
||||
private final Future<IgtimiConnectionFactoryImpl> connectionFactory;
|
||||
private final Future<IgtimiWindTrackerFactory> windTrackerFactory;
|
||||
private ServiceTracker<SecurityService, SecurityService> securityServiceServiceTracker;
|
||||
private FullyInitializedReplicableTracker<SecurityService> securityServiceServiceTracker;
|
||||
private final ExecutorService executor = Executors.newSingleThreadExecutor(new ThreadFactoryWithPriority(Thread.NORM_PRIORITY, /* daemon */ true));
|
||||
private SecurityService securityServiceTest;
|
||||
|
||||
@@ -106,10 +107,12 @@ public class Activator implements BundleActivator {
|
||||
}
|
||||
}
|
||||
});
|
||||
securityServiceServiceTracker = ServiceTrackerFactory.createAndOpen(context, SecurityService.class);
|
||||
securityServiceServiceTracker = new FullyInitializedReplicableTracker<>(context, SecurityService.class,
|
||||
/* customizer */ null, ServiceTrackerFactory.createAndOpen(context, ReplicationService.class));
|
||||
securityServiceServiceTracker.open();
|
||||
new Thread(() -> {
|
||||
try {
|
||||
final SecurityService securityService = securityServiceServiceTracker.waitForService(0);
|
||||
final SecurityService securityService = securityServiceServiceTracker.getInitializedService(0);
|
||||
IgtimiConnectionFactoryImpl igtimiConnectionFactory = connectionFactory.get();
|
||||
for (Account account : igtimiConnectionFactory.getAllAccounts()) {
|
||||
securityService.migrateOwnership(account);
|
||||
@@ -144,7 +147,11 @@ public class Activator implements BundleActivator {
|
||||
}
|
||||
|
||||
public SecurityService getSecurityService() {
|
||||
return securityServiceTest == null ? securityServiceServiceTracker.getService() : securityServiceTest;
|
||||
try {
|
||||
return securityServiceTest == null ? securityServiceServiceTracker.getInitializedService(0) : securityServiceTest;
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public IgtimiWindTrackerFactory getWindTrackerFactory() {
|
||||
|
||||
+10
-3
@@ -36,14 +36,16 @@ import com.sap.sailing.server.interfaces.RacingEventService;
|
||||
import com.sap.sailing.shared.persistence.device.DeviceIdentifierMongoHandler;
|
||||
import com.sap.sse.MasterDataImportClassLoaderService;
|
||||
import com.sap.sse.common.TypeBasedServiceFinder;
|
||||
import com.sap.sse.replication.FullyInitializedReplicableTracker;
|
||||
import com.sap.sse.replication.Replicable;
|
||||
import com.sap.sse.replication.ReplicationService;
|
||||
import com.sap.sse.util.ServiceTrackerFactory;
|
||||
|
||||
public class Activator implements BundleActivator {
|
||||
private static final Logger logger = Logger.getLogger(Activator.class.getName());
|
||||
|
||||
private static BundleContext context;
|
||||
private ServiceTracker<RacingEventService, RacingEventService> racingEventServiceTracker;
|
||||
private FullyInitializedReplicableTracker<RacingEventService> racingEventServiceTracker;
|
||||
private ServiceTracker<SensorFixMapper<?, ?, ?>, SensorFixMapper<?, ?, ?>> sensorFixMapperTracker;
|
||||
|
||||
public static BundleContext getContext() {
|
||||
@@ -84,13 +86,18 @@ public class Activator implements BundleActivator {
|
||||
registrations.add(context.registerService(SensorFixMapper.class, new BravoExtendedDataFixMapper(), null));
|
||||
registrations.add(context.registerService(SensorFixMapper.class, new ExpeditionExtendedDataFixMapper(), null));
|
||||
sensorFixMapperTracker = createSensorFixMapperServiceTracker(context);
|
||||
racingEventServiceTracker = ServiceTrackerFactory.createAndOpen(context, RacingEventService.class);
|
||||
racingEventServiceTracker = new FullyInitializedReplicableTracker<>(context, RacingEventService.class,
|
||||
/* customizer */ null, ServiceTrackerFactory.createAndOpen(context, ReplicationService.class));
|
||||
racingEventServiceTracker.open();
|
||||
RegattaLogFixTrackerRegattaListener regattaLogSensorDataTrackerTrackedRegattaListener = new RegattaLogFixTrackerRegattaListener(
|
||||
racingEventServiceTracker, new SensorFixMapperFactoryImpl(sensorFixMapperTracker));
|
||||
registrations.add(context.registerService(TrackedRegattaListener.class,
|
||||
regattaLogSensorDataTrackerTrackedRegattaListener, null));
|
||||
final Dictionary<String, String> replicableServiceProperties = new Hashtable<>();
|
||||
replicableServiceProperties.put(Replicable.OSGi_Service_Registry_ID_Property_Name,
|
||||
regattaLogSensorDataTrackerTrackedRegattaListener.getId().toString());
|
||||
registrations.add(context.registerService(Replicable.class,
|
||||
regattaLogSensorDataTrackerTrackedRegattaListener, null));
|
||||
regattaLogSensorDataTrackerTrackedRegattaListener, replicableServiceProperties));
|
||||
new Thread(()->{
|
||||
try {
|
||||
registrations.add(context.registerService(RaceTrackingConnectivityParametersHandler.class,
|
||||
|
||||
+37
-29
@@ -12,8 +12,6 @@ import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.osgi.util.tracker.ServiceTracker;
|
||||
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.racelog.tracking.SensorFixStore;
|
||||
import com.sap.sailing.domain.racelogsensortracking.SensorFixMapperFactory;
|
||||
@@ -24,14 +22,15 @@ import com.sap.sailing.domain.tracking.RaceTracker;
|
||||
import com.sap.sailing.domain.tracking.TrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.TrackedRegattaListener;
|
||||
import com.sap.sailing.server.interfaces.RacingEventService;
|
||||
import com.sap.sse.replication.FullyInitializedReplicableTracker;
|
||||
import com.sap.sse.replication.OperationExecutionListener;
|
||||
import com.sap.sse.replication.OperationWithResult;
|
||||
import com.sap.sse.replication.OperationWithResultWithIdWrapper;
|
||||
import com.sap.sse.replication.OperationsToMasterSender;
|
||||
import com.sap.sse.replication.OperationsToMasterSendingQueue;
|
||||
import com.sap.sse.replication.ReplicableWithObjectInputStream;
|
||||
import com.sap.sse.replication.ReplicationMasterDescriptor;
|
||||
import com.sap.sse.replication.ReplicationService;
|
||||
import com.sap.sse.replication.OperationsToMasterSendingQueue;
|
||||
|
||||
/**
|
||||
* This is the main entry point of the {@link SensorFixStore} based fix tracking.
|
||||
@@ -51,7 +50,7 @@ public class RegattaLogFixTrackerRegattaListener extends AbstractTrackedRegattaA
|
||||
private static final Logger log = Logger.getLogger(RegattaLogFixTrackerRegattaListener.class.getName());
|
||||
|
||||
private final Map<RegattaAndRaceIdentifier, RaceLogFixTrackerManager> dataTrackers = new ConcurrentHashMap<>();
|
||||
private final ServiceTracker<RacingEventService, RacingEventService> racingEventServiceTracker;
|
||||
private final FullyInitializedReplicableTracker<RacingEventService> racingEventServiceTracker;
|
||||
private final SensorFixMapperFactory sensorFixMapperFactory;
|
||||
|
||||
/**
|
||||
@@ -63,10 +62,11 @@ public class RegattaLogFixTrackerRegattaListener extends AbstractTrackedRegattaA
|
||||
private OperationsToMasterSendingQueue unsentOperationsToMasterSender;
|
||||
|
||||
public RegattaLogFixTrackerRegattaListener(
|
||||
ServiceTracker<RacingEventService, RacingEventService> racingEventServiceTracker,
|
||||
FullyInitializedReplicableTracker<RacingEventService> racingEventServiceTracker,
|
||||
SensorFixMapperFactory sensorFixMapperFactory) {
|
||||
this.racingEventServiceTracker = racingEventServiceTracker;
|
||||
this.sensorFixMapperFactory = sensorFixMapperFactory;
|
||||
this.currentlyFillingFromInitialLoad = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -81,30 +81,38 @@ public class RegattaLogFixTrackerRegattaListener extends AbstractTrackedRegattaA
|
||||
@Override
|
||||
protected void onRaceAdded(RegattaAndRaceIdentifier raceIdentifier, DynamicTrackedRegatta trackedRegatta,
|
||||
DynamicTrackedRace trackedRace) {
|
||||
racingEventServiceTracker.getService().getRaceTrackerByRegattaAndRaceIdentifier(raceIdentifier, (raceTracker) -> {
|
||||
if (raceTracker != null) {
|
||||
boolean added = raceTracker.add(new RaceTracker.Listener() {
|
||||
@Override
|
||||
public void onTrackerWillStop(boolean preemptive, boolean willBeRemoved) {
|
||||
raceTracker.remove(this);
|
||||
removeRaceLogSensorDataTracker(raceIdentifier, preemptive, willBeRemoved);
|
||||
try {
|
||||
racingEventServiceTracker.getInitializedService(0).getRaceTrackerByRegattaAndRaceIdentifier(raceIdentifier, (raceTracker) -> {
|
||||
try {
|
||||
if (raceTracker != null) {
|
||||
boolean added = raceTracker.add(new RaceTracker.Listener() {
|
||||
@Override
|
||||
public void onTrackerWillStop(boolean preemptive, boolean willBeRemoved) {
|
||||
raceTracker.remove(this);
|
||||
removeRaceLogSensorDataTracker(raceIdentifier, preemptive, willBeRemoved);
|
||||
}
|
||||
});
|
||||
// if !added, the RaceTracker is already stopped, so we are not allowed to start fix tracking
|
||||
if (added) {
|
||||
RaceLogFixTrackerManager trackerManager = new RaceLogFixTrackerManager(
|
||||
(DynamicTrackedRace) trackedRace, racingEventServiceTracker.getInitializedService(0).getSensorFixStore(),
|
||||
sensorFixMapperFactory);
|
||||
RaceLogFixTrackerManager oldInstance = null;
|
||||
synchronized (this) {
|
||||
oldInstance = dataTrackers.put(raceIdentifier, trackerManager);
|
||||
}
|
||||
if (oldInstance != null) {
|
||||
oldInstance.stop(/* preemptive */ true, /* willBeRemoved */ false);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
// if !added, the RaceTracker is already stopped, so we are not allowed to start fix tracking
|
||||
if (added) {
|
||||
RaceLogFixTrackerManager trackerManager = new RaceLogFixTrackerManager(
|
||||
(DynamicTrackedRace) trackedRace, racingEventServiceTracker.getService().getSensorFixStore(),
|
||||
sensorFixMapperFactory);
|
||||
RaceLogFixTrackerManager oldInstance = null;
|
||||
synchronized (this) {
|
||||
oldInstance = dataTrackers.put(raceIdentifier, trackerManager);
|
||||
}
|
||||
if (oldInstance != null) {
|
||||
oldInstance.stop(/* preemptive */ true, /* willBeRemoved */ false);
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -130,7 +138,7 @@ public class RegattaLogFixTrackerRegattaListener extends AbstractTrackedRegattaA
|
||||
|
||||
// Replication related methods and fields
|
||||
private final ConcurrentHashMap<OperationExecutionListener<RegattaLogFixTrackerRegattaListener>, OperationExecutionListener<RegattaLogFixTrackerRegattaListener>> operationExecutionListeners = new ConcurrentHashMap<>();
|
||||
private ThreadLocal<Boolean> currentlyFillingFromInitialLoad = ThreadLocal.withInitial(() -> false);
|
||||
private volatile boolean currentlyFillingFromInitialLoad;
|
||||
private ThreadLocal<Boolean> currentlyApplyingOperationReceivedFromMaster = ThreadLocal.withInitial(() -> false);
|
||||
private final Set<OperationWithResultWithIdWrapper<RegattaLogFixTrackerRegattaListener, ?>> operationsSentToMasterForReplication = new HashSet<>();
|
||||
private ReplicationMasterDescriptor master;
|
||||
@@ -174,12 +182,12 @@ public class RegattaLogFixTrackerRegattaListener extends AbstractTrackedRegattaA
|
||||
|
||||
@Override
|
||||
public boolean isCurrentlyFillingFromInitialLoad() {
|
||||
return currentlyFillingFromInitialLoad.get();
|
||||
return currentlyFillingFromInitialLoad;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentlyFillingFromInitialLoad(boolean currentlyFillingFromInitialLoad) {
|
||||
this.currentlyFillingFromInitialLoad.set(currentlyFillingFromInitialLoad);
|
||||
this.currentlyFillingFromInitialLoad = currentlyFillingFromInitialLoad;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -14,7 +14,8 @@ Require-Bundle: com.sap.sailing.domain.swisstimingadapter,
|
||||
com.sap.sailing.domain.persistence,
|
||||
com.sap.sse,
|
||||
org.mongodb.mongo-java-driver;bundle-version="3.6.4",
|
||||
com.sap.sse.security.common
|
||||
com.sap.sse.security.common,
|
||||
com.sap.sse.replication.interfaces
|
||||
Export-Package: com.sap.sailing.domain.swisstimingadapter.persistence,
|
||||
com.sap.sailing.domain.swisstimingadapter.persistence.impl;x-friends:="com.sap.sailing.domain.swisstimingadapter.test,com.sap.sailing.mongodb.test"
|
||||
Import-Package: com.sap.sse.security,
|
||||
|
||||
+6
-7
@@ -22,6 +22,8 @@ import com.sap.sailing.domain.swisstimingadapter.persistence.SwissTimingAdapterP
|
||||
import com.sap.sailing.domain.tracking.RaceTrackingConnectivityParametersHandler;
|
||||
import com.sap.sse.common.TypeBasedServiceFinder;
|
||||
import com.sap.sse.mongodb.MongoDBService;
|
||||
import com.sap.sse.replication.FullyInitializedReplicableTracker;
|
||||
import com.sap.sse.replication.ReplicationService;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
import com.sap.sse.util.ServiceTrackerFactory;
|
||||
|
||||
@@ -34,8 +36,9 @@ public class Activator implements BundleActivator {
|
||||
MongoDBService.INSTANCE.registerExclusively(CollectionNames.class, name.name());
|
||||
}
|
||||
new Thread(() -> {
|
||||
final ServiceTracker<SecurityService, SecurityService> securityServiceServiceTracker = ServiceTrackerFactory
|
||||
.createAndOpen(context, SecurityService.class);
|
||||
final FullyInitializedReplicableTracker<SecurityService> securityServiceServiceTracker = new FullyInitializedReplicableTracker<>(context, SecurityService.class,
|
||||
/* customizer */ null, ServiceTrackerFactory.createAndOpen(context, ReplicationService.class));
|
||||
securityServiceServiceTracker.open();
|
||||
final ServiceTracker<MongoObjectFactory, MongoObjectFactory> mongoObjectFactoryServiceTracker = ServiceTrackerFactory.createAndOpen(context, MongoObjectFactory.class);
|
||||
final ServiceTracker<DomainObjectFactory, DomainObjectFactory> domainObjectFactoryServiceTracker = ServiceTrackerFactory.createAndOpen(context, DomainObjectFactory.class);
|
||||
final ServiceTracker<SwissTimingAdapterFactory, SwissTimingAdapterFactory> swissTimingAdapterFactoryServiceTracker = ServiceTrackerFactory.createAndOpen(context, SwissTimingAdapterFactory.class);
|
||||
@@ -43,7 +46,7 @@ public class Activator implements BundleActivator {
|
||||
final MongoObjectFactory mongoObjectFactory = mongoObjectFactoryServiceTracker.waitForService(0);
|
||||
final DomainObjectFactory domainObjectFactory = domainObjectFactoryServiceTracker.waitForService(0);
|
||||
final SwissTimingAdapterFactory swissTimingAdapterFactory = swissTimingAdapterFactoryServiceTracker.waitForService(0);
|
||||
final SecurityService securityService = securityServiceServiceTracker.waitForService(0);
|
||||
final SecurityService securityService = securityServiceServiceTracker.getInitializedService(0);
|
||||
final Dictionary<String, Object> properties = new Hashtable<String, Object>();
|
||||
final com.sap.sailing.domain.swisstimingadapter.DomainFactory domainFactory = swissTimingAdapterFactory.getOrCreateSwissTimingAdapter(
|
||||
domainObjectFactory.getBaseDomainFactory()).getSwissTimingDomainFactory();
|
||||
@@ -53,21 +56,17 @@ public class Activator implements BundleActivator {
|
||||
domainFactory);
|
||||
properties.put(TypeBasedServiceFinder.TYPE, SwissTimingTrackingConnectivityParameters.TYPE);
|
||||
context.registerService(RaceTrackingConnectivityParametersHandler.class, paramsHandler, properties);
|
||||
|
||||
for (SwissTimingArchiveConfiguration swissTimingArchive : SwissTimingAdapterPersistence.INSTANCE
|
||||
.getSwissTimingArchiveConfigurations()) {
|
||||
securityService.migrateOwnership(swissTimingArchive);
|
||||
}
|
||||
|
||||
for (SwissTimingConfiguration swissTiming : SwissTimingAdapterPersistence.INSTANCE
|
||||
.getSwissTimingConfigurations()) {
|
||||
securityService.migrateOwnership(swissTiming);
|
||||
}
|
||||
|
||||
// we do not necessarily have swisstiming configs, so ensure that migration is marked as done
|
||||
securityService.assumeOwnershipMigrated(SecuredDomainType.SWISS_TIMING_ACCOUNT.getName());
|
||||
securityService.assumeOwnershipMigrated(SecuredDomainType.SWISS_TIMING_ARCHIVE_ACCOUNT.getName());
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Exception trying to register SwissTiming RaceTrackingConnectivityParametersHandler implementation", e);
|
||||
}
|
||||
|
||||
+4
-4
@@ -14,7 +14,6 @@ import java.util.function.Consumer;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.Timeout;
|
||||
import org.osgi.util.tracker.ServiceTracker;
|
||||
|
||||
import com.sap.sailing.domain.base.Course;
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
@@ -35,6 +34,7 @@ import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl;
|
||||
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRegattaImpl;
|
||||
import com.sap.sailing.server.impl.RacingEventServiceImpl;
|
||||
import com.sap.sailing.server.interfaces.RacingEventService;
|
||||
import com.sap.sse.replication.FullyInitializedReplicableTracker;
|
||||
import com.sap.sse.util.ThreadLocalTransporter;
|
||||
|
||||
public class TestDeadlockInRegattaListener {
|
||||
@@ -46,8 +46,8 @@ public class TestDeadlockInRegattaListener {
|
||||
CyclicBarrier latch = new CyclicBarrier(2);
|
||||
CyclicBarrier monitorOnRegattaListenerLatch = new CyclicBarrier(2);
|
||||
@SuppressWarnings("unchecked")
|
||||
ServiceTracker<RacingEventService, RacingEventService> racingEventServiceTracker =
|
||||
(ServiceTracker<RacingEventService, RacingEventService>) mock(ServiceTracker.class);
|
||||
FullyInitializedReplicableTracker<RacingEventService> racingEventServiceTracker =
|
||||
(FullyInitializedReplicableTracker<RacingEventService>) mock(FullyInitializedReplicableTracker.class);
|
||||
final String regattaName = "Test Regatta";
|
||||
final RegattaImpl regatta = new RegattaImpl(
|
||||
/* raceLogStore */ null, EmptyRegattaLogStore.INSTANCE, regattaName,
|
||||
@@ -102,7 +102,7 @@ public class TestDeadlockInRegattaListener {
|
||||
}
|
||||
}
|
||||
};
|
||||
when(racingEventServiceTracker.getService()).thenReturn(racingEventService);
|
||||
when(racingEventServiceTracker.getInitializedService(0)).thenReturn(racingEventService);
|
||||
RegattaLogFixTrackerRegattaListener listener = new RegattaLogFixTrackerRegattaListener(
|
||||
racingEventServiceTracker, null);
|
||||
|
||||
|
||||
@@ -14,7 +14,8 @@ Require-Bundle: com.sap.sse.mongodb,
|
||||
com.sap.sailing.domain.persistence,
|
||||
com.sap.sse,
|
||||
org.mongodb.mongo-java-driver;bundle-version="3.6.4",
|
||||
com.sap.sse.security.common
|
||||
com.sap.sse.security.common,
|
||||
com.sap.sse.replication.interfaces
|
||||
Export-Package: com.sap.sailing.domain.tractracadapter.persistence,
|
||||
com.sap.sailing.domain.tractracadapter.persistence.impl;x-friends:="com.sap.sailing.mongodb.test"
|
||||
Import-Package: com.sap.sse.security,
|
||||
|
||||
+25
-14
@@ -23,18 +23,20 @@ import com.sap.sailing.domain.tractracadapter.TracTracConfiguration;
|
||||
import com.sap.sailing.domain.tractracadapter.impl.RaceTrackingConnectivityParametersImpl;
|
||||
import com.sap.sse.common.TypeBasedServiceFinder;
|
||||
import com.sap.sse.mongodb.MongoDBService;
|
||||
import com.sap.sse.replication.FullyInitializedReplicableTracker;
|
||||
import com.sap.sse.replication.ReplicationService;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
import com.sap.sse.util.ClearStateTestSupport;
|
||||
import com.sap.sse.util.ServiceTrackerFactory;
|
||||
|
||||
public class Activator implements BundleActivator {
|
||||
private static final Logger logger = Logger.getLogger(Activator.class.getName());
|
||||
|
||||
|
||||
/**
|
||||
* Requires a base {@link DomainFactory} as well as a {@link RaceLogStore} and a {@link RegattaLogStore}. In order
|
||||
* to instantiate those two stores, the method requires a {@link MongoObjectFactory} and a {@link DomainObjectFactory}
|
||||
* which are waited for as services from the OSGi registry. This happens in a separate thread that the {@link #start(BundleContext)}
|
||||
* method launches.
|
||||
* to instantiate those two stores, the method requires a {@link MongoObjectFactory} and a
|
||||
* {@link DomainObjectFactory} which are waited for as services from the OSGi registry. This happens in a separate
|
||||
* thread that the {@link #start(BundleContext)} method launches.
|
||||
*/
|
||||
@Override
|
||||
public void start(BundleContext context) throws Exception {
|
||||
@@ -42,22 +44,29 @@ public class Activator implements BundleActivator {
|
||||
MongoDBService.INSTANCE.registerExclusively(CollectionNames.class, name.name());
|
||||
}
|
||||
new Thread(() -> {
|
||||
final ServiceTracker<MongoObjectFactory, MongoObjectFactory> mongoObjectFactoryServiceTracker = ServiceTrackerFactory.createAndOpen(context, MongoObjectFactory.class);
|
||||
final ServiceTracker<DomainObjectFactory, DomainObjectFactory> domainObjectFactoryServiceTracker = ServiceTrackerFactory.createAndOpen(context, DomainObjectFactory.class);
|
||||
final ServiceTracker<SecurityService, SecurityService> securityServiceServiceTracker = ServiceTrackerFactory
|
||||
.createAndOpen(context, SecurityService.class);
|
||||
final ServiceTracker<TracTracAdapterFactory, TracTracAdapterFactory> tractracAdapterFactoryTracker = ServiceTrackerFactory.createAndOpen(context, TracTracAdapterFactory.class);
|
||||
final ServiceTracker<MongoObjectFactory, MongoObjectFactory> mongoObjectFactoryServiceTracker = ServiceTrackerFactory
|
||||
.createAndOpen(context, MongoObjectFactory.class);
|
||||
final ServiceTracker<DomainObjectFactory, DomainObjectFactory> domainObjectFactoryServiceTracker = ServiceTrackerFactory
|
||||
.createAndOpen(context, DomainObjectFactory.class);
|
||||
final FullyInitializedReplicableTracker<SecurityService> securityServiceServiceTracker = new FullyInitializedReplicableTracker<>(
|
||||
context, SecurityService.class, /* customizer */ null,
|
||||
ServiceTrackerFactory.createAndOpen(context, ReplicationService.class));
|
||||
securityServiceServiceTracker.open();
|
||||
final ServiceTracker<TracTracAdapterFactory, TracTracAdapterFactory> tractracAdapterFactoryTracker = ServiceTrackerFactory
|
||||
.createAndOpen(context, TracTracAdapterFactory.class);
|
||||
try {
|
||||
final MongoObjectFactory mongoObjectFactory = mongoObjectFactoryServiceTracker.waitForService(0);
|
||||
final DomainObjectFactory domainObjectFactory = domainObjectFactoryServiceTracker.waitForService(0);
|
||||
final SecurityService securityService = securityServiceServiceTracker.waitForService(0);
|
||||
final SecurityService securityService = securityServiceServiceTracker.getInitializedService(0);
|
||||
final TracTracAdapterFactory tractracAdapterFactory = tractracAdapterFactoryTracker.waitForService(0);
|
||||
final Dictionary<String, Object> properties = new Hashtable<String, Object>();
|
||||
final com.sap.sailing.domain.tractracadapter.DomainFactory domainFactory = tractracAdapterFactory.getOrCreateTracTracAdapter(
|
||||
domainObjectFactory.getBaseDomainFactory()).getTracTracDomainFactory();
|
||||
final com.sap.sailing.domain.tractracadapter.DomainFactory domainFactory = tractracAdapterFactory
|
||||
.getOrCreateTracTracAdapter(domainObjectFactory.getBaseDomainFactory())
|
||||
.getTracTracDomainFactory();
|
||||
final TracTracConnectivityParamsHandler paramsHandler = new TracTracConnectivityParamsHandler(
|
||||
MongoRaceLogStoreFactory.INSTANCE.getMongoRaceLogStore(mongoObjectFactory, domainObjectFactory),
|
||||
MongoRegattaLogStoreFactory.INSTANCE.getMongoRegattaLogStore(mongoObjectFactory, domainObjectFactory),
|
||||
MongoRegattaLogStoreFactory.INSTANCE.getMongoRegattaLogStore(mongoObjectFactory,
|
||||
domainObjectFactory),
|
||||
domainFactory);
|
||||
|
||||
com.sap.sailing.domain.tractracadapter.persistence.DomainObjectFactory tractracDomainObjectFactory = com.sap.sailing.domain.tractracadapter.persistence.PersistenceFactory.INSTANCE
|
||||
@@ -79,7 +88,9 @@ public class Activator implements BundleActivator {
|
||||
}
|
||||
}, null);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Exception trying to register TracTrac RaceTrackingConnectivityParametersHandler implementation", e);
|
||||
logger.log(Level.SEVERE,
|
||||
"Exception trying to register TracTrac RaceTrackingConnectivityParametersHandler implementation",
|
||||
e);
|
||||
}
|
||||
}, getClass().getName() + " registering connectivity handler").start();
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ Export-Package: com.sap.sailing.domain.base,
|
||||
com.sap.sailing.domain.regattalog,
|
||||
com.sap.sailing.domain.regattalog.impl,
|
||||
com.sap.sailing.domain.sharding,
|
||||
com.sap.sailing.domain.sharedsailingdata,
|
||||
com.sap.sailing.domain.trackfiles,
|
||||
com.sap.sailing.domain.trackimport,
|
||||
com.sap.sailing.domain.tracking,
|
||||
|
||||
+6
-4
@@ -12,7 +12,6 @@ import java.util.logging.Logger;
|
||||
import org.osgi.framework.BundleActivator;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.framework.ServiceRegistration;
|
||||
import org.osgi.util.tracker.ServiceTracker;
|
||||
|
||||
import com.sap.sailing.domain.common.security.SecuredDomainType;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifierStringSerializationHandler;
|
||||
@@ -28,6 +27,8 @@ import com.sap.sailing.expeditionconnector.persistence.PersistenceFactory;
|
||||
import com.sap.sailing.server.gateway.serialization.racelog.tracking.DeviceIdentifierJsonHandler;
|
||||
import com.sap.sse.ServerInfo;
|
||||
import com.sap.sse.common.TypeBasedServiceFinder;
|
||||
import com.sap.sse.replication.FullyInitializedReplicableTracker;
|
||||
import com.sap.sse.replication.ReplicationService;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
import com.sap.sse.security.shared.QualifiedObjectIdentifier;
|
||||
import com.sap.sse.security.shared.impl.WildcardPermissionEncoder;
|
||||
@@ -91,10 +92,11 @@ public class Activator implements BundleActivator {
|
||||
registrations.add(context.registerService(DeviceIdentifierStringSerializationHandler.class, new ExpeditionSensorStringSerializationHandler(), getDict(ExpeditionSensorDeviceIdentifier.TYPE)));
|
||||
|
||||
new Thread(() -> {
|
||||
final ServiceTracker<SecurityService, SecurityService> securityServiceServiceTracker = ServiceTrackerFactory
|
||||
.createAndOpen(context, SecurityService.class);
|
||||
final FullyInitializedReplicableTracker<SecurityService> securityServiceServiceTracker = new FullyInitializedReplicableTracker<>(
|
||||
context, SecurityService.class, /* customizer */ null, ServiceTrackerFactory.createAndOpen(context, ReplicationService.class));
|
||||
securityServiceServiceTracker.open();
|
||||
try {
|
||||
final SecurityService securityService = securityServiceServiceTracker.waitForService(0);
|
||||
final SecurityService securityService = securityServiceServiceTracker.getInitializedService(0);
|
||||
final WildcardPermissionEncoder permissionEncoder = new WildcardPermissionEncoder();
|
||||
for (ExpeditionDeviceConfiguration deviceConfiguration : expeditionTrackerFactory
|
||||
.getDeviceConfigurations()) {
|
||||
|
||||
Regular → Executable
+21
-9
@@ -23,35 +23,47 @@ import com.sap.sse.gwt.dispatch.client.transport.gwtrpc.RequestWrapper;
|
||||
import com.sap.sse.gwt.dispatch.servlets.AbstractDispatchServlet;
|
||||
import com.sap.sse.gwt.dispatch.shared.commands.Action;
|
||||
import com.sap.sse.gwt.dispatch.shared.commands.Result;
|
||||
import com.sap.sse.replication.FullyInitializedReplicableTracker;
|
||||
import com.sap.sse.replication.ReplicationService;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
import com.sap.sse.util.ServiceTrackerFactory;
|
||||
|
||||
public class SailingDispatchServlet extends AbstractDispatchServlet<SailingDispatchContext> {
|
||||
private static final long serialVersionUID = -245230476512348999L;
|
||||
|
||||
private final ServiceTracker<RacingEventService, RacingEventService> racingEventServiceTracker;
|
||||
private final FullyInitializedReplicableTracker<RacingEventService> racingEventServiceTracker;
|
||||
private final ServiceTracker<WindFinderTrackerFactory, WindFinderTrackerFactory> windFinderTrackerFactory;
|
||||
private final ServiceTracker<EventNewsService, EventNewsService> eventNewsServiceTracker;
|
||||
private final ServiceTracker<SecurityService, SecurityService> securityServiceTracker;
|
||||
private final FullyInitializedReplicableTracker<SecurityService> securityServiceTracker;
|
||||
private final ServiceTracker<TrackedRaceStatisticsCache, TrackedRaceStatisticsCache> trackedRaceStatisticsCacheTracker;
|
||||
|
||||
public SailingDispatchServlet() {
|
||||
final BundleContext context = Activator.getDefault();
|
||||
racingEventServiceTracker = ServiceTrackerFactory.createAndOpen(context, RacingEventService.class);
|
||||
final ServiceTracker<ReplicationService, ReplicationService> replicationServiceTracker =
|
||||
ServiceTrackerFactory.createAndOpen(context, ReplicationService.class);
|
||||
racingEventServiceTracker = new FullyInitializedReplicableTracker<>(context, RacingEventService.class,
|
||||
/* customizer */ null, replicationServiceTracker);
|
||||
racingEventServiceTracker.open();
|
||||
windFinderTrackerFactory = ServiceTrackerFactory.createAndOpen(context, WindFinderTrackerFactory.class);
|
||||
eventNewsServiceTracker = ServiceTrackerFactory.createAndOpen(context, EventNewsService.class);
|
||||
securityServiceTracker = ServiceTrackerFactory.createAndOpen(context, SecurityService.class);
|
||||
securityServiceTracker = new FullyInitializedReplicableTracker<>(context, SecurityService.class,
|
||||
/* customizer */ null, replicationServiceTracker);
|
||||
securityServiceTracker.open();
|
||||
trackedRaceStatisticsCacheTracker = ServiceTrackerFactory.createAndOpen(context, TrackedRaceStatisticsCache.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <R extends Result, A extends Action<R, SailingDispatchContext>> SailingDispatchContext createDispatchContextFor(
|
||||
RequestWrapper<R, A, SailingDispatchContext> request) {
|
||||
return new SailingDispatchContextImpl(request.getCurrentClientTime(), racingEventServiceTracker.getService(),
|
||||
windFinderTrackerFactory.getService(),
|
||||
eventNewsServiceTracker.getService(), securityServiceTracker.getService(),
|
||||
trackedRaceStatisticsCacheTracker.getService(),
|
||||
request.getClientLocaleName(), getThreadLocalRequest());
|
||||
try {
|
||||
return new SailingDispatchContextImpl(request.getCurrentClientTime(), racingEventServiceTracker.getInitializedService(0),
|
||||
windFinderTrackerFactory.getService(),
|
||||
eventNewsServiceTracker.getService(), securityServiceTracker.getInitializedService(0),
|
||||
trackedRaceStatisticsCacheTracker.getService(),
|
||||
request.getClientLocaleName(), getThreadLocalRequest());
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+11
-4
@@ -1,12 +1,13 @@
|
||||
package com.sap.sailing.gwt.server;
|
||||
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.util.tracker.ServiceTracker;
|
||||
|
||||
import com.sap.sailing.gwt.ui.client.ServerConfigurationService;
|
||||
import com.sap.sailing.gwt.ui.server.Activator;
|
||||
import com.sap.sailing.server.interfaces.RacingEventService;
|
||||
import com.sap.sse.gwt.server.ProxiedRemoteServiceServlet;
|
||||
import com.sap.sse.replication.FullyInitializedReplicableTracker;
|
||||
import com.sap.sse.replication.ReplicationService;
|
||||
import com.sap.sse.util.ServiceTrackerFactory;
|
||||
|
||||
/**
|
||||
@@ -15,15 +16,21 @@ import com.sap.sse.util.ServiceTrackerFactory;
|
||||
public class ServerConfigurationServiceImpl extends ProxiedRemoteServiceServlet implements ServerConfigurationService {
|
||||
private static final long serialVersionUID = 2571063542941630865L;
|
||||
|
||||
private final ServiceTracker<RacingEventService, RacingEventService> racingEventServiceTracker;
|
||||
private final FullyInitializedReplicableTracker<RacingEventService> racingEventServiceTracker;
|
||||
|
||||
public ServerConfigurationServiceImpl() {
|
||||
BundleContext context = Activator.getDefault();
|
||||
racingEventServiceTracker = ServiceTrackerFactory.createAndOpen(context, RacingEventService.class);
|
||||
racingEventServiceTracker = new FullyInitializedReplicableTracker<>(context, RacingEventService.class,
|
||||
/* customizer */ null, ServiceTrackerFactory.createAndOpen(context, ReplicationService.class));
|
||||
racingEventServiceTracker.open();
|
||||
}
|
||||
|
||||
protected RacingEventService getService() {
|
||||
return racingEventServiceTracker.getService();
|
||||
try {
|
||||
return racingEventServiceTracker.getInitializedService(0);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+11
-3
@@ -49,6 +49,8 @@ import com.sap.sse.datamining.shared.impl.dto.StoredDataMiningQueryDTOImpl;
|
||||
import com.sap.sse.datamining.ui.client.DataMiningService;
|
||||
import com.sap.sse.gwt.server.ProxiedRemoteServiceServlet;
|
||||
import com.sap.sse.i18n.ResourceBundleStringMessages;
|
||||
import com.sap.sse.replication.FullyInitializedReplicableTracker;
|
||||
import com.sap.sse.replication.ReplicationService;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
import com.sap.sse.security.shared.impl.SecuredSecurityTypes.ServerActions;
|
||||
import com.sap.sse.util.ServiceTrackerFactory;
|
||||
@@ -58,14 +60,16 @@ public class DataMiningServiceImpl extends ProxiedRemoteServiceServlet implement
|
||||
|
||||
private final BundleContext context;
|
||||
private final ServiceTracker<DataMiningServer, DataMiningServer> dataMiningServerTracker;
|
||||
private final ServiceTracker<SecurityService, SecurityService> securityServiceTracker;
|
||||
private final FullyInitializedReplicableTracker<SecurityService> securityServiceTracker;
|
||||
private final StoredDataMiningQueryPersister storedDataMiningQueryPersistor;
|
||||
private final DataMiningDTOFactory dtoFactory;
|
||||
|
||||
public DataMiningServiceImpl() {
|
||||
context = Activator.getDefault();
|
||||
dataMiningServerTracker = createAndOpenDataMiningServerTracker(context);
|
||||
securityServiceTracker = ServiceTrackerFactory.createAndOpen(context, SecurityService.class);
|
||||
securityServiceTracker = new FullyInitializedReplicableTracker<>(context, SecurityService.class,
|
||||
/* customizer */ null, ServiceTrackerFactory.createAndOpen(context, ReplicationService.class));
|
||||
securityServiceTracker.open();
|
||||
storedDataMiningQueryPersistor = new StoredDataMiningQueryPersisterImpl(getSecurityService(),
|
||||
dataMiningServerTracker);
|
||||
dtoFactory = new DataMiningDTOFactory();
|
||||
@@ -84,7 +88,11 @@ public class DataMiningServiceImpl extends ProxiedRemoteServiceServlet implement
|
||||
}
|
||||
|
||||
private SecurityService getSecurityService() {
|
||||
return securityServiceTracker.getService();
|
||||
try {
|
||||
return securityServiceTracker.getInitializedService(0);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+39
-27
@@ -394,7 +394,6 @@ import com.sap.sailing.domain.regattalike.LeaderboardThatHasRegattaLike;
|
||||
import com.sap.sailing.domain.regattalog.RegattaLogStore;
|
||||
import com.sap.sailing.domain.resultimport.ResultUrlProvider;
|
||||
import com.sap.sailing.domain.sharding.ShardingContext;
|
||||
import com.sap.sailing.domain.sharedsailingdata.SharedSailingData;
|
||||
import com.sap.sailing.domain.swisstimingadapter.StartList;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SwissTimingAdapter;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SwissTimingAdapterFactory;
|
||||
@@ -601,6 +600,7 @@ import com.sap.sailing.server.operationaltransformation.UpdateSpecificRegatta;
|
||||
import com.sap.sailing.server.security.PermissionAwareRaceTrackingHandler;
|
||||
import com.sap.sailing.server.security.SailingViewerRole;
|
||||
import com.sap.sailing.server.util.WaitForTrackedRaceUtil;
|
||||
import com.sap.sailing.shared.server.SharedSailingData;
|
||||
import com.sap.sailing.simulator.Path;
|
||||
import com.sap.sailing.simulator.PolarDiagram;
|
||||
import com.sap.sailing.simulator.SimulationResults;
|
||||
@@ -658,6 +658,7 @@ import com.sap.sse.pairinglist.PairingList;
|
||||
import com.sap.sse.pairinglist.PairingListTemplate;
|
||||
import com.sap.sse.pairinglist.impl.PairingListTemplateImpl;
|
||||
import com.sap.sse.qrcode.QRCodeGenerationUtil;
|
||||
import com.sap.sse.replication.FullyInitializedReplicableTracker;
|
||||
import com.sap.sse.replication.OperationWithResult;
|
||||
import com.sap.sse.replication.ReplicaDescriptor;
|
||||
import com.sap.sse.replication.Replicable;
|
||||
@@ -706,7 +707,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
|
||||
|
||||
private static final long serialVersionUID = 9031688830194537489L;
|
||||
|
||||
private final ServiceTracker<RacingEventService, RacingEventService> racingEventServiceTracker;
|
||||
private final FullyInitializedReplicableTracker<RacingEventService> racingEventServiceTracker;
|
||||
|
||||
private final ServiceTracker<ReplicationService, ReplicationService> replicationServiceTracker;
|
||||
|
||||
@@ -733,9 +734,9 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
|
||||
private final ServiceTracker<DeviceIdentifierStringSerializationHandler, DeviceIdentifierStringSerializationHandler>
|
||||
deviceIdentifierStringSerializationHandlerTracker;
|
||||
|
||||
private final ServiceTracker<SecurityService, SecurityService> securityServiceTracker;
|
||||
private final FullyInitializedReplicableTracker<SecurityService> securityServiceTracker;
|
||||
|
||||
private final ServiceTracker<SharedSailingData, SharedSailingData> sharedSailingDataTracker;
|
||||
private final FullyInitializedReplicableTracker<SharedSailingData> sharedSailingDataTracker;
|
||||
|
||||
private final com.sap.sailing.domain.tractracadapter.persistence.MongoObjectFactory tractracMongoObjectFactory;
|
||||
|
||||
@@ -778,17 +779,23 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
|
||||
BundleContext context = Activator.getDefault();
|
||||
Activator activator = Activator.getInstance();
|
||||
quickRanksLiveCache = new QuickRanksLiveCache(this);
|
||||
racingEventServiceTracker = ServiceTrackerFactory.createAndOpen(context, RacingEventService.class);
|
||||
sharedSailingDataTracker = ServiceTrackerFactory.createAndOpen(context, SharedSailingData.class);
|
||||
windFinderTrackerFactoryServiceTracker = ServiceTrackerFactory.createAndOpen(context, WindFinderTrackerFactory.class);
|
||||
replicationServiceTracker = ServiceTrackerFactory.createAndOpen(context, ReplicationService.class);
|
||||
racingEventServiceTracker = new FullyInitializedReplicableTracker<>(context, RacingEventService.class,
|
||||
/* customizer */ null, replicationServiceTracker);
|
||||
racingEventServiceTracker.open();
|
||||
sharedSailingDataTracker = new FullyInitializedReplicableTracker<>(context, SharedSailingData.class,
|
||||
/* service tracker customizer */ null, replicationServiceTracker);
|
||||
sharedSailingDataTracker.open();
|
||||
windFinderTrackerFactoryServiceTracker = ServiceTrackerFactory.createAndOpen(context, WindFinderTrackerFactory.class);
|
||||
swissTimingAdapterTracker = ServiceTrackerFactory.createAndOpen(context, SwissTimingAdapterFactory.class);
|
||||
tractracAdapterTracker = ServiceTrackerFactory.createAndOpen(context, TracTracAdapterFactory.class);
|
||||
raceLogTrackingAdapterTracker = ServiceTrackerFactory.createAndOpen(context,
|
||||
RaceLogTrackingAdapterFactory.class);
|
||||
deviceIdentifierStringSerializationHandlerTracker = ServiceTrackerFactory.createAndOpen(context,
|
||||
DeviceIdentifierStringSerializationHandler.class);
|
||||
securityServiceTracker = ServiceTrackerFactory.createAndOpen(context, SecurityService.class);
|
||||
securityServiceTracker = new FullyInitializedReplicableTracker<>(context, SecurityService.class,
|
||||
/* service tracker customizer */ null, replicationServiceTracker);
|
||||
securityServiceTracker.open();
|
||||
igtimiAdapterTracker = ServiceTrackerFactory.createAndOpen(context, IgtimiConnectionFactory.class);
|
||||
baseDomainFactory = getService().getBaseDomainFactory();
|
||||
mongoObjectFactory = getService().getMongoObjectFactory();
|
||||
@@ -2776,7 +2783,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
|
||||
|
||||
protected RacingEventService getService() {
|
||||
try {
|
||||
return racingEventServiceTracker.waitForService(0);
|
||||
return racingEventServiceTracker.getInitializedService(0);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
} // grab the service
|
||||
@@ -2784,7 +2791,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
|
||||
|
||||
protected SharedSailingData getSharedSailingData() {
|
||||
try {
|
||||
return sharedSailingDataTracker.waitForService(0);
|
||||
return sharedSailingDataTracker.getInitializedService(0);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
} // grab the service
|
||||
@@ -2800,7 +2807,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
|
||||
|
||||
protected SecurityService getSecurityService() {
|
||||
try {
|
||||
return securityServiceTracker.waitForService(0);
|
||||
return securityServiceTracker.getInitializedService(0);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -4467,12 +4474,17 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
|
||||
// The queue name must always be the same for this server. In order to achieve
|
||||
// this we're using the unique server identifier
|
||||
final ReplicationService replicationService = getReplicationService();
|
||||
replicationService.startToReplicateFrom(replicationService.createReplicationMasterDescriptor(messagingHost,
|
||||
masterHostName, exchangeName, servletPort, messagingPort,
|
||||
/* use local server identifier as queue name */ replicationService.getServerIdentifier().toString(),
|
||||
RemoteServerUtil.resolveBearerTokenForRemoteServer(masterHostName, servletPort, usernameOrNull,
|
||||
passwordOrNull),
|
||||
replicationService.getAllReplicables()));
|
||||
replicationService.setReplicationStarting(true);
|
||||
try {
|
||||
replicationService.startToReplicateFrom(replicationService.createReplicationMasterDescriptor(messagingHost,
|
||||
masterHostName, exchangeName, servletPort, messagingPort,
|
||||
/* use local server identifier as queue name */ replicationService.getServerIdentifier().toString(),
|
||||
RemoteServerUtil.resolveBearerTokenForRemoteServer(masterHostName, servletPort, usernameOrNull,
|
||||
passwordOrNull),
|
||||
replicationService.getAllReplicables()));
|
||||
} finally {
|
||||
replicationService.setReplicationStarting(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -5324,15 +5336,15 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
|
||||
@Override
|
||||
public List<UrlDTO> getResultImportUrls(String resultProviderName) {
|
||||
final List<UrlDTO> result = new ArrayList<>();
|
||||
SecurityService securityService = getSecurityService();
|
||||
SecurityService securityService = getSecurityService();
|
||||
Iterable<URL> allUrlsReadableBySubject = getService().getResultImportUrls(resultProviderName);
|
||||
for (URL url : allUrlsReadableBySubject) {
|
||||
QualifiedObjectIdentifier objId = SecuredDomainType.RESULT_IMPORT_URL.getQualifiedObjectIdentifier(
|
||||
for (URL url : allUrlsReadableBySubject) {
|
||||
QualifiedObjectIdentifier objId = SecuredDomainType.RESULT_IMPORT_URL.getQualifiedObjectIdentifier(
|
||||
new TypeRelativeObjectIdentifier(resultProviderName, url.toString()));
|
||||
UrlDTO urlDTO = new UrlDTO(url.toString());
|
||||
SecurityDTOUtil.addSecurityInformation(securityService, urlDTO, objId);
|
||||
result.add(urlDTO);
|
||||
}
|
||||
UrlDTO urlDTO = new UrlDTO(url.toString());
|
||||
SecurityDTOUtil.addSecurityInformation(securityService, urlDTO, objId);
|
||||
result.add(urlDTO);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -5345,12 +5357,12 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
|
||||
return new URL(urlDto.getUrl());
|
||||
} catch (MalformedURLException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
})
|
||||
.filter(url -> url != null)
|
||||
.collect(Collectors.toSet());
|
||||
racingEventService.removeResultImportURLs(resultProviderName, urlsToRemove);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addResultImportUrl(String resultProviderName, UrlDTO urlDTO) throws Exception {
|
||||
@@ -5359,7 +5371,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
|
||||
.orElseThrow(() -> new IllegalStateException("ResultUrlProvider not found: " + resultProviderName));
|
||||
final URL url = resultUrlProvider.resolveUrl(urlDTO.getUrl());
|
||||
racingEventService.addResultImportUrl(resultProviderName, url);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String validateResultImportUrl(String resultProviderName, UrlDTO urlDTO) {
|
||||
|
||||
+4
-3
@@ -84,7 +84,7 @@ public class PolarDataServiceImpl implements ReplicablePolarService, ClearStateT
|
||||
|
||||
private final Set<OperationWithResult<PolarDataService, ?>> operationsSentToMasterForReplication;
|
||||
|
||||
private ThreadLocal<Boolean> currentlyFillingFromInitialLoad = ThreadLocal.withInitial(() -> false);
|
||||
private volatile boolean currentlyFillingFromInitialLoad;
|
||||
|
||||
private ThreadLocal<Boolean> currentlyApplyingOperationReceivedFromMaster = ThreadLocal.withInitial(() -> false);
|
||||
|
||||
@@ -103,6 +103,7 @@ public class PolarDataServiceImpl implements ReplicablePolarService, ClearStateT
|
||||
*/
|
||||
public PolarDataServiceImpl() {
|
||||
resetState();
|
||||
this.currentlyFillingFromInitialLoad = false;
|
||||
this.operationsSentToMasterForReplication = new HashSet<>();
|
||||
this.operationExecutionListeners = new ConcurrentHashMap<>();
|
||||
}
|
||||
@@ -322,12 +323,12 @@ public class PolarDataServiceImpl implements ReplicablePolarService, ClearStateT
|
||||
|
||||
@Override
|
||||
public boolean isCurrentlyFillingFromInitialLoad() {
|
||||
return currentlyFillingFromInitialLoad.get();
|
||||
return currentlyFillingFromInitialLoad;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentlyFillingFromInitialLoad(boolean currentlyFillingFromInitialLoad) {
|
||||
this.currentlyFillingFromInitialLoad.set(currentlyFillingFromInitialLoad);
|
||||
this.currentlyFillingFromInitialLoad = currentlyFillingFromInitialLoad;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -15,7 +15,8 @@ Require-Bundle: com.sap.sailing.domain.common,
|
||||
com.sap.sailing.server.gateway.serialization.shared.android,
|
||||
com.sap.sse.security,
|
||||
com.sap.sse.security.common,
|
||||
com.sap.sse.replication
|
||||
com.sap.sse.replication,
|
||||
com.sap.sailing.shared.server
|
||||
Export-Package: com.sap.sailing.server.gateway.deserialization.impl,
|
||||
com.sap.sailing.server.gateway.serialization,
|
||||
com.sap.sailing.server.gateway.serialization.impl,
|
||||
|
||||
+1
-1
@@ -52,9 +52,9 @@ import com.sap.sailing.domain.coursetemplate.impl.MarkTemplateBasedMarkConfigura
|
||||
import com.sap.sailing.domain.coursetemplate.impl.RegattaMarkConfigurationImpl;
|
||||
import com.sap.sailing.domain.coursetemplate.impl.WaypointWithMarkConfigurationImpl;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceMappingWithRegattaLogEvent;
|
||||
import com.sap.sailing.domain.sharedsailingdata.SharedSailingData;
|
||||
import com.sap.sailing.domain.tracking.GPSFixTrack;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.shared.server.SharedSailingData;
|
||||
import com.sap.sse.common.TimeRange;
|
||||
import com.sap.sse.common.Util.Triple;
|
||||
import com.sap.sse.common.WithID;
|
||||
|
||||
+1
-1
@@ -22,10 +22,10 @@ import com.sap.sailing.domain.coursetemplate.MarkConfigurationRequestAnnotation.
|
||||
import com.sap.sailing.domain.coursetemplate.Positioning;
|
||||
import com.sap.sailing.domain.coursetemplate.RepeatablePart;
|
||||
import com.sap.sailing.domain.coursetemplate.impl.MarkConfigurationRequestAnnotationImpl.MarkRoleCreationRequestImpl;
|
||||
import com.sap.sailing.domain.sharedsailingdata.SharedSailingData;
|
||||
import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException;
|
||||
import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
|
||||
import com.sap.sailing.server.gateway.serialization.impl.CourseConfigurationJsonSerializer;
|
||||
import com.sap.sailing.shared.server.SharedSailingData;
|
||||
|
||||
public class CourseConfigurationJsonDeserializer implements JsonDeserializer<CourseConfiguration<MarkConfigurationRequestAnnotation>> {
|
||||
|
||||
|
||||
+1
-1
@@ -20,10 +20,10 @@ import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.common.ScoreCorrectionProvider;
|
||||
import com.sap.sailing.domain.racelogtracking.RaceLogTrackingAdapter;
|
||||
import com.sap.sailing.domain.racelogtracking.RaceLogTrackingAdapterFactory;
|
||||
import com.sap.sailing.domain.sharedsailingdata.SharedSailingData;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.server.interfaces.RacingEventService;
|
||||
import com.sap.sailing.shared.server.SharedSailingData;
|
||||
import com.sap.sse.InvalidDateException;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.TypeBasedServiceFinderFactory;
|
||||
|
||||
+1
-1
@@ -7,8 +7,8 @@ import javax.ws.rs.core.Application;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.util.tracker.ServiceTracker;
|
||||
|
||||
import com.sap.sailing.domain.sharedsailingdata.SharedSailingData;
|
||||
import com.sap.sailing.server.interfaces.RacingEventService;
|
||||
import com.sap.sailing.shared.server.SharedSailingData;
|
||||
import com.sap.sse.datamining.DataMiningServer;
|
||||
import com.sap.sse.replication.ReplicationService;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
|
||||
@@ -37,5 +37,6 @@ Require-Bundle: com.sap.sailing.server,
|
||||
com.sun.jersey;bundle-version="1.17.0",
|
||||
com.sap.sse.security.testsupport,
|
||||
com.sap.sailing.domain.racelogtrackingadapter,
|
||||
com.sap.sailing.resultimport;bundle-version="1.0.0"
|
||||
com.sap.sailing.shared.server,
|
||||
com.sap.sailing.resultimport
|
||||
Automatic-Module-Name: com.sap.sailing.server.replication.test
|
||||
+8
-5
@@ -55,8 +55,10 @@ public abstract class AbstractServerReplicationTest extends com.sap.sse.replicat
|
||||
@Override public DomainFactory getBaseDomainFactory() { return baseDomainFactory; }
|
||||
@Override public CompetitorAndBoatStore getCompetitorAndBoatStore() { return getBaseDomainFactory().getCompetitorAndBoatStore(); }
|
||||
};
|
||||
}, MediaDBFactory.INSTANCE.getMediaDB(mongoDBService), EmptyWindStore.INSTANCE, EmptySensorFixStore.INSTANCE, null, null, /* sailingNotificationService */ null,
|
||||
/* trackedRaceStatisticsCache */ null, /* restoreTrackedRaces */ false, null, /* sharedSailingData */ null,
|
||||
}, MediaDBFactory.INSTANCE.getMediaDB(mongoDBService), EmptyWindStore.INSTANCE,
|
||||
EmptySensorFixStore.INSTANCE, null, null, /* sailingNotificationService */ null,
|
||||
/* trackedRaceStatisticsCache */ null, /* restoreTrackedRaces */ false,
|
||||
/* security service tracker */ null, /* sharedSailingData */ null, /* replicationServiceTracker */ null,
|
||||
/* scoreCorrectionProviderServiceTracker */ null, /* resultUrlRegistryServiceTracker */ null);
|
||||
}
|
||||
|
||||
@@ -75,9 +77,10 @@ public abstract class AbstractServerReplicationTest extends com.sap.sse.replicat
|
||||
@Override public DomainFactory getBaseDomainFactory() { return domainObjectFactory.getBaseDomainFactory(); }
|
||||
@Override public CompetitorAndBoatStore getCompetitorAndBoatStore() { return getBaseDomainFactory().getCompetitorAndBoatStore(); }
|
||||
};
|
||||
}, MediaDBFactory.INSTANCE.getMediaDB(mongoDBService), EmptyWindStore.INSTANCE, EmptySensorFixStore.INSTANCE,
|
||||
/* serviceFinderFactory */ null, null, /* sailingNotificationService */ null,
|
||||
/* trackedRaceStatisticsCache */ null, /* restoreTrackedRaces */ false, null, /* sharedSailingData */ null,
|
||||
}, MediaDBFactory.INSTANCE.getMediaDB(mongoDBService), EmptyWindStore.INSTANCE,
|
||||
EmptySensorFixStore.INSTANCE, /* serviceFinderFactory */ null, null,
|
||||
/* sailingNotificationService */ null, /* trackedRaceStatisticsCache */ null,
|
||||
/* restoreTrackedRaces */ false, /* security service tracker */ null, /* sharedSailingData */ null, /* replicationServiceTracker */ null,
|
||||
/* scoreCorrectionProviderServiceTracker */ null, /* resultUrlRegistryServiceTracker */ null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ Require-Bundle: com.sap.sailing.domain,
|
||||
com.sap.sailing.server.interface,
|
||||
org.mongodb.mongo-java-driver;bundle-version="3.6.4",
|
||||
com.sap.sse.security.common,
|
||||
com.sap.sailing.shared.server,
|
||||
com.sap.sailing.resultimport
|
||||
Bundle-ClassPath: .
|
||||
Export-Package: com.sap.sailing.server,
|
||||
|
||||
@@ -41,7 +41,6 @@ import com.sap.sailing.domain.persistence.racelog.tracking.impl.GPSFixMongoHandl
|
||||
import com.sap.sailing.domain.persistence.racelog.tracking.impl.GPSFixMovingMongoHandlerImpl;
|
||||
import com.sap.sailing.domain.polars.PolarDataService;
|
||||
import com.sap.sailing.domain.racelog.tracking.SensorFixStoreSupplier;
|
||||
import com.sap.sailing.domain.sharedsailingdata.SharedSailingData;
|
||||
import com.sap.sailing.domain.tracking.TrackedRegattaListener;
|
||||
import com.sap.sailing.domain.windestimation.WindEstimationFactoryService;
|
||||
import com.sap.sailing.resultimport.ResultUrlRegistry;
|
||||
@@ -56,6 +55,7 @@ import com.sap.sailing.server.notification.impl.SailingNotificationServiceImpl;
|
||||
import com.sap.sailing.server.security.SailingViewerRole;
|
||||
import com.sap.sailing.server.statistics.TrackedRaceStatisticsCache;
|
||||
import com.sap.sailing.server.statistics.TrackedRaceStatisticsCacheImpl;
|
||||
import com.sap.sailing.shared.server.SharedSailingData;
|
||||
import com.sap.sse.MasterDataImportClassLoaderService;
|
||||
import com.sap.sse.common.TypeBasedServiceFinder;
|
||||
import com.sap.sse.common.Util;
|
||||
@@ -63,7 +63,9 @@ import com.sap.sse.mail.MailService;
|
||||
import com.sap.sse.mail.queue.MailQueue;
|
||||
import com.sap.sse.mail.queue.impl.ExecutorMailQueue;
|
||||
import com.sap.sse.osgi.CachedOsgiTypeBasedServiceFinderFactory;
|
||||
import com.sap.sse.replication.FullyInitializedReplicableTracker;
|
||||
import com.sap.sse.replication.Replicable;
|
||||
import com.sap.sse.replication.ReplicationService;
|
||||
import com.sap.sse.security.SecurityInitializationCustomizer;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
import com.sap.sse.security.interfaces.PreferenceConverter;
|
||||
@@ -111,9 +113,11 @@ public class Activator implements BundleActivator {
|
||||
|
||||
private ServiceTracker<MailService, MailService> mailServiceTracker;
|
||||
|
||||
private ServiceTracker<SecurityService, SecurityService> securityServiceTracker;
|
||||
private FullyInitializedReplicableTracker<SecurityService> securityServiceTracker;
|
||||
|
||||
private ServiceTracker<SharedSailingData, SharedSailingData> sharedSailingDataTracker;
|
||||
private FullyInitializedReplicableTracker<SharedSailingData> sharedSailingDataTracker;
|
||||
|
||||
private ServiceTracker<ReplicationService, ReplicationService> replicationServiceTracker;
|
||||
|
||||
public Activator() {
|
||||
clearPersistentCompetitors = Boolean
|
||||
@@ -130,13 +134,19 @@ public class Activator implements BundleActivator {
|
||||
extenderBundleTracker = new ExtenderBundleTracker(context);
|
||||
extenderBundleTracker.open();
|
||||
mailServiceTracker = ServiceTrackerFactory.createAndOpen(context, MailService.class);
|
||||
securityServiceTracker = ServiceTrackerFactory.createAndOpen(context, SecurityService.class);
|
||||
replicationServiceTracker = ServiceTrackerFactory.createAndOpen(context, ReplicationService.class);
|
||||
sharedSailingDataTracker = new FullyInitializedReplicableTracker<>(context, SharedSailingData.class,
|
||||
/* customizer */ null, replicationServiceTracker);
|
||||
sharedSailingDataTracker.open();
|
||||
securityServiceTracker = new FullyInitializedReplicableTracker<>(context, SecurityService.class,
|
||||
/* customizer */ null, replicationServiceTracker);
|
||||
securityServiceTracker.open();
|
||||
if (securityServiceTracker != null) {
|
||||
new Thread("Racingevent wait for securityservice for migration thread") {
|
||||
public void run() {
|
||||
try {
|
||||
// only continue once we have the service, as some of the services require it to start properly
|
||||
securityServiceTracker.waitForService(0);
|
||||
securityServiceTracker.getInitializedService(0);
|
||||
internalStartBundle(context);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Could not start RacingEvent service properly", e);
|
||||
@@ -200,13 +210,15 @@ public class Activator implements BundleActivator {
|
||||
mailQueue.stop();
|
||||
mailServiceTracker.close();
|
||||
sharedSailingDataTracker.close();
|
||||
replicationServiceTracker.close();
|
||||
securityServiceTracker.close();
|
||||
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||
mbs.unregisterMBean(mBeanName);
|
||||
}
|
||||
|
||||
private void internalStartBundle(BundleContext context) throws MalformedURLException, MalformedObjectNameException,
|
||||
InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException {
|
||||
InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException, InterruptedException {
|
||||
assert securityServiceTracker.getInitializedService(0) != null; // callers must call securityServiceTracker.waitForService(0) before calling this method
|
||||
mailQueue = new ExecutorMailQueue(mailServiceTracker);
|
||||
notificationService = new SailingNotificationServiceImpl(context, mailQueue);
|
||||
trackedRegattaListener = new OSGiBasedTrackedRegattaListener(context);
|
||||
@@ -236,7 +248,6 @@ public class Activator implements BundleActivator {
|
||||
// this code block is not run, and the test case can inject some other type of finder
|
||||
// instead.
|
||||
serviceFinderFactory = new CachedOsgiTypeBasedServiceFinderFactory(context);
|
||||
sharedSailingDataTracker = ServiceTrackerFactory.createAndOpen(context, SharedSailingData.class);
|
||||
ServiceTracker<ScoreCorrectionProvider, ScoreCorrectionProvider> scoreCorrectionProviderServiceTracker =
|
||||
ServiceTrackerFactory.createAndOpen(context, ScoreCorrectionProvider.class);
|
||||
ServiceTracker<ResultUrlRegistry, ResultUrlRegistry> resultUrlRegistryServiceTracker = ServiceTrackerFactory
|
||||
@@ -244,7 +255,7 @@ public class Activator implements BundleActivator {
|
||||
racingEventService = new RacingEventServiceImpl(clearPersistentCompetitors,
|
||||
serviceFinderFactory, trackedRegattaListener, notificationService,
|
||||
trackedRaceStatisticsCache, restoreTrackedRaces, securityServiceTracker,
|
||||
sharedSailingDataTracker, scoreCorrectionProviderServiceTracker, resultUrlRegistryServiceTracker);
|
||||
sharedSailingDataTracker, replicationServiceTracker, scoreCorrectionProviderServiceTracker, resultUrlRegistryServiceTracker);
|
||||
notificationService.setRacingEventService(racingEventService);
|
||||
masterDataImportClassLoaderServiceTracker = new ServiceTracker<MasterDataImportClassLoaderService, MasterDataImportClassLoaderService>(
|
||||
context, MasterDataImportClassLoaderService.class,
|
||||
|
||||
+13
-6
@@ -18,8 +18,6 @@ import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.osgi.util.tracker.ServiceTracker;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver;
|
||||
import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState;
|
||||
@@ -88,22 +86,23 @@ import com.sap.sailing.domain.racelog.tracking.SensorFixStore;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceMappingWithRegattaLogEvent;
|
||||
import com.sap.sailing.domain.racelogtracking.PingDeviceIdentifier;
|
||||
import com.sap.sailing.domain.racelogtracking.impl.PingDeviceIdentifierImpl;
|
||||
import com.sap.sailing.domain.sharedsailingdata.SharedSailingData;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.server.gateway.deserialization.impl.CourseConfigurationBuilder;
|
||||
import com.sap.sailing.server.interfaces.CourseAndMarkConfigurationFactory;
|
||||
import com.sap.sailing.shared.server.SharedSailingData;
|
||||
import com.sap.sse.common.NoCorrespondingServiceRegisteredException;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.Timed;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.Util.Pair;
|
||||
import com.sap.sse.replication.FullyInitializedReplicableTracker;
|
||||
import com.sap.sse.security.shared.impl.UserGroup;
|
||||
|
||||
public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfigurationFactory {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(CourseAndMarkConfigurationFactoryImpl.class.getName());
|
||||
|
||||
private final ServiceTracker<SharedSailingData, SharedSailingData> sharedSailingDataTracker;
|
||||
private final FullyInitializedReplicableTracker<SharedSailingData> sharedSailingDataTracker;
|
||||
private final SensorFixStore sensorFixStore;
|
||||
|
||||
/**
|
||||
@@ -117,7 +116,7 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
|
||||
private final DomainFactory domainFactory;
|
||||
|
||||
public CourseAndMarkConfigurationFactoryImpl(
|
||||
ServiceTracker<SharedSailingData, SharedSailingData> sharedSailingDataTracker,
|
||||
FullyInitializedReplicableTracker<SharedSailingData> sharedSailingDataTracker,
|
||||
SensorFixStore sensorFixStore, RaceLogResolver raceLogResolver, DomainFactory domainFactory) {
|
||||
this.sharedSailingDataTracker = sharedSailingDataTracker;
|
||||
this.domainFactory = domainFactory;
|
||||
@@ -139,7 +138,15 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
|
||||
}
|
||||
|
||||
private SharedSailingData getSharedSailingData() {
|
||||
return sharedSailingDataTracker.getService();
|
||||
SharedSailingData result;
|
||||
try {
|
||||
result = sharedSailingDataTracker.getInitializedService(0);
|
||||
} catch (InterruptedException e) {
|
||||
logger.log(Level.SEVERE, "Interrupted while waiting for a fully initialized SharedSailingData service; "
|
||||
+ "continuing with null, probably causing a NullPointerException along the way", e);
|
||||
result = null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private CourseTemplate resolveCourseTemplateSafe(CourseBase course) {
|
||||
|
||||
+33
-21
@@ -189,7 +189,6 @@ import com.sap.sailing.domain.regattalike.IsRegattaLike;
|
||||
import com.sap.sailing.domain.regattalike.LeaderboardThatHasRegattaLike;
|
||||
import com.sap.sailing.domain.regattalog.RegattaLogStore;
|
||||
import com.sap.sailing.domain.resultimport.ResultUrlProvider;
|
||||
import com.sap.sailing.domain.sharedsailingdata.SharedSailingData;
|
||||
import com.sap.sailing.domain.statistics.Statistics;
|
||||
import com.sap.sailing.domain.tracking.AddResult;
|
||||
import com.sap.sailing.domain.tracking.DynamicRaceDefinitionSet;
|
||||
@@ -209,13 +208,13 @@ import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.TrackedRaceStatus;
|
||||
import com.sap.sailing.domain.tracking.TrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.TrackedRegattaListener;
|
||||
import com.sap.sailing.domain.tracking.TrackingConnectorInfo;
|
||||
import com.sap.sailing.domain.tracking.WindStore;
|
||||
import com.sap.sailing.domain.tracking.WindTracker;
|
||||
import com.sap.sailing.domain.tracking.WindTrackerFactory;
|
||||
import com.sap.sailing.domain.tracking.impl.AbstractRaceChangeListener;
|
||||
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRegattaImpl;
|
||||
import com.sap.sailing.domain.tracking.impl.TrackedRaceImpl;
|
||||
import com.sap.sailing.domain.tracking.TrackingConnectorInfo;
|
||||
import com.sap.sailing.domain.windestimation.WindEstimationFactoryService;
|
||||
import com.sap.sailing.expeditionconnector.ExpeditionTrackerFactory;
|
||||
import com.sap.sailing.resultimport.ResultUrlRegistry;
|
||||
@@ -286,6 +285,7 @@ import com.sap.sailing.server.statistics.StatisticsCalculator;
|
||||
import com.sap.sailing.server.statistics.TrackedRaceStatisticsCache;
|
||||
import com.sap.sailing.server.tagging.TaggingServiceFactory;
|
||||
import com.sap.sailing.server.util.EventUtil;
|
||||
import com.sap.sailing.shared.server.SharedSailingData;
|
||||
import com.sap.sse.ServerInfo;
|
||||
import com.sap.sse.common.Distance;
|
||||
import com.sap.sse.common.Duration;
|
||||
@@ -309,6 +309,7 @@ import com.sap.sse.pairinglist.PairingFrameProvider;
|
||||
import com.sap.sse.pairinglist.PairingList;
|
||||
import com.sap.sse.pairinglist.PairingListTemplate;
|
||||
import com.sap.sse.pairinglist.PairingListTemplateFactory;
|
||||
import com.sap.sse.replication.FullyInitializedReplicableTracker;
|
||||
import com.sap.sse.replication.OperationExecutionListener;
|
||||
import com.sap.sse.replication.OperationWithResult;
|
||||
import com.sap.sse.replication.OperationWithResultWithIdWrapper;
|
||||
@@ -519,7 +520,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
|
||||
private Set<OperationWithResultWithIdWrapper<?, ?>> operationsSentToMasterForReplication;
|
||||
|
||||
private boolean currentlyFillingFromInitialLoad = false;
|
||||
private volatile boolean currentlyFillingFromInitialLoad;
|
||||
|
||||
private ThreadLocal<Boolean> currentlyApplyingOperationReceivedFromMaster = ThreadLocal.withInitial(() -> false);
|
||||
|
||||
@@ -534,7 +535,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
private long numberOfTrackedRacesToRestore;
|
||||
|
||||
private final AtomicInteger numberOfTrackedRacesRestored;
|
||||
|
||||
|
||||
private final ServiceTracker<ResultUrlRegistry, ResultUrlRegistry> resultUrlRegistryServiceTracker;
|
||||
|
||||
private final ServiceTracker<ScoreCorrectionProvider, ScoreCorrectionProvider> scoreCorrectionProviderServiceTracker;
|
||||
@@ -565,8 +566,8 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
*/
|
||||
private OperationsToMasterSendingQueue unsentOperationsToMasterSender;
|
||||
|
||||
private ServiceTracker<SecurityService, SecurityService> securityServiceTracker;
|
||||
|
||||
private final FullyInitializedReplicableTracker<SecurityService> securityServiceTracker;
|
||||
|
||||
private final CourseAndMarkConfigurationFactory courseAndMarkConfigurationFactory;
|
||||
|
||||
/**
|
||||
@@ -609,7 +610,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
|
||||
public RacingEventServiceImpl(boolean clearPersistentCompetitorAndBoatStore, final TypeBasedServiceFinderFactory serviceFinderFactory, boolean restoreTrackedRaces) {
|
||||
this(clearPersistentCompetitorAndBoatStore, serviceFinderFactory, null, /* sailingNotificationService */ null,
|
||||
/* trackedRaceStatisticsCache */ null, restoreTrackedRaces, null, /* sharedSailingDataTracker */ null,
|
||||
/* trackedRaceStatisticsCache */ null, restoreTrackedRaces, null, /* sharedSailingDataTracker */ null, /* replicationServiceTracker */ null,
|
||||
/* scoreCorrectionProviderServiceTracker */ null, /* resultUrlRegistryServiceTracker */ null);
|
||||
}
|
||||
|
||||
@@ -636,8 +637,8 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
final TypeBasedServiceFinderFactory serviceFinderFactory, TrackedRegattaListenerManager trackedRegattaListener,
|
||||
SailingNotificationService sailingNotificationService,
|
||||
TrackedRaceStatisticsCache trackedRaceStatisticsCache, boolean restoreTrackedRaces,
|
||||
ServiceTracker<SecurityService, SecurityService> securityServiceTracker,
|
||||
ServiceTracker<SharedSailingData, SharedSailingData> sharedSailingDataTracker,
|
||||
FullyInitializedReplicableTracker<SecurityService> securityServiceTracker,
|
||||
FullyInitializedReplicableTracker<SharedSailingData> sharedSailingDataTracker, ServiceTracker<ReplicationService, ReplicationService> replicationServiceTracker,
|
||||
ServiceTracker<ScoreCorrectionProvider, ScoreCorrectionProvider> scoreCorrectionProviderServiceTracker,
|
||||
ServiceTracker<ResultUrlRegistry, ResultUrlRegistry> resultUrlRegistryServiceTracker) {
|
||||
this((final RaceLogAndTrackedRaceResolver raceLogResolver) -> {
|
||||
@@ -669,8 +670,9 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
}
|
||||
};
|
||||
}, MediaDBFactory.INSTANCE.getDefaultMediaDB(), null, null, serviceFinderFactory, trackedRegattaListener,
|
||||
sailingNotificationService, trackedRaceStatisticsCache, restoreTrackedRaces, securityServiceTracker,
|
||||
sharedSailingDataTracker, scoreCorrectionProviderServiceTracker, resultUrlRegistryServiceTracker);
|
||||
sailingNotificationService, trackedRaceStatisticsCache, restoreTrackedRaces,
|
||||
securityServiceTracker, sharedSailingDataTracker, /* replicationServiceTracker */ null,
|
||||
scoreCorrectionProviderServiceTracker, resultUrlRegistryServiceTracker);
|
||||
}
|
||||
|
||||
private RacingEventServiceImpl(final boolean clearPersistentCompetitorStore, WindStore windStore,
|
||||
@@ -703,10 +705,11 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
return competitorStore;
|
||||
}
|
||||
};
|
||||
}, MediaDBFactory.INSTANCE.getDefaultMediaDB(), windStore, sensorFixStore, serviceFinderFactory, null,
|
||||
sailingNotificationService, /* trackedRaceStatisticsCache */ null, restoreTrackedRaces, null,
|
||||
/* sharedSailingDataTracker */ null, /* scoreCorrectionProviderServiceTracker */ null,
|
||||
/* resultUrlRegistryServiceTracker */ null);
|
||||
}, MediaDBFactory.INSTANCE.getDefaultMediaDB(), windStore, sensorFixStore, serviceFinderFactory,
|
||||
/* tracked regatta listener */ null,
|
||||
sailingNotificationService, /* trackedRaceStatisticsCache */ null, restoreTrackedRaces,
|
||||
/* security service tracker */ null, /* sharedSailingDataTracker */ null, /* replicationServiceTracker */ null,
|
||||
/* scoreCorrectionProviderServiceTracker */ null, /* resultUrlRegistryServiceTracker */ null);
|
||||
}
|
||||
|
||||
public RacingEventServiceImpl(final DomainObjectFactory domainObjectFactory, MongoObjectFactory mongoObjectFactory,
|
||||
@@ -733,8 +736,10 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
return getBaseDomainFactory().getCompetitorAndBoatStore();
|
||||
}
|
||||
};
|
||||
}, mediaDB, windStore, sensorFixStore, null, null, /* sailingNotificationService */ null,
|
||||
/* trackedRaceStatisticsCache */ null, restoreTrackedRaces, null, /* sharedSailingDataTracker */ null,
|
||||
}, mediaDB, windStore, sensorFixStore, /* service finder factory */ null,
|
||||
/* tracked regatta listener */ null, /* sailingNotificationService */ null,
|
||||
/* trackedRaceStatisticsCache */ null, restoreTrackedRaces, /* security service tracker */ null,
|
||||
/* sharedSailingDataTracker */ null, /* replicationServiceTracker */ null,
|
||||
/* scoreCorrectionProviderServiceTracker */ null, /* resultUrlRegistryServiceTracker */ null);
|
||||
}
|
||||
|
||||
@@ -771,11 +776,13 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
TypeBasedServiceFinderFactory serviceFinderFactory, TrackedRegattaListenerManager trackedRegattaListener,
|
||||
SailingNotificationService sailingNotificationService,
|
||||
TrackedRaceStatisticsCache trackedRaceStatisticsCache, boolean restoreTrackedRaces,
|
||||
ServiceTracker<SecurityService, SecurityService> securityServiceTracker,
|
||||
ServiceTracker<SharedSailingData, SharedSailingData> sharedSailingDataTracker,
|
||||
FullyInitializedReplicableTracker<SecurityService> securityServiceTracker,
|
||||
FullyInitializedReplicableTracker<SharedSailingData> sharedSailingDataTracker,
|
||||
ServiceTracker<ReplicationService, ReplicationService> replicationServiceTracker,
|
||||
ServiceTracker<ScoreCorrectionProvider, ScoreCorrectionProvider> scoreCorrectionProviderServiceTracker,
|
||||
ServiceTracker<ResultUrlRegistry, ResultUrlRegistry> resultUrlRegistryServiceTracker) {
|
||||
logger.info("Created " + this);
|
||||
this.currentlyFillingFromInitialLoad = false;
|
||||
this.securityServiceTracker = securityServiceTracker;
|
||||
this.numberOfTrackedRacesRestored = new AtomicInteger();
|
||||
this.resultUrlRegistryServiceTracker = resultUrlRegistryServiceTracker;
|
||||
@@ -4776,13 +4783,18 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
return competitorWithBoat;
|
||||
}
|
||||
|
||||
@Override
|
||||
/**
|
||||
* This should only be used for replicable Operations that need access to the SecurityService, all other should
|
||||
* obtain the SecurityService in another way.
|
||||
*/
|
||||
@Override
|
||||
public SecurityService getSecurityService() {
|
||||
return securityServiceTracker.getService();
|
||||
try {
|
||||
return securityServiceTracker.getInitializedService(0);
|
||||
} catch (InterruptedException e) {
|
||||
logger.severe("Interrupted while waiting for security service; returning null");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
package com.sap.sailing.server.impl;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.sap.sailing.domain.common.DeviceIdentifier;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sailing.domain.coursetemplate.CommonMarkProperties;
|
||||
import com.sap.sailing.domain.coursetemplate.MarkRole;
|
||||
import com.sap.sailing.domain.coursetemplate.MarkTemplate;
|
||||
import com.sap.sailing.domain.coursetemplate.RepeatablePart;
|
||||
import com.sap.sailing.domain.coursetemplate.WaypointTemplate;
|
||||
import com.sap.sailing.domain.sharedsailingdata.SharedSailingData;
|
||||
import com.sap.sse.replication.OperationWithResult;
|
||||
import com.sap.sse.replication.ReplicableWithObjectInputStream;
|
||||
|
||||
public interface ReplicatingSharedSailingData extends SharedSailingData,
|
||||
ReplicableWithObjectInputStream<ReplicatingSharedSailingData, OperationWithResult<ReplicatingSharedSailingData, ?>> {
|
||||
|
||||
Void internalCreateMarkRole(UUID idOfNewMarkRole, String name);
|
||||
|
||||
Void internalCreateMarkProperties(UUID idOfNewMarkProperties, CommonMarkProperties properties,
|
||||
Iterable<String> tags);
|
||||
|
||||
Void internalUpdateMarkProperties(UUID idOfNewMarkProperties, CommonMarkProperties properties, Position position,
|
||||
DeviceIdentifier deviceIdentifier, Iterable<String> tags);
|
||||
|
||||
Void internalCreateMarkTemplate(UUID idOfNewMarkTemplate, CommonMarkProperties properties);
|
||||
|
||||
Void internalCreateCourseTemplate(UUID idOfNewCourseTemplate, String courseTemplateName,
|
||||
Iterable<MarkTemplate> marks, Iterable<WaypointTemplate> waypoints,
|
||||
Map<MarkTemplate, MarkRole> associatedRoles, RepeatablePart optionalRepeatablePart, Iterable<String> tags,
|
||||
URL optionalImageURL, Integer defaultNumberOfLaps);
|
||||
|
||||
Void internalSetTrackingDeviceIdentifierForMarkProperties(UUID markPropertiesUUID, DeviceIdentifier deviceIdentifier);
|
||||
|
||||
Void internalSetFixedPositionForMarkProperties(UUID markPropertiesUUID, Position position);
|
||||
|
||||
Void internalDeleteMarkProperties(UUID markPropertiesUUID);
|
||||
|
||||
Void internalDeleteCourseTemplate(UUID courseTemplateUUID);
|
||||
|
||||
Void internalRecordUsage(UUID markTemplateId, UUID markPropertiesId);
|
||||
|
||||
Void internalRecordUsage(UUID markPropertiesId, MarkRole roleName);
|
||||
|
||||
Void internalUpdateCourseTemplate(UUID uuid, String name, URL optionalImageURL, ArrayList<String> tags);
|
||||
|
||||
}
|
||||
+1
-1
@@ -13,10 +13,10 @@ 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.sharedsailingdata.SharedSailingData;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.server.interfaces.RacingEventService;
|
||||
import com.sap.sailing.shared.server.SharedSailingData;
|
||||
import com.sap.sse.InvalidDateException;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.TypeBasedServiceFinderFactory;
|
||||
|
||||
+1
-1
@@ -7,8 +7,8 @@ import javax.ws.rs.core.Application;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.util.tracker.ServiceTracker;
|
||||
|
||||
import com.sap.sailing.domain.sharedsailingdata.SharedSailingData;
|
||||
import com.sap.sailing.server.interfaces.RacingEventService;
|
||||
import com.sap.sailing.shared.server.SharedSailingData;
|
||||
import com.sap.sse.replication.ReplicationService;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
import com.sun.jersey.spi.container.servlet.ServletContainer;
|
||||
|
||||
@@ -7,38 +7,26 @@ Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Activator: com.sap.sailing.shared.server.impl.Activator
|
||||
Bundle-Vendor: SAP
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Import-Package: com.sap.sailing.server.gateway.deserialization,
|
||||
javax.mail;version="1.4.0",
|
||||
javax.mail.internet;version="1.4.0",
|
||||
javax.mail.util;version="1.4.0",
|
||||
org.json.simple,
|
||||
org.json.simple.parser,
|
||||
org.osgi.framework;version="1.3.0",
|
||||
Import-Package: org.osgi.framework;version="1.3.0",
|
||||
org.osgi.util.tracker;version="1.3.1"
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Require-Bundle: com.sap.sailing.domain,
|
||||
com.sap.sse.mongodb,
|
||||
com.sap.sailing.domain.common,
|
||||
Require-Bundle: com.sap.sailing.domain.common,
|
||||
com.sap.sailing.domain.shared.android,
|
||||
com.sap.sailing.server.gateway.serialization,
|
||||
com.sap.sse.common,
|
||||
com.sap.sse.operationaltransformation,
|
||||
com.sap.sse.replication.interfaces,
|
||||
com.sap.sse,
|
||||
com.sap.sailing.server.gateway.serialization.shared.android,
|
||||
com.sap.sse.shared.android,
|
||||
com.sap.sse.security,
|
||||
com.sap.sse.security.common,
|
||||
org.apache.shiro.web;bundle-version="1.2.2",
|
||||
org.apache.shiro.core;bundle-version="1.2.2",
|
||||
javax.servlet;bundle-version="3.1.0",
|
||||
com.sap.sse.mail,
|
||||
com.sap.sailing.server.interface,
|
||||
org.mongodb.mongo-java-driver;bundle-version="3.6.4",
|
||||
com.sap.sse.security.common,
|
||||
com.sap.sailing.shared.persistence
|
||||
com.sap.sse.operationaltransformation,
|
||||
com.sap.sse.security,
|
||||
com.sap.sailing.shared.persistence,
|
||||
javax.servlet;bundle-version="3.1.0"
|
||||
Bundle-ClassPath: .
|
||||
Export-Package: com.sap.sailing.shared.server.impl;
|
||||
Export-Package: com.sap.sailing.shared.server,
|
||||
com.sap.sailing.shared.server.impl;
|
||||
x-friends:="com.sap.sailing.mongodb.test,
|
||||
com.sap.sailing.server.test,
|
||||
com.sap.sailing.server.gateway.test,
|
||||
|
||||
+5
-2
@@ -1,4 +1,4 @@
|
||||
package com.sap.sailing.domain.sharedsailingdata;
|
||||
package com.sap.sailing.shared.server;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
@@ -17,8 +17,11 @@ import com.sap.sailing.domain.coursetemplate.MarkTemplate;
|
||||
import com.sap.sailing.domain.coursetemplate.Positioning;
|
||||
import com.sap.sailing.domain.coursetemplate.RepeatablePart;
|
||||
import com.sap.sailing.domain.coursetemplate.WaypointTemplate;
|
||||
import com.sap.sailing.shared.server.impl.ReplicatingSharedSailingData;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sse.replication.OperationWithResult;
|
||||
import com.sap.sse.replication.ReplicableWithObjectInputStream;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
import com.sap.sse.security.shared.HasPermissions.DefaultActions;
|
||||
import com.sap.sse.security.shared.impl.UserGroup;
|
||||
@@ -42,7 +45,7 @@ import com.sap.sse.security.shared.impl.UserGroup;
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
*/
|
||||
public interface SharedSailingData {
|
||||
public interface SharedSailingData extends ReplicableWithObjectInputStream<ReplicatingSharedSailingData, OperationWithResult<ReplicatingSharedSailingData, ?>> {
|
||||
|
||||
Iterable<MarkProperties> getAllMarkProperties(Iterable<String> tagsToFilterFor);
|
||||
|
||||
Regular → Executable
+14
-5
@@ -1,17 +1,20 @@
|
||||
package com.sap.sailing.shared.server.impl;
|
||||
|
||||
import java.util.Dictionary;
|
||||
import java.util.HashSet;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Set;
|
||||
|
||||
import org.osgi.framework.BundleActivator;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.framework.ServiceRegistration;
|
||||
import org.osgi.util.tracker.ServiceTracker;
|
||||
|
||||
import com.sap.sailing.domain.sharedsailingdata.SharedSailingData;
|
||||
import com.sap.sailing.shared.persistence.PersistenceFactory;
|
||||
import com.sap.sailing.shared.server.SharedSailingData;
|
||||
import com.sap.sse.osgi.CachedOsgiTypeBasedServiceFinderFactory;
|
||||
import com.sap.sse.replication.FullyInitializedReplicableTracker;
|
||||
import com.sap.sse.replication.Replicable;
|
||||
import com.sap.sse.replication.ReplicationService;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
import com.sap.sse.util.ClearStateTestSupport;
|
||||
import com.sap.sse.util.ServiceTrackerFactory;
|
||||
@@ -24,21 +27,27 @@ public class Activator implements BundleActivator {
|
||||
|
||||
private Set<ServiceRegistration<?>> registrations = new HashSet<>();
|
||||
|
||||
private ServiceTracker<SecurityService, SecurityService> securityServiceTracker;
|
||||
private FullyInitializedReplicableTracker<SecurityService> securityServiceTracker;
|
||||
|
||||
private SharedSailingDataImpl sharedSailingData;
|
||||
|
||||
public void start(BundleContext context) throws Exception {
|
||||
Activator.context = context;
|
||||
securityServiceTracker = ServiceTrackerFactory.createAndOpen(context, SecurityService.class);
|
||||
securityServiceTracker = new FullyInitializedReplicableTracker<>(context, SecurityService.class,
|
||||
/* customizer */ null, ServiceTrackerFactory.createAndOpen(context, ReplicationService.class));
|
||||
securityServiceTracker.open();
|
||||
serviceFinderFactory = new CachedOsgiTypeBasedServiceFinderFactory(context);
|
||||
sharedSailingData = new SharedSailingDataImpl(PersistenceFactory.INSTANCE.getDefaultDomainObjectFactory(serviceFinderFactory),
|
||||
PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(serviceFinderFactory), serviceFinderFactory,
|
||||
securityServiceTracker);
|
||||
registrations.add(context.registerService(SharedSailingData.class, sharedSailingData, /* properties */ null));
|
||||
registrations.add(context.registerService(ReplicatingSharedSailingData.class, sharedSailingData, /* properties */ null));
|
||||
registrations
|
||||
.add(context.registerService(ClearStateTestSupport.class, sharedSailingData, /* properties */ null));
|
||||
registrations.add(context.registerService(Replicable.class, sharedSailingData, /* properties */ null));
|
||||
final Dictionary<String, String> replicableServiceProperties = new Hashtable<>();
|
||||
replicableServiceProperties.put(Replicable.OSGi_Service_Registry_ID_Property_Name,
|
||||
sharedSailingData.getId().toString());
|
||||
registrations.add(context.registerService(Replicable.class, sharedSailingData, /* properties */ replicableServiceProperties));
|
||||
}
|
||||
|
||||
public static BundleContext getContext() {
|
||||
|
||||
+2
-5
@@ -11,12 +11,9 @@ import com.sap.sailing.domain.coursetemplate.MarkTemplate;
|
||||
import com.sap.sailing.domain.coursetemplate.Positioning;
|
||||
import com.sap.sailing.domain.coursetemplate.RepeatablePart;
|
||||
import com.sap.sailing.domain.coursetemplate.WaypointTemplate;
|
||||
import com.sap.sailing.domain.sharedsailingdata.SharedSailingData;
|
||||
import com.sap.sse.replication.OperationWithResult;
|
||||
import com.sap.sse.replication.ReplicableWithObjectInputStream;
|
||||
import com.sap.sailing.shared.server.SharedSailingData;
|
||||
|
||||
public interface ReplicatingSharedSailingData extends SharedSailingData,
|
||||
ReplicableWithObjectInputStream<ReplicatingSharedSailingData, OperationWithResult<ReplicatingSharedSailingData, ?>> {
|
||||
public interface ReplicatingSharedSailingData extends SharedSailingData {
|
||||
|
||||
Void internalCreateMarkRole(UUID idOfNewMarkRole, String name, String shortName);
|
||||
|
||||
|
||||
+12
-8
@@ -17,8 +17,6 @@ import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.osgi.util.tracker.ServiceTracker;
|
||||
|
||||
import com.sap.sailing.domain.common.DeviceIdentifier;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sailing.domain.common.security.SecuredDomainType;
|
||||
@@ -47,6 +45,7 @@ import com.sap.sse.common.TypeBasedServiceFinder;
|
||||
import com.sap.sse.common.TypeBasedServiceFinderFactory;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sse.replication.FullyInitializedReplicableTracker;
|
||||
import com.sap.sse.replication.OperationExecutionListener;
|
||||
import com.sap.sse.replication.OperationWithResult;
|
||||
import com.sap.sse.replication.OperationWithResultWithIdWrapper;
|
||||
@@ -69,11 +68,11 @@ public class SharedSailingDataImpl implements ReplicatingSharedSailingData, Clea
|
||||
private final Map<UUID, MarkRole> markRolesById = new ConcurrentHashMap<>();
|
||||
|
||||
private final TypeBasedServiceFinder<DeviceIdentifierMongoHandler> deviceIdentifierServiceFinder;
|
||||
private final ServiceTracker<SecurityService, SecurityService> securityServiceTracker;
|
||||
private final FullyInitializedReplicableTracker<SecurityService> securityServiceTracker;
|
||||
|
||||
// Replication related methods and fields
|
||||
private final ConcurrentHashMap<OperationExecutionListener<ReplicatingSharedSailingData>, OperationExecutionListener<ReplicatingSharedSailingData>> operationExecutionListeners = new ConcurrentHashMap<>();
|
||||
private ThreadLocal<Boolean> currentlyFillingFromInitialLoad = ThreadLocal.withInitial(() -> false);
|
||||
private volatile boolean currentlyFillingFromInitialLoad;
|
||||
private ThreadLocal<Boolean> currentlyApplyingOperationReceivedFromMaster = ThreadLocal.withInitial(() -> false);
|
||||
private final Set<OperationWithResultWithIdWrapper<ReplicatingSharedSailingData, ?>> operationsSentToMasterForReplication = new HashSet<>();
|
||||
private ReplicationMasterDescriptor master;
|
||||
@@ -87,7 +86,8 @@ public class SharedSailingDataImpl implements ReplicatingSharedSailingData, Clea
|
||||
|
||||
public SharedSailingDataImpl(final DomainObjectFactory domainObjectFactory,
|
||||
final MongoObjectFactory mongoObjectFactory, TypeBasedServiceFinderFactory serviceFinderFactory,
|
||||
ServiceTracker<SecurityService, SecurityService> securityServiceTracker) {
|
||||
FullyInitializedReplicableTracker<SecurityService> securityServiceTracker) {
|
||||
this.currentlyFillingFromInitialLoad = false;
|
||||
this.domainObjectFactory = domainObjectFactory;
|
||||
this.mongoObjectFactory = mongoObjectFactory;
|
||||
this.deviceIdentifierServiceFinder = serviceFinderFactory
|
||||
@@ -123,7 +123,11 @@ public class SharedSailingDataImpl implements ReplicatingSharedSailingData, Clea
|
||||
}
|
||||
|
||||
public SecurityService getSecurityService() {
|
||||
return securityServiceTracker.getService();
|
||||
try {
|
||||
return securityServiceTracker.getInitializedService(0);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -579,12 +583,12 @@ public class SharedSailingDataImpl implements ReplicatingSharedSailingData, Clea
|
||||
|
||||
@Override
|
||||
public boolean isCurrentlyFillingFromInitialLoad() {
|
||||
return currentlyFillingFromInitialLoad.get();
|
||||
return currentlyFillingFromInitialLoad;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentlyFillingFromInitialLoad(boolean currentlyFillingFromInitialLoad) {
|
||||
this.currentlyFillingFromInitialLoad.set(currentlyFillingFromInitialLoad);
|
||||
this.currentlyFillingFromInitialLoad = currentlyFillingFromInitialLoad;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+4
-3
@@ -45,7 +45,7 @@ public abstract class AbstractReplicableWithObjectInputStream<S, O extends Opera
|
||||
|
||||
private final Set<OperationWithResult<S, ?>> operationsSentToMasterForReplication;
|
||||
|
||||
private ThreadLocal<Boolean> currentlyFillingFromInitialLoad = ThreadLocal.withInitial(() -> false);
|
||||
private volatile boolean currentlyFillingFromInitialLoad;
|
||||
|
||||
private ThreadLocal<Boolean> currentlyApplyingOperationReceivedFromMaster = ThreadLocal.withInitial(() -> false);
|
||||
|
||||
@@ -54,6 +54,7 @@ public abstract class AbstractReplicableWithObjectInputStream<S, O extends Opera
|
||||
public AbstractReplicableWithObjectInputStream() {
|
||||
this.operationsSentToMasterForReplication = new HashSet<>();
|
||||
this.operationExecutionListeners = new ConcurrentHashMap<>();
|
||||
this.currentlyFillingFromInitialLoad = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,12 +87,12 @@ public abstract class AbstractReplicableWithObjectInputStream<S, O extends Opera
|
||||
|
||||
@Override
|
||||
public boolean isCurrentlyFillingFromInitialLoad() {
|
||||
return currentlyFillingFromInitialLoad.get();
|
||||
return currentlyFillingFromInitialLoad;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentlyFillingFromInitialLoad(boolean currentlyFillingFromInitialLoad) {
|
||||
this.currentlyFillingFromInitialLoad.set(currentlyFillingFromInitialLoad);
|
||||
this.currentlyFillingFromInitialLoad = currentlyFillingFromInitialLoad;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="yield_content">
|
||||
<div class="contentWrapper">
|
||||
<div class="mainContent">
|
||||
<h2 class="releaseHeadline">Release Notes - Administration Console</h2>
|
||||
<div class="innerContent">
|
||||
<div class="contentWrapper">
|
||||
<div class="mainContent">
|
||||
<h2 class="releaseHeadline">Release Notes - Administration Console</h2>
|
||||
<div class="innerContent">
|
||||
<h2 class="articleSubheadline">March 2020</h2>
|
||||
<ul class="bulletList">
|
||||
<li>The visualization for ORC certificates has been much improved. It now shows all the
|
||||
@@ -28,6 +28,11 @@
|
||||
official PDF version of the respective certificate, based on its reference number.
|
||||
</li>
|
||||
<li>Improved ESC/Enter key handling in user role/permission editing dialog</li>
|
||||
<li>The "Replication" panel in the "Advanced" category now has improved information about the
|
||||
replicables shown. An advanced replica information string may reveal more than just the address,
|
||||
and the address is now resolved through any <tt>X-Forwarded-For</tt> header fields present
|
||||
during replica registration, hence also working through load balancers and reverse proxies.
|
||||
</li>
|
||||
</ul>
|
||||
<h2 class="articleSubheadline">February 2020</h2>
|
||||
<ul class="bulletList">
|
||||
|
||||
+4
-3
@@ -48,7 +48,7 @@ public class FileStorageManagementServiceImpl implements ReplicableFileStorageMa
|
||||
private final Map<OperationExecutionListener<ReplicableFileStorageManagementService>, OperationExecutionListener<ReplicableFileStorageManagementService>> operationExecutionListeners = new ConcurrentHashMap<>();
|
||||
private final Set<OperationWithResultWithIdWrapper<?, ?>> operationsSentToMasterForReplication = new HashSet<>();
|
||||
private ReplicationMasterDescriptor replicationMasterDescriptor;
|
||||
private ThreadLocal<Boolean> currentlyFillingFromInitialLoad = ThreadLocal.withInitial(() -> false);
|
||||
private volatile boolean currentlyFillingFromInitialLoad;
|
||||
|
||||
private ThreadLocal<Boolean> currentlyApplyingOperationReceivedFromMaster = ThreadLocal.withInitial(() -> false);
|
||||
|
||||
@@ -68,6 +68,7 @@ public class FileStorageManagementServiceImpl implements ReplicableFileStorageMa
|
||||
|
||||
public FileStorageManagementServiceImpl(TypeBasedServiceFinder<FileStorageService> serviceFinder,
|
||||
FileStorageServicePropertyStore propertyStore) {
|
||||
this.currentlyFillingFromInitialLoad = false;
|
||||
this.serviceFinder = serviceFinder;
|
||||
this.propertyStore = propertyStore;
|
||||
serviceResolver = new FileStorageServiceResolverAgainstOsgiRegistryImpl(serviceFinder);
|
||||
@@ -229,12 +230,12 @@ public class FileStorageManagementServiceImpl implements ReplicableFileStorageMa
|
||||
|
||||
@Override
|
||||
public boolean isCurrentlyFillingFromInitialLoad() {
|
||||
return currentlyFillingFromInitialLoad.get();
|
||||
return currentlyFillingFromInitialLoad;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentlyFillingFromInitialLoad(boolean currentlyFillingFromInitialLoad) {
|
||||
this.currentlyFillingFromInitialLoad.set(currentlyFillingFromInitialLoad);
|
||||
this.currentlyFillingFromInitialLoad = currentlyFillingFromInitialLoad;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -48,7 +48,7 @@ public class MailServiceImpl implements ReplicableMailService {
|
||||
private ReplicationMasterDescriptor replicatingFromMaster;
|
||||
private final ConcurrentMap<OperationExecutionListener<ReplicableMailService>, OperationExecutionListener<ReplicableMailService>> operationExecutionListeners;
|
||||
private final Set<OperationWithResultWithIdWrapper<?, ?>> operationsSentToMasterForReplication = new HashSet<>();
|
||||
private ThreadLocal<Boolean> currentlyFillingFromInitialLoad = ThreadLocal.withInitial(() -> false);
|
||||
private volatile boolean currentlyFillingFromInitialLoad;
|
||||
|
||||
private ThreadLocal<Boolean> currentlyApplyingOperationReceivedFromMaster = ThreadLocal.withInitial(() -> false);
|
||||
|
||||
@@ -63,6 +63,7 @@ public class MailServiceImpl implements ReplicableMailService {
|
||||
private OperationsToMasterSendingQueue unsentOperationForMasterQueue;
|
||||
|
||||
public MailServiceImpl(Properties mailProperties, MailServiceResolver mailServiceResolver) {
|
||||
this.currentlyFillingFromInitialLoad = false;
|
||||
this.mailProperties = mailProperties;
|
||||
this.operationExecutionListeners = new ConcurrentHashMap<>();
|
||||
this.mailServiceResolver = mailServiceResolver;
|
||||
@@ -238,12 +239,12 @@ public class MailServiceImpl implements ReplicableMailService {
|
||||
|
||||
@Override
|
||||
public boolean isCurrentlyFillingFromInitialLoad() {
|
||||
return currentlyFillingFromInitialLoad.get();
|
||||
return currentlyFillingFromInitialLoad;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentlyFillingFromInitialLoad(boolean currentlyFillingFromInitialLoad) {
|
||||
this.currentlyFillingFromInitialLoad.set(currentlyFillingFromInitialLoad);
|
||||
this.currentlyFillingFromInitialLoad = currentlyFillingFromInitialLoad;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -9,7 +9,9 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Export-Package: com.sap.sse.replication,
|
||||
com.sap.sse.replication.impl
|
||||
Import-Package: com.rabbitmq.client;version="2.8.4",
|
||||
org.json.simple
|
||||
org.json.simple,
|
||||
org.osgi.framework;version="1.8.0",
|
||||
org.osgi.util.tracker;version="1.5.1"
|
||||
Require-Bundle: com.sap.sse.operationaltransformation;bundle-version="1.0.0",
|
||||
com.sap.sse.common;bundle-version="1.0.0",
|
||||
com.sap.sse;bundle-version="1.0.0"
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
package com.sap.sse.replication;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.framework.Filter;
|
||||
import org.osgi.framework.ServiceReference;
|
||||
import org.osgi.util.tracker.ServiceTracker;
|
||||
import org.osgi.util.tracker.ServiceTrackerCustomizer;
|
||||
|
||||
import com.sap.sse.replication.ReplicationService.ReplicationStartingListener;
|
||||
|
||||
/**
|
||||
* While a regular OSGi {@link ServiceTracker} would {@link ServiceTracker#waitForService(long) wait} for the service's
|
||||
* appearance in the OSGi registry and then return it, this specialization is aware of the {@link ReplicationService}
|
||||
* and understands the replication life cycle which can be in {@link ReplicationService#isReplicationStarting()
|
||||
* starting} mode, and furthermore each replicable can be in the process of handling its initial load. This tracker has
|
||||
* a specialized {@link #waitForService(long)} implementation that waits for the {@link ReplicationService} to not be in
|
||||
* state {@link ReplicationService#isReplicationStarting()}, waits for the replicable requested using the regular
|
||||
* (super-class) {@link ServiceTracker#waitForService(long)} method and asserts the {@link Replicable} to return is
|
||||
* not in the state {@link Replicable#isCurrentlyFillingFromInitialLoad()}.<p>
|
||||
*
|
||||
* By analogy, the {@link #getService()} and related methods return only services for which the above rules apply.
|
||||
* In particular, {@link #getService()} will return {@code null} if the {@link ReplicationService} is currently in mode
|
||||
* {@link ReplicationService#isReplicationStarting()} or the replicable found by the regular OSGi tracker is currently
|
||||
* {@link Replicable#isCurrentlyFillingFromInitialLoad() receiving its initial load}.<p>
|
||||
*
|
||||
* Note that {@link #waitForService(long)} must not be used during the activation of a {@link Replicable}'s bundle before
|
||||
* that {@link Replicable} has been registered with the OSGi registry. Otherwise, a deadlock can result because the waiting
|
||||
* {@link Replicable} will hold up the completion of the replication start-up and hence wait forever.
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
* @param <R>
|
||||
* the type of {@link Replicable} to track
|
||||
*/
|
||||
public class FullyInitializedReplicableTracker<R extends Replicable<?, ?>> extends ServiceTracker<R, R> {
|
||||
/**
|
||||
* Used to find the {@link ReplicationService}. If {@code null}, no attempt will be made to look
|
||||
* for the {@link ReplicationService}, and only the replicable's {@link Replicable#isCurrentlyFillingFromInitialLoad()}
|
||||
* result will be considered.
|
||||
*/
|
||||
private final ServiceTracker<ReplicationService, ReplicationService> replicationServiceTracker;
|
||||
|
||||
public FullyInitializedReplicableTracker(BundleContext context, Class<R> clazz,
|
||||
ServiceTrackerCustomizer<R, R> customizer,
|
||||
ServiceTracker<ReplicationService, ReplicationService> replicationServiceTracker) {
|
||||
super(context, clazz, customizer);
|
||||
this.replicationServiceTracker = replicationServiceTracker;
|
||||
}
|
||||
|
||||
public FullyInitializedReplicableTracker(BundleContext context, Filter filter,
|
||||
ServiceTrackerCustomizer<R, R> customizer,
|
||||
ServiceTracker<ReplicationService, ReplicationService> replicationServiceTracker) {
|
||||
super(context, filter, customizer);
|
||||
this.replicationServiceTracker = replicationServiceTracker;
|
||||
}
|
||||
|
||||
public FullyInitializedReplicableTracker(BundleContext context, ServiceReference<R> reference,
|
||||
ServiceTrackerCustomizer<R, R> customizer,
|
||||
ServiceTracker<ReplicationService, ReplicationService> replicationServiceTracker) {
|
||||
super(context, reference, customizer);
|
||||
this.replicationServiceTracker = replicationServiceTracker;
|
||||
}
|
||||
|
||||
public FullyInitializedReplicableTracker(BundleContext context, String clazz,
|
||||
ServiceTrackerCustomizer<R, R> customizer,
|
||||
ServiceTracker<ReplicationService, ReplicationService> replicationServiceTracker) {
|
||||
super(context, clazz, customizer);
|
||||
this.replicationServiceTracker = replicationServiceTracker;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param timeoutInMillis
|
||||
* 0 means indefinite waiting time
|
||||
* @return {@code true} if the {@link #replicationServiceTracker} is {@code null} or the {@link ReplicationService}
|
||||
* was obtained successfully and has been in or has reached the state of not
|
||||
* {@link ReplicationService#isReplicationStarting()} within the timeout provided. {@code false} otherwise.
|
||||
*/
|
||||
private boolean waitForReplicationToBeInitialized(long timeoutInMillis) throws InterruptedException {
|
||||
final boolean result;
|
||||
if (replicationServiceTracker != null) {
|
||||
final CountDownLatch latch = new CountDownLatch(1); // counted down either by the direct check or the listener
|
||||
final ReplicationService replicationService = replicationServiceTracker.waitForService(timeoutInMillis);
|
||||
final ReplicationStartingListener replicationStartingListener = newIsReplicationStarting->{
|
||||
if (!newIsReplicationStarting) {
|
||||
latch.countDown();
|
||||
}
|
||||
};
|
||||
replicationService.addReplicationStartingListener(replicationStartingListener);
|
||||
if (!replicationService.isReplicationStarting()) {
|
||||
latch.countDown();
|
||||
}
|
||||
result = latch.await(timeoutInMillis, TimeUnit.MILLISECONDS);
|
||||
replicationService.removeReplicationStartingListener(replicationStartingListener);
|
||||
} else {
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for one service object tracked to appear for {@code timeoutInMillis} milliseconds (see
|
||||
* {@link #waitForService(long)}). If no such service object can be found before timing out, {@code null}
|
||||
* is returned. Once a service object has been retrieved and a non-{@code null} {@link #replicationServiceTracker}
|
||||
* has been provided at construction time, the {@link ReplicationService} is obtained from that tracker by
|
||||
* waiting for it at least {@code timeoutInMillis} milliseconds and then
|
||||
*
|
||||
* @param timeoutInMillis
|
||||
* 0 means indefinite wait time
|
||||
* @return {@code null} if no service was obtained from the registry in the timeout specified or the replication did
|
||||
* not reach a fully initialized state in the timeout specified.
|
||||
*/
|
||||
public R getInitializedService(long timeoutInMillis) throws InterruptedException {
|
||||
final R service = waitForService(timeoutInMillis);
|
||||
final R result;
|
||||
if (service != null) {
|
||||
if (waitForReplicationToBeInitialized(timeoutInMillis)) {
|
||||
result = service;
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+7
@@ -45,6 +45,13 @@ public interface OperationWithResult<S, R> extends Operation<S>, Serializable {
|
||||
default boolean isRequiresExplicitTransitiveReplication() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the class to use for keeping statistics; this allows wrapper classes to report the actual inner class
|
||||
*/
|
||||
default Class<?> getClassForLogging() {
|
||||
return getClass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ignores the actual result of {@link #internalApplyTo(Object)} and returns <code>toState</code> which
|
||||
|
||||
+9
-2
@@ -24,8 +24,7 @@ public class OperationWithResultWithIdWrapper<S, R> implements OperationWithResu
|
||||
* Creates a new UUID for this wrapper operation
|
||||
*/
|
||||
public OperationWithResultWithIdWrapper(OperationWithResult<S, R> delegate) {
|
||||
this.delegate = delegate;
|
||||
this.id = UUID.randomUUID();
|
||||
this(delegate, UUID.randomUUID());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,6 +36,14 @@ public class OperationWithResultWithIdWrapper<S, R> implements OperationWithResu
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link #delegate}'s class for keeping statistics
|
||||
*/
|
||||
@Override
|
||||
public Class<?> getClassForLogging() {
|
||||
return delegate.getClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
|
||||
+13
@@ -113,7 +113,20 @@ public interface ReplicationService {
|
||||
*/
|
||||
ReplicationReceiver getReplicator();
|
||||
|
||||
/**
|
||||
* An update to this attribute can be observed by registering a {@link ReplicationStartingListener} using
|
||||
* the {@link #addReplicationStartingListener} method.
|
||||
*/
|
||||
void setReplicationStarting(boolean b);
|
||||
|
||||
@FunctionalInterface
|
||||
public static interface ReplicationStartingListener {
|
||||
void onReplicationStartingChanged(boolean newReplicationStartingValue);
|
||||
}
|
||||
|
||||
void addReplicationStartingListener(ReplicationStartingListener listener);
|
||||
|
||||
void removeReplicationStartingListener(ReplicationStartingListener listener);
|
||||
|
||||
/**
|
||||
* @return {@code true} if replication is starting; during this phase it is clear that the replicables managed by
|
||||
|
||||
Regular → Executable
+1
@@ -175,6 +175,7 @@ public class Activator implements BundleActivator {
|
||||
" before firing up replication automatically...");
|
||||
final List<Replicable<?, ?>> replicables = new ArrayList<>();
|
||||
for (String replicableIdAsString : replicableIdsAsStrings) {
|
||||
logger.info("Trying to obtain Replicable " + replicableIdAsString+", waiting if necessary");
|
||||
Replicable<?, ?> replicable = replicablesProvider.getReplicable(replicableIdAsString, /* wait */true);
|
||||
logger.info("Obtained Replicable " + replicableIdAsString);
|
||||
replicables.add(replicable);
|
||||
|
||||
+35
-13
@@ -19,6 +19,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.UUID;
|
||||
@@ -232,7 +233,7 @@ public class ReplicationServiceImpl implements ReplicationService, OperationsToM
|
||||
/**
|
||||
* Will be set
|
||||
*/
|
||||
private boolean replicationStarting;
|
||||
private volatile boolean replicationStarting;
|
||||
|
||||
/**
|
||||
* An optional link to a persistence layer that allows this service to record replicas
|
||||
@@ -240,6 +241,8 @@ public class ReplicationServiceImpl implements ReplicationService, OperationsToM
|
||||
* links can be re-established.
|
||||
*/
|
||||
private final Optional<MongoObjectFactory> mongoObjectFactory;
|
||||
|
||||
private final Set<ReplicationStartingListener> replicationStartingListeners;
|
||||
|
||||
private static class InitialLoadRequest {
|
||||
private final Channel channelForInitialLoad;
|
||||
@@ -320,6 +323,7 @@ public class ReplicationServiceImpl implements ReplicationService, OperationsToM
|
||||
Optional<MongoObjectFactory> optionalMongoObjectFactory, String exchangeName, String exchangeHost, int exchangePort,
|
||||
ReplicationInstancesManager replicationInstancesManager, ReplicablesProvider replicablesProvider) throws IOException {
|
||||
this.mongoObjectFactory = optionalMongoObjectFactory;
|
||||
this.replicationStartingListeners = new HashSet<>();
|
||||
timer = new Timer("ReplicationServiceImpl timer for delayed task sending", /* isDaemon */ true);
|
||||
unsentOperationsSenderJob = new UnsentOperationsSenderJob();
|
||||
executionListenersByReplicableIdAsString = new ConcurrentHashMap<>();
|
||||
@@ -521,7 +525,7 @@ public class ReplicationServiceImpl implements ReplicationService, OperationsToM
|
||||
outboundBufferClasses = new ArrayList<>();
|
||||
}
|
||||
outboundObjectBuffer.writeObject(serializedOperation);
|
||||
outboundBufferClasses.add(operation.getClass());
|
||||
outboundBufferClasses.add(operation.getClassForLogging());
|
||||
if (outboundBuffer.size() > TRIGGER_MESSAGE_SIZE_IN_BYTES) {
|
||||
logger.info("Triggering replication because buffer holds " + outboundBuffer.size()
|
||||
+ " bytes which exceeds trigger size " + TRIGGER_MESSAGE_SIZE_IN_BYTES + " bytes");
|
||||
@@ -647,7 +651,7 @@ public class ReplicationServiceImpl implements ReplicationService, OperationsToM
|
||||
final Iterable<Replicable<?, ?>> replicables = master.getReplicables();
|
||||
logger.info("Starting to replicate from " + master);
|
||||
try {
|
||||
registerReplicaWithMaster(master, replicables);
|
||||
registerReplicaWithMaster(master);
|
||||
} catch (Exception ex) {
|
||||
logger.log(Level.SEVERE, "ERROR", ex);
|
||||
throw ex;
|
||||
@@ -680,7 +684,7 @@ public class ReplicationServiceImpl implements ReplicationService, OperationsToM
|
||||
final URL initialLoadURL = master.getInitialLoadURL(replicables);
|
||||
logger.info("Initial load URL is " + initialLoadURL);
|
||||
// start receiving messages already now, but start in suspended mode
|
||||
replicator = new ReplicationReceiverImpl(master, replicablesProvider, /* startSuspended */true, consumer);
|
||||
replicator = new ReplicationReceiverImpl(master, replicablesProvider, /* startSuspended */ true, consumer);
|
||||
// clear Replicable state here, before starting to receive and de-serialize operations which builds up
|
||||
// new state, e.g., in competitor store
|
||||
for (Replicable<?, ?> r : replicables) {
|
||||
@@ -733,18 +737,13 @@ public class ReplicationServiceImpl implements ReplicationService, OperationsToM
|
||||
}
|
||||
|
||||
/**
|
||||
* @param replicables
|
||||
* the replica is registered for these {@link Replicable}s. The master sends operations only for
|
||||
* replicables that at least one replica has registered for. This may mean that operations are received
|
||||
* for replicables for which no replicable was requested. Replicas shall drop such operations silently.
|
||||
* TODO unused...
|
||||
*
|
||||
* @return the UUID that the master generated for this client which is also entered into {@link #replicaUUIDs}
|
||||
*/
|
||||
private String registerReplicaWithMaster(ReplicationMasterDescriptor master, Iterable<Replicable<?, ?>> replicables) throws IOException,
|
||||
private String registerReplicaWithMaster(ReplicationMasterDescriptor master) throws IOException,
|
||||
ClassNotFoundException {
|
||||
URL replicationRegistrationRequestURL = master.getReplicationRegistrationRequestURL(getServerIdentifier(),
|
||||
ServerInfo.getBuildVersion());
|
||||
logger.info("Replication registration request URL: "+replicationRegistrationRequestURL);
|
||||
final URLConnection registrationRequestConnection = HttpUrlConnectionHelper
|
||||
.redirectConnectionWithBearerToken(replicationRegistrationRequestURL, master.getBearerToken());
|
||||
final InputStream content = (InputStream) registrationRequestConnection.getContent();
|
||||
@@ -761,6 +760,7 @@ public class ReplicationServiceImpl implements ReplicationService, OperationsToM
|
||||
}
|
||||
}
|
||||
final String replicaUUID = uuid.toString();
|
||||
logger.info("Obtained replica UUID "+replicaUUID+" from master");
|
||||
registerReplicaUuidForMaster(replicaUUID, master);
|
||||
return replicaUUID;
|
||||
}
|
||||
@@ -891,9 +891,31 @@ public class ReplicationServiceImpl implements ReplicationService, OperationsToM
|
||||
servletPort, bearerToken, replicables);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setReplicationStarting(boolean b) {
|
||||
this.replicationStarting = b;
|
||||
public void addReplicationStartingListener(ReplicationStartingListener listener) {
|
||||
synchronized (replicationStartingListeners) {
|
||||
replicationStartingListeners.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeReplicationStartingListener(ReplicationStartingListener listener) {
|
||||
synchronized (replicationStartingListeners) {
|
||||
replicationStartingListeners.remove(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReplicationStarting(boolean newReplicationStarting) {
|
||||
if (this.replicationStarting != newReplicationStarting) {
|
||||
this.replicationStarting = newReplicationStarting;
|
||||
synchronized (replicationStartingListeners) {
|
||||
for (final ReplicationStartingListener listener : replicationStartingListeners) {
|
||||
listener.onReplicationStartingChanged(newReplicationStarting);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -504,7 +504,7 @@ public class UserManagementServiceImpl extends RemoteServiceServlet implements U
|
||||
public User call() throws Exception {
|
||||
if (userGroupExists(username + SecurityService.TENANT_SUFFIX)) {
|
||||
throw new UserManagementException(
|
||||
"User tenant already exists, please chose a different username!");
|
||||
"User "+username+" already exists, please chose a different username!");
|
||||
}
|
||||
try {
|
||||
User newUser = getSecurityService().createSimpleUser(username, email, password, fullName,
|
||||
|
||||
-2
@@ -381,7 +381,6 @@ public class AccessControlStoreImpl implements AccessControlStore {
|
||||
public Iterable<OwnershipAnnotation> getOwnerships() {
|
||||
return LockUtil.executeWithReadLockAndResult(lockForManagementMappings,
|
||||
new RunnableWithResult<Iterable<OwnershipAnnotation>>() {
|
||||
|
||||
@Override
|
||||
public Iterable<OwnershipAnnotation> run() {
|
||||
return new ArrayList<>(ownerships.values());
|
||||
@@ -392,7 +391,6 @@ public class AccessControlStoreImpl implements AccessControlStore {
|
||||
@Override
|
||||
public void clear() {
|
||||
LockUtil.executeWithWriteLock(lockForManagementMappings, new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
accessControlLists.clear();
|
||||
|
||||
@@ -171,7 +171,7 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
|
||||
|
||||
private Set<OperationWithResultWithIdWrapper<?, ?>> operationsSentToMasterForReplication;
|
||||
|
||||
private ThreadLocal<Boolean> currentlyFillingFromInitialLoad = ThreadLocal.withInitial(() -> false);
|
||||
private volatile boolean currentlyFillingFromInitialLoad;
|
||||
|
||||
private ThreadLocal<Boolean> currentlyApplyingOperationReceivedFromMaster = ThreadLocal.withInitial(() -> false);
|
||||
|
||||
@@ -240,6 +240,8 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
|
||||
AccessControlStore accessControlStore, HasPermissionsProvider hasPermissionsProvider,
|
||||
String sharedAcrossSubdomainsOf, String baseUrlForCrossDomainStorage) {
|
||||
logger.info("Initializing Security Service with user store " + userStore);
|
||||
this.currentlyFillingFromInitialLoad = false;
|
||||
this.currentlyFillingFromInitialLoad = false;
|
||||
operationsSentToMasterForReplication = new HashSet<>();
|
||||
this.sharedAcrossSubdomainsOf = sharedAcrossSubdomainsOf;
|
||||
this.baseUrlForCrossDomainStorage = baseUrlForCrossDomainStorage;
|
||||
@@ -288,12 +290,12 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
|
||||
|
||||
@Override
|
||||
public boolean isCurrentlyFillingFromInitialLoad() {
|
||||
return currentlyFillingFromInitialLoad.get();
|
||||
return currentlyFillingFromInitialLoad;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentlyFillingFromInitialLoad(boolean currentlyFillingFromInitialLoad) {
|
||||
this.currentlyFillingFromInitialLoad.set(currentlyFillingFromInitialLoad);
|
||||
this.currentlyFillingFromInitialLoad = currentlyFillingFromInitialLoad;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in new issue
Block a user