import java.util.ArrayList;
import java.util.Collection;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-import org.opendaylight.openflowjava.protocol.api.connection.ConnectionConfiguration;
-import org.opendaylight.openflowjava.protocol.api.connection.SwitchConnectionHandler;
import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider;
+import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.md.core.IMDMessageTranslator;
+import org.opendaylight.openflowplugin.api.openflow.md.core.NotificationQueueWrapper;
+import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
+import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
+import org.opendaylight.openflowplugin.openflow.md.core.translator.ErrorTranslator;
+import org.opendaylight.openflowplugin.openflow.md.core.translator.ErrorV10Translator;
+import org.opendaylight.openflowplugin.openflow.md.core.translator.ExperimenterTranslator;
+import org.opendaylight.openflowplugin.openflow.md.core.translator.FeaturesV10ToNodeConnectorUpdatedTranslator;
+import org.opendaylight.openflowplugin.openflow.md.core.translator.FlowRemovedTranslator;
+import org.opendaylight.openflowplugin.openflow.md.core.translator.MultiPartMessageDescToNodeUpdatedTranslator;
+import org.opendaylight.openflowplugin.openflow.md.core.translator.MultiPartReplyPortToNodeConnectorUpdatedTranslator;
+import org.opendaylight.openflowplugin.openflow.md.core.translator.MultipartReplyTableFeaturesToTableUpdatedTranslator;
+import org.opendaylight.openflowplugin.openflow.md.core.translator.MultipartReplyTranslator;
+import org.opendaylight.openflowplugin.openflow.md.core.translator.NotificationPlainTranslator;
+import org.opendaylight.openflowplugin.openflow.md.core.translator.PacketInTranslator;
+import org.opendaylight.openflowplugin.openflow.md.core.translator.PacketInV10Translator;
+import org.opendaylight.openflowplugin.openflow.md.core.translator.PortStatusMessageToNodeConnectorUpdatedTranslator;
+import org.opendaylight.openflowplugin.api.openflow.md.queue.PopListener;
+import org.opendaylight.openflowplugin.openflow.md.util.OpenflowPortsUtil;
+import org.opendaylight.openflowplugin.api.openflow.statistics.MessageSpy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeErrorNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SwitchFlowRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsUpdate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowsStatisticsUpdate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsUpdate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupDescStatsUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupFeaturesUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupStatisticsUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterConfigStatsUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterFeaturesUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterStatisticsUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.node.error.service.rev140410.BadActionErrorNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.node.error.service.rev140410.BadInstructionErrorNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.node.error.service.rev140410.BadMatchErrorNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.node.error.service.rev140410.BadRequestErrorNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.node.error.service.rev140410.ExperimenterErrorNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.node.error.service.rev140410.FlowModErrorNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.node.error.service.rev140410.GroupModErrorNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.node.error.service.rev140410.HelloFailedErrorNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.node.error.service.rev140410.MeterModErrorNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.node.error.service.rev140410.PortModErrorNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.node.error.service.rev140410.QueueOpErrorNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.node.error.service.rev140410.RoleRequestErrorNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.node.error.service.rev140410.SwitchConfigErrorNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.node.error.service.rev140410.TableFeaturesErrorNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.node.error.service.rev140410.TableModErrorNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemovedMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.NodeConnectorStatisticsUpdate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.QueueStatisticsUpdate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.TableUpdated;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.ForwardingBlockingQueue;
+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;
/**
- * @author mirehak
*
*/
-public class MDController implements IMDController {
+public class MDController implements IMDController, AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(MDController.class);
- private SwitchConnectionProvider switchConnectionProvider;
+ private Collection<SwitchConnectionProvider> switchConnectionProviders;
- private ConcurrentMap<Class<? extends DataObject>, Collection<IMDMessageListener>> messageListeners;
+ private ConcurrentMap<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> messageTranslators;
+ private Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> popListeners;
+ private MessageSpy<DataContainer> messageSpyCounter;
- public Map<Class<? extends DataObject>, Collection<IMDMessageListener>> getMessageListeners() {
- return messageListeners;
- }
+ final private int OF10 = OFConstants.OFP_VERSION_1_0;
+ final private int OF13 = OFConstants.OFP_VERSION_1_3;
+
+ private ErrorHandlerSimpleImpl errorHandler;
+ private ExtensionConverterProvider extensionConverterProvider;
+ /**
+ * @return translator mapping
+ */
+ public Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> getMessageTranslators() {
+ return messageTranslators;
+ }
+
+ /**
+ * provisioning of translator mapping
+ */
public void init() {
- LOG.debug("Initializing!");
- this.messageListeners = new ConcurrentHashMap<>();
+ LOG.debug("init");
+
+ OpenflowPortsUtil.init();
+
+ messageTranslators = new ConcurrentHashMap<>();
+ popListeners = new ConcurrentHashMap<>();
+ //TODO: move registration to factory
+ addMessageTranslator(ErrorMessage.class, OF10, new ErrorV10Translator());
+ addMessageTranslator(ErrorMessage.class, OF13, new ErrorTranslator());
+ addMessageTranslator(FlowRemovedMessage.class, OF10, new FlowRemovedTranslator());
+ addMessageTranslator(FlowRemovedMessage.class, OF13, new FlowRemovedTranslator());
+ addMessageTranslator(PacketInMessage.class,OF10, new PacketInV10Translator());
+ addMessageTranslator(PacketInMessage.class,OF13, new PacketInTranslator());
+ addMessageTranslator(PortStatusMessage.class,OF10, new PortStatusMessageToNodeConnectorUpdatedTranslator());
+ addMessageTranslator(PortStatusMessage.class,OF13, new PortStatusMessageToNodeConnectorUpdatedTranslator());
+ addMessageTranslator(MultipartReplyMessage.class,OF13,new MultiPartReplyPortToNodeConnectorUpdatedTranslator());
+ addMessageTranslator(MultipartReplyMessage.class,OF10, new MultiPartMessageDescToNodeUpdatedTranslator());
+ addMessageTranslator(MultipartReplyMessage.class,OF13, new MultiPartMessageDescToNodeUpdatedTranslator());
+ addMessageTranslator(ExperimenterMessage.class, OF10, new ExperimenterTranslator());
+ addMessageTranslator(MultipartReplyMessage.class,OF10, new MultipartReplyTranslator());
+ addMessageTranslator(MultipartReplyMessage.class,OF13, new MultipartReplyTranslator());
+ addMessageTranslator(MultipartReplyMessage.class,OF13,new MultipartReplyTableFeaturesToTableUpdatedTranslator());
+ addMessageTranslator(GetFeaturesOutput.class,OF10, new FeaturesV10ToNodeConnectorUpdatedTranslator());
+ addMessageTranslator(NotificationQueueWrapper.class, OF10, new NotificationPlainTranslator());
+ addMessageTranslator(NotificationQueueWrapper.class, OF13, new NotificationPlainTranslator());
+
+ NotificationPopListener<DataObject> notificationPopListener = new NotificationPopListener<DataObject>();
+ notificationPopListener.setNotificationProviderService(
+ OFSessionUtil.getSessionManager().getNotificationProviderService());
+ notificationPopListener.setMessageSpy(messageSpyCounter);
+
+ //TODO: move registration to factory
+ addMessagePopListener(NodeErrorNotification.class, notificationPopListener);
+ addMessagePopListener(BadActionErrorNotification.class, notificationPopListener);
+ addMessagePopListener(BadInstructionErrorNotification.class, notificationPopListener);
+ addMessagePopListener(BadMatchErrorNotification.class, notificationPopListener);
+ addMessagePopListener(BadRequestErrorNotification.class, notificationPopListener);
+ addMessagePopListener(ExperimenterErrorNotification.class, notificationPopListener);
+ addMessagePopListener(FlowModErrorNotification.class, notificationPopListener);
+ addMessagePopListener(GroupModErrorNotification.class, notificationPopListener);
+ addMessagePopListener(HelloFailedErrorNotification.class, notificationPopListener);
+ addMessagePopListener(MeterModErrorNotification.class, notificationPopListener);
+ addMessagePopListener(PortModErrorNotification.class, notificationPopListener);
+ addMessagePopListener(QueueOpErrorNotification.class, notificationPopListener);
+ addMessagePopListener(RoleRequestErrorNotification.class, notificationPopListener);
+ addMessagePopListener(SwitchConfigErrorNotification.class, notificationPopListener);
+ addMessagePopListener(TableFeaturesErrorNotification.class, notificationPopListener);
+ addMessagePopListener(TableModErrorNotification.class, notificationPopListener);
+ addMessagePopListener(NodeConnectorUpdated.class,notificationPopListener);
+ addMessagePopListener(NodeConnectorRemoved.class,notificationPopListener);
+ addMessagePopListener(PacketReceived.class,notificationPopListener);
+ addMessagePopListener(TransmitPacketInput.class, notificationPopListener);
+ addMessagePopListener(NodeUpdated.class, notificationPopListener);
+ addMessagePopListener(NodeRemoved.class, notificationPopListener);
+
+ addMessagePopListener(SwitchFlowRemoved.class, notificationPopListener);
+ addMessagePopListener(TableUpdated.class, notificationPopListener);
+
+ //Notification registration for flow statistics
+ addMessagePopListener(FlowsStatisticsUpdate.class, notificationPopListener);
+ addMessagePopListener(AggregateFlowStatisticsUpdate.class, notificationPopListener);
+
+ //Notification registrations for group-statistics
+ addMessagePopListener(GroupStatisticsUpdated.class, notificationPopListener);
+ addMessagePopListener(GroupFeaturesUpdated.class, notificationPopListener);
+ addMessagePopListener(GroupDescStatsUpdated.class, notificationPopListener);
+
+ //Notification registrations for meter-statistics
+ addMessagePopListener(MeterStatisticsUpdated.class, notificationPopListener);
+ addMessagePopListener(MeterConfigStatsUpdated.class, notificationPopListener);
+ addMessagePopListener(MeterFeaturesUpdated.class, notificationPopListener);
+
+ //Notification registration for port-statistics
+ addMessagePopListener(NodeConnectorStatisticsUpdate.class, notificationPopListener);
+
+ //Notification registration for flow-table statistics
+ addMessagePopListener(FlowTableStatisticsUpdate.class, notificationPopListener);
+
+ //Notification registration for queue-statistics
+ addMessagePopListener(QueueStatisticsUpdate.class, notificationPopListener);
+
// Push the updated Listeners to Session Manager which will be then picked up by ConnectionConductor eventually
- OFSessionUtil.getSessionManager().setListenerMapping(messageListeners);
+ OFSessionUtil.getSessionManager().setTranslatorMapping(messageTranslators);
+ OFSessionUtil.getSessionManager().setPopListenerMapping(popListeners);
+ OFSessionUtil.getSessionManager().setMessageSpy(messageSpyCounter);
+
+ // prepare worker pool for rpc
+ // TODO: get size from configSubsystem
+ int rpcThreadLimit = 10;
+ ListeningExecutorService rpcPoolDelegator = createRpcPoolSpyDecorated(rpcThreadLimit, messageSpyCounter);
+ OFSessionUtil.getSessionManager().setRpcPool(rpcPoolDelegator);
+ OFSessionUtil.getSessionManager().setExtensionConverterProvider(extensionConverterProvider);
+
}
/**
- * @param switchConnectionProvider
- * the switchConnectionProvider to set
+ * @param rpcThreadLimit
+ * @param messageSpy
+ * @return
*/
- public void setSwitchConnectionProvider(SwitchConnectionProvider switchConnectionProvider) {
- this.switchConnectionProvider = switchConnectionProvider;
+ private static ListeningExecutorService createRpcPoolSpyDecorated(final int rpcThreadLimit, final MessageSpy<DataContainer> messageSpy) {
+ final BlockingQueue<Runnable> delegate = new LinkedBlockingQueue<>(100000);
+ final BlockingQueue<Runnable> queue = new ForwardingBlockingQueue<Runnable>() {
+ @Override
+ protected BlockingQueue<Runnable> delegate() {
+ return delegate;
+ }
+
+ @Override
+ public boolean offer(final Runnable r) {
+ // ThreadPoolExecutor will spawn a new thread after core size is reached only
+ // if the queue.offer returns false.
+ return false;
+ }
+ };
+
+ ThreadPoolLoggingExecutor rpcPool = new ThreadPoolLoggingExecutor(rpcThreadLimit, rpcThreadLimit, 0L,
+ TimeUnit.MILLISECONDS, queue, "OFRpc");
+ rpcPool.setRejectedExecutionHandler(new RejectedExecutionHandler() {
+ @Override
+ public void rejectedExecution(final Runnable r, final ThreadPoolExecutor executor) {
+ try {
+ executor.getQueue().put(r);
+ } catch (InterruptedException e) {
+ throw new RejectedExecutionException("Interrupted while waiting on queue", e);
+ }
+
+ }
+ });
+ ListeningExecutorService listeningRpcPool = MoreExecutors.listeningDecorator(rpcPool);
+ RpcListeningExecutorService rpcPoolDecorated = new RpcListeningExecutorService(listeningRpcPool);
+ rpcPoolDecorated.setMessageSpy(messageSpy);
+ return rpcPoolDecorated;
}
/**
- * @param switchConnectionProviderToUnset
- * the switchConnectionProvider to unset
+ * @param switchConnectionProviders
+ * the switchConnectionProviders to set
*/
- public void unsetSwitchConnectionProvider(SwitchConnectionProvider switchConnectionProviderToUnset) {
- if (this.switchConnectionProvider == switchConnectionProviderToUnset) {
- this.switchConnectionProvider = null;
- }
+ public void setSwitchConnectionProviders(final Collection<SwitchConnectionProvider> switchConnectionProviders) {
+ this.switchConnectionProviders = switchConnectionProviders;
}
/**
*/
public void start() {
LOG.debug("starting ..");
- LOG.debug("switchConnectionProvider: " + switchConnectionProvider);
+ LOG.debug("switchConnectionProvider: " + switchConnectionProviders);
// setup handler
- SwitchConnectionHandler switchConnectionHandler = new SwitchConnectionHandlerImpl();
- switchConnectionProvider.setSwitchConnectionHandler(switchConnectionHandler);
- // configure and startup library servers
- switchConnectionProvider.configure(getConnectionConfiguration());
- Future<List<Boolean>> srvStarted = switchConnectionProvider.startup();
- }
+ SwitchConnectionHandlerImpl switchConnectionHandler = new SwitchConnectionHandlerImpl();
+ switchConnectionHandler.setMessageSpy(messageSpyCounter);
- /**
- * @return wished connections configurations
- */
- private static Collection<ConnectionConfiguration> getConnectionConfiguration() {
- // TODO:: get config from state manager
- ConnectionConfiguration configuration = ConnectionConfigurationFactory.getDefault();
- return Lists.newArrayList(configuration);
+ errorHandler = new ErrorHandlerSimpleImpl();
+
+ switchConnectionHandler.setErrorHandler(errorHandler);
+ switchConnectionHandler.init();
+
+ List<ListenableFuture<Boolean>> starterChain = new ArrayList<>(switchConnectionProviders.size());
+ for (SwitchConnectionProvider switchConnectionPrv : switchConnectionProviders) {
+ switchConnectionPrv.setSwitchConnectionHandler(switchConnectionHandler);
+ ListenableFuture<Boolean> isOnlineFuture = switchConnectionPrv.startup();
+ starterChain.add(isOnlineFuture);
+ }
+
+ Future<List<Boolean>> srvStarted = Futures.allAsList(starterChain);
}
/**
*/
public void stop() {
LOG.debug("stopping");
- Future<List<Boolean>> srvStopped = switchConnectionProvider.shutdown();
+ List<ListenableFuture<Boolean>> stopChain = new ArrayList<>(switchConnectionProviders.size());
try {
- srvStopped.get(5000, TimeUnit.MILLISECONDS);
+ for (SwitchConnectionProvider switchConnectionPrv : switchConnectionProviders) {
+ ListenableFuture<Boolean> shutdown = switchConnectionPrv.shutdown();
+ stopChain.add(shutdown);
+ }
+ Futures.allAsList(stopChain).get(5000, TimeUnit.MILLISECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
LOG.error(e.getMessage(), e);
}
+ close();
}
/**
*
*/
public void destroy() {
- // do nothing
+ close();
}
@Override
- public void addMessageListener(Class<? extends DataObject> messageType, IMDMessageListener listener) {
+ public void addMessageTranslator(final Class<? extends DataObject> messageType, final int version, final IMDMessageTranslator<OfHeader, List<DataObject>> translator) {
+ TranslatorKey tKey = new TranslatorKey(version, messageType.getName());
- Collection<IMDMessageListener> existingValues = messageListeners.get(messageType);
+ Collection<IMDMessageTranslator<OfHeader, List<DataObject>>> existingValues = messageTranslators.get(tKey);
if (existingValues == null) {
- existingValues = new ArrayList<IMDMessageListener>();
- messageListeners.put(messageType, existingValues);
+ existingValues = new LinkedHashSet<>();
+ messageTranslators.put(tKey, existingValues);
}
- existingValues.add(listener);
- LOG.debug("{} is now listened by {}", messageType, listener);
+ existingValues.add(translator);
+ LOG.debug("{} is now translated by {}", messageType, translator);
}
@Override
- public void removeMessageListener(Class<? extends DataObject> messageType, IMDMessageListener listener) {
+ public void removeMessageTranslator(final Class<? extends DataObject> messageType, final int version, final IMDMessageTranslator<OfHeader, List<DataObject>> translator) {
+ TranslatorKey tKey = new TranslatorKey(version, messageType.getName());
+ Collection<IMDMessageTranslator<OfHeader, List<DataObject>>> values = messageTranslators.get(tKey);
+ if (values != null) {
+ values.remove(translator);
+ if (values.isEmpty()) {
+ messageTranslators.remove(tKey);
+ }
+ LOG.debug("{} is now removed from translators", translator);
+ }
+ }
+
+ @Override
+ public void addMessagePopListener(final Class<? extends DataObject> messageType, final PopListener<DataObject> popListener) {
+ Collection<PopListener<DataObject>> existingValues = popListeners.get(messageType);
+ if (existingValues == null) {
+ existingValues = new LinkedHashSet<>();
+ popListeners.put(messageType, existingValues);
+ }
+ existingValues.add(popListener);
+ LOG.debug("{} is now popListened by {}", messageType, popListener);
+ }
- Collection<IMDMessageListener> values = messageListeners.get(messageType);
+ @Override
+ public void removeMessagePopListener(final Class<? extends DataObject> messageType, final PopListener<DataObject> popListener) {
+ Collection<PopListener<DataObject>> values = popListeners.get(messageType);
if (values != null) {
- values.remove(listener);
- if (values.size() == 0) {
- messageListeners.remove(messageType);
- }
- LOG.debug("{} is now removed", listener);
+ values.remove(popListener);
+ if (values.isEmpty()) {
+ popListeners.remove(messageType);
+ }
+ LOG.debug("{} is now removed from popListeners", popListener);
}
}
+ /**
+ * @param messageSpyCounter the messageSpyCounter to set
+ */
+ public void setMessageSpyCounter(
+ final MessageSpy<DataContainer> messageSpyCounter) {
+ this.messageSpyCounter = messageSpyCounter;
+ }
+ @Override
+ public void close() {
+ LOG.debug("close");
+ messageSpyCounter = null;
+ messageTranslators = null;
+ popListeners = null;
+ for (SwitchConnectionProvider switchConnectionPrv : switchConnectionProviders) {
+ switchConnectionPrv.setSwitchConnectionHandler(null);
+ }
+ switchConnectionProviders = null;
+ OpenflowPortsUtil.close();
+ OFSessionUtil.releaseSessionManager();
+ errorHandler = null;
+ }
+
+ /**
+ * @param extensionConverterProvider
+ */
+ public void setExtensionConverterProvider(ExtensionConverterProvider extensionConverterProvider) {
+ this.extensionConverterProvider = extensionConverterProvider;
+ }
}