Update MRI projects for Aluminium
[openflowplugin.git] / applications / forwardingrules-sync / src / main / java / org / opendaylight / openflowplugin / applications / frsync / impl / SimplifiedOperationalListener.java
index 326b1debea1f67f245d70f680f4504a8fdaa5120..3448b160b7c655e1a26c9074c517e0ee141b3d04 100644 (file)
@@ -1,25 +1,23 @@
-/**
+/*
  * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-
 package org.opendaylight.openflowplugin.applications.frsync.impl;
 
-import com.google.common.base.Optional;
 import com.google.common.util.concurrent.ListenableFuture;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Collection;
 import java.util.Date;
-import java.util.List;
-import javax.annotation.Nonnull;
-import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
-import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
-import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import java.util.Map;
+import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.api.DataObjectModification;
+import org.opendaylight.mdsal.binding.api.DataTreeModification;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.openflowplugin.applications.frsync.SyncReactor;
 import org.opendaylight.openflowplugin.applications.frsync.dao.FlowCapableNodeDao;
 import org.opendaylight.openflowplugin.applications.frsync.dao.FlowCapableNodeSnapshotDao;
@@ -34,6 +32,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.sn
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+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.NodeKey;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -66,83 +65,80 @@ public class SimplifiedOperationalListener extends AbstractFrmSyncListener<Node>
     }
 
     @Override
-    public void onDataTreeChanged(@Nonnull final Collection<DataTreeModification<Node>> modifications) {
+    public void onDataTreeChanged(@NonNull final Collection<DataTreeModification<Node>> modifications) {
         super.onDataTreeChanged(modifications);
     }
 
     /**
      * Update cache, register for device mastership when device connected and start reconciliation if device
      * is registered and actual modification is consistent.Skip the event otherwise.
-     * @throws InterruptedException from syncup
      */
+    @Override
     protected Optional<ListenableFuture<Boolean>> processNodeModification(
-            final DataTreeModification<Node> modification) throws InterruptedException {
+            final DataTreeModification<Node> modification) {
+        Optional<ListenableFuture<Boolean>> result;
         final NodeId nodeId = ModificationUtil.nodeId(modification);
-        updateCache(modification);
+        final DataObjectModification<Node> nodeModification = modification.getRootNode();
 
-        if (isAdd(modification) || isAddLogical(modification)) {
-            deviceMastershipManager.onDeviceConnected(nodeId);
-        }
-
-        if (reconciliationRegistry.isRegistered(nodeId) && isConsistentForReconcile(modification)) {
-            return reconciliation(modification);
+        if (isDelete(nodeModification) || isDeleteLogical(nodeModification)) {
+            operationalSnapshot.updateCache(nodeId, Optional.empty());
+            deviceMastershipManager.onDeviceDisconnected(nodeId);
+            result = skipModification(modification);
         } else {
-            return skipModification(modification);
-        }
-    }
+            operationalSnapshot.updateCache(nodeId, Optional.ofNullable(
+                    ModificationUtil.flowCapableNodeAfter(modification)));
 
-    /**
-     * Remove if delete. Update only if FlowCapableNode Augmentation modified.
-     * Unregister for device mastership.
-     * @param modification Datastore modification
-     */
-    private void updateCache(final DataTreeModification<Node> modification) {
-        NodeId nodeId = ModificationUtil.nodeId(modification);
-        if (isDelete(modification) || isDeleteLogical(modification)) {
-            operationalSnapshot.updateCache(nodeId, Optional.absent());
-            deviceMastershipManager.onDeviceDisconnected(nodeId);
-            return;
+            final boolean isAdd = isAdd(nodeModification) || isAddLogical(nodeModification);
+
+            if (isAdd) {
+                deviceMastershipManager.onDeviceConnected(nodeId);
+            }
+
+            // if node is registered for reconcile we need consistent data from operational DS (skip partial
+            // collections) but we can accept first modification since all statistics are intentionally collected in
+            // one step on startup
+            if (reconciliationRegistry.isRegistered(nodeId) && (isAdd || isConsistentForReconcile(modification))) {
+                result = reconciliation(modification);
+            } else {
+                result = skipModification(modification);
+            }
         }
-        operationalSnapshot.updateCache(nodeId, Optional.fromNullable(ModificationUtil.flowCapableNodeAfter(modification)));
+        return result;
     }
 
-    private Optional<ListenableFuture<Boolean>> skipModification(final DataTreeModification<Node> modification) {
+    private static Optional<ListenableFuture<Boolean>> skipModification(final DataTreeModification<Node> modification) {
         if (LOG.isTraceEnabled()) {
             LOG.trace("Skipping operational modification: {}, before {}, after {}",
                     ModificationUtil.nodeIdValue(modification),
                     modification.getRootNode().getDataBefore() == null ? "null" : "nonnull",
                     modification.getRootNode().getDataAfter() == null ? "null" : "nonnull");
         }
-        return Optional.absent();
+        return Optional.empty();
     }
 
-    /**
-     * ModificationType.DELETE.
-     */
-    private boolean isDelete(final DataTreeModification<Node> modification) {
-        return ModificationType.DELETE == modification.getRootNode().getModificationType();
+    private static boolean isDelete(final DataObjectModification<Node> nodeModification) {
+        return nodeModification.getDataBefore() != null && nodeModification.getDataAfter() == null;
     }
 
     /**
      * All connectors disappeared from operational store (logical delete).
      */
-    private boolean isDeleteLogical(final DataTreeModification<Node> modification) {
-        final DataObjectModification<Node> rootNode = modification.getRootNode();
-        return !safeConnectorsEmpty(rootNode.getDataBefore()) && safeConnectorsEmpty(rootNode.getDataAfter());
+    private static boolean isDeleteLogical(final DataObjectModification<Node> nodeModification) {
+        return !safeConnectorsEmpty(nodeModification.getDataBefore())
+                && safeConnectorsEmpty(nodeModification.getDataAfter());
 
     }
 
-    private boolean isAdd(final DataTreeModification<Node> modification) {
-        final DataObjectModification<Node> rootNode = modification.getRootNode();
-        return rootNode.getDataBefore() == null && rootNode.getDataAfter() != null;
+    private static boolean isAdd(final DataObjectModification<Node> nodeModification) {
+        return nodeModification.getDataBefore() == null && nodeModification.getDataAfter() != null;
     }
 
     /**
      * All connectors appeared in operational store (logical add).
      */
-    private boolean isAddLogical(final DataTreeModification<Node> modification) {
-        final DataObjectModification<Node> rootNode = modification.getRootNode();
-        return safeConnectorsEmpty(rootNode.getDataBefore()) && !safeConnectorsEmpty(rootNode.getDataAfter());
+    private static boolean isAddLogical(final DataObjectModification<Node> nodeModification) {
+        return safeConnectorsEmpty(nodeModification.getDataBefore())
+                && !safeConnectorsEmpty(nodeModification.getDataAfter());
     }
 
     /**
@@ -150,10 +146,8 @@ public class SimplifiedOperationalListener extends AbstractFrmSyncListener<Node>
      * configuration (coming from operational) should be calculated and sent to device.
      * @param modification from DS
      * @return optional syncup future
-     * @throws InterruptedException from syncup
      */
-    private Optional<ListenableFuture<Boolean>> reconciliation(final DataTreeModification<Node> modification)
-            throws InterruptedException {
+    private Optional<ListenableFuture<Boolean>> reconciliation(final DataTreeModification<Node> modification) {
         final NodeId nodeId = ModificationUtil.nodeId(modification);
         final Optional<FlowCapableNode> nodeConfiguration = configDao.loadByNodeId(nodeId);
 
@@ -173,10 +167,16 @@ public class SimplifiedOperationalListener extends AbstractFrmSyncListener<Node>
         }
     }
 
+    /**
+     * Check if modification is consistent for reconciliation. We need fresh data, which means that current statistics
+     * were collected after registration for reconcile and whole bunch of statistics was collected successfully.
+     * @param modification from DS
+     * @return status of modification
+     */
     private boolean isConsistentForReconcile(final DataTreeModification<Node> modification) {
         final NodeId nodeId = PathUtil.digNodeId(modification.getRootPath().getRootIdentifier());
         final FlowCapableStatisticsGatheringStatus gatheringStatus = modification.getRootNode().getDataAfter()
-                .getAugmentation(FlowCapableStatisticsGatheringStatus.class);
+                .augmentation(FlowCapableStatisticsGatheringStatus.class);
 
         if (gatheringStatus == null) {
             LOG.trace("Statistics gathering never started: {}", nodeId.getValue());
@@ -204,7 +204,7 @@ public class SimplifiedOperationalListener extends AbstractFrmSyncListener<Node>
                 return true;
             }
         } catch (ParseException e) {
-            LOG.warn("Timestamp parsing error {}", e);
+            LOG.warn("Timestamp parsing error", e);
         }
         LOG.debug("Fresh operational not present: {}", nodeId.getValue());
         return false;
@@ -214,7 +214,7 @@ public class SimplifiedOperationalListener extends AbstractFrmSyncListener<Node>
         if (node == null) {
             return true;
         }
-        final List<NodeConnector> nodeConnectors = node.getNodeConnector();
+        final Map<NodeConnectorKey, NodeConnector> nodeConnectors = node.getNodeConnector();
         return nodeConnectors == null || nodeConnectors.isEmpty();
     }