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 com.google.common.util.concurrent.ListeningExecutorService;
13 import java.util.Arrays;
14 import java.util.Collection;
15 import java.util.List;
17 import java.util.Map.Entry;
18 import java.util.concurrent.ConcurrentHashMap;
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
22 import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
23 import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
24 import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
25 import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionListener;
26 import org.opendaylight.openflowplugin.api.openflow.md.core.session.SwitchSessionKeyOF;
27 import org.opendaylight.openflowplugin.api.statistics.MessageSpy;
28 import org.opendaylight.openflowplugin.api.openflow.md.core.ConnectionConductor;
29 import org.opendaylight.openflowplugin.api.openflow.md.core.IMDMessageTranslator;
30 import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
31 import org.opendaylight.openflowplugin.api.openflow.md.queue.PopListener;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
33 import org.opendaylight.yangtools.concepts.ListenerRegistration;
34 import org.opendaylight.yangtools.util.ListenerRegistry;
35 import org.opendaylight.yangtools.yang.binding.DataContainer;
36 import org.opendaylight.yangtools.yang.binding.DataObject;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
43 public class SessionManagerOFImpl implements ConjunctSessionManager {
45 protected static final Logger LOG = LoggerFactory.getLogger(SessionManagerOFImpl.class);
46 private static SessionManagerOFImpl instance;
47 private ConcurrentHashMap<SwitchSessionKeyOF, SessionContext> sessionLot;
48 private Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> translatorMapping;
49 private Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> popListenerMapping;
51 protected ListenerRegistry<SessionListener> sessionListeners;
52 private NotificationProviderService notificationProviderService;
54 private DataBroker dataBroker;
55 private ListeningExecutorService rpcPool;
59 * @return singleton instance
61 public static ConjunctSessionManager getInstance() {
62 if (instance == null) {
63 synchronized (SessionContextOFImpl.class) {
64 if (instance == null) {
65 instance = new SessionManagerOFImpl();
73 * close and release singleton instace
75 public static void releaseInstance() {
76 if (instance != null) {
77 synchronized (SessionManagerOFImpl.class) {
78 if (instance != null) {
86 private SessionManagerOFImpl() {
87 LOG.debug("singleton creating");
88 sessionLot = new ConcurrentHashMap<>();
89 sessionListeners = new ListenerRegistry<>();
93 public SessionContext getSessionContext(SwitchSessionKeyOF sessionKey) {
94 return sessionLot.get(sessionKey);
98 public void invalidateSessionContext(SwitchSessionKeyOF sessionKey) {
99 SessionContext context = getSessionContext(sessionKey);
100 if (context == null) {
101 LOG.warn("context for invalidation not found");
103 synchronized (context) {
104 for (Entry<SwitchConnectionDistinguisher, ConnectionConductor> auxEntry : context.getAuxiliaryConductors()) {
105 invalidateAuxiliary(sessionKey, auxEntry.getKey());
107 context.getPrimaryConductor().disconnect();
108 context.setValid(false);
109 removeSessionContext(context);
110 // TODO:: notify listeners
115 private void invalidateDeadSessionContext(SessionContext sessionContext) {
116 if (sessionContext == null) {
117 LOG.warn("context for invalidation not found");
119 synchronized (sessionContext) {
120 for (Entry<SwitchConnectionDistinguisher, ConnectionConductor> auxEntry : sessionContext
121 .getAuxiliaryConductors()) {
122 invalidateAuxiliary(sessionContext, auxEntry.getKey(), true);
124 sessionContext.setValid(false);
125 removeSessionContext(sessionContext);
126 // TODO:: notify listeners
131 private void removeSessionContext(SessionContext sessionContext) {
132 if (LOG.isDebugEnabled()) {
133 LOG.debug("removing session: {}", Arrays.toString(sessionContext.getSessionKey().getId()));
135 sessionLot.remove(sessionContext.getSessionKey(), sessionContext);
136 sessionNotifier.onSessionRemoved(sessionContext);
140 public void addSessionContext(SwitchSessionKeyOF sessionKey, SessionContext context) {
141 synchronized (context) {
142 sessionLot.put(sessionKey, context);
143 sessionNotifier.onSessionAdded(sessionKey, context);
145 context.setValid(true);
150 public void invalidateAuxiliary(SwitchSessionKeyOF sessionKey,
151 SwitchConnectionDistinguisher connectionCookie) {
152 SessionContext context = getSessionContext(sessionKey);
153 invalidateAuxiliary(context, connectionCookie, true);
158 * @param connectionCookie
159 * @param disconnect true if auxiliary connection is to be disconnected
161 private static void invalidateAuxiliary(SessionContext context, SwitchConnectionDistinguisher connectionCookie,
162 boolean disconnect) {
163 if (context == null) {
164 LOG.warn("context for invalidation not found");
166 ConnectionConductor auxiliaryConductor = context.removeAuxiliaryConductor(connectionCookie);
167 if (auxiliaryConductor == null) {
168 LOG.warn("auxiliary conductor not found");
171 auxiliaryConductor.disconnect();
178 public void invalidateOnDisconnect(ConnectionConductor conductor) {
179 if (conductor.getAuxiliaryKey() == null) {
180 invalidateDeadSessionContext(conductor.getSessionContext());
181 // TODO:: notify listeners
183 invalidateAuxiliary(conductor.getSessionContext(), conductor.getAuxiliaryKey(), false);
188 public void setTranslatorMapping(Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> translatorMapping) {
189 this.translatorMapping = translatorMapping;
193 public ListenerRegistration<SessionListener> registerSessionListener(SessionListener listener) {
194 LOG.debug("registerSessionListener");
195 return sessionListeners.register(listener);
198 private final SessionListener sessionNotifier = new SessionListener() {
201 public void onSessionAdded(SwitchSessionKeyOF sessionKey, SessionContext context) {
202 for (ListenerRegistration<SessionListener> listener : sessionListeners) {
204 listener.getInstance().onSessionAdded(sessionKey, context);
205 } catch (Exception e) {
206 LOG.error("Unhandled exeption occured while invoking onSessionAdded on listener", e);
212 public void onSessionRemoved(SessionContext context) {
213 for (ListenerRegistration<SessionListener> listener : sessionListeners) {
215 listener.getInstance().onSessionRemoved(context);
216 } catch (Exception e) {
217 LOG.error("Unhandled exeption occured while invoking onSessionRemoved on listener", e);
222 private MessageSpy<DataContainer> messageSpy;
223 private ExtensionConverterProvider extensionConverterProvider;
227 public Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> getTranslatorMapping() {
228 return this.translatorMapping;
232 public void setNotificationProviderService(
233 NotificationProviderService notificationProviderService) {
234 this.notificationProviderService = notificationProviderService;
239 public DataBroker getDataBroker() {
244 public void setDataBroker(DataBroker dataBroker) {
245 this.dataBroker = dataBroker;
250 public NotificationProviderService getNotificationProviderService() {
251 return notificationProviderService;
255 public Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> getPopListenerMapping() {
256 return popListenerMapping;
260 public void setPopListenerMapping(
261 Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> popListenerMapping) {
262 this.popListenerMapping = popListenerMapping;
266 public void close() {
268 synchronized (sessionLot) {
269 for (SessionContext sessionContext : sessionLot.values()) {
270 sessionContext.getPrimaryConductor().disconnect();
272 // TODO: handle timeouted shutdown
276 for (ListenerRegistration<SessionListener> listenerRegistration : sessionListeners) {
277 SessionListener listener = listenerRegistration.getInstance();
278 if (listener instanceof AutoCloseable) {
280 ((AutoCloseable) listener).close();
281 } catch (Exception e) {
282 LOG.warn("closing of sessionListenerRegistration failed", e);
289 public void setRpcPool(ListeningExecutorService rpcPool) {
290 this.rpcPool = rpcPool;
294 public ListeningExecutorService getRpcPool() {
299 public void setMessageSpy(MessageSpy<DataContainer> messageSpy) {
300 this.messageSpy = messageSpy;
304 public MessageSpy<DataContainer> getMessageSpy() {
309 public void setExtensionConverterProvider(
310 ExtensionConverterProvider extensionConverterProvider) {
311 this.extensionConverterProvider = extensionConverterProvider;
315 * @return the extensionConverterProvider
318 public ExtensionConverterProvider getExtensionConverterProvider() {
319 return extensionConverterProvider;