use of org.apache.tephra.TransactionAware in project cdap by caskdata.
the class TableTest method testStringPutGet.
private void testStringPutGet(Table t, String key, String col, String val) throws Exception {
Transaction tx = txClient.startShort();
((TransactionAware) t).startTx(tx);
t.put(new Put(key, col, val));
Row row = t.get(new Get(key));
Assert.assertTrue(!row.isEmpty());
Assert.assertEquals(key, Bytes.toString(row.getRow()));
Assert.assertEquals(1, row.getColumns().size());
Assert.assertEquals(col, Bytes.toString(row.getColumns().entrySet().iterator().next().getKey()));
Assert.assertEquals(val, Bytes.toString(row.getColumns().entrySet().iterator().next().getValue()));
Assert.assertEquals(val, Bytes.toString(row.get(col)));
Assert.assertEquals(val, row.getString(col));
((TransactionAware) t).rollbackTx();
txClient.abort(tx);
}
use of org.apache.tephra.TransactionAware in project cdap by caskdata.
the class TableTest method testBasicIncrementWithTx.
private void testBasicIncrementWithTx(boolean doIncrAndGet, boolean readless) throws Exception {
DatasetProperties props = TableProperties.builder().setReadlessIncrementSupport(readless).build();
DatasetAdmin admin = getTableAdmin(CONTEXT1, MY_TABLE, props);
admin.create();
Table myTable1, myTable2, myTable3, myTable4;
try {
Transaction tx1 = txClient.startShort();
myTable1 = getTable(CONTEXT1, MY_TABLE, props);
((TransactionAware) myTable1).startTx(tx1);
myTable1.put(R1, a(C1), a(L4));
doIncrement(doIncrAndGet, myTable1, R1, a(C1), la(-3L), lb(1L));
doIncrement(doIncrAndGet, myTable1, R1, a(C2), la(2L), lb(2L));
// TableAssert.verify increment result visible inside tx before commit
TableAssert.assertRow(a(C1, L1, C2, L2), myTable1.get(R1, a(C1, C2)));
Assert.assertArrayEquals(L1, myTable1.get(R1, C1));
Assert.assertArrayEquals(L2, myTable1.get(R1, C2));
Assert.assertArrayEquals(null, myTable1.get(R1, C3));
TableAssert.assertRow(a(C1, L1), myTable1.get(R1, a(C1)));
TableAssert.assertRow(a(C1, L1, C2, L2), myTable1.get(R1));
// incrementing non-long value should fail
myTable1.put(R1, a(C5), a(V5));
try {
doIncrement(doIncrAndGet, myTable1, R1, a(C5), la(5L), lb(-1L));
Assert.fail("increment should have failed with NumberFormatException");
} catch (NumberFormatException e) {
// Expected
}
// previous increment should not do any change
TableAssert.assertRow(a(C5, V5), myTable1.get(R1, a(C5)));
Assert.assertArrayEquals(V5, myTable1.get(R1, C5));
// start new tx (doesn't see changes of the tx1)
Transaction tx2 = txClient.startShort();
// committing tx1 in stages to check races are handled well
// * first, flush operations of table
txClient.canCommitOrThrow(tx1, ((TransactionAware) myTable1).getTxChanges());
Assert.assertTrue(((TransactionAware) myTable1).commitTx());
// check that tx2 doesn't see changes (even though they were flushed) of tx1
// assuming current value is null
myTable2 = getTable(CONTEXT1, MY_TABLE, props);
((TransactionAware) myTable2).startTx(tx2);
TableAssert.assertRow(a(), myTable2.get(R1, a(C1, C2, C5)));
Assert.assertArrayEquals(null, myTable2.get(R1, C1));
Assert.assertArrayEquals(null, myTable2.get(R1, C2));
Assert.assertArrayEquals(null, myTable2.get(R1, C5));
TableAssert.assertRow(a(), myTable2.get(R1));
doIncrement(doIncrAndGet, myTable2, R1, a(C1), la(55L), lb(55L));
// start tx3 and TableAssert.verify same thing again
Transaction tx3 = txClient.startShort();
myTable3 = getTable(CONTEXT1, MY_TABLE, props);
((TransactionAware) myTable3).startTx(tx3);
TableAssert.assertRow(a(), myTable3.get(R1, a(C1, C2, C5)));
Assert.assertArrayEquals(null, myTable3.get(R1, C1));
Assert.assertArrayEquals(null, myTable3.get(R1, C2));
Assert.assertArrayEquals(null, myTable3.get(R1, C5));
TableAssert.assertRow(a(), myTable3.get(R1));
doIncrement(doIncrAndGet, myTable3, R1, a(C1), la(4L), lb(4L));
// * second, make tx visible
txClient.commitOrThrow(tx1);
// TableAssert.verify that tx2 cannot commit because of the conflicts...
try {
txClient.canCommitOrThrow(tx2, ((TransactionAware) myTable2).getTxChanges());
Assert.fail("Conflict not detected!");
} catch (TransactionConflictException e) {
// expected
}
((TransactionAware) myTable2).rollbackTx();
txClient.abort(tx2);
// start tx4 and TableAssert.verify that changes of tx1 are now visible
Transaction tx4 = txClient.startShort();
myTable4 = getTable(CONTEXT1, MY_TABLE, props);
((TransactionAware) myTable4).startTx(tx4);
TableAssert.assertRow(a(C1, L1, C2, L2, C5, V5), myTable4.get(R1, a(C1, C2, C3, C4, C5)));
TableAssert.assertRow(a(C2, L2), myTable4.get(R1, a(C2)));
Assert.assertArrayEquals(L1, myTable4.get(R1, C1));
Assert.assertArrayEquals(L2, myTable4.get(R1, C2));
Assert.assertArrayEquals(null, myTable4.get(R1, C3));
Assert.assertArrayEquals(V5, myTable4.get(R1, C5));
TableAssert.assertRow(a(C1, L1, C5, V5), myTable4.get(R1, a(C1, C5)));
TableAssert.assertRow(a(C1, L1, C2, L2, C5, V5), myTable4.get(R1));
// tx3 still cannot see tx1 changes, only its own
TableAssert.assertRow(a(C1, L4), myTable3.get(R1, a(C1, C2, C5)));
Assert.assertArrayEquals(L4, myTable3.get(R1, C1));
Assert.assertArrayEquals(null, myTable3.get(R1, C2));
Assert.assertArrayEquals(null, myTable3.get(R1, C5));
TableAssert.assertRow(a(C1, L4), myTable3.get(R1));
// and it cannot commit because its changes cause conflicts
try {
txClient.canCommitOrThrow(tx3, ((TransactionAware) myTable3).getTxChanges());
Assert.fail("Conflict not detected!");
} catch (TransactionConflictException e) {
// expected
}
((TransactionAware) myTable3).rollbackTx();
txClient.abort(tx3);
// TableAssert.verify we can do some ops with tx4 based on data written with tx1
doIncrement(doIncrAndGet, myTable4, R1, a(C1, C2, C3), la(2L, 1L, 5L), lb(3L, 3L, 5L));
myTable4.delete(R1, a(C2));
doIncrement(doIncrAndGet, myTable4, R1, a(C4), la(3L), lb(3L));
myTable4.delete(R1, a(C1));
// committing tx4
txClient.canCommitOrThrow(tx4, ((TransactionAware) myTable3).getTxChanges());
Assert.assertTrue(((TransactionAware) myTable4).commitTx());
txClient.commitOrThrow(tx4);
// TableAssert.verifying the result contents in next transaction
Transaction tx5 = txClient.startShort();
// NOTE: table instance can be re-used in series of transactions
((TransactionAware) myTable4).startTx(tx5);
TableAssert.assertRow(a(C3, L5, C4, L3, C5, V5), myTable4.get(R1, a(C1, C2, C3, C4, C5)));
Assert.assertArrayEquals(null, myTable4.get(R1, C1));
Assert.assertArrayEquals(null, myTable4.get(R1, C2));
Assert.assertArrayEquals(L5, myTable4.get(R1, C3));
Assert.assertArrayEquals(L3, myTable4.get(R1, C4));
Assert.assertArrayEquals(V5, myTable4.get(R1, C5));
TableAssert.assertRow(a(C3, L5, C4, L3, C5, V5), myTable4.get(R1));
txClient.canCommitOrThrow(tx5, ((TransactionAware) myTable3).getTxChanges());
Assert.assertTrue(((TransactionAware) myTable3).commitTx());
txClient.commitOrThrow(tx5);
} finally {
admin.drop();
}
}
use of org.apache.tephra.TransactionAware in project cdap by caskdata.
the class BufferingTableTest method testScanWithBuffering.
/**
* Tests that writes being buffered in memory by the client are still visible during scans.
*/
@Test
public void testScanWithBuffering() throws Exception {
String testScanWithBuffering = "testScanWithBuffering";
DatasetAdmin admin = getTableAdmin(CONTEXT1, testScanWithBuffering);
admin.create();
try {
//
Transaction tx1 = txClient.startShort();
Table table1 = getTable(CONTEXT1, testScanWithBuffering);
((TransactionAware) table1).startTx(tx1);
table1.put(Bytes.toBytes("1_01"), a(C1), a(V1));
table1.put(Bytes.toBytes("1_02"), a(C1), a(V1));
table1.put(Bytes.toBytes("1_03"), a(C1), a(V1));
// written values should not yet be persisted
TableAssert.assertScan(new byte[0][], new byte[0][][], ((BufferingTable) table1).scanPersisted(new Scan(Bytes.toBytes("1_"), Bytes.toBytes("2_"))));
// buffered values should be visible in a scan
TableAssert.assertScan(a(Bytes.toBytes("1_01"), Bytes.toBytes("1_02"), Bytes.toBytes("1_03")), aa(a(C1, V1), a(C1, V1), a(C1, V1)), table1.scan(Bytes.toBytes("1_"), Bytes.toBytes("2_")));
txClient.canCommitOrThrow(tx1, ((TransactionAware) table1).getTxChanges());
Assert.assertTrue(((TransactionAware) table1).commitTx());
txClient.commitOrThrow(tx1);
Transaction tx2 = txClient.startShort();
((TransactionAware) table1).startTx(tx2);
// written values should be visible after commit
TableAssert.assertScan(a(Bytes.toBytes("1_01"), Bytes.toBytes("1_02"), Bytes.toBytes("1_03")), aa(a(C1, V1), a(C1, V1), a(C1, V1)), table1.scan(Bytes.toBytes("1_"), Bytes.toBytes("2_")));
txClient.commitOrThrow(tx2);
Transaction tx3 = txClient.startShort();
((TransactionAware) table1).startTx(tx3);
// test merging of buffered writes on existing rows
table1.put(Bytes.toBytes("1_01"), a(C2), a(V2));
table1.put(Bytes.toBytes("1_02"), a(C1), a(V2));
table1.put(Bytes.toBytes("1_02a"), a(C1), a(V1));
table1.put(Bytes.toBytes("1_02b"), a(C1), a(V1));
table1.put(Bytes.toBytes("1_04"), a(C2), a(V2));
// persisted values should be the same
TableAssert.assertScan(a(Bytes.toBytes("1_01"), Bytes.toBytes("1_02"), Bytes.toBytes("1_03")), aa(a(C1, V1), a(C1, V1), a(C1, V1)), ((BufferingTable) table1).scanPersisted(new Scan(Bytes.toBytes("1_"), Bytes.toBytes("2_"))));
// all values should be visible in buffered scan
TableAssert.assertScan(a(Bytes.toBytes("1_01"), Bytes.toBytes("1_02"), Bytes.toBytes("1_02a"), Bytes.toBytes("1_02b"), Bytes.toBytes("1_03"), Bytes.toBytes("1_04")), aa(// 1_01
a(C1, V1, C2, V2), // 1_02
a(C1, V2), // 1_02a
a(C1, V1), // 1_02b
a(C1, V1), // 1_03
a(C1, V1), // 1_04
a(C2, V2)), table1.scan(Bytes.toBytes("1_"), Bytes.toBytes("2_")));
txClient.canCommitOrThrow(tx3, ((TransactionAware) table1).getTxChanges());
Assert.assertTrue(((TransactionAware) table1).commitTx());
txClient.commitOrThrow(tx3);
Transaction tx4 = txClient.startShort();
((TransactionAware) table1).startTx(tx4);
// all values should be visible after commit
TableAssert.assertScan(a(Bytes.toBytes("1_01"), Bytes.toBytes("1_02"), Bytes.toBytes("1_02a"), Bytes.toBytes("1_02b"), Bytes.toBytes("1_03"), Bytes.toBytes("1_04")), aa(// 1_01
a(C1, V1, C2, V2), // 1_02
a(C1, V2), // 1_02a
a(C1, V1), // 1_02b
a(C1, V1), // 1_03
a(C1, V1), // 1_04
a(C2, V2)), table1.scan(Bytes.toBytes("1_"), Bytes.toBytes("2_")));
txClient.commitOrThrow(tx4);
} finally {
admin.drop();
}
}
use of org.apache.tephra.TransactionAware in project cdap by caskdata.
the class BufferingTableTest method testRollingBackAfterExceptionDuringPersist.
@Test
public void testRollingBackAfterExceptionDuringPersist() throws Exception {
DatasetAdmin admin = getTableAdmin(CONTEXT1, MY_TABLE);
admin.create();
try {
Transaction tx1 = txClient.startShort();
BufferingTable myTable1 = new BufferingTableWithPersistingFailure(getTable(CONTEXT1, MY_TABLE));
myTable1.startTx(tx1);
// write some data but not commit
myTable1.put(R1, a(C1), a(V1));
myTable1.put(R2, a(C2), a(V2));
// verify can see changes inside tx
TableAssert.assertRow(a(C1, V1), myTable1.get(R1, a(C1)));
TableAssert.assertRow(a(C2, V2), myTable1.get(R2, a(C2)));
// persisting changes
try {
// should simulate exception
myTable1.commitTx();
Assert.assertFalse(true);
} catch (Throwable th) {
// Expected simulated exception
}
// let's pretend that after persisting changes we still got conflict when finalizing tx, so
// rolling back changes
Assert.assertTrue(myTable1.rollbackTx());
// making tx visible
txClient.abort(tx1);
// start new tx
Transaction tx2 = txClient.startShort();
Table myTable2 = getTable(CONTEXT1, MY_TABLE);
((TransactionAware) myTable2).startTx(tx2);
// verify don't see rolled back changes
TableAssert.assertRow(a(), myTable2.get(R1, a(C1)));
TableAssert.assertRow(a(), myTable2.get(R2, a(C2)));
} finally {
admin.drop();
}
}
use of org.apache.tephra.TransactionAware in project cdap by caskdata.
the class UsageRegistryTest method testUsageRegistry.
@Test
public void testUsageRegistry() {
// instantiate a usage registry
UsageRegistry registry = new DefaultUsageRegistry(new TransactionExecutorFactory() {
@Override
public TransactionExecutor createExecutor(Iterable<TransactionAware> iterable) {
return dsFrameworkUtil.newInMemoryTransactionExecutor(iterable);
}
}, new ForwardingDatasetFramework(dsFrameworkUtil.getFramework()) {
@Nullable
@Override
public <T extends Dataset> T getDataset(DatasetId datasetInstanceId, Map<String, String> arguments, @Nullable ClassLoader classLoader) throws DatasetManagementException, IOException {
T t = super.getDataset(datasetInstanceId, arguments, classLoader);
if (t instanceof UsageDataset) {
@SuppressWarnings("unchecked") T t1 = (T) new WrappedUsageDataset((UsageDataset) t);
return t1;
}
return t;
}
});
// register usage for a stream and a dataset for single and multiple "owners", including a non-program
registry.register(flow11, datasetInstance1);
registry.register(flow12, stream1);
registry.registerAll(ImmutableList.of(flow21, flow22), datasetInstance2);
registry.registerAll(ImmutableList.of(flow21, flow22), stream1);
int count = WrappedUsageDataset.registerCount;
// validate usage
Assert.assertEquals(ImmutableSet.of(datasetInstance1), registry.getDatasets(flow11));
Assert.assertEquals(ImmutableSet.of(stream1), registry.getStreams(flow12));
Assert.assertEquals(ImmutableSet.of(datasetInstance2), registry.getDatasets(flow21));
Assert.assertEquals(ImmutableSet.of(datasetInstance2), registry.getDatasets(flow22));
Assert.assertEquals(ImmutableSet.of(stream1), registry.getStreams(flow21));
Assert.assertEquals(ImmutableSet.of(stream1), registry.getStreams(flow22));
Assert.assertEquals(ImmutableSet.of(flow11), registry.getPrograms(datasetInstance1));
Assert.assertEquals(ImmutableSet.of(flow21, flow22), registry.getPrograms(datasetInstance2));
Assert.assertEquals(ImmutableSet.of(flow12, flow21, flow22), registry.getPrograms(stream1));
// register datasets again
registry.register(flow11, datasetInstance1);
registry.registerAll(ImmutableList.of(flow21, flow22), datasetInstance2);
// validate that this does re-register previous usages (DefaultUsageRegistry no longer avoids re-registration)
count += 3;
Assert.assertEquals(count, WrappedUsageDataset.registerCount);
// validate usage
Assert.assertEquals(ImmutableSet.of(datasetInstance1), registry.getDatasets(flow11));
Assert.assertEquals(ImmutableSet.of(stream1), registry.getStreams(flow12));
Assert.assertEquals(ImmutableSet.of(datasetInstance2), registry.getDatasets(flow21));
Assert.assertEquals(ImmutableSet.of(datasetInstance2), registry.getDatasets(flow22));
Assert.assertEquals(ImmutableSet.of(stream1), registry.getStreams(flow21));
Assert.assertEquals(ImmutableSet.of(stream1), registry.getStreams(flow22));
Assert.assertEquals(ImmutableSet.of(flow11), registry.getPrograms(datasetInstance1));
Assert.assertEquals(ImmutableSet.of(flow21, flow22), registry.getPrograms(datasetInstance2));
Assert.assertEquals(ImmutableSet.of(flow12, flow21, flow22), registry.getPrograms(stream1));
// unregister app
registry.unregister(flow11.getParent());
// validate usage for that app is gone
Assert.assertEquals(ImmutableSet.of(), registry.getDatasets(flow11));
Assert.assertEquals(ImmutableSet.of(), registry.getStreams(flow12));
Assert.assertEquals(ImmutableSet.of(datasetInstance2), registry.getDatasets(flow21));
Assert.assertEquals(ImmutableSet.of(datasetInstance2), registry.getDatasets(flow22));
Assert.assertEquals(ImmutableSet.of(stream1), registry.getStreams(flow21));
Assert.assertEquals(ImmutableSet.of(stream1), registry.getStreams(flow22));
Assert.assertEquals(ImmutableSet.of(), registry.getPrograms(datasetInstance1));
Assert.assertEquals(ImmutableSet.of(flow21, flow22), registry.getPrograms(datasetInstance2));
Assert.assertEquals(ImmutableSet.of(flow21, flow22), registry.getPrograms(stream1));
// register application 1 again
registry.register(flow11, datasetInstance1);
registry.register(flow12, stream1);
// validate it was re-registered
Assert.assertEquals(ImmutableSet.of(datasetInstance1), registry.getDatasets(flow11));
Assert.assertEquals(ImmutableSet.of(stream1), registry.getStreams(flow12));
Assert.assertEquals(ImmutableSet.of(datasetInstance2), registry.getDatasets(flow21));
Assert.assertEquals(ImmutableSet.of(datasetInstance2), registry.getDatasets(flow22));
Assert.assertEquals(ImmutableSet.of(stream1), registry.getStreams(flow21));
Assert.assertEquals(ImmutableSet.of(stream1), registry.getStreams(flow22));
Assert.assertEquals(ImmutableSet.of(flow11), registry.getPrograms(datasetInstance1));
Assert.assertEquals(ImmutableSet.of(flow21, flow22), registry.getPrograms(datasetInstance2));
Assert.assertEquals(ImmutableSet.of(flow12, flow21, flow22), registry.getPrograms(stream1));
// validate that this actually re-registered previous usages (through code in wrapped usage dataset)
Assert.assertEquals(count + 2, WrappedUsageDataset.registerCount);
}
Aggregations