Clean up mdsal-singleton-dom-impl 45/109245/1
authorRobert Varga <robert.varga@pantheon.tech>
Sat, 9 Dec 2023 06:38:46 +0000 (07:38 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Sat, 9 Dec 2023 07:46:50 +0000 (08:46 +0100)
Fold the multitude of implementation classes into a single
EOSClusterSingletonServiceProvider.

Furthermore do not expose close() from the implemented interface, so
that users do not end up shutting the implementation down.

Eliminate ServiceLoader integration, as we are a stateful component
and therefore want to explicit lifecycle.

The shutdown process is made synchronous, so that close() waits for
everything to settle down.

JIRA: MDSAL-843
Change-Id: I0d137d03d184de07e21e5a9a4329855a021dd433
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
14 files changed:
replicate/mdsal-replicate-netty/src/test/java/org/opendaylight/mdsal/replicate/netty/IntegrationTest.java
singleton-service/mdsal-singleton-common-api/src/main/java/org/opendaylight/mdsal/singleton/common/api/ClusterSingletonServiceProvider.java
singleton-service/mdsal-singleton-dom-impl/pom.xml
singleton-service/mdsal-singleton-dom-impl/src/main/java/module-info.java
singleton-service/mdsal-singleton-dom-impl/src/main/java/org/opendaylight/mdsal/singleton/dom/impl/ClusterSingletonServiceGroupImpl.java
singleton-service/mdsal-singleton-dom-impl/src/main/java/org/opendaylight/mdsal/singleton/dom/impl/DOMClusterSingletonServiceProviderImpl.java [deleted file]
singleton-service/mdsal-singleton-dom-impl/src/main/java/org/opendaylight/mdsal/singleton/dom/impl/EOSClusterSingletonServiceProvider.java [moved from singleton-service/mdsal-singleton-dom-impl/src/main/java/org/opendaylight/mdsal/singleton/dom/impl/AbstractClusterSingletonServiceProviderImpl.java with 67% similarity]
singleton-service/mdsal-singleton-dom-impl/src/main/java/org/opendaylight/mdsal/singleton/dom/impl/OSGiClusterSingletonServiceProvider.java [deleted file]
singleton-service/mdsal-singleton-dom-impl/src/main/java/org/opendaylight/mdsal/singleton/dom/impl/ServiceInfo.java
singleton-service/mdsal-singleton-dom-impl/src/main/java/org/opendaylight/mdsal/singleton/dom/impl/di/DefaultClusterSingletonServiceProvider.java [deleted file]
singleton-service/mdsal-singleton-dom-impl/src/test/java/org/opendaylight/mdsal/singleton/dom/impl/AbstractEOSClusterSingletonServiceProviderTest.java [moved from singleton-service/mdsal-singleton-dom-impl/src/test/java/org/opendaylight/mdsal/singleton/dom/impl/AbstractDOMClusterServiceProviderTest.java with 94% similarity]
singleton-service/mdsal-singleton-dom-impl/src/test/java/org/opendaylight/mdsal/singleton/dom/impl/AsyncEOSClusterSingletonServiceProviderTest.java [moved from singleton-service/mdsal-singleton-dom-impl/src/test/java/org/opendaylight/mdsal/singleton/dom/impl/DOMClusterSingletonServiceProviderAsyncImplTest.java with 99% similarity]
singleton-service/mdsal-singleton-dom-impl/src/test/java/org/opendaylight/mdsal/singleton/dom/impl/ClusterSingletonServiceGroupImplTest.java
singleton-service/mdsal-singleton-dom-impl/src/test/java/org/opendaylight/mdsal/singleton/dom/impl/SyncEOSClusterSingletonServiceProviderTest.java [moved from singleton-service/mdsal-singleton-dom-impl/src/test/java/org/opendaylight/mdsal/singleton/dom/impl/DOMClusterSingletonServiceProviderImplTest.java with 97% similarity]

index 9898cc4338c4bde276851303a072577f2ec8aa6f..b3f072d8f5f4778565f2cce39c3d27bef48b2d86 100644 (file)
@@ -33,7 +33,7 @@ import org.opendaylight.mdsal.dom.api.DOMDataBroker;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
 import org.opendaylight.mdsal.eos.dom.simple.SimpleDOMEntityOwnershipService;
-import org.opendaylight.mdsal.singleton.dom.impl.di.DefaultClusterSingletonServiceProvider;
+import org.opendaylight.mdsal.singleton.dom.impl.EOSClusterSingletonServiceProvider;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.core.general.entity.rev150930.Entity;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.core.general.entity.rev150930.EntityBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.core.general.entity.rev150930.EntityKey;
@@ -59,17 +59,16 @@ public class IntegrationTest extends AbstractDataBrokerTest {
     private static final QName ENTITY_NAME_QNAME = QName.create(ENTITY_QNAME, "name");
 
     private AbstractBootstrapSupport support;
-    private DefaultClusterSingletonServiceProvider css;
+    private EOSClusterSingletonServiceProvider css;
 
     @Before
     public void before() {
         support = AbstractBootstrapSupport.create();
-        css = new DefaultClusterSingletonServiceProvider(new SimpleDOMEntityOwnershipService());
-        css.initializeProvider();
+        css = new EOSClusterSingletonServiceProvider(new SimpleDOMEntityOwnershipService());
     }
 
     @After
-    public void after() throws InterruptedException {
+    public void after() throws Exception {
         support.close();
         css.close();
     }
index 6778a845b7966eae7d8cb4377669bf3c31ed2987..a9aef73b39c335a16b3f208f7547910227ebf3f2 100644 (file)
@@ -18,7 +18,7 @@ package org.opendaylight.mdsal.singleton.common.api;
  * closed prior to relinquishing service group ownership. To achieve ownership of the service group,
  * a service group candidate must hold ownership of both these entities.
  */
-public interface ClusterSingletonServiceProvider extends AutoCloseable {
+public interface ClusterSingletonServiceProvider {
     /**
      * Method registers {@link ClusterSingletonService} to Provider.
      * Method returns {@link java.lang.RuntimeException} for unexpected state, so be careful with implementation.
index 63093b361ef80888abfeecd404a731411e9efa86..6243baf805c34e685e02121efccac725e0b5b952 100644 (file)
 
     <dependencies>
         <dependency>
-            <groupId>com.github.spotbugs</groupId>
-            <artifactId>spotbugs-annotations</artifactId>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.guicedee.services</groupId>
+            <artifactId>javax.inject</artifactId>
             <optional>true</optional>
         </dependency>
         <dependency>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
+            <groupId>jakarta.annotation</groupId>
+            <artifactId>jakarta.annotation-api</artifactId>
+            <scope>provided</scope>
+            <optional>true</optional>
         </dependency>
         <dependency>
             <groupId>org.checkerframework</groupId>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>concepts</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>yang-common</artifactId>
-        </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-data-api</artifactId>
             <groupId>org.opendaylight.mdsal</groupId>
             <artifactId>mdsal-singleton-common-api</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.kohsuke.metainf-services</groupId>
-            <artifactId>metainf-services</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.guicedee.services</groupId>
-            <artifactId>javax.inject</artifactId>
-            <optional>true</optional>
-        </dependency>
         <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.service.component.annotations</artifactId>
index fcb4c9fcc4c0b6555f3e15415335bb69b60c17ea..99b60ea6d33dc3b4e96a467ede3db3710780c8e3 100644 (file)
@@ -5,14 +5,8 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-import org.opendaylight.mdsal.eos.dom.api.DOMEntityOwnershipService;
-import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
-import org.opendaylight.mdsal.singleton.dom.impl.DOMClusterSingletonServiceProviderImpl;
-
 module org.opendaylight.mdsal.singleton.dom.impl {
-    exports org.opendaylight.mdsal.singleton.dom.impl.di;
-
-    provides ClusterSingletonServiceProvider with DOMClusterSingletonServiceProviderImpl;
+    exports org.opendaylight.mdsal.singleton.dom.impl;
 
     requires transitive org.opendaylight.mdsal.singleton.common.api;
     requires transitive org.opendaylight.mdsal.eos.dom.api;
@@ -20,12 +14,10 @@ module org.opendaylight.mdsal.singleton.dom.impl {
     requires org.opendaylight.yangtools.concepts;
     requires org.slf4j;
 
-    uses DOMEntityOwnershipService;
-
     // Annotations
     requires static transitive org.eclipse.jdt.annotation;
+    requires static transitive java.annotation;
     requires static javax.inject;
     requires static org.checkerframework.checker.qual;
-    requires static org.kohsuke.metainf_services;
     requires static org.osgi.service.component.annotations;
 }
index 5fda4d9c2c19cc139443958468da17f5a76ce4ee..bab4be06f6465ce78c71da6348a4892aa3aa0a0b 100644 (file)
@@ -579,7 +579,7 @@ final class ClusterSingletonServiceGroupImpl extends ClusterSingletonServiceGrou
                     continue;
                 }
 
-                services.put(reg, ServiceInfo.started());
+                services.put(reg, ServiceInfo.STARTED);
             }
         }
     }
diff --git a/singleton-service/mdsal-singleton-dom-impl/src/main/java/org/opendaylight/mdsal/singleton/dom/impl/DOMClusterSingletonServiceProviderImpl.java b/singleton-service/mdsal-singleton-dom-impl/src/main/java/org/opendaylight/mdsal/singleton/dom/impl/DOMClusterSingletonServiceProviderImpl.java
deleted file mode 100644 (file)
index cd266d6..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.mdsal.singleton.dom.impl;
-
-import java.util.ServiceLoader;
-import org.kohsuke.MetaInfServices;
-import org.opendaylight.mdsal.eos.dom.api.DOMEntity;
-import org.opendaylight.mdsal.eos.dom.api.DOMEntityOwnershipService;
-import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
-import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
-
-/**
- * Binding version of {@link AbstractClusterSingletonServiceProviderImpl}.
- */
-@MetaInfServices(value = ClusterSingletonServiceProvider.class)
-public class DOMClusterSingletonServiceProviderImpl extends AbstractClusterSingletonServiceProviderImpl {
-    public DOMClusterSingletonServiceProviderImpl() {
-        this(ServiceLoader.load(DOMEntityOwnershipService.class).findFirst().orElseThrow(
-            () -> new IllegalStateException("Could not find DOMEntityOwnershipService")));
-    }
-
-    protected DOMClusterSingletonServiceProviderImpl(final DOMEntityOwnershipService entityOwnershipService) {
-        super(entityOwnershipService);
-    }
-
-    @Override
-    protected Registration registerListener(final String type, final DOMEntityOwnershipService eos) {
-        return eos.registerListener(type, this);
-    }
-
-    @Override
-    protected String getServiceIdentifierFromEntity(final DOMEntity entity) {
-        final YangInstanceIdentifier yii = entity.getIdentifier();
-        final NodeIdentifierWithPredicates niiwp = (NodeIdentifierWithPredicates) yii.getLastPathArgument();
-        return niiwp.values().iterator().next().toString();
-    }
-}
@@ -14,7 +14,6 @@ import static java.util.Objects.requireNonNull;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Strings;
-import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
@@ -22,6 +21,10 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutionException;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import javax.inject.Singleton;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.eos.common.api.CandidateAlreadyRegisteredException;
 import org.opendaylight.mdsal.eos.common.api.EntityOwnershipStateChange;
@@ -32,17 +35,22 @@ import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
 import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Abstract class {@link AbstractClusterSingletonServiceProviderImpl} represents implementations of
- * {@link ClusterSingletonServiceProvider} and it implements {@link DOMEntityOwnershipListener} for providing
- * OwnershipChange for all registered {@link ClusterSingletonServiceGroup} entity candidate.
+ * Implementation of {@link ClusterSingletonServiceProvider} working on top a {@link DOMEntityOwnershipService}.
  */
-public abstract class AbstractClusterSingletonServiceProviderImpl
-        implements ClusterSingletonServiceProvider, DOMEntityOwnershipListener {
-    private static final Logger LOG = LoggerFactory.getLogger(AbstractClusterSingletonServiceProviderImpl.class);
+@Singleton
+@Component(service = ClusterSingletonServiceProvider.class)
+public final class EOSClusterSingletonServiceProvider
+        implements ClusterSingletonServiceProvider, DOMEntityOwnershipListener, AutoCloseable {
+    private static final Logger LOG = LoggerFactory.getLogger(EOSClusterSingletonServiceProvider.class);
 
     @VisibleForTesting
     static final @NonNull String SERVICE_ENTITY_TYPE = "org.opendaylight.mdsal.ServiceEntityType";
@@ -56,27 +64,45 @@ public abstract class AbstractClusterSingletonServiceProviderImpl
     private Registration serviceEntityListenerReg;
     private Registration asyncCloseEntityListenerReg;
 
-    /**
-     * Class constructor.
-     *
-     * @param entityOwnershipService relevant EOS
-     */
-    protected AbstractClusterSingletonServiceProviderImpl(
-            final @NonNull DOMEntityOwnershipService entityOwnershipService) {
+    @Inject
+    @Activate
+    public EOSClusterSingletonServiceProvider(@Reference final DOMEntityOwnershipService entityOwnershipService) {
         this.entityOwnershipService = requireNonNull(entityOwnershipService);
+        serviceEntityListenerReg = entityOwnershipService.registerListener(SERVICE_ENTITY_TYPE, this);
+        asyncCloseEntityListenerReg = entityOwnershipService.registerListener(CLOSE_SERVICE_ENTITY_TYPE, this);
+        LOG.info("Cluster Singleton Service started");
     }
 
-    /**
-     * This method must be called once on startup to initialize this provider.
-     */
-    public final void initializeProvider() {
-        LOG.debug("Initialization method for ClusterSingletonService Provider {}", this);
-        serviceEntityListenerReg = registerListener(SERVICE_ENTITY_TYPE, entityOwnershipService);
-        asyncCloseEntityListenerReg = registerListener(CLOSE_SERVICE_ENTITY_TYPE, entityOwnershipService);
+    @PreDestroy
+    @Deactivate
+    @Override
+    public synchronized void close() throws ExecutionException, InterruptedException {
+        if (serviceEntityListenerReg == null) {
+            // Idempotent
+            return;
+        }
+
+        LOG.info("Cluster Singleton Service stopping");
+        serviceEntityListenerReg.close();
+        serviceEntityListenerReg = null;
+
+        final var future = Futures.allAsList(serviceGroupMap.values().stream()
+            .map(ClusterSingletonServiceGroup::closeClusterSingletonGroup)
+            .toList());
+        try {
+            LOG.debug("Waiting for service groups to stop");
+            future.get();
+        } finally {
+            asyncCloseEntityListenerReg.close();
+            asyncCloseEntityListenerReg = null;
+            serviceGroupMap.clear();
+        }
+
+        LOG.info("Cluster Singleton Service stopped");
     }
 
     @Override
-    public final synchronized ClusterSingletonServiceRegistration registerClusterSingletonService(
+    public synchronized ClusterSingletonServiceRegistration registerClusterSingletonService(
             final ClusterSingletonService service) {
         LOG.debug("Call registrationService {} method for ClusterSingletonService Provider {}", service, this);
 
@@ -99,12 +125,12 @@ public abstract class AbstractClusterSingletonServiceProviderImpl
             serviceGroup = existing;
         }
 
-        final var reg =  new AbstractClusterSingletonServiceRegistration(service) {
+        final var reg = new AbstractClusterSingletonServiceRegistration(service) {
             @Override
             protected void removeRegistration() {
                 // We need to bounce the unregistration through a ordered lock in order not to deal with asynchronous
                 // shutdown of the group and user registering it again.
-                AbstractClusterSingletonServiceProviderImpl.this.removeRegistration(serviceIdentifier, this);
+                EOSClusterSingletonServiceProvider.this.removeRegistration(serviceIdentifier, this);
             }
         };
 
@@ -129,7 +155,7 @@ public abstract class AbstractClusterSingletonServiceProviderImpl
         }
     }
 
-    void removeRegistration(final String serviceIdentifier, final ClusterSingletonServiceRegistration reg) {
+    private void removeRegistration(final String serviceIdentifier, final ClusterSingletonServiceRegistration reg) {
         final PlaceholderGroup placeHolder;
         final ListenableFuture<?> future;
         synchronized (this) {
@@ -153,7 +179,7 @@ public abstract class AbstractClusterSingletonServiceProviderImpl
         future.addListener(() -> finishShutdown(placeHolder), MoreExecutors.directExecutor());
     }
 
-    synchronized void finishShutdown(final PlaceholderGroup placeHolder) {
+    private synchronized void finishShutdown(final PlaceholderGroup placeHolder) {
         final var identifier = placeHolder.getIdentifier();
         LOG.debug("Service group {} closed", identifier);
 
@@ -182,38 +208,11 @@ public abstract class AbstractClusterSingletonServiceProviderImpl
     }
 
     @Override
-    public final void close() {
-        LOG.debug("Close method for ClusterSingletonService Provider {}", this);
-
-        if (serviceEntityListenerReg != null) {
-            serviceEntityListenerReg.close();
-            serviceEntityListenerReg = null;
-        }
-
-        final var futures = serviceGroupMap.values().stream()
-            .map(ClusterSingletonServiceGroup::closeClusterSingletonGroup)
-            .toList();
-        final var future = Futures.allAsList(futures);
-        Futures.addCallback(future, new FutureCallback<>() {
-            @Override
-            public void onSuccess(final List<Object> result) {
-                cleanup();
-            }
-
-            @Override
-            public void onFailure(final Throwable throwable) {
-                LOG.warn("Unexpected problem by closing ClusterSingletonServiceProvider {}",
-                    AbstractClusterSingletonServiceProviderImpl.this, throwable);
-                cleanup();
-            }
-        }, MoreExecutors.directExecutor());
-    }
-
-    @Override
-    public final void ownershipChanged(final DOMEntity entity, final EntityOwnershipStateChange change,
+    public void ownershipChanged(final DOMEntity entity, final EntityOwnershipStateChange change,
             final boolean inJeopardy) {
         LOG.debug("Ownership change for ClusterSingletonService Provider on {} {} inJeopardy={}", entity, change,
             inJeopardy);
+
         final var serviceIdentifier = getServiceIdentifierFromEntity(entity);
         final var serviceHolder = serviceGroupMap.get(serviceIdentifier);
         if (serviceHolder != null) {
@@ -223,14 +222,12 @@ public abstract class AbstractClusterSingletonServiceProviderImpl
         }
     }
 
-    /**
-     * Method implementation registers the listener.
-     *
-     * @param entityType the type of the entity
-     * @param eos - EOS type
-     * @return a {@link Registration}
-     */
-    protected abstract Registration registerListener(String entityType, DOMEntityOwnershipService eos);
+    @VisibleForTesting
+    static String getServiceIdentifierFromEntity(final DOMEntity entity) {
+        final var yii = entity.getIdentifier();
+        final var niiwp = (NodeIdentifierWithPredicates) yii.getLastPathArgument();
+        return niiwp.values().iterator().next().toString();
+    }
 
     /**
      * Creates an extended {@link DOMEntity} instance.
@@ -240,27 +237,7 @@ public abstract class AbstractClusterSingletonServiceProviderImpl
      * @return instance of Entity extended GenericEntity type
      */
     @VisibleForTesting
-    static final DOMEntity createEntity(final String entityType, final String entityIdentifier) {
+    static DOMEntity createEntity(final String entityType, final String entityIdentifier) {
         return new DOMEntity(entityType, entityIdentifier);
     }
-
-    /**
-     * Method is responsible for parsing ServiceGroupIdentifier from E entity.
-     *
-     * @param entity instance of GenericEntity type
-     * @return ServiceGroupIdentifier parsed from entity key value.
-     */
-    protected abstract String getServiceIdentifierFromEntity(DOMEntity entity);
-
-    /**
-     * Method is called async. from close method in end of Provider lifecycle.
-     */
-    final void cleanup() {
-        LOG.debug("Final cleaning ClusterSingletonServiceProvider {}", this);
-        if (asyncCloseEntityListenerReg != null) {
-            asyncCloseEntityListenerReg.close();
-            asyncCloseEntityListenerReg = null;
-        }
-        serviceGroupMap.clear();
-    }
 }
diff --git a/singleton-service/mdsal-singleton-dom-impl/src/main/java/org/opendaylight/mdsal/singleton/dom/impl/OSGiClusterSingletonServiceProvider.java b/singleton-service/mdsal-singleton-dom-impl/src/main/java/org/opendaylight/mdsal/singleton/dom/impl/OSGiClusterSingletonServiceProvider.java
deleted file mode 100644 (file)
index e709709..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2020 PANTHEON.tech, s.r.o. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.mdsal.singleton.dom.impl;
-
-import com.google.common.annotations.Beta;
-import org.opendaylight.mdsal.eos.dom.api.DOMEntityOwnershipService;
-import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
-import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
-import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
-import org.osgi.service.component.annotations.Activate;
-import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.Deactivate;
-import org.osgi.service.component.annotations.Reference;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Beta
-@Component(immediate = true, property = "type=default")
-public final class OSGiClusterSingletonServiceProvider implements ClusterSingletonServiceProvider {
-    private static final Logger LOG = LoggerFactory.getLogger(OSGiClusterSingletonServiceProvider.class);
-
-    @Reference
-    DOMEntityOwnershipService entityOwnershipService = null;
-
-    private DOMClusterSingletonServiceProviderImpl delegate;
-
-    @Override
-    public ClusterSingletonServiceRegistration registerClusterSingletonService(final ClusterSingletonService service) {
-        return delegate.registerClusterSingletonService(service);
-    }
-
-    @Override
-    public void close() {
-        // Ignored on purpose
-    }
-
-    @Activate
-    void activate() {
-        LOG.info("Cluster Singleton Service starting");
-        delegate = new DOMClusterSingletonServiceProviderImpl(entityOwnershipService);
-        delegate.initializeProvider();
-        LOG.info("Cluster Singleton Service started");
-    }
-
-    @Deactivate
-    void deactivate() {
-        LOG.info("Cluster Singleton Service stopping");
-        delegate.close();
-        delegate = null;
-        LOG.info("Cluster Singleton Service stopped");
-    }
-}
index 1b6db564c3fe8ca3139067944ed53e4b2b158855..081e5646be680b09a08acbafa5faaf0b0757096a 100644 (file)
@@ -12,42 +12,35 @@ import static com.google.common.base.Verify.verifyNotNull;
 import static java.util.Objects.requireNonNull;
 
 import com.google.common.util.concurrent.ListenableFuture;
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.mdsal.singleton.dom.impl.ClusterSingletonServiceGroupImpl.ServiceState;
 
-@NonNullByDefault
-@SuppressFBWarnings(value = "NP_NULL_PARAM_DEREF_NONVIRTUAL", justification = "SpotBugs does not grok @Nullable field")
 final class ServiceInfo {
-    private static final ServiceInfo STARTED = new ServiceInfo(ServiceState.STARTED, null);
+    static final @NonNull ServiceInfo STARTED = new ServiceInfo(ServiceState.STARTED, null);
 
     private final @Nullable ListenableFuture<?> future;
-    private final ServiceState state;
+    private final @NonNull ServiceState state;
 
     private ServiceInfo(final ServiceState state, final @Nullable ListenableFuture<?> future) {
         this.state = requireNonNull(state);
         this.future = future;
     }
 
-    static ServiceInfo started() {
-        return STARTED;
-    }
-
-    ServiceState getState() {
+    @NonNull ServiceState getState() {
         return state;
     }
 
-    ListenableFuture<?> getFuture() {
+    @NonNull ListenableFuture<?> getFuture() {
         return verifyNotNull(future);
     }
 
-    ServiceInfo toState(final ServiceState newState) {
+    @NonNull ServiceInfo toState(final @NonNull ServiceState newState) {
         verify(state != newState, "Attempted to re-transition into %s", state);
         return new ServiceInfo(newState, null);
     }
 
-    ServiceInfo toState(final ServiceState newState, final ListenableFuture<?> newFuture) {
+    @NonNull ServiceInfo toState(final @NonNull ServiceState newState, final @NonNull ListenableFuture<?> newFuture) {
         verify(state != newState, "Attempted to re-transition into %s", state);
         return new ServiceInfo(newState, requireNonNull(newFuture));
     }
diff --git a/singleton-service/mdsal-singleton-dom-impl/src/main/java/org/opendaylight/mdsal/singleton/dom/impl/di/DefaultClusterSingletonServiceProvider.java b/singleton-service/mdsal-singleton-dom-impl/src/main/java/org/opendaylight/mdsal/singleton/dom/impl/di/DefaultClusterSingletonServiceProvider.java
deleted file mode 100644 (file)
index ca02793..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (c) 2020 PANTHEON.tech, s.r.o. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.mdsal.singleton.dom.impl.di;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-import org.opendaylight.mdsal.eos.dom.api.DOMEntityOwnershipService;
-import org.opendaylight.mdsal.singleton.dom.impl.DOMClusterSingletonServiceProviderImpl;
-
-@Singleton
-public final class DefaultClusterSingletonServiceProvider extends DOMClusterSingletonServiceProviderImpl {
-    @Inject
-    public DefaultClusterSingletonServiceProvider(final DOMEntityOwnershipService entityOwnershipService) {
-        super(entityOwnershipService);
-    }
-}
@@ -21,8 +21,8 @@ import static org.opendaylight.mdsal.eos.common.api.EntityOwnershipStateChange.L
 import static org.opendaylight.mdsal.eos.common.api.EntityOwnershipStateChange.LOCAL_OWNERSHIP_LOST_NEW_OWNER;
 import static org.opendaylight.mdsal.eos.common.api.EntityOwnershipStateChange.REMOTE_OWNERSHIP_CHANGED;
 import static org.opendaylight.mdsal.eos.common.api.EntityOwnershipStateChange.REMOTE_OWNERSHIP_LOST_NO_OWNER;
-import static org.opendaylight.mdsal.singleton.dom.impl.AbstractClusterSingletonServiceProviderImpl.CLOSE_SERVICE_ENTITY_TYPE;
-import static org.opendaylight.mdsal.singleton.dom.impl.AbstractClusterSingletonServiceProviderImpl.SERVICE_ENTITY_TYPE;
+import static org.opendaylight.mdsal.singleton.dom.impl.EOSClusterSingletonServiceProvider.CLOSE_SERVICE_ENTITY_TYPE;
+import static org.opendaylight.mdsal.singleton.dom.impl.EOSClusterSingletonServiceProvider.SERVICE_ENTITY_TYPE;
 
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
@@ -39,9 +39,9 @@ import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
 import org.opendaylight.yangtools.concepts.Registration;
 
 /**
- * Abstract {@link DOMClusterSingletonServiceProviderImpl} testing substrate.
+ * Abstract {@link EOSClusterSingletonServiceProvider} testing substrate.
  */
-public abstract class AbstractDOMClusterServiceProviderTest {
+abstract class AbstractEOSClusterSingletonServiceProviderTest {
     /**
      * Base states for AbstractClusterProjectProvider.
      */
@@ -101,7 +101,7 @@ public abstract class AbstractDOMClusterServiceProviderTest {
     @Mock
     public Registration mockEosDoubleEntityListReg;
 
-    public DOMClusterSingletonServiceProviderImpl clusterSingletonServiceProvider;
+    public EOSClusterSingletonServiceProvider clusterSingletonServiceProvider;
     public TestClusterSingletonService clusterSingletonService;
     public TestClusterSingletonService clusterSingletonService2;
 
@@ -112,14 +112,13 @@ public abstract class AbstractDOMClusterServiceProviderTest {
         doNothing().when(mockEntityCandReg).close();
         doNothing().when(mockDoubleEntityCandReg).close();
         doReturn(mockEosEntityListReg).when(mockEos).registerListener(eq(SERVICE_ENTITY_TYPE),
-                any(DOMClusterSingletonServiceProviderImpl.class));
+                any(EOSClusterSingletonServiceProvider.class));
         doReturn(mockEosDoubleEntityListReg).when(mockEos).registerListener(eq(CLOSE_SERVICE_ENTITY_TYPE),
-                any(DOMClusterSingletonServiceProviderImpl.class));
+                any(EOSClusterSingletonServiceProvider.class));
         doReturn(mockEntityCandReg).when(mockEos).registerCandidate(ENTITY);
         doReturn(mockDoubleEntityCandReg).when(mockEos).registerCandidate(DOUBLE_ENTITY);
 
-        clusterSingletonServiceProvider = new DOMClusterSingletonServiceProviderImpl(mockEos);
-        clusterSingletonServiceProvider.initializeProvider();
+        clusterSingletonServiceProvider = new EOSClusterSingletonServiceProvider(mockEos);
         verify(mockEos).registerListener(SERVICE_ENTITY_TYPE, clusterSingletonServiceProvider);
         verify(mockEos).registerListener(CLOSE_SERVICE_ENTITY_TYPE, clusterSingletonServiceProvider);
 
@@ -138,11 +137,11 @@ public abstract class AbstractDOMClusterServiceProviderTest {
      */
     @Test
     public void initializationClusterSingletonServiceProviderNullInputTest() {
-        assertThrows(NullPointerException.class, () -> new DOMClusterSingletonServiceProviderImpl(null));
+        assertThrows(NullPointerException.class, () -> new EOSClusterSingletonServiceProvider(null));
     }
 
     /**
-     * Test GoldPath for close {@link DOMClusterSingletonServiceProviderImpl}.
+     * Test GoldPath for close {@link EOSClusterSingletonServiceProvider}.
      *
      * @throws Exception if the condition does not meet
      */
@@ -160,10 +159,10 @@ public abstract class AbstractDOMClusterServiceProviderTest {
      */
     @Test
     public void makeEntityClusterSingletonServiceProviderTest() {
-        final var testEntity = AbstractClusterSingletonServiceProviderImpl.createEntity(SERVICE_ENTITY_TYPE,
+        final var testEntity = EOSClusterSingletonServiceProvider.createEntity(SERVICE_ENTITY_TYPE,
             SERVICE_NAME);
         assertEquals(ENTITY, testEntity);
-        final var testDbEn = AbstractClusterSingletonServiceProviderImpl.createEntity(CLOSE_SERVICE_ENTITY_TYPE,
+        final var testDbEn = EOSClusterSingletonServiceProvider.createEntity(CLOSE_SERVICE_ENTITY_TYPE,
                 SERVICE_NAME);
         assertEquals(DOUBLE_ENTITY, testDbEn);
     }
@@ -173,8 +172,8 @@ public abstract class AbstractDOMClusterServiceProviderTest {
      */
     @Test
     public void getIdentifierClusterSingletonServiceProviderTest() {
-        assertEquals(SERVICE_NAME, clusterSingletonServiceProvider.getServiceIdentifierFromEntity(ENTITY));
-        assertEquals(SERVICE_NAME, clusterSingletonServiceProvider.getServiceIdentifierFromEntity(DOUBLE_ENTITY));
+        assertEquals(SERVICE_NAME, EOSClusterSingletonServiceProvider.getServiceIdentifierFromEntity(ENTITY));
+        assertEquals(SERVICE_NAME, EOSClusterSingletonServiceProvider.getServiceIdentifierFromEntity(DOUBLE_ENTITY));
     }
 
     /**
@@ -32,7 +32,7 @@ import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegist
  * Testing {@link DOMClusterSingletonServiceProviderImpl} implementation
  */
 @RunWith(MockitoJUnitRunner.StrictStubs.class)
-public final class DOMClusterSingletonServiceProviderAsyncImplTest extends AbstractDOMClusterServiceProviderTest {
+public final class AsyncEOSClusterSingletonServiceProviderTest extends AbstractEOSClusterSingletonServiceProviderTest {
     /*
      * Test implementation of {@link ClusterSingletonService}
      */
index 26276164d40814cc8869d3c7acdab216b2717a6d..31c0e2bdd7204fbf85e7fdb7196dd0e8468b9ebd 100644 (file)
@@ -21,8 +21,8 @@ import static org.opendaylight.mdsal.eos.common.api.EntityOwnershipStateChange.L
 import static org.opendaylight.mdsal.eos.common.api.EntityOwnershipStateChange.LOCAL_OWNERSHIP_LOST_NO_OWNER;
 import static org.opendaylight.mdsal.eos.common.api.EntityOwnershipStateChange.REMOTE_OWNERSHIP_CHANGED;
 import static org.opendaylight.mdsal.eos.common.api.EntityOwnershipStateChange.REMOTE_OWNERSHIP_LOST_NO_OWNER;
-import static org.opendaylight.mdsal.singleton.dom.impl.AbstractClusterSingletonServiceProviderImpl.CLOSE_SERVICE_ENTITY_TYPE;
-import static org.opendaylight.mdsal.singleton.dom.impl.AbstractClusterSingletonServiceProviderImpl.SERVICE_ENTITY_TYPE;
+import static org.opendaylight.mdsal.singleton.dom.impl.EOSClusterSingletonServiceProvider.CLOSE_SERVICE_ENTITY_TYPE;
+import static org.opendaylight.mdsal.singleton.dom.impl.EOSClusterSingletonServiceProvider.SERVICE_ENTITY_TYPE;
 
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
@@ -19,7 +19,6 @@ import static org.opendaylight.mdsal.eos.common.api.EntityOwnershipStateChange.L
 import static org.opendaylight.mdsal.eos.common.api.EntityOwnershipStateChange.REMOTE_OWNERSHIP_CHANGED;
 import static org.opendaylight.mdsal.eos.common.api.EntityOwnershipStateChange.REMOTE_OWNERSHIP_LOST_NO_OWNER;
 
-import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.junit.MockitoJUnitRunner;
@@ -30,16 +29,7 @@ import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegist
  * Synchronous test suite.
  */
 @RunWith(MockitoJUnitRunner.StrictStubs.class)
-public class DOMClusterSingletonServiceProviderImplTest extends AbstractDOMClusterServiceProviderTest {
-    /**
-     * Initialization functionality for every Tests in this suite.
-     */
-    @Override
-    @Before
-    public void setup() throws Exception {
-        super.setup();
-    }
-
+public class SyncEOSClusterSingletonServiceProviderTest extends AbstractEOSClusterSingletonServiceProviderTest {
     /**
      * Test GoldPath for takeLeadership with ownership result MASTER {@link ClusterSingletonService}.
      *