ec6ea1223e71f6103fcfef6aecb655c1108e6179
[controller.git] / opendaylight / protocol_plugins / openflow / src / main / java / org / opendaylight / controller / protocol_plugin / openflow / internal / InventoryService.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.controller.protocol_plugin.openflow.internal;
10
11 import java.util.Collections;
12 import java.util.Date;
13 import java.util.Dictionary;
14 import java.util.HashMap;
15 import java.util.HashSet;
16 import java.util.Map;
17 import java.util.Set;
18 import java.util.concurrent.ConcurrentHashMap;
19 import java.util.concurrent.ConcurrentMap;
20
21 import org.apache.felix.dm.Component;
22 import org.opendaylight.controller.protocol_plugin.openflow.IInventoryProvider;
23 import org.opendaylight.controller.protocol_plugin.openflow.IInventoryShimInternalListener;
24 import org.opendaylight.controller.protocol_plugin.openflow.core.IController;
25 import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitch;
26 import org.opendaylight.controller.sal.core.ConstructionException;
27 import org.opendaylight.controller.sal.core.Node;
28 import org.opendaylight.controller.sal.core.Node.NodeIDType;
29 import org.opendaylight.controller.sal.core.NodeConnector;
30 import org.opendaylight.controller.sal.core.Property;
31 import org.opendaylight.controller.sal.core.UpdateType;
32 import org.opendaylight.controller.sal.inventory.IPluginInInventoryService;
33 import org.opendaylight.controller.sal.inventory.IPluginOutInventoryService;
34 import org.opendaylight.controller.sal.utils.GlobalConstants;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 /**
39  * The class describes inventory service protocol plugin. One instance per
40  * container of the network. Each instance gets container specific inventory
41  * events from InventoryServiceShim. It interacts with SAL to pass inventory
42  * data to the upper application.
43  *
44  *
45  */
46 public class InventoryService implements IInventoryShimInternalListener,
47         IPluginInInventoryService, IInventoryProvider {
48     protected static final Logger logger = LoggerFactory
49             .getLogger(InventoryService.class);
50     private Set<IPluginOutInventoryService> pluginOutInventoryServices = Collections
51             .synchronizedSet(new HashSet<IPluginOutInventoryService>());
52     private IController controller = null;
53     private ConcurrentMap<Node, Map<String, Property>> nodeProps; // properties are maintained in global container only
54     private ConcurrentMap<NodeConnector, Map<String, Property>> nodeConnectorProps; // properties are maintained in global container only
55     private boolean isDefaultContainer = false;
56
57     void setController(IController s) {
58         this.controller = s;
59     }
60
61     void unsetController(IController s) {
62         if (this.controller == s) {
63             this.controller = null;
64         }
65     }
66
67     /**
68      * Function called by the dependency manager when all the required
69      * dependencies are satisfied
70      *
71      */
72     @SuppressWarnings("rawtypes")
73     void init(Component c) {
74         logger.trace("INIT called!");
75
76         Dictionary props = c.getServiceProperties();
77         if (props != null) {
78             String containerName = (String) props.get("containerName");
79             isDefaultContainer = containerName.equals(GlobalConstants.DEFAULT
80                     .toString());
81         }
82
83         nodeProps = new ConcurrentHashMap<Node, Map<String, Property>>();
84         nodeConnectorProps = new ConcurrentHashMap<NodeConnector, Map<String, Property>>();
85     }
86
87     /**
88      * Function called by the dependency manager when at least one dependency
89      * become unsatisfied or when the component is shutting down because for
90      * example bundle is being stopped.
91      *
92      */
93     void destroy() {
94         logger.trace("DESTROY called!");
95     }
96
97     /**
98      * Function called by dependency manager after "init ()" is called and after
99      * the services provided by the class are registered in the service registry
100      *
101      */
102     void start() {
103         logger.trace("START called!");
104     }
105
106     /**
107      * Function called by the dependency manager before the services exported by
108      * the component are unregistered, this will be followed by a "destroy ()"
109      * calls
110      *
111      */
112     void stop() {
113         logger.trace("STOP called!");
114     }
115
116     public void setPluginOutInventoryServices(IPluginOutInventoryService service) {
117         logger.trace("Got a service set request {}", service);
118         if (this.pluginOutInventoryServices != null) {
119             this.pluginOutInventoryServices.add(service);
120         }
121     }
122
123     public void unsetPluginOutInventoryServices(
124             IPluginOutInventoryService service) {
125         logger.trace("Got a service UNset request");
126         if (this.pluginOutInventoryServices != null) {
127             this.pluginOutInventoryServices.remove(service);
128         }
129     }
130
131     protected Node OFSwitchToNode(ISwitch sw) {
132         Node node = null;
133         Object id = sw.getId();
134
135         try {
136             node = new Node(NodeIDType.OPENFLOW, id);
137         } catch (ConstructionException e) {
138             logger.error("", e);
139         }
140
141         return node;
142     }
143
144     /**
145      * Retrieve nodes from openflow
146      */
147     @Override
148     public ConcurrentMap<Node, Map<String, Property>> getNodeProps() {
149         return nodeProps;
150     }
151
152     @Override
153     public ConcurrentMap<NodeConnector, Map<String, Property>> getNodeConnectorProps(
154             Boolean refresh) {
155         if (nodeConnectorProps == null) {
156             return null;
157         }
158
159         if (isDefaultContainer && refresh) {
160             Map<Long, ISwitch> switches = controller.getSwitches();
161             for (ISwitch sw : switches.values()) {
162                 Map<NodeConnector, Set<Property>> ncProps = InventoryServiceHelper
163                         .OFSwitchToProps(sw);
164                 for (Map.Entry<NodeConnector, Set<Property>> entry : ncProps
165                         .entrySet()) {
166                     updateNodeConnector(entry.getKey(), UpdateType.ADDED,
167                             entry.getValue());
168                 }
169             }
170         }
171
172         return nodeConnectorProps;
173     }
174
175     @Override
176     public void updateNodeConnector(NodeConnector nodeConnector,
177             UpdateType type, Set<Property> props) {
178         logger.trace("updateNodeConnector {} type {}", nodeConnector,
179                 type.getName());
180         if (nodeConnectorProps == null) {
181             logger.trace("nodeConnectorProps is null");
182             return;
183         }
184
185         Map<String, Property> propMap = nodeConnectorProps.get(nodeConnector);
186         switch (type) {
187         case ADDED:
188         case CHANGED:
189             if (propMap == null) {
190                 propMap = new HashMap<String, Property>();
191             }
192             if (props != null) {
193                 for (Property prop : props) {
194                     propMap.put(prop.getName(), prop);
195                 }
196             }
197             nodeConnectorProps.put(nodeConnector, propMap);
198             break;
199         case REMOVED:
200             nodeConnectorProps.remove(nodeConnector);
201             break;
202         default:
203             return;
204         }
205
206         // update sal and discovery
207         synchronized (pluginOutInventoryServices) {
208             for (IPluginOutInventoryService service : pluginOutInventoryServices) {
209                 service.updateNodeConnector(nodeConnector, type, props);
210             }
211         }
212     }
213
214     private void addNode(Node node, Set<Property> props) {
215         logger.trace("{} added, props: {}", node, props);
216         if (nodeProps == null) {
217             return;
218         }
219
220         // update local cache
221         Map<String, Property> propMap = new HashMap<String, Property>();
222         for (Property prop : props) {
223             propMap.put(prop.getName(), prop);
224         }
225         nodeProps.put(node, propMap);
226
227         // update sal
228         synchronized (pluginOutInventoryServices) {
229             for (IPluginOutInventoryService service : pluginOutInventoryServices) {
230                 service.updateNode(node, UpdateType.ADDED, props);
231             }
232         }
233     }
234
235     private void removeNode(Node node) {
236         logger.trace("{} removed", node);
237         if (nodeProps == null)
238             return;
239
240         // update local cache
241         nodeProps.remove(node);
242
243         Set<NodeConnector> removeSet = new HashSet<NodeConnector>();
244         for (NodeConnector nodeConnector : nodeConnectorProps.keySet()) {
245             if (nodeConnector.getNode().equals(node)) {
246                 removeSet.add(nodeConnector);
247             }
248         }
249         for (NodeConnector nodeConnector : removeSet) {
250             nodeConnectorProps.remove(nodeConnector);
251         }
252
253         // update sal
254         synchronized (pluginOutInventoryServices) {
255             for (IPluginOutInventoryService service : pluginOutInventoryServices) {
256                 service.updateNode(node, UpdateType.REMOVED, null);
257             }
258         }
259     }
260
261     private void updateNode(Node node, Set<Property> properties) {
262         logger.trace("{} updated, props: {}", node, properties);
263         if (nodeProps == null || !nodeProps.containsKey(node) ||
264                 properties == null || properties.isEmpty()) {
265             return;
266         }
267
268         // Update local cache with new properties
269         Set<Property> newProperties = new HashSet<Property>(properties.size());
270         Map<String, Property> propertyMap = nodeProps.get(node);
271         for (Property property : properties) {
272             String name = property.getName();
273             Property currentProperty = propertyMap.get(name);
274             if (!property.equals(currentProperty)) {
275                 propertyMap.put(name, property);
276                 newProperties.add(property);
277             }
278         }
279
280         // Update SAL if we got new properties
281         if (!newProperties.isEmpty()) {
282             synchronized (pluginOutInventoryServices) {
283                 for (IPluginOutInventoryService service : pluginOutInventoryServices) {
284                     service.updateNode(node, UpdateType.CHANGED, newProperties);
285                 }
286             }
287         }
288     }
289
290     @Override
291     public void updateNode(Node node, UpdateType type, Set<Property> props) {
292         switch (type) {
293         case ADDED:
294             addNode(node, props);
295             break;
296         case REMOVED:
297             removeNode(node);
298             break;
299         case CHANGED:
300             updateNode(node, props);
301             break;
302         default:
303             break;
304         }
305     }
306
307 }