use of org.apache.tephra.TransactionAware in project cdap by caskdata.
the class TableConcurrentTest method testConcurrentCreate.
/**
* tests that creating a table concurrently from two different clients does not fail.
*/
// table create wait time is 5 sec
@Test(timeout = 20000)
public void testConcurrentCreate() throws Exception {
AtomicBoolean success1 = new AtomicBoolean(false);
AtomicBoolean success2 = new AtomicBoolean(false);
// start two threads both attempting to create the same table
Thread t1 = new CreateThread(success1);
Thread t2 = new CreateThread(success2);
t1.start();
t2.start();
t1.join();
t2.join();
// make sure both threads report success
Assert.assertTrue("First thread failed. ", success1.get());
Assert.assertTrue("Second thread failed. ", success2.get());
// perform a read - if the table was not opened successfully this will fail
final Table t = getTable(CONTEXT1, "conccreate");
Assert.assertNotNull(t);
TransactionExecutor txExecutor = txExecutorFactory.createExecutor(Lists.newArrayList((TransactionAware) t));
txExecutor.execute(new TransactionExecutor.Subroutine() {
@Override
public void apply() throws Exception {
t.get(new byte[] { 'a' }, new byte[][] { { 'b' } });
}
});
}
use of org.apache.tephra.TransactionAware in project cdap by caskdata.
the class TableConcurrentTest method before.
@Before
public void before() {
super.before();
txExecutorFactory = new TransactionExecutorFactory() {
@Override
public TransactionExecutor createExecutor(Iterable<TransactionAware> txAwares) {
return new DefaultTransactionExecutor(txClient, txAwares);
}
};
}
use of org.apache.tephra.TransactionAware in project cdap by caskdata.
the class TableTest method testBasicColumnRangeWithTx.
@Test
public void testBasicColumnRangeWithTx() throws Exception {
// todo: test more tx logic (or add to get/put unit-test)
DatasetAdmin admin = getTableAdmin(CONTEXT1, MY_TABLE);
admin.create();
try {
// write test data and commit
Transaction tx1 = txClient.startShort();
Table myTable1 = getTable(CONTEXT1, MY_TABLE);
((TransactionAware) myTable1).startTx(tx1);
myTable1.put(R1, a(C1, C2, C3, C4, C5), a(V1, V2, V3, V4, V5));
myTable1.put(R2, a(C1), a(V2));
txClient.canCommitOrThrow(tx1, ((TransactionAware) myTable1).getTxChanges());
Assert.assertTrue(((TransactionAware) myTable1).commitTx());
txClient.commitOrThrow(tx1);
// Now, we will test column range get
Transaction tx2 = txClient.startShort();
Table myTable2 = getTable(CONTEXT1, MY_TABLE);
((TransactionAware) myTable2).startTx(tx2);
// bounded range
TableAssert.assertRow(a(C2, V2, C3, V3, C4, V4), myTable2.get(R1, C2, C5, Integer.MAX_VALUE));
// open start range
TableAssert.assertRow(a(C1, V1, C2, V2, C3, V3), myTable2.get(R1, null, C4, Integer.MAX_VALUE));
// open end range
TableAssert.assertRow(a(C3, V3, C4, V4, C5, V5), myTable2.get(R1, C3, null, Integer.MAX_VALUE));
// open ends range
TableAssert.assertRow(a(C1, V1, C2, V2, C3, V3, C4, V4, C5, V5), myTable2.get(R1, null, null, Integer.MAX_VALUE));
// same with limit
// bounded range with limit
TableAssert.assertRow(a(C2, V2), myTable2.get(R1, C2, C5, 1));
// open start range with limit
TableAssert.assertRow(a(C1, V1, C2, V2), myTable2.get(R1, null, C4, 2));
// open end range with limit
TableAssert.assertRow(a(C3, V3, C4, V4), myTable2.get(R1, C3, null, 2));
// open ends range with limit
TableAssert.assertRow(a(C1, V1, C2, V2, C3, V3, C4, V4), myTable2.get(R1, null, null, 4));
// adding/changing/removing some columns
myTable2.put(R1, a(C1, C2, C3), a(V4, V3, V2));
myTable2.delete(R1, a(C4));
txClient.canCommitOrThrow(tx2, ((TransactionAware) myTable2).getTxChanges());
Assert.assertTrue(((TransactionAware) myTable2).commitTx());
txClient.commitOrThrow(tx2);
// Checking that changes are reflected in new scans in new tx
Transaction tx3 = txClient.startShort();
// NOTE: table can be re-used betweet tx
((TransactionAware) myTable1).startTx(tx3);
TableAssert.assertRow(a(C2, V3, C3, V2), myTable1.get(R1, C2, C5, Integer.MAX_VALUE));
txClient.canCommitOrThrow(tx3, ((TransactionAware) myTable1).getTxChanges());
Assert.assertTrue(((TransactionAware) myTable1).commitTx());
txClient.commitOrThrow(tx3);
} finally {
admin.drop();
}
}
use of org.apache.tephra.TransactionAware in project cdap by caskdata.
the class TableTest method testEmptyGet.
@Test
public void testEmptyGet() throws Exception {
DatasetAdmin admin = getTableAdmin(CONTEXT1, MY_TABLE);
admin.create();
try {
Transaction tx = txClient.startShort();
Table myTable = getTable(CONTEXT1, MY_TABLE);
((TransactionAware) myTable).startTx(tx);
myTable.put(R1, C1, V1);
myTable.put(R1, C2, V2);
// to be used for validation later
TreeMap<byte[], byte[]> expectedColumns = new TreeMap<>(Bytes.BYTES_COMPARATOR);
expectedColumns.put(C1, V1);
expectedColumns.put(C2, V2);
Result expectedResult = new Result(R1, expectedColumns);
Result emptyResult = new Result(R1, ImmutableMap.<byte[], byte[]>of());
((TransactionAware) myTable).commitTx();
txClient.commitOrThrow(tx);
// start another transaction, so that the buffering table doesn't cache the values; the underlying Table
// implementations are tested this way.
tx = txClient.startShort();
((TransactionAware) myTable).startTx(tx);
Row row = myTable.get(R1, new byte[][] { C1, C2 });
assertEquals(expectedResult, row);
// passing in empty columns returns empty result
row = myTable.get(R1, new byte[][] {});
assertEquals(emptyResult, row);
// test all the Get constructors and their behavior
// constructors specifying only rowkey retrieve all columns
Get get = new Get(R1);
Assert.assertNull(get.getColumns());
assertEquals(expectedResult, myTable.get(get));
get = new Get(Bytes.toString(R1));
Assert.assertNull(get.getColumns());
assertEquals(expectedResult, myTable.get(get));
get.add(C1);
get.add(Bytes.toString(C2));
assertEquals(expectedResult, myTable.get(get));
// constructor specifying columns, but with an empty array/collection retrieve 0 columns
get = new Get(R1, new byte[][] {});
Assert.assertNotNull(get.getColumns());
assertEquals(emptyResult, myTable.get(get));
get = new Get(R1, ImmutableList.<byte[]>of());
Assert.assertNotNull(get.getColumns());
assertEquals(emptyResult, myTable.get(get));
get = new Get(Bytes.toString(R1), new String[] {});
Assert.assertNotNull(get.getColumns());
assertEquals(emptyResult, myTable.get(get));
get = new Get(Bytes.toString(R1), ImmutableList.<String>of());
Assert.assertNotNull(get.getColumns());
assertEquals(emptyResult, myTable.get(get));
row = myTable.get(R1, new byte[][] {});
assertEquals(emptyResult, row);
txClient.abort(tx);
} finally {
admin.drop();
}
}
use of org.apache.tephra.TransactionAware in project cdap by caskdata.
the class TableTest method testBasicDeleteWithTx.
@Test
public void testBasicDeleteWithTx() throws Exception {
// we will test 3 different delete column ops and one delete row op
// * delete column with delete
// * delete column with put null value
// * delete column with put byte[0] value
// * delete row with delete
DatasetAdmin admin = getTableAdmin(CONTEXT1, MY_TABLE);
admin.create();
try {
// write smth and commit
Transaction tx1 = txClient.startShort();
Table myTable1 = getTable(CONTEXT1, MY_TABLE);
((TransactionAware) myTable1).startTx(tx1);
myTable1.put(R1, a(C1, C2), a(V1, V2));
myTable1.put(R2, a(C1, C2), a(V2, V3));
myTable1.put(R3, a(C1, C2), a(V3, V4));
myTable1.put(R4, a(C1, C2), a(V4, V5));
txClient.canCommitOrThrow(tx1, ((TransactionAware) myTable1).getTxChanges());
Assert.assertTrue(((TransactionAware) myTable1).commitTx());
txClient.commitOrThrow(tx1);
// Now, we will test delete ops
// start new tx2
Transaction tx2 = txClient.startShort();
Table myTable2 = getTable(CONTEXT1, MY_TABLE);
((TransactionAware) myTable2).startTx(tx2);
// TableAssert.verify tx2 sees changes of tx1
TableAssert.assertRow(a(C1, V1, C2, V2), myTable2.get(R1, a(C1, C2)));
// TableAssert.verify tx2 sees changes of tx1
TableAssert.assertRow(a(C1, V2, C2, V3), myTable2.get(R2));
// delete c1, r2
myTable2.delete(R1, a(C1));
myTable2.delete(R2);
// same as delete a column
myTable2.put(R3, C1, null);
// TableAssert.verify can see deletes in own changes before commit
TableAssert.assertRow(a(C2, V2), myTable2.get(R1, a(C1, C2)));
Assert.assertArrayEquals(null, myTable2.get(R1, C1));
Assert.assertArrayEquals(V2, myTable2.get(R1, C2));
TableAssert.assertRow(a(), myTable2.get(R2));
TableAssert.assertRow(a(C2, V4), myTable2.get(R3));
// overwrite c2 and write new value to c1
myTable2.put(R1, a(C1, C2), a(V3, V4));
myTable2.put(R2, a(C1, C2), a(V4, V5));
myTable2.put(R3, a(C1, C2), a(V1, V2));
myTable2.put(R4, a(C1, C2), a(V2, V3));
// TableAssert.verify can see changes in own changes before commit
TableAssert.assertRow(a(C1, V3, C2, V4), myTable2.get(R1, a(C1, C2, C3)));
Assert.assertArrayEquals(V3, myTable2.get(R1, C1));
Assert.assertArrayEquals(V4, myTable2.get(R1, C2));
Assert.assertArrayEquals(null, myTable2.get(R1, C3));
TableAssert.assertRow(a(C1, V4, C2, V5), myTable2.get(R2));
TableAssert.assertRow(a(C1, V1, C2, V2), myTable2.get(R3));
TableAssert.assertRow(a(C1, V2, C2, V3), myTable2.get(R4));
// delete c2 and r2
myTable2.delete(R1, a(C2));
myTable2.delete(R2);
myTable2.put(R1, C2, null);
// TableAssert.verify that delete is there (i.e. not reverted to whatever was persisted before)
TableAssert.assertRow(a(C1, V3), myTable2.get(R1, a(C1, C2)));
Assert.assertArrayEquals(V3, myTable2.get(R1, C1));
Assert.assertArrayEquals(null, myTable2.get(R1, C2));
TableAssert.assertRow(a(), myTable2.get(R2));
Assert.assertArrayEquals(V1, myTable2.get(R3, C1));
Assert.assertArrayEquals(V2, myTable2.get(R4, C1));
// start tx3 and TableAssert.verify that changes of tx2 are not visible yet
Transaction tx3 = txClient.startShort();
// NOTE: table instance can be re-used between tx
((TransactionAware) myTable1).startTx(tx3);
TableAssert.assertRow(a(C1, V1, C2, V2), myTable1.get(R1, a(C1, C2)));
Assert.assertArrayEquals(V1, myTable1.get(R1, C1));
Assert.assertArrayEquals(V2, myTable1.get(R1, C2));
Assert.assertArrayEquals(null, myTable1.get(R1, C3));
TableAssert.assertRow(a(C1, V1, C2, V2), myTable1.get(R1));
TableAssert.assertRow(a(C1, V2, C2, V3), myTable1.get(R2));
TableAssert.assertRow(a(C1, V3, C2, V4), myTable1.get(R3));
TableAssert.assertRow(a(C1, V4, C2, V5), myTable1.get(R4));
txClient.canCommitOrThrow(tx3, ((TransactionAware) myTable1).getTxChanges());
Assert.assertTrue(((TransactionAware) myTable1).commitTx());
txClient.commitOrThrow(tx3);
// starting tx4 before committing tx2 so that we can check conflicts are detected wrt deletes
Transaction tx4 = txClient.startShort();
// starting tx5 before committing tx2 so that we can check conflicts are detected wrt deletes
Transaction tx5 = txClient.startShort();
// commit tx2 in stages to see how races are handled wrt delete ops
txClient.canCommitOrThrow(tx2, ((TransactionAware) myTable2).getTxChanges());
Assert.assertTrue(((TransactionAware) myTable2).commitTx());
// start tx6 and TableAssert.verify that changes of tx2 are not visible yet (even though they are flushed)
Transaction tx6 = txClient.startShort();
// NOTE: table instance can be re-used between tx
((TransactionAware) myTable1).startTx(tx6);
TableAssert.assertRow(a(C1, V1, C2, V2), myTable1.get(R1, a(C1, C2)));
Assert.assertArrayEquals(V1, myTable1.get(R1, C1));
Assert.assertArrayEquals(V2, myTable1.get(R1, C2));
Assert.assertArrayEquals(null, myTable1.get(R1, C3));
TableAssert.assertRow(a(C1, V1, C2, V2), myTable1.get(R1));
TableAssert.assertRow(a(C1, V2, C2, V3), myTable1.get(R2));
TableAssert.assertRow(a(C1, V3, C2, V4), myTable1.get(R3));
TableAssert.assertRow(a(C1, V4, C2, V5), myTable1.get(R4));
txClient.canCommitOrThrow(tx6, ((TransactionAware) myTable1).getTxChanges());
Assert.assertTrue(((TransactionAware) myTable1).commitTx());
txClient.commitOrThrow(tx6);
// make tx2 visible
txClient.commitOrThrow(tx2);
// start tx7 and TableAssert.verify that changes of tx2 are now visible
Transaction tx7 = txClient.startShort();
// NOTE: table instance can be re-used between tx
((TransactionAware) myTable1).startTx(tx7);
TableAssert.assertRow(a(C1, V3), myTable1.get(R1, a(C1, C2)));
TableAssert.assertRow(a(C1, V3), myTable1.get(R1));
Assert.assertArrayEquals(V3, myTable1.get(R1, C1));
Assert.assertArrayEquals(null, myTable1.get(R1, C2));
TableAssert.assertRow(a(C1, V3), myTable1.get(R1, a(C1, C2)));
TableAssert.assertRow(a(), myTable1.get(R2));
Assert.assertArrayEquals(V1, myTable1.get(R3, C1));
Assert.assertArrayEquals(V2, myTable1.get(R4, C1));
txClient.canCommitOrThrow(tx6, ((TransactionAware) myTable1).getTxChanges());
Assert.assertTrue(((TransactionAware) myTable1).commitTx());
txClient.commitOrThrow(tx7);
// but not visible to tx4 that we started earlier than tx2 became visible
// NOTE: table instance can be re-used between tx
((TransactionAware) myTable1).startTx(tx4);
TableAssert.assertRow(a(C1, V1, C2, V2), myTable1.get(R1, a(C1, C2)));
Assert.assertArrayEquals(V1, myTable1.get(R1, C1));
Assert.assertArrayEquals(V2, myTable1.get(R1, C2));
Assert.assertArrayEquals(null, myTable1.get(R1, C3));
TableAssert.assertRow(a(C1, V1, C2, V2), myTable1.get(R1));
TableAssert.assertRow(a(C1, V2, C2, V3), myTable1.get(R2));
TableAssert.assertRow(a(C1, V3, C2, V4), myTable1.get(R3));
TableAssert.assertRow(a(C1, V4, C2, V5), myTable1.get(R4));
// writing to deleted column, to check conflicts are detected (delete-write conflict)
myTable1.put(R1, a(C2), a(V5));
try {
txClient.canCommitOrThrow(tx4, ((TransactionAware) myTable1).getTxChanges());
Assert.fail("Conflict not detected!");
} catch (TransactionConflictException e) {
// expected
}
((TransactionAware) myTable1).rollbackTx();
txClient.abort(tx4);
// deleting changed column, to check conflicts are detected (write-delete conflict)
// NOTE: table instance can be re-used between tx
((TransactionAware) myTable1).startTx(tx5);
TableAssert.assertRow(a(C1, V1, C2, V2), myTable1.get(R1, a(C1, C2)));
Assert.assertArrayEquals(V1, myTable1.get(R1, C1));
Assert.assertArrayEquals(V2, myTable1.get(R1, C2));
Assert.assertArrayEquals(null, myTable1.get(R1, C3));
TableAssert.assertRow(a(C1, V1, C2, V2), myTable1.get(R1));
TableAssert.assertRow(a(C1, V2, C2, V3), myTable1.get(R2));
TableAssert.assertRow(a(C1, V3, C2, V4), myTable1.get(R3));
TableAssert.assertRow(a(C1, V4, C2, V5), myTable1.get(R4));
// NOTE: we are TableAssert.verifying conflict in one operation only. We may want to test each...
myTable1.delete(R1, a(C1));
try {
txClient.canCommitOrThrow(tx5, ((TransactionAware) myTable1).getTxChanges());
Assert.fail("Conflict not detected!");
} catch (TransactionConflictException e) {
// expected
}
((TransactionAware) myTable1).rollbackTx();
txClient.abort(tx5);
} finally {
admin.drop();
}
}
Aggregations