Merge "Removed unused fields"
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / device / TransactionChainManager.java
index 079297928a8cd467e4dfe7c6e87aa0297735bdda..4706cc1df8d789a24605306c3a32c3563d5fc6eb 100644 (file)
@@ -10,6 +10,9 @@ package org.opendaylight.openflowplugin.impl.device;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
 import javax.annotation.Nonnull;
 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -18,9 +21,13 @@ import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+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.concepts.Registration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -34,7 +41,7 @@ import org.slf4j.LoggerFactory;
  * and submitTransaction method (wrapped {@link WriteTransaction#submit()})
  *
  * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *         <p/>
+ *         </p>
  *         Created: Apr 2, 2015
  */
 class TransactionChainManager implements TransactionChainListener, AutoCloseable {
@@ -43,64 +50,94 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
 
     private final Object txLock = new Object();
 
-    private final DeviceState deviceState;
     private final DataBroker dataBroker;
     private WriteTransaction wTx;
     private BindingTransactionChain txChainFactory;
     private boolean submitIsEnabled;
 
-    TransactionChainManager(@Nonnull final DataBroker dataBroker, @Nonnull final DeviceState deviceState) {
+    public TransactionChainManagerStatus getTransactionChainManagerStatus() {
+        return transactionChainManagerStatus;
+    }
+
+    private TransactionChainManagerStatus transactionChainManagerStatus;
+    private ReadyForNewTransactionChainHandler readyForNewTransactionChainHandler;
+    private final KeyedInstanceIdentifier<Node, NodeKey> nodeII;
+    private Registration managerRegistration;
+
+    TransactionChainManager(@Nonnull final DataBroker dataBroker,
+                            @Nonnull final KeyedInstanceIdentifier<Node, NodeKey> nodeII,
+                            @Nonnull final Registration managerRegistration) {
         this.dataBroker = Preconditions.checkNotNull(dataBroker);
-        this.deviceState = Preconditions.checkNotNull(deviceState);
-        txChainFactory = dataBroker.createTransactionChain(TransactionChainManager.this);
+        this.nodeII = Preconditions.checkNotNull(nodeII);
+        this.managerRegistration = Preconditions.checkNotNull(managerRegistration);
+        this.transactionChainManagerStatus = TransactionChainManagerStatus.WORKING;
+        createTxChain(dataBroker);
         LOG.debug("created txChainManager");
     }
 
+    private void createTxChain(final DataBroker dataBroker) {
+        txChainFactory = dataBroker.createTransactionChain(TransactionChainManager.this);
+    }
+
     void initialSubmitWriteTransaction() {
         enableSubmit();
         submitWriteTransaction();
     }
 
-    boolean submitWriteTransaction() {
-        if ( ! submitIsEnabled) {
-            LOG.trace("transaction not committed - submit block issued");
-            return false;
-        }
-        if (wTx == null) {
-            LOG.trace("nothing to commit - submit returns true");
+    public synchronized boolean attemptToRegisterHandler(final ReadyForNewTransactionChainHandler readyForNewTransactionChainHandler) {
+        if (TransactionChainManagerStatus.SHUTTING_DOWN.equals(this.transactionChainManagerStatus)
+                && null == this.readyForNewTransactionChainHandler) {
+            this.readyForNewTransactionChainHandler = readyForNewTransactionChainHandler;
+            if (managerRegistration == null) {
+                this.readyForNewTransactionChainHandler.onReadyForNewTransactionChain();
+            }
             return true;
+        } else {
+            return false;
         }
-        if ( ! deviceState.isValid()) {
-            LOG.info("DeviceState is not valid will not submit transaction");
+    }
+
+    boolean submitWriteTransaction() {
+        if (!submitIsEnabled) {
+            LOG.trace("transaction not committed - submit block issued");
             return false;
         }
         synchronized (txLock) {
-            wTx.submit();
+            if (wTx == null) {
+                LOG.trace("nothing to commit - submit returns true");
+                return true;
+            }
+            final CheckedFuture<Void, TransactionCommitFailedException> submitFuture = wTx.submit();
+            Futures.addCallback(submitFuture, new FutureCallback<Void>() {
+                @Override
+                public void onSuccess(Void result) {
+                    //no action required
+                }
+
+                @Override
+                public void onFailure(Throwable t) {
+                    if (t instanceof TransactionCommitFailedException) {
+                        LOG.error("Transaction commit failed. {}", t);
+                    } else {
+                        LOG.error("Exception during transaction submitting. {}", t);
+                    }
+                }
+            });
             wTx = null;
         }
         return true;
     }
 
     <T extends DataObject> void addDeleteOperationTotTxChain(final LogicalDatastoreType store,
-            final InstanceIdentifier<T> path) {
-        try {
-            final WriteTransaction writeTx = getTransactionSafely();
-            writeTx.delete(store, path);
-        } catch (final Exception e) {
-            LOG.warn("failed to put into writeOnlyTransaction : {}", e.getMessage());
-            LOG.trace("failed to put into writeOnlyTransaction.. ", e);
-        }
+                                                             final InstanceIdentifier<T> path) {
+        final WriteTransaction writeTx = getTransactionSafely();
+        writeTx.delete(store, path);
     }
 
     <T extends DataObject> void writeToTransaction(final LogicalDatastoreType store,
-            final InstanceIdentifier<T> path, final T data) {
-        try {
-            final WriteTransaction writeTx = getTransactionSafely();
-            writeTx.put(store, path, data);
-        } catch (final Exception e) {
-            LOG.warn("failed to put into writeOnlyTransaction: {}", e.getMessage());
-            LOG.trace("failed to put into writeOnlyTransaction.. ", e);
-        }
+                                                   final InstanceIdentifier<T> path, final T data) {
+        final WriteTransaction writeTx = getTransactionSafely();
+        writeTx.put(store, path, data);
     }
 
     @Override
@@ -117,14 +154,14 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
 
     private void recreateTxChain() {
         txChainFactory.close();
-        txChainFactory = dataBroker.createTransactionChain(TransactionChainManager.this);
+        createTxChain(dataBroker);
         synchronized (txLock) {
             wTx = null;
         }
     }
 
     private WriteTransaction getTransactionSafely() {
-        if (wTx == null) {
+        if (wTx == null && !TransactionChainManagerStatus.SHUTTING_DOWN.equals(transactionChainManagerStatus)) {
             synchronized (txLock) {
                 if (wTx == null) {
                     wTx = txChainFactory.newWriteOnlyTransaction();
@@ -140,14 +177,51 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
     }
 
     @Override
-    public void close() throws Exception {
-        LOG.debug("Removing node {} from operational DS.", deviceState.getNodeId());
+    public void close() {
+        LOG.debug("Removing node {} from operational DS.", nodeII);
         synchronized (txLock) {
             final WriteTransaction writeTx = getTransactionSafely();
-            writeTx.delete(LogicalDatastoreType.OPERATIONAL, deviceState.getNodeInstanceIdentifier());
-            writeTx.submit();
+            this.transactionChainManagerStatus = TransactionChainManagerStatus.SHUTTING_DOWN;
+            writeTx.delete(LogicalDatastoreType.OPERATIONAL, nodeII);
+            LOG.debug("Delete node {} from operational DS put to write transaction.", nodeII);
+            CheckedFuture<Void, TransactionCommitFailedException> submitsFuture = writeTx.submit();
+            LOG.debug("Delete node {} from operational DS write transaction submitted.", nodeII);
+            Futures.addCallback(submitsFuture, new FutureCallback<Void>() {
+                @Override
+                public void onSuccess(final Void aVoid) {
+                    LOG.debug("Removing node {} from operational DS successful .", nodeII);
+                    notifyReadyForNewTransactionChainAndCloseFactory();
+                }
+
+                @Override
+                public void onFailure(final Throwable throwable) {
+                    LOG.info("Attempt to close transaction chain factory failed.", throwable);
+                    notifyReadyForNewTransactionChainAndCloseFactory();
+                }
+            });
             wTx = null;
-            txChainFactory.close();
         }
     }
+
+    private void notifyReadyForNewTransactionChainAndCloseFactory() {
+        synchronized (this) {
+            try {
+                LOG.debug("Closing registration in manager.");
+                managerRegistration.close();
+            } catch (Exception e) {
+                LOG.warn("Failed to close transaction chain manager's registration.", e);
+            }
+            managerRegistration = null;
+            if (null != readyForNewTransactionChainHandler) {
+                readyForNewTransactionChainHandler.onReadyForNewTransactionChain();
+            }
+        }
+        txChainFactory.close();
+        LOG.debug("Transaction chain factory closed.");
+    }
+
+    public enum TransactionChainManagerStatus {
+        WORKING, SHUTTING_DOWN;
+    }
+
 }