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