* 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 static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Verify.verify;
import static com.google.common.base.Verify.verifyNotNull;
+import static java.util.Objects.requireNonNull;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
-import com.google.common.base.Verify;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nonnull;
+import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.eos.common.api.CandidateAlreadyRegisteredException;
+import org.opendaylight.mdsal.eos.common.api.EntityOwnershipStateChange;
import org.opendaylight.mdsal.eos.common.api.GenericEntity;
-import org.opendaylight.mdsal.eos.common.api.GenericEntityOwnershipChange;
import org.opendaylight.mdsal.eos.common.api.GenericEntityOwnershipListener;
-import org.opendaylight.mdsal.eos.common.api.GenericEntityOwnershipListenerRegistration;
import org.opendaylight.mdsal.eos.common.api.GenericEntityOwnershipService;
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.Path;
+import org.opendaylight.yangtools.concepts.HierarchicalIdentifier;
+import org.opendaylight.yangtools.concepts.Registration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
*
* @param <P> the instance identifier path type
* @param <E> the GenericEntity type
- * @param <C> the GenericEntityOwnershipChange type
* @param <G> the GenericEntityOwnershipListener type
* @param <S> the GenericEntityOwnershipService type
- * @param <R> the GenericEntityOwnershipListenerRegistration type
*/
-public abstract class AbstractClusterSingletonServiceProviderImpl<P extends Path<P>, E extends GenericEntity<P>,
- C extends GenericEntityOwnershipChange<P, E>,
- G extends GenericEntityOwnershipListener<P, C>,
- S extends GenericEntityOwnershipService<P, E, G>,
- R extends GenericEntityOwnershipListenerRegistration<P, G>>
- implements ClusterSingletonServiceProvider, GenericEntityOwnershipListener<P, C> {
-
+public abstract class AbstractClusterSingletonServiceProviderImpl<P extends HierarchicalIdentifier<P>,
+ E extends GenericEntity<P>, G extends GenericEntityOwnershipListener<E>,
+ S extends GenericEntityOwnershipService<E, G>>
+ implements ClusterSingletonServiceProvider, GenericEntityOwnershipListener<E> {
private static final Logger LOG = LoggerFactory.getLogger(AbstractClusterSingletonServiceProviderImpl.class);
@VisibleForTesting
- static final String SERVICE_ENTITY_TYPE = "org.opendaylight.mdsal.ServiceEntityType";
+ static final @NonNull String SERVICE_ENTITY_TYPE = "org.opendaylight.mdsal.ServiceEntityType";
@VisibleForTesting
- static final String CLOSE_SERVICE_ENTITY_TYPE = "org.opendaylight.mdsal.AsyncServiceCloseEntityType";
+ static final @NonNull String CLOSE_SERVICE_ENTITY_TYPE = "org.opendaylight.mdsal.AsyncServiceCloseEntityType";
private final S entityOwnershipService;
- private final Map<String, ClusterSingletonServiceGroup<P, E, C>> serviceGroupMap = new ConcurrentHashMap<>();
+ private final Map<String, ClusterSingletonServiceGroup<P, E>> serviceGroupMap = new ConcurrentHashMap<>();
/* EOS Entity Listeners Registration */
- private R serviceEntityListenerReg;
- private R asyncCloseEntityListenerReg;
+ private Registration serviceEntityListenerReg;
+ private Registration asyncCloseEntityListenerReg;
/**
* Class constructor.
*
* @param entityOwnershipService relevant EOS
*/
- protected AbstractClusterSingletonServiceProviderImpl(@Nonnull final S entityOwnershipService) {
- this.entityOwnershipService = Preconditions.checkNotNull(entityOwnershipService);
+ protected AbstractClusterSingletonServiceProviderImpl(final @NonNull S entityOwnershipService) {
+ this.entityOwnershipService = requireNonNull(entityOwnershipService);
}
/**
*/
public final void initializeProvider() {
LOG.debug("Initialization method for ClusterSingletonService Provider {}", this);
- this.serviceEntityListenerReg = registerListener(SERVICE_ENTITY_TYPE, entityOwnershipService);
- this.asyncCloseEntityListenerReg = registerListener(CLOSE_SERVICE_ENTITY_TYPE, entityOwnershipService);
+ serviceEntityListenerReg = registerListener(SERVICE_ENTITY_TYPE, entityOwnershipService);
+ asyncCloseEntityListenerReg = registerListener(CLOSE_SERVICE_ENTITY_TYPE, entityOwnershipService);
}
@Override
public final synchronized ClusterSingletonServiceRegistration registerClusterSingletonService(
- @CheckForNull final ClusterSingletonService service) {
+ final ClusterSingletonService service) {
LOG.debug("Call registrationService {} method for ClusterSingletonService Provider {}", service, this);
- final String serviceIdentifier = service.getIdentifier().getValue();
- Preconditions.checkArgument(!Strings.isNullOrEmpty(serviceIdentifier),
- "ClusterSingletonService identifier may not be null nor empty");
+ final String serviceIdentifier = service.getIdentifier().getName();
+ checkArgument(!Strings.isNullOrEmpty(serviceIdentifier),
+ "ClusterSingletonService identifier may not be null nor empty");
- final ClusterSingletonServiceGroup<P, E, C> serviceGroup;
- ClusterSingletonServiceGroup<P, E, C> existing = serviceGroupMap.get(serviceIdentifier);
+ final ClusterSingletonServiceGroup<P, E> serviceGroup;
+ final var existing = serviceGroupMap.get(serviceIdentifier);
if (existing == null) {
serviceGroup = createGroup(serviceIdentifier, new ArrayList<>(1));
serviceGroupMap.put(serviceIdentifier, serviceGroup);
serviceGroup = existing;
}
- final ClusterSingletonServiceRegistration 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
return reg;
}
- private ClusterSingletonServiceGroup<P, E, C> createGroup(final String serviceIdentifier,
+ private ClusterSingletonServiceGroup<P, E> createGroup(final String serviceIdentifier,
final List<ClusterSingletonServiceRegistration> services) {
return new ClusterSingletonServiceGroupImpl<>(serviceIdentifier, entityOwnershipService,
- createEntity(SERVICE_ENTITY_TYPE, serviceIdentifier),
- createEntity(CLOSE_SERVICE_ENTITY_TYPE, serviceIdentifier), services);
+ createEntity(SERVICE_ENTITY_TYPE, serviceIdentifier),
+ createEntity(CLOSE_SERVICE_ENTITY_TYPE, serviceIdentifier), services);
}
- private void initializeOrRemoveGroup(final ClusterSingletonServiceGroup<P, E, C> group)
+ private void initializeOrRemoveGroup(final ClusterSingletonServiceGroup<P, E> group)
throws CandidateAlreadyRegisteredException {
try {
group.initialize();
}
void removeRegistration(final String serviceIdentifier, final ClusterSingletonServiceRegistration reg) {
-
- final PlaceholderGroup<P, E, C> placeHolder;
+ final PlaceholderGroup<P, E> placeHolder;
final ListenableFuture<?> future;
synchronized (this) {
- final ClusterSingletonServiceGroup<P, E, C> lookup = verifyNotNull(serviceGroupMap.get(serviceIdentifier));
+ final var lookup = verifyNotNull(serviceGroupMap.get(serviceIdentifier));
future = lookup.unregisterService(reg);
if (future == null) {
return;
LOG.debug("Closing service group {}", serviceIdentifier);
placeHolder = new PlaceholderGroup<>(lookup, future);
- final String identifier = reg.getInstance().getIdentifier().getValue();
+ final String identifier = reg.getInstance().getIdentifier().getName();
verify(serviceGroupMap.replace(identifier, lookup, placeHolder));
LOG.debug("Replaced group {} with {}", serviceIdentifier, placeHolder);
future.addListener(() -> finishShutdown(placeHolder), MoreExecutors.directExecutor());
}
- synchronized void finishShutdown(final PlaceholderGroup<P, E, C> placeHolder) {
+ synchronized void finishShutdown(final PlaceholderGroup<P, E> placeHolder) {
final String identifier = placeHolder.getIdentifier();
LOG.debug("Service group {} closed", identifier);
- final List<ClusterSingletonServiceRegistration> services = placeHolder.getServices();
+ final var services = placeHolder.getServices();
if (services.isEmpty()) {
// No services, we are all done
if (serviceGroupMap.remove(identifier, placeHolder)) {
}
// Placeholder is being retired, we are reusing its services as the seed for the group.
- final ClusterSingletonServiceGroup<P, E, C> group = createGroup(identifier, services);
- Verify.verify(serviceGroupMap.replace(identifier, placeHolder, group));
+ final var group = createGroup(identifier, services);
+ verify(serviceGroupMap.replace(identifier, placeHolder, group));
placeHolder.setSuccessor(group);
LOG.debug("Service group upgraded from {} to {}", placeHolder, group);
serviceEntityListenerReg = null;
}
- final List<ListenableFuture<?>> listGroupCloseListFuture = new ArrayList<>();
-
- for (final ClusterSingletonServiceGroup<P, E, C> serviceGroup : serviceGroupMap.values()) {
- listGroupCloseListFuture.add(serviceGroup.closeClusterSingletonGroup());
- }
-
- final ListenableFuture<List<Object>> finalCloseFuture = Futures.allAsList(listGroupCloseListFuture);
- Futures.addCallback(finalCloseFuture, new FutureCallback<List<?>>() {
-
+ 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<?> result) {
+ public void onSuccess(final List<Object> result) {
cleanup();
}
}
@Override
- public final void ownershipChanged(final C ownershipChange) {
- LOG.debug("Ownership change for ClusterSingletonService Provider {}", ownershipChange);
- final String serviceIdentifier = getServiceIdentifierFromEntity(ownershipChange.getEntity());
- final ClusterSingletonServiceGroup<P, E, C> serviceHolder = serviceGroupMap.get(serviceIdentifier);
+ public final void ownershipChanged(final E 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) {
- serviceHolder.ownershipChanged(ownershipChange);
+ serviceHolder.ownershipChanged(entity, change, inJeopardy);
} else {
LOG.debug("ClusterSingletonServiceGroup was not found for serviceIdentifier {}", serviceIdentifier);
}
}
/**
- * Method implementation registers a defined {@link GenericEntityOwnershipListenerRegistration} type
- * EntityOwnershipListenerRegistration.
+ * Method implementation registers the listener.
*
* @param entityType the type of the entity
* @param entityOwnershipServiceInst - EOS type
- * @return instance of EntityOwnershipListenerRegistration
+ * @return a {@link Registration}
*/
- protected abstract R registerListener(String entityType, S entityOwnershipServiceInst);
+ protected abstract Registration registerListener(String entityType, S entityOwnershipServiceInst);
/**
* Creates an extended {@link GenericEntity} instance.