* 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.openflowplugin.impl;
+import static java.util.Objects.requireNonNull;
-import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
-import java.lang.management.ManagementFactory;
-import java.util.Collection;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
+import io.netty.util.HashedWheelTimer;
+import io.netty.util.Timer;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
-import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
-import javax.annotation.Nonnull;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.MBeanRegistrationException;
-import javax.management.MBeanServer;
-import javax.management.MalformedObjectNameException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.ObjectName;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
-import org.opendaylight.controller.md.sal.binding.api.NotificationService;
-import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
-import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import org.opendaylight.infrautils.diagstatus.ServiceState;
+import org.opendaylight.infrautils.ready.SystemReadyListener;
+import org.opendaylight.infrautils.ready.SystemReadyMonitor;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.binding.api.NotificationPublishService;
+import org.opendaylight.mdsal.binding.api.RpcProviderService;
+import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipService;
+import org.opendaylight.mdsal.singleton.api.ClusterSingletonServiceProvider;
import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider;
-import org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginProvider;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupInfoHistories;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupInfoHistory;
+import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionManager;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
+import org.opendaylight.openflowplugin.api.openflow.mastership.MastershipChangeServiceManager;
+import org.opendaylight.openflowplugin.api.openflow.role.RoleManager;
import org.opendaylight.openflowplugin.api.openflow.rpc.RpcManager;
import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsManager;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency;
-import org.opendaylight.openflowplugin.extension.api.ExtensionConverterProviderKeeper;
import org.opendaylight.openflowplugin.extension.api.ExtensionConverterRegistrator;
import org.opendaylight.openflowplugin.extension.api.OpenFlowPluginExtensionRegistratorProvider;
import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterManager;
+import org.opendaylight.openflowplugin.impl.configuration.OpenFlowProviderConfigImpl;
import org.opendaylight.openflowplugin.impl.connection.ConnectionManagerImpl;
import org.opendaylight.openflowplugin.impl.device.DeviceManagerImpl;
import org.opendaylight.openflowplugin.impl.device.initialization.DeviceInitializerProvider;
import org.opendaylight.openflowplugin.impl.device.initialization.DeviceInitializerProviderFactory;
+import org.opendaylight.openflowplugin.impl.lifecycle.ContextChainHolderImpl;
import org.opendaylight.openflowplugin.impl.protocol.deserialization.DeserializerInjector;
import org.opendaylight.openflowplugin.impl.protocol.serialization.SerializerInjector;
+import org.opendaylight.openflowplugin.impl.role.RoleManagerImpl;
import org.opendaylight.openflowplugin.impl.rpc.RpcManagerImpl;
import org.opendaylight.openflowplugin.impl.statistics.StatisticsManagerImpl;
-import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.MessageIntelligenceAgencyImpl;
-import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.MessageIntelligenceAgencyMXBean;
+import org.opendaylight.openflowplugin.impl.util.ThreadPoolLoggingExecutor;
import org.opendaylight.openflowplugin.impl.util.TranslatorLibraryUtil;
-import org.opendaylight.openflowplugin.openflow.md.core.ThreadPoolLoggingExecutor;
import org.opendaylight.openflowplugin.openflow.md.core.extension.ExtensionConverterManagerImpl;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfig;
+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.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import io.netty.util.HashedWheelTimer;
-
-public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenFlowPluginExtensionRegistratorProvider {
+@Singleton
+@Component(immediate = true, service = {
+ OpenFlowPluginExtensionRegistratorProvider.class,
+ FlowGroupInfoHistories.class
+})
+public final class OpenFlowPluginProviderImpl
+ implements OpenFlowPluginExtensionRegistratorProvider, FlowGroupInfoHistories, SystemReadyListener,
+ AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(OpenFlowPluginProviderImpl.class);
- private static final MessageIntelligenceAgency messageIntelligenceAgency = new MessageIntelligenceAgencyImpl();
- private static final int TICKS_PER_WHEEL = 500;
- // 0.5 sec.
- private static final long TICK_DURATION = 10;
- private static final Integer DEFAULT_BARRIER_COUNT = 25600;
- private static final Long DEFAULT_ECHO_TIMEOUT = 2000L;
- private static final Long DEFAULT_BARRIER_TIMEOUT = 500L;
- private final HashedWheelTimer hashedWheelTimer = new HashedWheelTimer(TICK_DURATION, TimeUnit.MILLISECONDS, TICKS_PER_WHEEL);
+ private static final int TICKS_PER_WHEEL = 500; // 0.5 sec.
+ private static final long TICK_DURATION = 10;
+ private static final String POOL_NAME = "ofppool";
- private final int rpcRequestsQuota;
- private final long globalNotificationQuota;
+ // TODO: Split this out into a separate component, which requires proper timer cancellation from all users. But is
+ // that worth the complications?
+ private final HashedWheelTimer hashedWheelTimer =
+ new HashedWheelTimer(TICK_DURATION, TimeUnit.MILLISECONDS, TICKS_PER_WHEEL);
+ private final ExtensionConverterManager extensionConverterManager;
+ private final DeviceInitializerProvider deviceInitializerProvider;
private final ConvertorManager convertorManager;
- private long barrierInterval;
- private int barrierCountLimit;
- private long echoReplyTimeout;
- private DeviceManager deviceManager;
- private RpcManager rpcManager;
- private RpcProviderRegistry rpcProviderRegistry;
- private StatisticsManager statisticsManager;
+ private final OpenflowProviderConfig config;
+ private final DeviceManager deviceManager;
+ private final RpcManager rpcManager;
+ private final StatisticsManager statisticsManager;
+ private final RoleManager roleManager;
+ private final ExecutorService executorService;
+ private final ContextChainHolderImpl contextChainHolder;
+ private final DiagStatusProvider diagStatusProvider;
+
+ private final List<SwitchConnectionProvider> connectionProviders = new ArrayList<>();
+
+ private List<SwitchConnectionProvider> startedProviders;
private ConnectionManager connectionManager;
- private NotificationService notificationProviderService;
- private NotificationPublishService notificationPublishService;
- private ExtensionConverterManager extensionConverterManager;
- private DataBroker dataBroker;
- private Collection<SwitchConnectionProvider> switchConnectionProviders;
- private boolean switchFeaturesMandatory = false;
- private boolean isStatisticsPollingOn = true;
- private boolean isStatisticsRpcEnabled;
- private boolean isFlowRemovedNotificationOn = true;
- private boolean skipTableFeatures = true;
- private long basicTimerDelay;
- private long maximumTimerDelay;
- private boolean useSingleLayerSerialization = false;
- private final DeviceInitializerProvider deviceInitializerProvider;
+ private int startingProviders;
+
+ @Inject
+ @Activate
+ public OpenFlowPluginProviderImpl(@Reference final ConfigurationService configurationService,
+ @Reference final DataBroker dataBroker, @Reference final RpcProviderService rpcProviderRegistry,
+ @Reference final NotificationPublishService notificationPublishService,
+ @Reference final ClusterSingletonServiceProvider singletonServiceProvider,
+ @Reference final EntityOwnershipService entityOwnershipService,
+ @Reference final MastershipChangeServiceManager mastershipChangeServiceManager,
+ @Reference final MessageIntelligenceAgency messageIntelligenceAgency,
+ @Reference final DiagStatusProvider diagStatusProvider,
+ @Reference final SystemReadyMonitor systemReadyMonitor) {
+ config = new OpenFlowProviderConfigImpl(configurationService);
+ final var ppdb = new PingPongDataBroker(dataBroker);
+ this.diagStatusProvider = requireNonNull(diagStatusProvider);
- private final ThreadPoolExecutor threadPool;
- private ClusterSingletonServiceProvider singletonServicesProvider;
+ convertorManager = ConvertorManagerFactory.createDefaultManager();
+ extensionConverterManager = new ExtensionConverterManagerImpl();
+ deviceInitializerProvider = DeviceInitializerProviderFactory.createDefaultProvider();
- public OpenFlowPluginProviderImpl(final long rpcRequestsQuota,
- final long globalNotificationQuota,
- final int threadPoolMinThreads,
- final int threadPoolMaxThreads,
- final long threadPoolTimeout) {
- Preconditions.checkArgument(rpcRequestsQuota > 0 && rpcRequestsQuota <= Integer.MAX_VALUE, "rpcRequestQuota has to be in range <1,%s>", Integer.MAX_VALUE);
- this.rpcRequestsQuota = (int) rpcRequestsQuota;
- this.globalNotificationQuota = Preconditions.checkNotNull(globalNotificationQuota);
+ // TODO: copied from OpenFlowPluginProvider (Helium) misusesing the old way of distributing extension converters
+ // TODO: rewrite later!
+ OFSessionUtil.getSessionManager().setExtensionConverterProvider(extensionConverterManager);
// Creates a thread pool that creates new threads as needed, but will reuse previously
// constructed threads when they are available.
// Threads that have not been used for x seconds are terminated and removed from the cache.
- threadPool = new ThreadPoolLoggingExecutor(
- Preconditions.checkNotNull(threadPoolMinThreads),
- Preconditions.checkNotNull(threadPoolMaxThreads),
- Preconditions.checkNotNull(threadPoolTimeout), TimeUnit.SECONDS,
- new SynchronousQueue<>(), "ofppool");
+ executorService = new ThreadPoolLoggingExecutor(
+ config.getThreadPoolMinThreads().toJava(),
+ config.getThreadPoolMaxThreads().getValue().toJava(),
+ config.getThreadPoolTimeout().toJava(),
+ TimeUnit.SECONDS, new SynchronousQueue<>(), POOL_NAME);
+
+ final var devMgr = new DeviceManagerImpl(
+ config,
+ ppdb,
+ messageIntelligenceAgency,
+ notificationPublishService,
+ hashedWheelTimer,
+ convertorManager,
+ deviceInitializerProvider,
+ executorService);
+ deviceManager = devMgr;
- convertorManager = ConvertorManagerFactory.createDefaultManager();
- deviceInitializerProvider = DeviceInitializerProviderFactory.createDefaultProvider();
+ TranslatorLibraryUtil.injectBasicTranslatorLibrary(deviceManager, convertorManager);
+ devMgr.setExtensionConverterProvider(extensionConverterManager);
+
+ rpcManager = new RpcManagerImpl(
+ config,
+ rpcProviderRegistry,
+ extensionConverterManager,
+ convertorManager,
+ notificationPublishService);
+
+ statisticsManager = new StatisticsManagerImpl(
+ config,
+ rpcProviderRegistry,
+ convertorManager,
+ executorService);
+
+ roleManager = new RoleManagerImpl(hashedWheelTimer, config, executorService);
+
+ contextChainHolder = new ContextChainHolderImpl(
+ executorService,
+ singletonServiceProvider,
+ entityOwnershipService,
+ mastershipChangeServiceManager,
+ config);
+
+ contextChainHolder.addManager(deviceManager);
+ contextChainHolder.addManager(statisticsManager);
+ contextChainHolder.addManager(rpcManager);
+ contextChainHolder.addManager(roleManager);
+
+ connectionManager = new ConnectionManagerImpl(config, executorService, ppdb, notificationPublishService);
+ connectionManager.setDeviceConnectedHandler(contextChainHolder);
+ connectionManager.setDeviceDisconnectedHandler(contextChainHolder);
+
+ deviceManager.setContextChainHolder(contextChainHolder);
+ deviceManager.initialize();
+ systemReadyMonitor.registerListener(this);
+ LOG.info("OpenFlowPluginProvider started, waiting for onSystemBootReady()");
}
- @Override
- public boolean isStatisticsPollingOn() {
- return isStatisticsPollingOn;
+ @Reference(cardinality = ReferenceCardinality.AT_LEAST_ONE,
+ policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY)
+ public synchronized void bindConnectionProvider(final SwitchConnectionProvider switchConnectionProvider) {
+ connectionProviders.add(switchConnectionProvider);
+ LOG.info("Added connection provider {}", switchConnectionProvider);
+
+ if (startedProviders != null) {
+ LOG.info("Starting latecomer connection provider {}", switchConnectionProvider);
+ startingProviders += 1;
+ startProvider(switchConnectionProvider);
+ }
}
- @Override
- public void setStatisticsPollingOn(final boolean isStatisticsPollingOn) {
- this.isStatisticsPollingOn = isStatisticsPollingOn;
+ public synchronized void unbindConnectionProvider(final SwitchConnectionProvider switchConnectionProvider) {
+ connectionProviders.remove(switchConnectionProvider);
+ if (startedProviders != null && startedProviders.remove(switchConnectionProvider)) {
+ switchConnectionProvider.shutdown();
+ }
+ LOG.info("Removed connection provider {}", switchConnectionProvider);
}
- private void startSwitchConnections() {
- Futures.addCallback(Futures.allAsList(switchConnectionProviders.stream().map(switchConnectionProvider -> {
- // Inject OpenflowPlugin custom serializers and deserializers into OpenflowJava
- if (useSingleLayerSerialization) {
- SerializerInjector.injectSerializers(switchConnectionProvider);
- DeserializerInjector.injectDeserializers(switchConnectionProvider);
- }
+ private ListenableFuture<Void> startProvider(final SwitchConnectionProvider provider) {
+ // Inject OpenFlowPlugin custom serializers and deserializers into OpenFlowJava
+ if (config.getUseSingleLayerSerialization()) {
+ SerializerInjector.injectSerializers(provider, provider.getConfiguration().isGroupAddModEnabled());
+ DeserializerInjector.injectDeserializers(provider);
+ } else {
+ DeserializerInjector.revertDeserializers(provider);
+ }
- // Set handler of incoming connections and start switch connection provider
- switchConnectionProvider.setSwitchConnectionHandler(connectionManager);
- return switchConnectionProvider.startup();
- }).collect(Collectors.toSet())), new FutureCallback<List<Boolean>>() {
+ // Set handler of incoming connections and start switch connection provider
+ final var future = provider.startup(connectionManager);
+ startedProviders.add(provider);
+ Futures.addCallback(future, new FutureCallback<>() {
@Override
- public void onSuccess(final List<Boolean> result) {
- LOG.info("All switchConnectionProviders are up and running ({}).", result.size());
+ public void onSuccess(final Void result) {
+ LOG.info("Connection provider {} started", provider);
+ connectionStarted();
}
@Override
- public void onFailure(@Nonnull final Throwable t) {
- LOG.warn("Some switchConnectionProviders failed to start.", t);
+ public void onFailure(final Throwable cause) {
+ LOG.warn("Connection provider {} failed to start", provider, cause);
+ connectionFailed(cause);
}
- });
+ }, MoreExecutors.directExecutor());
+ return future;
}
@Override
- public boolean isSwitchFeaturesMandatory() {
- return switchFeaturesMandatory;
- }
+ public synchronized void onSystemBootReady() {
+ LOG.info("onSystemBootReady() received, starting the switch connections");
- @Override
- public void setBarrierCountLimit(final int barrierCountLimit) {
- this.barrierCountLimit = barrierCountLimit;
+ final var size = connectionProviders.size();
+ startedProviders = new ArrayList<>(size);
+ startingProviders = size;
+ connectionProviders.forEach(this::startProvider);
}
- @Override
- public void setBarrierInterval(final long barrierTimeoutLimit) {
- this.barrierInterval = barrierTimeoutLimit;
- }
-
- @Override
- public void setEchoReplyTimeout(final long echoReplyTimeout) {
- this.echoReplyTimeout = echoReplyTimeout;
+ private synchronized void connectionFailed(final Throwable cause) {
+ // Decrement below zero, so we do not arrive to zero
+ startingProviders = -1;
+ diagStatusProvider.reportStatus(ServiceState.ERROR, cause);
}
- @Override
- public void setFlowRemovedNotification(boolean isFlowRemovedNotificationOn) {
- this.isFlowRemovedNotificationOn = isFlowRemovedNotificationOn;
- }
-
- @Override
- public void setClusteringSingletonServicesProvider(ClusterSingletonServiceProvider singletonServicesProvider) {
- this.singletonServicesProvider = singletonServicesProvider;
- }
-
- @Override
- public void setSkipTableFeatures(final boolean skipTableFeatures){
- this.skipTableFeatures = skipTableFeatures;
+ private synchronized void connectionStarted() {
+ if (--startingProviders == 0 && startedProviders.equals(connectionProviders)) {
+ LOG.info("All switchConnectionProviders are up and running ({}).", startedProviders.size());
+ diagStatusProvider.reportStatus(ServiceState.OPERATIONAL);
+ }
}
- @Override
- public void setBasicTimerDelay(long basicTimerDelay) {
- this.basicTimerDelay = basicTimerDelay;
- }
+ private ListenableFuture<List<Void>> shutdownSwitchConnections() {
+ final var future = Futures.allAsList(startedProviders.stream()
+ .map(switchConnectionProvider -> {
+ // Revert deserializers to their original state
+ if (config.getUseSingleLayerSerialization()) {
+ DeserializerInjector.revertDeserializers(switchConnectionProvider);
+ }
- @Override
- public void setMaximumTimerDelay(long maximumTimerDelay) {
- this.maximumTimerDelay = maximumTimerDelay;
- }
+ // Shutdown switch connection provider
+ return switchConnectionProvider.shutdown();
+ }).collect(Collectors.toList()));
+ startedProviders.clear();
- @Override
- public void setSwitchFeaturesMandatory(final boolean switchFeaturesMandatory) {
- this.switchFeaturesMandatory = switchFeaturesMandatory;
- }
+ Futures.addCallback(future, new FutureCallback<>() {
+ @Override
+ public void onSuccess(final List<Void> result) {
+ LOG.info("All switchConnectionProviders were successfully shut down ({}).", result.size());
+ }
- public static MessageIntelligenceAgency getMessageIntelligenceAgency() {
- return OpenFlowPluginProviderImpl.messageIntelligenceAgency;
- }
+ @Override
+ public void onFailure(final Throwable throwable) {
+ LOG.warn("Some switchConnectionProviders failed to shutdown.", throwable);
+ }
+ }, MoreExecutors.directExecutor());
- @Override
- public void setSwitchConnectionProviders(final Collection<SwitchConnectionProvider> switchConnectionProviders) {
- this.switchConnectionProviders = switchConnectionProviders;
+ return future;
}
@Override
- public void setDataBroker(final DataBroker dataBroker) {
- this.dataBroker = dataBroker;
+ public ExtensionConverterRegistrator getExtensionConverterRegistrator() {
+ return extensionConverterManager;
}
@Override
- public void setRpcProviderRegistry(final RpcProviderRegistry rpcProviderRegistry) {
- this.rpcProviderRegistry = rpcProviderRegistry;
+ public Map<NodeId, FlowGroupInfoHistory> getAllFlowGroupHistories() {
+ return deviceManager.getAllFlowGroupHistories();
}
@Override
- public void initialize() {
- Preconditions.checkNotNull(dataBroker, "missing data broker");
- Preconditions.checkNotNull(rpcProviderRegistry, "missing RPC provider registry");
- Preconditions.checkNotNull(notificationProviderService, "missing notification provider service");
- Preconditions.checkNotNull(singletonServicesProvider, "missing singleton services provider");
-
- extensionConverterManager = new ExtensionConverterManagerImpl();
- // TODO: copied from OpenFlowPluginProvider (Helium) misusesing the old way of distributing extension converters
- // TODO: rewrite later!
- OFSessionUtil.getSessionManager().setExtensionConverterProvider(extensionConverterManager);
-
- connectionManager = new ConnectionManagerImpl(echoReplyTimeout, threadPool);
-
- registerMXBean(messageIntelligenceAgency);
-
- deviceManager = new DeviceManagerImpl(dataBroker,
- globalNotificationQuota,
- switchFeaturesMandatory,
- barrierInterval,
- barrierCountLimit,
- getMessageIntelligenceAgency(),
- isFlowRemovedNotificationOn,
- singletonServicesProvider,
- notificationPublishService,
- hashedWheelTimer,
- convertorManager,
- skipTableFeatures,
- useSingleLayerSerialization,
- deviceInitializerProvider);
-
- ((ExtensionConverterProviderKeeper) deviceManager).setExtensionConverterProvider(extensionConverterManager);
-
- rpcManager = new RpcManagerImpl(rpcProviderRegistry, rpcRequestsQuota, extensionConverterManager, convertorManager, notificationPublishService);
- statisticsManager = new StatisticsManagerImpl(rpcProviderRegistry, isStatisticsPollingOn, hashedWheelTimer,
- convertorManager,basicTimerDelay,maximumTimerDelay);
-
- /* Initialization Phase ordering - OFP Device Context suite */
- // CM -> DM -> SM -> RPC -> Role -> DM
- connectionManager.setDeviceConnectedHandler(deviceManager);
- deviceManager.setDeviceInitializationPhaseHandler(statisticsManager);
- statisticsManager.setDeviceInitializationPhaseHandler(rpcManager);
- rpcManager.setDeviceInitializationPhaseHandler(deviceManager);
-
- /* Termination Phase ordering - OFP Device Context suite */
- deviceManager.setDeviceTerminationPhaseHandler(rpcManager);
- rpcManager.setDeviceTerminationPhaseHandler(statisticsManager);
- statisticsManager.setDeviceTerminationPhaseHandler(deviceManager);
-
- rpcManager.setStatisticsRpcEnabled(isStatisticsRpcEnabled);
-
- TranslatorLibraryUtil.injectBasicTranslatorLibrary(deviceManager, convertorManager);
- deviceManager.initialize();
-
- startSwitchConnections();
+ public FlowGroupInfoHistory getFlowGroupHistory(final NodeId nodeId) {
+ return deviceManager.getFlowGroupHistory(nodeId);
}
@Override
- public void update(Map<String,Object> props) {
- LOG.debug("Update managed properties = {}", props.toString());
-
- final boolean containsUseSingleLayer = props.containsKey("use-single-layer-serialization");
-
- if (containsUseSingleLayer) {
- final Boolean useSingleLayer = Boolean.valueOf(props.get("use-single-layer-serialization").toString());
-
- if (useSingleLayer != useSingleLayerSerialization) {
- useSingleLayerSerialization = useSingleLayer;
-
- if (useSingleLayer) {
- switchConnectionProviders.forEach(switchConnectionProvider -> {
- SerializerInjector.injectSerializers(switchConnectionProvider);
- DeserializerInjector.injectDeserializers(switchConnectionProvider);
- });
- } else {
- switchConnectionProviders.forEach(DeserializerInjector::revertDeserializers);
- }
- }
+ @PreDestroy
+ @Deactivate
+ @SuppressWarnings("checkstyle:IllegalCatch")
+ public synchronized void close() {
+ LOG.info("OpenFlowPluginProvider stopping");
+ try {
+ shutdownSwitchConnections().get(10, TimeUnit.SECONDS);
+ } catch (InterruptedException | ExecutionException | TimeoutException e) {
+ LOG.warn("Failed to shut down switch connections in time {}s", 10, e);
}
- if(deviceManager != null) {
- if (containsUseSingleLayer) {
- deviceManager.setUseSingleLayerSerialization(Boolean.valueOf(props.get("use-single-layer-serialization").toString()));
- }
-
- if (props.containsKey("notification-flow-removed-off")) {
- deviceManager.setFlowRemovedNotificationOn(Boolean.valueOf(props.get("enable-flow-removed-notification").toString()));
- }
- if (props.containsKey("skip-table-features")) {
- deviceManager.setSkipTableFeatures(Boolean.valueOf(props.get("skip-table-features").toString()));
- }
- if (props.containsKey("barrier-count-limit")) {
- try {
- deviceManager.setBarrierCountLimit(Integer.valueOf(props.get("barrier-count-limit").toString()));
- } catch (NumberFormatException ex) {
- deviceManager.setBarrierCountLimit(DEFAULT_BARRIER_COUNT);
- }
- }
- if (props.containsKey("barrier-interval-timeout-limit")){
- try {
- deviceManager.setBarrierInterval(Long.valueOf(props.get("barrier-interval-timeout-limit").toString()));
- } catch (NumberFormatException ex) {
- deviceManager.setBarrierInterval(DEFAULT_BARRIER_TIMEOUT);
- }
+ gracefulShutdown(contextChainHolder);
+ gracefulShutdown(connectionManager);
+ gracefulShutdown(deviceManager);
+ gracefulShutdown(rpcManager);
+ gracefulShutdown(statisticsManager);
+ gracefulShutdown(roleManager);
+ gracefulShutdown(executorService);
+ gracefulShutdown(hashedWheelTimer);
+ diagStatusProvider.reportStatus(ServiceState.UNREGISTERED);
+ try {
+ if (connectionManager != null) {
+ connectionManager.close();
+ connectionManager = null;
}
+ } catch (Exception e) {
+ LOG.error("Failed to close ConnectionManager", e);
}
+ LOG.info("OpenFlowPluginProvider stopped");
+ }
- if(rpcManager != null && props.containsKey("is-statistics-rpc-enabled")){
- rpcManager.setStatisticsRpcEnabled(Boolean.valueOf((props.get("is-statistics-rpc-enabled").toString())));
- }
-
- if (connectionManager != null && props.containsKey("echo-reply-timeout") ){
+ @SuppressWarnings("checkstyle:IllegalCatch")
+ private static void gracefulShutdown(final AutoCloseable closeable) {
+ if (closeable != null) {
try {
- connectionManager.setEchoReplyTimeout(Long.valueOf(props.get("echo-reply-timeout").toString()));
- }catch (NumberFormatException ex){
- connectionManager.setEchoReplyTimeout(DEFAULT_ECHO_TIMEOUT);
+ closeable.close();
+ } catch (Exception e) {
+ LOG.warn("Failed to shutdown {} gracefully.", closeable);
}
}
-
- if(statisticsManager != null && props.containsKey("is-statistics-polling-on")){
- statisticsManager.setIsStatisticsPollingOn(Boolean.valueOf(props.get("is-statistics-polling-on").toString()));
- }
-
- if(statisticsManager != null && props.containsKey("basic-timer-delay")){
- statisticsManager.setBasicTimerDelay(Long.valueOf(props.get("basic-timer-delay").toString()));
- }
-
- if(statisticsManager != null && props.containsKey("maximum-timer-delay")){
- statisticsManager.setMaximumTimerDelay(Long.valueOf(props.get("maximum-timer-delay").toString()));
- }
}
- private static void registerMXBean(final MessageIntelligenceAgency messageIntelligenceAgency) {
- final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
- try {
- final String pathToMxBean = String.format("%s:type=%s",
- MessageIntelligenceAgencyMXBean.class.getPackage().getName(),
- MessageIntelligenceAgencyMXBean.class.getSimpleName());
- final ObjectName name = new ObjectName(pathToMxBean);
- mbs.registerMBean(messageIntelligenceAgency, name);
- } catch (MalformedObjectNameException
- | NotCompliantMBeanException
- | MBeanRegistrationException
- | InstanceAlreadyExistsException e) {
- LOG.warn("Error registering MBean {}", e);
+ private static void gracefulShutdown(final Timer timer) {
+ if (timer != null) {
+ try {
+ timer.stop();
+ } catch (IllegalStateException e) {
+ LOG.warn("Failed to shutdown {} gracefully.", timer);
+ }
}
}
- @Override
- public void setNotificationProviderService(final NotificationService notificationProviderService) {
- this.notificationProviderService = notificationProviderService;
- }
-
- @Override
- public void setNotificationPublishService(final NotificationPublishService notificationPublishProviderService) {
- this.notificationPublishService = notificationPublishProviderService;
- }
-
- @Override
- public ExtensionConverterRegistrator getExtensionConverterRegistrator() {
- return extensionConverterManager;
- }
-
- @Override
- public void setIsStatisticsRpcEnabled(final boolean isStatisticsRpcEnabled) {
- this.isStatisticsRpcEnabled = isStatisticsRpcEnabled;
- }
-
- @Override
- public void close() throws Exception {
- //TODO: consider wrapping each manager into try-catch
- deviceManager.close();
- rpcManager.close();
- statisticsManager.close();
-
- // Manually shutdown all remaining running threads in pool
- threadPool.shutdown();
- }
-
- @Override
- public void setIsUseSingleLayerSerialization(Boolean useSingleLayerSerialization) {
- this.useSingleLayerSerialization = useSingleLayerSerialization;
+ private static void gracefulShutdown(final ExecutorService executorService) {
+ if (executorService != null) {
+ try {
+ executorService.shutdownNow();
+ } catch (SecurityException e) {
+ LOG.warn("Failed to shutdown {} gracefully.", executorService);
+ }
+ }
}
}