Inventory Cleanup fails as txn could not be created 77/28977/5
authorKamal Rameshan <kramesha@cisco.com>
Sun, 4 Oct 2015 07:15:18 +0000 (00:15 -0700)
committerKamal Rameshan <kramesha@cisco.com>
Wed, 11 Nov 2015 21:20:14 +0000 (13:20 -0800)
Cleanup of the inventory is done post closure of txn manager.

Hence if the status of the txn manager is shutting-down, get the WriteTx directly
to perform a datastore cleanup

Change-Id: If9dc9449f7e54e54ea4159376217297f6998e289
Signed-off-by: Kamal Rameshan <kramesha@cisco.com>
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/TransactionChainManager.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/DeviceTransactionChainManagerProviderTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/TransactionChainManagerTest.java

index dbc9b54f1a9255a819aaeb6776e96474f16c83a1..5731c93bfde19943525c6e1c2331760336618247 100644 (file)
@@ -412,13 +412,13 @@ public class DeviceContextImpl implements DeviceContext {
         }
 
         LOG.info("Closing transaction chain manager without cleaning inventory operational");
-        transactionChainManager.closeWithoutCleanup();
+        transactionChainManager.close();
     }
 
     @Override
     public void onDeviceDisconnectedFromCluster() {
         LOG.info("Removing device from operational and closing transaction Manager for device:{}", getDeviceState().getNodeId());
-        transactionChainManager.close();
+        transactionChainManager.cleanupPostClosure();
     }
 
     @Override
index 9bd51876c7ce3678e8ef3c3441acffff421428b2..06228701495bec0be2cbedd9934f90ac2ae76226 100644 (file)
@@ -183,16 +183,39 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
         submitIsEnabled = true;
     }
 
-    @Override
-    public void close() {
+    /**
+     * When a device disconnects from a node of the cluster, the device context gets closed. With that the txChainMgr
+     * status is set to SHUTTING_DOWN and is closed.
+     * When the EntityOwnershipService notifies and is derived that this was indeed the last node from which the device
+     * had disconnected, then we clean the inventory.
+     * Called from DeviceContext
+     */
+    public void cleanupPostClosure() {
         LOG.debug("Removing node {} from operational DS.", nodeII);
         synchronized (txLock) {
-            final WriteTransaction writeTx = getTransactionSafely();
+            final WriteTransaction writeTx;
+
+            //TODO(Kamal): Fix this. This might cause two txChain Manager working on the same node.
+            if (txChainFactory == null) {
+                LOG.info("Creating new Txn Chain Factory for cleanup purposes - Race Condition Hazard, " +
+                        "Concurrent Modification Hazard, node:{}", nodeII);
+                createTxChain(dataBroker);
+            }
+
+            if (TransactionChainManagerStatus.SHUTTING_DOWN.equals(transactionChainManagerStatus)) {
+                // status is already shutdown. so get the tx directly
+                writeTx = txChainFactory.newWriteOnlyTransaction();
+            } else {
+                writeTx = getTransactionSafely();
+            }
+
             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) {
@@ -228,10 +251,12 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
             }
         }
         txChainFactory.close();
+        txChainFactory = null;
         LOG.debug("Transaction chain factory closed.");
     }
 
-    public void closeWithoutCleanup() {
+    @Override
+    public void close() {
         LOG.debug("closing txChainManager without cleanup of node {} from operational DS.", nodeII);
         synchronized (txLock) {
             this.transactionChainManagerStatus = TransactionChainManagerStatus.SHUTTING_DOWN;
index 98df88ee5c2544aea24c457f66f9bdb5f45b4c82..7c918a839a5702245dfd0f7b1747f9054dcdb951 100644 (file)
@@ -373,7 +373,7 @@ public class DeviceContextImplTest {
         deviceContext.close();
         verify(connectionContext).closeConnection(eq(false));
         verify(deviceState).setValid(eq(false));
-        verify(txChainManager).closeWithoutCleanup();
+        verify(txChainManager).close();
         verify(mockedAuxiliaryConnectionContext).closeConnection(eq(false));
     }
 
@@ -483,6 +483,6 @@ public class DeviceContextImplTest {
         Assert.assertEquals(0, deviceContext.getDeviceGroupRegistry().getAllGroupIds().size());
         Assert.assertEquals(0, deviceContext.getDeviceMeterRegistry().getAllMeterIds().size());
 
-        Mockito.verify(txChainManager).closeWithoutCleanup();
+        Mockito.verify(txChainManager).close();
     }
 }
index 6b759be020636e3ceb5219048c05569471900879..e4691fdd4793af94919bfa60ea1b359ebde1f313 100644 (file)
@@ -154,7 +154,7 @@ public class DeviceTransactionChainManagerProviderTest {
                     }
                 });
         Mockito.when(writeTx.submit()).thenReturn(checkedSubmitCleanFuture);
-        txChainManager.close();
+        txChainManager.cleanupPostClosure();
         Assert.assertEquals(TransactionChainManager.TransactionChainManagerStatus.SHUTTING_DOWN,
                 txChainManagerRegistration_1.getTransactionChainManager().getTransactionChainManagerStatus());
         txChainManager.attemptToRegisterHandler(readyForNewTransactionChainHandler);
index 9026c60f810c9f34f9a7b9300eb457336e6d380b..7909a3637a80bab91b7c81d7c9b686fd7156033a 100644 (file)
@@ -166,7 +166,7 @@ public class TransactionChainManagerTest {
     public void testAttemptToRegisterHandler2() throws Exception {
         final InOrder inOrder = Mockito.inOrder(writeTx, txChain);
 
-        txChainManager.close();
+        txChainManager.cleanupPostClosure();
         Assert.assertEquals(TransactionChainManager.TransactionChainManagerStatus.SHUTTING_DOWN, txChainManager.getTransactionChainManagerStatus());
 
         boolean attemptResult = txChainManager.attemptToRegisterHandler(readyForNewTransactionChainHandler);