X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-distributed-datastore%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fcluster%2Fdatastore%2FSimpleShardDataTreeCohort.java;h=5dda3612a14150c1397664d2ef94918795a09ea0;hp=9f22ce8a73e2380625f2f03c0e1ab5e7b35a2c29;hb=8e6e0aeb5ca474cb292aab6ca581e921b0a56489;hpb=559c2b6afa7714572e01b52029acaa4d5a7315e2 diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/SimpleShardDataTreeCohort.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/SimpleShardDataTreeCohort.java index 9f22ce8a73..5dda3612a1 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/SimpleShardDataTreeCohort.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/SimpleShardDataTreeCohort.java @@ -10,8 +10,13 @@ package org.opendaylight.controller.cluster.datastore; import com.google.common.base.Preconditions; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import org.opendaylight.controller.cluster.datastore.utils.PruningDataTreeModification; +import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException; +import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; +import org.opendaylight.yangtools.yang.data.api.schema.tree.ConflictingModificationAppliedException; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateTip; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification; +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,11 +26,14 @@ final class SimpleShardDataTreeCohort extends ShardDataTreeCohort { private static final ListenableFuture VOID_FUTURE = Futures.immediateFuture(null); private final DataTreeModification transaction; private final ShardDataTree dataTree; + private final String transactionId; private DataTreeCandidateTip candidate; - SimpleShardDataTreeCohort(final ShardDataTree dataTree, final DataTreeModification transaction) { + SimpleShardDataTreeCohort(final ShardDataTree dataTree, final DataTreeModification transaction, + final String transactionId) { this.dataTree = Preconditions.checkNotNull(dataTree); this.transaction = Preconditions.checkNotNull(transaction); + this.transactionId = transactionId; } @Override @@ -35,11 +43,25 @@ final class SimpleShardDataTreeCohort extends ShardDataTreeCohort { @Override public ListenableFuture canCommit() { + DataTreeModification modification = getDataTreeModification(); try { - dataTree.getDataTree().validate(transaction); - LOG.debug("Transaction {} validated", transaction); + dataTree.getDataTree().validate(modification); + LOG.trace("Transaction {} validated", transaction); return TRUE_FUTURE; + } + catch (ConflictingModificationAppliedException e) { + LOG.warn("Store Tx {}: Conflicting modification for path {}.", transactionId, e.getPath()); + return Futures.immediateFailedFuture(new OptimisticLockFailedException("Optimistic lock failed.", e)); + } catch (DataValidationFailedException e) { + LOG.warn("Store Tx {}: Data validation failed for path {}.", transactionId, e.getPath(), e); + + // For debugging purposes, allow dumping of the modification. Coupled with the above + // precondition log, it should allow us to understand what went on. + LOG.debug("Store Tx {}: modifications: {} tree: {}", transactionId, modification, dataTree.getDataTree()); + + return Futures.immediateFailedFuture(new TransactionCommitFailedException("Data did not pass validation.", e)); } catch (Exception e) { + LOG.warn("Unexpected failure in validation phase", e); return Futures.immediateFailedFuture(e); } } @@ -47,19 +69,32 @@ final class SimpleShardDataTreeCohort extends ShardDataTreeCohort { @Override public ListenableFuture preCommit() { try { - candidate = dataTree.getDataTree().prepare(transaction); + candidate = dataTree.getDataTree().prepare(getDataTreeModification()); /* * FIXME: this is the place where we should be interacting with persistence, specifically by invoking * persist on the candidate (which gives us a Future). */ - LOG.debug("Transaction {} prepared candidate {}", transaction, candidate); + LOG.trace("Transaction {} prepared candidate {}", transaction, candidate); return VOID_FUTURE; } catch (Exception e) { - LOG.debug("Transaction {} failed to prepare", transaction, e); + if(LOG.isTraceEnabled()) { + LOG.trace("Transaction {} failed to prepare", transaction, e); + } else { + LOG.error("Transaction failed to prepare", e); + } return Futures.immediateFailedFuture(e); } } + @Override + DataTreeModification getDataTreeModification() { + DataTreeModification dataTreeModification = transaction; + if(transaction instanceof PruningDataTreeModification){ + dataTreeModification = ((PruningDataTreeModification) transaction).getResultingModification(); + } + return dataTreeModification; + } + @Override public ListenableFuture abort() { // No-op, really @@ -71,11 +106,15 @@ final class SimpleShardDataTreeCohort extends ShardDataTreeCohort { try { dataTree.getDataTree().commit(candidate); } catch (Exception e) { - LOG.error("Transaction {} failed to commit", transaction, e); + if(LOG.isTraceEnabled()) { + LOG.trace("Transaction {} failed to commit", transaction, e); + } else { + LOG.error("Transaction failed to commit", e); + } return Futures.immediateFailedFuture(e); } - LOG.debug("Transaction {} committed, proceeding to notify", transaction); + LOG.trace("Transaction {} committed, proceeding to notify", transaction); dataTree.notifyListeners(candidate); return VOID_FUTURE; }