2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.openflowplugin.openflow.md.core.session;
11 import java.util.Arrays;
12 import java.util.Collection;
13 import java.util.List;
15 import java.util.Map.Entry;
16 import java.util.concurrent.ConcurrentHashMap;
18 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
19 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
20 import org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductor;
21 import org.opendaylight.openflowplugin.openflow.md.core.IMDMessageTranslator;
22 import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDistinguisher;
23 import org.opendaylight.openflowplugin.openflow.md.core.TranslatorKey;
24 import org.opendaylight.openflowplugin.openflow.md.core.extension.ExtensionConverterProvider;
25 import org.opendaylight.openflowplugin.openflow.md.queue.PopListener;
26 import org.opendaylight.openflowplugin.statistics.MessageSpy;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
28 import org.opendaylight.yangtools.concepts.ListenerRegistration;
29 import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
30 import org.opendaylight.yangtools.yang.binding.DataContainer;
31 import org.opendaylight.yangtools.yang.binding.DataObject;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
35 import com.google.common.util.concurrent.ListeningExecutorService;
40 public class SessionManagerOFImpl implements SessionManager {
42 protected static final Logger LOG = LoggerFactory.getLogger(SessionManagerOFImpl.class);
43 private static SessionManagerOFImpl instance;
44 private ConcurrentHashMap<SwitchSessionKeyOF, SessionContext> sessionLot;
45 private Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> translatorMapping;
46 private Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> popListenerMapping;
48 protected ListenerRegistry<SessionListener> sessionListeners;
49 private NotificationProviderService notificationProviderService;
51 private DataProviderService dataProviderService;
52 private ListeningExecutorService rpcPool;
56 * @return singleton instance
58 public static SessionManager getInstance() {
59 if (instance == null) {
60 synchronized (SessionContextOFImpl.class) {
61 if (instance == null) {
62 instance = new SessionManagerOFImpl();
70 * close and release singleton instace
72 public static void releaseInstance() {
73 if (instance != null) {
74 synchronized (SessionManagerOFImpl.class) {
75 if (instance != null) {
83 private SessionManagerOFImpl() {
84 LOG.debug("singleton creating");
85 sessionLot = new ConcurrentHashMap<>();
86 sessionListeners = new ListenerRegistry<>();
90 public SessionContext getSessionContext(SwitchSessionKeyOF sessionKey) {
91 return sessionLot.get(sessionKey);
95 public void invalidateSessionContext(SwitchSessionKeyOF sessionKey) {
96 SessionContext context = getSessionContext(sessionKey);
97 if (context == null) {
98 LOG.warn("context for invalidation not found");
100 for (Entry<SwitchConnectionDistinguisher, ConnectionConductor> auxEntry : context.getAuxiliaryConductors()) {
101 invalidateAuxiliary(sessionKey, auxEntry.getKey());
103 context.getPrimaryConductor().disconnect();
104 context.setValid(false);
105 removeSessionContext(context);
106 // TODO:: notify listeners
110 private void invalidateDeadSessionContext(SessionContext sessionContext) {
111 if (sessionContext == null) {
112 LOG.warn("context for invalidation not found");
114 for (Entry<SwitchConnectionDistinguisher, ConnectionConductor> auxEntry : sessionContext
115 .getAuxiliaryConductors()) {
116 invalidateAuxiliary(sessionContext, auxEntry.getKey(), true);
118 sessionContext.setValid(false);
119 removeSessionContext(sessionContext);
120 // TODO:: notify listeners
124 private void removeSessionContext(SessionContext sessionContext) {
125 if (LOG.isDebugEnabled()) {
126 LOG.debug("removing session: {}", Arrays.toString(sessionContext.getSessionKey().getId()));
128 sessionLot.remove(sessionContext.getSessionKey(), sessionContext);
129 sessionNotifier.onSessionRemoved(sessionContext);
133 public void addSessionContext(SwitchSessionKeyOF sessionKey, SessionContext context) {
134 sessionLot.put(sessionKey, context);
136 sessionNotifier.onSessionAdded(sessionKey, context);
141 public void invalidateAuxiliary(SwitchSessionKeyOF sessionKey,
142 SwitchConnectionDistinguisher connectionCookie) {
143 SessionContext context = getSessionContext(sessionKey);
144 invalidateAuxiliary(context, connectionCookie, true);
149 * @param connectionCookie
151 * true if auxiliary connection is to be disconnected
153 private static void invalidateAuxiliary(SessionContext context, SwitchConnectionDistinguisher connectionCookie,
154 boolean disconnect) {
155 if (context == null) {
156 LOG.warn("context for invalidation not found");
158 ConnectionConductor auxiliaryConductor = context.removeAuxiliaryConductor(connectionCookie);
159 if (auxiliaryConductor == null) {
160 LOG.warn("auxiliary conductor not found");
163 auxiliaryConductor.disconnect();
170 public void invalidateOnDisconnect(ConnectionConductor conductor) {
171 if (conductor.getAuxiliaryKey() == null) {
172 invalidateDeadSessionContext(conductor.getSessionContext());
173 // TODO:: notify listeners
175 invalidateAuxiliary(conductor.getSessionContext(), conductor.getAuxiliaryKey(), false);
180 public void setTranslatorMapping(Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> translatorMapping) {
181 this.translatorMapping = translatorMapping;
185 public ListenerRegistration<SessionListener> registerSessionListener(SessionListener listener) {
186 LOG.debug("registerSessionListener");
187 return sessionListeners.register(listener);
190 private final SessionListener sessionNotifier = new SessionListener() {
193 public void onSessionAdded(SwitchSessionKeyOF sessionKey, SessionContext context) {
194 for (ListenerRegistration<SessionListener> listener : sessionListeners) {
196 listener.getInstance().onSessionAdded(sessionKey, context);
197 } catch (Exception e) {
198 LOG.error("Unhandled exeption occured while invoking onSessionAdded on listener", e);
204 public void onSessionRemoved(SessionContext context) {
205 for (ListenerRegistration<SessionListener> listener : sessionListeners) {
207 listener.getInstance().onSessionRemoved(context);
208 } catch (Exception e) {
209 LOG.error("Unhandled exeption occured while invoking onSessionRemoved on listener", e);
214 private MessageSpy<DataContainer> messageSpy;
215 private ExtensionConverterProvider extensionConverterProvider;
219 public Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> getTranslatorMapping() {
220 return this.translatorMapping;
224 public void setNotificationProviderService(
225 NotificationProviderService notificationProviderService) {
226 this.notificationProviderService = notificationProviderService;
231 public DataProviderService getDataProviderService() {
232 return dataProviderService;
236 public void setDataProviderService(DataProviderService dataServiceProvider) {
237 this.dataProviderService = dataServiceProvider;
242 public NotificationProviderService getNotificationProviderService() {
243 return notificationProviderService;
247 public Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> getPopListenerMapping() {
248 return popListenerMapping;
252 public void setPopListenerMapping(
253 Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> popListenerMapping) {
254 this.popListenerMapping = popListenerMapping;
258 public void close() {
260 sessionListeners = null;
261 synchronized (sessionLot) {
262 for (SessionContext sessionContext : sessionLot.values()) {
263 sessionContext.getPrimaryConductor().disconnect();
265 // TODO: handle timeouted shutdown
271 public void setRpcPool(ListeningExecutorService rpcPool) {
272 this.rpcPool = rpcPool;
276 public ListeningExecutorService getRpcPool() {
281 public void setMessageSpy(MessageSpy<DataContainer> messageSpy) {
282 this.messageSpy = messageSpy;
286 public MessageSpy<DataContainer> getMessageSpy() {
291 public void setExtensionConverterProvider(
292 ExtensionConverterProvider extensionConverterProvider) {
293 this.extensionConverterProvider = extensionConverterProvider;
297 * @return the extensionConverterProvider
300 public ExtensionConverterProvider getExtensionConverterProvider() {
301 return extensionConverterProvider;