Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -233,8 +233,8 @@ private static void checkDateTieredCompactionForTimeRangeDataTiering(final Confi
checkDateTieredCompactionForTimeRangeDataTiering(conf);
for (ColumnFamilyDescriptor cfd : td.getColumnFamilies()) {
// Column family level configurations
Configuration cfdConf =
new CompoundConfiguration().add(conf).addStringMap(cfd.getConfiguration());
Configuration cfdConf = new CompoundConfiguration().add(conf)
.addStringMap(cfd.getConfiguration()).addBytesMap(cfd.getValues());
Comment on lines +236 to +237
Copy link
Copy Markdown
Contributor Author

@jinhyukify jinhyukify May 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will fix this bug:

Before

# This should fail but succeed
create 'mytable2', {NAME => 'f', CONFIGURATION => {'hbase.hstore.datatiering.type'  => 'TIME_RANGE', 'hbase.hstore.engine.class' => 'org.apache.hadoop.hbase.regionserver.DefaultStoreEngine'}}

After

# This fails
create 'mytable2', {NAME => 'f', CONFIGURATION => {'hbase.hstore.datatiering.type'  => 'TIME_RANGE', 'hbase.hstore.engine.class' => 'org.apache.hadoop.hbase.regionserver.DefaultStoreEngine'}}

ERROR: org.apache.hadoop.hbase.DoNotRetryIOException: Time Range Data Tiering should be enabled with Date Tiered Compaction. Set hbase.table.sanity.checks to false at conf or table descriptor if you want to bypass sanity checks
        at org.apache.hadoop.hbase.util.TableDescriptorChecker.warnOrThrowExceptionForFailure(TableDescriptorChecker.java:365)
        at org.apache.hadoop.hbase.util.TableDescriptorChecker.warnOrThrowExceptionForFailure(TableDescriptorChecker.java:382)
        at org.apache.hadoop.hbase.util.TableDescriptorChecker.checkDateTieredCompactionForTimeRangeDataTiering(TableDescriptorChecker.java:247)
        at org.apache.hadoop.hbase.util.TableDescriptorChecker.checkDateTieredCompactionForTimeRangeDataTiering(TableDescriptorChecker.java:238)
        at org.apache.hadoop.hbase.util.TableDescriptorChecker.sanityCheck(TableDescriptorChecker.java:210)
        at org.apache.hadoop.hbase.master.HMaster.createTable(HMaster.java:2494)
        at org.apache.hadoop.hbase.master.MasterRpcServices.createTable(MasterRpcServices.java:792)
        at org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos$MasterService$2.callBlockingMethod(MasterProtos.java)
        at org.apache.hadoop.hbase.ipc.RpcServer.call(RpcServer.java:461)
        at org.apache.hadoop.hbase.ipc.CallRunner.run(CallRunner.java:124)
        at org.apache.hadoop.hbase.ipc.RpcHandler.run(RpcHandler.java:102)
        at org.apache.hadoop.hbase.ipc.RpcHandler.run(RpcHandler.java:82)
Caused by: java.lang.IllegalArgumentException: Time Range Data Tiering should be enabled with Date Tiered Compaction.
        at org.apache.hadoop.hbase.util.TableDescriptorChecker.lambda$checkDateTieredCompactionForTimeRangeDataTiering$4(TableDescriptorChecker.java:253)
        at org.apache.hadoop.hbase.util.TableDescriptorChecker.warnOrThrowExceptionForFailure(TableDescriptorChecker.java:380)
        ... 10 more

checkDateTieredCompactionForTimeRangeDataTiering(cfdConf);
}
}
Expand Down Expand Up @@ -318,7 +318,8 @@ private static void checkBloomFilterType(final Configuration conf, final TableDe
throws IOException {
warnOrThrowExceptionForFailure(conf, () -> {
for (ColumnFamilyDescriptor cfd : td.getColumnFamilies()) {
Configuration cfdConf = new CompoundConfiguration().addStringMap(cfd.getConfiguration());
Configuration cfdConf = new CompoundConfiguration().addStringMap(cfd.getConfiguration())
.addBytesMap(cfd.getValues());
try {
BloomFilterUtil.getBloomFilterParam(cfd.getBloomFilterType(), cfdConf);
} catch (IllegalArgumentException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,23 +213,34 @@ public void testIllegalTableDescriptorWithDataTiering() throws IOException {
checkTableIsIllegal(builder.build());

// column family level configuration changes
builder = TableDescriptorBuilder.newBuilder(TableName.valueOf(name.getMethodName()));
cfBuilder = ColumnFamilyDescriptorBuilder.newBuilder(FAMILY);

// First scenario: DataTieringType set to TIME_RANGE without DateTieredStoreEngine
cfBuilder.setConfiguration(DataTieringManager.DATATIERING_KEY,
DataTieringType.TIME_RANGE.name());
checkTableIsIllegal(builder.setColumnFamily(cfBuilder.build()).build());

// Second scenario: DataTieringType set to TIME_RANGE with DateTieredStoreEngine
cfBuilder.setConfiguration(StoreEngine.STORE_ENGINE_CLASS_KEY,
"org.apache.hadoop.hbase.regionserver.DateTieredStoreEngine");
checkTableIsLegal(builder.modifyColumnFamily(cfBuilder.build()).build());
for (boolean viaSetValue : new boolean[] { false, true }) {
builder = TableDescriptorBuilder.newBuilder(TableName.valueOf(name.getMethodName()));
cfBuilder = ColumnFamilyDescriptorBuilder.newBuilder(FAMILY);

// First scenario: DataTieringType set to TIME_RANGE without DateTieredStoreEngine
setCfKey(cfBuilder, viaSetValue, DataTieringManager.DATATIERING_KEY,
DataTieringType.TIME_RANGE.name());
checkTableIsIllegal(builder.setColumnFamily(cfBuilder.build()).build());

// Second scenario: DataTieringType set to TIME_RANGE with DateTieredStoreEngine
setCfKey(cfBuilder, viaSetValue, StoreEngine.STORE_ENGINE_CLASS_KEY,
"org.apache.hadoop.hbase.regionserver.DateTieredStoreEngine");
checkTableIsLegal(builder.modifyColumnFamily(cfBuilder.build()).build());

// Third scenario: Disabling DateTieredStoreEngine while Time Range DataTiering is active
setCfKey(cfBuilder, viaSetValue, StoreEngine.STORE_ENGINE_CLASS_KEY,
"org.apache.hadoop.hbase.regionserver.DefaultStoreEngine");
checkTableIsIllegal(builder.modifyColumnFamily(cfBuilder.build()).build());
}
}

// Third scenario: Disabling DateTieredStoreEngine while Time Range DataTiering is active
cfBuilder.setConfiguration(StoreEngine.STORE_ENGINE_CLASS_KEY,
"org.apache.hadoop.hbase.regionserver.DefaultStoreEngine");
checkTableIsIllegal(builder.modifyColumnFamily(cfBuilder.build()).build());
private static void setCfKey(ColumnFamilyDescriptorBuilder cfb, boolean viaSetValue, String key,
String value) {
if (viaSetValue) {
cfb.setValue(key, value);
} else {
cfb.setConfiguration(key, value);
}
}

private void checkTableIsLegal(TableDescriptor tableDescriptor) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
import org.apache.hadoop.hbase.conf.ConfigKey;
import org.apache.hadoop.hbase.regionserver.BloomType;
import org.apache.hadoop.hbase.testclassification.MiscTests;
import org.apache.hadoop.hbase.testclassification.SmallTests;
import org.junit.jupiter.api.Tag;
Expand Down Expand Up @@ -84,4 +85,38 @@ public void testSanityCheck() throws IOException {
TableDescriptorChecker.sanityCheck(conf, t.build());
}
}

@Test
public void testBloomFilterPrefixLengthValidation() throws IOException {
Configuration conf = new Configuration();
String key = BloomFilterUtil.PREFIX_LENGTH_KEY;

for (boolean viaSetValue : new boolean[] { true, false }) {
ColumnFamilyDescriptorBuilder cf = ColumnFamilyDescriptorBuilder.newBuilder("cf".getBytes())
.setBloomFilterType(BloomType.ROWPREFIX_FIXED_LENGTH);
TableDescriptorBuilder t = TableDescriptorBuilder.newBuilder(TableName.valueOf("test"));

// Invalid: prefix length must be > 0 for ROWPREFIX_FIXED_LENGTH
if (viaSetValue) {
cf.setValue(key, "0");
} else {
cf.setConfiguration(key, "0");
}
t.setColumnFamily(cf.build());
assertThrows(DoNotRetryIOException.class,
() -> TableDescriptorChecker.sanityCheck(conf, t.build()),
"Should reject ROWPREFIX_FIXED_LENGTH with prefix length 0 set via "
+ (viaSetValue ? "setValue" : "setConfiguration"));

// Fix the error.
if (viaSetValue) {
cf.setValue(key, "5");
} else {
cf.setConfiguration(key, "5");
}
t.removeColumnFamily("cf".getBytes());
t.setColumnFamily(cf.build());
TableDescriptorChecker.sanityCheck(conf, t.build());
}
}
}