Search in sources :

Example 11 with DatasetAdmin

use of co.cask.cdap.api.dataset.DatasetAdmin in project cdap by caskdata.

the class TableTest method testMultiIncrementWithFlush.

private void testMultiIncrementWithFlush(boolean readless) throws Exception {
    final String tableName = "incrFlush";
    DatasetProperties props = TableProperties.builder().setReadlessIncrementSupport(readless).build();
    DatasetAdmin admin = getTableAdmin(CONTEXT1, tableName, props);
    admin.create();
    Map<String, String> args = new HashMap<>();
    if (readless) {
        args.put(HBaseTable.SAFE_INCREMENTS, "true");
    }
    Table table = getTable(CONTEXT1, tableName, props, args);
    Transaction tx = txClient.startShort();
    try {
        ((TransactionAware) table).startTx(tx);
        // Write an increment, then flush it by calling commitTx.
        table.increment(new Increment(R1, C1, 10L));
        ((TransactionAware) table).commitTx();
    } finally {
        // invalidate the tx, leaving an excluded write in the table
        txClient.invalidate(tx.getTransactionId());
    }
    // validate the first write is not visible
    tx = txClient.startShort();
    try {
        ((TransactionAware) table).startTx(tx);
        Assert.assertEquals(null, table.get(new Get(R1, C1)).getLong(C1));
    } finally {
        txClient.commit(tx);
    }
    tx = txClient.startShort();
    try {
        ((TransactionAware) table).startTx(tx);
        // Write an increment, then flush it by calling commitTx.
        table.increment(new Increment(R1, C1, 1L));
        ((TransactionAware) table).commitTx();
        // Write another increment, from both table instances
        table.increment(new Increment(R1, C1, 1L));
        if (readless) {
            Table table2 = getTable(CONTEXT1, tableName, props, args);
            ((TransactionAware) table2).startTx(tx);
            table2.increment(new Increment(R1, C1, 1L));
            ((TransactionAware) table2).commitTx();
        }
        ((TransactionAware) table).commitTx();
    } finally {
        txClient.commit(tx);
    }
    // validate all increments are visible to a new tx
    tx = txClient.startShort();
    try {
        ((TransactionAware) table).startTx(tx);
        Assert.assertEquals(new Long(readless ? 3L : 2L), table.get(new Get(R1, C1)).getLong(C1));
    } finally {
        txClient.commit(tx);
    }
    // drop table
    admin.drop();
}
Also used : Table(co.cask.cdap.api.dataset.table.Table) HBaseTable(co.cask.cdap.data2.dataset2.lib.table.hbase.HBaseTable) Transaction(org.apache.tephra.Transaction) HashMap(java.util.HashMap) TransactionAware(org.apache.tephra.TransactionAware) DatasetProperties(co.cask.cdap.api.dataset.DatasetProperties) Increment(co.cask.cdap.api.dataset.table.Increment) Get(co.cask.cdap.api.dataset.table.Get) DatasetAdmin(co.cask.cdap.api.dataset.DatasetAdmin)

Example 12 with DatasetAdmin

use of co.cask.cdap.api.dataset.DatasetAdmin in project cdap by caskdata.

the class TableTest method testCreate.

@Test
public void testCreate() throws Exception {
    DatasetAdmin admin = getTableAdmin(CONTEXT1, MY_TABLE);
    Assert.assertFalse(admin.exists());
    admin.create();
    Assert.assertTrue(admin.exists());
    // creation of non-existing table should do nothing
    admin.create();
    admin.drop();
}
Also used : DatasetAdmin(co.cask.cdap.api.dataset.DatasetAdmin) Test(org.junit.Test)

Example 13 with DatasetAdmin

use of co.cask.cdap.api.dataset.DatasetAdmin 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));
        Assert.assertTrue(txClient.canCommit(tx1, ((TransactionAware) myTable1).getTxChanges()));
        Assert.assertTrue(((TransactionAware) myTable1).commitTx());
        Assert.assertTrue(txClient.commit(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));
        Assert.assertTrue(txClient.canCommit(tx3, ((TransactionAware) myTable1).getTxChanges()));
        Assert.assertTrue(((TransactionAware) myTable1).commitTx());
        Assert.assertTrue(txClient.commit(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
        Assert.assertTrue(txClient.canCommit(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));
        Assert.assertTrue(txClient.canCommit(tx6, ((TransactionAware) myTable1).getTxChanges()));
        Assert.assertTrue(((TransactionAware) myTable1).commitTx());
        Assert.assertTrue(txClient.commit(tx6));
        // make tx2 visible
        Assert.assertTrue(txClient.commit(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));
        Assert.assertTrue(txClient.canCommit(tx6, ((TransactionAware) myTable1).getTxChanges()));
        Assert.assertTrue(((TransactionAware) myTable1).commitTx());
        Assert.assertTrue(txClient.commit(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));
        Assert.assertFalse(txClient.canCommit(tx4, ((TransactionAware) myTable1).getTxChanges()));
        ((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));
        Assert.assertFalse(txClient.canCommit(tx5, ((TransactionAware) myTable1).getTxChanges()));
        ((TransactionAware) myTable1).rollbackTx();
        txClient.abort(tx5);
    } finally {
        admin.drop();
    }
}
Also used : Table(co.cask.cdap.api.dataset.table.Table) HBaseTable(co.cask.cdap.data2.dataset2.lib.table.hbase.HBaseTable) Transaction(org.apache.tephra.Transaction) TransactionAware(org.apache.tephra.TransactionAware) DatasetAdmin(co.cask.cdap.api.dataset.DatasetAdmin) Test(org.junit.Test)

Example 14 with DatasetAdmin

use of co.cask.cdap.api.dataset.DatasetAdmin 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
        Assert.assertTrue(txClient.canCommit(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
        Assert.assertTrue(txClient.commit(tx1));
        // TableAssert.verify that tx2 cannot commit because of the conflicts...
        Assert.assertFalse(txClient.canCommit(tx2, ((TransactionAware) myTable2).getTxChanges()));
        ((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
        Assert.assertFalse(txClient.canCommit(tx3, ((TransactionAware) myTable3).getTxChanges()));
        ((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
        Assert.assertTrue(txClient.canCommit(tx4, ((TransactionAware) myTable3).getTxChanges()));
        Assert.assertTrue(((TransactionAware) myTable4).commitTx());
        Assert.assertTrue(txClient.commit(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));
        Assert.assertTrue(txClient.canCommit(tx5, ((TransactionAware) myTable3).getTxChanges()));
        Assert.assertTrue(((TransactionAware) myTable3).commitTx());
        Assert.assertTrue(txClient.commit(tx5));
    } finally {
        admin.drop();
    }
}
Also used : Table(co.cask.cdap.api.dataset.table.Table) HBaseTable(co.cask.cdap.data2.dataset2.lib.table.hbase.HBaseTable) Transaction(org.apache.tephra.Transaction) TransactionAware(org.apache.tephra.TransactionAware) DatasetProperties(co.cask.cdap.api.dataset.DatasetProperties) DatasetAdmin(co.cask.cdap.api.dataset.DatasetAdmin)

Example 15 with DatasetAdmin

use of co.cask.cdap.api.dataset.DatasetAdmin in project cdap by caskdata.

the class TableTest method testBasicGetPutWithTx.

@Test
public void testBasicGetPutWithTx() throws Exception {
    DatasetAdmin admin = getTableAdmin(CONTEXT1, MY_TABLE);
    admin.create();
    try {
        Transaction tx1 = txClient.startShort();
        Table myTable1 = getTable(CONTEXT1, MY_TABLE);
        ((TransactionAware) myTable1).startTx(tx1);
        // write r1->c1,v1 but not commit
        myTable1.put(R1, a(C1), a(V1));
        // TableAssert.verify can see changes inside tx
        TableAssert.assertRow(a(C1, V1), myTable1.get(R1, a(C1, C2)).getColumns());
        Assert.assertArrayEquals(V1, myTable1.get(R1, C1));
        Assert.assertArrayEquals(null, myTable1.get(R1, C2));
        Assert.assertArrayEquals(null, myTable1.get(R2, C1));
        TableAssert.assertRow(a(C1, V1), myTable1.get(R1).getColumns());
        // start new tx (doesn't see changes of the tx1)
        Transaction tx2 = txClient.startShort();
        Table myTable2 = getTable(CONTEXT1, MY_TABLE);
        ((TransactionAware) myTable2).startTx(tx2);
        // TableAssert.verify doesn't see changes of tx1
        TableAssert.assertRow(a(), myTable2.get(R1, a(C1, C2)));
        Assert.assertArrayEquals(null, myTable2.get(R1, C1));
        Assert.assertArrayEquals(null, myTable2.get(R1, C2));
        TableAssert.assertRow(a(), myTable2.get(R1));
        // write r2->c2,v2 in tx2
        myTable2.put(R2, a(C2), a(V2));
        // TableAssert.verify can see own changes
        TableAssert.assertRow(a(C2, V2), myTable2.get(R2, a(C1, C2)));
        Assert.assertArrayEquals(null, myTable2.get(R2, C1));
        Assert.assertArrayEquals(V2, myTable2.get(R2, C2));
        TableAssert.assertRow(a(C2, V2), myTable2.get(R2));
        // TableAssert.verify tx1 cannot see changes of tx2
        TableAssert.assertRow(a(), myTable1.get(R2, a(C1, C2)));
        Assert.assertArrayEquals(null, myTable1.get(R2, C1));
        Assert.assertArrayEquals(null, myTable1.get(R2, C2));
        TableAssert.assertRow(a(), myTable1.get(R2));
        // committing tx1 in stages to check races are handled well
        // * first, flush operations of table
        Assert.assertTrue(txClient.canCommit(tx1, ((TransactionAware) myTable1).getTxChanges()));
        Assert.assertTrue(((TransactionAware) myTable1).commitTx());
        // start tx3 and TableAssert.verify that changes of tx1 are not visible yet (even though they are flushed)
        Transaction tx3 = txClient.startShort();
        Table myTable3 = getTable(CONTEXT1, MY_TABLE);
        ((TransactionAware) myTable3).startTx(tx3);
        TableAssert.assertRow(a(), myTable3.get(R1, a(C1, C2)));
        Assert.assertArrayEquals(null, myTable3.get(R1, C1));
        Assert.assertArrayEquals(null, myTable3.get(R1, C2));
        TableAssert.assertRow(a(), myTable3.get(R1));
        Assert.assertTrue(txClient.canCommit(tx3, ((TransactionAware) myTable3).getTxChanges()));
        Assert.assertTrue(((TransactionAware) myTable3).commitTx());
        Assert.assertTrue(txClient.commit(tx3));
        // * second, make tx visible
        Assert.assertTrue(txClient.commit(tx1));
        // start tx4 and TableAssert.verify that changes of tx1 are now visible
        // NOTE: table instance can be re-used in series of transactions
        Transaction tx4 = txClient.startShort();
        ((TransactionAware) myTable3).startTx(tx4);
        TableAssert.assertRow(a(C1, V1), myTable3.get(R1, a(C1, C2)));
        Assert.assertArrayEquals(V1, myTable3.get(R1, C1));
        Assert.assertArrayEquals(null, myTable3.get(R1, C2));
        TableAssert.assertRow(a(C1, V1), myTable3.get(R1));
        // but tx2 still doesn't see committed changes of tx2
        TableAssert.assertRow(a(), myTable2.get(R1, a(C1, C2)));
        Assert.assertArrayEquals(null, myTable2.get(R1, C1));
        Assert.assertArrayEquals(null, myTable2.get(R1, C2));
        TableAssert.assertRow(a(), myTable2.get(R1));
        // and tx4 doesn't see changes of tx2
        TableAssert.assertRow(a(), myTable3.get(R2, a(C1, C2)));
        Assert.assertArrayEquals(null, myTable3.get(R2, C1));
        Assert.assertArrayEquals(null, myTable3.get(R2, C2));
        TableAssert.assertRow(a(), myTable3.get(R2));
        // committing tx4
        Assert.assertTrue(txClient.canCommit(tx4, ((TransactionAware) myTable3).getTxChanges()));
        Assert.assertTrue(((TransactionAware) myTable3).commitTx());
        Assert.assertTrue(txClient.commit(tx4));
        // do change in tx2 that is conflicting with tx1
        myTable2.put(R1, a(C1), a(V2));
        // change is OK and visible inside tx2
        TableAssert.assertRow(a(C1, V2), myTable2.get(R1, a(C1, C2)));
        Assert.assertArrayEquals(V2, myTable2.get(R1, C1));
        Assert.assertArrayEquals(null, myTable2.get(R1, C2));
        TableAssert.assertRow(a(C1, V2), myTable2.get(R1));
        // cannot commit: conflict should be detected
        Assert.assertFalse(txClient.canCommit(tx2, ((TransactionAware) myTable2).getTxChanges()));
        // rolling back tx2 changes and aborting tx
        ((TransactionAware) myTable2).rollbackTx();
        txClient.abort(tx2);
        // TableAssert.verifying that none of the changes of tx2 made it to be visible to other txs
        // NOTE: table instance can be re-used in series of transactions
        Transaction tx5 = txClient.startShort();
        ((TransactionAware) myTable3).startTx(tx5);
        TableAssert.assertRow(a(C1, V1), myTable3.get(R1, a(C1, C2)));
        Assert.assertArrayEquals(V1, myTable3.get(R1, C1));
        Assert.assertArrayEquals(null, myTable3.get(R1, C2));
        TableAssert.assertRow(a(C1, V1), myTable3.get(R1));
        TableAssert.assertRow(a(), myTable3.get(R2, a(C1, C2)));
        Assert.assertArrayEquals(null, myTable3.get(R2, C1));
        Assert.assertArrayEquals(null, myTable3.get(R2, C2));
        TableAssert.assertRow(a(), myTable3.get(R2));
        Assert.assertTrue(txClient.canCommit(tx5, ((TransactionAware) myTable3).getTxChanges()));
        Assert.assertTrue(((TransactionAware) myTable3).commitTx());
        Assert.assertTrue(txClient.commit(tx5));
    } finally {
        admin.drop();
    }
}
Also used : Table(co.cask.cdap.api.dataset.table.Table) HBaseTable(co.cask.cdap.data2.dataset2.lib.table.hbase.HBaseTable) Transaction(org.apache.tephra.Transaction) TransactionAware(org.apache.tephra.TransactionAware) DatasetAdmin(co.cask.cdap.api.dataset.DatasetAdmin) Test(org.junit.Test)

Aggregations

DatasetAdmin (co.cask.cdap.api.dataset.DatasetAdmin)50 Test (org.junit.Test)27 Table (co.cask.cdap.api.dataset.table.Table)25 Transaction (org.apache.tephra.Transaction)25 TransactionAware (org.apache.tephra.TransactionAware)22 HBaseTable (co.cask.cdap.data2.dataset2.lib.table.hbase.HBaseTable)20 DatasetProperties (co.cask.cdap.api.dataset.DatasetProperties)8 DatasetSpecification (co.cask.cdap.api.dataset.DatasetSpecification)8 Get (co.cask.cdap.api.dataset.table.Get)8 IOException (java.io.IOException)8 DatasetManagementException (co.cask.cdap.api.dataset.DatasetManagementException)6 Put (co.cask.cdap.api.dataset.table.Put)6 Row (co.cask.cdap.api.dataset.table.Row)6 DatasetType (co.cask.cdap.data2.datafabric.dataset.DatasetType)5 IncompatibleUpdateException (co.cask.cdap.api.dataset.IncompatibleUpdateException)4 Updatable (co.cask.cdap.api.dataset.Updatable)4 Scan (co.cask.cdap.api.dataset.table.Scan)4 DatasetDefinition (co.cask.cdap.api.dataset.DatasetDefinition)3 InstanceConflictException (co.cask.cdap.api.dataset.InstanceConflictException)3 ConstantClassLoaderProvider (co.cask.cdap.data2.datafabric.dataset.type.ConstantClassLoaderProvider)3