Fix context chain closing
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / device / TransactionChainManager.java
index aded9b26d9ee3d76f6222f9ae172934ddf872885..350372d3a94a30a1a6911dfbaf6ca1a1847246ca 100644 (file)
@@ -17,8 +17,10 @@ import com.google.common.util.concurrent.ListenableFuture;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
 import javax.annotation.concurrent.GuardedBy;
 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -30,7 +32,6 @@ import org.opendaylight.controller.md.sal.common.api.data.TransactionChainClosed
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
-import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
@@ -53,7 +54,6 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
     private final Object txLock = new Object();
     private final DataBroker dataBroker;
     private final String nodeId;
-    private LifecycleService lifecycleService;
 
     @GuardedBy("txLock")
     private WriteTransaction wTx;
@@ -72,7 +72,7 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
     TransactionChainManager(@Nonnull final DataBroker dataBroker,
                             @Nonnull final DeviceInfo deviceInfo) {
         this.dataBroker = dataBroker;
-        this.nodeId = deviceInfo.getNodeInstanceIdentifier().getKey().getId().getValue();
+        this.nodeId = deviceInfo.getLOGValue();
         this.lastSubmittedFuture = Futures.immediateFuture(null);
     }
 
@@ -83,13 +83,9 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
         Optional.ofNullable(txChainFactoryTemp).ifPresent(TransactionChain::close);
     }
 
-    public void setLifecycleService(final LifecycleService lifecycleService) {
-        this.lifecycleService = lifecycleService;
-    }
-
-    void initialSubmitWriteTransaction() {
+    boolean initialSubmitWriteTransaction() {
         enableSubmit();
-        submitWriteTransaction();
+        return submitWriteTransaction();
     }
 
     /**
@@ -99,12 +95,15 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
      */
     void activateTransactionManager() {
         if (LOG.isDebugEnabled()) {
-            LOG.debug("activateTransactionManager for node {} transaction submit is set to {}", this.nodeId, submitIsEnabled);
+            LOG.debug("activateTransactionManager for node {} transaction submit is set to {}",
+                    this.nodeId, submitIsEnabled);
         }
         synchronized (txLock) {
             if (TransactionChainManagerStatus.SLEEPING == transactionChainManagerStatus) {
-                Preconditions.checkState(txChainFactory == null, "TxChainFactory survive last close.");
-                Preconditions.checkState(wTx == null, "We have some unexpected WriteTransaction.");
+                Preconditions.checkState(txChainFactory == null,
+                        "TxChainFactory survive last close.");
+                Preconditions.checkState(wTx == null,
+                        "We have some unexpected WriteTransaction.");
                 this.transactionChainManagerStatus = TransactionChainManagerStatus.WORKING;
                 this.submitIsEnabled = false;
                 this.initCommit = true;
@@ -128,7 +127,8 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
             if (TransactionChainManagerStatus.WORKING == transactionChainManagerStatus) {
                 transactionChainManagerStatus = TransactionChainManagerStatus.SLEEPING;
                 future = txChainShuttingDown();
-                Preconditions.checkState(wTx == null, "We have some unexpected WriteTransaction.");
+                Preconditions.checkState(wTx == null,
+                        "We have some unexpected WriteTransaction.");
                 Futures.addCallback(future, new FutureCallback<Void>() {
                     @Override
                     public void onSuccess(final Void result) {
@@ -141,7 +141,7 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
                     }
                 });
             } else {
-                // TODO : ignoring redundant deactivate invocation
+                // ignoring redundant deactivate invocation
                 future = Futures.immediateCheckedFuture(null);
             }
         }
@@ -168,15 +168,27 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
                 return true;
             }
             Preconditions.checkState(TransactionChainManagerStatus.WORKING == transactionChainManagerStatus,
-                    "we have here Uncompleted Transaction for node {} and we are not MASTER", this.nodeId);
+                    "we have here Uncompleted Transaction for node {} and we are not MASTER",
+                    this.nodeId);
             final CheckedFuture<Void, TransactionCommitFailedException> submitFuture = wTx.submit();
             lastSubmittedFuture = submitFuture;
             wTx = null;
 
+            if (initCommit) {
+                try {
+                    submitFuture.get(5L, TimeUnit.SECONDS);
+                } catch (InterruptedException | ExecutionException | TimeoutException ex) {
+                    LOG.error("Exception during INITIAL transaction submitting. ", ex);
+                    return false;
+                }
+                initCommit = false;
+                return true;
+            }
+
             Futures.addCallback(submitFuture, new FutureCallback<Void>() {
                 @Override
                 public void onSuccess(final Void result) {
-                    initCommit = false;
+                    //NOOP
                 }
 
                 @Override
@@ -191,9 +203,6 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
                             LOG.error("Exception during transaction submitting. ", t);
                         }
                     }
-                    if (initCommit) {
-                        Optional.ofNullable(lifecycleService).ifPresent(LifecycleService::closeConnection);
-                    }
                 }
             });
         }
@@ -246,7 +255,6 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
     }
 
     @GuardedBy("txLock")
-    @Nullable
     private void ensureTransaction() {
         if (wTx == null && TransactionChainManagerStatus.WORKING == transactionChainManagerStatus
             && txChainFactory != null) {
@@ -274,11 +282,18 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
 
     @GuardedBy("txLock")
     private ListenableFuture<Void> txChainShuttingDown() {
+        boolean wasSubmitEnabled = submitIsEnabled;
         submitIsEnabled = false;
         ListenableFuture<Void> future;
-        if (txChainFactory == null) {
+
+        if (!wasSubmitEnabled || txChainFactory == null) {
             // stay with actual thread
             future = Futures.immediateCheckedFuture(null);
+
+            if (wTx != null) {
+                wTx.cancel();
+                wTx = null;
+            }
         } else if (wTx == null) {
             // hijack md-sal thread
             future = lastSubmittedFuture;
@@ -290,6 +305,7 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
             future = wTx.submit();
             wTx = null;
         }
+
         return future;
     }