X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=openflowplugin-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fopenflowplugin%2Fimpl%2FOpenFlowPluginProviderImpl.java;h=f1dd7155e367be2e8a034209948cd9a1634db8e0;hb=06455079c58e3f27fd30b865331463c0b2668392;hp=541ba88b529c7a59f905258edf5dac16b84b5f94;hpb=039e2f7cb8d5522b12fbef658fe17e3950dcabf9;p=openflowplugin.git diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/OpenFlowPluginProviderImpl.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/OpenFlowPluginProviderImpl.java index 541ba88b52..f1dd7155e3 100644 --- a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/OpenFlowPluginProviderImpl.java +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/OpenFlowPluginProviderImpl.java @@ -8,22 +8,26 @@ package org.opendaylight.openflowplugin.impl; - -import com.google.common.base.Preconditions; 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.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; import io.netty.util.HashedWheelTimer; +import io.netty.util.Timer; import java.lang.management.ManagementFactory; -import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.Map; +import java.util.Objects; +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.InstanceNotFoundException; import javax.management.MBeanRegistrationException; import javax.management.MBeanServer; import javax.management.MalformedObjectNameException; @@ -31,13 +35,20 @@ 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.infrautils.diagstatus.ServiceState; +import org.opendaylight.infrautils.ready.SystemReadyListener; +import org.opendaylight.infrautils.ready.SystemReadyMonitor; +import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipService; import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider; import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider; +import org.opendaylight.openflowplugin.api.diagstatus.OpenflowPluginDiagStatusProvider; import org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginProvider; +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; @@ -45,277 +56,288 @@ import org.opendaylight.openflowplugin.extension.api.ExtensionConverterProviderK 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.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenFlowPluginExtensionRegistratorProvider { +public class OpenFlowPluginProviderImpl implements + OpenFlowPluginProvider, + OpenFlowPluginExtensionRegistratorProvider, + SystemReadyListener { 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 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 static final String POOL_NAME = "ofppool"; - private final HashedWheelTimer hashedWheelTimer = new HashedWheelTimer(TICK_DURATION, TimeUnit.MILLISECONDS, TICKS_PER_WHEEL); + private static final MessageIntelligenceAgency MESSAGE_INTELLIGENCE_AGENCY = new MessageIntelligenceAgencyImpl(); + private static final String MESSAGE_INTELLIGENCE_AGENCY_MX_BEAN_NAME = String + .format("%s:type=%s", + MessageIntelligenceAgencyMXBean.class.getPackage().getName(), + MessageIntelligenceAgencyMXBean.class.getSimpleName()); - private final int rpcRequestsQuota; - private final long globalNotificationQuota; + private final HashedWheelTimer hashedWheelTimer = + new HashedWheelTimer(TICK_DURATION, TimeUnit.MILLISECONDS, TICKS_PER_WHEEL); + private final NotificationPublishService notificationPublishService; + private final ExtensionConverterManager extensionConverterManager; + private final DataBroker dataBroker; + private final Collection switchConnectionProviders; + private final DeviceInitializerProvider deviceInitializerProvider; private final ConvertorManager convertorManager; - private long barrierInterval; - private int barrierCountLimit; - private long echoReplyTimeout; + private final RpcProviderRegistry rpcProviderRegistry; + private final ClusterSingletonServiceProvider singletonServicesProvider; + private final OpenflowProviderConfig config; + private final EntityOwnershipService entityOwnershipService; + private final MastershipChangeServiceManager mastershipChangeServiceManager; private DeviceManager deviceManager; private RpcManager rpcManager; - private RpcProviderRegistry rpcProviderRegistry; private StatisticsManager statisticsManager; + private RoleManager roleManager; private ConnectionManager connectionManager; - private NotificationService notificationProviderService; - private NotificationPublishService notificationPublishService; - private ExtensionConverterManager extensionConverterManager; - private DataBroker dataBroker; - private Collection switchConnectionProviders; - private boolean switchFeaturesMandatory = false; - private boolean isStatisticsPollingOn = true; - private boolean isStatisticsRpcEnabled; - private boolean isNotificationFlowRemovedOff = false; - private boolean skipTableFeatures = true; - - private final ThreadPoolExecutor threadPool; - private ClusterSingletonServiceProvider singletonServicesProvider; - - 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); + private ListeningExecutorService executorService; + private ContextChainHolderImpl contextChainHolder; + private final OpenflowPluginDiagStatusProvider openflowPluginStatusMonitor; - // 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"); - convertorManager = ConvertorManagerFactory.createDefaultManager(); + public static MessageIntelligenceAgency getMessageIntelligenceAgency() { + return MESSAGE_INTELLIGENCE_AGENCY; } - @Override - public boolean isStatisticsPollingOn() { - return isStatisticsPollingOn; + OpenFlowPluginProviderImpl(final ConfigurationService configurationService, + final List switchConnectionProviders, + final DataBroker dataBroker, + final RpcProviderRegistry rpcProviderRegistry, + final NotificationPublishService notificationPublishService, + final ClusterSingletonServiceProvider singletonServiceProvider, + final EntityOwnershipService entityOwnershipService, + final MastershipChangeServiceManager mastershipChangeServiceManager, + final OpenflowPluginDiagStatusProvider openflowPluginStatusMonitor, + final SystemReadyMonitor systemReadyMonitor) { + this.switchConnectionProviders = switchConnectionProviders; + this.dataBroker = dataBroker; + this.rpcProviderRegistry = rpcProviderRegistry; + this.notificationPublishService = notificationPublishService; + this.singletonServicesProvider = singletonServiceProvider; + this.entityOwnershipService = entityOwnershipService; + convertorManager = ConvertorManagerFactory.createDefaultManager(); + extensionConverterManager = new ExtensionConverterManagerImpl(); + deviceInitializerProvider = DeviceInitializerProviderFactory.createDefaultProvider(); + config = new OpenFlowProviderConfigImpl(configurationService); + this.mastershipChangeServiceManager = mastershipChangeServiceManager; + this.openflowPluginStatusMonitor = openflowPluginStatusMonitor; + systemReadyMonitor.registerListener(this); + LOG.debug("registered onSystemBootReady() listener for deferred startSwitchConnections()"); } @Override - public void setIsStatisticsPollingOn(final boolean isStatisticsPollingOn) { - this.isStatisticsPollingOn = isStatisticsPollingOn; + public void onSystemBootReady() { + LOG.debug("onSystemBootReady() received, starting the switch connections"); + startSwitchConnections(); } private void startSwitchConnections() { - final List> starterChain = new ArrayList<>(switchConnectionProviders.size()); - for (final SwitchConnectionProvider switchConnectionPrv : switchConnectionProviders) { - switchConnectionPrv.setSwitchConnectionHandler(connectionManager); - final ListenableFuture isOnlineFuture = switchConnectionPrv.startup(); - starterChain.add(isOnlineFuture); - } + Futures.addCallback(Futures.allAsList(switchConnectionProviders.stream().map(switchConnectionProvider -> { + // Inject OpenFlowPlugin custom serializers and deserializers into OpenFlowJava + if (config.isUseSingleLayerSerialization()) { + SerializerInjector.injectSerializers(switchConnectionProvider, + switchConnectionProvider.getConfiguration().isGroupAddModEnabled()); + DeserializerInjector.injectDeserializers(switchConnectionProvider); + } else { + DeserializerInjector.revertDeserializers(switchConnectionProvider); + } - final ListenableFuture> srvStarted = Futures.allAsList(starterChain); - Futures.addCallback(srvStarted, new FutureCallback>() { + // Set handler of incoming connections and start switch connection provider + switchConnectionProvider.setSwitchConnectionHandler(connectionManager); + return switchConnectionProvider.startup(); + }).collect(Collectors.toSet())), new FutureCallback>() { @Override - public void onSuccess(final List result) { - LOG.info("All switchConnectionProviders are up and running ({}).", - result.size()); + public void onSuccess(@Nonnull final List result) { + LOG.info("All switchConnectionProviders are up and running ({}).", result.size()); + openflowPluginStatusMonitor.reportStatus(ServiceState.OPERATIONAL, "switch connections started"); } @Override - public void onFailure(@Nonnull final Throwable t) { - LOG.warn("Some switchConnectionProviders failed to start.", t); + public void onFailure(@Nonnull final Throwable throwable) { + LOG.warn("Some switchConnectionProviders failed to start.", throwable); + openflowPluginStatusMonitor.reportStatus(ServiceState.ERROR, "some switch connections failed to start"); } - }); - } - - @Override - public boolean isSwitchFeaturesMandatory() { - return switchFeaturesMandatory; - } - - @Override - public void setBarrierCountLimit(final int barrierCountLimit) { - this.barrierCountLimit = barrierCountLimit; + }, MoreExecutors.directExecutor()); } - @Override - public void setBarrierInterval(final long barrierTimeoutLimit) { - this.barrierInterval = barrierTimeoutLimit; - } + private ListenableFuture> shutdownSwitchConnections() { + final ListenableFuture> listListenableFuture = + Futures.allAsList(switchConnectionProviders.stream().map(switchConnectionProvider -> { + // Revert deserializers to their original state + if (config.isUseSingleLayerSerialization()) { + DeserializerInjector.revertDeserializers(switchConnectionProvider); + } - @Override - public void setEchoReplyTimeout(final long echoReplyTimeout) { - this.echoReplyTimeout = echoReplyTimeout; - } + // Shutdown switch connection provider + return switchConnectionProvider.shutdown(); + }).collect(Collectors.toSet())); - @Override - public void setNotificationFlowRemovedOff(boolean isNotificationFlowRemovedOff) { - this.isNotificationFlowRemovedOff = isNotificationFlowRemovedOff; - } - - @Override - public void setClusteringSingletonServicesProvider(ClusterSingletonServiceProvider singletonServicesProvider) { - this.singletonServicesProvider = singletonServicesProvider; - } - - @Override - public void setSkipTableFeatures(final boolean skipTableFeatures){ - this.skipTableFeatures = skipTableFeatures; - } - - @Override - public void setSwitchFeaturesMandatory(final boolean switchFeaturesMandatory) { - this.switchFeaturesMandatory = switchFeaturesMandatory; - } - - public static MessageIntelligenceAgency getMessageIntelligenceAgency() { - return OpenFlowPluginProviderImpl.messageIntelligenceAgency; - } - - @Override - public void setSwitchConnectionProviders(final Collection switchConnectionProviders) { - this.switchConnectionProviders = switchConnectionProviders; - } + Futures.addCallback(listListenableFuture, new FutureCallback>() { + @Override + public void onSuccess(@Nonnull final List result) { + LOG.info("All switchConnectionProviders were successfully shut down ({}).", result.size()); + } - @Override - public void setDataBroker(final DataBroker dataBroker) { - this.dataBroker = dataBroker; - } + @Override + public void onFailure(@Nonnull final Throwable throwable) { + LOG.warn("Some switchConnectionProviders failed to shutdown.", throwable); + } + }, MoreExecutors.directExecutor()); - @Override - public void setRpcProviderRegistry(final RpcProviderRegistry rpcProviderRegistry) { - this.rpcProviderRegistry = rpcProviderRegistry; + return listListenableFuture; } @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"); + registerMXBean(MESSAGE_INTELLIGENCE_AGENCY, MESSAGE_INTELLIGENCE_AGENCY_MX_BEAN_NAME); - 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, + // 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. + executorService = MoreExecutors.listeningDecorator(new ThreadPoolLoggingExecutor( + config.getThreadPoolMinThreads(), + config.getThreadPoolMaxThreads().getValue(), + config.getThreadPoolTimeout(), + TimeUnit.SECONDS, new SynchronousQueue<>(), POOL_NAME)); + + deviceManager = new DeviceManagerImpl( + config, + dataBroker, getMessageIntelligenceAgency(), - isNotificationFlowRemovedOff, - singletonServicesProvider, notificationPublishService, hashedWheelTimer, convertorManager, - skipTableFeatures); + deviceInitializerProvider); + TranslatorLibraryUtil.injectBasicTranslatorLibrary(deviceManager, convertorManager); ((ExtensionConverterProviderKeeper) deviceManager).setExtensionConverterProvider(extensionConverterManager); - rpcManager = new RpcManagerImpl(rpcProviderRegistry, rpcRequestsQuota, extensionConverterManager, convertorManager, notificationPublishService); - statisticsManager = new StatisticsManagerImpl(rpcProviderRegistry, isStatisticsPollingOn, hashedWheelTimer, convertorManager); + rpcManager = new RpcManagerImpl( + config, + rpcProviderRegistry, + extensionConverterManager, + convertorManager, + notificationPublishService); + + statisticsManager = new StatisticsManagerImpl( + config, + rpcProviderRegistry, + convertorManager, + executorService); - /* 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); + roleManager = new RoleManagerImpl(hashedWheelTimer); - /* Termination Phase ordering - OFP Device Context suite */ - deviceManager.setDeviceTerminationPhaseHandler(rpcManager); - rpcManager.setDeviceTerminationPhaseHandler(statisticsManager); - statisticsManager.setDeviceTerminationPhaseHandler(deviceManager); + contextChainHolder = new ContextChainHolderImpl( + executorService, + singletonServicesProvider, + entityOwnershipService, + mastershipChangeServiceManager); - rpcManager.setStatisticsRpcEnabled(isStatisticsRpcEnabled); + contextChainHolder.addManager(deviceManager); + contextChainHolder.addManager(statisticsManager); + contextChainHolder.addManager(rpcManager); + contextChainHolder.addManager(roleManager); + + connectionManager = new ConnectionManagerImpl(config, executorService); + connectionManager.setDeviceConnectedHandler(contextChainHolder); + connectionManager.setDeviceDisconnectedHandler(contextChainHolder); - TranslatorLibraryUtil.injectBasicTranslatorLibrary(deviceManager, convertorManager); deviceManager.initialize(); + } - startSwitchConnections(); + @Override + public ExtensionConverterRegistrator getExtensionConverterRegistrator() { + return extensionConverterManager; } @Override - public void update(Map props) { - LOG.debug("Update managed properties = {}", props.toString()); + public void close() { + try { + shutdownSwitchConnections().get(10, TimeUnit.SECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + LOG.warn("Failed to shut down switch connections in time {}s, error: {}", 10, e); + } - if(deviceManager != null) { - if (props.containsKey("notification-flow-removed-off")) { - deviceManager.setIsNotificationFlowRemovedOff(Boolean.valueOf(props.get("notification-flow-removed-off").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(deviceManager); + gracefulShutdown(rpcManager); + gracefulShutdown(statisticsManager); + gracefulShutdown(roleManager); + gracefulShutdown(executorService); + gracefulShutdown(hashedWheelTimer); + unregisterMXBean(MESSAGE_INTELLIGENCE_AGENCY_MX_BEAN_NAME); + openflowPluginStatusMonitor.reportStatus(ServiceState.UNREGISTERED, "service shutting down"); + } + + @SuppressWarnings("checkstyle:IllegalCatch") + private static void gracefulShutdown(final AutoCloseable closeable) { + if (Objects.isNull(closeable)) { + return; } - if(rpcManager != null && props.containsKey("is-statistics-rpc-enabled")){ - rpcManager.setStatisticsRpcEnabled(Boolean.valueOf((props.get("is-statistics-rpc-enabled").toString()))); + try { + closeable.close(); + } catch (Exception e) { + LOG.warn("Failed to shutdown {} gracefully.", closeable); } + } - if (connectionManager != null && props.containsKey("echo-reply-timeout") ){ - try { - connectionManager.setEchoReplyTimeout(Long.valueOf(props.get("echo-reply-timeout").toString())); - }catch (NumberFormatException ex){ - connectionManager.setEchoReplyTimeout(DEFAULT_ECHO_TIMEOUT); - } + private static void gracefulShutdown(final Timer timer) { + if (Objects.isNull(timer)) { + return; } - if(statisticsManager != null && props.containsKey("is-statistics-polling-on")){ - statisticsManager.setIsStatisticsPollingOn(Boolean.valueOf(props.get("is-statistics-polling-on").toString())); + try { + timer.stop(); + } catch (IllegalStateException e) { + LOG.warn("Failed to shutdown {} gracefully.", timer); + } + } + + private static void gracefulShutdown(final ExecutorService executorService) { + if (Objects.isNull(executorService)) { + return; + } + + try { + executorService.shutdownNow(); + } catch (SecurityException e) { + LOG.warn("Failed to shutdown {} gracefully.", executorService); } } - private static void registerMXBean(final MessageIntelligenceAgency messageIntelligenceAgency) { + private static void registerMXBean(final Object bean, final String beanName) { 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); + mbs.registerMBean(bean, new ObjectName(beanName)); } catch (MalformedObjectNameException | NotCompliantMBeanException | MBeanRegistrationException @@ -324,34 +346,15 @@ public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenF } } - @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; - } + private static void unregisterMXBean(final String beanName) { + final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - @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(); + try { + mbs.unregisterMBean(new ObjectName(beanName)); + } catch (InstanceNotFoundException + | MBeanRegistrationException + | MalformedObjectNameException e) { + LOG.warn("Error unregistering MBean {}", e); + } } -} \ No newline at end of file +}