Merge "GetFlowNodeCache cli"
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / services / sal / SalGroupServiceImpl.java
old mode 100644 (file)
new mode 100755 (executable)
index b041541..df8380b
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
@@ -7,20 +7,24 @@
  */
 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 java.util.concurrent.Future;
-import javax.annotation.Nullable;
+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.api.openflow.rpc.ItemLifeCycleSource;
-import org.opendaylight.openflowplugin.api.openflow.rpc.listener.ItemLifecycleListener;
-import org.opendaylight.openflowplugin.impl.services.singlelayer.SingleLayerGroupService;
 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.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInput;
@@ -29,17 +33,12 @@ 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.group.types.rev131018.GroupId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
-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;
+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;
 
-public class SalGroupServiceImpl implements SalGroupService, ItemLifeCycleSource {
+public class SalGroupServiceImpl implements SalGroupService {
     private static final Logger LOG = LoggerFactory.getLogger(SalGroupServiceImpl.class);
     private final MultiLayerGroupService<AddGroupInput, AddGroupOutput> addGroup;
     private final MultiLayerGroupService<Group, UpdateGroupOutput> updateGroup;
@@ -49,13 +48,30 @@ public class SalGroupServiceImpl implements SalGroupService, ItemLifeCycleSource
     private final SingleLayerGroupService<RemoveGroupOutput> removeGroupMessage;
 
     private final DeviceContext deviceContext;
-    private ItemLifecycleListener itemLifecycleListener;
+    private final FlowGroupCacheManager provider ;
 
-    public SalGroupServiceImpl(final RequestContextStack requestContextStack, final DeviceContext deviceContext, final ConvertorExecutor convertorExecutor) {
+    public static final int FLOWGROUP_CACHE_SIZE = 10000;
+
+    public SalGroupServiceImpl(final RequestContextStack requestContextStack,
+                               final DeviceContext deviceContext,
+                               final ConvertorExecutor convertorExecutor,
+                               final FlowGroupCacheManager provider) {
         this.deviceContext = deviceContext;
-        addGroup = new MultiLayerGroupService<>(requestContextStack, deviceContext, AddGroupOutput.class, convertorExecutor);
-        updateGroup = new MultiLayerGroupService<>(requestContextStack, deviceContext, UpdateGroupOutput.class, convertorExecutor);
-        removeGroup = new MultiLayerGroupService<>(requestContextStack, deviceContext, RemoveGroupOutput.class, convertorExecutor);
+        this.provider = provider;
+        addGroup = new MultiLayerGroupService<>(requestContextStack,
+                                                deviceContext,
+                                                AddGroupOutput.class,
+                                                convertorExecutor);
+
+        updateGroup = new MultiLayerGroupService<>(requestContextStack,
+                                                   deviceContext,
+                                                   UpdateGroupOutput.class,
+                                                   convertorExecutor);
+
+        removeGroup = new MultiLayerGroupService<>(requestContextStack,
+                                                   deviceContext,
+                                                   RemoveGroupOutput.class,
+                                                   convertorExecutor);
 
         addGroupMessage = new SingleLayerGroupService<>(requestContextStack, deviceContext, AddGroupOutput.class);
         updateGroupMessage = new SingleLayerGroupService<>(requestContextStack, deviceContext, UpdateGroupOutput.class);
@@ -63,25 +79,28 @@ public class SalGroupServiceImpl implements SalGroupService, ItemLifeCycleSource
     }
 
     @Override
-    public void setItemLifecycleListener(@Nullable ItemLifecycleListener itemLifecycleListener) {
-        this.itemLifecycleListener = itemLifecycleListener;
-    }
-
-    @Override
-    public Future<RpcResult<AddGroupOutput>> addGroup(final AddGroupInput input) {
-        final ListenableFuture<RpcResult<AddGroupOutput>> resultFuture = addGroupMessage.canUseSingleLayerSerialization()
+    public ListenableFuture<RpcResult<AddGroupOutput>> addGroup(final AddGroupInput input) {
+        final ListenableFuture<RpcResult<AddGroupOutput>> resultFuture =
+            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()) {
-                    if (LOG.isDebugEnabled()) {
-                        LOG.debug("Group add with id={} finished without error", 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);
                     }
-                    deviceContext.getDeviceGroupRegistry().store(input.getGroupId());
-                    addIfNecessaryToDS(input.getGroupId(), input);
                 } else {
                     if (LOG.isDebugEnabled()) {
                         LOG.debug("Group add with id={} failed, errors={}", input.getGroupId().getValue(),
@@ -91,17 +110,20 @@ public class SalGroupServiceImpl implements SalGroupService, ItemLifeCycleSource
             }
 
             @Override
-            public void onFailure(Throwable t) {
-                LOG.warn("Service call for adding group={} failed, reason: {}", input.getGroupId().getValue(), t);
+            public void onFailure(Throwable throwable) {
+                LOG.warn("Service call for adding group={} failed",
+                          input.getGroupId().getValue(),
+                          throwable);
             }
-        });
+        }, MoreExecutors.directExecutor());
         return resultFuture;
     }
 
 
     @Override
-    public Future<RpcResult<UpdateGroupOutput>> updateGroup(final UpdateGroupInput input) {
-        final ListenableFuture<RpcResult<UpdateGroupOutput>> resultFuture = updateGroupMessage.canUseSingleLayerSerialization()
+    public ListenableFuture<RpcResult<UpdateGroupOutput>> updateGroup(final UpdateGroupInput input) {
+        final ListenableFuture<RpcResult<UpdateGroupOutput>> resultFuture =
+            updateGroupMessage.canUseSingleLayerSerialization()
             ? updateGroupMessage.handleServiceCall(input.getUpdatedGroup())
             : updateGroup.handleServiceCall(input.getUpdatedGroup());
 
@@ -109,12 +131,23 @@ public class SalGroupServiceImpl implements SalGroupService, ItemLifeCycleSource
             @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());
                     }
-                    removeIfNecessaryFromDS(input.getOriginalGroup().getGroupId());
-                    addIfNecessaryToDS(input.getUpdatedGroup().getGroupId(), input.getUpdatedGroup());
                 } else {
                     LOG.warn("Group update with original id={} failed, errors={}",
                         input.getOriginalGroup().getGroupId(), ErrorUtil.errorsToString(result.getErrors()));
@@ -123,17 +156,18 @@ public class SalGroupServiceImpl implements SalGroupService, ItemLifeCycleSource
             }
 
             @Override
-            public void onFailure(Throwable t) {
-                LOG.warn("Service call for updating group={} failed, reason: {}",
-                        input.getOriginalGroup().getGroupId(), t);
+            public void onFailure(Throwable throwable) {
+                LOG.warn("Service call for updating group={} failed",
+                        input.getOriginalGroup().getGroupId(), throwable);
             }
-        });
+        }, MoreExecutors.directExecutor());
         return resultFuture;
     }
 
     @Override
-    public Future<RpcResult<RemoveGroupOutput>> removeGroup(final RemoveGroupInput input) {
-        final ListenableFuture<RpcResult<RemoveGroupOutput>> resultFuture = removeGroupMessage.canUseSingleLayerSerialization()
+    public ListenableFuture<RpcResult<RemoveGroupOutput>> removeGroup(final RemoveGroupInput input) {
+        final ListenableFuture<RpcResult<RemoveGroupOutput>> resultFuture =
+            removeGroupMessage.canUseSingleLayerSerialization()
             ? removeGroupMessage.handleServiceCall(input)
             : removeGroup.handleServiceCall(input);
 
@@ -142,10 +176,20 @@ public class SalGroupServiceImpl implements SalGroupService, ItemLifeCycleSource
             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);
+                        }
                     }
-                    removeGroup.getDeviceRegistry().getDeviceGroupRegistry().addMark(input.getGroupId());
-                    removeIfNecessaryFromDS(input.getGroupId());
                 } else {
                     LOG.warn("Group remove with id={} failed, errors={}", input.getGroupId().getValue(),
                         ErrorUtil.errorsToString(result.getErrors()));
@@ -154,35 +198,12 @@ public class SalGroupServiceImpl implements SalGroupService, ItemLifeCycleSource
             }
 
             @Override
-            public void onFailure(Throwable t) {
-                LOG.warn("Service call for removing group={} failed, reason: {}",
-                        input.getGroupId().getValue(), t);
+            public void onFailure(Throwable throwable) {
+                LOG.warn("Service call for removing group={} failed",
+                        input.getGroupId().getValue(), throwable);
             }
-        });
+        }, MoreExecutors.directExecutor());
         return resultFuture;
     }
 
-    private void removeIfNecessaryFromDS(final GroupId groupId) {
-        if (itemLifecycleListener != null) {
-            KeyedInstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group, GroupKey> groupPath
-                    = createGroupPath(groupId,
-                    deviceContext.getDeviceInfo().getNodeInstanceIdentifier());
-            itemLifecycleListener.onRemoved(groupPath);
-        }
-    }
-
-    private void addIfNecessaryToDS(final GroupId groupId, final Group data) {
-        if (itemLifecycleListener != null) {
-            KeyedInstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group, GroupKey> groupPath
-                    = createGroupPath(groupId,
-                    deviceContext.getDeviceInfo().getNodeInstanceIdentifier());
-            itemLifecycleListener.onAdded(groupPath, new GroupBuilder(data).build());
-        }
-    }
-
-    private static KeyedInstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group, GroupKey>
-    createGroupPath(final GroupId groupId, final KeyedInstanceIdentifier<Node, NodeKey> nodePath) {
-        return nodePath.augmentation(FlowCapableNode.class).
-                child(org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group.class, new GroupKey(groupId));
-    }
 }