Merge "Bug 5936 - DeviceFlowRegistry flowId bug"
authorJozef Bacigal <jbacigal@cisco.com>
Tue, 28 Jun 2016 08:40:29 +0000 (08:40 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 28 Jun 2016 08:40:29 +0000 (08:40 +0000)
16 files changed:
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/registry/flow/DeviceFlowRegistry.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/registry/flow/FlowRegistryKey.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/LifecycleConductorImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/registry/flow/DeviceFlowRegistryImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/registry/flow/FlowRegistryKeyFactory.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsGatheringUtils.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/FlowDirectStatisticsService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/FlowUtil.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/LifecycleConductorImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/registry/flow/DeviceFlowRegistryImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/MultipartRequestOnTheFlyCallbackTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/ServiceMocking.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsGatheringUtilsTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsManagerImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/services/direct/FlowDirectStatisticsServiceTest.java

index ab4da891c03710cddda8f6cdcbde7b1d8e89cf84..d410766d6236b084299cacfc7ad319ccfa1c8649 100644 (file)
@@ -11,17 +11,22 @@ package org.opendaylight.openflowplugin.api.openflow.registry.flow;
 
 import java.util.Map;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 
 /**
  * Created by Martin Bobak &lt;mbobak@cisco.com&gt; on 8.4.2015.
  */
 public interface DeviceFlowRegistry extends AutoCloseable {
 
+    void fill(KeyedInstanceIdentifier<Node, NodeKey> instanceIdentifier);
+
     FlowDescriptor retrieveIdForFlow(FlowRegistryKey flowRegistryKey);
 
     void store(FlowRegistryKey flowRegistryKey, FlowDescriptor flowDescriptor);
 
-    FlowId storeIfNecessary(FlowRegistryKey flowRegistryKey, short tableId);
+    FlowId storeIfNecessary(FlowRegistryKey flowRegistryKey);
 
     void markToBeremoved(FlowRegistryKey flowRegistryKey);
 
index 9460552a438edc2f0d08199c5ec1c952dafeda65..7a3869a243fa9f9b73f45d46ee978adf6d1a1cf5 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.openflowplugin.api.openflow.registry.flow;
 
 import java.math.BigInteger;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
 
 /**
  * Marker interface identifying flow stored in OFP local flow registry.
@@ -22,5 +23,5 @@ public interface FlowRegistryKey {
 
     BigInteger getCookie();
 
-
+    Match getMatch();
 }
index 74c7f39d5422164f6d6ae66e08746da9bd8cb7d8..d265336b5eaf725dc4afed72700972afcd6c9741 100644 (file)
@@ -179,6 +179,9 @@ final class LifecycleConductorImpl implements LifecycleConductor, RoleChangeList
                             notificationPublishService,
                             new AtomicLong());
                 }
+
+                // Fill flow registry with flows found in operational and config datastore
+                deviceContext.getDeviceFlowRegistry().fill(deviceInfo.getNodeInstanceIdentifier());
             } else {
                 logText = "Stopp";
                 statisticsManager.stopScheduling(deviceInfo);
index f85f29d06f5d6f717090a55095385e0b37b78673..5fb487c2cf408cc0546222e176214e8c1b852b3a 100644 (file)
@@ -148,7 +148,7 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
         deviceInfo = primaryConnectionContext.getDeviceInfo();
         this.transactionChainManager = new TransactionChainManager(dataBroker, deviceInfo, conductor);
         auxiliaryConnectionContexts = new HashMap<>();
-        deviceFlowRegistry = new DeviceFlowRegistryImpl();
+        deviceFlowRegistry = new DeviceFlowRegistryImpl(dataBroker);
         deviceGroupRegistry = new DeviceGroupRegistryImpl();
         deviceMeterRegistry = new DeviceMeterRegistryImpl();
         messageSpy = conductor.getMessageIntelligenceAgency();
index 9c4660e981405990495b6b11400cdae733cc4317..03bcc5bed6413af79cd0ca2d721f31cb98681343 100644 (file)
@@ -7,18 +7,33 @@
  */
 package org.opendaylight.openflowplugin.impl.registry.flow;
 
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
 import com.romix.scala.collection.concurrent.TrieMap;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutionException;
 import javax.annotation.concurrent.GuardedBy;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowDescriptor;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
 import org.opendaylight.openflowplugin.impl.util.FlowUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -31,10 +46,106 @@ public class DeviceFlowRegistryImpl implements DeviceFlowRegistry {
     private final ConcurrentMap<FlowRegistryKey, FlowDescriptor> flowRegistry = new TrieMap<>();
     @GuardedBy("marks")
     private final Collection<FlowRegistryKey> marks = new HashSet<>();
+    private final DataBroker dataBroker;
+
+    public DeviceFlowRegistryImpl(final DataBroker dataBroker) {
+        this.dataBroker = dataBroker;
+    }
+
+    @Override
+    public void fill(final KeyedInstanceIdentifier<Node, NodeKey> instanceIdentifier) {
+        LOG.trace("Filling flow registry with flows for node: {}", instanceIdentifier);
+
+        // Prepare path for read transaction
+        // TODO: Read only Tables, and not entire FlowCapableNode (fix Yang model)
+        final InstanceIdentifier<FlowCapableNode> path = instanceIdentifier.augmentation(FlowCapableNode.class);
+
+        // First, try to fill registry with flows from DS/Configuration
+        fillFromDatastore(LogicalDatastoreType.CONFIGURATION, path);
+
+        // Now, try to fill registry with flows from DS/Operational
+        // in case of cluster fail over, when clients are not using DS/Configuration
+        // for adding flows, but only RPCs
+        fillFromDatastore(LogicalDatastoreType.OPERATIONAL, path);
+    }
+
+    private void fillFromDatastore(final LogicalDatastoreType logicalDatastoreType, final InstanceIdentifier<FlowCapableNode> path) {
+        // Create new read-only transaction
+        final ReadOnlyTransaction transaction = dataBroker.newReadOnlyTransaction();
+
+        // Bail out early if transaction is null
+        if (transaction == null) {
+            return;
+        }
+
+        // Prepare read operation from datastore for path
+        final CheckedFuture<Optional<FlowCapableNode>, ReadFailedException> future =
+                transaction.read(logicalDatastoreType, path);
+
+        // Bail out early if future is null
+        if (future == null) {
+            return;
+        }
+
+        try {
+            // Synchronously read all data in path
+            final Optional<FlowCapableNode> data = future.get();
+
+            if (data.isPresent()) {
+                final List<Table> tables = data.get().getTable();
+
+                if (tables != null) {
+                    for (Table table : tables) {
+                        final List<Flow> flows = table.getFlow();
+
+                        if (flows != null) {
+                            // If we finally got some flows, store each of them in registry if needed
+                            for (Flow flow : table.getFlow()) {
+                                final FlowRegistryKey key = FlowRegistryKeyFactory.create(flow);
+
+                                // Now, we will update the registry, but we will also try to prevent duplicate entries
+                                if (!flowRegistry.containsKey(key)) {
+                                    LOG.trace("Reading and storing flowDescriptor with table ID : {} and flow ID : {}",
+                                            flow.getTableId(),
+                                            flow.getId().getValue());
+
+                                    final FlowDescriptor descriptor = FlowDescriptorFactory.create(
+                                            flow.getTableId(),
+                                            flow.getId());
+
+                                    flowRegistry.put(key, descriptor);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error("Read transaction for identifier {} failed with exception: {}", path, e);
+        }
+
+        // After we are done with reading from datastore, close the transaction
+        transaction.close();
+    }
 
     @Override
     public FlowDescriptor retrieveIdForFlow(final FlowRegistryKey flowRegistryKey) {
+        LOG.trace("Trying to retrieve flowDescriptor for flow hash: {}", flowRegistryKey.hashCode());
+
+        // First, try to get FlowDescriptor from flow registry
         FlowDescriptor flowDescriptor = flowRegistry.get(flowRegistryKey);
+
+        // We was not able to retrieve FlowDescriptor, so we will at least try to generate it
+        if (flowDescriptor == null) {
+            final short tableId = flowRegistryKey.getTableId();
+            final FlowId alienFlowId = FlowUtil.createAlienFlowId(tableId);
+            flowDescriptor = FlowDescriptorFactory.create(tableId, alienFlowId);
+
+            // Finally we got flowDescriptor, so now we will store it to registry,
+            // so next time we won't need to generate it again
+            store(flowRegistryKey, flowDescriptor);
+        }
+
         return flowDescriptor;
     }
 
@@ -45,18 +156,10 @@ public class DeviceFlowRegistryImpl implements DeviceFlowRegistry {
     }
 
     @Override
-    public FlowId storeIfNecessary(final FlowRegistryKey flowRegistryKey, @Deprecated final short tableId) {
-        //TODO: remove tableId parameter - it is contained in the first one
-        final FlowId alienFlowId = FlowUtil.createAlienFlowId(tableId);
-        final FlowDescriptor alienFlowDescriptor = FlowDescriptorFactory.create(tableId, alienFlowId);
-
-        final FlowDescriptor previous = flowRegistry.putIfAbsent(flowRegistryKey, alienFlowDescriptor);
-        if (previous == null) {
-            LOG.trace("Flow descriptor for flow hash {} wasn't found.", flowRegistryKey.hashCode());
-            return alienFlowId;
-        } else {
-            return previous.getFlowId();
-        }
+    public FlowId storeIfNecessary(final FlowRegistryKey flowRegistryKey) {
+        // We will simply reuse retrieveIdForFlow to get or generate FlowDescriptor and store it if needed
+        final FlowDescriptor flowDescriptor = retrieveIdForFlow(flowRegistryKey);
+        return flowDescriptor.getFlowId();
     }
 
     @Override
index 80d5c7e3ba034d11566d94056dd22afe685088ca..195626bf28dd2c1c0066485ab77111ccd592dde1 100644 (file)
@@ -49,23 +49,16 @@ public class FlowRegistryKeyFactory {
             if (this == o) {
                 return true;
             }
-            if (o == null || getClass() != o.getClass()) {
-                return false;
-            }
-
-            final FlowRegistryKeyDto that = (FlowRegistryKeyDto) o;
 
-            if (priority != that.priority) {
-                return false;
-            }
-            if (tableId != that.tableId) {
-                return false;
-            }
-            if (!match.equals(that.match)) {
+            if (o == null || !(o instanceof FlowRegistryKey)) {
                 return false;
             }
 
-            return true;
+            final FlowRegistryKey that = (FlowRegistryKey) o;
+
+            return getPriority() == that.getPriority() &&
+                    getTableId() == that.getTableId() &&
+                    getMatch().equals(that.getMatch());
         }
 
         @Override
@@ -90,5 +83,10 @@ public class FlowRegistryKeyFactory {
         public BigInteger getCookie() {
             return cookie;
         }
+
+        @Override
+        public Match getMatch() {
+            return match;
+        }
     }
 }
index afe4d0085a704ae165c3c870da2ee33f424c7c2d..e482a7f792b3428133d55150dad39d3536eda852 100644 (file)
@@ -281,7 +281,7 @@ public final class StatisticsGatheringUtils {
 
                     final short tableId = flowStat.getTableId();
                     final FlowRegistryKey flowRegistryKey = FlowRegistryKeyFactory.create(flowBuilder.build());
-                    final FlowId flowId = registry.storeIfNecessary(flowRegistryKey, tableId);
+                    final FlowId flowId = registry.storeIfNecessary(flowRegistryKey);
 
                     final FlowKey flowKey = new FlowKey(flowId);
                     flowBuilder.setKey(flowKey);
index edfede1aef7d0df584a168d6177ec7db3242db2d..66c8a93679c9d90334477205c4e5bb16f2fd60ef 100644 (file)
@@ -158,8 +158,7 @@ public class FlowDirectStatisticsService extends AbstractDirectStatisticsService
         final FlowBuilder flowBuilder = new FlowBuilder(flowStatistics)
                 .addAugmentation(FlowStatisticsData.class, flowStatisticsDataBld.build());
 
-        final short tableId = flowStatistics.getTableId();
         final FlowRegistryKey flowRegistryKey = FlowRegistryKeyFactory.create(flowBuilder.build());
-        return getDeviceRegistry().getDeviceFlowRegistry().storeIfNecessary(flowRegistryKey, tableId);
+        return getDeviceRegistry().getDeviceFlowRegistry().storeIfNecessary(flowRegistryKey);
     }
 }
index a16e27a7db2b69042232e5e8e2ec2fca117800c3..931532e41e5e7c404619ff8aa5a12e095194524f 100644 (file)
@@ -56,15 +56,21 @@ public final class FlowUtil {
     private static final RpcResultBuilder<List<BatchFailedFlowsOutput>> SUCCESSFUL_FLOW_OUTPUT_RPC_RESULT =
             RpcResultBuilder.success(Collections.<BatchFailedFlowsOutput>emptyList());
 
-    /** Attach barrier response to given {@link RpcResult}&lt;RemoveFlowsBatchOutput&gt; */
+    /**
+     * Attach barrier response to given {@link RpcResult}&lt;RemoveFlowsBatchOutput&gt;
+     */
     public static final Function<Pair<RpcResult<RemoveFlowsBatchOutput>, RpcResult<Void>>, RpcResult<RemoveFlowsBatchOutput>>
             FLOW_REMOVE_COMPOSING_TRANSFORM = createComposingFunction();
 
-    /** Attach barrier response to given {@link RpcResult}&lt;AddFlowsBatchOutput&gt; */
+    /**
+     * Attach barrier response to given {@link RpcResult}&lt;AddFlowsBatchOutput&gt;
+     */
     public static final Function<Pair<RpcResult<AddFlowsBatchOutput>, RpcResult<Void>>, RpcResult<AddFlowsBatchOutput>>
             FLOW_ADD_COMPOSING_TRANSFORM = createComposingFunction();
 
-    /** Attach barrier response to given {@link RpcResult}&lt;UpdateFlowsBatchOutput&gt; */
+    /**
+     * Attach barrier response to given {@link RpcResult}&lt;UpdateFlowsBatchOutput&gt;
+     */
     public static final Function<Pair<RpcResult<UpdateFlowsBatchOutput>, RpcResult<Void>>, RpcResult<UpdateFlowsBatchOutput>>
             FLOW_UPDATE_COMPOSING_TRANSFORM = createComposingFunction();
 
@@ -145,6 +151,12 @@ public final class FlowUtil {
         return resultBld;
     }
 
+    /**
+     * Create alien flow id
+     *
+     * @param tableId the table id
+     * @return the flow id
+     */
     public static FlowId createAlienFlowId(final short tableId) {
         final StringBuilder sBuilder = new StringBuilder(ALIEN_SYSTEM_FLOW_ID)
                 .append(tableId).append('-').append(unaccountedFlowsCounter.incrementAndGet());
@@ -188,6 +200,8 @@ public final class FlowUtil {
     }
 
     /**
+     * Build flow path flow ref.
+     *
      * @param nodePath path to {@link Node}
      * @param tableId  path to {@link Table} under {@link Node}
      * @param flowId   path to {@link Flow} under {@link Table}
@@ -207,8 +221,8 @@ public final class FlowUtil {
      * Factory method: creates {@link Function} which keeps info of original inputs (passed to flow-rpc) and processes
      * list of all flow-rpc results.
      *
-     * @param inputBatchFlows collection of problematic flow-ids wrapped in container of given type &lt;O&gt;
      * @param <O>             result container type
+     * @param inputBatchFlows collection of problematic flow-ids wrapped in container of given type &lt;O&gt;
      * @return static reusable function
      */
     public static <O> Function<List<RpcResult<O>>, RpcResult<List<BatchFailedFlowsOutput>>> createCumulatingFunction(
index 39d4e4c917c279e9819fa23bac850d7777636226..c089672c304148cc060c3a9aa82730faa7f124c8 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.openflowplugin.impl;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -25,6 +26,7 @@ import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
@@ -35,9 +37,15 @@ import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
 import org.opendaylight.openflowplugin.api.openflow.rpc.RpcManager;
 import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsManager;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency;
+import org.opendaylight.openflowplugin.impl.registry.flow.DeviceFlowRegistryImpl;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+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.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 
 @RunWith(MockitoJUnitRunner.class)
 public class LifecycleConductorImplTest {
@@ -83,6 +91,7 @@ public class LifecycleConductorImplTest {
 
     @Before
     public void setUp() {
+        final KeyedInstanceIdentifier<Node, NodeKey> nodeInstanceIdentifier = InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(nodeId));
 
         lifecycleConductor = new LifecycleConductorImpl(messageIntelligenceAgency);
         lifecycleConductor.setSafelyManager(deviceManager);
@@ -95,6 +104,7 @@ public class LifecycleConductorImplTest {
         when(rpcManager.gainContext(Mockito.<DeviceInfo>any())).thenReturn(rpcContext);
         when(deviceInfo.getNodeId()).thenReturn(nodeId);
         when(deviceInfo.getDatapathId()).thenReturn(BigInteger.TEN);
+        when(deviceInfo.getNodeInstanceIdentifier()).thenReturn(nodeInstanceIdentifier);
         when(deviceContext.getDeviceInfo()).thenReturn(deviceInfo);
         when(rpcManager.gainContext(Mockito.<DeviceInfo>any())).thenReturn(rpcContext);
     }
@@ -188,7 +198,10 @@ public class LifecycleConductorImplTest {
      */
     @Test
     public void roleChangeOnDeviceTest4() {
+        final DataBroker dataBroker = mock(DataBroker.class);
+
         when(deviceContext.getDeviceState()).thenReturn(deviceState);
+        when(deviceContext.getDeviceFlowRegistry()).thenReturn(new DeviceFlowRegistryImpl(dataBroker));
         when(deviceManager.gainContext(deviceInfo)).thenReturn(deviceContext);
         when(deviceManager.onClusterRoleChange(deviceInfo, OfpRole.BECOMEMASTER)).thenReturn(listenableFuture);
         lifecycleConductor.roleChangeOnDevice(deviceInfo,true,OfpRole.BECOMEMASTER,false);
@@ -200,9 +213,13 @@ public class LifecycleConductorImplTest {
      */
     @Test
     public void roleChangeOnDeviceTest5() {
+        final DataBroker dataBroker = mock(DataBroker.class);
+
         when(deviceContext.getDeviceState()).thenReturn(deviceState);
+        when(deviceContext.getDeviceFlowRegistry()).thenReturn(new DeviceFlowRegistryImpl(dataBroker));
         when(deviceManager.gainContext(deviceInfo)).thenReturn(deviceContext);
         when(deviceManager.onClusterRoleChange(deviceInfo, OfpRole.BECOMESLAVE)).thenReturn(listenableFuture);
+
         lifecycleConductor.roleChangeOnDevice(deviceInfo,true,OfpRole.BECOMESLAVE,false);
         verify(statisticsManager).stopScheduling(Mockito.<DeviceInfo>any());
     }
index 3f279cd0e14c57fb7076512c563af22bd1571a54..0f9e65181d928499e1bb5b7480731ad4a317fd0b 100644 (file)
@@ -8,26 +8,54 @@
 
 package org.opendaylight.openflowplugin.impl.registry.flow;
 
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowDescriptor;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+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.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 
 /**
  * Test for {@link DeviceFlowRegistryImpl}.
  */
+@RunWith(MockitoJUnitRunner.class)
 public class DeviceFlowRegistryImplTest {
-
+    private static final String NODE_ID = "openflow:1";
     private DeviceFlowRegistryImpl deviceFlowRegistry;
     private FlowRegistryKey key;
     private FlowDescriptor descriptor;
+    @Mock
+    private DataBroker dataBroker;
+    @Mock
+    private ReadOnlyTransaction readOnlyTransaction;
 
     @Before
     public void setUp() throws Exception {
-        deviceFlowRegistry = new DeviceFlowRegistryImpl();
+        when(dataBroker.newReadOnlyTransaction()).thenReturn(readOnlyTransaction);
+        when(readOnlyTransaction.read(any(), any())).thenReturn(Futures.immediateCheckedFuture(Optional.absent()));
+        deviceFlowRegistry = new DeviceFlowRegistryImpl(dataBroker);
         final FlowAndStatisticsMapList flowStats = TestFlowHelper.createFlowAndStatisticsMapListBuilder(1).build();
         key = FlowRegistryKeyFactory.create(flowStats);
         descriptor = FlowDescriptorFactory.create(key.getTableId(), new FlowId("ut:1"));
@@ -37,6 +65,18 @@ public class DeviceFlowRegistryImplTest {
         Assert.assertEquals(1, deviceFlowRegistry.getAllFlowDescriptors().size());
     }
 
+    @Test
+    public void testFill() throws Exception {
+        final KeyedInstanceIdentifier<Node, NodeKey> nodeInstanceIdentifier = InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(new NodeId(NODE_ID)));
+        final InstanceIdentifier<FlowCapableNode> path = nodeInstanceIdentifier.augmentation(FlowCapableNode.class);
+
+        deviceFlowRegistry.fill(nodeInstanceIdentifier);
+
+        verify(dataBroker, times(2)).newReadOnlyTransaction();
+        verify(readOnlyTransaction).read(LogicalDatastoreType.CONFIGURATION, path);
+        verify(readOnlyTransaction).read(LogicalDatastoreType.OPERATIONAL, path);
+    }
+
     @Test
     public void testRetrieveIdForFlow() throws Exception {
         Assert.assertEquals(descriptor, deviceFlowRegistry.retrieveIdForFlow(key));
@@ -63,7 +103,7 @@ public class DeviceFlowRegistryImplTest {
         FlowId newFlowId;
 
         //store existing key
-        newFlowId = deviceFlowRegistry.storeIfNecessary(key, key.getTableId());
+        newFlowId = deviceFlowRegistry.storeIfNecessary(key);
 
         Assert.assertEquals(1, deviceFlowRegistry.getAllFlowDescriptors().size());
         Assert.assertEquals(descriptor, deviceFlowRegistry.retrieveIdForFlow(key));
@@ -72,7 +112,7 @@ public class DeviceFlowRegistryImplTest {
         //store new key
         final String alienPrefix = "#UF$TABLE*2-";
         final FlowRegistryKey key2 = FlowRegistryKeyFactory.create(TestFlowHelper.createFlowAndStatisticsMapListBuilder(2).build());
-        newFlowId = deviceFlowRegistry.storeIfNecessary(key2, key2.getTableId());
+        newFlowId = deviceFlowRegistry.storeIfNecessary(key2);
 
         Assert.assertTrue(newFlowId.getValue().startsWith(alienPrefix));
         Assert.assertTrue(deviceFlowRegistry.retrieveIdForFlow(key2).getFlowId().getValue().startsWith(alienPrefix));
index 7b3bcd26615e29838ce4bd00e9b56e03f9b68950..394538c131e79c22d14146e8e4d5f73d8db3f846 100644 (file)
@@ -227,7 +227,7 @@ public class MultipartRequestOnTheFlyCallbackTest {
 
         verify(mockedReadOnlyTx, times(1)).read(LogicalDatastoreType.OPERATIONAL, nodePath);
         verify(mockedReadOnlyTx, times(1)).close();
-        verify(mockedFlowRegistry).storeIfNecessary(Matchers.<FlowRegistryKey> any(), Matchers.anyShort());
+        verify(mockedFlowRegistry).storeIfNecessary(Matchers.<FlowRegistryKey> any());
         verify(mockedDeviceContext, times(1)).writeToTransaction(eq(LogicalDatastoreType.OPERATIONAL),
                 eq(tableIdent), Matchers.<Table> any());
         /*
@@ -258,7 +258,7 @@ public class MultipartRequestOnTheFlyCallbackTest {
         assertNotNull(actualResult.getResult());
         assertTrue(actualResult.getResult().isEmpty());
 
-        Mockito.verify(mockedFlowRegistry, Mockito.never()).storeIfNecessary(Matchers.<FlowRegistryKey>any(), Matchers.anyShort());
+        Mockito.verify(mockedFlowRegistry, Mockito.never()).storeIfNecessary(Matchers.any());
         Mockito.verify(mockedDeviceContext, Mockito.never()).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL),
                 Matchers.<InstanceIdentifier>any(), Matchers.<DataObject>any());
     }
index 63d55df295f394c343e56797889506fd2266d336..c3e68af0f087a1f519fe598b7c7d35688b409ed6 100644 (file)
@@ -5,12 +5,12 @@ import static org.mockito.Mockito.when;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import java.math.BigInteger;
-import java.util.List;
 import org.junit.Before;
 import org.junit.runner.RunWith;
 import org.mockito.Matchers;
 import org.mockito.Mock;
 import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
 import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
 import org.opendaylight.openflowplugin.api.OFConstants;
@@ -31,7 +31,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
@@ -48,7 +47,6 @@ public abstract class ServiceMocking {
     private static final KeyedInstanceIdentifier<Node, NodeKey> NODE_II
             = InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(new NodeId(DUMMY_NODE_ID)));
 
-
     @Mock
     protected RequestContextStack mockedRequestContextStack;
     @Mock
@@ -75,6 +73,8 @@ public abstract class ServiceMocking {
     protected OutboundQueue mockedOutboundQueue;
     @Mock
     protected MultiMsgCollector multiMessageCollector;
+    @Mock
+    protected DataBroker dataBroker;
 
     @Before
     public void initialization() {
@@ -98,10 +98,10 @@ public abstract class ServiceMocking {
 
         when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(mockedPrimConnectionContext);
         when(mockedDeviceContext.getMessageSpy()).thenReturn(mockedMessagSpy);
-        when(mockedDeviceContext.getDeviceFlowRegistry()).thenReturn(new DeviceFlowRegistryImpl());
+        when(mockedDeviceContext.getDeviceFlowRegistry()).thenReturn(new DeviceFlowRegistryImpl(dataBroker));
         when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
         when(mockedDeviceContext.getDeviceInfo()).thenReturn(mockedDeviceInfo);
-        when(mockedDeviceContext.getMultiMsgCollector(Matchers.<RequestContext<List<MultipartReply>>>any())).thenReturn(multiMessageCollector);
+        when(mockedDeviceContext.getMultiMsgCollector(Matchers.any())).thenReturn(multiMessageCollector);
 
         setup();
     }
index 64fa767cca3a2022ea6aab3f114f84ff0cc35219..7d167fa118202c324f5d4538e6bbc56103121e3e 100644 (file)
@@ -416,7 +416,7 @@ public class StatisticsGatheringUtilsTest {
     public void testGatherStatistics_flow() throws Exception {
         final short tableId = 0;
         final MultipartType type = MultipartType.OFPMPFLOW;
-        when(deviceFlowRegistry.storeIfNecessary(Matchers.any(FlowRegistryKey.class), Matchers.anyShort()))
+        when(deviceFlowRegistry.storeIfNecessary(Matchers.any(FlowRegistryKey.class)))
                 .thenReturn(new FlowId("openflow:21"));
 
         final InstanceIdentifier<FlowCapableNode> nodePath = deviceInfo.getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
@@ -456,7 +456,7 @@ public class StatisticsGatheringUtilsTest {
                 .child(Table.class, new TableKey((short) 0))
                 .child(Flow.class, new FlowKey(new FlowId("openflow:21")));
         verify(deviceContext, Mockito.never()).addDeleteToTxChain(Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.<InstanceIdentifier<?>>any());
-        verify(deviceFlowRegistry).storeIfNecessary(FlowRegistryKeyFactory.create(flowBld.build()), (short) 0);
+        verify(deviceFlowRegistry).storeIfNecessary(FlowRegistryKeyFactory.create(flowBld.build()));
         verify(txFacade).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.eq(flowPath), Matchers.any(Flow.class));
     }
 
index 24e040cd300e75b6208857a0611dac6e24a18510..44c3f3a864e7fd10129ccef928f6a9fa2339dd7c 100644 (file)
@@ -1,3 +1,4 @@
+
 /**
  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
  *
@@ -35,6 +36,7 @@ import org.mockito.Mockito;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.runners.MockitoJUnitRunner;
 import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
@@ -132,6 +134,8 @@ public class StatisticsManagerImplTest {
     private DeviceInitializationPhaseHandler deviceInitializationPhaseHandler;
     @Mock
     private DeviceInfo deviceInfo;
+    @Mock
+    private DataBroker dataBroker;
 
     private RequestContext<List<MultipartReply>> currentRequestContext;
     private StatisticsManagerImpl statisticsManager;
@@ -162,7 +166,7 @@ public class StatisticsManagerImplTest {
         when(mockedDeviceContext.getDeviceInfo()).thenReturn(mockedDeviceInfo);
         when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(mockedPrimConnectionContext);
         when(mockedDeviceContext.getMessageSpy()).thenReturn(mockedMessagSpy);
-        when(mockedDeviceContext.getDeviceFlowRegistry()).thenReturn(new DeviceFlowRegistryImpl());
+        when(mockedDeviceContext.getDeviceFlowRegistry()).thenReturn(new DeviceFlowRegistryImpl(dataBroker));
         when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
         when(mockedDeviceContext.getMultiMsgCollector(
                 Matchers.<RequestContext<List<MultipartReply>>>any())).thenAnswer(
index 1a12318a0ababc1c7301e446d35fb8d631cbc752..b2f39f30e73b560e0a12b65e99401359a21b753c 100644 (file)
@@ -44,7 +44,7 @@ public class FlowDirectStatisticsServiceTest extends AbstractDirectStatisticsSer
     public void setUp() throws Exception {
         service = new FlowDirectStatisticsService(requestContextStack, deviceContext);
         final DeviceFlowRegistry registry = mock(DeviceFlowRegistry.class);
-        when(registry.storeIfNecessary(any(), eq(TABLE_NO))).thenReturn(new FlowId("1"));
+        when(registry.storeIfNecessary(any())).thenReturn(new FlowId("1"));
         when(deviceContext.getDeviceFlowRegistry()).thenReturn(registry);
     }