Bug 4143 - Transation failed with OptimisticLockFailedException 32/25332/3
authorIsaku Yamahata <isaku.yamahata@intel.com>
Sat, 15 Aug 2015 05:01:19 +0000 (22:01 -0700)
committerIsaku Yamahata <isaku.yamahata@intel.com>
Wed, 23 Sep 2015 05:17:02 +0000 (22:17 -0700)
transaction in AbstractNeutronInterface.updateMd() can abort with
OptimisticLockFailedException as follows when updating a same resource.
For example, when attaching an interface to a router,
neutron creates a port, then update it right after creation. It may
causes transaction abort.

o.o.controller.sal.restconf.impl.RestconfImpl#updateConfigurationData
has a similar issue and retries 2 times.
By following the precedence, add retry logic to updateMd() to mitigate
transaction abort.

> 2015-08-14 17:20:26,623 | WARN  | ult-dispatcher-4 | ConcurrentDOMDataBroker          | 157 - org.opendaylight.controller.sal-distributed-datastore - 1.3.0.SNAPSHOT | Tx: DOM-183 Error during phase CAN_COMMIT, starting Abort OptimisticLockFailedException{message=Optimistic lock failed., errorList=[RpcError [message=Optimistic lock failed., severity=ERROR, errorType=APPLICATION, tag=resource-denied, applicationTag=null, info=null, cause=org.opendaylight.yangtools.yang.data.api.schema.tree.ConflictingModificationAppliedException: Node was created by other transaction.]]}

Change-Id: I4fe57ad42867bbbfc38f4d0175ae417bc15afa0a
Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com>
transcriber/src/main/java/org/opendaylight/neutron/transcriber/AbstractNeutronInterface.java

index cca849d70d5d51ab8e74f1bfd81a607480b9bf08..2994e8f851c12d989e084833afd74a67b7c18ad6 100644 (file)
@@ -22,6 +22,7 @@ import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 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.OptimisticLockFailedException;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
@@ -168,16 +169,33 @@ public abstract class AbstractNeutronInterface<T extends DataObject, S extends I
 
    protected boolean _updateMd(S neutronObject, BindingTransactionChain chain) {
         Preconditions.checkNotNull(chain);
-        WriteTransaction transaction = chain.newWriteOnlyTransaction();
-        T item = toMd(neutronObject);
-        InstanceIdentifier<T> iid = createInstanceIdentifier(item);
-        transaction.put(LogicalDatastoreType.CONFIGURATION, iid, item,true);
-        CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
-        try {
-            future.get();
-        } catch (InterruptedException | ExecutionException e) {
-            LOGGER.warn("Transation failed ",e);
-            return false;
+
+        /*
+         * retry for transaction conflict.
+         * see the comment
+         * org.opendaylight.controller.sal.restconf.impl.RestconfImpl#updateConfigurationData
+         */
+        int retries = 2;
+        while (true) {
+            WriteTransaction transaction = chain.newWriteOnlyTransaction();
+            T item = toMd(neutronObject);
+            InstanceIdentifier<T> iid = createInstanceIdentifier(item);
+            transaction.put(LogicalDatastoreType.CONFIGURATION, iid, item, true);
+            CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
+            try {
+                future.get();
+            } catch (InterruptedException | ExecutionException e) {
+                if (e.getCause() instanceof OptimisticLockFailedException) {
+                    if(--retries >= 0) {
+                        LOGGER.debug("Got OptimisticLockFailedException - trying again {}", neutronObject);
+                        continue;
+                    }
+                    LOGGER.warn("Got OptimisticLockFailedException on last try - failing {}", neutronObject);
+                }
+                LOGGER.warn("Transation failed ", e);
+                return false;
+            }
+            break;
         }
         return true;
     }