OVSDB-438: missing operational node
[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
9 package org.opendaylight.ovsdb.hwvtepsouthbound;
10
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.Collections;
14 import java.util.HashSet;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Objects;
18 import java.util.Set;
19 import java.util.Timer;
20 import java.util.TimerTask;
21 import java.util.concurrent.Callable;
22 import java.util.concurrent.ConcurrentHashMap;
23 import java.util.concurrent.ExecutionException;
24
25 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
26 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
27 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
28 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
29 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
30 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
31 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
32 import org.opendaylight.ovsdb.lib.message.TableUpdates;
33 import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
35 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
36 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
37 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
38 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
39 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
40 import org.opendaylight.yangtools.concepts.ListenerRegistration;
41 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
42 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 public class HwvtepOperGlobalListener implements ClusteredDataTreeChangeListener<Node>, AutoCloseable {
47
48     private static final Logger LOG = LoggerFactory.getLogger(HwvtepOperGlobalListener.class);
49
50     private Timer timer = new Timer();
51     private ListenerRegistration<HwvtepOperGlobalListener> registration;
52     private HwvtepConnectionManager hcm;
53     private DataBroker db;
54     private Map<YangInstanceIdentifier, Node> connectedNodes = new ConcurrentHashMap<>();
55
56     HwvtepOperGlobalListener(DataBroker db, HwvtepConnectionManager hcm) {
57         LOG.info("Registering HwvtepOperGlobalListener");
58         this.db = db;
59         this.hcm = hcm;
60         registerListener(db);
61     }
62
63     private void registerListener(final DataBroker db) {
64         final DataTreeIdentifier<Node> treeId =
65                         new DataTreeIdentifier<Node>(LogicalDatastoreType.OPERATIONAL, getWildcardPath());
66         try {
67             registration = db.registerDataTreeChangeListener(treeId, HwvtepOperGlobalListener.this);
68         } catch (final Exception e) {
69             LOG.error("HwvtepDataChangeListener registration failed", e);
70         }
71     }
72
73     @Override
74     public void close() throws Exception {
75         if(registration != null) {
76             registration.close();
77         }
78     }
79
80     @Override
81     public void onDataTreeChanged(Collection<DataTreeModification<Node>> changes) {
82         changes.forEach( (change) -> {
83             InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
84             DataObjectModification<Node> mod = change.getRootNode();
85             InstanceIdentifier<Node> nodeIid = change.getRootPath().getRootIdentifier();
86             YangInstanceIdentifier entityId =
87                     HwvtepSouthboundUtil.getInstanceIdentifierCodec().getYangInstanceIdentifier(nodeIid);
88             Node node = getCreated(mod);
89             if (node != null) {
90                 connectedNodes.put(entityId, node);
91             }
92             node = getRemoved(mod);
93             if (node != null) {
94                 connectedNodes.remove(entityId);
95                 HwvtepConnectionInstance connectionInstance = hcm.getConnectionInstanceFromNodeIid(nodeIid);
96                 if (Objects.equals(connectionInstance.getConnectionInfo().getRemotePort(),
97                         HwvtepSouthboundUtil.getRemotePort(node))) {
98                     //Oops some one deleted the node held by me This should never happen
99                     try {
100                         connectionInstance.refreshOperNode();
101                     } catch (ExecutionException | InterruptedException e) {
102                         LOG.error("Failed to refresh operational nodes ", e);
103                     }
104                 }
105
106             }
107         });
108     }
109
110     private Node getCreated(DataObjectModification<Node> mod) {
111         if((mod.getModificationType() == ModificationType.WRITE)
112                         && (mod.getDataBefore() == null)){
113             return mod.getDataAfter();
114         }
115         return null;
116     }
117
118     private Node getRemoved(DataObjectModification<Node> mod) {
119         if(mod.getModificationType() == ModificationType.DELETE){
120             return mod.getDataBefore();
121         }
122         return null;
123     }
124
125     public Map<YangInstanceIdentifier, Node> getConnectedNodes() {
126         return Collections.unmodifiableMap(connectedNodes);
127     }
128
129     private InstanceIdentifier<Node> getWildcardPath() {
130         InstanceIdentifier<Node> path = InstanceIdentifier
131                         .create(NetworkTopology.class)
132                         .child(Topology.class, new TopologyKey(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID))
133                         .child(Node.class);
134         return path;
135     }
136 }