bug 7599 performance improvement for ucast macs 26/51426/5
authorK.V Suneelu Verma <k.v.suneelu.verma@ericsson.com>
Sun, 5 Feb 2017 05:56:07 +0000 (11:26 +0530)
committerK.V Suneelu Verma <k.v.suneelu.verma@ericsson.com>
Tue, 14 Mar 2017 10:39:48 +0000 (16:09 +0530)
Using the getModifiedChildren api on the modification to identify the
modified children data under node.

updated data and deleted data is stored in operational state for access
by all the commands.

Added the following accessor methods in operational state.
List<? extends Identifiable> getUpdatedData(InstanceIdentifier<Node> key,
Class<? extends Identifiable> cls)
List<? extends Identifiable> getDeletedData(InstanceIdentifier<Node> key,
Class<? extends Identifiable> cls)

Change-Id: I76584d7c90323313da35e28a600019c05081f9d0
Signed-off-by: K.V Suneelu Verma <k.v.suneelu.verma@ericsson.com>
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepConnectionManager.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepDataChangeListener.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/reconciliation/configuration/HwvtepReconciliationTask.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/AbstractTransactCommand.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/HwvtepOperationalState.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/TransactCommandAggregator.java

index 835d435d917f0f3a739ad8e36f5fa5a220b7af7d..9ca92a88b95fa0c1517b4ab442bff8b0d7923490 100644 (file)
@@ -225,7 +225,10 @@ public class HwvtepConnectionManager implements OvsdbConnectionListener, AutoClo
         LOG.info("Clients after put: {}", clients);
     }
 
-    public HwvtepConnectionInstance getConnectionInstance(ConnectionInfo key) {
+    public HwvtepConnectionInstance getConnectionInstance(final ConnectionInfo key) {
+        if (key == null) {
+            return null;
+        }
         ConnectionInfo connectionInfo = HwvtepSouthboundMapper.suppressLocalIpPort(key);
         return clients.get(connectionInfo);
     }
index f5d96e38632919e307d6466d23f74624c43b0183..ec4e18ad4c2edf4d739e0125acf93d0cae12bfa9 100644 (file)
@@ -296,7 +296,7 @@ public class HwvtepDataChangeListener implements ClusteredDataTreeChangeListener
                     result.get(connection).add(change);
                 }
             } else {
-                LOG.warn("Failed to get the connection of changed node: {}", node);
+                LOG.warn("Failed to get the connection of changed node: {}", node.getKey().getNodeId().getValue());
             }
         }
         LOG.trace("Connection Change Map: {}", result);
index 38379f54fb5d3632322cab09dc36b3abb99a30cf..97dfe5b902cf29b31a4f7e64c35186a79da9cab6 100644 (file)
@@ -54,6 +54,7 @@ public class HwvtepReconciliationTask extends ReconciliationTask {
 
     private void transactChangesToDevice(Collection<DataTreeModification<Node>> changes) {
         HwvtepOperationalState hwvtepOperationalState = new HwvtepOperationalState(db, connectionInstance, changes);
+        hwvtepOperationalState.setInReconciliation(true);
         connectionInstance.transact(new TransactCommandAggregator(hwvtepOperationalState,changes));
     }
 
index 349cf3db26cfa17732783a6f1e7ce8e62532dbfd..39a543659feab674e396b04adf63074b18dfadd1 100644 (file)
@@ -169,7 +169,12 @@ public abstract class AbstractTransactCommand<T extends Identifiable, Aug extend
         if (changes != null && !changes.isEmpty()) {
             for (DataTreeModification<Node> change : changes) {
                 final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
-                removed = getRemoved(change);
+                Class<? extends Identifiable> classType = (Class<? extends Identifiable>) getClassType();
+                if (operationalState.isInReconciliation()) {
+                    removed = getRemoved(change);
+                } else {
+                    removed = (List<T>) operationalState.getDeletedData(key, classType);
+                }
                 removed.addAll(getCascadeDeleteData(change));
                 result.put(key, removed);
             }
@@ -184,7 +189,14 @@ public abstract class AbstractTransactCommand<T extends Identifiable, Aug extend
         if (changes != null && !changes.isEmpty()) {
             for (DataTreeModification<Node> change : changes) {
                 InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
-                result.put(key, getUpdated(change));
+                Class<? extends Identifiable> classType = (Class<? extends Identifiable>) getClassType();
+                List<T> updated = null;
+                if (operationalState.isInReconciliation()) {
+                    updated = getUpdated(change);
+                } else {
+                    updated = (List<T>) operationalState.getUpdatedData(key, classType);
+                }
+                result.put(key, updated);
             }
         }
         return result;
@@ -222,10 +234,9 @@ public abstract class AbstractTransactCommand<T extends Identifiable, Aug extend
 
     List<T> getUpdated(DataTreeModification<Node> change) {
         DataObjectModification<Node> mod = change.getRootNode();
-        Node created = TransactUtils.getCreated(mod);
         Node updated = TransactUtils.getUpdated(mod);
         Node before = mod.getDataBefore();
-        return diffOf(created, updated, before, false);
+        return diffOf(updated, before, false);
     }
 
     List<T> diffOf(Node include, Node a, Node b, boolean compareKeyOnly) {
@@ -273,6 +284,13 @@ public abstract class AbstractTransactCommand<T extends Identifiable, Aug extend
         return result;
     }
 
+
+    protected Type getClassType() {
+        Type type = getClass().getGenericSuperclass();
+        Type classType = ((ParameterizedType)type).getActualTypeArguments()[0];
+        return classType;
+    }
+
     protected boolean areEqual(T a , T b) {
         return a.getKey().equals(b.getKey());
     }
index 2c15a506a6a33249bc67c3f827365b35b16dccad..fbaae846b9189739e514bf15835dd31ec6a3d1a8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 China Telecom Beijing Research Institute and others.  All rights reserved.
+ * Copyright (c) 2015, 2017 China Telecom Beijing Research Institute 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,
@@ -11,6 +11,7 @@ package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
+import org.apache.commons.lang3.tuple.Pair;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
@@ -67,6 +68,16 @@ public class HwvtepOperationalState {
     private Map<Class<? extends Identifiable>, Map<InstanceIdentifier, UUID>> currentTxUUIDs = new ConcurrentHashMap<>();
     private Map<Class<? extends Identifiable>, Map<InstanceIdentifier, Boolean>> currentTxDeletedKeys = new ConcurrentHashMap<>();
 
+    /* stores the modified and deleted data for each child type of each node id
+       Map<nodeid , Pair < updated, deleted >
+       each updated/ deleted contains Map < child type, List<ChildData>>
+       child type is the child of hwvtep Global augmentation
+     */
+    private Map<InstanceIdentifier<Node>,
+            Pair<Map<Class<? extends Identifiable>, List<Identifiable>>,
+                    Map<Class<? extends Identifiable>, List<Identifiable>>>> modifiedData = new HashMap<>();
+    private boolean inReconciliation = false;
+
     public HwvtepOperationalState(DataBroker db, HwvtepConnectionInstance connectionInstance,
                                   Collection<DataTreeModification<Node>> changes) {
         this.connectionInstance = connectionInstance;
@@ -364,4 +375,41 @@ public class HwvtepOperationalState {
         return Collections.EMPTY_SET;
     }
 
+    public List<? extends Identifiable> getUpdatedData(final InstanceIdentifier<Node> key,
+                                                       final Class<? extends Identifiable> cls) {
+        List<Identifiable> result = null;
+        if (modifiedData.get(key) != null && modifiedData.get(key).getLeft() != null) {
+            result = modifiedData.get(key).getLeft().get(cls);
+        }
+        if (result == null) {
+            result = Collections.EMPTY_LIST;
+        }
+        return result;
+    }
+
+    public List<? extends Identifiable> getDeletedData(final InstanceIdentifier<Node> key,
+                                                       final Class<? extends Identifiable> cls) {
+        List<Identifiable> result = null;
+        if (modifiedData.get(key) != null && modifiedData.get(key).getRight() != null) {
+            result = modifiedData.get(key).getRight().get(cls);
+        }
+        if (result == null) {
+            result = Collections.EMPTY_LIST;
+        }
+        return result;
+    }
+
+    public void setModifiedData(final Map<InstanceIdentifier<Node>,
+            Pair<Map<Class<? extends Identifiable>, List<Identifiable>>,
+                    Map<Class<? extends Identifiable>, List<Identifiable>>>> modifiedData) {
+        this.modifiedData = modifiedData;
+    }
+
+    public boolean isInReconciliation() {
+        return inReconciliation;
+    }
+
+    public void setInReconciliation(boolean inReconciliation) {
+        this.inReconciliation = inReconciliation;
+    }
 }
index b9b6b012196e5dde482ba6960e74c13e0fd1dd3d..0e07f3dac2b0cd261939263abdd48230a3381e93 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 China Telecom Beijing Research Institute and others.  All rights reserved.
+ * Copyright (c) 2015, 2017 China Telecom Beijing Research Institute 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,
@@ -8,21 +8,45 @@
 
 package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
 
+import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentation;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.Identifiable;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Objects;
 
 public class TransactCommandAggregator implements TransactCommand {
 
+    private static final Logger LOG = LoggerFactory.getLogger(TransactCommandAggregator.class);
+
     private List<TransactCommand> commands = new ArrayList<TransactCommand>();
+    private final HwvtepOperationalState operationalState;
+    /* stores the modified and deleted data for each child type of each node id
+       Map<nodeid , Pair < updated, deleted >
+       each updated/ deleted contains Map < child type, List<ChildData>>
+       child type is the child of hwvtep Global augmentation
+     */
+    private final Map<InstanceIdentifier<Node>,
+            Pair<Map<Class<? extends Identifiable>, List<Identifiable>>,
+                Map<Class<? extends Identifiable>, List<Identifiable>>>> modifiedData = new HashMap<>();
+
 
     public TransactCommandAggregator(HwvtepOperationalState state, Collection<DataTreeModification<Node>> changes) {
+        this.operationalState = state;
+        onDataTreeChanged(changes);
         commands.add(new PhysicalSwitchUpdateCommand(state,changes));
         commands.add(new PhysicalSwitchRemoveCommand(state,changes));
         commands.add(new LogicalSwitchUpdateCommand(state,changes));
@@ -59,4 +83,95 @@ public class TransactCommandAggregator implements TransactCommand {
                                     InstanceIdentifier key,
                                     Object... extraData) {
     }
+
+    private void onDataTreeChanged(final Collection<DataTreeModification<Node>> changes) {
+        for (DataTreeModification<Node> change : changes) {
+            final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
+            final DataObjectModification<Node> mod = change.getRootNode();
+            final Map<Class<? extends Identifiable>, List<Identifiable>> updatedData = new HashMap<>();
+            final Map<Class<? extends Identifiable>, List<Identifiable>> deletedData = new HashMap<>();
+            extractDataChanged(key, mod, updatedData, deletedData);
+            modifiedData.put(key, Pair.of(updatedData, deletedData));
+            operationalState.setModifiedData(modifiedData);
+        }
+    }
+
+    private void extractDataChanged(final InstanceIdentifier<Node> key,
+                                    final DataObjectModification<Node> mod,
+                                    final Map<Class<? extends Identifiable>, List<Identifiable>> updatedData,
+                                    final Map<Class<? extends Identifiable>, List<Identifiable>> deletedData) {
+
+        extractDataChanged(mod.getModifiedChildren(), updatedData, deletedData);
+        DataObjectModification<HwvtepGlobalAugmentation> aug = mod.getModifiedAugmentation(
+                HwvtepGlobalAugmentation.class);
+        if (aug != null && getModificationType(aug) != null) {
+            extractDataChanged(aug.getModifiedChildren(), updatedData, deletedData);
+        }
+        DataObjectModification<PhysicalSwitchAugmentation> psAug = mod.getModifiedAugmentation(
+                PhysicalSwitchAugmentation.class);
+        if (psAug != null && getModificationType(psAug) != null) {
+            extractDataChanged(psAug.getModifiedChildren(), updatedData, deletedData);
+        }
+    }
+
+    private void extractDataChanged(final Collection<DataObjectModification<? extends DataObject>> children,
+                                    final Map<Class<? extends Identifiable>, List<Identifiable>> updatedData,
+                                    final Map<Class<? extends Identifiable>, List<Identifiable>> deletedData) {
+        if (children == null) {
+            return;
+        }
+        for (DataObjectModification<? extends DataObject> child : children) {
+            DataObjectModification.ModificationType type = getModificationType(child);
+            if (type == null) {
+                continue;
+            }
+            InstanceIdentifier instanceIdentifier = null;
+            Class<? extends Identifiable> childClass = (Class<? extends Identifiable>) child.getDataType();
+            InstanceIdentifier.PathArgument pathArgument = child.getIdentifier();
+            switch (type) {
+                case WRITE:
+                case SUBTREE_MODIFIED:
+                    DataObject dataAfter = child.getDataAfter();
+                    if (!(dataAfter instanceof Identifiable)) {
+                        continue;
+                    }
+                    DataObject before = child.getDataBefore();
+                    if (Objects.equals(dataAfter, before)) {
+                        /*
+                        in cluster reboot scenarios,
+                        application rewrites the data tx.put( logicalswitchiid, logicalswitch )
+                        that time it fires the update again ignoring such updates here
+                         */
+                        continue;
+                    }
+                    Identifiable identifiable = (Identifiable) dataAfter;
+                    addToUpdatedData(updatedData, childClass, identifiable);
+                    break;
+                case DELETE:
+                    DataObject dataBefore = child.getDataBefore();
+                    if (!(dataBefore instanceof Identifiable)) {
+                        continue;
+                    }
+                    addToUpdatedData(deletedData, childClass, (Identifiable)dataBefore);
+                    break;
+            }
+        }
+    }
+
+    private void addToUpdatedData(Map<Class<? extends Identifiable>, List<Identifiable>> updatedData,
+                                  Class<? extends Identifiable> childClass, Identifiable identifiable) {
+        updatedData.computeIfAbsent(childClass, (cls) -> new ArrayList<>());
+        updatedData.get(childClass).add(identifiable);
+    }
+
+    private DataObjectModification.ModificationType getModificationType(
+            DataObjectModification<? extends DataObject> mod) {
+        try {
+            return mod.getModificationType();
+        } catch (IllegalStateException e) {
+            //not sure why this getter throws this exception, could be some mdsal bug
+            LOG.warn("Failed to get the modification type for mod {}", mod);
+        }
+        return null;
+    }
 }