import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipChange;
import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipListenerRegistration;
import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class ContextChainHolderImpl implements ContextChainHolder, MasterChecker {
+public final class ContextChainHolderImpl implements ContextChainHolder, MasterChecker {
private static final Logger LOG = LoggerFactory.getLogger(ContextChainHolderImpl.class);
private static final Logger OF_EVENT_LOG = LoggerFactory.getLogger("OfEventLog");
private static final String ASYNC_SERVICE_ENTITY_TYPE = "org.opendaylight.mdsal.AsyncServiceCloseEntityType";
private static final String SERVICE_ENTITY_TYPE = "org.opendaylight.mdsal.ServiceEntityType";
private static final String SEPARATOR = ":";
- private final Map<DeviceInfo, ContextChain> contextChainMap = new ConcurrentHashMap<>();
- private final Map<DeviceInfo, ? super ConnectionContext> connectingDevices = new ConcurrentHashMap<>();
+ private final ConcurrentMap<DeviceInfo, ContextChain> contextChainMap = new ConcurrentHashMap<>();
+ private final ConcurrentMap<DeviceInfo, ? super ConnectionContext> connectingDevices = new ConcurrentHashMap<>();
private final EntityOwnershipListenerRegistration eosListenerRegistration;
private final ClusterSingletonServiceProvider singletonServiceProvider;
- private final ExecutorService executorService;
+ private final Executor executor;
private final OwnershipChangeListener ownershipChangeListener;
private final ThreadFactory threadFactory = new ThreadFactoryBuilder().setDaemon(true)
.setNameFormat("node-cleaner-%d").setUncaughtExceptionHandler((thread, throwable) -> {
private StatisticsManager statisticsManager;
private RoleManager roleManager;
- public ContextChainHolderImpl(final ExecutorService executorService,
+ public ContextChainHolderImpl(final Executor executor,
final ClusterSingletonServiceProvider singletonServiceProvider,
final EntityOwnershipService entityOwnershipService,
final OwnershipChangeListener ownershipChangeListener,
final OpenflowProviderConfig config) {
this.singletonServiceProvider = singletonServiceProvider;
- this.executorService = executorService;
+ this.executor = executor;
this.ownershipChangeListener = ownershipChangeListener;
this.ownershipChangeListener.setMasterChecker(this);
this.entityOwnershipService = entityOwnershipService;
this.config = config;
- this.eosListenerRegistration = Objects
+ eosListenerRegistration = Objects
.requireNonNull(entityOwnershipService.registerListener(ASYNC_SERVICE_ENTITY_TYPE, this));
}
roleContext.registerMastershipWatcher(this);
LOG.debug("Role" + CONTEXT_CREATED_FOR_CONNECTION, deviceInfo);
- final ContextChain contextChain = new ContextChainImpl(this, connectionContext, executorService);
+ final ContextChain contextChain = new ContextChainImpl(this, connectionContext, executor);
contextChain.registerDeviceRemovedHandler(deviceManager);
contextChain.registerDeviceRemovedHandler(rpcManager);
contextChain.registerDeviceRemovedHandler(statisticsManager);
}
@Override
- public void onNotAbleToStartMastership(@NonNull final DeviceInfo deviceInfo, @NonNull final String reason,
- final boolean mandatory) {
+ public void onNotAbleToStartMastership(final DeviceInfo deviceInfo, final String reason, final boolean mandatory) {
LOG.error("Not able to set MASTER role on device {}, reason: {}", deviceInfo, reason);
if (!mandatory) {
return;
}
-
- Optional.ofNullable(contextChainMap.get(deviceInfo)).ifPresent(contextChain -> {
+ if (contextChainMap.containsKey(deviceInfo)) {
LOG.warn("This mastering is mandatory, destroying context chain and closing connection for device {}.",
deviceInfo);
destroyContextChain(deviceInfo);
- });
+ }
}
@Override
public void onMasterRoleAcquired(final DeviceInfo deviceInfo, final ContextChainMastershipState mastershipState) {
- Optional.ofNullable(contextChainMap.get(deviceInfo)).ifPresent(contextChain -> {
+ final ContextChain contextChain = contextChainMap.get(deviceInfo);
+ if (contextChain != null) {
if (!ContextChainMastershipState.INITIAL_SUBMIT.equals(mastershipState)) {
if (contextChain.isMastered(mastershipState, true)) {
Futures.addCallback(ownershipChangeListener.becomeMasterBeforeSubmittedDS(deviceInfo),
OF_EVENT_LOG.debug("Master Elected, Node: {}", deviceInfo.getDatapathId());
deviceManager.sendNodeAddedNotification(deviceInfo.getNodeInstanceIdentifier());
}
- });
+ }
}
@Override
public void onSlaveRoleAcquired(final DeviceInfo deviceInfo) {
ownershipChangeListener.becomeSlaveOrDisconnect(deviceInfo);
LOG.info("Role SLAVE was granted to device {}", deviceInfo);
- Optional.ofNullable(contextChainMap.get(deviceInfo)).ifPresent(ContextChain::makeContextChainStateSlave);
+ final ContextChain contextChain = contextChainMap.get(deviceInfo);
+ if (contextChain != null) {
+ contextChain.makeContextChainStateSlave();
+ }
}
@Override
public void onSlaveRoleNotAcquired(final DeviceInfo deviceInfo, final String reason) {
LOG.error("Not able to set SLAVE role on device {}, reason: {}", deviceInfo, reason);
- Optional.ofNullable(contextChainMap.get(deviceInfo)).ifPresent(contextChain -> destroyContextChain(deviceInfo));
+ if (contextChainMap.containsKey(deviceInfo)) {
+ destroyContextChain(deviceInfo);
+ }
}
@Override
public void onDeviceDisconnected(final ConnectionContext connectionContext) {
final DeviceInfo deviceInfo = connectionContext.getDeviceInfo();
-
- Optional.ofNullable(connectionContext.getDeviceInfo()).map(contextChainMap::get).ifPresent(contextChain -> {
- if (contextChain.auxiliaryConnectionDropped(connectionContext)) {
- LOG.info("Auxiliary connection from device {} disconnected.", deviceInfo);
- } else {
- LOG.info("Device {} disconnected.", deviceInfo);
- destroyContextChain(deviceInfo);
+ if (deviceInfo != null) {
+ final ContextChain contextChain = contextChainMap.get(deviceInfo);
+ if (contextChain != null) {
+ if (contextChain.auxiliaryConnectionDropped(connectionContext)) {
+ LOG.info("Auxiliary connection from device {} disconnected.", deviceInfo);
+ } else {
+ LOG.info("Device {} disconnected.", deviceInfo);
+ destroyContextChain(deviceInfo);
+ }
}
- });
+ }
}
@VisibleForTesting
final String dpnId = getDpnIdFromNodeName(entityName);
nodeCleanerExecutor.schedule(() -> {
try {
- Optional<EntityOwnershipState> ownershipState = getCurrentOwnershipStatus(entityName);
- if (!ownershipState.isPresent()
- || Objects.equals(ownershipState.get(), EntityOwnershipState.NO_OWNER)) {
+ EntityOwnershipState ownershipState = getCurrentOwnershipStatus(entityName);
+ if (ownershipState == null || EntityOwnershipState.NO_OWNER.equals(ownershipState)) {
LOG.debug("Entity {} has no owner", entityName);
final KeyedInstanceIdentifier<Node, NodeKey> nodeInstanceIdentifier =
DeviceStateUtil.createNodeInstanceIdentifier(new NodeId(entityName));
LOG.warn("Seems like device is still owned by other controller instance. Skip deleting {} "
+ "node from operational datastore.", entityName);
}
- } catch (TimeoutException | ExecutionException | NullPointerException | InterruptedException e) {
+ } catch (TimeoutException | ExecutionException | InterruptedException e) {
LOG.warn("Not able to remove device {} from operational DS. ", entityName, e);
}
}, config.getDeviceDatastoreRemovalDelay().getValue().toJava(), TimeUnit.MILLISECONDS);
private void destroyContextChain(final DeviceInfo deviceInfo) {
OF_EVENT_LOG.debug("Destroying context chain for device {}", deviceInfo.getDatapathId());
ownershipChangeListener.becomeSlaveOrDisconnect(deviceInfo);
- Optional.ofNullable(contextChainMap.get(deviceInfo)).ifPresent(contextChain -> {
+ final ContextChain contextChain = contextChainMap.get(deviceInfo);
+ if (contextChain != null) {
deviceManager.sendNodeRemovedNotification(deviceInfo.getNodeInstanceIdentifier());
contextChain.close();
connectingDevices.remove(deviceInfo);
- });
+ }
}
@Override
return nodeName.substring(nodeName.lastIndexOf(SEPARATOR) + 1);
}
- private Optional<EntityOwnershipState> getCurrentOwnershipStatus(final String nodeId) {
+ private @Nullable EntityOwnershipState getCurrentOwnershipStatus(final String nodeId) {
org.opendaylight.mdsal.eos.binding.api.Entity entity = createNodeEntity(nodeId);
Optional<EntityOwnershipState> ownershipStatus
= entityOwnershipService.getOwnershipState(entity);
if (ownershipStatus.isPresent()) {
LOG.debug("Current ownership status for node {} is {}", nodeId, ownershipStatus.get());
- return Optional.of(ownershipStatus.get());
- } else {
- LOG.trace("Ownership status is not available for node {}", nodeId);
+ return ownershipStatus.get();
}
- return Optional.empty();
+
+ LOG.trace("Ownership status is not available for node {}", nodeId);
+ return null;
}
private static org.opendaylight.mdsal.eos.binding.api.Entity createNodeEntity(final String nodeId) {