use of org.apache.tephra.TransactionFailureException in project cdap by caskdata.
the class TransactionContextTest method testPersistAndRollbackFalse.
@Test
public void testPersistAndRollbackFalse() throws TransactionFailureException, InterruptedException {
ds1.failCommitTxOnce = InduceFailure.ReturnFalse;
ds1.failRollbackTxOnce = InduceFailure.ReturnFalse;
TransactionContext context = newTransactionContext(ds1, ds2);
// start transaction
context.start();
// add a change to ds1 and ds2
ds1.addChange(A);
ds2.addChange(B);
// commit transaction should fail and cause rollback
try {
context.finish();
Assert.fail("Persist should have failed - exception should be thrown");
} catch (TransactionFailureException e) {
// in this case, the ds simply returned false
Assert.assertNull(e.getCause());
}
// verify both are rolled back and tx is invalidated
Assert.assertTrue(ds1.started);
Assert.assertTrue(ds2.started);
Assert.assertTrue(ds1.checked);
Assert.assertTrue(ds2.checked);
Assert.assertTrue(ds1.committed);
Assert.assertFalse(ds2.committed);
Assert.assertFalse(ds1.postCommitted);
Assert.assertFalse(ds2.postCommitted);
Assert.assertTrue(ds1.rolledBack);
Assert.assertTrue(ds2.rolledBack);
Assert.assertEquals(txClient.state, DummyTxClient.CommitState.Invalidated);
}
use of org.apache.tephra.TransactionFailureException in project cdap by caskdata.
the class TransactionContextTest method testAddThenFailure.
@Test
public void testAddThenFailure() throws TransactionFailureException, InterruptedException {
ds2.failCommitTxOnce = InduceFailure.ThrowException;
TransactionContext context = newTransactionContext(ds1);
// start transaction
context.start();
// add a change to ds1
ds1.addChange(A);
// add ds2 to the tx
context.addTransactionAware(ds2);
// add a change to ds2
ds2.addChange(B);
// commit transaction should fail and cause rollback
try {
context.finish();
Assert.fail("Persist should have failed - exception should be thrown");
} catch (TransactionFailureException e) {
Assert.assertEquals("persist failure", e.getCause().getMessage());
}
// verify both are rolled back and tx is aborted
Assert.assertTrue(ds1.started);
Assert.assertTrue(ds2.started);
Assert.assertTrue(ds1.checked);
Assert.assertTrue(ds2.checked);
Assert.assertTrue(ds1.committed);
Assert.assertTrue(ds2.committed);
Assert.assertFalse(ds1.postCommitted);
Assert.assertFalse(ds2.postCommitted);
Assert.assertTrue(ds1.rolledBack);
Assert.assertTrue(ds2.rolledBack);
Assert.assertEquals(txClient.state, DummyTxClient.CommitState.Aborted);
}
use of org.apache.tephra.TransactionFailureException in project cdap by caskdata.
the class TransactionContextTest method testStartAndRollbackFailure.
@Test
public void testStartAndRollbackFailure() throws TransactionFailureException, InterruptedException {
ds1.failStartTxOnce = InduceFailure.ThrowException;
TransactionContext context = newTransactionContext(ds1, ds2);
// start transaction
try {
context.start();
Assert.fail("start failed - exception should be thrown");
} catch (TransactionFailureException e) {
Assert.assertEquals("start failure", e.getCause().getMessage());
}
// verify both are not rolled back and tx is aborted
Assert.assertTrue(ds1.started);
Assert.assertFalse(ds2.started);
Assert.assertFalse(ds1.checked);
Assert.assertFalse(ds2.checked);
Assert.assertFalse(ds1.committed);
Assert.assertFalse(ds2.committed);
Assert.assertFalse(ds1.postCommitted);
Assert.assertFalse(ds2.postCommitted);
Assert.assertFalse(ds1.rolledBack);
Assert.assertFalse(ds2.rolledBack);
Assert.assertEquals(txClient.state, DummyTxClient.CommitState.Aborted);
}
use of org.apache.tephra.TransactionFailureException in project cdap by caskdata.
the class KeyValueTableTest method testTransactionAcrossTables.
@Test
public void testTransactionAcrossTables() throws Exception {
DatasetId t1 = DatasetFrameworkTestUtil.NAMESPACE_ID.dataset("t1");
DatasetId t2 = DatasetFrameworkTestUtil.NAMESPACE_ID.dataset("t2");
dsFrameworkUtil.createInstance("keyValueTable", t1, DatasetProperties.EMPTY);
dsFrameworkUtil.createInstance("keyValueTable", t2, DatasetProperties.EMPTY);
final KeyValueTable table1 = dsFrameworkUtil.getInstance(t1);
final KeyValueTable table2 = dsFrameworkUtil.getInstance(t2);
TransactionExecutor txnl = dsFrameworkUtil.newTransactionExecutor(table1, table2, kvTable);
// write a value to table1 and verify it
txnl.execute(new TransactionExecutor.Subroutine() {
@Override
public void apply() throws Exception {
table1.write(KEY1, VAL1);
Assert.assertArrayEquals(VAL1, table1.read(KEY1));
table2.write(KEY2, VAL2);
Assert.assertArrayEquals(VAL2, table2.read(KEY2));
}
});
// start a new transaction
try {
txnl.execute(new TransactionExecutor.Subroutine() {
@Override
public void apply() throws Exception {
// add a write for table 1 to the transaction
table1.write(KEY1, VAL2);
// submit a delete for table 2
table2.delete(KEY2);
throw new RuntimeException("Cancel transaction");
}
});
Assert.fail("Transaction should have been cancelled");
} catch (TransactionFailureException e) {
Assert.assertEquals("Cancel transaction", e.getCause().getMessage());
}
// test a swap for a third row that should fail
txnl.execute(new TransactionExecutor.Subroutine() {
@Override
public void apply() throws Exception {
Assert.assertFalse(kvTable.compareAndSwap(KEY3, VAL1, VAL1));
}
});
txnl.execute(new TransactionExecutor.Subroutine() {
@Override
public void apply() throws Exception {
Assert.assertArrayEquals(VAL1, table1.read(KEY1));
Assert.assertArrayEquals(VAL2, table2.read(KEY2));
}
});
// verify synchronously that old value are still there
final KeyValueTable table1v2 = dsFrameworkUtil.getInstance(t1);
final KeyValueTable table2v2 = dsFrameworkUtil.getInstance(t2);
TransactionExecutor txnlv2 = dsFrameworkUtil.newTransactionExecutor(table1v2, table2v2);
txnlv2.execute(new TransactionExecutor.Subroutine() {
@Override
public void apply() throws Exception {
Assert.assertArrayEquals(VAL1, table1v2.read(KEY1));
Assert.assertArrayEquals(VAL2, table2v2.read(KEY2));
}
});
dsFrameworkUtil.deleteInstance(t1);
dsFrameworkUtil.deleteInstance(t2);
}
use of org.apache.tephra.TransactionFailureException in project cdap by caskdata.
the class HBaseQueueDebugger method scanQueue.
private void scanQueue(TransactionExecutor txExecutor, HBaseConsumerStateStore stateStore, QueueName queueName, QueueBarrier start, @Nullable QueueBarrier end, final QueueStatistics outStats) throws Exception {
final byte[] queueRowPrefix = QueueEntryRow.getQueueRowPrefix(queueName);
ConsumerGroupConfig groupConfig = start.getGroupConfig();
printProgress("Got consumer group config: %s\n", groupConfig);
HBaseQueueAdmin admin = queueClientFactory.getQueueAdmin();
TableId tableId = admin.getDataTableId(queueName, QueueConstants.QueueType.SHARDED_QUEUE);
HTable hTable = queueClientFactory.createHTable(tableId);
printProgress("Looking at HBase table: %s\n", Bytes.toString(hTable.getTableName()));
final byte[] stateColumnName = Bytes.add(QueueEntryRow.STATE_COLUMN_PREFIX, Bytes.toBytes(groupConfig.getGroupId()));
int distributorBuckets = queueClientFactory.getDistributorBuckets(hTable.getTableDescriptor());
ShardedHBaseQueueStrategy queueStrategy = new ShardedHBaseQueueStrategy(tableUtil, distributorBuckets);
ScanBuilder scan = tableUtil.buildScan();
scan.setStartRow(start.getStartRow());
if (end != null) {
scan.setStopRow(end.getStartRow());
} else {
scan.setStopRow(QueueEntryRow.getQueueEntryRowKey(queueName, Long.MAX_VALUE, Integer.MAX_VALUE));
}
// Needs to include meta column for row that doesn't have state yet.
scan.addColumn(QueueEntryRow.COLUMN_FAMILY, QueueEntryRow.META_COLUMN);
scan.addColumn(QueueEntryRow.COLUMN_FAMILY, stateColumnName);
// Don't do block cache for debug tool. We don't want old blocks get cached
scan.setCacheBlocks(false);
scan.setMaxVersions(1);
printProgress("Scanning section with scan: %s\n", scan.toString());
List<Integer> instanceIds = Lists.newArrayList();
if (groupConfig.getDequeueStrategy() == DequeueStrategy.FIFO) {
instanceIds.add(0);
} else {
for (int instanceId = 0; instanceId < groupConfig.getGroupSize(); instanceId++) {
instanceIds.add(instanceId);
}
}
final int rowsCache = Integer.parseInt(System.getProperty(PROP_ROWS_CACHE, "100000"));
for (final int instanceId : instanceIds) {
printProgress("Processing instance %d", instanceId);
ConsumerConfig consConfig = new ConsumerConfig(groupConfig, instanceId);
final QueueScanner scanner = queueStrategy.createScanner(consConfig, hTable, scan.build(), rowsCache);
try {
txExecutor.execute(new TransactionExecutor.Procedure<HBaseConsumerStateStore>() {
@Override
public void apply(HBaseConsumerStateStore input) throws Exception {
ImmutablePair<byte[], Map<byte[], byte[]>> result;
while ((result = scanner.next()) != null) {
byte[] rowKey = result.getFirst();
Map<byte[], byte[]> columns = result.getSecond();
visitRow(outStats, input.getTransaction(), rowKey, columns.get(stateColumnName), queueRowPrefix.length);
if (showProgress() && outStats.getTotal() % rowsCache == 0) {
System.out.printf("\rProcessing instance %d: %s", instanceId, outStats.getReport(showTxTimestampOnly()));
}
}
}
}, stateStore);
} catch (TransactionFailureException e) {
// Ignore transaction not in progress exception as it's caused by short TX timeout on commit
if (!(Throwables.getRootCause(e) instanceof TransactionNotInProgressException)) {
throw Throwables.propagate(e);
}
}
printProgress("\rProcessing instance %d: %s\n", instanceId, outStats.getReport(showTxTimestampOnly()));
}
}
Aggregations