This is an automated email from the ASF dual-hosted git repository.

junegunn pushed a commit to branch branch-3
in repository https://gitbox.apache.org/repos/asf/hbase.git


The following commit(s) were added to refs/heads/branch-3 by this push:
     new 93fb422cd37 HBASE-30117 TableDescriptorChecker should verify CF 
date-tiered and bloom filter configuration set via setValue (#8144)
93fb422cd37 is described below

commit 93fb422cd37bb70c2fe67bf7b437e979493fc29d
Author: Jinhyuk Kim <[email protected]>
AuthorDate: Fri May 8 10:13:33 2026 +0900

    HBASE-30117 TableDescriptorChecker should verify CF date-tiered and bloom 
filter configuration set via setValue (#8144)
    
    Signed-off-by: Junegunn Choi <[email protected]>
---
 .../hadoop/hbase/util/TableDescriptorChecker.java  |  7 ++--
 .../hbase/client/TestIllegalTableDescriptor.java   | 43 ++++++++++++++--------
 .../hbase/util/TestTableDescriptorChecker.java     | 35 ++++++++++++++++++
 3 files changed, 66 insertions(+), 19 deletions(-)

diff --git 
a/hbase-server/src/main/java/org/apache/hadoop/hbase/util/TableDescriptorChecker.java
 
b/hbase-server/src/main/java/org/apache/hadoop/hbase/util/TableDescriptorChecker.java
index 409cc284dee..691103ba256 100644
--- 
a/hbase-server/src/main/java/org/apache/hadoop/hbase/util/TableDescriptorChecker.java
+++ 
b/hbase-server/src/main/java/org/apache/hadoop/hbase/util/TableDescriptorChecker.java
@@ -233,8 +233,8 @@ public final class TableDescriptorChecker {
     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());
       checkDateTieredCompactionForTimeRangeDataTiering(cfdConf);
     }
   }
@@ -318,7 +318,8 @@ public final class TableDescriptorChecker {
     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) {
diff --git 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestIllegalTableDescriptor.java
 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestIllegalTableDescriptor.java
index 666cfbdf54a..9b314ba87c5 100644
--- 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestIllegalTableDescriptor.java
+++ 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestIllegalTableDescriptor.java
@@ -213,23 +213,34 @@ public class TestIllegalTableDescriptor {
     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 {
diff --git 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestTableDescriptorChecker.java
 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestTableDescriptorChecker.java
index fcc2ab4ce8f..17a36b43750 100644
--- 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestTableDescriptorChecker.java
+++ 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestTableDescriptorChecker.java
@@ -26,6 +26,7 @@ import org.apache.hadoop.hbase.TableName;
 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;
@@ -84,4 +85,38 @@ public class TestTableDescriptorChecker {
       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());
+    }
+  }
 }

Reply via email to