/** * Creates properties for {@link Table} or {@link Table} data set instance. * * @param level level on which to detect conflicts in changes made by different transactions * @param ttl time to live for data written into a table, in ms. {@link #NO_TTL} means unlimited * @return {@link DatasetProperties} for the data set */ public static DatasetProperties tableProperties( ConflictDetection level, int ttl, DatasetProperties props) { return DatasetProperties.builder() .add(Table.PROPERTY_CONFLICT_LEVEL, level.name()) .add(Table.PROPERTY_TTL, ttl) .addAll(props.getProperties()) .build(); }
@Test public void testColumnFamily() throws Exception { DatasetProperties props = DatasetProperties.builder().add(Table.PROPERTY_COLUMN_FAMILY, "t").build(); HBaseTableDefinition tableDefinition = new HBaseTableDefinition("foo"); String tableName = "testcf"; DatasetSpecification spec = tableDefinition.configure(tableName, props); DatasetAdmin admin = new HBaseTableAdmin( CONTEXT1, spec, testHBase.getConfiguration(), hBaseTableUtil, CConfiguration.create(), new LocalLocationFactory(tmpFolder.newFolder())); admin.create(); final HBaseTable table = new HBaseTable(CONTEXT1, spec, cConf, testHBase.getConfiguration(), hBaseTableUtil); TransactionSystemClient txClient = new DetachedTxSystemClient(); TransactionExecutor executor = new DefaultTransactionExecutor(txClient, table); executor.execute( new TransactionExecutor.Subroutine() { @Override public void apply() throws Exception { table.put(new Put("row", "column", "testValue")); } }); final HBaseTable table2 = new HBaseTable(CONTEXT1, spec, cConf, testHBase.getConfiguration(), hBaseTableUtil); executor = new DefaultTransactionExecutor(txClient, table2); executor.execute( new TransactionExecutor.Subroutine() { @Override public void apply() throws Exception { Assert.assertEquals( "testValue", table2.get(new Get("row", "column")).getString("column")); } }); // Verify the column family name HTableDescriptor htd = hBaseTableUtil.getHTableDescriptor( testHBase.getHBaseAdmin(), TableId.from(CONTEXT1.getNamespaceId(), tableName)); HColumnDescriptor hcd = htd.getFamily(Bytes.toBytes("t")); Assert.assertNotNull(hcd); Assert.assertEquals("t", hcd.getNameAsString()); }
@Test public void testPreSplit() throws Exception { byte[][] splits = new byte[][] {Bytes.toBytes("a"), Bytes.toBytes("b"), Bytes.toBytes("c")}; DatasetProperties props = DatasetProperties.builder().add("hbase.splits", new Gson().toJson(splits)).build(); String presplittedTable = "presplitted"; getTableAdmin(CONTEXT1, presplittedTable, props).create(); HBaseAdmin hBaseAdmin = testHBase.getHBaseAdmin(); try { List<HRegionInfo> regions = hBaseTableUtil.getTableRegions( hBaseAdmin, TableId.from(NAMESPACE1.getId(), presplittedTable)); // note: first region starts at very first row key, so we have one extra to the splits count Assert.assertEquals(4, regions.size()); Assert.assertArrayEquals(Bytes.toBytes("a"), regions.get(1).getStartKey()); Assert.assertArrayEquals(Bytes.toBytes("b"), regions.get(2).getStartKey()); Assert.assertArrayEquals(Bytes.toBytes("c"), regions.get(3).getStartKey()); } finally { hBaseAdmin.close(); } }
@Test public void testEnableIncrements() throws Exception { // setup a table with increments disabled and with it enabled String disableTableName = "incr-disable"; String enabledTableName = "incr-enable"; TableId disabledTableId = TableId.from(NAMESPACE1.getId(), disableTableName); TableId enabledTableId = TableId.from(NAMESPACE1.getId(), enabledTableName); HBaseTableAdmin disabledAdmin = getTableAdmin(CONTEXT1, disableTableName, DatasetProperties.EMPTY); disabledAdmin.create(); HBaseAdmin admin = testHBase.getHBaseAdmin(); DatasetProperties props = DatasetProperties.builder().add(Table.PROPERTY_READLESS_INCREMENT, "true").build(); HBaseTableAdmin enabledAdmin = getTableAdmin(CONTEXT1, enabledTableName, props); enabledAdmin.create(); try { try { HTableDescriptor htd = hBaseTableUtil.getHTableDescriptor(admin, disabledTableId); List<String> cps = htd.getCoprocessors(); assertFalse(cps.contains(IncrementHandler.class.getName())); htd = hBaseTableUtil.getHTableDescriptor(admin, enabledTableId); cps = htd.getCoprocessors(); assertTrue(cps.contains(IncrementHandler.class.getName())); } finally { admin.close(); } BufferingTable table = getTable(CONTEXT1, enabledTableName, ConflictDetection.COLUMN); byte[] row = Bytes.toBytes("row1"); byte[] col = Bytes.toBytes("col1"); DetachedTxSystemClient txSystemClient = new DetachedTxSystemClient(); Transaction tx = txSystemClient.startShort(); table.startTx(tx); table.increment(row, col, 10); table.commitTx(); // verify that value was written as a delta value final byte[] expectedValue = Bytes.add(IncrementHandlerState.DELTA_MAGIC_PREFIX, Bytes.toBytes(10L)); final AtomicBoolean foundValue = new AtomicBoolean(); byte[] enabledTableNameBytes = hBaseTableUtil.getHTableDescriptor(admin, enabledTableId).getName(); testHBase.forEachRegion( enabledTableNameBytes, new Function<HRegion, Object>() { @Nullable @Override public Object apply(@Nullable HRegion hRegion) { Scan scan = new Scan(); try { RegionScanner scanner = hRegion.getScanner(scan); List<Cell> results = Lists.newArrayList(); boolean hasMore; do { hasMore = scanner.next(results); for (Cell cell : results) { if (CellUtil.matchingValue(cell, expectedValue)) { foundValue.set(true); } } } while (hasMore); } catch (IOException ioe) { fail("IOException scanning region: " + ioe.getMessage()); } return null; } }); assertTrue( "Should have seen the expected encoded delta value in the " + enabledTableName + " table region", foundValue.get()); } finally { disabledAdmin.drop(); enabledAdmin.drop(); } }
@Test public void testTTL() throws Exception { // for the purpose of this test it is fine not to configure ttl when creating table: we want to // see if it // applies on reading int ttl = 1000; String ttlTable = "ttl"; String noTtlTable = "nottl"; DatasetProperties props = DatasetProperties.builder().add(Table.PROPERTY_TTL, String.valueOf(ttl)).build(); getTableAdmin(CONTEXT1, ttlTable, props).create(); DatasetSpecification ttlTableSpec = DatasetSpecification.builder(ttlTable, HBaseTable.class.getName()) .properties(props.getProperties()) .build(); HBaseTable table = new HBaseTable(CONTEXT1, ttlTableSpec, cConf, testHBase.getConfiguration(), hBaseTableUtil); DetachedTxSystemClient txSystemClient = new DetachedTxSystemClient(); Transaction tx = txSystemClient.startShort(); table.startTx(tx); table.put(b("row1"), b("col1"), b("val1")); table.commitTx(); TimeUnit.SECONDS.sleep(2); tx = txSystemClient.startShort(); table.startTx(tx); table.put(b("row2"), b("col2"), b("val2")); table.commitTx(); // now, we should not see first as it should have expired, but see the last one tx = txSystemClient.startShort(); table.startTx(tx); byte[] val = table.get(b("row1"), b("col1")); if (val != null) { LOG.info("Unexpected value " + Bytes.toStringBinary(val)); } Assert.assertNull(val); Assert.assertArrayEquals(b("val2"), table.get(b("row2"), b("col2"))); // test a table with no TTL DatasetProperties props2 = DatasetProperties.builder().add(Table.PROPERTY_TTL, String.valueOf(Tables.NO_TTL)).build(); getTableAdmin(CONTEXT1, noTtlTable, props2).create(); DatasetSpecification noTtlTableSpec = DatasetSpecification.builder(noTtlTable, HBaseTable.class.getName()) .properties(props2.getProperties()) .build(); HBaseTable table2 = new HBaseTable( CONTEXT1, noTtlTableSpec, cConf, testHBase.getConfiguration(), hBaseTableUtil); tx = txSystemClient.startShort(); table2.startTx(tx); table2.put(b("row1"), b("col1"), b("val1")); table2.commitTx(); TimeUnit.SECONDS.sleep(2); tx = txSystemClient.startShort(); table2.startTx(tx); table2.put(b("row2"), b("col2"), b("val2")); table2.commitTx(); // if ttl is -1 (unlimited), it should see both tx = txSystemClient.startShort(); table2.startTx(tx); Assert.assertArrayEquals(b("val1"), table2.get(b("row1"), b("col1"))); Assert.assertArrayEquals(b("val2"), table2.get(b("row2"), b("col2"))); }