Merge "Parents pom distribution"
[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     private String containerName = null;
57
58     void setController(IController s) {
59         this.controller = s;
60     }
61
62     void unsetController(IController s) {
63         if (this.controller == s) {
64             this.controller = null;
65         }
66     }
67
68     /**
69      * Function called by the dependency manager when all the required
70      * dependencies are satisfied
71      *
72      */
73     @SuppressWarnings("rawtypes")
74     void init(Component c) {
75         logger.trace("INIT called!");
76
77         Dictionary props = c.getServiceProperties();
78         if (props != null) {
79             containerName = (String) props.get("containerName");
80             isDefaultContainer = containerName.equals(GlobalConstants.DEFAULT
81                     .toString());
82         }
83
84         nodeProps = new ConcurrentHashMap<Node, Map<String, Property>>();
85         nodeConnectorProps = new ConcurrentHashMap<NodeConnector, Map<String, Property>>();
86     }
87
88     /**
89      * Function called by the dependency manager when at least one dependency
90      * become unsatisfied or when the component is shutting down because for
91      * example bundle is being stopped.
92      *
93      */
94     void destroy() {
95         logger.trace("DESTROY called!");
96     }
97
98     /**
99      * Function called by dependency manager after "init ()" is called and after
100      * the services provided by the class are registered in the service registry
101      *
102      */
103     void start() {
104         logger.trace("START called!");
105     }
106
107     /**
108      * Function called by the dependency manager before the services exported by
109      * the component are unregistered, this will be followed by a "destroy ()"
110      * calls
111      *
112      */
113     void stop() {
114         logger.trace("STOP called!");
115     }
116
117     public void setPluginOutInventoryServices(IPluginOutInventoryService service) {
118         logger.trace("Got a service set request {}", service);
119         if (this.pluginOutInventoryServices != null) {
120             this.pluginOutInventoryServices.add(service);
121         }
122     }
123
124     public void unsetPluginOutInventoryServices(
125             IPluginOutInventoryService service) {
126         logger.trace("Got a service UNset request");
127         if (this.pluginOutInventoryServices != null) {
128             this.pluginOutInventoryServices.remove(service);
129         }
130     }
131
132     protected Node OFSwitchToNode(ISwitch sw) {
133         Node node = null;
134         Object id = sw.getId();
135
136         try {
137             node = new Node(NodeIDType.OPENFLOW, id);
138         } catch (ConstructionException e) {
139             logger.error("", e);
140         }
141
142         return node;
143     }
144
145     /**
146      * Retrieve nodes from openflow
147      */
148     @Override
149     public ConcurrentMap<Node, Map<String, Property>> getNodeProps() {
150         logger.debug("getNodePros for container {}", containerName);
151         return nodeProps;
152     }
153
154     @Override
155     public ConcurrentMap<NodeConnector, Map<String, Property>> getNodeConnectorProps(
156             Boolean refresh) {
157         if (nodeConnectorProps == null) {
158             return null;
159         }
160
161         if (isDefaultContainer && refresh) {
162             Map<Long, ISwitch> switches = controller.getSwitches();
163             for (ISwitch sw : switches.values()) {
164                 Map<NodeConnector, Set<Property>> ncProps = InventoryServiceHelper
165                         .OFSwitchToProps(sw);
166                 for (Map.Entry<NodeConnector, Set<Property>> entry : ncProps
167                         .entrySet()) {
168                     updateNodeConnector(entry.getKey(), UpdateType.ADDED,
169                             entry.getValue());
170                 }
171             }
172         }
173
174         return nodeConnectorProps;
175     }
176
177     @Override
178     public void updateNodeConnector(NodeConnector nodeConnector,
179             UpdateType type, Set<Property> props) {
180         logger.trace("updateNodeConnector {} type {}", nodeConnector,
181                 type.getName());
182         if (nodeConnectorProps == null) {
183             logger.trace("nodeConnectorProps is null");
184             return;
185         }
186
187         Map<String, Property> propMap = nodeConnectorProps.get(nodeConnector);
188         switch (type) {
189         case ADDED:
190         case CHANGED:
191             if (propMap == null) {
192                 propMap = new HashMap<String, Property>();
193             }
194             if (props != null) {
195                 for (Property prop : props) {
196                     propMap.put(prop.getName(), prop);
197                 }
198             }
199             nodeConnectorProps.put(nodeConnector, propMap);
200             break;
201         case REMOVED:
202             nodeConnectorProps.remove(nodeConnector);
203             break;
204         default:
205             return;
206         }
207
208         // update sal and discovery
209         synchronized (pluginOutInventoryServices) {
210             for (IPluginOutInventoryService service : pluginOutInventoryServices) {
211                 service.updateNodeConnector(nodeConnector, type, props);
212             }
213         }
214     }
215
216     private void addNode(Node node, Set<Property> props) {
217         if (nodeProps == null) {
218             return;
219         }
220
221         Set<Node> nodeSet = nodeProps.keySet();
222         if (((props == null) || props.isEmpty()) && (nodeSet != null)
223                 && nodeSet.contains(node)) {
224             // node already added
225             return;
226         }
227
228         logger.trace("addNode: {} added, props: {} for container {}",
229                 new Object[] { node, props, containerName });
230
231         // update local cache
232         Map<String, Property> propMap = nodeProps.get(node);
233         if (propMap == null) {
234             propMap = new HashMap<String, Property>();
235         }
236
237         if (props != null) {
238             for (Property prop : props) {
239                 propMap.put(prop.getName(), prop);
240             }
241         }
242         nodeProps.put(node, propMap);
243
244         // update sal
245         synchronized (pluginOutInventoryServices) {
246             for (IPluginOutInventoryService service : pluginOutInventoryServices) {
247                 service.updateNode(node, UpdateType.ADDED, props);
248             }
249         }
250     }
251
252     private void removeNode(Node node) {
253         logger.trace("{} removed", node);
254         if (nodeProps == null)
255             return;
256
257         // update local cache
258         nodeProps.remove(node);
259
260         Set<NodeConnector> removeSet = new HashSet<NodeConnector>();
261         for (NodeConnector nodeConnector : nodeConnectorProps.keySet()) {
262             if (nodeConnector.getNode().equals(node)) {
263                 removeSet.add(nodeConnector);
264             }
265         }
266         for (NodeConnector nodeConnector : removeSet) {
267             nodeConnectorProps.remove(nodeConnector);
268         }
269
270         // update sal
271         synchronized (pluginOutInventoryServices) {
272             for (IPluginOutInventoryService service : pluginOutInventoryServices) {
273                 service.updateNode(node, UpdateType.REMOVED, null);
274             }
275         }
276     }
277
278     private void updateNode(Node node, Set<Property> properties) {
279         logger.trace("{} updated, props: {}", node, properties);
280         if (nodeProps == null || !nodeProps.containsKey(node) ||
281                 properties == null || properties.isEmpty()) {
282             return;
283         }
284
285         // Update local cache with new properties
286         Set<Property> newProperties = new HashSet<Property>(properties.size());
287         Map<String, Property> propertyMap = nodeProps.get(node);
288         for (Property property : properties) {
289             String name = property.getName();
290             Property currentProperty = propertyMap.get(name);
291             if (!property.equals(currentProperty)) {
292                 propertyMap.put(name, property);
293                 newProperties.add(property);
294             }
295         }
296
297         // Update SAL if we got new properties
298         if (!newProperties.isEmpty()) {
299             synchronized (pluginOutInventoryServices) {
300                 for (IPluginOutInventoryService service : pluginOutInventoryServices) {
301                     service.updateNode(node, UpdateType.CHANGED, newProperties);
302                 }
303             }
304         }
305     }
306
307     @Override
308     public void updateNode(Node node, UpdateType type, Set<Property> props) {
309         switch (type) {
310         case ADDED:
311             addNode(node, props);
312             break;
313         case REMOVED:
314             removeNode(node);
315             break;
316         case CHANGED:
317             updateNode(node, props);
318             break;
319         default:
320             break;
321         }
322     }
323
324 }