e4f6875b3e2dd9801270ec97a58c14bd6de29d13
[openflowplugin.git] / openflowplugin / src / main / java / org / opendaylight / openflowplugin / openflow / md / core / session / SessionManagerOFImpl.java
1 /**
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.openflowplugin.openflow.md.core.session;
10
11 import com.google.common.util.concurrent.ListeningExecutorService;
12 import java.util.Arrays;
13 import java.util.Collection;
14 import java.util.List;
15 import java.util.Map;
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.openflow.md.core.ConnectionConductor;
21 import org.opendaylight.openflowplugin.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.openflow.md.core.extension.ExtensionConverterProvider;
25 import org.opendaylight.openflowplugin.openflow.md.queue.PopListener;
26 import org.opendaylight.openflowplugin.api.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;
34
35 /**
36  * @author mirehak
37  */
38 public class SessionManagerOFImpl implements SessionManager {
39
40     protected static final Logger LOG = LoggerFactory.getLogger(SessionManagerOFImpl.class);
41     private static SessionManagerOFImpl instance;
42     private ConcurrentHashMap<SwitchSessionKeyOF, SessionContext> sessionLot;
43     private Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> translatorMapping;
44     private Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> popListenerMapping;
45
46     protected ListenerRegistry<SessionListener> sessionListeners;
47     private NotificationProviderService notificationProviderService;
48
49     private DataBroker dataBroker;
50     private ListeningExecutorService rpcPool;
51
52
53     /**
54      * @return singleton instance
55      */
56     public static SessionManager getInstance() {
57         if (instance == null) {
58             synchronized (SessionContextOFImpl.class) {
59                 if (instance == null) {
60                     instance = new SessionManagerOFImpl();
61                 }
62             }
63         }
64         return instance;
65     }
66
67     /**
68      * close and release singleton instace
69      */
70     public static void releaseInstance() {
71         if (instance != null) {
72             synchronized (SessionManagerOFImpl.class) {
73                 if (instance != null) {
74                     instance.close();
75                     instance = null;
76                 }
77             }
78         }
79     }
80
81     private SessionManagerOFImpl() {
82         LOG.debug("singleton creating");
83         sessionLot = new ConcurrentHashMap<>();
84         sessionListeners = new ListenerRegistry<>();
85     }
86
87     @Override
88     public SessionContext getSessionContext(SwitchSessionKeyOF sessionKey) {
89         return sessionLot.get(sessionKey);
90     }
91
92     @Override
93     public void invalidateSessionContext(SwitchSessionKeyOF sessionKey) {
94         SessionContext context = getSessionContext(sessionKey);
95         if (context == null) {
96             LOG.warn("context for invalidation not found");
97         } else {
98             for (Entry<SwitchConnectionDistinguisher, ConnectionConductor> auxEntry : context.getAuxiliaryConductors()) {
99                 invalidateAuxiliary(sessionKey, auxEntry.getKey());
100             }
101             context.getPrimaryConductor().disconnect();
102             context.setValid(false);
103             removeSessionContext(context);
104             // TODO:: notify listeners
105         }
106     }
107
108     private void invalidateDeadSessionContext(SessionContext sessionContext) {
109         if (sessionContext == null) {
110             LOG.warn("context for invalidation not found");
111         } else {
112             for (Entry<SwitchConnectionDistinguisher, ConnectionConductor> auxEntry : sessionContext
113                     .getAuxiliaryConductors()) {
114                 invalidateAuxiliary(sessionContext, auxEntry.getKey(), true);
115             }
116             sessionContext.setValid(false);
117             removeSessionContext(sessionContext);
118             // TODO:: notify listeners
119         }
120     }
121
122     private void removeSessionContext(SessionContext sessionContext) {
123         if (LOG.isDebugEnabled()) {
124             LOG.debug("removing session: {}", Arrays.toString(sessionContext.getSessionKey().getId()));
125         }
126         sessionLot.remove(sessionContext.getSessionKey(), sessionContext);
127         sessionNotifier.onSessionRemoved(sessionContext);
128     }
129
130     @Override
131     public void addSessionContext(SwitchSessionKeyOF sessionKey, SessionContext context) {
132         sessionLot.put(sessionKey, context);
133
134         sessionNotifier.onSessionAdded(sessionKey, context);
135
136     }
137
138     @Override
139     public void invalidateAuxiliary(SwitchSessionKeyOF sessionKey,
140                                     SwitchConnectionDistinguisher connectionCookie) {
141         SessionContext context = getSessionContext(sessionKey);
142         invalidateAuxiliary(context, connectionCookie, true);
143     }
144
145     /**
146      * @param context
147      * @param connectionCookie
148      * @param disconnect       true if auxiliary connection is to be disconnected
149      */
150     private static void invalidateAuxiliary(SessionContext context, SwitchConnectionDistinguisher connectionCookie,
151                                             boolean disconnect) {
152         if (context == null) {
153             LOG.warn("context for invalidation not found");
154         } else {
155             ConnectionConductor auxiliaryConductor = context.removeAuxiliaryConductor(connectionCookie);
156             if (auxiliaryConductor == null) {
157                 LOG.warn("auxiliary conductor not found");
158             } else {
159                 if (disconnect) {
160                     auxiliaryConductor.disconnect();
161                 }
162             }
163         }
164     }
165
166     @Override
167     public void invalidateOnDisconnect(ConnectionConductor conductor) {
168         if (conductor.getAuxiliaryKey() == null) {
169             invalidateDeadSessionContext(conductor.getSessionContext());
170             // TODO:: notify listeners
171         } else {
172             invalidateAuxiliary(conductor.getSessionContext(), conductor.getAuxiliaryKey(), false);
173         }
174     }
175
176     @Override
177     public void setTranslatorMapping(Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> translatorMapping) {
178         this.translatorMapping = translatorMapping;
179     }
180
181     @Override
182     public ListenerRegistration<SessionListener> registerSessionListener(SessionListener listener) {
183         LOG.debug("registerSessionListener");
184         return sessionListeners.register(listener);
185     }
186
187     private final SessionListener sessionNotifier = new SessionListener() {
188
189         @Override
190         public void onSessionAdded(SwitchSessionKeyOF sessionKey, SessionContext context) {
191             for (ListenerRegistration<SessionListener> listener : sessionListeners) {
192                 try {
193                     listener.getInstance().onSessionAdded(sessionKey, context);
194                 } catch (Exception e) {
195                     LOG.error("Unhandled exeption occured while invoking onSessionAdded on listener", e);
196                 }
197             }
198         }
199
200         @Override
201         public void onSessionRemoved(SessionContext context) {
202             for (ListenerRegistration<SessionListener> listener : sessionListeners) {
203                 try {
204                     listener.getInstance().onSessionRemoved(context);
205                 } catch (Exception e) {
206                     LOG.error("Unhandled exeption occured while invoking onSessionRemoved on listener", e);
207                 }
208             }
209         }
210     };
211     private MessageSpy<DataContainer> messageSpy;
212     private ExtensionConverterProvider extensionConverterProvider;
213
214
215     @Override
216     public Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> getTranslatorMapping() {
217         return this.translatorMapping;
218     }
219
220     @Override
221     public void setNotificationProviderService(
222             NotificationProviderService notificationProviderService) {
223         this.notificationProviderService = notificationProviderService;
224
225     }
226
227     @Override
228     public DataBroker getDataBroker() {
229         return dataBroker;
230     }
231
232     @Override
233     public void setDataBroker(DataBroker dataBroker) {
234         this.dataBroker = dataBroker;
235
236     }
237
238     @Override
239     public NotificationProviderService getNotificationProviderService() {
240         return notificationProviderService;
241     }
242
243     @Override
244     public Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> getPopListenerMapping() {
245         return popListenerMapping;
246     }
247
248     @Override
249     public void setPopListenerMapping(
250             Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> popListenerMapping) {
251         this.popListenerMapping = popListenerMapping;
252     }
253
254     @Override
255     public void close() {
256         LOG.debug("close");
257         sessionListeners = null;
258         synchronized (sessionLot) {
259             for (SessionContext sessionContext : sessionLot.values()) {
260                 sessionContext.getPrimaryConductor().disconnect();
261             }
262             // TODO: handle timeouted shutdown
263             rpcPool.shutdown();
264         }
265     }
266
267     @Override
268     public void setRpcPool(ListeningExecutorService rpcPool) {
269         this.rpcPool = rpcPool;
270     }
271
272     @Override
273     public ListeningExecutorService getRpcPool() {
274         return rpcPool;
275     }
276
277     @Override
278     public void setMessageSpy(MessageSpy<DataContainer> messageSpy) {
279         this.messageSpy = messageSpy;
280     }
281
282     @Override
283     public MessageSpy<DataContainer> getMessageSpy() {
284         return messageSpy;
285     }
286
287     @Override
288     public void setExtensionConverterProvider(
289             ExtensionConverterProvider extensionConverterProvider) {
290         this.extensionConverterProvider = extensionConverterProvider;
291     }
292
293     /**
294      * @return the extensionConverterProvider
295      */
296     @Override
297     public ExtensionConverterProvider getExtensionConverterProvider() {
298         return extensionConverterProvider;
299     }
300 }