Bug 2107: Use DataCommitListeners for inventory events 05/11705/5
authorEd Warnicke <eaw@cisco.com>
Wed, 1 Oct 2014 16:40:29 +0000 (09:40 -0700)
committerEd Warnicke <eaw@cisco.com>
Wed, 1 Oct 2014 21:06:26 +0000 (14:06 -0700)
Change-Id: I648bba5e7585cc9d1a70f3dcaf6f8fdbcfeb1787
Signed-off-by: Ed Warnicke <eaw@cisco.com>
opendaylight/karaf-branding/.gitignore [new file with mode: 0644]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/AbstractDataChangeListener.java [new file with mode: 0644]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.java
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NCDataChangeListener.java [new file with mode: 0644]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeDataChangeListener.java [new file with mode: 0644]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/SalCompatibilityProvider.java

diff --git a/opendaylight/karaf-branding/.gitignore b/opendaylight/karaf-branding/.gitignore
new file mode 100644 (file)
index 0000000..b83d222
--- /dev/null
@@ -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 (file)
index 0000000..2306508
--- /dev/null
@@ -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 <T extends DataObject> implements AutoCloseable,DataChangeListener{
+
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractDataChangeListener.class);
+    protected InventoryAndReadAdapter adapter;
+    protected final Class<T> clazz;
+    protected ListenerRegistration<DataChangeListener> listenerRegistration;
+
+    public AbstractDataChangeListener(final InventoryAndReadAdapter adapter, DataBroker db, final Class<T> 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<InstanceIdentifier<?>, DataObject> changeEvent) {
+        Preconditions.checkNotNull(changeEvent,"Async ChangeEvent can not be null!");
+        /* All DataObjects for create */
+        final Map<InstanceIdentifier<?>, DataObject> createdData = changeEvent.getCreatedData() != null
+                ? changeEvent.getCreatedData() : Collections.<InstanceIdentifier<?>, DataObject> emptyMap();
+        /* All DataObjects for remove */
+        final Set<InstanceIdentifier<?>> removeData = changeEvent.getRemovedPaths() != null
+                ? changeEvent.getRemovedPaths() : Collections.<InstanceIdentifier<?>> emptySet();
+        /* All DataObjects for updates */
+        final Map<InstanceIdentifier<?>, DataObject> updateData = changeEvent.getUpdatedData() != null
+                ? changeEvent.getUpdatedData() : Collections.<InstanceIdentifier<?>, DataObject> emptyMap();
+        /* All Original DataObjects */
+        final Map<InstanceIdentifier<?>, DataObject> originalData = changeEvent.getOriginalData() != null
+                ? changeEvent.getOriginalData() : Collections.<InstanceIdentifier<?>, DataObject> emptyMap();
+        this.createData(createdData);
+        this.updateData(updateData, originalData);
+        this.removeData(removeData, originalData);
+    }
+
+    @SuppressWarnings("unchecked")
+    private void createData(final Map<InstanceIdentifier<?>, DataObject> createdData) {
+        final Set<InstanceIdentifier<?>> keys = createdData.keySet() != null
+                ? createdData.keySet() : Collections.<InstanceIdentifier<?>> emptySet();
+        for (InstanceIdentifier<?> key : keys) {
+            if (clazz.equals(key.getTargetType())) {
+                InstanceIdentifier<T> createKeyIdent = key.firstIdentifierOf(clazz);
+                final Optional<DataObject> value = Optional.of(createdData.get(key));
+                if (value.isPresent()) {
+                    this.add(createKeyIdent, (T)value.get());
+                }
+            }
+        }
+    }
+
+    abstract protected void add(InstanceIdentifier<T> createKeyIdent, T node);
+
+    @SuppressWarnings("unchecked")
+    private void updateData(final Map<InstanceIdentifier<?>, DataObject> updateData, final Map<InstanceIdentifier<?>, DataObject> originalData) {
+
+        final Set<InstanceIdentifier<?>> keys = updateData.keySet() != null
+                ? updateData.keySet() : Collections.<InstanceIdentifier<?>> emptySet();
+        for (InstanceIdentifier<?> key : keys) {
+            if (clazz.equals(key.getTargetType())) {
+                InstanceIdentifier<T> updateKeyIdent = key.firstIdentifierOf(clazz);
+                final Optional<DataObject> value = Optional.of(updateData.get(key));
+                final Optional<DataObject> 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<T> updateKeyIdent, T node,
+            T node2);
+
+    @SuppressWarnings("unchecked")
+    private void removeData(final Set<InstanceIdentifier<?>> removeData, final Map<InstanceIdentifier<?>, DataObject> originalData) {
+
+        for (InstanceIdentifier<?> key : removeData) {
+            if (clazz.equals(key.getTargetType())) {
+                final InstanceIdentifier<T> ident = key.firstIdentifierOf(clazz);
+                final DataObject removeValue = originalData.get(key);
+                this.remove(ident, (T)removeValue);
+            }
+        }
+    }
+
+    abstract protected void remove(InstanceIdentifier<T> 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
index 1530e90..bbb6673 100644 (file)
@@ -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 (file)
index 0000000..d93d40d
--- /dev/null
@@ -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<NodeConnector> {
+    private static final Logger LOG = LoggerFactory.getLogger(NodeDataChangeListener.class);
+    private ListenerRegistration<DataChangeListener> listenerRegistration;
+    public NCDataChangeListener (final InventoryAndReadAdapter adapter, final DataBroker db) {
+        super(adapter,db,NodeConnector.class);
+    }
+
+    @Override
+    protected void add(InstanceIdentifier<NodeConnector> 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<NodeConnector> updateKeyIdent, NodeConnector original,
+            NodeConnector update) {
+        add(updateKeyIdent,update);
+    }
+
+    @Override
+    protected void remove(InstanceIdentifier<NodeConnector> ident, NodeConnector removeValue) {
+        NodeConnectorRemovedBuilder builder = new NodeConnectorRemovedBuilder();
+        builder.setNodeConnectorRef(new NodeConnectorRef(ident));
+        adapter.onNodeConnectorRemovedInternal(builder.build());
+    }
+
+    protected InstanceIdentifier<NodeConnector> 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 (file)
index 0000000..cdb2616
--- /dev/null
@@ -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<Node> {
+    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<Node> 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<Node> updateKeyIdent, Node original,
+            Node update) {
+        this.add(updateKeyIdent, update);
+    }
+
+    protected void remove(InstanceIdentifier<Node> ident, Node removeValue) {
+        NodeRemovedBuilder builder = new NodeRemovedBuilder();
+        builder.setNodeRef(new NodeRef(ident));
+        adapter.onNodeRemovedInternal(builder.build());
+    }
+
+    protected InstanceIdentifier<Node> getWildCardPath() {
+        return InstanceIdentifier.create(Nodes.class).child(Node.class);
+    }
+
+}
index 0ddbcaa..f8f2b37 100644 (file)
@@ -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);