From d6ddc2ab00eb897adc5be169f27b27893b4287db Mon Sep 17 00:00:00 2001 From: Stephen Kitt Date: Thu, 31 Mar 2016 16:58:00 +0200 Subject: [PATCH] Use DataTreeChangeListener instead of DataChangeListener For now this patch sticks to the old approach, where we just listen for all Node events and rebuild the changes and re-extract them. Change-Id: I0f8e4ed09998a28326d39306cbb1b3486260e7f8 Signed-off-by: Stephen Kitt --- southbound/southbound-impl/pom.xml | 6 + .../southbound/OvsdbConnectionInstance.java | 23 ++ .../OvsdbDataTreeChangeListener.java | 239 ++++++++++++++ .../ovsdb/southbound/SouthboundProvider.java | 6 +- .../transact/AutoAttachRemovedCommand.java | 10 +- .../transact/AutoAttachUpdateCommand.java | 8 + .../transact/BridgeOperationalState.java | 19 ++ .../ovsdb/transact/BridgeRemovedCommand.java | 10 + .../ovsdb/transact/BridgeUpdateCommand.java | 9 + .../transact/ControllerRemovedCommand.java | 10 + .../transact/ControllerUpdateCommand.java | 10 + .../transact/OpenVSwitchBridgeAddCommand.java | 9 + .../transact/OvsdbNodeUpdateCommand.java | 8 + .../transact/ProtocolRemovedCommand.java | 10 + .../ovsdb/transact/ProtocolUpdateCommand.java | 10 + .../ovsdb/transact/QosRemovedCommand.java | 11 + .../ovsdb/transact/QosUpdateCommand.java | 9 + .../ovsdb/transact/QueueRemovedCommand.java | 10 + .../ovsdb/transact/QueueUpdateCommand.java | 9 + .../TerminationPointCreateCommand.java | 9 + .../TerminationPointDeleteCommand.java | 11 + .../TerminationPointUpdateCommand.java | 10 + .../ovsdb/transact/TransactCommand.java | 15 + .../transact/TransactCommandAggregator.java | 16 + .../ovsdb/transact/TransactInvoker.java | 14 + .../ovsdb/transact/TransactInvokerImpl.java | 11 + .../ovsdb/transact/TransactUtils.java | 303 ++++++++++++++++++ .../OvsdbDataChangeListenerTest.java | 4 +- .../OvsdbDataTreeChangeListenerTest.java | 74 +++++ 29 files changed, 888 insertions(+), 5 deletions(-) create mode 100644 southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbDataTreeChangeListener.java create mode 100644 southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/OvsdbDataTreeChangeListenerTest.java diff --git a/southbound/southbound-impl/pom.xml b/southbound/southbound-impl/pom.xml index 062bf28e4..3b908b6c6 100644 --- a/southbound/southbound-impl/pom.xml +++ b/southbound/southbound-impl/pom.xml @@ -106,6 +106,12 @@ and is available at http://www.eclipse.org/legal/epl-v10.html test-jar test + + org.opendaylight.ovsdb + utils.southbound-utils + 1.3.0-SNAPSHOT + test + diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbConnectionInstance.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbConnectionInstance.java index 516cd2202..69907f2b5 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbConnectionInstance.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbConnectionInstance.java @@ -9,6 +9,7 @@ package org.opendaylight.ovsdb.southbound; import static org.opendaylight.ovsdb.lib.operations.Operations.op; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -18,6 +19,7 @@ import java.util.concurrent.ExecutionException; import javax.annotation.Nonnull; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.common.api.clustering.Entity; import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipCandidateRegistration; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; @@ -88,6 +90,13 @@ public class OvsdbConnectionInstance implements OvsdbClient { this.instanceIdentifier = iid; } + /** + * Apply the given command to the given events, based on the given bridge state. + * + * @param command The command to run. + * @param state The current bridge state. + * @param events The events to process. + */ public void transact(TransactCommand command, BridgeOperationalState state, AsyncDataChangeEvent, DataObject> events) { for (TransactInvoker transactInvoker : transactInvokers.values()) { @@ -95,6 +104,20 @@ public class OvsdbConnectionInstance implements OvsdbClient { } } + /** + * Apply the given command to the given modifications, based on the given bridge state. + * + * @param command The command to run. + * @param state The current bridge state. + * @param modifications The modifications to process. + */ + public void transact(TransactCommand command, BridgeOperationalState state, + Collection> modifications) { + for (TransactInvoker transactInvoker : transactInvokers.values()) { + transactInvoker.invoke(command, state, modifications); + } + } + public void registerCallbacks() { if ( this.callback == null) { if (this.initialCreateData != null ) { diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbDataTreeChangeListener.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbDataTreeChangeListener.java new file mode 100644 index 000000000..2c0d7093f --- /dev/null +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbDataTreeChangeListener.java @@ -0,0 +1,239 @@ +/* + * Copyright © 2016 Red Hat, 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.ovsdb.southbound; + +import java.net.UnknownHostException; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import javax.annotation.Nonnull; + +import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +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.common.api.data.LogicalDatastoreType; +import org.opendaylight.ovsdb.lib.OvsdbClient; +import org.opendaylight.ovsdb.southbound.ovsdb.transact.BridgeOperationalState; +import org.opendaylight.ovsdb.southbound.ovsdb.transact.TransactCommandAggregator; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.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.Node; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Data-tree change listener for OVSDB. + */ +public class OvsdbDataTreeChangeListener implements ClusteredDataTreeChangeListener, AutoCloseable { + + /** Our registration. */ + private final ListenerRegistration> registration; + + /** The connection manager. */ + private final OvsdbConnectionManager cm; + + /** The data broker. */ + private final DataBroker db; + + /** Logger. */ + private static final Logger LOG = LoggerFactory.getLogger(OvsdbDataTreeChangeListener.class); + + /** + * Create an instance and register the listener. + * + * @param db The data broker. + * @param cm The connection manager. + */ + OvsdbDataTreeChangeListener(DataBroker db, OvsdbConnectionManager cm) { + LOG.info("Registering OvsdbNodeDataChangeListener"); + this.cm = cm; + this.db = db; + InstanceIdentifier path = InstanceIdentifier + .create(NetworkTopology.class) + .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID)) + .child(Node.class); + DataTreeIdentifier dataTreeIdentifier = + new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, path); + registration = db.registerDataTreeChangeListener(dataTreeIdentifier, this); + } + + @Override + public void close() { + registration.close(); + } + + @Override + public void onDataTreeChanged(@Nonnull Collection> changes) { + LOG.trace("onDataTreeChanged: {}", changes); + + // Connect first if necessary + connect(changes); + + // Update connections if necessary + updateConnections(changes); + + // Update the actual data + updateData(changes); + + // Disconnect if necessary + disconnect(changes); + + LOG.trace("onDataTreeChanged: exit"); + } + + private void connect(@Nonnull Collection> changes) { + for (DataTreeModification change : changes) { + if (change.getRootNode().getModificationType() == DataObjectModification.ModificationType.WRITE || change + .getRootNode().getModificationType() == DataObjectModification.ModificationType.SUBTREE_MODIFIED) { + DataObjectModification ovsdbNodeModification = + change.getRootNode().getModifiedAugmentation(OvsdbNodeAugmentation.class); + if (ovsdbNodeModification != null && ovsdbNodeModification.getDataBefore() == null + && ovsdbNodeModification.getDataAfter() != null) { + OvsdbNodeAugmentation ovsdbNode = ovsdbNodeModification.getDataAfter(); + ConnectionInfo key = ovsdbNode.getConnectionInfo(); + InstanceIdentifier iid = cm.getInstanceIdentifier(key); + if ( iid != null) { + LOG.warn("Connection to device {} already exists. Plugin does not allow multiple connections " + + "to same device, hence dropping the request {}", key, ovsdbNode); + } else { + try { + InstanceIdentifier instanceIdentifier = change.getRootPath().getRootIdentifier(); + LOG.info("Connecting on key {} to {}", instanceIdentifier, ovsdbNode); + cm.connect(instanceIdentifier, ovsdbNode); + } catch (UnknownHostException e) { + LOG.warn("Failed to connect to ovsdbNode", e); + } + } + } + } + } + } + + private void disconnect(@Nonnull Collection> changes) { + for (DataTreeModification change : changes) { + if (change.getRootNode().getModificationType() == DataObjectModification.ModificationType.DELETE) { + DataObjectModification ovsdbNodeModification = + change.getRootNode().getModifiedAugmentation(OvsdbNodeAugmentation.class); + if (ovsdbNodeModification != null && ovsdbNodeModification.getDataBefore() != null) { + OvsdbNodeAugmentation ovsdbNode = ovsdbNodeModification.getDataBefore(); + ConnectionInfo key = ovsdbNode.getConnectionInfo(); + InstanceIdentifier iid = cm.getInstanceIdentifier(key); + try { + LOG.info("Disconnecting from {}", ovsdbNode); + cm.disconnect(ovsdbNode); + cm.stopConnectionReconciliationIfActive(iid.firstIdentifierOf(Node.class), ovsdbNode); + } catch (UnknownHostException e) { + LOG.warn("Failed to disconnect ovsdbNode", e); + } + } + } + } + } + + private void updateConnections(@Nonnull Collection> changes) { + for (DataTreeModification change : changes) { + if (change.getRootNode().getModificationType() == DataObjectModification.ModificationType.WRITE || change + .getRootNode().getModificationType() == DataObjectModification.ModificationType.SUBTREE_MODIFIED) { + DataObjectModification ovsdbNodeModification = + change.getRootNode().getModifiedAugmentation(OvsdbNodeAugmentation.class); + if (ovsdbNodeModification != null && ovsdbNodeModification.getDataBefore() != null + && ovsdbNodeModification.getDataAfter() != null) { + OvsdbClient client = cm.getClient(ovsdbNodeModification.getDataAfter().getConnectionInfo()); + if (client == null) { + if (ovsdbNodeModification.getDataBefore() != null) { + try { + cm.disconnect(ovsdbNodeModification.getDataBefore()); + cm.connect(change.getRootPath().getRootIdentifier(), ovsdbNodeModification + .getDataAfter()); + } catch (UnknownHostException e) { + LOG.warn("Error disconnecting from or connecting to ovsdbNode", e); + } + } + } + } + } + } + } + + private void updateData(@Nonnull Collection> changes) { + for (Entry, OvsdbConnectionInstance> connectionInstanceEntry : + connectionInstancesFromChanges(changes).entrySet()) { + OvsdbConnectionInstance connectionInstance = connectionInstanceEntry.getValue(); + connectionInstance.transact(new TransactCommandAggregator(), + new BridgeOperationalState(db, changes), changes); + } + } + + private Map, OvsdbConnectionInstance> connectionInstancesFromChanges( + @Nonnull Collection> changes) { + Map,OvsdbConnectionInstance> result = + new HashMap<>(); + for (DataTreeModification change : changes) { + DataObjectModification bridgeModification = + change.getRootNode().getModifiedAugmentation(OvsdbBridgeAugmentation.class); + OvsdbConnectionInstance client = null; + Node node = change.getRootNode().getDataAfter(); + if (bridgeModification != null && bridgeModification.getDataAfter() != null) { + client = cm.getConnectionInstance(bridgeModification.getDataAfter()); + } else { + DataObjectModification nodeModification = + change.getRootNode().getModifiedAugmentation(OvsdbNodeAugmentation.class); + if (nodeModification != null && nodeModification.getDataAfter() != null && nodeModification + .getDataAfter().getConnectionInfo() != null) { + client = cm.getConnectionInstance(nodeModification.getDataAfter().getConnectionInfo()); + } else { + if (node != null) { + List terminationPoints = node.getTerminationPoint(); + if (terminationPoints != null && !terminationPoints.isEmpty()) { + InstanceIdentifier nodeIid = SouthboundMapper.createInstanceIdentifier( + node.getNodeId()); + client = cm.getConnectionInstance(nodeIid); + } + } + } + } + if (client != null) { + LOG.debug("Found client for {}", node); + /* + * As of now data change sets are processed by single thread, so we can assume that device will + * be connected and ownership will be decided before sending any instructions down to the device. + * Note:Processing order in onDataChange() method should not change. If processing is changed to + * use multiple thread, we might need to take care of corner cases, where ownership is not decided + * but transaction are ready to go to switch. In that scenario, either we need to queue those task + * till ownership is decided for that specific device. + * Given that each DataChangeNotification is notified through separate thread, so we are already + * multi threaded and i don't see any need to further parallelism per DataChange + * notifications processing. + */ + if ( cm.getHasDeviceOwnership(client.getMDConnectionInfo())) { + LOG.debug("*This* instance of southbound plugin is an owner of the device {}", node); + result.put(change.getRootPath().getRootIdentifier(), client); + } else { + LOG.debug("*This* instance of southbound plugin is *not* an owner of the device {}", node); + } + } else { + LOG.debug("Did not find client for {}", node); + } + } + return result; + } +} diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundProvider.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundProvider.java index a331a2ab5..28e93c4e4 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundProvider.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundProvider.java @@ -48,7 +48,7 @@ public class SouthboundProvider implements BindingAwareProvider, AutoCloseable { private static DataBroker db; private OvsdbConnectionManager cm; private TransactionInvoker txInvoker; - private OvsdbDataChangeListener ovsdbDataChangeListener; + private OvsdbDataTreeChangeListener ovsdbDataTreeChangeListener; private EntityOwnershipService entityOwnershipService; private EntityOwnershipCandidateRegistration registration; private SouthboundPluginInstanceEntityOwnershipListener providerOwnershipChangeListener; @@ -70,7 +70,7 @@ public class SouthboundProvider implements BindingAwareProvider, AutoCloseable { db = session.getSALService(DataBroker.class); this.txInvoker = new TransactionInvokerImpl(db); cm = new OvsdbConnectionManager(db,txInvoker,entityOwnershipService, ovsdbConnection); - ovsdbDataChangeListener = new OvsdbDataChangeListener(db,cm); + ovsdbDataTreeChangeListener = new OvsdbDataTreeChangeListener(db, cm); //Register listener for entityOnwership changes providerOwnershipChangeListener = @@ -100,7 +100,7 @@ public class SouthboundProvider implements BindingAwareProvider, AutoCloseable { public void close() { LOG.info("SouthboundProvider Closed"); cm.close(); - ovsdbDataChangeListener.close(); + ovsdbDataTreeChangeListener.close(); registration.close(); providerOwnershipChangeListener.close(); } diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/AutoAttachRemovedCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/AutoAttachRemovedCommand.java index 8fd2a6655..feb537f61 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/AutoAttachRemovedCommand.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/AutoAttachRemovedCommand.java @@ -10,10 +10,12 @@ package org.opendaylight.ovsdb.southbound.ovsdb.transact; import static org.opendaylight.ovsdb.lib.operations.Operations.op; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; @@ -38,12 +40,18 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Optional; -import com.google.common.base.Preconditions; import com.google.common.collect.Sets; public class AutoAttachRemovedCommand implements TransactCommand { private static final Logger LOG = LoggerFactory.getLogger(AutoAttachRemovedCommand.class); + @Override + public void execute(TransactionBuilder transaction, BridgeOperationalState state, + Collection> modifications) { + execute(transaction, state, TransactUtils.extractOriginal(modifications, OvsdbNodeAugmentation.class), + TransactUtils.extractUpdated(modifications, OvsdbNodeAugmentation.class)); + } + @Override public void execute(TransactionBuilder transaction, BridgeOperationalState state, AsyncDataChangeEvent, DataObject> events) { diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/AutoAttachUpdateCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/AutoAttachUpdateCommand.java index 593bbb999..4c320094d 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/AutoAttachUpdateCommand.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/AutoAttachUpdateCommand.java @@ -10,12 +10,14 @@ package org.opendaylight.ovsdb.southbound.ovsdb.transact; import static org.opendaylight.ovsdb.lib.operations.Operations.op; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ExecutionException; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; @@ -58,6 +60,12 @@ public class AutoAttachUpdateCommand implements TransactCommand { execute(transaction, state, TransactUtils.extractCreatedOrUpdated(events, OvsdbNodeAugmentation.class)); } + @Override + public void execute(TransactionBuilder transaction, BridgeOperationalState state, + Collection> modifications) { + execute(transaction, state, TransactUtils.extractCreatedOrUpdated(modifications, OvsdbNodeAugmentation.class)); + } + private void execute(TransactionBuilder transaction, BridgeOperationalState state, Map, OvsdbNodeAugmentation> createdOrUpdated) { diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/BridgeOperationalState.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/BridgeOperationalState.java index 86e60e9ca..1a6cb96d0 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/BridgeOperationalState.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/BridgeOperationalState.java @@ -8,12 +8,14 @@ package org.opendaylight.ovsdb.southbound.ovsdb.transact; +import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ExecutionException; 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.ReadOnlyTransaction; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; @@ -61,6 +63,23 @@ public class BridgeOperationalState { transaction.close(); } + public BridgeOperationalState(DataBroker db, Collection> changes) { + ReadOnlyTransaction transaction = db.newReadOnlyTransaction(); + Map, Node> nodeCreateOrUpdateOrRemove = + TransactUtils.extractCreatedOrUpdatedOrRemoved(changes, Node.class); + for (Entry, Node> entry : nodeCreateOrUpdateOrRemove.entrySet()) { + try { + Optional nodeOptional = transaction.read(LogicalDatastoreType.OPERATIONAL, entry.getKey()) + .checkedGet(); + if (nodeOptional.isPresent()) { + operationalNodes.put(entry.getKey(), nodeOptional.get()); + } + } catch (ReadFailedException e) { + LOG.warn("Error reading from datastore", e); + } + } + } + public Optional getBridgeNode(InstanceIdentifier iid) { InstanceIdentifier nodeIid = iid.firstIdentifierOf(Node.class); return Optional.fromNullable(operationalNodes.get(nodeIid)); diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/BridgeRemovedCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/BridgeRemovedCommand.java index ebd1c140f..ef6c2d6df 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/BridgeRemovedCommand.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/BridgeRemovedCommand.java @@ -10,9 +10,11 @@ package org.opendaylight.ovsdb.southbound.ovsdb.transact; import static org.opendaylight.ovsdb.lib.operations.Operations.op; +import java.util.Collection; import java.util.Map; import java.util.Set; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; import org.opendaylight.ovsdb.lib.notation.Mutator; import org.opendaylight.ovsdb.lib.notation.UUID; @@ -21,6 +23,7 @@ import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils; import org.opendaylight.ovsdb.schema.openvswitch.Bridge; import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation; +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.InstanceIdentifier; import org.slf4j.Logger; @@ -39,6 +42,13 @@ public class BridgeRemovedCommand implements TransactCommand { TransactUtils.extractOriginal(events, OvsdbBridgeAugmentation.class)); } + @Override + public void execute(TransactionBuilder transaction, BridgeOperationalState state, + Collection> modifications) { + execute(transaction, state, TransactUtils.extractRemoved(modifications, OvsdbBridgeAugmentation.class), + TransactUtils.extractOriginal(modifications, OvsdbBridgeAugmentation.class)); + } + private void execute(TransactionBuilder transaction, BridgeOperationalState state, Set> removed, Map, OvsdbBridgeAugmentation> originals) { for (InstanceIdentifier ovsdbManagedNodeIid: removed) { diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/BridgeUpdateCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/BridgeUpdateCommand.java index 5f04ff018..676a2aaa0 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/BridgeUpdateCommand.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/BridgeUpdateCommand.java @@ -9,6 +9,7 @@ package org.opendaylight.ovsdb.southbound.ovsdb.transact; import static org.opendaylight.ovsdb.lib.operations.Operations.op; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -16,6 +17,7 @@ import java.util.Map.Entry; import javax.annotation.Nonnull; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; import org.opendaylight.ovsdb.lib.notation.UUID; import org.opendaylight.ovsdb.lib.operations.Insert; @@ -53,6 +55,13 @@ public class BridgeUpdateCommand implements TransactCommand { execute(transaction, state, TransactUtils.extractCreatedOrUpdated(events, OvsdbBridgeAugmentation.class)); } + @Override + public void execute(TransactionBuilder transaction, BridgeOperationalState state, + Collection> modifications) { + execute(transaction, state, + TransactUtils.extractCreatedOrUpdated(modifications, OvsdbBridgeAugmentation.class)); + } + private void execute(TransactionBuilder transaction, BridgeOperationalState state, Map, OvsdbBridgeAugmentation> createdOrUpdated) { for (Entry, OvsdbBridgeAugmentation> ovsdbManagedNodeEntry : diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/ControllerRemovedCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/ControllerRemovedCommand.java index dd9e630b3..2e75636fb 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/ControllerRemovedCommand.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/ControllerRemovedCommand.java @@ -9,9 +9,11 @@ package org.opendaylight.ovsdb.southbound.ovsdb.transact; import static org.opendaylight.ovsdb.lib.operations.Operations.op; +import java.util.Collection; import java.util.Map; import java.util.Set; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; import org.opendaylight.ovsdb.lib.notation.Mutator; import org.opendaylight.ovsdb.lib.notation.UUID; @@ -20,6 +22,7 @@ import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils; import org.opendaylight.ovsdb.schema.openvswitch.Bridge; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry; +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.InstanceIdentifier; @@ -35,6 +38,13 @@ public class ControllerRemovedCommand implements TransactCommand { TransactUtils.extractCreatedOrUpdatedOrRemoved(events, OvsdbBridgeAugmentation.class)); } + @Override + public void execute(TransactionBuilder transaction, BridgeOperationalState state, + Collection> modifications) { + execute(transaction, state, TransactUtils.extractRemoved(modifications, ControllerEntry.class), + TransactUtils.extractCreatedOrUpdatedOrRemoved(modifications, OvsdbBridgeAugmentation.class)); + } + private void execute(TransactionBuilder transaction, BridgeOperationalState state, Set> removedControllers, Map, OvsdbBridgeAugmentation> diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/ControllerUpdateCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/ControllerUpdateCommand.java index 8e55699df..4737cf135 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/ControllerUpdateCommand.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/ControllerUpdateCommand.java @@ -9,9 +9,11 @@ package org.opendaylight.ovsdb.southbound.ovsdb.transact; import static org.opendaylight.ovsdb.lib.operations.Operations.op; +import java.util.Collection; import java.util.Map; import java.util.Map.Entry; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; import org.opendaylight.ovsdb.lib.notation.Mutator; import org.opendaylight.ovsdb.lib.notation.UUID; @@ -22,6 +24,7 @@ import org.opendaylight.ovsdb.schema.openvswitch.Controller; import org.opendaylight.ovsdb.southbound.SouthboundMapper; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry; +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.InstanceIdentifier; @@ -40,6 +43,13 @@ public class ControllerUpdateCommand implements TransactCommand { TransactUtils.extractCreatedOrUpdated(events, OvsdbBridgeAugmentation.class)); } + @Override + public void execute(TransactionBuilder transaction, BridgeOperationalState state, + Collection> modifications) { + execute(transaction, state, TransactUtils.extractCreatedOrUpdated(modifications, ControllerEntry.class), + TransactUtils.extractCreatedOrUpdated(modifications, OvsdbBridgeAugmentation.class)); + } + private void execute(TransactionBuilder transaction, BridgeOperationalState state, Map, ControllerEntry> controllers, Map, OvsdbBridgeAugmentation> bridges) { diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/OpenVSwitchBridgeAddCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/OpenVSwitchBridgeAddCommand.java index b8bcf0bfc..b90df1225 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/OpenVSwitchBridgeAddCommand.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/OpenVSwitchBridgeAddCommand.java @@ -10,8 +10,10 @@ package org.opendaylight.ovsdb.southbound.ovsdb.transact; import static org.opendaylight.ovsdb.lib.operations.Operations.op; +import java.util.Collection; import java.util.List; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; import org.opendaylight.ovsdb.lib.notation.Mutator; import org.opendaylight.ovsdb.lib.operations.Insert; @@ -21,6 +23,7 @@ import org.opendaylight.ovsdb.schema.openvswitch.Bridge; import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch; import com.google.common.collect.Sets; +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.InstanceIdentifier; @@ -32,6 +35,12 @@ public class OpenVSwitchBridgeAddCommand implements TransactCommand { execute(transaction); } + @Override + public void execute(TransactionBuilder transaction, BridgeOperationalState state, + Collection> modifications) { + execute(transaction); + } + private void execute(TransactionBuilder transaction) { Bridge bridge = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), Bridge.class); List inserts = TransactUtils.extractInsert(transaction, bridge.getSchema()); diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/OvsdbNodeUpdateCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/OvsdbNodeUpdateCommand.java index ba24c908d..a79bbcade 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/OvsdbNodeUpdateCommand.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/OvsdbNodeUpdateCommand.java @@ -9,11 +9,13 @@ package org.opendaylight.ovsdb.southbound.ovsdb.transact; import static org.opendaylight.ovsdb.lib.operations.Operations.op; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; import org.opendaylight.ovsdb.lib.notation.Mutator; import org.opendaylight.ovsdb.lib.operations.Mutate; @@ -40,6 +42,12 @@ public class OvsdbNodeUpdateCommand implements TransactCommand { execute(transaction, TransactUtils.extractCreatedOrUpdated(events, OvsdbNodeAugmentation.class)); } + @Override + public void execute(TransactionBuilder transaction, BridgeOperationalState state, + Collection> modifications) { + execute(transaction, TransactUtils.extractCreatedOrUpdated(modifications, OvsdbNodeAugmentation.class)); + } + private void execute(TransactionBuilder transaction, Map, OvsdbNodeAugmentation> updated) { for (Entry, OvsdbNodeAugmentation> ovsdbNodeEntry: diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/ProtocolRemovedCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/ProtocolRemovedCommand.java index 79184c58f..cb9456003 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/ProtocolRemovedCommand.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/ProtocolRemovedCommand.java @@ -10,9 +10,11 @@ package org.opendaylight.ovsdb.southbound.ovsdb.transact; import static org.opendaylight.ovsdb.lib.operations.Operations.op; +import java.util.Collection; import java.util.Map; import java.util.Set; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; import org.opendaylight.ovsdb.lib.error.SchemaVersionMismatchException; import org.opendaylight.ovsdb.lib.notation.Mutator; @@ -22,6 +24,7 @@ import org.opendaylight.ovsdb.schema.openvswitch.Bridge; import org.opendaylight.ovsdb.southbound.SouthboundConstants; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry; +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.InstanceIdentifier; import org.slf4j.Logger; @@ -41,6 +44,13 @@ public class ProtocolRemovedCommand implements TransactCommand { TransactUtils.extractCreatedOrUpdatedOrRemoved(events, OvsdbBridgeAugmentation.class)); } + @Override + public void execute(TransactionBuilder transaction, BridgeOperationalState state, + Collection> modifications) { + execute(transaction, state, TransactUtils.extractRemoved(modifications, ProtocolEntry.class), + TransactUtils.extractCreatedOrUpdatedOrRemoved(modifications, OvsdbBridgeAugmentation.class)); + } + private void execute(TransactionBuilder transaction, BridgeOperationalState state, Set> removed, Map, OvsdbBridgeAugmentation> updatedBridges) { for (InstanceIdentifier protocolIid : removed) { diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/ProtocolUpdateCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/ProtocolUpdateCommand.java index a42c6a489..3eb9f460d 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/ProtocolUpdateCommand.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/ProtocolUpdateCommand.java @@ -10,9 +10,11 @@ package org.opendaylight.ovsdb.southbound.ovsdb.transact; import static org.opendaylight.ovsdb.lib.operations.Operations.op; +import java.util.Collection; import java.util.Map; import java.util.Map.Entry; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; import org.opendaylight.ovsdb.lib.error.SchemaVersionMismatchException; import org.opendaylight.ovsdb.lib.notation.Mutator; @@ -22,6 +24,7 @@ import org.opendaylight.ovsdb.schema.openvswitch.Bridge; import org.opendaylight.ovsdb.southbound.SouthboundConstants; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry; +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.InstanceIdentifier; import org.slf4j.Logger; @@ -41,6 +44,13 @@ public class ProtocolUpdateCommand implements TransactCommand { TransactUtils.extractCreatedOrUpdated(events, OvsdbBridgeAugmentation.class)); } + @Override + public void execute(TransactionBuilder transaction, BridgeOperationalState state, + Collection> modifications) { + execute(transaction, state, TransactUtils.extractCreatedOrUpdated(modifications, ProtocolEntry.class), + TransactUtils.extractCreatedOrUpdated(modifications, OvsdbBridgeAugmentation.class)); + } + private void execute(TransactionBuilder transaction, BridgeOperationalState state, Map, ProtocolEntry> protocols, Map, OvsdbBridgeAugmentation> bridges) { diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/QosRemovedCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/QosRemovedCommand.java index 4abcd53e0..8822cd8f0 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/QosRemovedCommand.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/QosRemovedCommand.java @@ -10,9 +10,11 @@ package org.opendaylight.ovsdb.southbound.ovsdb.transact; import static org.opendaylight.ovsdb.lib.operations.Operations.op; +import java.util.Collection; import java.util.List; import java.util.Map; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; import org.opendaylight.ovsdb.lib.notation.UUID; import org.opendaylight.ovsdb.lib.operations.TransactionBuilder; @@ -22,6 +24,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types. import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntries; +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.InstanceIdentifier; import org.slf4j.Logger; @@ -38,6 +41,14 @@ public class QosRemovedCommand implements TransactCommand { TransactUtils.extractUpdated(events, OvsdbNodeAugmentation.class)); } + @Override + public void execute(TransactionBuilder transaction, BridgeOperationalState state, + Collection> modifications) { + execute(transaction, state, + TransactUtils.extractOriginal(modifications, OvsdbNodeAugmentation.class), + TransactUtils.extractUpdated(modifications, OvsdbNodeAugmentation.class)); + } + private void execute(TransactionBuilder transaction, BridgeOperationalState state, Map, OvsdbNodeAugmentation> originals, Map, OvsdbNodeAugmentation> updated) { diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/QosUpdateCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/QosUpdateCommand.java index e4deca17a..4f1cb86da 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/QosUpdateCommand.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/QosUpdateCommand.java @@ -9,11 +9,13 @@ package org.opendaylight.ovsdb.southbound.ovsdb.transact; import static org.opendaylight.ovsdb.lib.operations.Operations.op; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; import org.opendaylight.ovsdb.lib.notation.UUID; import org.opendaylight.ovsdb.lib.operations.TransactionBuilder; @@ -29,6 +31,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.re import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosExternalIds; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosOtherConfig; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QueueList; +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.InstanceIdentifier; import org.slf4j.Logger; @@ -43,6 +46,12 @@ public class QosUpdateCommand implements TransactCommand { execute(transaction, state, TransactUtils.extractCreatedOrUpdated(events, OvsdbNodeAugmentation.class)); } + @Override + public void execute(TransactionBuilder transaction, BridgeOperationalState state, + Collection> modifications) { + execute(transaction, state, TransactUtils.extractCreatedOrUpdated(modifications, OvsdbNodeAugmentation.class)); + } + private void execute(TransactionBuilder transaction, BridgeOperationalState state, Map, OvsdbNodeAugmentation> createdOrUpdated) { for (Entry, OvsdbNodeAugmentation> ovsdbNodeEntry: diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/QueueRemovedCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/QueueRemovedCommand.java index c9706c895..2e590af0e 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/QueueRemovedCommand.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/QueueRemovedCommand.java @@ -10,9 +10,11 @@ package org.opendaylight.ovsdb.southbound.ovsdb.transact; import static org.opendaylight.ovsdb.lib.operations.Operations.op; +import java.util.Collection; import java.util.List; import java.util.Map; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; import org.opendaylight.ovsdb.lib.notation.UUID; import org.opendaylight.ovsdb.lib.operations.TransactionBuilder; @@ -22,6 +24,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types. import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.Queues; +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.InstanceIdentifier; import org.slf4j.Logger; @@ -37,6 +40,13 @@ public class QueueRemovedCommand implements TransactCommand { TransactUtils.extractUpdated(events, OvsdbNodeAugmentation.class)); } + @Override + public void execute(TransactionBuilder transaction, BridgeOperationalState state, + Collection> modifications) { + execute(transaction, state, TransactUtils.extractOriginal(modifications, OvsdbNodeAugmentation.class), + TransactUtils.extractUpdated(modifications, OvsdbNodeAugmentation.class)); + } + private void execute(TransactionBuilder transaction, BridgeOperationalState state, Map, OvsdbNodeAugmentation> originals, Map, OvsdbNodeAugmentation> updated) { diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/QueueUpdateCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/QueueUpdateCommand.java index 761973117..6018b8572 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/QueueUpdateCommand.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/QueueUpdateCommand.java @@ -9,6 +9,7 @@ package org.opendaylight.ovsdb.southbound.ovsdb.transact; import static org.opendaylight.ovsdb.lib.operations.Operations.op; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -16,6 +17,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; import org.opendaylight.ovsdb.lib.notation.UUID; import org.opendaylight.ovsdb.lib.operations.TransactionBuilder; @@ -29,6 +31,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.re import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.Queues; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesExternalIds; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesOtherConfig; +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.InstanceIdentifier; import org.slf4j.Logger; @@ -43,6 +46,12 @@ public class QueueUpdateCommand implements TransactCommand { execute(transaction, state, TransactUtils.extractCreatedOrUpdated(events, OvsdbNodeAugmentation.class)); } + @Override + public void execute(TransactionBuilder transaction, BridgeOperationalState state, + Collection> modifications) { + execute(transaction, state, TransactUtils.extractCreatedOrUpdated(modifications, OvsdbNodeAugmentation.class)); + } + private void execute(TransactionBuilder transaction, BridgeOperationalState state, Map, OvsdbNodeAugmentation> createdOrUpdated) { for (Entry, OvsdbNodeAugmentation> ovsdbNodeEntry: diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TerminationPointCreateCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TerminationPointCreateCommand.java index 9c102f2ed..1bef344ac 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TerminationPointCreateCommand.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TerminationPointCreateCommand.java @@ -9,6 +9,7 @@ package org.opendaylight.ovsdb.southbound.ovsdb.transact; import static org.opendaylight.ovsdb.lib.operations.Operations.op; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -18,6 +19,7 @@ import java.util.Map.Entry; import java.util.concurrent.ExecutionException; import java.util.Set; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; @@ -69,6 +71,13 @@ public class TerminationPointCreateCommand implements TransactCommand { TransactUtils.extractCreatedOrUpdated(events, Node.class)); } + @Override + public void execute(TransactionBuilder transaction, BridgeOperationalState state, + Collection> modifications) { + execute(transaction, state, TransactUtils.extractCreated(modifications, OvsdbTerminationPointAugmentation.class), + TransactUtils.extractCreatedOrUpdated(modifications, Node.class)); + } + private void execute(TransactionBuilder transaction, BridgeOperationalState state, Map, OvsdbTerminationPointAugmentation> diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TerminationPointDeleteCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TerminationPointDeleteCommand.java index b59e6db15..431f4ba3b 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TerminationPointDeleteCommand.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TerminationPointDeleteCommand.java @@ -9,9 +9,11 @@ package org.opendaylight.ovsdb.southbound.ovsdb.transact; import static org.opendaylight.ovsdb.lib.operations.Operations.op; +import java.util.Collection; import java.util.Map; import java.util.Set; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; import org.opendaylight.ovsdb.lib.notation.Mutator; import org.opendaylight.ovsdb.lib.notation.UUID; @@ -45,6 +47,15 @@ public class TerminationPointDeleteCommand implements TransactCommand { TransactUtils.extractRemoved(events, OvsdbTerminationPointAugmentation.class)); } + @Override + public void execute(TransactionBuilder transaction, BridgeOperationalState state, + Collection> modifications) { + execute(transaction, state, + TransactUtils.extractOriginal(modifications, OvsdbTerminationPointAugmentation.class), + TransactUtils.extractOriginal(modifications, Node.class), + TransactUtils.extractRemoved(modifications, OvsdbTerminationPointAugmentation.class)); + } + private void execute(TransactionBuilder transaction, BridgeOperationalState state, Map, OvsdbTerminationPointAugmentation> originals, Map, Node> originalNodes, diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TerminationPointUpdateCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TerminationPointUpdateCommand.java index 344eb92bc..3e91aab5e 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TerminationPointUpdateCommand.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TerminationPointUpdateCommand.java @@ -9,6 +9,7 @@ package org.opendaylight.ovsdb.southbound.ovsdb.transact; import static org.opendaylight.ovsdb.lib.operations.Operations.op; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -16,6 +17,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; import org.opendaylight.ovsdb.lib.error.SchemaVersionMismatchException; import org.opendaylight.ovsdb.lib.notation.UUID; @@ -36,6 +38,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.re import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortExternalIds; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortOtherConfigs; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Trunks; +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.InstanceIdentifier; import org.slf4j.Logger; @@ -53,6 +56,13 @@ public class TerminationPointUpdateCommand implements TransactCommand { execute(transaction, TransactUtils.extractCreatedOrUpdated(events, OvsdbTerminationPointAugmentation.class)); } + @Override + public void execute(TransactionBuilder transaction, BridgeOperationalState state, + Collection> modifications) { + execute(transaction, + TransactUtils.extractCreatedOrUpdated(modifications, OvsdbTerminationPointAugmentation.class)); + } + private void execute(TransactionBuilder transaction, Map, OvsdbTerminationPointAugmentation> createdOrUpdated) { diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TransactCommand.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TransactCommand.java index 7d265e721..971e6a386 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TransactCommand.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TransactCommand.java @@ -7,8 +7,12 @@ */ package org.opendaylight.ovsdb.southbound.ovsdb.transact; +import java.util.Collection; + +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; import org.opendaylight.ovsdb.lib.operations.TransactionBuilder; +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.InstanceIdentifier; @@ -26,4 +30,15 @@ public interface TransactCommand { */ void execute(TransactionBuilder transaction, BridgeOperationalState state, AsyncDataChangeEvent, DataObject> events); + + /** + * Queue the command defined by the class implementing this interface in the given transaction builder, with the + * given bridge state, in reaction to the given modifications. + * + * @param transaction The transaction builder. + * @param state The bridge state. + * @param modifications The modifications to be represented. + */ + void execute(TransactionBuilder transaction, BridgeOperationalState state, + Collection> modifications); } diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TransactCommandAggregator.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TransactCommandAggregator.java index e3e430058..17bd9aa35 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TransactCommandAggregator.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TransactCommandAggregator.java @@ -7,8 +7,12 @@ */ package org.opendaylight.ovsdb.southbound.ovsdb.transact; +import java.util.Collection; + +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; import org.opendaylight.ovsdb.lib.operations.TransactionBuilder; +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.InstanceIdentifier; import org.slf4j.Logger; @@ -52,4 +56,16 @@ public class TransactCommandAggregator implements TransactCommand { } } } + + @Override + public void execute(TransactionBuilder transaction, BridgeOperationalState state, + Collection> modifications) { + for (Class commandClass : COMMAND_CLASSES) { + try { + commandClass.newInstance().execute(transaction, state, modifications); + } catch (InstantiationException | IllegalAccessException e) { + LOG.error("Error instantiating {}", commandClass, e); + } + } + } } diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TransactInvoker.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TransactInvoker.java index 33b7b4e4f..5009ece16 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TransactInvoker.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TransactInvoker.java @@ -7,7 +7,11 @@ */ package org.opendaylight.ovsdb.southbound.ovsdb.transact; +import java.util.Collection; + +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; +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.InstanceIdentifier; @@ -24,4 +28,14 @@ public interface TransactInvoker { */ void invoke(TransactCommand command, BridgeOperationalState state, AsyncDataChangeEvent, DataObject> events); + + /** + * Invoke the given transactional command, with the given bridge state, on the given modifications. + * + * @param command The transactional command. + * @param state The bridge state. + * @param modifications The modifications to be processed. + */ + void invoke(TransactCommand command, BridgeOperationalState state, + Collection> modifications); } diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TransactInvokerImpl.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TransactInvokerImpl.java index cc7056d65..a179df7d3 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TransactInvokerImpl.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TransactInvokerImpl.java @@ -7,13 +7,16 @@ */ package org.opendaylight.ovsdb.southbound.ovsdb.transact; +import java.util.Collection; import java.util.List; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; import org.opendaylight.ovsdb.lib.operations.OperationResult; import org.opendaylight.ovsdb.lib.operations.TransactionBuilder; import org.opendaylight.ovsdb.lib.schema.DatabaseSchema; import org.opendaylight.ovsdb.southbound.OvsdbConnectionInstance; +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.InstanceIdentifier; import org.slf4j.Logger; @@ -39,6 +42,14 @@ public class TransactInvokerImpl implements TransactInvoker { invoke(command, tb); } + @Override + public void invoke(TransactCommand command, BridgeOperationalState state, + Collection> modifications) { + TransactionBuilder tb = new TransactionBuilder(connectionInstance, dbSchema); + command.execute(tb, state, modifications); + invoke(command, tb); + } + private void invoke(TransactCommand command, TransactionBuilder tb) { ListenableFuture> result = tb.execute(); LOG.debug("invoke: command: {}, tb: {}", command, tb); diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TransactUtils.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TransactUtils.java index 0d37f5ece..26b9581fa 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TransactUtils.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/ovsdb/transact/TransactUtils.java @@ -10,13 +10,21 @@ package org.opendaylight.ovsdb.southbound.ovsdb.transact; import static org.opendaylight.ovsdb.lib.operations.Operations.op; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Queue; import java.util.Set; +import javax.annotation.Nullable; + +import com.google.common.base.Predicate; +import org.opendaylight.controller.md.sal.binding.api.DataObjectModification; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; import org.opendaylight.ovsdb.lib.notation.Mutation; import org.opendaylight.ovsdb.lib.notation.Mutator; @@ -33,8 +41,13 @@ import org.opendaylight.ovsdb.southbound.SouthboundConstants; import org.opendaylight.ovsdb.southbound.SouthboundMapper; import org.opendaylight.ovsdb.southbound.SouthboundUtil; 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.ChildOf; import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.Identifiable; +import org.opendaylight.yangtools.yang.binding.Identifier; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -47,6 +60,73 @@ import com.google.common.collect.Sets; public class TransactUtils { private static final Logger LOG = LoggerFactory.getLogger(TransactUtils.class); + private static Predicate> hasDataBefore() { + return new Predicate>() { + @Override + public boolean apply(@Nullable DataObjectModification input) { + return input != null && input.getDataBefore() != null; + } + }; + } + + private static Predicate> hasDataBeforeAndDataAfter() { + return new Predicate>() { + @Override + public boolean apply(@Nullable DataObjectModification input) { + return input != null && input.getDataBefore() != null && input.getDataAfter() != null; + } + }; + } + + private static Predicate> hasNoDataBefore() { + return new Predicate>() { + @Override + public boolean apply(@Nullable DataObjectModification input) { + return input != null && input.getDataBefore() == null; + } + }; + } + + private static Predicate> hasDataAfterAndMatchesFilter( + final Predicate> filter) { + return new Predicate>() { + @Override + public boolean apply(@Nullable DataObjectModification input) { + return input != null && input.getDataAfter() != null && filter.apply(input); + } + }; + } + + private static Predicate> matchesEverything() { + return new Predicate>() { + @Override + public boolean apply(@Nullable DataObjectModification input) { + return true; + } + }; + } + + private static Predicate> modificationIsDeletion() { + return new Predicate>() { + @Override + public boolean apply(@Nullable DataObjectModification input) { + return input != null && input.getModificationType() == DataObjectModification + .ModificationType.DELETE; + } + }; + } + + private static Predicate> modificationIsDeletionAndHasDataBefore + () { + return new Predicate>() { + @Override + public boolean apply(@Nullable DataObjectModification input) { + return input != null && input.getModificationType() == DataObjectModification + .ModificationType.DELETE && input.getDataBefore() != null; + } + }; + } + public static Map,Node> extractNode( Map, DataObject> changes) { Map,Node> result @@ -72,11 +152,61 @@ public class TransactUtils { return extract(changes.getCreatedData(),klazz); } + /** + * Extract all the instances of {@code clazz} which were created in the given set of modifications. + * + * @param changes The changes to process. + * @param clazz The class we're interested in. + * @param The type of changes we're interested in. + * @param The type of changes to process. + * @return The created instances, mapped by instance identifier. + */ + public static Map, T> extractCreated( + Collection> changes, Class clazz) { + return extractCreatedOrUpdated(changes, clazz, hasNoDataBefore()); + } + + /** + * Extract all the instance of {@code clazz} which were created or updated in the given set of modifications, and + * which satisfy the given filter. + * + * @param changes The changes to process. + * @param clazz The class we're interested in. + * @param filter The filter the changes must satisfy. + * @param The type of changes we're interested in. + * @param The type of changes to process. + * @return The created or updated instances which satisfy the filter, mapped by instance identifier. + */ + public static Map, T> extractCreatedOrUpdated( + Collection> changes, Class clazz, + Predicate> filter) { + Map, T> result = new HashMap<>(); + for (Map.Entry, DataObjectModification> entry : extractDataObjectModifications(changes, + clazz, hasDataAfterAndMatchesFilter(filter)).entrySet()) { + result.put(entry.getKey(), entry.getValue().getDataAfter()); + } + return result; + } + public static Map,T> extractUpdated( AsyncDataChangeEvent,DataObject> changes,Class klazz) { return extract(changes.getUpdatedData(),klazz); } + /** + * Extract all the instances of {@code clazz} which were updated in the given set of modifications. + * + * @param changes The changes to process. + * @param clazz The class we're interested in. + * @param The type of changes we're interested in. + * @param The type of changes to process. + * @return The updated instances, mapped by instance identifier. + */ + public static Map, T> extractUpdated( + Collection> changes, Class clazz) { + return extractCreatedOrUpdated(changes, clazz, hasDataBeforeAndDataAfter()); + } + public static Map,T> extractCreatedOrUpdated( AsyncDataChangeEvent,DataObject> changes,Class klazz) { Map,T> result = extractUpdated(changes,klazz); @@ -84,6 +214,20 @@ public class TransactUtils { return result; } + /** + * Extract all the instances of {@code clazz} which were created or updated in the given set of modifications. + * + * @param changes The changes to process. + * @param clazz The class we're interested in. + * @param The type of changes we're interested in. + * @param The type of changes to process. + * @return The created or updated instances, mapped by instance identifier. + */ + public static Map, T> extractCreatedOrUpdated( + Collection> changes, Class clazz) { + return extractCreatedOrUpdated(changes, clazz, matchesEverything()); + } + public static Map, T> extractCreatedOrUpdatedOrRemoved( AsyncDataChangeEvent, DataObject> changes, Class klazz) { @@ -92,11 +236,49 @@ public class TransactUtils { return result; } + /** + * Extract all the instances of {@code clazz} which were created, updated, or removed in the given set of + * modifications. For instances which were created or updated, the new instances are returned; for instances + * which were removed, the old instances are returned. + * + * @param changes The changes to process. + * @param clazz The class we're interested in. + * @param The type of changes we're interested in. + * @param The type of changes to process. + * @return The created, updated or removed instances, mapped by instance identifier. + */ + public static Map, T> + extractCreatedOrUpdatedOrRemoved( + Collection> changes, Class clazz) { + Map, T> result = extractCreatedOrUpdated(changes, clazz); + result.putAll(extractRemovedObjects(changes, clazz)); + return result; + } + public static Map,T> extractOriginal( AsyncDataChangeEvent,DataObject> changes,Class klazz) { return extract(changes.getOriginalData(),klazz); } + /** + * Extract the original instances of class {@code clazz} in the given set of modifications. + * + * @param changes The changes to process. + * @param clazz The class we're interested in. + * @param The type of changes we're interested in. + * @param The type of changes to process. + * @return The original instances, mapped by instance identifier. + */ + public static Map, T> extractOriginal( + Collection> changes, Class clazz) { + Map, T> result = new HashMap<>(); + for (Map.Entry, DataObjectModification> entry : + extractDataObjectModifications(changes, clazz, hasDataBefore()).entrySet()) { + result.put(entry.getKey(), entry.getValue().getDataBefore()); + } + return result; + } + public static Set> extractRemoved( AsyncDataChangeEvent,DataObject> changes,Class klazz) { Set> result = new HashSet<>(); @@ -112,6 +294,108 @@ public class TransactUtils { return result; } + /** + * Extract the instance identifier of removed instances of {@code clazz} from the given set of modifications. + * + * @param changes The changes to process. + * @param clazz The class we're interested in. + * @param The type of changes we're interested in. + * @param The type of changes to process. + * @return The instance identifiers of removed instances. + */ + public static Set> extractRemoved( + Collection> changes, Class clazz) { + return extractDataObjectModifications(changes, clazz, modificationIsDeletion()).keySet(); + } + + /** + * Extract all the modifications affecting instances of {@code clazz} which are present in the given set of + * modifications and satisfy the given filter. + * + * @param changes The changes to process. + * @param clazz The class we're interested in. + * @param filter The filter the changes must satisfy. + * @param The type of changes we're interested in. + * @param The type of changes to process. + * @return The modifications, mapped by instance identifier. + */ + private static Map, DataObjectModification> + extractDataObjectModifications( + Collection> changes, Class clazz, + Predicate> filter) { + List> dataObjectModifications = new ArrayList<>(); + List> paths = new ArrayList<>(); + if (changes != null) { + for (DataTreeModification change : changes) { + dataObjectModifications.add(change.getRootNode()); + paths.add(change.getRootPath().getRootIdentifier()); + } + } + return extractDataObjectModifications(dataObjectModifications, paths, clazz, filter); + } + + /** + * Extract all the modifications affecting instances of {@code clazz} which are present in the given set of + * modifications and satisfy the given filter. + * + * @param changes The changes to process. + * @param paths The paths of the changes. + * @param clazz The class we're interested in. + * @param filter The filter the changes must satisfy. + * @param The type of changes we're interested in. + * @return The modifications, mapped by instance identifier. + */ + private static Map, DataObjectModification> + extractDataObjectModifications( + Collection> changes, + Collection> paths, Class clazz, + Predicate> filter) { + Map, DataObjectModification> result = new HashMap<>(); + Queue> remainingChanges = new LinkedList<>(changes); + Queue> remainingPaths = new LinkedList<>(paths); + while (!remainingChanges.isEmpty()) { + DataObjectModification change = remainingChanges.remove(); + InstanceIdentifier path = remainingPaths.remove(); + // Is the change relevant? + if (clazz.isAssignableFrom(change.getDataType()) && filter.apply((DataObjectModification) change)) { + result.put((InstanceIdentifier) path, (DataObjectModification) change); + } + // Add any children to the queue + for (DataObjectModification child : change.getModifiedChildren()) { + remainingChanges.add(child); + remainingPaths.add(extendPath(path, child)); + } + } + return result; + } + + /** + * Extends the given instance identifier path to include the given child. Augmentations are treated in the same way + * as children; keyed children are handled correctly. + * + * @param path The current path. + * @param child The child modification to include. + * @return The extended path. + */ + private static & ChildOf, K extends Identifier, T extends DataObject> + InstanceIdentifier extendPath( + InstanceIdentifier path, + DataObjectModification child) { + Class item = (Class) child.getDataType(); + if (child.getIdentifier() instanceof InstanceIdentifier.IdentifiableItem) { + K key = (K) ((InstanceIdentifier.IdentifiableItem) child.getIdentifier()).getKey(); + KeyedInstanceIdentifier extendedPath = path.child(item, key); + LOG.debug("Building a new child iid for {} with {} and key {}, resulting in {}", + path, item, extendedPath); + return extendedPath; + } else { + InstanceIdentifier extendedPath = path.child(item); + LOG.debug("Building a new child iid for {} with {}, resulting in {}", + path, item, extendedPath); + return extendedPath; + } + } + public static Map, T> extractRemovedObjects( AsyncDataChangeEvent, DataObject> changes, Class klazz) { @@ -119,6 +403,25 @@ public class TransactUtils { return Maps.filterKeys(extractOriginal(changes, klazz),Predicates.in(iids)); } + /** + * Extract the removed instances of {@code clazz} from the given set of modifications. + * + * @param changes The changes to process. + * @param clazz The class we're interested in. + * @param The type of changes we're interested in. + * @param The type of changes to process. + * @return The removed instances, keyed by instance identifier. + */ + public static Map, T> extractRemovedObjects( + Collection> changes, Class clazz) { + Map, T> result = new HashMap<>(); + for (Map.Entry, DataObjectModification> entry : + extractDataObjectModifications(changes, clazz, modificationIsDeletionAndHasDataBefore()).entrySet()) { + result.put(entry.getKey(), entry.getValue().getDataBefore()); + } + return result; + } + public static Map,T> extract( Map, DataObject> changes, Class klazz) { Map,T> result = new HashMap<>(); diff --git a/southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/OvsdbDataChangeListenerTest.java b/southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/OvsdbDataChangeListenerTest.java index 3db9470fe..d5cdba818 100644 --- a/southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/OvsdbDataChangeListenerTest.java +++ b/southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/OvsdbDataChangeListenerTest.java @@ -125,7 +125,9 @@ public class OvsdbDataChangeListenerTest { any(InstanceIdentifier.class), any(AsyncDataChangeEvent.class)).thenReturn(dataChangesManagedByOvsdbNodeEvent); - PowerMockito.whenNew(BridgeOperationalState.class).withArguments(any(DataBroker.class), any(AsyncDataChangeEvent.class)).thenReturn(bridgeOperationalState); + PowerMockito.whenNew(BridgeOperationalState.class.getConstructor(DataBroker.class, + AsyncDataChangeEvent.class)).withArguments(any(DataBroker.class), + any(AsyncDataChangeEvent.class)).thenReturn(bridgeOperationalState); when(connectionInstance.getInstanceIdentifier()).thenReturn(iid); doNothing().when(connectionInstance).transact(any(TransactCommandAggregator.class), eq(bridgeOperationalState), diff --git a/southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/OvsdbDataTreeChangeListenerTest.java b/southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/OvsdbDataTreeChangeListenerTest.java new file mode 100644 index 000000000..6b546e82e --- /dev/null +++ b/southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/OvsdbDataTreeChangeListenerTest.java @@ -0,0 +1,74 @@ +/* + * Copyright © 2016 Red Hat, Inc. and others. + * + * 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.ovsdb.southbound; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.concurrent.ExecutionException; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest; +import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.ovsdb.lib.OvsdbConnection; +import org.opendaylight.ovsdb.southbound.transactions.md.TransactionInvokerImpl; +import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes + .ConnectionInfoBuilder; +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.InstanceIdentifier; + +/** + * Unit tests for the data-tree change listener. + */ +public class OvsdbDataTreeChangeListenerTest extends AbstractDataBrokerTest { + private final OvsdbConnection ovsdbConnection = Mockito.mock(OvsdbConnection.class); + private DataBroker dataBroker; + private OvsdbDataTreeChangeListener listener; + + @Before + public void setupListener() { + dataBroker = getDataBroker(); + EntityOwnershipService entityOwnershipService = Mockito.mock(EntityOwnershipService.class); + listener = new OvsdbDataTreeChangeListener(dataBroker, + new OvsdbConnectionManager(dataBroker, new TransactionInvokerImpl(dataBroker), entityOwnershipService, + ovsdbConnection)); + } + + @Test + public void testConnect() throws UnknownHostException, InterruptedException, ExecutionException { + // Given ... + + // When we request a connection ... + InetAddress inetAddress = InetAddress.getByName("127.0.0.1"); + int port = 6640; + IpAddress ipAddress = SouthboundMapper.createIpAddress(inetAddress); + PortNumber portNumber = new PortNumber(port); + + final ConnectionInfo connectionInfo = new ConnectionInfoBuilder() + .setRemoteIp(ipAddress) + .setRemotePort(portNumber) + .build(); + final InstanceIdentifier iid = SouthboundUtils.createInstanceIdentifier(connectionInfo); + WriteTransaction transaction = dataBroker.newWriteOnlyTransaction(); + transaction.put(LogicalDatastoreType.CONFIGURATION, iid, SouthboundUtils.createNode(connectionInfo), + WriteTransaction.CREATE_MISSING_PARENTS); + transaction.submit().get(); + + // Then the listener tries to open a connection + Mockito.verify(ovsdbConnection).connect(inetAddress, port); + } +} -- 2.36.6