From 1b462903a7e74d65a953070504bc72fdccbcc7af Mon Sep 17 00:00:00 2001 From: Tomas Cere Date: Fri, 24 Mar 2017 11:29:16 +0100 Subject: [PATCH] BUG 7801: prevent OptimisticLockFailedExceptions in write-transactions. When multiple instances of this rpc are running concurrently in paralel we would run into an optimistic lock since every instance tries to write the topmost parent list first. When these happen handle these failures as expected and resume with the next stage of the rpc. Change-Id: I43efaea3315b04272113eb86733e68609e434984 Signed-off-by: Tomas Cere --- .../impl/WriteTransactionsHandler.java | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/opendaylight/md-sal/samples/clustering-test-app/provider/src/main/java/org/opendaylight/controller/clustering/it/provider/impl/WriteTransactionsHandler.java b/opendaylight/md-sal/samples/clustering-test-app/provider/src/main/java/org/opendaylight/controller/clustering/it/provider/impl/WriteTransactionsHandler.java index fd47b7176b..664e7fd26f 100644 --- a/opendaylight/md-sal/samples/clustering-test-app/provider/src/main/java/org/opendaylight/controller/clustering/it/provider/impl/WriteTransactionsHandler.java +++ b/opendaylight/md-sal/samples/clustering-test-app/provider/src/main/java/org/opendaylight/controller/clustering/it/provider/impl/WriteTransactionsHandler.java @@ -26,6 +26,7 @@ import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; 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.TransactionChain; import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; @@ -127,17 +128,31 @@ public class WriteTransactionsHandler implements Runnable { private boolean ensureListExists(final SettableFuture> settableFuture) { + final MapNode mapNode = ImmutableNodes.mapNodeBuilder(ID_INTS).build(); + + DOMDataWriteTransaction tx = txProvider.createTransaction(); + // write only the top list + tx.merge(LogicalDatastoreType.CONFIGURATION, ID_INTS_YID, mapNode); + try { + tx.submit().checkedGet(); + } catch (final OptimisticLockFailedException e) { + // when multiple write-transactions are executed concurrently we need to ignore this. + // If we get optimistic lock here it means id-ints already exists and we can continue. + LOG.debug("Got an optimistic lock when writing initial top level list element.", e); + } catch (final TransactionCommitFailedException e) { + LOG.warn("Unable to ensure IdInts list for id: {} exists.", id, e); + settableFuture.set(RpcResultBuilder.failed() + .withError(RpcError.ErrorType.APPLICATION, "Unexpected-exception", e).build()); + return false; + } + final MapEntryNode entry = ImmutableNodes.mapEntryBuilder(ID_INTS, ID, id) .withChild(ImmutableNodes.mapNodeBuilder(ITEM).build()) .build(); - final MapNode mapNode = - ImmutableNodes.mapNodeBuilder(ID_INTS) - .withChild(entry) - .build(); - final DOMDataWriteTransaction tx = txProvider.createTransaction(); idListWithKey = ID_INTS_YID.node(entry.getIdentifier()); - tx.merge(LogicalDatastoreType.CONFIGURATION, ID_INTS_YID, mapNode); + tx = txProvider.createTransaction(); + tx.merge(LogicalDatastoreType.CONFIGURATION, idListWithKey, entry); try { tx.submit().checkedGet(); -- 2.36.6