From e062c06cd7ca669e3fc2200a43c11c5ed3b20f04 Mon Sep 17 00:00:00 2001 From: Ed Warnicke Date: Wed, 1 Oct 2014 09:40:29 -0700 Subject: [PATCH 1/1] Bug 2107: Use DataCommitListeners for inventory events Change-Id: I648bba5e7585cc9d1a70f3dcaf6f8fdbcfeb1787 Signed-off-by: Ed Warnicke --- opendaylight/karaf-branding/.gitignore | 1 + .../AbstractDataChangeListener.java | 146 ++++++++++++++++++ .../InventoryAndReadAdapter.java | 19 +-- .../compatibility/NCDataChangeListener.java | 62 ++++++++ .../compatibility/NodeDataChangeListener.java | 59 +++++++ .../SalCompatibilityProvider.java | 5 + 6 files changed, 280 insertions(+), 12 deletions(-) create mode 100644 opendaylight/karaf-branding/.gitignore create mode 100644 opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/AbstractDataChangeListener.java create mode 100644 opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NCDataChangeListener.java create mode 100644 opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeDataChangeListener.java diff --git a/opendaylight/karaf-branding/.gitignore b/opendaylight/karaf-branding/.gitignore new file mode 100644 index 0000000000..b83d22266a --- /dev/null +++ b/opendaylight/karaf-branding/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/AbstractDataChangeListener.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/AbstractDataChangeListener.java new file mode 100644 index 0000000000..2306508759 --- /dev/null +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/AbstractDataChangeListener.java @@ -0,0 +1,146 @@ +/** + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.sal.compatibility; + +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; + +public abstract class AbstractDataChangeListener implements AutoCloseable,DataChangeListener{ + + private static final Logger LOG = LoggerFactory.getLogger(AbstractDataChangeListener.class); + protected InventoryAndReadAdapter adapter; + protected final Class clazz; + protected ListenerRegistration listenerRegistration; + + public AbstractDataChangeListener(final InventoryAndReadAdapter adapter, DataBroker db, final Class clazz) { + this.adapter = Preconditions.checkNotNull(adapter, "InventoryAndReadAdapter can not be null!"); + this.clazz = Preconditions.checkNotNull(clazz, "Class can not be null!"); + Preconditions.checkNotNull(db, "DataBroker can not be null!"); + registrationListener(db, 5); + } + + @Override + public void onDataChanged(AsyncDataChangeEvent, DataObject> changeEvent) { + Preconditions.checkNotNull(changeEvent,"Async ChangeEvent can not be null!"); + /* All DataObjects for create */ + final Map, DataObject> createdData = changeEvent.getCreatedData() != null + ? changeEvent.getCreatedData() : Collections., DataObject> emptyMap(); + /* All DataObjects for remove */ + final Set> removeData = changeEvent.getRemovedPaths() != null + ? changeEvent.getRemovedPaths() : Collections.> emptySet(); + /* All DataObjects for updates */ + final Map, DataObject> updateData = changeEvent.getUpdatedData() != null + ? changeEvent.getUpdatedData() : Collections., DataObject> emptyMap(); + /* All Original DataObjects */ + final Map, DataObject> originalData = changeEvent.getOriginalData() != null + ? changeEvent.getOriginalData() : Collections., DataObject> emptyMap(); + this.createData(createdData); + this.updateData(updateData, originalData); + this.removeData(removeData, originalData); + } + + @SuppressWarnings("unchecked") + private void createData(final Map, DataObject> createdData) { + final Set> keys = createdData.keySet() != null + ? createdData.keySet() : Collections.> emptySet(); + for (InstanceIdentifier key : keys) { + if (clazz.equals(key.getTargetType())) { + InstanceIdentifier createKeyIdent = key.firstIdentifierOf(clazz); + final Optional value = Optional.of(createdData.get(key)); + if (value.isPresent()) { + this.add(createKeyIdent, (T)value.get()); + } + } + } + } + + abstract protected void add(InstanceIdentifier createKeyIdent, T node); + + @SuppressWarnings("unchecked") + private void updateData(final Map, DataObject> updateData, final Map, DataObject> originalData) { + + final Set> keys = updateData.keySet() != null + ? updateData.keySet() : Collections.> emptySet(); + for (InstanceIdentifier key : keys) { + if (clazz.equals(key.getTargetType())) { + InstanceIdentifier updateKeyIdent = key.firstIdentifierOf(clazz); + final Optional value = Optional.of(updateData.get(key)); + final Optional original = Optional.of(originalData.get(key)); + if (value.isPresent() && original.isPresent()) { + this.update(updateKeyIdent, (T)original.get(), (T)value.get()); + } + } + } + } + + abstract protected void update(InstanceIdentifier updateKeyIdent, T node, + T node2); + + @SuppressWarnings("unchecked") + private void removeData(final Set> removeData, final Map, DataObject> originalData) { + + for (InstanceIdentifier key : removeData) { + if (clazz.equals(key.getTargetType())) { + final InstanceIdentifier ident = key.firstIdentifierOf(clazz); + final DataObject removeValue = originalData.get(key); + this.remove(ident, (T)removeValue); + } + } + } + + abstract protected void remove(InstanceIdentifier ident, T removeValue); + + protected void registrationListener(final DataBroker db, int i) { + try { + listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, + getWildCardPath(), this, DataChangeScope.BASE); + } catch (final Exception e) { + if (i >= 1) { + try { + Thread.sleep(100); + } catch (InterruptedException e1) { + LOG.error("Thread interrupted '{}'", e1); + Thread.currentThread().interrupt(); + } + registrationListener(db, --i); + } else { + LOG.error("AbstractDataChangeListener registration fail!", e); + throw new IllegalStateException("AbstractDataChangeListener registration Listener fail! System needs restart.", e); + } + } + } + + protected abstract InstanceIdentifier getWildCardPath(); + + @Override + public void close() { + if (listenerRegistration != null) { + try { + listenerRegistration.close(); + } catch (final Exception e) { + LOG.error("Error by stop AbstractDataChangeListener.", e); + } + listenerRegistration = null; + } + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.java index 1530e909ad..bbb6673a8e 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.java +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.java @@ -7,8 +7,6 @@ */ package org.opendaylight.controller.sal.compatibility; -import com.google.common.collect.Iterables; - import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -70,7 +68,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemoved; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.OpendaylightInventoryListener; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.GenericStatistics; @@ -89,7 +86,9 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class InventoryAndReadAdapter implements IPluginInReadService, IPluginInInventoryService, OpendaylightInventoryListener, OpendaylightFlowStatisticsListener, OpendaylightFlowTableStatisticsListener, OpendaylightPortStatisticsListener { +import com.google.common.collect.Iterables; + +public class InventoryAndReadAdapter implements IPluginInReadService, IPluginInInventoryService, OpendaylightFlowStatisticsListener, OpendaylightFlowTableStatisticsListener, OpendaylightPortStatisticsListener { private static final Logger LOG = LoggerFactory.getLogger(InventoryAndReadAdapter.class); private static final short OPENFLOWV10_TABLE_ID = 0; @@ -398,13 +397,11 @@ public class InventoryAndReadAdapter implements IPluginInReadService, IPluginInI return nodeStats; } - @Override - public void onNodeConnectorRemoved(final NodeConnectorRemoved update) { + public void onNodeConnectorRemovedInternal(final NodeConnectorRemoved update) { // Never received } - @Override - public void onNodeRemoved(final NodeRemoved notification) { + public void onNodeRemovedInternal(final NodeRemoved notification) { this.removeNodeConnectors(notification.getNodeRef().getValue()); try { final Node aDNode = NodeMapping.toADNode(notification.getNodeRef()); @@ -414,8 +411,7 @@ public class InventoryAndReadAdapter implements IPluginInReadService, IPluginInI } } - @Override - public void onNodeConnectorUpdated(final NodeConnectorUpdated update) { + public void onNodeConnectorUpdatedInternal(final NodeConnectorUpdated update) { final NodeConnectorRef ref = update.getNodeConnectorRef(); final UpdateType updateType; if (!this.isKnownNodeConnector(ref.getValue())) { @@ -434,8 +430,7 @@ public class InventoryAndReadAdapter implements IPluginInReadService, IPluginInI } } - @Override - public void onNodeUpdated(final NodeUpdated notification) { + public void onNodeUpdatedInternal(final NodeUpdated notification) { final NodeRef ref = notification.getNodeRef(); final UpdateType updateType; diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NCDataChangeListener.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NCDataChangeListener.java new file mode 100644 index 0000000000..d93d40d2a6 --- /dev/null +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NCDataChangeListener.java @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.sal.compatibility; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorUpdated; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorUpdatedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemovedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdatedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NCDataChangeListener extends AbstractDataChangeListener { + private static final Logger LOG = LoggerFactory.getLogger(NodeDataChangeListener.class); + private ListenerRegistration listenerRegistration; + public NCDataChangeListener (final InventoryAndReadAdapter adapter, final DataBroker db) { + super(adapter,db,NodeConnector.class); + } + + @Override + protected void add(InstanceIdentifier createKeyIdent, NodeConnector node) { + FlowCapableNodeConnector fcnc = node.getAugmentation(FlowCapableNodeConnector.class); + if(fcnc != null) { + FlowCapableNodeConnectorUpdatedBuilder fcncub = new FlowCapableNodeConnectorUpdatedBuilder(fcnc); + NodeConnectorUpdatedBuilder builder = new NodeConnectorUpdatedBuilder(); + builder.setId(node.getId()); + builder.setNodeConnectorRef(new NodeConnectorRef(createKeyIdent)); + builder.addAugmentation(FlowCapableNodeConnectorUpdated.class, fcncub.build()); + adapter.onNodeConnectorUpdatedInternal(builder.build()); + } + } + + @Override + protected void update(InstanceIdentifier updateKeyIdent, NodeConnector original, + NodeConnector update) { + add(updateKeyIdent,update); + } + + @Override + protected void remove(InstanceIdentifier ident, NodeConnector removeValue) { + NodeConnectorRemovedBuilder builder = new NodeConnectorRemovedBuilder(); + builder.setNodeConnectorRef(new NodeConnectorRef(ident)); + adapter.onNodeConnectorRemovedInternal(builder.build()); + } + + protected InstanceIdentifier getWildCardPath() { + return InstanceIdentifier.create(Nodes.class).child(Node.class).child(NodeConnector.class); + } +} diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeDataChangeListener.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeDataChangeListener.java new file mode 100644 index 0000000000..cdb26162c0 --- /dev/null +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeDataChangeListener.java @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.sal.compatibility; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdatedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemovedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdatedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NodeDataChangeListener extends AbstractDataChangeListener { + private static final Logger LOG = LoggerFactory.getLogger(NodeDataChangeListener.class); + + + public NodeDataChangeListener (final InventoryAndReadAdapter adapter, final DataBroker db) { + super(adapter,db,Node.class); + } + + protected void add(InstanceIdentifier createKeyIdent, Node node) { + FlowCapableNode fcn = node.getAugmentation(FlowCapableNode.class); + if(fcn != null) { + FlowCapableNodeUpdatedBuilder fcbnu = new FlowCapableNodeUpdatedBuilder(fcn); + NodeUpdatedBuilder builder = new NodeUpdatedBuilder(); + builder.setId(node.getId()); + builder.setNodeRef(new NodeRef(createKeyIdent)); + builder.setNodeConnector(node.getNodeConnector()); + builder.addAugmentation(FlowCapableNodeUpdated.class, fcbnu.build()); + adapter.onNodeUpdatedInternal(builder.build()); + } + } + + protected void update(InstanceIdentifier updateKeyIdent, Node original, + Node update) { + this.add(updateKeyIdent, update); + } + + protected void remove(InstanceIdentifier ident, Node removeValue) { + NodeRemovedBuilder builder = new NodeRemovedBuilder(); + builder.setNodeRef(new NodeRef(ident)); + adapter.onNodeRemovedInternal(builder.build()); + } + + protected InstanceIdentifier getWildCardPath() { + return InstanceIdentifier.create(Nodes.class).child(Node.class); + } + +} diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/SalCompatibilityProvider.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/SalCompatibilityProvider.java index 0ddbcaa2e0..f8f2b37819 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/SalCompatibilityProvider.java +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/SalCompatibilityProvider.java @@ -10,6 +10,7 @@ package org.opendaylight.controller.sal.compatibility; import java.util.Collection; import java.util.Collections; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext; import org.opendaylight.controller.sal.binding.api.BindingAwareProvider; @@ -68,6 +69,10 @@ class SalCompatibilityProvider implements BindingAwareProvider { inv.setNodeConnectorStatisticsService(session.getRpcService(OpendaylightPortStatisticsService.class)); inv.setTopologyDiscovery(session.getRpcService(FlowTopologyDiscoveryService.class)); inv.setDataProviderService(session.getSALService(DataProviderService.class)); + + final NodeDataChangeListener ndcl = new NodeDataChangeListener(inv,session.getSALService(DataBroker.class)); + final NCDataChangeListener ncdcl = new NCDataChangeListener(inv,session.getSALService(DataBroker.class)); + // FIXME: remember registration for clean shutdown subscribe.registerNotificationListener(inv); -- 2.36.6