fix of BUG 434
[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.queue.PopListener;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
26 import org.opendaylight.yangtools.concepts.ListenerRegistration;
27 import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
28 import org.opendaylight.yangtools.yang.binding.DataObject;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 /**
33  * @author mirehak
34  */
35 public class SessionManagerOFImpl implements SessionManager {
36
37     protected static final Logger LOG = LoggerFactory.getLogger(SessionManagerOFImpl.class);
38     private static SessionManagerOFImpl instance;
39     private ConcurrentHashMap<SwitchConnectionDistinguisher, SessionContext> sessionLot;
40     private Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> translatorMapping;
41     private Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> popListenerMapping;
42
43
44     protected ListenerRegistry<SessionListener> sessionListeners;
45     private NotificationProviderService notificationProviderService;
46
47     private DataProviderService dataProviderService;
48
49     /**
50      * @return singleton instance
51      */
52     public static synchronized SessionManager getInstance() {
53         if (instance == null) {
54             instance = new SessionManagerOFImpl();
55         }
56         return instance;
57     }
58     
59     /**
60      * close and release singleton instace
61      */
62     public static synchronized void releaseInstance() {
63         instance.close();
64         instance = null;
65     }
66
67     private SessionManagerOFImpl() {
68         LOG.debug("singleton creating");
69         sessionLot = new ConcurrentHashMap<>();
70         sessionListeners = new ListenerRegistry<>();
71     }
72
73     @Override
74     public SessionContext getSessionContext(SwitchConnectionDistinguisher sessionKey) {
75         return sessionLot.get(sessionKey);
76     }
77
78     @Override
79     public void invalidateSessionContext(SwitchConnectionDistinguisher sessionKey) {
80         SessionContext context = getSessionContext(sessionKey);
81         if (context == null) {
82             LOG.warn("context for invalidation not found");
83         } else {
84             for (Entry<SwitchConnectionDistinguisher, ConnectionConductor> auxEntry : context.getAuxiliaryConductors()) {
85                 invalidateAuxiliary(sessionKey, auxEntry.getKey());
86             }
87             context.getPrimaryConductor().disconnect();
88             context.setValid(false);
89             removeSessionContext(context);
90             // TODO:: notify listeners
91         }
92     }
93
94     private void invalidateDeadSessionContext(SessionContext sessionContext) {
95         if (sessionContext == null) {
96             LOG.warn("context for invalidation not found");
97         } else {
98             for (Entry<SwitchConnectionDistinguisher, ConnectionConductor> auxEntry : sessionContext
99                     .getAuxiliaryConductors()) {
100                 invalidateAuxiliary(sessionContext, auxEntry.getKey(), true);
101             }
102             sessionContext.setValid(false);
103             removeSessionContext(sessionContext);
104             // TODO:: notify listeners
105         }
106     }
107
108     private void removeSessionContext(SessionContext sessionContext) {
109         if (LOG.isDebugEnabled()) {
110             LOG.debug("removing session: {}", Arrays.toString(sessionContext.getSessionKey().getId()));
111         }
112         sessionLot.remove(sessionContext.getSessionKey(), sessionContext);
113         sessionNotifier.onSessionRemoved(sessionContext);
114     }
115
116     @Override
117     public void addSessionContext(SwitchConnectionDistinguisher sessionKey, SessionContext context) {
118         sessionLot.put(sessionKey, context);
119
120         sessionNotifier.onSessionAdded(sessionKey, context);
121
122     }
123
124     @Override
125     public void invalidateAuxiliary(SwitchConnectionDistinguisher sessionKey,
126             SwitchConnectionDistinguisher connectionCookie) {
127         SessionContext context = getSessionContext(sessionKey);
128         invalidateAuxiliary(context, connectionCookie, true);
129     }
130
131     /**
132      * @param context
133      * @param connectionCookie
134      * @param disconnect
135      *            true if auxiliary connection is to be disconnected
136      */
137     private static void invalidateAuxiliary(SessionContext context, SwitchConnectionDistinguisher connectionCookie,
138             boolean disconnect) {
139         if (context == null) {
140             LOG.warn("context for invalidation not found");
141         } else {
142             ConnectionConductor auxiliaryConductor = context.removeAuxiliaryConductor(connectionCookie);
143             if (auxiliaryConductor == null) {
144                 LOG.warn("auxiliary conductor not found");
145             } else {
146                 if (disconnect) {
147                     auxiliaryConductor.disconnect();
148                 }
149             }
150         }
151     }
152
153     @Override
154     public void invalidateOnDisconnect(ConnectionConductor conductor) {
155         if (conductor.getAuxiliaryKey() == null) {
156             invalidateDeadSessionContext(conductor.getSessionContext());
157             // TODO:: notify listeners
158         } else {
159             invalidateAuxiliary(conductor.getSessionContext(), conductor.getAuxiliaryKey(), false);
160         }
161     }
162
163     @Override
164     public void setTranslatorMapping(Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> translatorMapping) {
165         this.translatorMapping = translatorMapping;
166     }
167
168     @Override
169     public ListenerRegistration<SessionListener> registerSessionListener(SessionListener listener) {
170         LOG.debug("registerSessionListener");
171         return sessionListeners.register(listener);
172     }
173
174     private final SessionListener sessionNotifier = new SessionListener() {
175
176         @Override
177         public void onSessionAdded(SwitchConnectionDistinguisher sessionKey, SessionContext context) {
178             for (ListenerRegistration<SessionListener> listener : sessionListeners) {
179                 try {
180                     listener.getInstance().onSessionAdded(sessionKey, context);
181                 } catch (Exception e) {
182                     LOG.error("Unhandled exeption occured while invoking onSessionAdded on listener", e);
183                 }
184             }
185         }
186
187         @Override
188         public void onSessionRemoved(SessionContext context) {
189             for (ListenerRegistration<SessionListener> listener : sessionListeners) {
190                 try {
191                     listener.getInstance().onSessionRemoved(context);
192                 } catch (Exception e) {
193                     LOG.error("Unhandled exeption occured while invoking onSessionRemoved on listener", e);
194                 }
195             }
196         }
197     };
198
199
200     @Override
201     public Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> getTranslatorMapping() {
202         return this.translatorMapping;
203     }
204
205     @Override
206     public void setNotificationProviderService(
207             NotificationProviderService notificationProviderService) {
208         this.notificationProviderService = notificationProviderService;
209
210     }
211
212     @Override
213     public DataProviderService getDataProviderService() {
214         return dataProviderService;
215     }
216
217     @Override
218     public void setDataProviderService(DataProviderService dataServiceProvider) {
219         this.dataProviderService = dataServiceProvider;
220
221     }
222
223     @Override
224     public NotificationProviderService getNotificationProviderService() {
225         return notificationProviderService;
226     }
227
228     @Override
229     public Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> getPopListenerMapping() {
230         return popListenerMapping;
231     }
232
233     @Override
234     public void setPopListenerMapping(
235             Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> popListenerMapping) {
236         this.popListenerMapping = popListenerMapping;
237     }
238     
239     @Override
240     public void close() {
241         LOG.debug("close");
242         sessionListeners = null;
243         synchronized (sessionLot) {
244             for (SessionContext sessionContext : sessionLot.values()) {
245                 sessionContext.getPrimaryConductor().disconnect();
246             }
247         }
248     }
249 }