Merge "GetFlowNodeCache cli"
authorArunprakash D <d.arunprakash@ericsson.com>
Wed, 9 Sep 2020 15:47:10 +0000 (15:47 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Wed, 9 Sep 2020 15:47:10 +0000 (15:47 +0000)
20 files changed:
applications/forwardingrules-manager/src/main/java/org/opendaylight/openflowplugin/applications/frm/util/FrmUtil.java
applications/southbound-cli/src/main/java/org/opendaylight/openflowplugin/applications/southboundcli/cli/GetFlowGroupCacheProvider.java [new file with mode: 0644]
applications/southbound-cli/src/main/resources/OSGI-INF/blueprint/commands.xml
applications/southbound-cli/src/main/resources/OSGI-INF/blueprint/southbound-cli.xml
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/FlowGroupCache.java [new file with mode: 0644]
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/FlowGroupCacheManager.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/FlowGroupStatus.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/OpenFlowPluginProviderImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/rpc/RpcContextImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/rpc/RpcManagerImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/cache/FlowGroupCacheManagerImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalFlowServiceImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalGroupServiceImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/MdSalRegistrationUtils.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/OpenFlowPluginProviderImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/rpc/RpcContextImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/rpc/RpcManagerImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/sal/SalFlowServiceImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/sal/SalGroupServiceImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/util/MdSalRegistrationUtilsTest.java

index cdcb2bf8bb81e9e713a5550ecd40f8ccf7356408..bc926b87fdd00966f66caed49e5110d5a0776581 100644 (file)
@@ -58,6 +58,7 @@ public final class FrmUtil {
     private static final Logger LOG = LoggerFactory.getLogger(FrmUtil.class);
     private static final String SEPARATOR = ":";
     private static final long RPC_RESULT_TIMEOUT = 2500;
+    public static final String OPENFLOW_PREFIX = "openflow:";
 
     private static final String JMX_OBJ_NAME_LIST_OF_SHRDS = "org.opendaylight.controller:type="
             + "DistributedConfigDatastore,Category=ShardManager,name=shard-manager-config";
diff --git a/applications/southbound-cli/src/main/java/org/opendaylight/openflowplugin/applications/southboundcli/cli/GetFlowGroupCacheProvider.java b/applications/southbound-cli/src/main/java/org/opendaylight/openflowplugin/applications/southboundcli/cli/GetFlowGroupCacheProvider.java
new file mode 100644 (file)
index 0000000..94d6c56
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2020 Ericsson India Global Services Pvt Ltd. 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.openflowplugin.applications.southboundcli.cli;
+
+import static org.opendaylight.openflowplugin.applications.frm.util.FrmUtil.OPENFLOW_PREFIX;
+
+import java.util.ArrayList;
+import java.util.Formatter;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCache;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
+
+@Command(scope = "openflow", name = "getflownodecache", description = "Print all flow/group cache")
+public class GetFlowGroupCacheProvider extends OsgiCommandSupport {
+
+    @Option(name = "-d", description = "Node Id")
+    String dpnId;
+
+    private FlowGroupCacheManager flowGroupCacheManager;
+
+    public GetFlowGroupCacheProvider(final FlowGroupCacheManager flowGroupCacheManager) {
+        this.flowGroupCacheManager = flowGroupCacheManager;
+    }
+
+    @SuppressWarnings("checkstyle:RegexpSinglelineJava")
+    @Override
+    protected Object doExecute() throws Exception {
+        String nodeId = OPENFLOW_PREFIX + dpnId;
+        List<String> result = new ArrayList<>();
+
+        if (dpnId == null) {
+            Map<String, Queue<FlowGroupCache>> flowGroupCacheListForAllNodes = flowGroupCacheManager
+                    .getAllNodesFlowGroupCache();
+            if (!flowGroupCacheListForAllNodes.isEmpty()) {
+                StringBuilder stringBuilder = new StringBuilder();
+                Formatter formatter = new Formatter(stringBuilder);
+                result.add(getAllLocalNodesHeaderOutput());
+                result.add(getLineSeparator());
+                for (Map.Entry<String, Queue<FlowGroupCache>> cacheEntry : flowGroupCacheListForAllNodes.entrySet()) {
+                    String[] temp = cacheEntry.getKey().split(":");
+                    String node = temp[1];
+                    Queue<FlowGroupCache> flowGroupCacheList = cacheEntry.getValue();
+                    synchronized (flowGroupCacheList) {
+                        for (FlowGroupCache cache : flowGroupCacheList) {
+                            result.add(formatter.format("%-15s %1s %-10s %1s %-8s %1s %-21s %1s %-60s",
+                                    node, "", cache.getDescription(), "", cache.getStatus(), "",
+                                    cache.getTime(), "", cache.getId()).toString());
+                            stringBuilder.setLength(0);
+                        }
+                    }
+                }
+                formatter.close();
+                result.stream().forEach(p -> System.out.println(p));
+            } else {
+                session.getConsole().println("No flow/group is programmed yet");
+            }
+        } else {
+            if (!flowGroupCacheManager.getAllNodesFlowGroupCache().containsKey(nodeId)) {
+                session.getConsole().println("No node available for this NodeID");
+                return null;
+            }
+            Queue<FlowGroupCache> flowGroupCacheList = flowGroupCacheManager.getAllNodesFlowGroupCache()
+                    .get(nodeId);
+            if (!flowGroupCacheList.isEmpty()) {
+                StringBuilder stringBuilder = new StringBuilder();
+                Formatter formatter = new Formatter(stringBuilder);
+                result.add(String.format("Number of flows and groups in cache for node %s : %d", nodeId,
+                        flowGroupCacheList.size()));
+                result.add(getLocalNodeHeaderOutput());
+                result.add(getLineSeparator());
+                for (FlowGroupCache cache : flowGroupCacheList) {
+                    result.add(formatter.format("%-10s %1s %-8s %1s %-23s %1s %-60s",
+                            cache.getDescription(), "", cache.getStatus(), "",
+                            cache.getTime(), "", cache.getId()).toString());
+                    stringBuilder.setLength(0);
+                }
+                formatter.close();
+                result.stream().forEach(p -> System.out.println(p));
+            } else {
+                session.getConsole().println("No flow/group is programmed yet for the the node " + nodeId);
+            }
+        }
+        return null;
+    }
+
+    private String getLocalNodeHeaderOutput() {
+        Formatter formatter = new Formatter();
+        String header = formatter.format("%-10s %1s %-8s %1s %-23s %1s %-60s",
+                "TableId", "", "Status", "", "Time", "", "Flow/Group Id").toString();
+        formatter.close();
+        return header;
+    }
+
+    private String getAllLocalNodesHeaderOutput() {
+        Formatter formatter = new Formatter();
+        String header = formatter.format("%-15s %1s %-10s %1s %-8s %1s %-23s %1s %-60s",
+                "DpnId", "", "TableId", "", "Status", "", "Time", "", "Flow/Group Id").toString();
+        formatter.close();
+        return header;
+    }
+
+    private String getLineSeparator() {
+        return "---------------------------------------------------------------------------------------------"
+                + "-----------------------------------------------";
+    }
+}
index c8d1c4effc8571f356fae8e6dd55122e7b0025fd..5c3454ff8bac7e44f36c510a8e82dbf2971d1875 100644 (file)
@@ -13,7 +13,6 @@
     <reference id="clusterMemberInfoProvider"
                interface="org.opendaylight.infrautils.diagstatus.ClusterMemberInfo"
                availability="optional"/>
-
     <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.0.0">
         <command name="openflow/getallnodes">
             <action class="org.opendaylight.openflowplugin.applications.southboundcli.cli.GetAllNodesCommandProvider">
                 <argument value="${org.osgi.service.http.port}"/>
             </action>
         </command>
+        <command name="openflow/getflownodecache">
+            <action class="org.opendaylight.openflowplugin.applications.southboundcli.cli.GetFlowGroupCacheProvider">
+                <argument ref="flowCacheManager"/>
+            </action>
+        </command>
     </command-bundle>
 
 </blueprint>
\ No newline at end of file
index b4bce7b42abd16f16bd0bb0c671ff6cdbc6624b1..1c9d8d851a649d27b4b21af31f4137d42f9c96aa 100644 (file)
@@ -6,11 +6,10 @@
 
     <reference id="dataBroker"
                interface="org.opendaylight.mdsal.binding.api.DataBroker"/>
-    <reference id="flowGroupCacheManager" interface="org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager"/>
+    <reference id="flowCacheManager" interface="org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager"/>
 
     <odl:rpc-service id="frmReconciliationService"
              interface="org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.frm.reconciliation.service.rev180227.FrmReconciliationService"/>
-
     <bean id="alarmAgent"
           class="org.opendaylight.openflowplugin.applications.southboundcli.alarm.AlarmAgent" init-method="start">
     </bean>
@@ -27,7 +26,7 @@
         <argument ref="frmReconciliationService"/>
         <argument ref="alarmAgent"/>
         <argument ref="nodeListener"/>
-        <argument ref="flowGroupCacheManager"/>
+        <argument ref="flowCacheManager"/>
     </bean>
 
     <odl:rpc-implementation ref="reconciliationService"/>
diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/FlowGroupCache.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/FlowGroupCache.java
new file mode 100644 (file)
index 0000000..63f22bb
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2020 Ericsson India Global Services Pvt Ltd. 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.openflowplugin.api.openflow;
+
+import java.time.LocalDateTime;
+
+public class FlowGroupCache {
+    private final String id;
+    private final String description;
+    private final FlowGroupStatus status;
+    private final LocalDateTime time;
+
+    public FlowGroupCache(String id, String description, FlowGroupStatus status,
+                          LocalDateTime time) {
+        this.id = id;
+        this.description = description;
+        this.status = status;
+        this.time = time;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public FlowGroupStatus getStatus() {
+        return status;
+    }
+
+    public LocalDateTime getTime() {
+        return time;
+    }
+}
index 5a49578d719d8e0fae456e1794b1cc888d74f3a4..b206aa4a78262c13e7bf37e2f4cc7507a47d380b 100644 (file)
@@ -8,8 +8,11 @@
 package org.opendaylight.openflowplugin.api.openflow;
 
 import java.util.Map;
+import java.util.Queue;
 
 public interface FlowGroupCacheManager {
 
     Map<String, ReconciliationState> getReconciliationStates();
+
+    Map<String, Queue<FlowGroupCache>> getAllNodesFlowGroupCache();
 }
diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/FlowGroupStatus.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/FlowGroupStatus.java
new file mode 100644 (file)
index 0000000..108e5a2
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2020 Ericsson India Global Services Pvt Ltd. 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.openflowplugin.api.openflow;
+
+public enum FlowGroupStatus {
+    ADDED,
+    MODIFIED,
+    REMOVED
+}
\ No newline at end of file
index 8a61ca1a5c954871e3fa388568ff56e0fbe2281d..f1970937805f11559105c445e533e90177cb0a8b 100644 (file)
@@ -50,6 +50,7 @@ import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvid
 import org.opendaylight.openflowjava.protocol.api.connection.OpenflowDiagStatusProvider;
 import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider;
 import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProviderList;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
 import org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginProvider;
 import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionManager;
@@ -127,6 +128,7 @@ public class OpenFlowPluginProviderImpl implements
     private ContextChainHolderImpl contextChainHolder;
     private final OpenflowDiagStatusProvider openflowDiagStatusProvider;
     private final SystemReadyMonitor systemReadyMonitor;
+    private final FlowGroupCacheManager flowGroupCacheManager;
     private final SettableFuture<Void> fullyStarted = SettableFuture.create();
     private static final String OPENFLOW_SERVICE_NAME = "OPENFLOW";
 
@@ -144,7 +146,8 @@ public class OpenFlowPluginProviderImpl implements
                                final @Reference EntityOwnershipService entityOwnershipService,
                                final MastershipChangeServiceManager mastershipChangeServiceManager,
                                final @Reference OpenflowDiagStatusProvider openflowDiagStatusProvider,
-                               final @Reference SystemReadyMonitor systemReadyMonitor) {
+                               final @Reference SystemReadyMonitor systemReadyMonitor,
+                               final FlowGroupCacheManager flowGroupCacheManager) {
         this.switchConnectionProviders = switchConnectionProviders;
         this.dataBroker = pingPongDataBroker;
         this.rpcProviderRegistry = rpcProviderRegistry;
@@ -158,6 +161,7 @@ public class OpenFlowPluginProviderImpl implements
         this.mastershipChangeServiceManager = mastershipChangeServiceManager;
         this.openflowDiagStatusProvider = openflowDiagStatusProvider;
         this.systemReadyMonitor = systemReadyMonitor;
+        this.flowGroupCacheManager = flowGroupCacheManager;
     }
 
     @Override
@@ -261,7 +265,8 @@ public class OpenFlowPluginProviderImpl implements
                 rpcProviderRegistry,
                 extensionConverterManager,
                 convertorManager,
-                notificationPublishService);
+                notificationPublishService,
+                flowGroupCacheManager);
 
         statisticsManager = new StatisticsManagerImpl(
                 config,
@@ -290,7 +295,7 @@ public class OpenFlowPluginProviderImpl implements
         deviceManager.setContextChainHolder(contextChainHolder);
         deviceManager.initialize();
         systemReadyMonitor.registerListener(this);
-        LOG.info("registered onSystemBootReady() listener for deferred startSwitchConnections()");
+        LOG.info("registered onSystemBootReady() listener for OpenFlowPluginProvider");
     }
 
     @Override
index 19d4ef6e1ebdd2a067d40675ebfdf5ddb9391642..40b7cf47535762a5da4986edd15ab3a0c951bb60 100644 (file)
@@ -22,6 +22,7 @@ import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
 import org.opendaylight.mdsal.binding.api.RpcProviderService;
 import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
@@ -58,6 +59,7 @@ class RpcContextImpl implements RpcContext {
     private final ConvertorExecutor convertorExecutor;
     private final NotificationPublishService notificationPublishService;
     private ContextChainMastershipWatcher contextChainMastershipWatcher;
+    private final FlowGroupCacheManager flowGroupCacheManager;
 
     RpcContextImpl(@NonNull final RpcProviderService rpcProviderRegistry,
                    final int maxRequests,
@@ -65,7 +67,8 @@ class RpcContextImpl implements RpcContext {
                    @NonNull final ExtensionConverterProvider extensionConverterProvider,
                    @NonNull final ConvertorExecutor convertorExecutor,
                    @NonNull final NotificationPublishService notificationPublishService,
-                   final boolean statisticsRpcEnabled) {
+                   final boolean statisticsRpcEnabled,
+                   @NonNull final FlowGroupCacheManager flowGroupCacheManager) {
         this.deviceContext = deviceContext;
         this.deviceInfo = deviceContext.getDeviceInfo();
         this.nodeInstanceIdentifier = deviceContext.getDeviceInfo().getNodeInstanceIdentifier();
@@ -74,6 +77,7 @@ class RpcContextImpl implements RpcContext {
         this.extensionConverterProvider = extensionConverterProvider;
         this.notificationPublishService = notificationPublishService;
         this.convertorExecutor = convertorExecutor;
+        this.flowGroupCacheManager = flowGroupCacheManager;
         this.isStatisticsRpcEnabled = statisticsRpcEnabled;
         this.tracker = new Semaphore(maxRequests, true);
     }
@@ -184,7 +188,8 @@ class RpcContextImpl implements RpcContext {
 
     @Override
     public void instantiateServiceInstance() {
-        MdSalRegistrationUtils.registerServices(this, deviceContext, extensionConverterProvider, convertorExecutor);
+        MdSalRegistrationUtils.registerServices(this, deviceContext, extensionConverterProvider,
+                convertorExecutor, flowGroupCacheManager);
 
         if (isStatisticsRpcEnabled && !deviceContext.canUseSingleLayerSerialization()) {
             MdSalRegistrationUtils.registerStatCompatibilityServices(
index 748cbce10b96d60809105728274fc4168934665c..817bc7ae85a95a992bc9a34141a0e460167867f9 100644 (file)
@@ -15,6 +15,7 @@ import java.util.concurrent.ConcurrentMap;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
 import org.opendaylight.mdsal.binding.api.RpcProviderService;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
 import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
@@ -34,17 +35,20 @@ public class RpcManagerImpl implements RpcManager {
     private final ExtensionConverterProvider extensionConverterProvider;
     private final ConvertorExecutor convertorExecutor;
     private final NotificationPublishService notificationPublishService;
+    private final FlowGroupCacheManager flowGroupCacheManager;
 
     public RpcManagerImpl(final OpenflowProviderConfig config,
                           final RpcProviderService rpcProviderRegistry,
                           final ExtensionConverterProvider extensionConverterProvider,
                           final ConvertorExecutor convertorExecutor,
-                          final NotificationPublishService notificationPublishService) {
+                          final NotificationPublishService notificationPublishService,
+                          final FlowGroupCacheManager flowGroupCacheManager) {
         this.config = config;
         this.rpcProviderRegistry = rpcProviderRegistry;
         this.extensionConverterProvider = extensionConverterProvider;
         this.convertorExecutor = convertorExecutor;
         this.notificationPublishService = notificationPublishService;
+        this.flowGroupCacheManager = flowGroupCacheManager;
     }
 
     @Override
@@ -74,7 +78,8 @@ public class RpcManagerImpl implements RpcManager {
                 extensionConverterProvider,
                 convertorExecutor,
                 notificationPublishService,
-                config.isIsStatisticsRpcEnabled());
+                config.isIsStatisticsRpcEnabled(),
+                flowGroupCacheManager);
 
         contexts.put(deviceContext.getDeviceInfo(), rpcContext);
         return rpcContext;
index 5d2323e3b2dbe0680421a75f7cf3c73619041503..4f6b6a28d1c4a985199e2f991e5837b0a43103d0 100644 (file)
@@ -8,9 +8,11 @@
 package org.opendaylight.openflowplugin.impl.services.cache;
 
 import java.util.Map;
+import java.util.Queue;
 import java.util.concurrent.ConcurrentHashMap;
 import javax.inject.Singleton;
 import org.apache.aries.blueprint.annotation.service.Service;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCache;
 import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
 import org.opendaylight.openflowplugin.api.openflow.ReconciliationState;
 
@@ -19,6 +21,12 @@ import org.opendaylight.openflowplugin.api.openflow.ReconciliationState;
 public class FlowGroupCacheManagerImpl implements FlowGroupCacheManager {
 
     private Map<String, ReconciliationState> reconciliationStates = new ConcurrentHashMap<>();
+    private Map<String, Queue<FlowGroupCache>> allNodesFlowGroupCache = new ConcurrentHashMap<>();
+
+    @Override
+    public Map<String, Queue<FlowGroupCache>> getAllNodesFlowGroupCache() {
+        return allNodesFlowGroupCache;
+    }
 
     @Override
     public Map<String, ReconciliationState> getReconciliationStates() {
index ffe22fb4b21a9a394e190d37687ca40021fed604..a9f4c04e6439e66a8d246ec33ff9d5c571eca8f3 100644 (file)
@@ -7,14 +7,21 @@
  */
 package org.opendaylight.openflowplugin.impl.services.sal;
 
+import com.google.common.collect.EvictingQueue;
+import com.google.common.collect.Queues;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
 import com.google.common.util.concurrent.SettableFuture;
+import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Queue;
 import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCache;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupStatus;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
@@ -26,6 +33,7 @@ import org.opendaylight.openflowplugin.impl.services.multilayer.MultiLayerFlowSe
 import org.opendaylight.openflowplugin.impl.services.singlelayer.SingleLayerFlowService;
 import org.opendaylight.openflowplugin.impl.util.ErrorUtil;
 import org.opendaylight.openflowplugin.impl.util.FlowCreatorUtil;
+import org.opendaylight.openflowplugin.impl.util.PathUtil;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
 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.Flow;
@@ -40,6 +48,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.Upda
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInputBuilder;
 import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
@@ -58,11 +67,16 @@ public class SalFlowServiceImpl implements SalFlowService {
     private final SingleLayerFlowService<RemoveFlowOutput> flowRemoveMessage;
     private final DeviceContext deviceContext;
     private static final Uint8 OFPTT_ALL = Uint8.MAX_VALUE;
+    private final FlowGroupCacheManager provider;
+    public static final int FLOWGROUP_CACHE_SIZE = 10000;
+
 
     public SalFlowServiceImpl(final RequestContextStack requestContextStack,
                               final DeviceContext deviceContext,
-                              final ConvertorExecutor convertorExecutor) {
+                              final ConvertorExecutor convertorExecutor,
+                              final FlowGroupCacheManager provider) {
         this.deviceContext = deviceContext;
+        this.provider = provider;
         flowRemove = new MultiLayerFlowService<>(requestContextStack,
                                                  deviceContext,
                                                  RemoveFlowOutput.class,
@@ -85,13 +99,15 @@ public class SalFlowServiceImpl implements SalFlowService {
         final FlowRegistryKey flowRegistryKey =
                 FlowRegistryKeyFactory.create(deviceContext.getDeviceInfo().getVersion(), input);
         final ListenableFuture<RpcResult<AddFlowOutput>> future;
-
+        NodeId nodeId = PathUtil.extractNodeId(input.getNode());
         if (flowAddMessage.canUseSingleLayerSerialization()) {
             future = flowAddMessage.handleServiceCall(input);
-            Futures.addCallback(future, new AddFlowCallback(input, flowRegistryKey), MoreExecutors.directExecutor());
+            Futures.addCallback(future, new AddFlowCallback(input, flowRegistryKey, nodeId),
+                    MoreExecutors.directExecutor());
         } else {
             future = flowAdd.processFlowModInputBuilders(flowAdd.toFlowModInputs(input));
-            Futures.addCallback(future, new AddFlowCallback(input, flowRegistryKey), MoreExecutors.directExecutor());
+            Futures.addCallback(future, new AddFlowCallback(input, flowRegistryKey, nodeId),
+                    MoreExecutors.directExecutor());
 
         }
         return future;
@@ -100,14 +116,14 @@ public class SalFlowServiceImpl implements SalFlowService {
     @Override
     public ListenableFuture<RpcResult<RemoveFlowOutput>> removeFlow(final RemoveFlowInput input) {
         final ListenableFuture<RpcResult<RemoveFlowOutput>> future;
-
+        NodeId nodeId = PathUtil.extractNodeId(input.getNode());
         if (flowRemoveMessage.canUseSingleLayerSerialization()) {
             future = flowRemoveMessage.handleServiceCall(input);
-            Futures.addCallback(future, new RemoveFlowCallback(input), MoreExecutors.directExecutor());
+            Futures.addCallback(future, new RemoveFlowCallback(input, nodeId), MoreExecutors.directExecutor());
 
         } else {
             future = flowRemove.processFlowModInputBuilders(flowRemove.toFlowModInputs(input));
-            Futures.addCallback(future, new RemoveFlowCallback(input), MoreExecutors.directExecutor());
+            Futures.addCallback(future, new RemoveFlowCallback(input, nodeId), MoreExecutors.directExecutor());
         }
 
         return future;
@@ -117,7 +133,7 @@ public class SalFlowServiceImpl implements SalFlowService {
     public ListenableFuture<RpcResult<UpdateFlowOutput>> updateFlow(final UpdateFlowInput input) {
         final UpdatedFlow updated = input.getUpdatedFlow();
         final OriginalFlow original = input.getOriginalFlow();
-
+        String nodeId =  PathUtil.extractNodeId(input.getNode()).getValue();
         final List<FlowModInputBuilder> allFlowMods = new ArrayList<>();
         final List<FlowModInputBuilder> ofFlowModInputs;
 
@@ -186,27 +202,39 @@ public class SalFlowServiceImpl implements SalFlowService {
             future = flowUpdate.processFlowModInputBuilders(allFlowMods);
         }
 
-        Futures.addCallback(future, new UpdateFlowCallback(input), MoreExecutors.directExecutor());
+        Futures.addCallback(future, new UpdateFlowCallback(input, nodeId), MoreExecutors.directExecutor());
         return future;
     }
 
     private final class AddFlowCallback implements FutureCallback<RpcResult<AddFlowOutput>> {
         private final AddFlowInput input;
         private final FlowRegistryKey flowRegistryKey;
+        private final NodeId nodeId;
 
         private AddFlowCallback(final AddFlowInput input,
-                                final FlowRegistryKey flowRegistryKey) {
+                                final FlowRegistryKey flowRegistryKey,
+                                final NodeId nodeId) {
             this.input = input;
             this.flowRegistryKey = flowRegistryKey;
+            this.nodeId = nodeId;
         }
 
         @Override
         public void onSuccess(final RpcResult<AddFlowOutput> rpcResult) {
             if (rpcResult.isSuccessful()) {
                 final FlowDescriptor flowDescriptor;
-
+                final FlowId flowId = input.getFlowRef().getValue().firstKeyOf(Flow.class).getId();
+                FlowGroupCache cache = new FlowGroupCache(flowId.getValue(), input.getTableId().toString(),
+                        FlowGroupStatus.ADDED, LocalDateTime.now());
+                if (provider.getAllNodesFlowGroupCache().containsKey(nodeId.getValue())) {
+                    provider.getAllNodesFlowGroupCache().get(nodeId.getValue()).add(cache);
+                } else {
+                    Queue<FlowGroupCache> flowGroupCacheList =
+                            Queues.synchronizedQueue(EvictingQueue.create(FLOWGROUP_CACHE_SIZE));
+                    flowGroupCacheList.add(cache);
+                    provider.getAllNodesFlowGroupCache().put(nodeId.getValue(), flowGroupCacheList);
+                }
                 if (input.getFlowRef() != null) {
-                    final FlowId flowId = input.getFlowRef().getValue().firstKeyOf(Flow.class).getId();
                     flowDescriptor = FlowDescriptorFactory.create(input.getTableId(), flowId);
                     deviceContext.getDeviceFlowRegistry().storeDescriptor(flowRegistryKey, flowDescriptor);
                 } else {
@@ -233,9 +261,11 @@ public class SalFlowServiceImpl implements SalFlowService {
 
     private final class RemoveFlowCallback implements FutureCallback<RpcResult<RemoveFlowOutput>> {
         private final RemoveFlowInput input;
+        private final NodeId nodeId;
 
-        private RemoveFlowCallback(final RemoveFlowInput input) {
+        private RemoveFlowCallback(final RemoveFlowInput input, final NodeId nodeId) {
             this.input = input;
+            this.nodeId = nodeId;
         }
 
         @Override
@@ -248,6 +278,18 @@ public class SalFlowServiceImpl implements SalFlowService {
                     FlowRegistryKey flowRegistryKey =
                             FlowRegistryKeyFactory.create(deviceContext.getDeviceInfo().getVersion(), input);
                     deviceContext.getDeviceFlowRegistry().addMark(flowRegistryKey);
+                    final FlowId flowId = input.getFlowRef().getValue().firstKeyOf(Flow.class).getId();
+                    FlowGroupCache cache = new FlowGroupCache(flowId.getValue(),
+                            input.getTableId().toString(), FlowGroupStatus.REMOVED,
+                            LocalDateTime.now());
+                    if (provider.getAllNodesFlowGroupCache().containsKey(nodeId.getValue())) {
+                        provider.getAllNodesFlowGroupCache().get(nodeId.getValue()).add(cache);
+                    } else {
+                        Queue<FlowGroupCache> flowGroupCacheList =
+                                Queues.synchronizedQueue(EvictingQueue.create(FLOWGROUP_CACHE_SIZE));
+                        flowGroupCacheList.add(cache);
+                        provider.getAllNodesFlowGroupCache().put(nodeId.getValue(), flowGroupCacheList);
+                    }
                 } else {
                     deviceContext.getDeviceFlowRegistry().clearFlowRegistry();
                 }
@@ -267,15 +309,17 @@ public class SalFlowServiceImpl implements SalFlowService {
 
     private final class UpdateFlowCallback implements FutureCallback<RpcResult<UpdateFlowOutput>> {
         private final UpdateFlowInput input;
+        private final String nodeId;
 
-        private UpdateFlowCallback(UpdateFlowInput input) {
+        private UpdateFlowCallback(UpdateFlowInput input,  String nodeId) {
             this.input = input;
+            this.nodeId = nodeId;
         }
 
         @Override
         public void onSuccess(final RpcResult<UpdateFlowOutput> updateFlowOutputRpcResult) {
             final DeviceFlowRegistry deviceFlowRegistry = deviceContext.getDeviceFlowRegistry();
-
+            final FlowId flowId = input.getFlowRef().getValue().firstKeyOf(Flow.class).getId();
             final UpdatedFlow updated = input.getUpdatedFlow();
             final OriginalFlow original = input.getOriginalFlow();
             final FlowRegistryKey origFlowRegistryKey =
@@ -286,6 +330,17 @@ public class SalFlowServiceImpl implements SalFlowService {
 
             final boolean isUpdate = origFlowDescriptor != null;
             final FlowDescriptor updatedFlowDescriptor;
+            FlowGroupCache cache = new FlowGroupCache(flowId.getValue(), updated.getTableId().toString(),
+                    FlowGroupStatus.MODIFIED,
+                    LocalDateTime.now());
+            if (provider.getAllNodesFlowGroupCache().containsKey(nodeId)) {
+                provider.getAllNodesFlowGroupCache().get(nodeId).add(cache);
+            } else {
+                Queue<FlowGroupCache> flowGroupCacheList =
+                        Queues.synchronizedQueue(EvictingQueue.create(FLOWGROUP_CACHE_SIZE));
+                flowGroupCacheList.add(cache);
+                provider.getAllNodesFlowGroupCache().put(nodeId, flowGroupCacheList);
+            }
 
             if (input.getFlowRef() != null) {
                 updatedFlowDescriptor =
index 7c14b0deeba3bad9534451f23af4558ace789623..df8380b7e20e8987e8b80c3b54113aa875b036c4 100755 (executable)
@@ -7,15 +7,23 @@
  */
 package org.opendaylight.openflowplugin.impl.services.sal;
 
+import com.google.common.collect.EvictingQueue;
+import com.google.common.collect.Queues;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
+import java.time.LocalDateTime;
+import java.util.Queue;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCache;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupStatus;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.impl.services.multilayer.MultiLayerGroupService;
 import org.opendaylight.openflowplugin.impl.services.singlelayer.SingleLayerGroupService;
 import org.opendaylight.openflowplugin.impl.util.ErrorUtil;
+import org.opendaylight.openflowplugin.impl.util.PathUtil;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupOutput;
@@ -25,6 +33,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.Sal
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -39,11 +48,16 @@ public class SalGroupServiceImpl implements SalGroupService {
     private final SingleLayerGroupService<RemoveGroupOutput> removeGroupMessage;
 
     private final DeviceContext deviceContext;
+    private final FlowGroupCacheManager provider ;
+
+    public static final int FLOWGROUP_CACHE_SIZE = 10000;
 
     public SalGroupServiceImpl(final RequestContextStack requestContextStack,
                                final DeviceContext deviceContext,
-                               final ConvertorExecutor convertorExecutor) {
+                               final ConvertorExecutor convertorExecutor,
+                               final FlowGroupCacheManager provider) {
         this.deviceContext = deviceContext;
+        this.provider = provider;
         addGroup = new MultiLayerGroupService<>(requestContextStack,
                                                 deviceContext,
                                                 AddGroupOutput.class,
@@ -70,12 +84,23 @@ public class SalGroupServiceImpl implements SalGroupService {
             addGroupMessage.canUseSingleLayerSerialization()
             ? addGroupMessage.handleServiceCall(input)
             : addGroup.handleServiceCall(input);
-
+        String nodeId =  PathUtil.extractNodeId(input.getNode()).getValue();
         Futures.addCallback(resultFuture, new FutureCallback<RpcResult<AddGroupOutput>>() {
             @Override
             public void onSuccess(RpcResult<AddGroupOutput> result) {
                 if (result.isSuccessful()) {
-                    LOG.debug("adding group successful {}", input.getGroupId().getValue());
+                    LOG.debug("adding group successful {}", input.getGroupId());
+                    FlowGroupCache cache = new FlowGroupCache(input.getGroupId().toString(),
+                            input.getGroupType().getName(), FlowGroupStatus.ADDED,
+                            LocalDateTime.now());
+                    if (provider.getAllNodesFlowGroupCache().containsKey(nodeId)) {
+                        provider.getAllNodesFlowGroupCache().get(nodeId).add(cache);
+                    } else {
+                        Queue<FlowGroupCache> flowGroupCacheList =
+                                Queues.synchronizedQueue(EvictingQueue.create(FLOWGROUP_CACHE_SIZE));
+                        flowGroupCacheList.add(cache);
+                        provider.getAllNodesFlowGroupCache().put(nodeId, flowGroupCacheList);
+                    }
                 } else {
                     if (LOG.isDebugEnabled()) {
                         LOG.debug("Group add with id={} failed, errors={}", input.getGroupId().getValue(),
@@ -106,6 +131,19 @@ public class SalGroupServiceImpl implements SalGroupService {
             @Override
             public void onSuccess(RpcResult<UpdateGroupOutput> result) {
                 if (result.isSuccessful()) {
+                    NodeId nodeId = PathUtil.extractNodeId(input.getNode());
+                    FlowGroupCache cache = new FlowGroupCache(
+                            input.getUpdatedGroup().getGroupId().getValue().toString(),
+                            input.getUpdatedGroup().getGroupType().getName(), FlowGroupStatus.MODIFIED,
+                            LocalDateTime.now());
+                    if (provider.getAllNodesFlowGroupCache().containsKey(nodeId.getValue())) {
+                        provider.getAllNodesFlowGroupCache().get(nodeId.getValue()).add(cache);
+                    } else {
+                        Queue<FlowGroupCache> flowGroupCacheList =
+                                Queues.synchronizedQueue(EvictingQueue.create(FLOWGROUP_CACHE_SIZE));
+                        flowGroupCacheList.add(cache);
+                        provider.getAllNodesFlowGroupCache().put(nodeId.getValue(), flowGroupCacheList);
+                    }
                     if (LOG.isDebugEnabled()) {
                         LOG.debug("Group update with original id={} finished without error",
                             input.getOriginalGroup().getGroupId().getValue());
@@ -138,7 +176,19 @@ public class SalGroupServiceImpl implements SalGroupService {
             public void onSuccess(RpcResult<RemoveGroupOutput> result) {
                 if (result.isSuccessful()) {
                     if (LOG.isDebugEnabled()) {
+                        NodeId nodeId = PathUtil.extractNodeId(input.getNode());
                         LOG.debug("Group remove with id={} finished without error", input.getGroupId().getValue());
+                        FlowGroupCache cache = new FlowGroupCache(input.getGroupId().getValue().toString(),
+                                input.getGroupType().getName(), FlowGroupStatus.REMOVED,
+                                LocalDateTime.now());
+                        if (provider.getAllNodesFlowGroupCache().containsKey(nodeId.getValue())) {
+                            provider.getAllNodesFlowGroupCache().get(nodeId.getValue()).add(cache);
+                        } else {
+                            Queue<FlowGroupCache> flowGroupCacheList =
+                                    Queues.synchronizedQueue(EvictingQueue.create(FLOWGROUP_CACHE_SIZE));
+                            flowGroupCacheList.add(cache);
+                            provider.getAllNodesFlowGroupCache().put(nodeId.getValue(), flowGroupCacheList);
+                        }
                     }
                 } else {
                     LOG.warn("Group remove with id={} failed, errors={}", input.getGroupId().getValue(),
index 3f3f3600273b6ee0281a375b46e023e89a60de14..6c33657529e286fbcb4234b4bceb52cc5cd561ae 100644 (file)
@@ -11,6 +11,7 @@ import com.google.common.base.Preconditions;
 import java.util.concurrent.atomic.AtomicLong;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
 import org.opendaylight.openflowplugin.api.openflow.statistics.compatibility.Delegator;
@@ -89,19 +90,21 @@ public final class MdSalRegistrationUtils {
     public static void registerServices(@NonNull final RpcContext rpcContext,
                                         @NonNull final DeviceContext deviceContext,
                                         final ExtensionConverterProvider extensionConverterProvider,
-                                        final ConvertorExecutor convertorExecutor) {
+                                        final ConvertorExecutor convertorExecutor,
+                                        final FlowGroupCacheManager flowGroupCacheManager) {
         // TODO: Use multipart writer provider from device context
         final MultipartWriterProvider multipartWriterProvider = MultipartWriterProviderFactory
             .createDefaultProvider(deviceContext);
 
         // create service instances
-        final SalFlowServiceImpl salFlowService = new SalFlowServiceImpl(rpcContext, deviceContext, convertorExecutor);
+        final SalFlowServiceImpl salFlowService = new SalFlowServiceImpl(rpcContext, deviceContext,
+                convertorExecutor, flowGroupCacheManager);
         final FlowCapableTransactionServiceImpl flowCapableTransactionService =
                 new FlowCapableTransactionServiceImpl(rpcContext, deviceContext);
         final SalAsyncConfigServiceImpl salAsyncConfigService =
                 new SalAsyncConfigServiceImpl(rpcContext, deviceContext);
         final SalGroupServiceImpl salGroupService =
-                new SalGroupServiceImpl(rpcContext, deviceContext, convertorExecutor);
+                new SalGroupServiceImpl(rpcContext, deviceContext, convertorExecutor, flowGroupCacheManager);
         final SalMeterServiceImpl salMeterService =
                 new SalMeterServiceImpl(rpcContext, deviceContext, convertorExecutor);
 
index 934fb1516bdfe2fedbde1ecc94cbfa9725e46b1b..3e672beef5179709ffcf032fa4a295c2529b4910 100644 (file)
@@ -32,6 +32,7 @@ import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvid
 import org.opendaylight.openflowjava.protocol.api.connection.OpenflowDiagStatusProvider;
 import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider;
 import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProviderList;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
 import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationProperty;
 import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService;
 import org.opendaylight.openflowplugin.api.openflow.mastership.MastershipChangeServiceManager;
@@ -82,6 +83,9 @@ public class OpenFlowPluginProviderImplTest {
     @Mock
     MastershipChangeServiceManager mastershipChangeServiceManager;
 
+    @Mock
+    FlowGroupCacheManager flowGroupCacheManager;
+
     private static final int RPC_REQUESTS_QUOTA = 500;
     private static final long GLOBAL_NOTIFICATION_QUOTA = 131072;
     private static final Uint16 THREAD_POOL_MIN_THREADS = Uint16.ONE;
@@ -128,7 +132,8 @@ public class OpenFlowPluginProviderImplTest {
                 entityOwnershipService,
                 mastershipChangeServiceManager,
                 ofPluginDiagstatusProvider,
-                systemReadyMonitor);
+                systemReadyMonitor,
+                flowGroupCacheManager);
 
         provider.initialize();
         // Calling the onSystemBootReady() callback
index f38973f4b45caaa42db4746d99a46de88ca1e4f7..8a537c1a341fe30e3aff9db4cf0c492f55e521f7 100644 (file)
@@ -24,6 +24,7 @@ import org.mockito.Mockito;
 import org.mockito.junit.MockitoJUnitRunner;
 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
 import org.opendaylight.mdsal.binding.api.RpcProviderService;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
@@ -47,7 +48,8 @@ public class RpcContextImplTest {
     private static final int MAX_REQUESTS = 5;
     private RpcContextImpl rpcContext;
 
-
+    @Mock
+    private FlowGroupCacheManager flowGroupCacheManager;
     @Mock
     private RpcProviderService rpcProviderRegistry;
     @Mock
@@ -88,7 +90,7 @@ public class RpcContextImplTest {
                 deviceContext,
                 extensionConverterProvider,
                 convertorExecutor,
-                notificationPublishService, true);
+                notificationPublishService, true, flowGroupCacheManager);
 
         when(rpcProviderRegistry.registerRpcImplementation(eq(TestRpcService.class), eq(serviceInstance), anySet()))
                 .thenReturn(routedRpcReg);
@@ -102,7 +104,7 @@ public class RpcContextImplTest {
                 deviceContext,
                 extensionConverterProvider,
                 convertorExecutor,
-                notificationPublishService, true)) {
+                notificationPublishService, true, flowGroupCacheManager)) {
             final RequestContext<?> requestContext = rpcContext.createRequestContext();
             assertNotNull(requestContext);
         }
@@ -116,7 +118,7 @@ public class RpcContextImplTest {
                 deviceContext,
                 extensionConverterProvider,
                 convertorExecutor,
-                notificationPublishService, true)) {
+                notificationPublishService, true, flowGroupCacheManager)) {
             final RequestContext<?> requestContext = rpcContext.createRequestContext();
             assertNull(requestContext);
         }
@@ -130,7 +132,7 @@ public class RpcContextImplTest {
                 deviceContext,
                 extensionConverterProvider,
                 convertorExecutor,
-                notificationPublishService, true)) {
+                notificationPublishService, true, flowGroupCacheManager)) {
             final RequestContext<?> requestContext = rpcContext.createRequestContext();
             assertNotNull(requestContext);
             requestContext.close();
index 2da9fcb414439bb090c5e1452afb2b8a8c0f1ab4..1119f97f5fd9200171bc2b26ee68a231bad7514a 100644 (file)
@@ -21,6 +21,7 @@ import org.mockito.junit.MockitoJUnitRunner;
 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
 import org.opendaylight.mdsal.binding.api.RpcProviderService;
 import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
@@ -72,6 +73,8 @@ public class RpcManagerImplTest {
     private NotificationPublishService notificationPublishService;
     @Mock
     private KeyedInstanceIdentifier<Node, NodeKey> nodePath;
+    @Mock
+    private FlowGroupCacheManager flowGroupCacheManager;
 
     private final NodeId nodeId = new NodeId("openflow-junit:1");
 
@@ -82,7 +85,8 @@ public class RpcManagerImplTest {
                 .setRpcRequestsQuota(new NonZeroUint16Type(QUOTA_VALUE))
                 .setIsStatisticsRpcEnabled(false)
                 .build(),
-                rpcProviderRegistry, extensionConverterProvider, convertorExecutor, notificationPublishService);
+                rpcProviderRegistry, extensionConverterProvider, convertorExecutor, notificationPublishService,
+                flowGroupCacheManager);
 
         FeaturesReply features = new GetFeaturesOutputBuilder()
                 .setVersion(OFConstants.OFP_VERSION_1_3)
index d22270c2f6daa882ce00571b5024ec8d915042fa..97350e440b5d80895d8635fc57588672da4fd618 100644 (file)
@@ -7,11 +7,15 @@
  */
 package org.opendaylight.openflowplugin.impl.services.sal;
 
-import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import com.google.common.util.concurrent.Futures;
+import java.time.LocalDateTime;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Queue;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import junit.framework.TestCase;
@@ -24,6 +28,8 @@ import org.mockito.junit.MockitoJUnitRunner;
 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
 import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
 import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCache;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupStatus;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
@@ -32,9 +38,8 @@ import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
 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.api.openflow.statistics.ofpspecific.MessageSpy;
+import org.opendaylight.openflowplugin.impl.services.cache.FlowGroupCacheManagerImpl;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
@@ -57,6 +62,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
 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;
@@ -85,6 +91,27 @@ public class SalFlowServiceImplTest extends TestCase {
     private static final KeyedInstanceIdentifier<Table, TableKey> TABLE_II
             = NODE_II.augmentation(FlowCapableNode.class).child(Table.class, new TableKey(DUMMY_TABLE_ID));
 
+    private NodeRef noderef = new NodeRef(NODE_II);
+    private static final String KEY = "0";
+    private static FlowGroupCache flowcache =
+            new FlowGroupCache("0","mock class", FlowGroupStatus.ADDED, LocalDateTime.MAX);
+
+    private static Queue<FlowGroupCache> caches() {
+        Queue<FlowGroupCache> cache = new LinkedList<>();
+        cache.add(flowcache);
+        return cache;
+    }
+
+    private static final Queue<FlowGroupCache> CACHE = caches();
+
+    private static Map<String, Queue<FlowGroupCache>> createMap() {
+        Map<String,Queue<FlowGroupCache>> myMap = new HashMap<>();
+        myMap.put(KEY, CACHE);
+        return myMap;
+    }
+
+    private static final Map<String, Queue<FlowGroupCache>> MYMAP = createMap();
+
     @Mock
     private RequestContextStack mockedRequestContextStack;
     @Mock
@@ -112,6 +139,8 @@ public class SalFlowServiceImplTest extends TestCase {
     private DeviceFlowRegistry deviceFlowRegistry;
     @Mock
     private GetFeaturesOutput mockedFeaturesOutput;
+    @Mock
+    private FlowGroupCacheManagerImpl flowGroupCacheManager;
 
     @Before
     public void initialization() {
@@ -129,6 +158,7 @@ public class SalFlowServiceImplTest extends TestCase {
         when(mockedDeviceInfo.getDatapathId()).thenReturn(DUMMY_DATAPATH_ID);
 
         when(mockedDeviceContext.getDeviceInfo()).thenReturn(mockedDeviceInfo);
+        when(flowGroupCacheManager.getAllNodesFlowGroupCache()).thenReturn(MYMAP);
     }
 
     private SalFlowServiceImpl mockSalFlowService(final short version) {
@@ -138,7 +168,8 @@ public class SalFlowServiceImplTest extends TestCase {
         when(mockedDeviceInfo.getVersion()).thenReturn(version);
 
         final ConvertorManager convertorManager = ConvertorManagerFactory.createDefaultManager();
-        return new SalFlowServiceImpl(mockedRequestContextStack, mockedDeviceContext, convertorManager);
+        return new SalFlowServiceImpl(mockedRequestContextStack, mockedDeviceContext, convertorManager,
+                flowGroupCacheManager);
     }
 
     @Test
@@ -161,12 +192,12 @@ public class SalFlowServiceImplTest extends TestCase {
         AddFlowInput mockedAddFlowInput = new AddFlowInputBuilder()
                 .setMatch(match)
                 .setTableId((short)1)
+                .setNode(noderef)
                 .build();
 
         Mockito.doReturn(Futures.<RequestContext<Object>>immediateFailedFuture(new Exception("ut-failed-response")))
                 .when(requestContext).getFuture();
 
-        mockingFlowRegistryLookup();
         final Future<RpcResult<AddFlowOutput>> rpcResultFuture =
                 mockSalFlowService(version).addFlow(mockedAddFlowInput);
 
@@ -190,6 +221,7 @@ public class SalFlowServiceImplTest extends TestCase {
         RemoveFlowInput mockedRemoveFlowInput = new RemoveFlowInputBuilder()
                 .setTableId((short)1)
                 .setMatch(match)
+                .setNode(noderef)
                 .build();
 
         Mockito.doReturn(Futures.<RequestContext<Object>>immediateFailedFuture(new Exception("ut-failed-response")))
@@ -214,10 +246,10 @@ public class SalFlowServiceImplTest extends TestCase {
         AddFlowInput mockedAddFlowInput = new AddFlowInputBuilder()
                 .setMatch(match)
                 .setTableId((short)1)
+                .setNode(noderef)
                 .build();
         SalFlowServiceImpl salFlowService = mockSalFlowService(version);
 
-        mockingFlowRegistryLookup();
         verifyOutput(salFlowService.addFlow(mockedAddFlowInput));
     }
 
@@ -237,6 +269,7 @@ public class SalFlowServiceImplTest extends TestCase {
         RemoveFlowInput mockedRemoveFlowInput = new RemoveFlowInputBuilder()
                 .setMatch(match)
                 .setTableId((short)1)
+                .setNode(noderef)
                 .build();
 
         SalFlowServiceImpl salFlowService = mockSalFlowService(version);
@@ -294,20 +327,12 @@ public class SalFlowServiceImplTest extends TestCase {
         when(mockedUpdateFlowInput1.getOriginalFlow()).thenReturn(mockedOriginalFlow1);
 
         SalFlowServiceImpl salFlowService = mockSalFlowService(version);
-
+        when(mockedUpdateFlowInput.getNode()).thenReturn(noderef);
+        when(mockedUpdateFlowInput1.getNode()).thenReturn(noderef);
         verifyOutput(salFlowService.updateFlow(mockedUpdateFlowInput));
         verifyOutput(salFlowService.updateFlow(mockedUpdateFlowInput1));
     }
 
-    private void mockingFlowRegistryLookup() {
-        FlowDescriptor mockedFlowDescriptor = mock(FlowDescriptor.class);
-        FlowId flowId = new FlowId(DUMMY_FLOW_ID);
-        when(mockedFlowDescriptor.getFlowId()).thenReturn(flowId);
-
-        when(deviceFlowRegistry
-                .retrieveDescriptor(any(FlowRegistryKey.class))).thenReturn(mockedFlowDescriptor);
-    }
-
     private static <T extends DataObject> void verifyOutput(final Future<RpcResult<T>> rpcResultFuture)
             throws ExecutionException, InterruptedException {
         assertNotNull(rpcResultFuture);
index 33ee1f8e71de7464e8fc24754a38666b4af6460e..895f65e9024825323211642ac6a21f46fd676c27 100755 (executable)
@@ -11,6 +11,7 @@ import static org.mockito.Mockito.verify;
 
 import org.junit.Test;
 import org.mockito.Mock;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
 import org.opendaylight.openflowplugin.api.openflow.registry.group.DeviceGroupRegistry;
 import org.opendaylight.openflowplugin.impl.services.ServiceMocking;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
@@ -29,20 +30,33 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.gro
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroup;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroupBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+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;
 
 public class SalGroupServiceImplTest extends ServiceMocking {
 
     private static final Long DUMMY_GROUP_ID = 15L;
+    private static final
+        KeyedInstanceIdentifier<Node, NodeKey> NODE_II = InstanceIdentifier.create(Nodes.class).child(Node.class,
+            new NodeKey(new NodeId(DUMMY_NODE_ID)));
+    NodeRef noderef = new NodeRef(NODE_II);
 
     @Mock
     DeviceGroupRegistry mockedDeviceGroupRegistry;
+    FlowGroupCacheManager flowGroupCacheManager;
 
     SalGroupServiceImpl salGroupService;
 
     @Override
     protected void setup() {
         final ConvertorManager convertorManager = ConvertorManagerFactory.createDefaultManager();
-        salGroupService = new SalGroupServiceImpl(mockedRequestContextStack, mockedDeviceContext, convertorManager);
+        salGroupService = new SalGroupServiceImpl(mockedRequestContextStack, mockedDeviceContext, convertorManager,
+                flowGroupCacheManager);
     }
 
     @Test
@@ -52,7 +66,7 @@ public class SalGroupServiceImplTest extends ServiceMocking {
 
     private void addGroup() {
         final GroupId dummyGroupId = new GroupId(DUMMY_GROUP_ID);
-        AddGroupInput addGroupInput = new AddGroupInputBuilder().setGroupId(dummyGroupId).build();
+        AddGroupInput addGroupInput = new AddGroupInputBuilder().setGroupId(dummyGroupId).setNode(noderef).build();
 
         this.<AddGroupOutput>mockSuccessfulFuture();
 
index 7c768174d97497e48c7de6e66285ab9133f5e9fe..cce1903580c95b18d80b9a1a51621bcbfa82b1b9 100644 (file)
@@ -19,6 +19,7 @@ import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnitRunner;
 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
+import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
@@ -61,6 +62,7 @@ public class MdSalRegistrationUtilsTest {
     private NotificationPublishService notificationPublishService;
 
     private ConvertorManager convertorManager;
+    private FlowGroupCacheManager flowGroupCacheManager;
 
     @Before
     public void setUp() {
@@ -76,7 +78,8 @@ public class MdSalRegistrationUtilsTest {
         MdSalRegistrationUtils.registerServices(mockedRpcContext,
                                                 mockedDeviceContext,
                                                 extensionConverterProvider,
-                                                convertorManager);
+                                                convertorManager,
+                                                flowGroupCacheManager);
         verify(mockedRpcContext, times(NUMBER_OF_RPC_SERVICE_REGISTRATION)).registerRpcServiceImplementation(
                 any(), any(RpcService.class));
     }