Cleanup RequestContextStack
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / rpc / RpcContextImpl.java
index 9a8c19ec3cdc710dda9ea3787160df3107402958..ab39f92f3acd2e1f9e65e2beea69832dd3e86899 100644 (file)
@@ -7,36 +7,38 @@
  */
 package org.opendaylight.openflowplugin.impl.rpc;
 
-import com.google.common.util.concurrent.SettableFuture;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.concurrent.Semaphore;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
 import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
-import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeContext;
+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.yangtools.yang.binding.RpcService;
-import org.opendaylight.yangtools.yang.common.RpcError;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class RpcContextImpl implements RpcContext {
-
-    final ProviderContext providerContext;
+    private static final Logger LOG = LoggerFactory.getLogger(RpcContextImpl.class);
+    private final RpcProviderRegistry rpcProviderRegistry;
+    private final MessageSpy messageSpy;
+    private final Semaphore tracker;
 
     // TODO: add private Sal salBroker
-    private final List<RequestContext> requestContexts = new ArrayList<>();
-    private DeviceContext deviceContext;
-    private final List<RoutedRpcRegistration> rpcRegistrations = new ArrayList<>();
-    private final List<RequestContext> synchronizedRequestsList = Collections.synchronizedList(new ArrayList<RequestContext>());
-
-    private int maxRequestsPerDevice;
-
-    public RpcContextImpl(final ProviderContext providerContext, final DeviceContext deviceContext) {
-        this.providerContext = providerContext;
-        this.deviceContext = deviceContext;
+    private final KeyedInstanceIdentifier<Node, NodeKey> nodeInstanceIdentifier;
+    private final Collection<RoutedRpcRegistration<?>> rpcRegistrations = new HashSet<>();
+
+    public RpcContextImpl(final MessageSpy messageSpy, final RpcProviderRegistry rpcProviderRegistry, final KeyedInstanceIdentifier<Node, NodeKey> nodeInstanceIdentifier, final int maxRequests) {
+        this.messageSpy = messageSpy;
+        this.rpcProviderRegistry = rpcProviderRegistry;
+        this.nodeInstanceIdentifier = nodeInstanceIdentifier;
+        tracker = new Semaphore(maxRequests, true);
     }
 
     /**
@@ -46,60 +48,46 @@ public class RpcContextImpl implements RpcContext {
     @Override
     public <S extends RpcService> void registerRpcServiceImplementation(final Class<S> serviceClass,
                                                                         final S serviceInstance) {
-        rpcRegistrations.add(providerContext.addRoutedRpcImplementation(serviceClass, serviceInstance));
+        final RoutedRpcRegistration<S> routedRpcReg = rpcProviderRegistry.addRoutedRpcImplementation(serviceClass, serviceInstance);
+        routedRpcReg.registerPath(NodeContext.class, nodeInstanceIdentifier);
+        rpcRegistrations.add(routedRpcReg);
+        LOG.debug("Registration of service {} for device {}.", serviceClass, nodeInstanceIdentifier);
     }
 
-    @Override
-    public <T extends DataObject> SettableFuture<RpcResult<T>> storeOrFail(RequestContext requestContext) {
-        final SettableFuture<RpcResult<T>> rpcResultFuture = requestContext.getFuture();
-
-        if (synchronizedRequestsList.size() < maxRequestsPerDevice) {
-            synchronizedRequestsList.add(requestContext);
-        } else {
-            RpcResult rpcResult = RpcResultBuilder.failed().withError(RpcError.ErrorType.APPLICATION, "", "Device's request queue is full.").build();
-            rpcResultFuture.set(rpcResult);
-        }
-        return rpcResultFuture;
-    }
-
-
     /**
      * Unregisters all services.
      *
      * @see java.lang.AutoCloseable#close()
      */
     @Override
-    public void close() throws Exception {
-        for (final RoutedRpcRegistration rpcRegistration : rpcRegistrations) {
+    public void close() {
+        for (final RoutedRpcRegistration<?> rpcRegistration : rpcRegistrations) {
+            rpcRegistration.unregisterPath(NodeContext.class, nodeInstanceIdentifier);
             rpcRegistration.close();
         }
     }
 
-    /**
-     * @see org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext#setRequestContextQuota(int)
-     */
     @Override
-    public void setRequestContextQuota(final int maxRequestsPerDevice) {
-        this.maxRequestsPerDevice = maxRequestsPerDevice;
-    }
-
-    @Override
-    public void forgetRequestContext(final RequestContext requestContext) {
-        requestContexts.remove(requestContext);
-    }
+    public <T> RequestContext<T> createRequestContext() {
+        if (!tracker.tryAcquire()) {
+            LOG.trace("Device queue {} at capacity", this);
+            return null;
+        }
 
-    @Override
-    public DeviceContext getDeviceContext() {
-        return deviceContext;
+        return new AbstractRequestContext<T>() {
+            @Override
+            public void close() {
+                tracker.release();
+                LOG.trace("Removed request context with xid {}", getXid().getValue());
+                messageSpy.spyMessage(RpcContextImpl.class, MessageSpy.STATISTIC_GROUP.REQUEST_STACK_FREED);
+            }
+        };
     }
 
     @Override
-    public <T extends DataObject> RequestContext createRequestContext() {
-        return new RequestContextImpl<T>(this);
-    }
-
-    public boolean isRequestContextCapacityEmpty() {
-        return requestContexts.size() <= maxRequestsPerDevice;
+    public void onDeviceDisconnected(final ConnectionContext connectionContext) {
+        for (RoutedRpcRegistration<?> registration : rpcRegistrations) {
+            registration.close();
+        }
     }
-
 }