Add UT for SouthboundMapper and SouthboundProvider
[netvirt.git] / openstack / net-virt / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / impl / NodeCacheManagerImpl.java
1 /*
2  * Copyright (c) 2015 Red Hat, 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 package org.opendaylight.ovsdb.openstack.netvirt.impl;
9
10 import java.util.List;
11 import java.util.Map;
12 import java.util.concurrent.ConcurrentHashMap;
13
14 import org.opendaylight.ovsdb.openstack.netvirt.AbstractEvent;
15 import org.opendaylight.ovsdb.openstack.netvirt.AbstractHandler;
16 import org.opendaylight.ovsdb.openstack.netvirt.ConfigInterface;
17 import org.opendaylight.ovsdb.openstack.netvirt.NodeCacheManagerEvent;
18 import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
19 import org.opendaylight.ovsdb.openstack.netvirt.api.EventDispatcher;
20 import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheListener;
21 import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheManager;
22 import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
23 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
24 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
25 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
26 import org.osgi.framework.BundleContext;
27 import org.osgi.framework.ServiceReference;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 import com.google.common.collect.Lists;
32 import com.google.common.collect.Maps;
33
34 /**
35  * @author Flavio Fernandes (ffernand@redhat.com)
36  * @author Sam Hague (shague@redhat.com)
37  */
38 public class NodeCacheManagerImpl extends AbstractHandler implements NodeCacheManager, ConfigInterface {
39     private static final Logger LOG = LoggerFactory.getLogger(NodeCacheManagerImpl.class);
40     private Map<NodeId, Node> nodeCache = new ConcurrentHashMap<>();
41     private Map<Long, NodeCacheListener> handlers = Maps.newHashMap();
42     private volatile Southbound southbound;
43
44     @Override
45     public void nodeAdded(Node node) {
46         LOG.debug("nodeAdded: {}", node);
47         enqueueEvent(new NodeCacheManagerEvent(node, Action.UPDATE));
48     }
49
50     @Override
51     public void nodeRemoved(Node node) {
52         LOG.debug("nodeRemoved: {}", node);
53         enqueueEvent(new NodeCacheManagerEvent(node, Action.DELETE));
54     }
55
56     // TODO SB_MIGRATION
57     // might need to break this into two different events
58     // notifyOvsdbNode, notifyBridgeNode or just make sure the
59     // classes implementing the interface check for ovsdbNode or bridgeNode
60     private void processNodeUpdate(Node node) {
61         Action action = Action.UPDATE;
62
63         NodeId nodeId = node.getNodeId();
64         if (nodeCache.get(nodeId) == null) {
65             action = Action.ADD;
66         }
67         nodeCache.put(nodeId, node);
68
69         LOG.debug("processNodeUpdate: {} Node type {} {}: {}",
70                 nodeCache.size(),
71                 southbound.getBridge(node) != null ? "BridgeNode" : "OvsdbNode",
72                 action == Action.ADD ? "ADD" : "UPDATE",
73                 node);
74
75         for (NodeCacheListener handler : handlers.values()) {
76             try {
77                 handler.notifyNode(node, action);
78             } catch (Exception e) {
79                 LOG.error("Failed notifying node add event", e);
80             }
81         }
82         LOG.debug("processNodeUpdate returns");
83     }
84
85     private void processNodeRemoved(Node node) {
86         nodeCache.remove(node.getNodeId());
87         for (NodeCacheListener handler : handlers.values()) {
88             try {
89                 handler.notifyNode(node, Action.DELETE);
90             } catch (Exception e) {
91                 LOG.error("Failed notifying node remove event", e);
92             }
93         }
94         LOG.warn("processNodeRemoved returns");
95     }
96
97     /**
98      * Process the event.
99      *
100      * @param abstractEvent the {@link org.opendaylight.ovsdb.openstack.netvirt.AbstractEvent} event to be handled.
101      * @see org.opendaylight.ovsdb.openstack.netvirt.api.EventDispatcher
102      */
103     @Override
104     public void processEvent(AbstractEvent abstractEvent) {
105         if (!(abstractEvent instanceof NodeCacheManagerEvent)) {
106             LOG.error("Unable to process abstract event {}", abstractEvent);
107             return;
108         }
109         NodeCacheManagerEvent ev = (NodeCacheManagerEvent) abstractEvent;
110         LOG.debug("NodeCacheManagerImpl: dequeue: {}", ev);
111         switch (ev.getAction()) {
112             case DELETE:
113                 processNodeRemoved(ev.getNode());
114                 break;
115             case UPDATE:
116                 processNodeUpdate(ev.getNode());
117                 break;
118             default:
119                 LOG.warn("Unable to process event action {}", ev.getAction());
120                 break;
121         }
122     }
123
124     public void cacheListenerAdded(final ServiceReference ref, NodeCacheListener handler){
125         Long pid = (Long) ref.getProperty(org.osgi.framework.Constants.SERVICE_ID);
126         handlers.put(pid, handler);
127         LOG.info("Node cache listener registered, pid {} {}", pid, handler.getClass().getName());
128     }
129
130     public void cacheListenerRemoved(final ServiceReference ref){
131         Long pid = (Long) ref.getProperty(org.osgi.framework.Constants.SERVICE_ID);
132         handlers.remove(pid);
133         LOG.debug("Node cache listener unregistered, pid {}", pid);
134     }
135
136     @Override
137     public Map<NodeId,Node> getOvsdbNodes() {
138         Map<NodeId,Node> ovsdbNodesMap = new ConcurrentHashMap<>();
139         for (Map.Entry<NodeId, Node> ovsdbNodeEntry : nodeCache.entrySet()) {
140             if (southbound.extractOvsdbNode(ovsdbNodeEntry.getValue()) != null) {
141                 ovsdbNodesMap.put(ovsdbNodeEntry.getKey(), ovsdbNodeEntry.getValue());
142             }
143         }
144         return ovsdbNodesMap;
145     }
146
147     @Override
148     public List<Node> getBridgeNodes() {
149         List<Node> nodes = Lists.newArrayList();
150         for (Node node : nodeCache.values()) {
151             if (southbound.getBridge(node) != null) {
152                 nodes.add(node);
153             }
154         }
155         return nodes;
156     }
157
158     @Override
159     public List<Node> getNodes() {
160         List<Node> nodes = Lists.newArrayList();
161         for (Node node : nodeCache.values()) {
162             nodes.add(node);
163         }
164         return nodes;
165     }
166
167     @Override
168     public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
169         southbound =
170                 (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
171         eventDispatcher =
172                 (EventDispatcher) ServiceHelper.getGlobalInstance(EventDispatcher.class, this);
173         eventDispatcher.eventHandlerAdded(
174                 bundleContext.getServiceReference(NodeCacheManager.class.getName()), this);
175     }
176
177     @Override
178     public void setDependencies(Object impl) {}
179 }