Search in sources :

Example 16 with TransactionExecutor

use of org.apache.tephra.TransactionExecutor in project cdap by caskdata.

the class ReflectionTableTest method testStructuredRecordProjection.

@Test
public void testStructuredRecordProjection() throws Exception {
    dsFrameworkUtil.createInstance("table", users, DatasetProperties.builder().build());
    try {
        final Table usersTable = dsFrameworkUtil.getInstance(users);
        final byte[] rowKey = Bytes.toBytes(123);
        final User2 projected = new User2("Samuel L.", 123L, ((Float) 50000000.02f).doubleValue(), Double.MAX_VALUE, ByteBuffer.wrap(new byte[] { 0, 1, 2 }));
        final Schema fullSchema = new ReflectionSchemaGenerator().generate(User.class);
        final Schema projSchema = new ReflectionSchemaGenerator().generate(User2.class);
        // TableDataset is not accessible here, but we know that's the underlying implementation...
        TransactionExecutor tx = dsFrameworkUtil.newTransactionExecutor((TransactionAware) usersTable);
        tx.execute(new TransactionExecutor.Subroutine() {

            @Override
            public void apply() throws Exception {
                Put put = new Put(rowKey);
                ReflectionPutWriter<User> putWriter = new ReflectionPutWriter<>(fullSchema);
                putWriter.write(SAMUEL, put);
                usersTable.put(put);
                Row row = usersTable.get(rowKey);
                ReflectionRowRecordReader rowReader = new ReflectionRowRecordReader(projSchema, null);
                StructuredRecord actual = rowReader.read(row, fullSchema);
                assertRecordEqualsUser(projected, actual);
            }
        });
    } finally {
        dsFrameworkUtil.deleteInstance(users);
    }
}
Also used : Table(co.cask.cdap.api.dataset.table.Table) Schema(co.cask.cdap.api.data.schema.Schema) TransactionExecutor(org.apache.tephra.TransactionExecutor) ReflectionSchemaGenerator(co.cask.cdap.internal.io.ReflectionSchemaGenerator) Put(co.cask.cdap.api.dataset.table.Put) StructuredRecord(co.cask.cdap.api.data.format.StructuredRecord) ReflectionPutWriter(co.cask.cdap.internal.io.ReflectionPutWriter) Row(co.cask.cdap.api.dataset.table.Row) ReflectionRowRecordReader(co.cask.cdap.internal.io.ReflectionRowRecordReader) Test(org.junit.Test)

Example 17 with TransactionExecutor

use of org.apache.tephra.TransactionExecutor in project cdap by caskdata.

the class IndexedTableTest method testMultipleIndexedColumns.

@Test
public void testMultipleIndexedColumns() throws Exception {
    DatasetId multiColumnTabInstance = DatasetFrameworkTestUtil.NAMESPACE_ID.dataset("multicolumntab");
    dsFrameworkUtil.createInstance("indexedTable", multiColumnTabInstance, DatasetProperties.builder().add(IndexedTable.INDEX_COLUMNS_CONF_KEY, "idx1,idx2,idx3").build());
    final byte[] idxCol1 = Bytes.toBytes("idx1");
    final byte[] idxCol2 = Bytes.toBytes("idx2");
    final byte[] idxCol3 = Bytes.toBytes("idx3");
    final IndexedTable mcTable = dsFrameworkUtil.getInstance(multiColumnTabInstance);
    try {
        TransactionExecutor tx = dsFrameworkUtil.newTransactionExecutor(mcTable);
        tx.execute(new TransactionExecutor.Subroutine() {

            @Override
            public void apply() throws Exception {
                // every row has idx3 = index mod 3
                for (int i = 1; i < 10; i++) {
                    Put put = new Put(Bytes.toBytes("row" + i));
                    put.add(idxCol1, idx1);
                    if (i % 2 == 0) {
                        put.add(idxCol2, idx2);
                    }
                    put.add(idxCol3, Bytes.toBytes(i % 3));
                    put.add(valCol, valA);
                    mcTable.put(put);
                }
            }
        });
        final byte[][] allColumns = new byte[][] { idxCol1, idxCol2, idxCol3, valCol };
        final byte[][] oddColumns = new byte[][] { idxCol1, idxCol3, valCol };
        final byte[] zero = Bytes.toBytes(0);
        final byte[] one = Bytes.toBytes(1);
        final byte[] two = Bytes.toBytes(2);
        // read by index 1
        tx.execute(new TransactionExecutor.Subroutine() {

            @Override
            public void apply() throws Exception {
                Scanner scanner = mcTable.readByIndex(idxCol1, idx1);
                try {
                    // should have all rows, all data
                    Row row = scanner.next();
                    TableAssert.assertRow(row, Bytes.toBytes("row1"), oddColumns, new byte[][] { idx1, one, valA });
                    row = scanner.next();
                    TableAssert.assertRow(row, Bytes.toBytes("row2"), allColumns, new byte[][] { idx1, idx2, two, valA });
                    row = scanner.next();
                    TableAssert.assertRow(row, Bytes.toBytes("row3"), oddColumns, new byte[][] { idx1, zero, valA });
                    row = scanner.next();
                    TableAssert.assertRow(row, Bytes.toBytes("row4"), allColumns, new byte[][] { idx1, idx2, one, valA });
                    row = scanner.next();
                    TableAssert.assertRow(row, Bytes.toBytes("row5"), oddColumns, new byte[][] { idx1, two, valA });
                    row = scanner.next();
                    TableAssert.assertRow(row, Bytes.toBytes("row6"), allColumns, new byte[][] { idx1, idx2, zero, valA });
                    row = scanner.next();
                    TableAssert.assertRow(row, Bytes.toBytes("row7"), oddColumns, new byte[][] { idx1, one, valA });
                    row = scanner.next();
                    TableAssert.assertRow(row, Bytes.toBytes("row8"), allColumns, new byte[][] { idx1, idx2, two, valA });
                    row = scanner.next();
                    TableAssert.assertRow(row, Bytes.toBytes("row9"), oddColumns, new byte[][] { idx1, zero, valA });
                    // should be end of rows
                    assertEmpty(scanner);
                } finally {
                    scanner.close();
                }
            }
        });
        // read by index 2
        tx.execute(new TransactionExecutor.Subroutine() {

            @Override
            public void apply() throws Exception {
                Scanner scanner = mcTable.readByIndex(idxCol2, idx2);
                try {
                    // Should have only even rows
                    Row row = scanner.next();
                    TableAssert.assertRow(row, Bytes.toBytes("row2"), allColumns, new byte[][] { idx1, idx2, two, valA });
                    row = scanner.next();
                    TableAssert.assertRow(row, Bytes.toBytes("row4"), allColumns, new byte[][] { idx1, idx2, one, valA });
                    row = scanner.next();
                    TableAssert.assertRow(row, Bytes.toBytes("row6"), allColumns, new byte[][] { idx1, idx2, zero, valA });
                    row = scanner.next();
                    TableAssert.assertRow(row, Bytes.toBytes("row8"), allColumns, new byte[][] { idx1, idx2, two, valA });
                    // should be at the end
                    assertEmpty(scanner);
                } finally {
                    scanner.close();
                }
            }
        });
        // read by index 3
        tx.execute(new TransactionExecutor.Subroutine() {

            @Override
            public void apply() throws Exception {
                // 0 should have rows 3, 6, 9
                Scanner scanner = mcTable.readByIndex(idxCol3, zero);
                try {
                    Row row = scanner.next();
                    TableAssert.assertRow(row, Bytes.toBytes("row3"), oddColumns, new byte[][] { idx1, zero, valA });
                    row = scanner.next();
                    TableAssert.assertRow(row, Bytes.toBytes("row6"), allColumns, new byte[][] { idx1, idx2, zero, valA });
                    row = scanner.next();
                    TableAssert.assertRow(row, Bytes.toBytes("row9"), oddColumns, new byte[][] { idx1, zero, valA });
                    // should be end of rows
                    assertEmpty(scanner);
                } finally {
                    scanner.close();
                }
                // 1 should have rows 1, 4, 7
                scanner = mcTable.readByIndex(idxCol3, one);
                try {
                    Row row = scanner.next();
                    TableAssert.assertRow(row, Bytes.toBytes("row1"), oddColumns, new byte[][] { idx1, one, valA });
                    row = scanner.next();
                    TableAssert.assertRow(row, Bytes.toBytes("row4"), allColumns, new byte[][] { idx1, idx2, one, valA });
                    row = scanner.next();
                    TableAssert.assertRow(row, Bytes.toBytes("row7"), oddColumns, new byte[][] { idx1, one, valA });
                    // should be end of rows
                    assertEmpty(scanner);
                } finally {
                    scanner.close();
                }
                // 2 should have rows 2, 5, 8
                scanner = mcTable.readByIndex(idxCol3, two);
                try {
                    Row row = scanner.next();
                    TableAssert.assertRow(row, Bytes.toBytes("row2"), allColumns, new byte[][] { idx1, idx2, two, valA });
                    row = scanner.next();
                    TableAssert.assertRow(row, Bytes.toBytes("row5"), oddColumns, new byte[][] { idx1, two, valA });
                    row = scanner.next();
                    TableAssert.assertRow(row, Bytes.toBytes("row8"), allColumns, new byte[][] { idx1, idx2, two, valA });
                    // should be end of rows
                    assertEmpty(scanner);
                } finally {
                    scanner.close();
                }
            }
        });
        // update idx2 value for rows 2 & 4
        final byte[] idx2b = new byte[] { '2', 'b' };
        tx.execute(new TransactionExecutor.Subroutine() {

            @Override
            public void apply() throws Exception {
                mcTable.put(Bytes.toBytes("row2"), idxCol2, idx2b);
                mcTable.put(Bytes.toBytes("row4"), idxCol2, idx2b);
            }
        });
        // only rows 6 & 8 should be returned for idx2 now
        tx.execute(new TransactionExecutor.Subroutine() {

            @Override
            public void apply() throws Exception {
                Scanner scanner = mcTable.readByIndex(idxCol2, idx2);
                try {
                    Row row = scanner.next();
                    TableAssert.assertRow(row, Bytes.toBytes("row6"), allColumns, new byte[][] { idx1, idx2, zero, valA });
                    row = scanner.next();
                    TableAssert.assertRow(row, Bytes.toBytes("row8"), allColumns, new byte[][] { idx1, idx2, two, valA });
                    assertEmpty(scanner);
                } finally {
                    scanner.close();
                }
                scanner = mcTable.readByIndex(idxCol2, idx2b);
                try {
                    Row row = scanner.next();
                    TableAssert.assertRow(row, Bytes.toBytes("row2"), allColumns, new byte[][] { idx1, idx2b, two, valA });
                    row = scanner.next();
                    TableAssert.assertRow(row, Bytes.toBytes("row4"), allColumns, new byte[][] { idx1, idx2b, one, valA });
                    assertEmpty(scanner);
                } finally {
                    scanner.close();
                }
            }
        });
    // rows 2 & 4 should be returned for idx2b
    } finally {
        dsFrameworkUtil.deleteInstance(multiColumnTabInstance);
    }
}
Also used : Scanner(co.cask.cdap.api.dataset.table.Scanner) TransactionExecutor(org.apache.tephra.TransactionExecutor) Row(co.cask.cdap.api.dataset.table.Row) Put(co.cask.cdap.api.dataset.table.Put) DatasetId(co.cask.cdap.proto.id.DatasetId) Test(org.junit.Test)

Example 18 with TransactionExecutor

use of org.apache.tephra.TransactionExecutor in project cdap by caskdata.

the class KeyValueTableTest method testBatchReads.

@Test
public void testBatchReads() throws Exception {
    DatasetId tBatch = DatasetFrameworkTestUtil.NAMESPACE_ID.dataset("tBatch");
    dsFrameworkUtil.createInstance("keyValueTable", tBatch, DatasetProperties.EMPTY);
    final KeyValueTable t = dsFrameworkUtil.getInstance(tBatch);
    TransactionExecutor txnl = dsFrameworkUtil.newTransactionExecutor(t);
    final SortedSet<Long> keysWritten = Sets.newTreeSet();
    // start a transaction
    txnl.execute(new TransactionExecutor.Subroutine() {

        @Override
        public void apply() throws Exception {
            // write 1000 random values to the table and remember them in a set
            Random rand = new Random(451);
            for (int i = 0; i < 1000; i++) {
                long keyLong = rand.nextLong();
                byte[] key = Bytes.toBytes(keyLong);
                t.write(key, key);
                keysWritten.add(keyLong);
            }
        }
    });
    // start a sync transaction
    txnl.execute(new TransactionExecutor.Subroutine() {

        @Override
        public void apply() throws Exception {
            // get the splits for the table
            List<Split> splits = t.getSplits();
            // read each split and verify the keys
            SortedSet<Long> keysToVerify = Sets.newTreeSet(keysWritten);
            verifySplits(t, splits, keysToVerify);
        }
    });
    // start a sync transaction
    txnl.execute(new TransactionExecutor.Subroutine() {

        @Override
        public void apply() throws Exception {
            // get specific number of splits for a subrange
            SortedSet<Long> keysToVerify = Sets.newTreeSet(keysWritten.subSet(0x10000000L, 0x40000000L));
            List<Split> splits = t.getSplits(5, Bytes.toBytes(0x10000000L), Bytes.toBytes(0x40000000L));
            Assert.assertTrue(splits.size() <= 5);
            // read each split and verify the keys
            verifySplits(t, splits, keysToVerify);
        }
    });
    dsFrameworkUtil.deleteInstance(tBatch);
}
Also used : Random(java.util.Random) TransactionExecutor(org.apache.tephra.TransactionExecutor) List(java.util.List) SortedSet(java.util.SortedSet) TransactionFailureException(org.apache.tephra.TransactionFailureException) NoSuchElementException(java.util.NoSuchElementException) DatasetId(co.cask.cdap.proto.id.DatasetId) Test(org.junit.Test)

Example 19 with TransactionExecutor

use of org.apache.tephra.TransactionExecutor in project cdap by caskdata.

the class KeyValueTableTest method testASyncWriteReadSwapDelete.

@Test
public void testASyncWriteReadSwapDelete() throws Exception {
    TransactionExecutor txnl = dsFrameworkUtil.newTransactionExecutor(kvTable);
    // defer all writes until commit
    txnl.execute(new TransactionExecutor.Subroutine() {

        @Override
        public void apply() throws Exception {
            // write a value
            kvTable.write(KEY2, VAL1);
        }
    });
    // verify synchronously
    txnl.execute(new TransactionExecutor.Subroutine() {

        @Override
        public void apply() throws Exception {
            // verify that the value is now visible
            Assert.assertArrayEquals(VAL1, kvTable.read(KEY2));
        }
    });
    // defer all writes until commit
    txnl.execute(new TransactionExecutor.Subroutine() {

        @Override
        public void apply() throws Exception {
            // update the value
            kvTable.write(KEY2, VAL2);
        }
    });
    // verify synchronously
    txnl.execute(new TransactionExecutor.Subroutine() {

        @Override
        public void apply() throws Exception {
            // verify that the value is now visible
            Assert.assertArrayEquals(VAL2, kvTable.read(KEY2));
        }
    });
    // defer all writes until commit
    txnl.execute(new TransactionExecutor.Subroutine() {

        @Override
        public void apply() throws Exception {
            // write a swap, this should fail
            Assert.assertFalse(kvTable.compareAndSwap(KEY2, VAL1, VAL3));
            Assert.assertArrayEquals(VAL2, kvTable.read(KEY2));
        }
    });
    // defer all writes until commit
    txnl.execute(new TransactionExecutor.Subroutine() {

        @Override
        public void apply() throws Exception {
            // swap the value
            Assert.assertTrue(kvTable.compareAndSwap(KEY2, VAL2, VAL3));
        }
    });
    // verify synchronously
    txnl.execute(new TransactionExecutor.Subroutine() {

        @Override
        public void apply() throws Exception {
            // verify the value was swapped
            Assert.assertArrayEquals(VAL3, kvTable.read(KEY2));
        }
    });
    // defer all writes until commit
    txnl.execute(new TransactionExecutor.Subroutine() {

        @Override
        public void apply() throws Exception {
            // delete the value
            kvTable.delete(KEY2);
        }
    });
    // verify synchronously
    txnl.execute(new TransactionExecutor.Subroutine() {

        @Override
        public void apply() throws Exception {
            // verify it is gone now
            Assert.assertNull(kvTable.read(KEY2));
        }
    });
}
Also used : TransactionExecutor(org.apache.tephra.TransactionExecutor) TransactionFailureException(org.apache.tephra.TransactionFailureException) NoSuchElementException(java.util.NoSuchElementException) Test(org.junit.Test)

Example 20 with TransactionExecutor

use of org.apache.tephra.TransactionExecutor 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);
}
Also used : TransactionFailureException(org.apache.tephra.TransactionFailureException) TransactionExecutor(org.apache.tephra.TransactionExecutor) TransactionFailureException(org.apache.tephra.TransactionFailureException) NoSuchElementException(java.util.NoSuchElementException) DatasetId(co.cask.cdap.proto.id.DatasetId) Test(org.junit.Test)

Aggregations

TransactionExecutor (org.apache.tephra.TransactionExecutor)79 Test (org.junit.Test)64 TransactionFailureException (org.apache.tephra.TransactionFailureException)31 DatasetId (co.cask.cdap.proto.id.DatasetId)30 Table (co.cask.cdap.api.dataset.table.Table)15 List (java.util.List)15 NoSuchElementException (java.util.NoSuchElementException)15 TransactionAware (org.apache.tephra.TransactionAware)15 IOException (java.io.IOException)12 Row (co.cask.cdap.api.dataset.table.Row)11 DefaultTransactionExecutor (org.apache.tephra.DefaultTransactionExecutor)11 Put (co.cask.cdap.api.dataset.table.Put)10 ImmutableList (com.google.common.collect.ImmutableList)9 ProgramId (co.cask.cdap.proto.id.ProgramId)8 DatasetManagementException (co.cask.cdap.api.dataset.DatasetManagementException)6 Scanner (co.cask.cdap.api.dataset.table.Scanner)6 Map (java.util.Map)6 ProgramRunId (co.cask.cdap.proto.id.ProgramRunId)5 TypeToken (com.google.common.reflect.TypeToken)5 Iterator (java.util.Iterator)5