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;
12 import java.util.Arrays;
13 import java.util.Collection;
14 import java.util.List;
16 import java.util.Map.Entry;
17 import java.util.concurrent.ConcurrentHashMap;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
20 import org.opendaylight.openflowplugin.api.openflow.md.core.ConnectionConductor;
21 import org.opendaylight.openflowplugin.api.openflow.md.core.IMDMessageTranslator;
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.openflow.md.queue.PopListener;
28 import org.opendaylight.openflowplugin.api.openflow.statistics.MessageSpy;
29 import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
31 import org.opendaylight.yangtools.concepts.ListenerRegistration;
32 import org.opendaylight.yangtools.util.ListenerRegistry;
33 import org.opendaylight.yangtools.yang.binding.DataContainer;
34 import org.opendaylight.yangtools.yang.binding.DataObject;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
41 public class SessionManagerOFImpl implements ConjunctSessionManager {
43 protected static final Logger LOG = LoggerFactory.getLogger(SessionManagerOFImpl.class);
44 private static SessionManagerOFImpl instance;
45 private ConcurrentHashMap<SwitchSessionKeyOF, SessionContext> sessionLot;
46 private Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> translatorMapping;
47 private Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> popListenerMapping;
49 protected ListenerRegistry<SessionListener> sessionListeners;
50 private NotificationProviderService notificationProviderService;
52 private DataBroker dataBroker;
53 private ListeningExecutorService rpcPool;
57 * @return singleton instance
59 public static ConjunctSessionManager getInstance() {
60 if (instance == null) {
61 synchronized (SessionContextOFImpl.class) {
62 if (instance == null) {
63 instance = new SessionManagerOFImpl();
71 * close and release singleton instance
73 public static void releaseInstance() {
74 if (instance != null) {
75 synchronized (SessionManagerOFImpl.class) {
76 if (instance != null) {
84 private SessionManagerOFImpl() {
85 LOG.debug("singleton creating");
86 sessionLot = new ConcurrentHashMap<>();
87 sessionListeners = new ListenerRegistry<>();
91 public SessionContext getSessionContext(SwitchSessionKeyOF sessionKey) {
92 return sessionLot.get(sessionKey);
96 public void invalidateSessionContext(SwitchSessionKeyOF sessionKey) {
97 SessionContext context = getSessionContext(sessionKey);
98 if (context == null) {
99 LOG.info("context for invalidation not found");
101 synchronized (context) {
102 if (context.isValid()) {
103 for (Entry<SwitchConnectionDistinguisher, ConnectionConductor> auxEntry : context.getAuxiliaryConductors()) {
104 invalidateAuxiliary(sessionKey, auxEntry.getKey());
106 context.getPrimaryConductor().disconnect();
107 context.setValid(false);
108 removeSessionContext(context);
109 // TODO:: notify listeners
111 LOG.warn("Ignore invalid session context: {}",
112 Arrays.toString(sessionKey.getId()));
118 private void invalidateDeadSessionContext(SessionContext sessionContext) {
119 if (sessionContext == null) {
120 LOG.info("context for invalidation not found");
122 synchronized (sessionContext) {
123 if (sessionContext.isValid()) {
124 for (Entry<SwitchConnectionDistinguisher, ConnectionConductor> auxEntry : sessionContext
125 .getAuxiliaryConductors()) {
126 invalidateAuxiliary(sessionContext, auxEntry.getKey(), true);
128 sessionContext.setValid(false);
129 removeSessionContext(sessionContext);
130 // TODO:: notify listeners
132 LOG.warn("Ignore invalid dead session context: {}",
134 sessionContext.getSessionKey().getId()));
140 private void removeSessionContext(SessionContext sessionContext) {
141 if (LOG.isDebugEnabled()) {
142 LOG.debug("removing session: {}", Arrays.toString(sessionContext.getSessionKey().getId()));
144 if (sessionLot.remove(sessionContext.getSessionKey(), sessionContext)) {
145 sessionNotifier.onSessionRemoved(sessionContext);
147 // This should never happen.
148 LOG.warn("Ignore session context that was already removed: {}",
149 Arrays.toString(sessionContext.getSessionKey().getId()));
154 public void addSessionContext(SwitchSessionKeyOF sessionKey, SessionContext context) {
155 synchronized (context) {
156 sessionLot.put(sessionKey, context);
157 sessionNotifier.onSessionAdded(sessionKey, context);
158 context.setValid(true);
163 public void setRole(SessionContext context) {
164 sessionNotifier.setRole(context);
167 public void invalidateAuxiliary(SwitchSessionKeyOF sessionKey,
168 SwitchConnectionDistinguisher connectionCookie) {
169 SessionContext context = getSessionContext(sessionKey);
170 invalidateAuxiliary(context, connectionCookie, true);
175 * @param connectionCookie
176 * @param disconnect true if auxiliary connection is to be disconnected
178 private static void invalidateAuxiliary(SessionContext context, SwitchConnectionDistinguisher connectionCookie,
179 boolean disconnect) {
180 if (context == null) {
181 LOG.info("context for invalidation not found");
183 ConnectionConductor auxiliaryConductor = context.removeAuxiliaryConductor(connectionCookie);
184 if (auxiliaryConductor == null) {
185 LOG.warn("auxiliary conductor not found");
188 auxiliaryConductor.disconnect();
195 public void invalidateOnDisconnect(ConnectionConductor conductor) {
196 if (conductor.getAuxiliaryKey() == null) {
197 invalidateDeadSessionContext(conductor.getSessionContext());
198 // TODO:: notify listeners
200 invalidateAuxiliary(conductor.getSessionContext(), conductor.getAuxiliaryKey(), false);
205 public void setTranslatorMapping(Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> translatorMapping) {
206 this.translatorMapping = translatorMapping;
210 public ListenerRegistration<SessionListener> registerSessionListener(SessionListener listener) {
211 LOG.debug("registerSessionListener");
212 return sessionListeners.register(listener);
215 private final SessionListener sessionNotifier = new SessionListener() {
218 public void onSessionAdded(SwitchSessionKeyOF sessionKey, SessionContext context) {
219 for (ListenerRegistration<SessionListener> listener : sessionListeners) {
221 listener.getInstance().onSessionAdded(sessionKey, context);
222 } catch (Exception e) {
223 LOG.error("Unhandled exeption occured while invoking onSessionAdded on listener", e);
229 public void setRole(SessionContext context) {
230 for (ListenerRegistration<SessionListener> listener : sessionListeners) {
232 listener.getInstance().setRole(context);
233 } catch (Exception e) {
234 LOG.error("Unhandled exeption occured while invoking setRole on listener", e);
240 public void onSessionRemoved(SessionContext context) {
241 for (ListenerRegistration<SessionListener> listener : sessionListeners) {
243 listener.getInstance().onSessionRemoved(context);
244 } catch (Exception e) {
245 LOG.error("Unhandled exeption occured while invoking onSessionRemoved on listener", e);
250 private MessageSpy<DataContainer> messageSpy;
251 private ExtensionConverterProvider extensionConverterProvider;
255 public Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> getTranslatorMapping() {
256 return this.translatorMapping;
260 public void setNotificationProviderService(
261 NotificationProviderService notificationProviderService) {
262 this.notificationProviderService = notificationProviderService;
267 public DataBroker getDataBroker() {
272 public void setDataBroker(DataBroker dataBroker) {
273 this.dataBroker = dataBroker;
278 public NotificationProviderService getNotificationProviderService() {
279 return notificationProviderService;
283 public Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> getPopListenerMapping() {
284 return popListenerMapping;
288 public void setPopListenerMapping(
289 Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> popListenerMapping) {
290 this.popListenerMapping = popListenerMapping;
294 public void close() {
296 synchronized (sessionLot) {
297 for (SessionContext sessionContext : sessionLot.values()) {
298 sessionContext.getPrimaryConductor().disconnect();
300 // TODO: handle timeouted shutdown
304 for (ListenerRegistration<SessionListener> listenerRegistration : sessionListeners) {
305 SessionListener listener = listenerRegistration.getInstance();
306 if (listener instanceof AutoCloseable) {
308 ((AutoCloseable) listener).close();
309 } catch (Exception e) {
310 LOG.warn("closing of sessionListenerRegistration failed", e);
317 public void setRpcPool(ListeningExecutorService rpcPool) {
318 this.rpcPool = rpcPool;
322 public ListeningExecutorService getRpcPool() {
327 public void setMessageSpy(MessageSpy<DataContainer> messageSpy) {
328 this.messageSpy = messageSpy;
332 public MessageSpy<DataContainer> getMessageSpy() {
337 public void setExtensionConverterProvider(
338 ExtensionConverterProvider extensionConverterProvider) {
339 this.extensionConverterProvider = extensionConverterProvider;
343 * @return the extensionConverterProvider
346 public ExtensionConverterProvider getExtensionConverterProvider() {
347 return extensionConverterProvider;
351 public Collection<SessionContext> getAllSessions() {
352 return sessionLot.values();