HBASE-21732 Should call toUpperCase before using Enum.valueOf in some methods for ColumnFamilyDescriptor
Signed-off-by: Zheng Hu <openinx@gmail.com>
This commit is contained in:
parent
51c58e083c
commit
348cbf63ec
|
@ -17,7 +17,6 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.hadoop.hbase.client;
|
package org.apache.hadoop.hbase.client;
|
||||||
|
|
||||||
import org.apache.hbase.thirdparty.com.google.common.base.Preconditions;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -25,21 +24,23 @@ import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import org.apache.hadoop.hbase.HConstants;
|
import org.apache.hadoop.hbase.HConstants;
|
||||||
import org.apache.hadoop.hbase.KeepDeletedCells;
|
import org.apache.hadoop.hbase.KeepDeletedCells;
|
||||||
import org.apache.hadoop.hbase.MemoryCompactionPolicy;
|
import org.apache.hadoop.hbase.MemoryCompactionPolicy;
|
||||||
import org.apache.yetus.audience.InterfaceAudience;
|
|
||||||
import org.apache.hadoop.hbase.exceptions.DeserializationException;
|
import org.apache.hadoop.hbase.exceptions.DeserializationException;
|
||||||
import org.apache.hadoop.hbase.exceptions.HBaseException;
|
import org.apache.hadoop.hbase.exceptions.HBaseException;
|
||||||
import org.apache.hadoop.hbase.io.compress.Compression;
|
import org.apache.hadoop.hbase.io.compress.Compression;
|
||||||
import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding;
|
import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding;
|
||||||
import org.apache.hadoop.hbase.regionserver.BloomType;
|
import org.apache.hadoop.hbase.regionserver.BloomType;
|
||||||
import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
|
|
||||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.ColumnFamilySchema;
|
|
||||||
import org.apache.hadoop.hbase.util.Bytes;
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
import org.apache.hadoop.hbase.util.PrettyPrinter;
|
import org.apache.hadoop.hbase.util.PrettyPrinter;
|
||||||
import org.apache.hadoop.hbase.util.PrettyPrinter.Unit;
|
import org.apache.hadoop.hbase.util.PrettyPrinter.Unit;
|
||||||
|
import org.apache.yetus.audience.InterfaceAudience;
|
||||||
|
|
||||||
|
import org.apache.hbase.thirdparty.com.google.common.base.Preconditions;
|
||||||
|
|
||||||
|
import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
|
||||||
|
import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.ColumnFamilySchema;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
|
@ -129,7 +130,6 @@ public class ColumnFamilyDescriptorBuilder {
|
||||||
private static final Bytes BLOOMFILTER_BYTES = new Bytes(Bytes.toBytes(BLOOMFILTER));
|
private static final Bytes BLOOMFILTER_BYTES = new Bytes(Bytes.toBytes(BLOOMFILTER));
|
||||||
@InterfaceAudience.Private
|
@InterfaceAudience.Private
|
||||||
public static final String REPLICATION_SCOPE = "REPLICATION_SCOPE";
|
public static final String REPLICATION_SCOPE = "REPLICATION_SCOPE";
|
||||||
private static final Bytes REPLICATION_SCOPE_BYTES = new Bytes(Bytes.toBytes(REPLICATION_SCOPE));
|
|
||||||
@InterfaceAudience.Private
|
@InterfaceAudience.Private
|
||||||
public static final String MAX_VERSIONS = HConstants.VERSIONS;
|
public static final String MAX_VERSIONS = HConstants.VERSIONS;
|
||||||
private static final Bytes MAX_VERSIONS_BYTES = new Bytes(Bytes.toBytes(MAX_VERSIONS));
|
private static final Bytes MAX_VERSIONS_BYTES = new Bytes(Bytes.toBytes(MAX_VERSIONS));
|
||||||
|
@ -778,8 +778,7 @@ public class ColumnFamilyDescriptorBuilder {
|
||||||
@Override
|
@Override
|
||||||
public Compression.Algorithm getCompressionType() {
|
public Compression.Algorithm getCompressionType() {
|
||||||
return getStringOrDefault(COMPRESSION_BYTES,
|
return getStringOrDefault(COMPRESSION_BYTES,
|
||||||
Compression.Algorithm::valueOf,
|
n -> Compression.Algorithm.valueOf(n.toUpperCase()), DEFAULT_COMPRESSION);
|
||||||
DEFAULT_COMPRESSION);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -799,8 +798,7 @@ public class ColumnFamilyDescriptorBuilder {
|
||||||
@Override
|
@Override
|
||||||
public DataBlockEncoding getDataBlockEncoding() {
|
public DataBlockEncoding getDataBlockEncoding() {
|
||||||
return getStringOrDefault(DATA_BLOCK_ENCODING_BYTES,
|
return getStringOrDefault(DATA_BLOCK_ENCODING_BYTES,
|
||||||
DataBlockEncoding::valueOf,
|
n -> DataBlockEncoding.valueOf(n.toUpperCase()), DataBlockEncoding.NONE);
|
||||||
DataBlockEncoding.NONE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -833,8 +831,7 @@ public class ColumnFamilyDescriptorBuilder {
|
||||||
@Override
|
@Override
|
||||||
public Compression.Algorithm getCompactionCompressionType() {
|
public Compression.Algorithm getCompactionCompressionType() {
|
||||||
return getStringOrDefault(COMPRESSION_COMPACT_BYTES,
|
return getStringOrDefault(COMPRESSION_COMPACT_BYTES,
|
||||||
Compression.Algorithm::valueOf,
|
n -> Compression.Algorithm.valueOf(n.toUpperCase()), getCompressionType());
|
||||||
getCompressionType());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -868,7 +865,8 @@ public class ColumnFamilyDescriptorBuilder {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MemoryCompactionPolicy getInMemoryCompaction() {
|
public MemoryCompactionPolicy getInMemoryCompaction() {
|
||||||
return getStringOrDefault(IN_MEMORY_COMPACTION_BYTES, MemoryCompactionPolicy::valueOf, null);
|
return getStringOrDefault(IN_MEMORY_COMPACTION_BYTES,
|
||||||
|
n -> MemoryCompactionPolicy.valueOf(n.toUpperCase()), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -962,7 +960,8 @@ public class ColumnFamilyDescriptorBuilder {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BloomType getBloomFilterType() {
|
public BloomType getBloomFilterType() {
|
||||||
return getStringOrDefault(BLOOMFILTER_BYTES, BloomType::valueOf, DEFAULT_BLOOMFILTER);
|
return getStringOrDefault(BLOOMFILTER_BYTES, n -> BloomType.valueOf(n.toUpperCase()),
|
||||||
|
DEFAULT_BLOOMFILTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModifyableColumnFamilyDescriptor setBloomFilterType(final BloomType bt) {
|
public ModifyableColumnFamilyDescriptor setBloomFilterType(final BloomType bt) {
|
||||||
|
@ -1302,7 +1301,8 @@ public class ColumnFamilyDescriptorBuilder {
|
||||||
@Override
|
@Override
|
||||||
public MobCompactPartitionPolicy getMobCompactPartitionPolicy() {
|
public MobCompactPartitionPolicy getMobCompactPartitionPolicy() {
|
||||||
return getStringOrDefault(MOB_COMPACT_PARTITION_POLICY_BYTES,
|
return getStringOrDefault(MOB_COMPACT_PARTITION_POLICY_BYTES,
|
||||||
MobCompactPartitionPolicy::valueOf, DEFAULT_MOB_COMPACT_PARTITION_POLICY);
|
n -> MobCompactPartitionPolicy.valueOf(n.toUpperCase()),
|
||||||
|
DEFAULT_MOB_COMPACT_PARTITION_POLICY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.hadoop.hbase.client;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
import org.apache.hadoop.hbase.HBaseClassTestRule;
|
||||||
|
import org.apache.hadoop.hbase.testclassification.ClientTests;
|
||||||
|
import org.apache.hadoop.hbase.testclassification.SmallTests;
|
||||||
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
|
import org.junit.ClassRule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.experimental.categories.Category;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Testcase for HBASE-21732. Make sure that all enum configurations can accept lower case value.
|
||||||
|
*/
|
||||||
|
@Category({ ClientTests.class, SmallTests.class })
|
||||||
|
public class TestColumnFamilyDescriptorLowerCaseEnum {
|
||||||
|
|
||||||
|
@ClassRule
|
||||||
|
public static final HBaseClassTestRule CLASS_RULE =
|
||||||
|
HBaseClassTestRule.forClass(TestColumnFamilyDescriptorLowerCaseEnum.class);
|
||||||
|
|
||||||
|
private static final Logger LOG =
|
||||||
|
LoggerFactory.getLogger(TestColumnFamilyDescriptorLowerCaseEnum.class);
|
||||||
|
|
||||||
|
private Method getSetMethod(Method getMethod, Class<?> enumType) throws NoSuchMethodException {
|
||||||
|
String methodName = getMethod.getName().replaceFirst("get", "set");
|
||||||
|
return ColumnFamilyDescriptorBuilder.class.getMethod(methodName, enumType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Enum<?> getEnumValue(Class<?> enumType) {
|
||||||
|
for (Enum<?> enumConst : enumType.asSubclass(Enum.class).getEnumConstants()) {
|
||||||
|
if (!enumConst.name().equalsIgnoreCase("NONE") && !enumConst.name().equals("DEFAULT")) {
|
||||||
|
return enumConst;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new NoSuchElementException(enumType.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean contains(Collection<Enum<?>> enumConsts, String value) {
|
||||||
|
return enumConsts.stream().anyMatch(e -> e.name().equals(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test()
|
||||||
|
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
|
||||||
|
Map<Method, Enum<?>> getMethod2Value = new HashMap<>();
|
||||||
|
ColumnFamilyDescriptorBuilder builder =
|
||||||
|
ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes("test"));
|
||||||
|
for (Method method : ColumnFamilyDescriptor.class.getMethods()) {
|
||||||
|
if (method.getParameterCount() == 0 && method.getReturnType().isEnum()) {
|
||||||
|
LOG.info("Checking " + method);
|
||||||
|
Class<?> enumType = method.getReturnType();
|
||||||
|
Method setMethod = getSetMethod(method, enumType);
|
||||||
|
Enum<?> enumConst = getEnumValue(enumType);
|
||||||
|
LOG.info("Using " + setMethod + " to set the value to " + enumConst);
|
||||||
|
setMethod.invoke(builder, enumConst);
|
||||||
|
getMethod2Value.put(method, enumConst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ColumnFamilyDescriptor desc = builder.build();
|
||||||
|
ColumnFamilyDescriptorBuilder builder2 =
|
||||||
|
ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes("test2"));
|
||||||
|
desc.getValues().forEach((k, v) -> {
|
||||||
|
LOG.info(k.toString() + "=>" + v.toString());
|
||||||
|
String str = Bytes.toString(v.get(), v.getOffset(), v.getLength());
|
||||||
|
if (contains(getMethod2Value.values(), str)) {
|
||||||
|
LOG.info("Set to lower case " + str.toLowerCase());
|
||||||
|
builder2.setValue(k, new Bytes(Bytes.toBytes(str.toLowerCase())));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ColumnFamilyDescriptor desc2 = builder2.build();
|
||||||
|
for (Map.Entry<Method, Enum<?>> entry : getMethod2Value.entrySet()) {
|
||||||
|
assertEquals(entry.getKey() + " should return " + entry.getValue(), entry.getValue(),
|
||||||
|
entry.getKey().invoke(desc2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue