Bug 5596 Changes when closing device
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / device / DeviceManagerImpl.java
index ef850d972f48018a4b172dc3666b430264a758cd..0614df6bd5c2447102208e9cf7c9a29a0fb4fc21 100644 (file)
@@ -18,6 +18,7 @@ import io.netty.util.HashedWheelTimer;
 import io.netty.util.TimerTask;
 import java.util.Collections;
 import java.util.Iterator;
+import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ExecutionException;
@@ -154,7 +155,12 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
          * If context already exist we are in state closing process (connection flapping) and we should not propagate connection close
          */
          if (deviceContexts.containsKey(deviceInfo)) {
-            LOG.warn("Rejecting connection from node which is already connected and there exist deviceContext for it: {}", connectionContext.getNodeId());
+             DeviceContext deviceContext = deviceContexts.get(deviceInfo);
+             if (!deviceContext.getState().equals(OFPContext.CONTEXT_STATE.TERMINATION)) {
+                 LOG.warn("Context state for node {} is not in TERMINATION state, trying to reconnect", connectionContext.getNodeId().getValue());
+             } else {
+                 LOG.warn("Rejecting connection from node which is already connected and there exist deviceContext for it: {}", connectionContext.getNodeId().getValue());
+             }
              return false;
          }
 
@@ -184,7 +190,7 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
                 this,
                 convertorExecutor);
 
-        Verify.verify(deviceContexts.putIfAbsent(deviceInfo, deviceContext) == null, "DeviceCtx still not closed.");
+        deviceContexts.putIfAbsent(deviceInfo, deviceContext);
 
         final LifecycleService lifecycleService = new LifecycleServiceImpl();
         lifecycleService.setDeviceContext(deviceContext);
@@ -249,14 +255,15 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
 
     @Override
     public void onDeviceContextLevelDown(final DeviceInfo deviceInfo) {
-        LOG.debug("onDeviceContextClosed for Node {}", deviceInfo.getNodeId());
         deviceContexts.remove(deviceInfo);
-        updatePacketInRateLimiters();
         LifecycleService lifecycleService = lifecycleServices.remove(deviceInfo);
-        try {
-            lifecycleService.close();
-        } catch (Exception e) {
-            LOG.warn("Closing service for node {} was unsuccessful ", deviceInfo.getNodeId().getValue(), e);
+        updatePacketInRateLimiters();
+        if (Objects.nonNull(lifecycleService)) {
+            try {
+                lifecycleService.close();
+            } catch (Exception e) {
+                LOG.warn("Closing service for node {} was unsuccessful ", deviceInfo.getNodeId().getValue(), e);
+            }
         }
     }
 
@@ -291,30 +298,41 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
             return;
         }
 
+        if (deviceCtx.getState().equals(OFPContext.CONTEXT_STATE.TERMINATION)) {
+            LOG.debug("Device context for node {} is already is termination state, waiting for close all context");
+            return;
+        }
+
+        deviceCtx.setState(OFPContext.CONTEXT_STATE.TERMINATION);
+
         if (!connectionContext.equals(deviceCtx.getPrimaryConnectionContext())) {
+            LOG.debug("Node {} disconnected, but not primary connection.", connectionContext.getDeviceInfo().getNodeId().getValue());
             /* Connection is not PrimaryConnection so try to remove from Auxiliary Connections */
             deviceCtx.removeAuxiliaryConnectionContext(connectionContext);
-        } else {
+        }
+        //TODO: Auxiliary connections supported ?
+        {
             /* Device is disconnected and so we need to close TxManager */
             final ListenableFuture<Void> future = deviceCtx.shuttingDownDataStoreTransactions();
             Futures.addCallback(future, new FutureCallback<Void>() {
 
                 @Override
                 public void onSuccess(final Void result) {
-                    LOG.debug("TxChainManager for device {} is closed successful.", deviceInfo.getNodeId());
+                    LOG.debug("TxChainManager for device {} is closed successful.", deviceInfo.getNodeId().getValue());
                     deviceTerminPhaseHandler.onDeviceContextLevelDown(deviceInfo);
                 }
 
                 @Override
                 public void onFailure(final Throwable t) {
-                    LOG.warn("TxChainManager for device {} failed by closing.", deviceInfo.getNodeId(), t);
+                    LOG.warn("TxChainManager for device {} failed by closing.", deviceInfo.getNodeId().getValue());
+                    LOG.trace("TxChainManager failed by closing. ", t);
                     deviceTerminPhaseHandler.onDeviceContextLevelDown(deviceInfo);
                 }
             });
             /* Add timer for Close TxManager because it could fain ind cluster without notification */
             final TimerTask timerTask = timeout -> {
                 if (!future.isDone()) {
-                    LOG.info("Shutting down TxChain for node {} not completed during 10 sec. Continue anyway.", deviceInfo.getNodeId());
+                    LOG.warn("Shutting down TxChain for node {} not completed during 10 sec. Continue anyway.", deviceInfo.getNodeId().getValue());
                     future.cancel(false);
                 }
             };
@@ -327,11 +345,6 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
         deviceContexts.put(deviceInfo, deviceContext);
     }
 
-    @VisibleForTesting
-    void removeDeviceContextFromMap(final DeviceInfo deviceInfo){
-        deviceContexts.remove(deviceInfo);
-    }
-
     @Override
     public <T extends OFPContext> T gainContext(final DeviceInfo deviceInfo) {
         return (T) deviceContexts.get(deviceInfo);