use of org.opendaylight.mdsal.common.api.TransactionCommitFailedException in project controller by opendaylight.
the class DistributedDataStoreRemotingIntegrationTest method testChainedTransactionFailureWithSingleShard.
@Test
public void testChainedTransactionFailureWithSingleShard() throws Exception {
initDatastoresWithCars("testChainedTransactionFailureWithSingleShard");
final ConcurrentDOMDataBroker broker = new ConcurrentDOMDataBroker(ImmutableMap.<LogicalDatastoreType, DOMStore>builder().put(LogicalDatastoreType.CONFIGURATION, followerDistributedDataStore).build(), MoreExecutors.directExecutor());
final TransactionChainListener listener = Mockito.mock(TransactionChainListener.class);
final DOMTransactionChain txChain = broker.createTransactionChain(listener);
final DOMDataTreeWriteTransaction writeTx = txChain.newWriteOnlyTransaction();
final ContainerNode invalidData = ImmutableContainerNodeBuilder.create().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(CarsModel.BASE_QNAME)).withChild(ImmutableNodes.leafNode(TestModel.JUNK_QNAME, "junk")).build();
writeTx.merge(LogicalDatastoreType.CONFIGURATION, CarsModel.BASE_PATH, invalidData);
try {
writeTx.submit().checkedGet(5, TimeUnit.SECONDS);
fail("Expected TransactionCommitFailedException");
} catch (final TransactionCommitFailedException e) {
// Expected
}
verify(listener, timeout(5000)).onTransactionChainFailed(eq(txChain), eq(writeTx), any(Throwable.class));
txChain.close();
broker.close();
}
use of org.opendaylight.mdsal.common.api.TransactionCommitFailedException in project controller by opendaylight.
the class ConcurrentDOMDataBroker method doCanCommit.
private void doCanCommit(final AsyncNotifyingSettableFuture clientSubmitFuture, final DOMDataTreeWriteTransaction transaction, final Collection<DOMStoreThreePhaseCommitCohort> cohorts) {
final long startTime = System.nanoTime();
final Iterator<DOMStoreThreePhaseCommitCohort> cohortIterator = cohorts.iterator();
// Not using Futures.allAsList here to avoid its internal overhead.
FutureCallback<Boolean> futureCallback = new FutureCallback<Boolean>() {
@Override
public void onSuccess(final Boolean result) {
if (result == null || !result) {
handleException(clientSubmitFuture, transaction, cohorts, CAN_COMMIT, CAN_COMMIT_ERROR_MAPPER, new TransactionCommitFailedException("Can Commit failed, no detailed cause available."));
} else if (!cohortIterator.hasNext()) {
// All cohorts completed successfully - we can move on to the preCommit phase
doPreCommit(startTime, clientSubmitFuture, transaction, cohorts);
} else {
Futures.addCallback(cohortIterator.next().canCommit(), this, MoreExecutors.directExecutor());
}
}
@Override
public void onFailure(final Throwable failure) {
handleException(clientSubmitFuture, transaction, cohorts, CAN_COMMIT, CAN_COMMIT_ERROR_MAPPER, failure);
}
};
ListenableFuture<Boolean> canCommitFuture = cohortIterator.next().canCommit();
Futures.addCallback(canCommitFuture, futureCallback, MoreExecutors.directExecutor());
}
use of org.opendaylight.mdsal.common.api.TransactionCommitFailedException in project controller by opendaylight.
the class ConcurrentDOMDataBroker method handleException.
@SuppressFBWarnings(value = "BC_UNCONFIRMED_CAST_OF_RETURN_VALUE", justification = "Pertains to the assignment of the 'clientException' var. FindBugs flags this as an " + "uncomfirmed cast but the generic type in TransactionCommitFailedExceptionMapper is " + "TransactionCommitFailedException and thus should be deemed as confirmed.")
private static void handleException(final AsyncNotifyingSettableFuture clientSubmitFuture, final DOMDataTreeWriteTransaction transaction, final Collection<DOMStoreThreePhaseCommitCohort> cohorts, final String phase, final TransactionCommitFailedExceptionMapper exMapper, final Throwable throwable) {
if (clientSubmitFuture.isDone()) {
// We must have had failures from multiple cohorts.
return;
}
// Use debug instead of warn level here because this exception gets propagate back to the caller via the Future
LOG.debug("Tx: {} Error during phase {}, starting Abort", transaction.getIdentifier(), phase, throwable);
// Transaction failed - tell all cohorts to abort.
@SuppressWarnings("unchecked") ListenableFuture<Void>[] canCommitFutures = new ListenableFuture[cohorts.size()];
int index = 0;
for (DOMStoreThreePhaseCommitCohort cohort : cohorts) {
canCommitFutures[index++] = cohort.abort();
}
// Propagate the original exception
final Exception e;
if (throwable instanceof NoShardLeaderException || throwable instanceof ShardLeaderNotRespondingException) {
e = new DataStoreUnavailableException(throwable.getMessage(), throwable);
} else if (throwable instanceof Exception) {
e = (Exception) throwable;
} else {
e = new RuntimeException("Unexpected error occurred", throwable);
}
clientSubmitFuture.setException(exMapper.apply(e));
ListenableFuture<List<Void>> combinedFuture = Futures.allAsList(canCommitFutures);
Futures.addCallback(combinedFuture, new FutureCallback<List<Void>>() {
@Override
public void onSuccess(final List<Void> notUsed) {
// Propagate the original exception to the client.
LOG.debug("Tx: {} aborted successfully", transaction.getIdentifier());
}
@Override
public void onFailure(final Throwable failure) {
LOG.error("Tx: {} Error during Abort.", transaction.getIdentifier(), failure);
}
}, MoreExecutors.directExecutor());
}
use of org.opendaylight.mdsal.common.api.TransactionCommitFailedException in project controller by opendaylight.
the class ShardDataTree method processNextPendingTransaction.
@SuppressWarnings("checkstyle:IllegalCatch")
private void processNextPendingTransaction() {
++currentTransactionBatch;
if (currentTransactionBatch > MAX_TRANSACTION_BATCH) {
LOG.debug("{}: Already processed {}, scheduling continuation", logContext, currentTransactionBatch);
shard.scheduleNextPendingTransaction();
return;
}
processNextPending(pendingTransactions, State.CAN_COMMIT_PENDING, entry -> {
final SimpleShardDataTreeCohort cohort = entry.cohort;
final DataTreeModification modification = cohort.getDataTreeModification();
LOG.debug("{}: Validating transaction {}", logContext, cohort.getIdentifier());
Exception cause;
try {
tip.validate(modification);
LOG.debug("{}: Transaction {} validated", logContext, cohort.getIdentifier());
cohort.successfulCanCommit();
entry.lastAccess = readTime();
return;
} catch (ConflictingModificationAppliedException e) {
LOG.warn("{}: Store Tx {}: Conflicting modification for path {}.", logContext, cohort.getIdentifier(), e.getPath());
cause = new OptimisticLockFailedException("Optimistic lock failed.", e);
} catch (DataValidationFailedException e) {
LOG.warn("{}: Store Tx {}: Data validation failed for path {}.", logContext, cohort.getIdentifier(), 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: {}", cohort.getIdentifier(), modification, dataTree);
cause = new TransactionCommitFailedException("Data did not pass validation.", e);
} catch (Exception e) {
LOG.warn("{}: Unexpected failure in validation phase", logContext, e);
cause = e;
}
// Failure path: propagate the failure, remove the transaction from the queue and loop to the next one
pendingTransactions.poll().cohort.failedCanCommit(cause);
});
}
use of org.opendaylight.mdsal.common.api.TransactionCommitFailedException in project controller by opendaylight.
the class ConcurrentDOMDataBrokerTest method testSubmitWithCanCommitDataStoreUnavailableException.
@Test
public void testSubmitWithCanCommitDataStoreUnavailableException() throws Exception {
doReturn(Futures.immediateFuture(true)).when(mockCohort1).canCommit();
doReturn(Futures.immediateFuture(null)).when(mockCohort1).abort();
NoShardLeaderException rootCause = new NoShardLeaderException("mock");
DataStoreUnavailableException cause = new DataStoreUnavailableException(rootCause.getMessage(), rootCause);
doReturn(Futures.immediateFailedFuture(rootCause)).when(mockCohort2).canCommit();
doReturn(Futures.immediateFuture(null)).when(mockCohort2).abort();
CheckedFuture<Void, TransactionCommitFailedException> future = coordinator.submit(transaction, Arrays.asList(mockCohort1, mockCohort2));
assertFailure(future, cause, mockCohort1, mockCohort2);
}
Aggregations