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);
}
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;
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) {
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());
}
/*
- * 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,
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;
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;
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;
+ }
}
/*
- * 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,
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));
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;
+ }
}