Fix checkstyle violations
[l2switch.git] / loopremover / implementation / src / main / java / org / opendaylight / l2switch / loopremover / topology / TopologyLinkDataChangeHandler.java
index eb28bdbbc475e260ee49a68b3722527f99ae8fe7..6b5dbf4ce300147b8533156fdaeced7f9729ffdb 100644 (file)
@@ -9,22 +9,27 @@ package org.opendaylight.l2switch.loopremover.topology;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.l2switch.loopremover.util.InstanceIdentifierUtils;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2switch.loopremover.rev140714.StpStatus;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2switch.loopremover.rev140714.StpStatusAwareNodeConnector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2switch.loopremover.rev140714.StpStatusAwareNodeConnectorBuilder;
@@ -34,324 +39,283 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
 /**
- * Listens to data change events on topology links
- * {@link org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link}
+ * Listens to data change events on topology links {@link
+ * org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link}
  * and maintains a topology graph using provided NetworkGraphService
  * {@link org.opendaylight.l2switch.loopremover.topology.NetworkGraphService}.
- * It refreshes the graph after a delay(default 10 sec) to accommodate burst of change events if they come in bulk.
- * This is to avoid continuous refresh of graph on a series of change events in short time.
+ * It refreshes the graph after a delay(default 10 sec) to accommodate burst of
+ * change events if they come in bulk. This is to avoid continuous refresh of
+ * graph on a series of change events in short time.
  */
-public class TopologyLinkDataChangeHandler implements DataChangeListener {
-  private static final Logger _logger = LoggerFactory.getLogger(TopologyLinkDataChangeHandler.class);
-  private static final String DEFAULT_TOPOLOGY_ID = "flow:1";
-
-  private final ExecutorService topologyDataChangeEventProcessor = Executors.newFixedThreadPool(1);
-
-  private final NetworkGraphService networkGraphService;
-  private final DataBroker dataBroker;
-  boolean doneOnce = false;
-
-  /**
-   * Uses default delay to refresh topology graph if this constructor is used.
-   *
-   * @param dataBroker
-   * @param networkGraphService
-   */
-  public TopologyLinkDataChangeHandler(DataBroker dataBroker, NetworkGraphService networkGraphService) {
-    Preconditions.checkNotNull(dataBroker, "dataBroker should not be null.");
-    Preconditions.checkNotNull(networkGraphService, "networkGraphService should not be null.");
-    this.dataBroker = dataBroker;
-    this.networkGraphService = networkGraphService;
-  }
-
-  /**
-   * Registers as a data listener to receive changes done to
-   * {@link org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link}
-   * under {@link org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology}
-   * operation data root.
-   */
-
-  public ListenerRegistration<DataChangeListener> registerAsDataChangeListener() {
-    InstanceIdentifier<Link> linkInstance = InstanceIdentifier.builder(NetworkTopology.class)
-        .child(Topology.class, new TopologyKey(new TopologyId(DEFAULT_TOPOLOGY_ID))).child(Link.class).toInstance();
-    return dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, linkInstance, this, AsyncDataBroker.DataChangeScope.BASE);
-  }
-
-  @Override
-  public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> instanceIdentifierDataObjectAsyncDataChangeEvent) {
-    if(instanceIdentifierDataObjectAsyncDataChangeEvent == null) {
-      return;
+public class TopologyLinkDataChangeHandler implements DataTreeChangeListener<Link> {
+    private static final Logger LOG = LoggerFactory.getLogger(TopologyLinkDataChangeHandler.class);
+    private static final String DEFAULT_TOPOLOGY_ID = "flow:1";
+    private static final long DEFAULT_GRAPH_REFRESH_DELAY = 1000;
+
+    private final ScheduledExecutorService topologyDataChangeEventProcessor = Executors.newScheduledThreadPool(1);
+
+    private final NetworkGraphService networkGraphService;
+    private volatile boolean networkGraphRefreshScheduled = false;
+    private volatile boolean threadReschedule = false;
+    private long graphRefreshDelay;
+    private String topologyId;
+
+    private final DataBroker dataBroker;
+
+    public TopologyLinkDataChangeHandler(DataBroker dataBroker, NetworkGraphService networkGraphService) {
+        Preconditions.checkNotNull(dataBroker, "dataBroker should not be null.");
+        Preconditions.checkNotNull(networkGraphService, "networkGraphService should not be null.");
+        this.dataBroker = dataBroker;
+        this.networkGraphService = networkGraphService;
     }
 
-    topologyDataChangeEventProcessor.submit(new TopologyDataChangeEventProcessor(instanceIdentifierDataObjectAsyncDataChangeEvent));
-    _logger.info("************After topologyDataChangeEventProcessor called ");
-  }
-
-  /**
-   *
-   */
-  private class TopologyDataChangeEventProcessor implements Runnable {
-    AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> instanceIdentifierDataObjectAsyncDataChangeEvent;
-
-
-    public TopologyDataChangeEventProcessor(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> dataChangeEvent) {
-      this.instanceIdentifierDataObjectAsyncDataChangeEvent = dataChangeEvent;
-    }
-
-    @Override
-    public void run() {
-
-      if(instanceIdentifierDataObjectAsyncDataChangeEvent == null) {
-        return;
-      }
-      Map<InstanceIdentifier<?>, DataObject> createdData = instanceIdentifierDataObjectAsyncDataChangeEvent.getCreatedData();
-      Set<InstanceIdentifier<?>> removedPaths = instanceIdentifierDataObjectAsyncDataChangeEvent.getRemovedPaths();
-      Map<InstanceIdentifier<?>, DataObject> originalData = instanceIdentifierDataObjectAsyncDataChangeEvent.getOriginalData();
-      boolean isGraphUpdated = false;
-      ReadWriteTransaction readWriteTransaction = null;
-
-      _logger.info("Topology Event Started********************** ");
-      if(createdData != null && !createdData.isEmpty()) {
-        List<Link> links = new ArrayList<>();
-        for(InstanceIdentifier<?> instanceId : createdData.keySet()) {
-          if(Link.class.isAssignableFrom(instanceId.getTargetType())) {
-            links.add((Link) createdData.get(instanceId));
-          }
-        }
-        if(!links.isEmpty()) {
-          networkGraphService.addLinks(links);
-          isGraphUpdated = true;
-        }
-      }
-
-      List<Link> removedLinks = null;
-      if(removedPaths != null && !removedPaths.isEmpty() && originalData != null && !originalData.isEmpty()) {
-        removedLinks = new ArrayList<>();
-        for(InstanceIdentifier<?> instanceId : removedPaths) {
-          if(Link.class.isAssignableFrom(instanceId.getTargetType())) {
-            Link link = (Link) originalData.get(instanceId);
-            removedLinks.add(link);
-          }
-        }
-        if(!removedLinks.isEmpty()) {
-          networkGraphService.removeLinks(removedLinks);
-          isGraphUpdated = true;
-        }
-      }
-
-      if(isGraphUpdated) {
-        readWriteTransaction = dataBroker.newReadWriteTransaction();
-        if(removedLinks != null && !removedLinks.isEmpty()) {
-          for(Link link : removedLinks) {
-            updateNodeConnector(readWriteTransaction, getSourceNodeConnectorRef(link), StpStatus.Discarding);
-            updateNodeConnector(readWriteTransaction, getDestNodeConnectorRef(link), StpStatus.Discarding);
-          }
+    public void setGraphRefreshDelay(long graphRefreshDelay) {
+        if (graphRefreshDelay < 0) {
+            this.graphRefreshDelay = DEFAULT_GRAPH_REFRESH_DELAY;
+        } else {
+            this.graphRefreshDelay = graphRefreshDelay;
         }
-        updateNodeConnectorStatus(readWriteTransaction);
-        readWriteTransaction.commit();
-      }
     }
 
-    /**
-     * @param readWriteTransaction
-     */
-    private void updateNodeConnectorStatus(ReadWriteTransaction readWriteTransaction) {
-      List<Link> allLinks = networkGraphService.getAllLinks();
-      if(allLinks == null || allLinks.isEmpty()) {
-        return;
-      }
-
-      List<Link> mstLinks = networkGraphService.getLinksInMst();
-      for(Link link : allLinks) {
-        if(mstLinks != null && !mstLinks.isEmpty() && mstLinks.contains(link)) {
-          updateNodeConnector(readWriteTransaction, getSourceNodeConnectorRef(link), StpStatus.Forwarding);
-          updateNodeConnector(readWriteTransaction, getDestNodeConnectorRef(link), StpStatus.Forwarding);
+    public void setTopologyId(String topologyId) {
+        if (topologyId == null || topologyId.isEmpty()) {
+            this.topologyId = DEFAULT_TOPOLOGY_ID;
         } else {
-          updateNodeConnector(readWriteTransaction, getSourceNodeConnectorRef(link), StpStatus.Discarding);
-          updateNodeConnector(readWriteTransaction, getDestNodeConnectorRef(link), StpStatus.Discarding);
+            this.topologyId = topologyId;
         }
-      }
     }
 
     /**
-     * @param link
-     * @return
+     * Registers as a data listener to receive changes done to {@link org.opendaylight.yang.gen.v1.urn.tbd.params
+     * .xml.ns.yang.network.topology.rev131021.network.topology.topology.Link}
+     * under
+     * {@link org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology}
+     * operation data root.
      */
-    private NodeConnectorRef getSourceNodeConnectorRef(Link link) {
-      InstanceIdentifier<NodeConnector> nodeConnectorInstanceIdentifier
-          = InstanceIdentifierUtils.createNodeConnectorIdentifier(
-          link.getSource().getSourceNode().getValue(),
-          link.getSource().getSourceTp().getValue());
-      return new NodeConnectorRef(nodeConnectorInstanceIdentifier);
+    public ListenerRegistration<TopologyLinkDataChangeHandler> registerAsDataChangeListener() {
+        InstanceIdentifier<Link> linkInstance = InstanceIdentifier.builder(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(new TopologyId(topologyId))).child(Link.class).build();
+        return dataBroker.registerDataTreeChangeListener(new DataTreeIdentifier<>(
+                LogicalDatastoreType.OPERATIONAL, linkInstance), this);
     }
 
     /**
-     * @param link
-     * @return
+     * Handler for onDataChanged events and schedules the building of the
+     * network graph.
      */
-    private NodeConnectorRef getDestNodeConnectorRef(Link link) {
-      InstanceIdentifier<NodeConnector> nodeConnectorInstanceIdentifier
-          = InstanceIdentifierUtils.createNodeConnectorIdentifier(
-          link.getDestination().getDestNode().getValue(),
-          link.getDestination().getDestTp().getValue());
-
-      return new NodeConnectorRef(nodeConnectorInstanceIdentifier);
-    }
+    @Override
+    public void onDataTreeChanged(Collection<DataTreeModification<Link>> changes) {
+        boolean isGraphUpdated = false;
+
+        for (DataTreeModification<Link> change: changes) {
+            DataObjectModification<Link> rootNode = change.getRootNode();
+            switch (rootNode.getModificationType()) {
+                case WRITE:
+                    Link createdLink = rootNode.getDataAfter();
+                    if (rootNode.getDataBefore() == null && !createdLink.getLinkId().getValue().contains("host")) {
+                        isGraphUpdated = true;
+                        LOG.debug("Graph is updated! Added Link {}", createdLink.getLinkId().getValue());
+                    }
+                    break;
+                case DELETE:
+                    Link deletedLink = rootNode.getDataBefore();
+                    if (!deletedLink.getLinkId().getValue().contains("host")) {
+                        isGraphUpdated = true;
+                        LOG.debug("Graph is updated! Removed Link {}", deletedLink.getLinkId().getValue());
+                        break;
+                    }
+                    break;
+                default:
+                    break;
+            }
+        }
 
-    /**
-     * @param readWriteTransaction
-     * @param nodeConnectorRef
-     * @param stpStatus
-     */
-    private void updateNodeConnector(ReadWriteTransaction readWriteTransaction, NodeConnectorRef nodeConnectorRef, StpStatus stpStatus) {
-      StpStatusAwareNodeConnectorBuilder stpStatusAwareNodeConnectorBuilder = new StpStatusAwareNodeConnectorBuilder()
-          .setStatus(stpStatus);
-      checkIfExistAndUpdateNodeConnector(readWriteTransaction, nodeConnectorRef, stpStatusAwareNodeConnectorBuilder.build());
+        if (!isGraphUpdated) {
+            return;
+        }
+        if (!networkGraphRefreshScheduled) {
+            synchronized (this) {
+                if (!networkGraphRefreshScheduled) {
+                    topologyDataChangeEventProcessor.schedule(new TopologyDataChangeEventProcessor(), graphRefreshDelay,
+                            TimeUnit.MILLISECONDS);
+                    networkGraphRefreshScheduled = true;
+                    LOG.debug("Scheduled Graph for refresh.");
+                }
+            }
+        } else {
+            LOG.debug("Already scheduled for network graph refresh.");
+            threadReschedule = true;
+        }
     }
 
-    /**
-     * @param readWriteTransaction
-     * @param nodeConnectorRef
-     * @param stpStatusAwareNodeConnector
-     */
-    private void checkIfExistAndUpdateNodeConnector(ReadWriteTransaction readWriteTransaction, NodeConnectorRef nodeConnectorRef, StpStatusAwareNodeConnector stpStatusAwareNodeConnector) {
-      NodeConnector nc = null;
-      try {
-        Optional<DataObject> dataObjectOptional = readWriteTransaction.read(LogicalDatastoreType.CONFIGURATION, nodeConnectorRef.getValue()).get();
-        if(dataObjectOptional.isPresent())
-          nc = (NodeConnector) dataObjectOptional.get();
-      } catch(Exception e) {
-        _logger.error("Error reading node connector {}", nodeConnectorRef.getValue());
-        readWriteTransaction.commit();
-        throw new RuntimeException("Error reading from configuration store, node connector : " + nodeConnectorRef, e);
-      }
-      NodeConnectorBuilder nodeConnectorBuilder;
-      if(nc != null) {
-        if(sameStatusPresent(nc.getAugmentation(StpStatusAwareNodeConnector.class), stpStatusAwareNodeConnector.getStatus())) {
-          return;
+    private class TopologyDataChangeEventProcessor implements Runnable {
+
+        @Override
+        public void run() {
+            if (threadReschedule) {
+                topologyDataChangeEventProcessor.schedule(this, graphRefreshDelay, TimeUnit.MILLISECONDS);
+                threadReschedule = false;
+                return;
+            }
+            LOG.debug("In network graph refresh thread.");
+            networkGraphRefreshScheduled = false;
+            networkGraphService.clear();
+            List<Link> links = getLinksFromTopology();
+            if (links == null || links.isEmpty()) {
+                return;
+            }
+            networkGraphService.addLinks(links);
+            final ReadWriteTransaction readWriteTransaction = dataBroker.newReadWriteTransaction();
+            updateNodeConnectorStatus(readWriteTransaction);
+            Futures.addCallback(readWriteTransaction.submit(), new FutureCallback<Void>() {
+                @Override
+                public void onSuccess(Void notUsed) {
+                    LOG.debug("TopologyLinkDataChangeHandler write successful for tx :{}",
+                            readWriteTransaction.getIdentifier());
+                }
+
+                @Override
+                public void onFailure(Throwable throwable) {
+                    LOG.error("TopologyLinkDataChangeHandler write transaction {} failed",
+                            readWriteTransaction.getIdentifier(), throwable.getCause());
+                }
+            }, MoreExecutors.directExecutor());
+            LOG.debug("Done with network graph refresh thread.");
         }
-        nodeConnectorBuilder = new NodeConnectorBuilder(nc)
-            .setKey(nc.getKey())
-            .addAugmentation(StpStatusAwareNodeConnector.class, stpStatusAwareNodeConnector);
-        readWriteTransaction.put(LogicalDatastoreType.CONFIGURATION, nodeConnectorRef.getValue(), nodeConnectorBuilder.build());
-        _logger.info("Updated node connector in configuration {}", nodeConnectorRef);
-      } else {
 
-        NodeConnectorKey nodeConnectorKey = InstanceIdentifierUtils.getNodeConnectorKey(nodeConnectorRef.getValue());
-        nodeConnectorBuilder = new NodeConnectorBuilder()
-            .setKey(nodeConnectorKey)
-            .setId(nodeConnectorKey.getId())
-            .addAugmentation(StpStatusAwareNodeConnector.class, stpStatusAwareNodeConnector);
-        nc = nodeConnectorBuilder.build();
-        checkIfExistAndUpdateNode(readWriteTransaction, nodeConnectorRef, nc);
-      }
-    }
+        private List<Link> getLinksFromTopology() {
+            InstanceIdentifier<Topology> topologyInstanceIdentifier = InstanceIdentifierUtils
+                    .generateTopologyInstanceIdentifier(topologyId);
+            Topology topology = null;
+            ReadOnlyTransaction readOnlyTransaction = dataBroker.newReadOnlyTransaction();
+            try {
+                Optional<Topology> topologyOptional = readOnlyTransaction
+                        .read(LogicalDatastoreType.OPERATIONAL, topologyInstanceIdentifier).get();
+                if (topologyOptional.isPresent()) {
+                    topology = topologyOptional.get();
+                }
+            } catch (InterruptedException | ExecutionException e) {
+                LOG.error("Error reading topology {}", topologyInstanceIdentifier);
+                readOnlyTransaction.close();
+                throw new RuntimeException(
+                        "Error reading from operational store, topology : " + topologyInstanceIdentifier, e);
+            }
+            readOnlyTransaction.close();
+            if (topology == null) {
+                return null;
+            }
+            List<Link> links = topology.getLink();
+            if (links == null || links.isEmpty()) {
+                return null;
+            }
+            List<Link> internalLinks = new ArrayList<>();
+            for (Link link : links) {
+                if (!link.getLinkId().getValue().contains("host")) {
+                    internalLinks.add(link);
+                }
+            }
+            return internalLinks;
+        }
 
-    /**
-     * @param stpStatusAwareNodeConnector
-     * @return
-     */
-    private boolean sameStatusPresent(StpStatusAwareNodeConnector stpStatusAwareNodeConnector, StpStatus stpStatus) {
+        private void updateNodeConnectorStatus(ReadWriteTransaction readWriteTransaction) {
+            List<Link> allLinks = networkGraphService.getAllLinks();
+            if (allLinks == null || allLinks.isEmpty()) {
+                return;
+            }
+
+            List<Link> mstLinks = networkGraphService.getLinksInMst();
+            for (Link link : allLinks) {
+                if (mstLinks != null && !mstLinks.isEmpty() && mstLinks.contains(link)) {
+                    updateNodeConnector(readWriteTransaction, getSourceNodeConnectorRef(link), StpStatus.Forwarding);
+                    updateNodeConnector(readWriteTransaction, getDestNodeConnectorRef(link), StpStatus.Forwarding);
+                } else {
+                    updateNodeConnector(readWriteTransaction, getSourceNodeConnectorRef(link), StpStatus.Discarding);
+                    updateNodeConnector(readWriteTransaction, getDestNodeConnectorRef(link), StpStatus.Discarding);
+                }
+            }
+        }
 
-      if(stpStatusAwareNodeConnector == null)
-        return false;
+        private NodeConnectorRef getSourceNodeConnectorRef(Link link) {
+            InstanceIdentifier<NodeConnector> nodeConnectorInstanceIdentifier = InstanceIdentifierUtils
+                    .createNodeConnectorIdentifier(link.getSource().getSourceNode().getValue(),
+                            link.getSource().getSourceTp().getValue());
+            return new NodeConnectorRef(nodeConnectorInstanceIdentifier);
+        }
 
-      if(stpStatusAwareNodeConnector.getStatus() == null)
-        return false;
+        private NodeConnectorRef getDestNodeConnectorRef(Link link) {
+            InstanceIdentifier<NodeConnector> nodeConnectorInstanceIdentifier = InstanceIdentifierUtils
+                    .createNodeConnectorIdentifier(link.getDestination().getDestNode().getValue(),
+                            link.getDestination().getDestTp().getValue());
 
-      if(stpStatus.getIntValue() != stpStatusAwareNodeConnector.getStatus().getIntValue())
-        return false;
+            return new NodeConnectorRef(nodeConnectorInstanceIdentifier);
+        }
 
-      return true;
-    }
+        private void updateNodeConnector(ReadWriteTransaction readWriteTransaction, NodeConnectorRef nodeConnectorRef,
+                StpStatus stpStatus) {
+            StpStatusAwareNodeConnectorBuilder stpStatusAwareNodeConnectorBuilder =
+                    new StpStatusAwareNodeConnectorBuilder().setStatus(stpStatus);
+            checkIfExistAndUpdateNodeConnector(readWriteTransaction, nodeConnectorRef,
+                    stpStatusAwareNodeConnectorBuilder.build());
+        }
 
-    /**
-     * @param readWriteTransaction
-     * @param nodeConnectorRef
-     * @param nc
-     */
-    private void checkIfExistAndUpdateNode(ReadWriteTransaction readWriteTransaction, NodeConnectorRef nodeConnectorRef, NodeConnector nc) {
-      Node node = null;
-      InstanceIdentifier<Node> nodeInstanceIdentifier = InstanceIdentifierUtils.generateNodeInstanceIdentifier(nodeConnectorRef);
-      try {
-        Optional<DataObject> dataObjectOptional = readWriteTransaction.read(LogicalDatastoreType.CONFIGURATION, nodeInstanceIdentifier).get();
-        if(dataObjectOptional.isPresent())
-          node = (Node) dataObjectOptional.get();
-      } catch(Exception e) {
-        _logger.error("Error reading node {}", nodeInstanceIdentifier);
-        readWriteTransaction.commit();
-        throw new RuntimeException("Error reading from configuration store, node  : " + nodeInstanceIdentifier, e);
-      }
-      if(node != null) {
-        List<NodeConnector> nodeConnectors = node.getNodeConnector();
-        if(nodeConnectors == null) {
-          nodeConnectors = new ArrayList<>();
+        private void checkIfExistAndUpdateNodeConnector(ReadWriteTransaction readWriteTransaction,
+                NodeConnectorRef nodeConnectorRef, StpStatusAwareNodeConnector stpStatusAwareNodeConnector) {
+            NodeConnector nc = null;
+            try {
+                Optional<NodeConnector> dataObjectOptional = readWriteTransaction.read(LogicalDatastoreType.OPERATIONAL,
+                        (InstanceIdentifier<NodeConnector>) nodeConnectorRef.getValue()).get();
+                if (dataObjectOptional.isPresent()) {
+                    nc = dataObjectOptional.get();
+                }
+            } catch (InterruptedException | ExecutionException e) {
+                LOG.error("Error reading node connector {}", nodeConnectorRef.getValue());
+                readWriteTransaction.submit();
+                throw new RuntimeException("Error reading from operational store, node connector : " + nodeConnectorRef,
+                        e);
+            }
+
+            if (nc != null) {
+                if (sameStatusPresent(nc.getAugmentation(StpStatusAwareNodeConnector.class),
+                        stpStatusAwareNodeConnector.getStatus())) {
+                    return;
+                }
+
+                // build instance id for StpStatusAwareNodeConnector
+                InstanceIdentifier<StpStatusAwareNodeConnector> stpStatusAwareNcInstanceId =
+                        ((InstanceIdentifier<NodeConnector>) nodeConnectorRef
+                                .getValue()).augmentation(StpStatusAwareNodeConnector.class);
+                // update StpStatusAwareNodeConnector in operational store
+                readWriteTransaction.merge(LogicalDatastoreType.OPERATIONAL, stpStatusAwareNcInstanceId,
+                        stpStatusAwareNodeConnector);
+                LOG.debug("Merged Stp Status aware node connector in operational {} with status {}",
+                        stpStatusAwareNcInstanceId, stpStatusAwareNodeConnector);
+            } else {
+                LOG.error("Unable to update Stp Status node connector {} note present in  operational store",
+                        nodeConnectorRef.getValue());
+            }
         }
-        nodeConnectors.add(nc);
-        NodeBuilder nodeBuilder = new NodeBuilder(node)
-            .setNodeConnector(nodeConnectors);
-        node = nodeBuilder.build();
-        readWriteTransaction.put(LogicalDatastoreType.CONFIGURATION, nodeInstanceIdentifier, node);
-        _logger.info("Updated node {}  in configuration store with node id {}", node, nodeInstanceIdentifier);
-      } else {
-        NodeKey nodeKey = nodeConnectorRef.getValue().firstKeyOf(Node.class, NodeKey.class);
-        List<NodeConnector> nodeConnectors = new ArrayList<>();
-        nodeConnectors.add(nc);
-        NodeBuilder nodeBuilder = new NodeBuilder()
-            .setKey(nodeKey)
-            .setId(nodeKey.getId())
-            .setNodeConnector(nodeConnectors);
-        node = nodeBuilder.build();
 
-        checkIfExistsAndUpdateNodes(readWriteTransaction, nodeConnectorRef, node);
-      }
-    }
+        private boolean sameStatusPresent(StpStatusAwareNodeConnector stpStatusAwareNodeConnector,
+                StpStatus stpStatus) {
 
-    /**
-     * @param readWriteTransaction
-     * @param nodeConnectorRef
-     * @param node
-     */
-    private void checkIfExistsAndUpdateNodes(ReadWriteTransaction readWriteTransaction, NodeConnectorRef nodeConnectorRef, Node node) {
+            if (stpStatusAwareNodeConnector == null) {
+                return false;
+            }
+
+            if (stpStatusAwareNodeConnector.getStatus() == null) {
+                return false;
+            }
 
-      List<Node> nodesList = null;
+            if (stpStatus.getIntValue() != stpStatusAwareNodeConnector.getStatus().getIntValue()) {
+                return false;
+            }
 
-      Nodes nodes = null;
-      InstanceIdentifier<Nodes> nodesInstanceIdentifier = nodeConnectorRef.getValue().firstIdentifierOf(Nodes.class);
-      try {
-        Optional<DataObject> dataObjectOptional = readWriteTransaction.read(LogicalDatastoreType.CONFIGURATION, nodesInstanceIdentifier).get();
-        if(dataObjectOptional.isPresent())
-          nodes = (Nodes) dataObjectOptional.get();
-      } catch(Exception e) {
-        _logger.error("Error reading nodes  {}", nodesInstanceIdentifier);
-        readWriteTransaction.commit();
-        throw new RuntimeException("Error reading from configuration store, nodes  : " + nodesInstanceIdentifier, e);
-      }
-      if(nodes != null) {
-        nodesList = nodes.getNode();
-      }
-      if(nodesList == null) {
-        nodesList = new ArrayList<>();
-      }
-      nodesList.add(node);
-      NodesBuilder nodesBuilder = new NodesBuilder()
-          .setNode(nodesList);
-      nodes = nodesBuilder.build();
-      readWriteTransaction.put(LogicalDatastoreType.CONFIGURATION, nodesInstanceIdentifier, nodes);
-      _logger.info("Updated nodes {}  in configuration store with nodes id {}", nodes, nodesInstanceIdentifier);
+            return true;
+        }
     }
-  }
 }