Fix NPEs in HwvtepOperGlobalListener
[ovsdb.git] / hwvtepsouthbound / hwvtepsouthbound-impl / src / main / java / org / opendaylight / ovsdb / hwvtepsouthbound / HwvtepOperGlobalListener.java
1 /*
2  * Copyright (c) 2017 Ericsson India Global Services Pvt Ltd. 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.hwvtepsouthbound;
9
10 import java.util.Collection;
11 import java.util.Collections;
12 import java.util.Map;
13 import java.util.Objects;
14 import java.util.Timer;
15 import java.util.concurrent.ConcurrentHashMap;
16 import java.util.concurrent.ExecutionException;
17 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
20 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
21 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
22 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
23 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
24 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
25 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
26 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
27 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
28 import org.opendaylight.yangtools.concepts.ListenerRegistration;
29 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 public class HwvtepOperGlobalListener implements ClusteredDataTreeChangeListener<Node>, AutoCloseable {
34     private static final Logger LOG = LoggerFactory.getLogger(HwvtepOperGlobalListener.class);
35
36     private final Timer timer = new Timer();
37     private ListenerRegistration<HwvtepOperGlobalListener> registration;
38     private final HwvtepConnectionManager hcm;
39     private final DataBroker db;
40     private static final Map<InstanceIdentifier<Node>, Node> CONNECTED_NODES = new ConcurrentHashMap<>();
41
42     HwvtepOperGlobalListener(final DataBroker db, final HwvtepConnectionManager hcm) {
43         LOG.info("Registering HwvtepOperGlobalListener");
44         this.db = db;
45         this.hcm = hcm;
46         registerListener();
47     }
48
49     private void registerListener() {
50         final DataTreeIdentifier<Node> treeId =
51                         new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, getWildcardPath());
52
53         registration = db.registerDataTreeChangeListener(treeId, HwvtepOperGlobalListener.this);
54     }
55
56     @Override
57     public void close() {
58         if (registration != null) {
59             registration.close();
60         }
61     }
62
63     @Override
64     public void onDataTreeChanged(final Collection<DataTreeModification<Node>> changes) {
65         changes.forEach(change -> {
66             InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
67             DataObjectModification<Node> mod = change.getRootNode();
68             InstanceIdentifier<Node> nodeIid = change.getRootPath().getRootIdentifier();
69             Node node = getCreated(mod);
70             if (node != null) {
71                 CONNECTED_NODES.put(key, node);
72             }
73             node = getRemoved(mod);
74             if (node != null) {
75                 CONNECTED_NODES.remove(key);
76                 HwvtepConnectionInstance connectionInstance = hcm.getConnectionInstanceFromNodeIid(nodeIid);
77                 if (connectionInstance != null && Objects.equals(connectionInstance.getConnectionInfo().getRemotePort(),
78                             HwvtepSouthboundUtil.getRemotePort(node))) {
79                     //Oops some one deleted the node held by me This should never happen
80                     try {
81                         connectionInstance.refreshOperNode();
82                     } catch (ExecutionException | InterruptedException e) {
83                         LOG.error("Failed to refresh operational nodes ", e);
84                     }
85                 }
86
87             }
88         });
89     }
90
91     private static Node getCreated(final DataObjectModification<Node> mod) {
92         if (mod.getModificationType() == ModificationType.WRITE && mod.getDataBefore() == null) {
93             return mod.getDataAfter();
94         }
95         return null;
96     }
97
98     private static Node getRemoved(final DataObjectModification<Node> mod) {
99         if (mod.getModificationType() == ModificationType.DELETE) {
100             return mod.getDataBefore();
101         }
102         return null;
103     }
104
105     public Map<InstanceIdentifier<Node>, Node> getConnectedNodes() {
106         return Collections.unmodifiableMap(CONNECTED_NODES);
107     }
108
109     private static InstanceIdentifier<Node> getWildcardPath() {
110         return InstanceIdentifier.create(NetworkTopology.class)
111                 .child(Topology.class, new TopologyKey(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID))
112                 .child(Node.class);
113     }
114
115     public static Node getNode(final InstanceIdentifier<Node> key) {
116         return CONNECTED_NODES.get(key);
117     }
118 }