diff --git a/pom.xml b/pom.xml index 3b8fbf94..255b54ac 100644 --- a/pom.xml +++ b/pom.xml @@ -45,8 +45,8 @@ - 2.7.7 - 2.0.6 + 3.1.0 + 2.0.0-alpha4 1.8 1.8 4.13.1 @@ -54,7 +54,7 @@ ${project.encoding} UTF-8 1.7.21 - 2.0.0 + 2.0.1-SNAPSHOT @@ -198,6 +198,11 @@ 1.2.12 test + + com.fasterxml.jackson.core + jackson-databind + 2.19.0 + diff --git a/src/main/java/com/alipay/oceanbase/hbase/OHTable.java b/src/main/java/com/alipay/oceanbase/hbase/OHTable.java index 106058eb..47a170f0 100644 --- a/src/main/java/com/alipay/oceanbase/hbase/OHTable.java +++ b/src/main/java/com/alipay/oceanbase/hbase/OHTable.java @@ -154,7 +154,7 @@ public class OHTable implements Table { /** * the buffer of put request */ - private final ArrayList writeBuffer = new ArrayList(); + private final ArrayList writeBuffer = new ArrayList(); /** * when the put request reach the write buffer size the do put will * flush commits automatically @@ -459,8 +459,8 @@ private void finishSetUp() { } public static OHConnectionConfiguration setUserDefinedNamespace(String tableNameString, - OHConnectionConfiguration ohConnectionConf) - throws IllegalArgumentException { + OHConnectionConfiguration ohConnectionConf) + throws IllegalArgumentException { if (tableNameString.indexOf(':') != -1) { String[] params = tableNameString.split(":"); if (params.length != 2) { @@ -500,13 +500,15 @@ public Configuration getConfiguration() { @Override public HTableDescriptor getTableDescriptor() throws IOException { - OHTableDescriptorExecutor executor = new OHTableDescriptorExecutor(tableNameString, obTableClient); + OHTableDescriptorExecutor executor = new OHTableDescriptorExecutor(tableNameString, + obTableClient); return executor.getTableDescriptor(); } @Override public TableDescriptor getDescriptor() throws IOException { - OHTableDescriptorExecutor executor = new OHTableDescriptorExecutor(tableNameString, obTableClient); + OHTableDescriptorExecutor executor = new OHTableDescriptorExecutor(tableNameString, + obTableClient); return executor.getTableDescriptor(); } @@ -620,8 +622,8 @@ private BatchOperation compatOldServerDel(final List actions, fin } else if (delete.getFamilyCellMap().size() > 1) { boolean has_delete_family = delete.getFamilyCellMap().entrySet().stream() .flatMap(entry -> entry.getValue().stream()).anyMatch( - kv -> kv.getType().getCode() == KeyValue.Type.DeleteFamily.getCode() || - kv.getType().getCode() == KeyValue.Type.DeleteFamilyVersion.getCode()); + kv -> kv.getTypeByte() == KeyValue.Type.DeleteFamily.getCode() || + kv.getTypeByte() == KeyValue.Type.DeleteFamilyVersion.getCode()); if (!has_delete_family) { return buildBatchOperation(tableNameString, Collections.singletonList(delete), true, @@ -909,10 +911,12 @@ private void processColumnFilters(NavigableSet columnFilters, byte[] family = entry.getKey(); if (entry.getValue() != null) { for (byte[] columnName : entry.getValue()) { - byte[] newQualifier = new byte[family.length + 1/* length of "." */ + columnName.length]; + byte[] newQualifier = new byte[family.length + 1/* length of "." */ + + columnName.length]; System.arraycopy(family, 0, newQualifier, 0, family.length); newQualifier[family.length] = 0x2E; // 0x2E in utf-8 is "." - System.arraycopy(columnName, 0, newQualifier, family.length + 1, columnName.length); + System.arraycopy(columnName, 0, newQualifier, family.length + 1, + columnName.length); columnFilters.add(newQualifier); } } else { @@ -1402,8 +1406,8 @@ public boolean checkAndMutate(byte[] row, byte[] family, byte[] qualifier, Compa } @Override - public CheckAndMutateBuilder checkAndMutate(byte[] row, byte[] family) { - return new ObCheckAndMutateBuilderImpl(row, family); + public long getRpcTimeout(TimeUnit unit) { + return getRpcTimeout(); } private boolean checkAndMutation(byte[] row, byte[] family, byte[] qualifier, @@ -1723,6 +1727,11 @@ public int getOperationTimeout() { return operationTimeout; } + @Override + public long getOperationTimeout(TimeUnit unit) { + return getOperationTimeout(); + } + //todo @Override public void setRpcTimeout(int rpcTimeout) { @@ -1741,11 +1750,31 @@ public int getReadRpcTimeout() { return this.readRpcTimeout; } + @Override + public void setReadRpcTimeout(int readRpcTimeout) { + this.readRpcTimeout = readRpcTimeout; + } + + @Override + public long getReadRpcTimeout(TimeUnit unit) { + return getReadRpcTimeout(); + } + + @Override + public long getWriteRpcTimeout(TimeUnit unit) { + return this.readRpcTimeout; + } + @Override public int getWriteRpcTimeout() { return this.writeRpcTimeout; } + @Override + public void setWriteRpcTimeout(int writeRpcTimeout) { + this.writeRpcTimeout = writeRpcTimeout; + } + public void setRuntimeBatchExecutor(ExecutorService runtimeBatchExecutor) { this.obTableClient.setRuntimeBatchExecutor(runtimeBatchExecutor); } @@ -1877,7 +1906,7 @@ private ObHTableFilter buildObHTableFilter(byte[] filterString, TimeRange timeRa if (columnQualifier == null) { obHTableFilter.addSelectColumnQualifier(new byte[0]); } else { - obHTableFilter.addSelectColumnQualifier(columnQualifier); + obHTableFilter.addSelectColumnQualifier(columnQualifier); } } } @@ -1935,11 +1964,11 @@ private ObTableQuery buildObTableQuery(ObHTableFilter filter, final Scan scan) { filter.setOffsetPerRowPerCf(scan.getRowOffsetPerColumnFamily()); } if (scan.isReversed()) { - obTableQuery = buildObTableQuery(filter, scan.getStopRow(), scan.includeStopRow(), scan.getStartRow(), - scan.includeStartRow(), true, ts); + obTableQuery = buildObTableQuery(filter, scan.getStopRow(), scan.includeStopRow(), + scan.getStartRow(), scan.includeStartRow(), true, ts); } else { - obTableQuery = buildObTableQuery(filter, scan.getStartRow(), scan.includeStartRow(), scan.getStopRow(), - scan.includeStopRow(), false, ts); + obTableQuery = buildObTableQuery(filter, scan.getStartRow(), scan.includeStartRow(), + scan.getStopRow(), scan.includeStopRow(), false, ts); } obTableQuery.setBatchSize(scan.getBatch()); obTableQuery.setLimit(scan.getLimit()); @@ -2016,13 +2045,14 @@ public static ObTableBatchOperation buildObTableBatchOperation(List ro private QueryAndMutate buildDeleteQueryAndMutate(KeyValue kv, ObTableOperationType operationType, boolean isTableGroup, byte[] family, Long TTL) { - KeyValue.Type kvType = KeyValue.Type.codeToType(kv.getType().getCode()); + KeyValue.Type kvType = KeyValue.Type.codeToType(kv.getTypeByte()); com.alipay.oceanbase.rpc.mutation.Mutation tableMutation = buildMutation(kv, operationType, isTableGroup, family, TTL); - if(isTableGroup) { + if (isTableGroup) { // construct new_kv otherwise filter will fail to match targeted columns byte[] oldQualifier = CellUtil.cloneQualifier(kv); - byte[] newQualifier = new byte[family.length + 1/* length of "." */ + oldQualifier.length]; + byte[] newQualifier = new byte[family.length + 1/* length of "." */ + + oldQualifier.length]; System.arraycopy(family, 0, newQualifier, 0, family.length); newQualifier[family.length] = 0x2E; // 0x2E in utf-8 is "." System.arraycopy(oldQualifier, 0, newQualifier, family.length + 1, oldQualifier.length); @@ -2105,12 +2135,10 @@ private QueryAndMutate buildDeleteQueryAndMutate(KeyValue kv, range.setEndKey(ObRowKey.getInstance(CellUtil.cloneRow(kv), ObObj.getMax(), ObObj.getMax())); if (!isTableGroup) { - filter = buildObHTableFilter(null, - new TimeRange(0, kv.getTimestamp() + 1), + filter = buildObHTableFilter(null, new TimeRange(0, kv.getTimestamp() + 1), Integer.MAX_VALUE); } else { - filter = buildObHTableFilter(null, - new TimeRange(0, kv.getTimestamp() + 1), + filter = buildObHTableFilter(null, new TimeRange(0, kv.getTimestamp() + 1), Integer.MAX_VALUE, CellUtil.cloneQualifier(kv)); } } @@ -2130,13 +2158,14 @@ private com.alipay.oceanbase.rpc.mutation.Mutation buildMutation(Cell kv, Cell newCell = kv; if (isTableGroup && family != null) { byte[] oldQualifier = CellUtil.cloneQualifier(kv); - byte[] newQualifier = new byte[family.length + 1/* length of "." */ + oldQualifier.length]; + byte[] newQualifier = new byte[family.length + 1/* length of "." */ + + oldQualifier.length]; System.arraycopy(family, 0, newQualifier, 0, family.length); newQualifier[family.length] = 0x2E; // 0x2E in utf-8 is "." System.arraycopy(oldQualifier, 0, newQualifier, family.length + 1, oldQualifier.length); newCell = modifyQualifier(kv, newQualifier); } - Cell.Type kvType = kv.getType(); + KeyValue.Type kvType = KeyValue.Type.codeToType(kv.getTypeByte()); switch (kvType) { case Put: String[] propertyColumns = V_COLUMNS; @@ -2182,7 +2211,7 @@ private KeyValue modifyQualifier(Cell original, byte[] newQualifier) { byte[] family = CellUtil.cloneFamily(original); byte[] value = CellUtil.cloneValue(original); long timestamp = original.getTimestamp(); - KeyValue.Type type = KeyValue.Type.codeToType(original.getType().getCode()); + KeyValue.Type type = KeyValue.Type.codeToType(original.getTypeByte()); // Create a new KeyValue with the modified qualifier return new KeyValue(row, family, newQualifier, timestamp, type, value); } @@ -2312,7 +2341,7 @@ private BatchOperation buildBatchOperation(String tableName, List public static ObTableOperation buildObTableOperation(Cell kv, ObTableOperationType operationType, Long TTL) { - Cell.Type kvType = kv.getType(); + KeyValue.Type kvType = KeyValue.Type.codeToType(kv.getTypeByte()); String[] propertyColumns = V_COLUMNS; Object[] property = new Object[] { CellUtil.cloneValue(kv) }; if (TTL != Long.MAX_VALUE) { @@ -2449,7 +2478,7 @@ public Pair getStartEndKeys() throws IOException { return new Pair<>(getStartKeys(), getEndKeys()); } - private CompareFilter.CompareOp getCompareOp(CompareOperator cmpOp) { + public static CompareFilter.CompareOp getCompareOp(CompareOperator cmpOp) { switch (cmpOp) { case LESS: return CompareFilter.CompareOp.LESS; @@ -2467,96 +2496,4 @@ private CompareFilter.CompareOp getCompareOp(CompareOperator cmpOp) { return CompareFilter.CompareOp.NO_OP; } } - - private class ObCheckAndMutateBuilderImpl implements CheckAndMutateBuilder { - private final byte[] row; - private final byte[] family; - private byte[] qualifier; - private byte[] value; - private TimeRange timeRange; - private CompareOperator cmpOp; - - ObCheckAndMutateBuilderImpl(byte[] row, byte[] family) { - this.row = checkNotNull(row, "The provided row is null."); - this.family = checkNotNull(family, "The provided family is null."); - } - - @Override - public CheckAndMutateBuilder qualifier(byte[] qualifier) { - this.qualifier = checkNotNull( - qualifier, - "The provided qualifier is null. You could" - + " use an empty byte array, or do not call this method if you want a null qualifier."); - return this; - } - - @Override - public CheckAndMutateBuilder timeRange(TimeRange timeRange) { - this.timeRange = timeRange; - return this; - } - - @Override - public CheckAndMutateBuilder ifNotExists() { - this.cmpOp = CompareOperator.EQUAL; - this.value = null; - return this; - } - - @Override - public CheckAndMutateBuilder ifMatches(CompareOperator cmpOp, byte[] value) { - this.cmpOp = checkNotNull(cmpOp, "The provided cmpOp is null."); - this.value = checkNotNull(value, "The provided value is null."); - return this; - } - - @Override - public boolean thenPut(Put put) throws IOException { - checkCmpOp(); - RowMutations rowMutations = new RowMutations(row); - rowMutations.add(put); - try { - return checkAndMutation(row, family, qualifier, getCompareOp(cmpOp), value, - timeRange, rowMutations); - } catch (Exception e) { - logger.error(LCD.convert("01-00005"), rowMutations, tableNameString, e); - throw new IOException("checkAndMutate type table: " + tableNameString + " e.msg: " - + e.getMessage() + " error.", e); - } - } - - @Override - public boolean thenDelete(Delete delete) throws IOException { - checkCmpOp(); - RowMutations rowMutations = new RowMutations(row); - rowMutations.add(delete); - try { - return checkAndMutation(row, family, qualifier, getCompareOp(cmpOp), value, - timeRange, rowMutations); - } catch (Exception e) { - logger.error(LCD.convert("01-00005"), rowMutations, tableNameString, e); - throw new IOException("checkAndMutate type table: " + tableNameString + " e.msg: " - + e.getMessage() + " error.", e); - } - } - - @Override - public boolean thenMutate(RowMutations mutation) throws IOException { - checkCmpOp(); - try { - return checkAndMutation(row, family, qualifier, getCompareOp(cmpOp), value, - timeRange, mutation); - } catch (Exception e) { - logger.error(LCD.convert("01-00005"), mutation, tableNameString, e); - throw new IOException("checkAndMutate type table: " + tableNameString + " e.msg: " - + e.getMessage() + " error.", e); - } - } - - private void checkCmpOp() { - checkNotNull(this.cmpOp, - "The compare condition is null. Please use" - + " ifNotExists/ifEquals/ifMatches before executing the request"); - } - } -} \ No newline at end of file +} diff --git a/src/main/java/com/alipay/oceanbase/hbase/OHTableClient.java b/src/main/java/com/alipay/oceanbase/hbase/OHTableClient.java index 8a2c2f89..122b7756 100644 --- a/src/main/java/com/alipay/oceanbase/hbase/OHTableClient.java +++ b/src/main/java/com/alipay/oceanbase/hbase/OHTableClient.java @@ -23,6 +23,7 @@ import com.google.protobuf.Service; import com.google.protobuf.ServiceException; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.CompareOperator; import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.*; @@ -35,8 +36,11 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; +import static com.alipay.oceanbase.hbase.OHTable.getCompareOp; + public class OHTableClient implements Table, Lifecycle { private byte[] tableName; private String tableNameString; @@ -174,9 +178,15 @@ public boolean checkAndMutate(byte[] row, byte[] family, byte[] qualifier, } @Override - public CheckAndMutateBuilder checkAndMutate(byte[] row, byte[] family) { + public boolean checkAndMutate(byte[] row, byte[] family, byte[] qualifier, CompareOperator op, + byte[] value, RowMutations mutation) throws IOException { + return checkAndMutate(row, family, qualifier, getCompareOp(op), value, mutation); + } + + @Override + public long getRpcTimeout(TimeUnit unit) { checkStatus(); - return ohTable.checkAndMutate(row, family); + return ohTable.getRpcTimeout(unit); } @Override @@ -197,6 +207,48 @@ public void setRpcTimeout(int i) { ohTable.setRpcTimeout(i); } + @Override + public long getReadRpcTimeout(TimeUnit unit) { + checkStatus(); + return ohTable.getReadRpcTimeout(unit); + } + + @Override + public int getReadRpcTimeout() { + checkStatus(); + return ohTable.getReadRpcTimeout(); + } + + @Override + public void setReadRpcTimeout(int readRpcTimeout) { + checkStatus(); + ohTable.setReadRpcTimeout(readRpcTimeout); + } + + @Override + public long getWriteRpcTimeout(TimeUnit unit) { + checkStatus(); + return ohTable.getWriteRpcTimeout(unit); + } + + @Override + public int getWriteRpcTimeout() { + checkStatus(); + return ohTable.getWriteRpcTimeout(); + } + + @Override + public void setWriteRpcTimeout(int writeRpcTimeout) { + checkStatus(); + ohTable.setWriteRpcTimeout(writeRpcTimeout); + } + + @Override + public long getOperationTimeout(TimeUnit unit) { + checkStatus(); + return ohTable.getOperationTimeout(unit); + } + @Override public int getRpcTimeout() { checkStatus(); @@ -323,6 +375,12 @@ public boolean checkAndPut(byte[] row, byte[] family, byte[] qualifier, return ohTable.checkAndPut(row, family, qualifier, compareOp, value, put); } + @Override + public boolean checkAndPut(byte[] row, byte[] family, byte[] qualifier, CompareOperator op, + byte[] value, Put put) throws IOException { + return checkAndPut(row, family, qualifier, getCompareOp(op), value, put); + } + @Override public void delete(Delete delete) throws IOException { checkStatus(); @@ -350,6 +408,12 @@ public boolean checkAndDelete(byte[] row, byte[] family, byte[] qualifier, return ohTable.checkAndDelete(row, family, qualifier, compareOp, value, delete); } + @Override + public boolean checkAndDelete(byte[] row, byte[] family, byte[] qualifier, CompareOperator op, + byte[] value, Delete delete) throws IOException { + return ohTable.checkAndDelete(row, family, qualifier, getCompareOp(op), value, delete); + } + // Not support. @Override public void mutateRow(RowMutations rm) throws IOException { diff --git a/src/main/java/com/alipay/oceanbase/hbase/OHTablePool.java b/src/main/java/com/alipay/oceanbase/hbase/OHTablePool.java index 2214321e..5e01b8fe 100644 --- a/src/main/java/com/alipay/oceanbase/hbase/OHTablePool.java +++ b/src/main/java/com/alipay/oceanbase/hbase/OHTablePool.java @@ -25,6 +25,7 @@ import com.google.protobuf.Service; import com.google.protobuf.ServiceException; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.CompareOperator; import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.*; @@ -42,7 +43,9 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; +import static com.alipay.oceanbase.hbase.OHTable.getCompareOp; import static com.alipay.oceanbase.hbase.constants.OHConstants.*; import static org.apache.hadoop.hbase.HConstants.DEFAULT_HBASE_CLIENT_OPERATION_TIMEOUT; @@ -802,6 +805,12 @@ public boolean checkAndPut(byte[] row, byte[] family, byte[] qualifier, return table.checkAndPut(row, family, qualifier, compareOp, value, put); } + @Override + public boolean checkAndPut(byte[] row, byte[] family, byte[] qualifier, CompareOperator op, + byte[] value, Put put) throws IOException { + return checkAndPut(row, family, qualifier, getCompareOp(op), value, put); + } + @Override public void delete(Delete delete) throws IOException { table.delete(delete); @@ -826,8 +835,10 @@ public boolean checkAndDelete(byte[] row, byte[] family, byte[] qualifier, } @Override - public CheckAndMutateBuilder checkAndMutate(byte[] row, byte[] family) { - return table.checkAndMutate(row, family); + public boolean checkAndDelete(byte[] row, byte[] family, byte[] qualifier, + CompareOperator op, byte[] value, Delete delete) + throws IOException { + return checkAndDelete(row, family, qualifier, getCompareOp(op), value, delete); } @Override @@ -847,11 +858,6 @@ public long incrementColumnValue(byte[] row, byte[] family, byte[] qualifier, lo return table.incrementColumnValue(row, family, qualifier, amount, durability); } - /** - * Returns the actual table back to the pool - * - * @throws IOException if failed - */ public void close() throws IOException { returnTable(table); } @@ -935,6 +941,27 @@ public boolean checkAndMutate(byte[] row, byte[] family, byte[] qualifier, return table.checkAndMutate(row, family, qualifier, compareOp, value, mutations); } + @Override + public boolean checkAndMutate(byte[] row, byte[] family, byte[] qualifier, + CompareOperator op, byte[] value, RowMutations mutation) + throws IOException { + return checkAndMutate(row, family, qualifier, getCompareOp(op), value, mutation); + } + + /** + * Get timeout of each rpc request in this Table instance. It will be overridden by a more + * specific rpc timeout config such as readRpcTimeout or writeRpcTimeout. + * + * @param unit the unit of time the timeout to be represented in + * @return rpc timeout in the specified time unit + * @see #getReadRpcTimeout(TimeUnit) + * @see #getWriteRpcTimeout(TimeUnit) + */ + @Override + public long getRpcTimeout(TimeUnit unit) { + return getRpcTimeout(); + } + @Override public void setOperationTimeout(int i) { table.setOperationTimeout(i); @@ -950,6 +977,89 @@ public void setRpcTimeout(int i) { table.setRpcTimeout(i); } + /** + * Get timeout of each rpc read request in this Table instance. + * + * @param unit the unit of time the timeout to be represented in + * @return read rpc timeout in the specified time unit + */ + @Override + public long getReadRpcTimeout(TimeUnit unit) { + return table.getReadRpcTimeout(unit); + } + + /** + * Get timeout (millisecond) of each rpc read request in this Table instance. + * + * @deprecated since 2.0 and will be removed in 3.0 version + * use {@link #getReadRpcTimeout(TimeUnit)} instead + */ + @Override + public int getReadRpcTimeout() { + return table.getReadRpcTimeout(); + } + + /** + * Set timeout (millisecond) of each rpc read request in operations of this Table instance, will + * override the value of hbase.rpc.read.timeout in configuration. + * If a rpc read request waiting too long, it will stop waiting and send a new request to retry + * until retries exhausted or operation timeout reached. + * + * @param readRpcTimeout the timeout for read rpc request in milliseconds + * @deprecated since 2.0.0, use {@link TableBuilder#setReadRpcTimeout} instead + */ + @Override + public void setReadRpcTimeout(int readRpcTimeout) { + table.setReadRpcTimeout(readRpcTimeout); + } + + /** + * Get timeout of each rpc write request in this Table instance. + * + * @param unit the unit of time the timeout to be represented in + * @return write rpc timeout in the specified time unit + */ + @Override + public long getWriteRpcTimeout(TimeUnit unit) { + return table.getWriteRpcTimeout(unit); + } + + /** + * Get timeout (millisecond) of each rpc write request in this Table instance. + * + * @deprecated since 2.0 and will be removed in 3.0 version + * use {@link #getWriteRpcTimeout(TimeUnit)} instead + */ + @Override + public int getWriteRpcTimeout() { + return table.getWriteRpcTimeout(); + } + + /** + * Set timeout (millisecond) of each rpc write request in operations of this Table instance, will + * override the value of hbase.rpc.write.timeout in configuration. + * If a rpc write request waiting too long, it will stop waiting and send a new request to retry + * until retries exhausted or operation timeout reached. + * + * @param writeRpcTimeout the timeout for write rpc request in milliseconds + * @deprecated since 2.0.0, use {@link TableBuilder#setWriteRpcTimeout} instead + */ + @Override + public void setWriteRpcTimeout(int writeRpcTimeout) { + table.setWriteRpcTimeout(writeRpcTimeout); + } + + /** + * Get timeout of each operation in Table instance. + * + * @param unit the unit of time the timeout to be represented in + * @return operation rpc timeout in the specified time unit + */ + @Override + public long getOperationTimeout(TimeUnit unit) { + return table.getOperationTimeout(unit); + } + @Override public int getRpcTimeout() { return table.getRpcTimeout(); diff --git a/src/main/java/com/alipay/oceanbase/hbase/constants/OHConstants.java b/src/main/java/com/alipay/oceanbase/hbase/constants/OHConstants.java index deb94f75..a69aa7c5 100644 --- a/src/main/java/com/alipay/oceanbase/hbase/constants/OHConstants.java +++ b/src/main/java/com/alipay/oceanbase/hbase/constants/OHConstants.java @@ -127,7 +127,7 @@ public final class OHConstants { /** * use to specify whether to query only the data in hot storage when performing a query. */ - public static final String HBASE_HTABLE_QUERY_HOT_ONLY = "hbase.htable.query.hot_only"; + public static final String HBASE_HTABLE_QUERY_HOT_ONLY = "hbase.htable.query.hot_only"; /*-------------------------------------------------------------------------------------------------------------*/ diff --git a/src/main/java/com/alipay/oceanbase/hbase/execute/AbstractObTableMetaExecutor.java b/src/main/java/com/alipay/oceanbase/hbase/execute/AbstractObTableMetaExecutor.java index d6d99da1..30558872 100644 --- a/src/main/java/com/alipay/oceanbase/hbase/execute/AbstractObTableMetaExecutor.java +++ b/src/main/java/com/alipay/oceanbase/hbase/execute/AbstractObTableMetaExecutor.java @@ -1,3 +1,20 @@ +/*- + * #%L + * com.oceanbase:obkv-hbase-client + * %% + * Copyright (C) 2022 - 2025 OceanBase Group + * %% + * OBKV HBase Client Framework is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * #L% + */ + package com.alipay.oceanbase.hbase.execute; import com.alipay.oceanbase.rpc.ObTableClient; @@ -18,10 +35,7 @@ public T execute(ObTableClient client, ObTableMetaRequest request) throws IOExce ObTable table = client.getRandomTable(); ObTableMetaResponse response; try { - response = (ObTableMetaResponse) client.executeWithRetry( - table, - request, - null /*tableName*/ + response = (ObTableMetaResponse) client.executeWithRetry(table, request, null /*tableName*/ ); } catch (Exception e) { throw new IOException("Failed to execute request", e); diff --git a/src/main/java/com/alipay/oceanbase/hbase/execute/ObTableMetaExecutor.java b/src/main/java/com/alipay/oceanbase/hbase/execute/ObTableMetaExecutor.java index 4e8a0ffb..bef2211d 100644 --- a/src/main/java/com/alipay/oceanbase/hbase/execute/ObTableMetaExecutor.java +++ b/src/main/java/com/alipay/oceanbase/hbase/execute/ObTableMetaExecutor.java @@ -1,3 +1,20 @@ +/*- + * #%L + * com.oceanbase:obkv-hbase-client + * %% + * Copyright (C) 2022 - 2025 OceanBase Group + * %% + * OBKV HBase Client Framework is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * #L% + */ + package com.alipay.oceanbase.hbase.execute; import com.alipay.oceanbase.rpc.ObTableClient; @@ -8,25 +25,9 @@ import java.io.IOException; public interface ObTableMetaExecutor { - /** - * 执行元数据请求 - * @param request 元数据请求 - * @return 解析后的元数据对象 - * @throws IOException 如果执行失败或解析失败 - */ T execute(ObTableClient client, ObTableMetaRequest request) throws IOException; - /** - * 解析元数据响应, 用户需要重写 - * @param response 元数据响应 - * @return 解析后的元数据对象 - * @throws IOException 如果解析失败 - */ T parse(ObTableMetaResponse response) throws IOException; - /** - * 获取元信息类型, 用户需要重写 - * @return 元信息类型 - */ ObTableRpcMetaType getMetaType() throws IOException; } diff --git a/src/main/java/com/alipay/oceanbase/hbase/filter/HBaseFilterUtils.java b/src/main/java/com/alipay/oceanbase/hbase/filter/HBaseFilterUtils.java index a791d7f7..6849249b 100644 --- a/src/main/java/com/alipay/oceanbase/hbase/filter/HBaseFilterUtils.java +++ b/src/main/java/com/alipay/oceanbase/hbase/filter/HBaseFilterUtils.java @@ -76,8 +76,6 @@ private static void toParseableByteArray(ByteArrayOutputStream byteStream, Filte toParseableByteArray(byteStream, (FuzzyRowFilter) filter); } else if (filter instanceof TimestampsFilter) { toParseableByteArray(byteStream, (TimestampsFilter) filter); - } else if (filter instanceof ColumnValueFilter) { - toParseableByteArray(byteStream, (ColumnValueFilter) filter); } else if (filter instanceof MultiRowRangeFilter) { toParseableByteArray(byteStream, (MultiRowRangeFilter) filter); } else if (filter instanceof InclusiveStopFilter) { @@ -354,22 +352,6 @@ private static void toParseableByteArray(ByteArrayOutputStream byteStream, Times byteStream.write(')'); } - // ColumnValueFilter('cf','q') - private static void toParseableByteArray(ByteArrayOutputStream byteStream, - ColumnValueFilter filter) throws IOException { - byteStream.write(filter.getClass().getSimpleName().getBytes()); - byteStream.write('('); - byteStream.write("'".getBytes()); - writeBytesWithEscape(byteStream, filter.getFamily()); - byteStream.write("','".getBytes()); - writeBytesWithEscape(byteStream, filter.getQualifier()); - byteStream.write("',".getBytes()); - byteStream.write(toParseableByteArray(filter.getCompareOperator())); - byteStream.write(','); - toParseableByteArray(byteStream, filter.getComparator()); - byteStream.write(')'); - } - // MultiRowRangeFilter('a',true,'b',false,'c',true,'d',false); private static void toParseableByteArray(ByteArrayOutputStream byteStream, MultiRowRangeFilter filter) throws IOException { diff --git a/src/main/java/com/alipay/oceanbase/hbase/result/ClientStreamScanner.java b/src/main/java/com/alipay/oceanbase/hbase/result/ClientStreamScanner.java index dca76d20..be880fa0 100644 --- a/src/main/java/com/alipay/oceanbase/hbase/result/ClientStreamScanner.java +++ b/src/main/java/com/alipay/oceanbase/hbase/result/ClientStreamScanner.java @@ -29,7 +29,6 @@ import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hbase.util.Bytes; -import org.mortbay.util.SingletonList; import org.slf4j.Logger; import java.io.IOException; import java.nio.ByteBuffer; diff --git a/src/main/java/com/alipay/oceanbase/hbase/util/OHAdmin.java b/src/main/java/com/alipay/oceanbase/hbase/util/OHAdmin.java index add7434c..d27a3f30 100644 --- a/src/main/java/com/alipay/oceanbase/hbase/util/OHAdmin.java +++ b/src/main/java/com/alipay/oceanbase/hbase/util/OHAdmin.java @@ -1,10 +1,30 @@ +/*- + * #%L + * com.oceanbase:obkv-hbase-client + * %% + * Copyright (C) 2022 - 2025 OceanBase Group + * %% + * OBKV HBase Client Framework is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * #L% + */ + package com.alipay.oceanbase.hbase.util; import com.alipay.oceanbase.rpc.ObTableClient; import com.alipay.oceanbase.rpc.bolt.transport.TransportCodes; import com.alipay.oceanbase.hbase.exception.FeatureNotSupportedException; +import com.alipay.oceanbase.rpc.exception.ObTableException; import com.alipay.oceanbase.rpc.exception.ObTableTransportException; import com.alipay.oceanbase.rpc.meta.ObTableRpcMetaType; +import org.apache.commons.cli.Option; +import com.alipay.oceanbase.rpc.protocol.payload.ResultCodes; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.*; import org.apache.hadoop.hbase.client.*; @@ -16,7 +36,6 @@ import org.apache.hadoop.hbase.quotas.QuotaRetriever; import org.apache.hadoop.hbase.quotas.QuotaSettings; import org.apache.hadoop.hbase.regionserver.wal.FailedLogCloseException; -import org.apache.hadoop.hbase.replication.ReplicationException; import org.apache.hadoop.hbase.replication.ReplicationPeerConfig; import org.apache.hadoop.hbase.replication.ReplicationPeerDescription; import org.apache.hadoop.hbase.snapshot.HBaseSnapshotException; @@ -34,6 +53,7 @@ public class OHAdmin implements Admin { private boolean aborted = false; private final OHConnectionImpl connection; private final Configuration conf; + OHAdmin(OHConnectionImpl connection) { this.connection = connection; this.conf = connection.getConfiguration(); @@ -63,10 +83,28 @@ public Connection getConnection() { @Override public boolean tableExists(TableName tableName) throws IOException { - OHConnectionConfiguration connectionConf = new OHConnectionConfiguration(conf); - ObTableClient tableClient = ObTableClientManager.getOrCreateObTableClientByTableName(tableName, connectionConf); - OHTableExistsExecutor executor = new OHTableExistsExecutor(tableClient); - return executor.tableExists(tableName.getNameAsString()); + try { + OHConnectionConfiguration connectionConf = new OHConnectionConfiguration(conf); + ObTableClient tableClient = ObTableClientManager.getOrCreateObTableClientByTableName( + tableName, connectionConf); + OHTableExistsExecutor executor = new OHTableExistsExecutor(tableClient); + return executor.tableExists(tableName.getNameAsString()); + } catch (Exception e) { + // try to get the original cause + Throwable cause = e.getCause(); + while (cause != null && cause.getCause() != null) { + cause = cause.getCause(); + } + if (cause instanceof ObTableException) { + int errCode = ((ObTableException) cause).getErrorCode(); + // if the original cause is database_not_exist, means namespace in tableName does not exist + // for HBase, namespace not exist will not throw exceptions but will return false + if (errCode == ResultCodes.OB_ERR_BAD_DATABASE.errorCode) { + return false; + } + } + throw e; + } } @Override @@ -100,7 +138,8 @@ public HTableDescriptor[] listTables(Pattern pattern, boolean b) throws IOExcept } @Override - public List listTableDescriptors(Pattern pattern, boolean b) throws IOException { + public List listTableDescriptors(Pattern pattern, boolean b) + throws IOException { throw new FeatureNotSupportedException("does not support yet"); } @@ -135,15 +174,18 @@ public TableName[] listTableNames(String s, boolean b) throws IOException { } @Override - public HTableDescriptor getTableDescriptor(TableName tableName) throws TableNotFoundException, IOException { + public HTableDescriptor getTableDescriptor(TableName tableName) throws TableNotFoundException, + IOException { OHConnectionConfiguration connectionConf = new OHConnectionConfiguration(conf); - ObTableClient tableClient = ObTableClientManager.getOrCreateObTableClientByTableName(tableName, connectionConf); - OHTableDescriptorExecutor executor = new OHTableDescriptorExecutor(tableName.getNameAsString(), tableClient); + ObTableClient tableClient = ObTableClientManager.getOrCreateObTableClientByTableName( + tableName, connectionConf); + OHTableDescriptorExecutor executor = new OHTableDescriptorExecutor( + tableName.getNameAsString(), tableClient); try { return executor.getTableDescriptor(); } catch (IOException e) { if (e.getCause() instanceof ObTableTransportException - && ((ObTableTransportException) e.getCause()).getErrorCode() == TransportCodes.BOLT_TIMEOUT) { + && ((ObTableTransportException) e.getCause()).getErrorCode() == TransportCodes.BOLT_TIMEOUT) { throw new TimeoutIOException(e.getCause()); } else if (e.getCause().getMessage().contains("OB_TABLEGROUP_NOT_EXIST")) { throw new TableNotFoundException(tableName); @@ -156,13 +198,15 @@ public HTableDescriptor getTableDescriptor(TableName tableName) throws TableNotF @Override public TableDescriptor getDescriptor(TableName tableName) throws IOException { OHConnectionConfiguration connectionConf = new OHConnectionConfiguration(conf); - ObTableClient tableClient = ObTableClientManager.getOrCreateObTableClientByTableName(tableName, connectionConf); - OHTableDescriptorExecutor executor = new OHTableDescriptorExecutor(tableName.getNameAsString(), tableClient); + ObTableClient tableClient = ObTableClientManager.getOrCreateObTableClientByTableName( + tableName, connectionConf); + OHTableDescriptorExecutor executor = new OHTableDescriptorExecutor( + tableName.getNameAsString(), tableClient); try { return executor.getTableDescriptor(); } catch (IOException e) { if (e.getCause() instanceof ObTableTransportException - && ((ObTableTransportException) e.getCause()).getErrorCode() == TransportCodes.BOLT_TIMEOUT) { + && ((ObTableTransportException) e.getCause()).getErrorCode() == TransportCodes.BOLT_TIMEOUT) { throw new TimeoutIOException(e.getCause()); } else if (e.getCause().getMessage().contains("OB_TABLEGROUP_NOT_EXIST")) { throw new TableNotFoundException(tableName); @@ -174,24 +218,25 @@ public TableDescriptor getDescriptor(TableName tableName) throws IOException { @Override public void createTable(TableDescriptor tableDescriptor) throws IOException { - throw new FeatureNotSupportedException("does not support yet"); -// OHConnectionConfiguration connectionConf = new OHConnectionConfiguration(conf); -// ObTableClient tableClient = ObTableClientManager.getOrCreateObTableClientByTableName(tableDescriptor.getTableName(), connectionConf); -// OHCreateTableExecutor executor = new OHCreateTableExecutor(tableClient); -// try { -// executor.createTable(tableDescriptor, null); -// } catch (IOException e) { -// if (e.getCause() instanceof ObTableTransportException -// && ((ObTableTransportException) e.getCause()).getErrorCode() == TransportCodes.BOLT_TIMEOUT) { -// throw new TimeoutIOException(e.getCause()); -// } else { -// throw e; -// } -// } + OHConnectionConfiguration connectionConf = new OHConnectionConfiguration(conf); + ObTableClient tableClient = ObTableClientManager.getOrCreateObTableClientByTableName( + tableDescriptor.getTableName(), connectionConf); + OHCreateTableExecutor executor = new OHCreateTableExecutor(tableClient); + try { + executor.createTable(tableDescriptor, null); + } catch (IOException e) { + if (e.getCause() instanceof ObTableTransportException + && ((ObTableTransportException) e.getCause()).getErrorCode() == TransportCodes.BOLT_TIMEOUT) { + throw new TimeoutIOException(e.getCause()); + } else { + throw e; + } + } } @Override - public void createTable(TableDescriptor tableDescriptor, byte[] bytes, byte[] bytes1, int i) throws IOException { + public void createTable(TableDescriptor tableDescriptor, byte[] bytes, byte[] bytes1, int i) + throws IOException { throw new FeatureNotSupportedException("does not support yet"); } @@ -201,26 +246,27 @@ public void createTable(TableDescriptor tableDescriptor, byte[][] bytes) throws } @Override - public Future createTableAsync(TableDescriptor tableDescriptor, byte[][] bytes) throws IOException { + public Future createTableAsync(TableDescriptor tableDescriptor, byte[][] bytes) + throws IOException { throw new FeatureNotSupportedException("does not support yet"); } @Override public void deleteTable(TableName tableName) throws IOException { - throw new FeatureNotSupportedException("does not support yet"); -// OHConnectionConfiguration connectionConf = new OHConnectionConfiguration(conf); -// ObTableClient tableClient = ObTableClientManager.getOrCreateObTableClientByTableName(tableName, connectionConf); -// OHDeleteTableExecutor executor = new OHDeleteTableExecutor(tableClient); -// try { -// executor.deleteTable(tableName.getNameAsString()); -// } catch (IOException e) { -// if (e.getCause() instanceof ObTableTransportException -// && ((ObTableTransportException) e.getCause()).getErrorCode() == TransportCodes.BOLT_TIMEOUT) { -// throw new TimeoutIOException(e.getCause()); -// } else { -// throw e; -// } -// } + OHConnectionConfiguration connectionConf = new OHConnectionConfiguration(conf); + ObTableClient tableClient = ObTableClientManager.getOrCreateObTableClientByTableName( + tableName, connectionConf); + OHDeleteTableExecutor executor = new OHDeleteTableExecutor(tableClient); + try { + executor.deleteTable(tableName.getNameAsString()); + } catch (IOException e) { + if (e.getCause() instanceof ObTableTransportException + && ((ObTableTransportException) e.getCause()).getErrorCode() == TransportCodes.BOLT_TIMEOUT) { + throw new TimeoutIOException(e.getCause()); + } else { + throw e; + } + } } @Override @@ -250,20 +296,21 @@ public Future truncateTableAsync(TableName tableName, boolean b) throws IO @Override public void enableTable(TableName tableName) throws IOException { - throw new FeatureNotSupportedException("does not support yet"); -// OHConnectionConfiguration connectionConf = new OHConnectionConfiguration(conf); -// ObTableClient tableClient = ObTableClientManager.getOrCreateObTableClientByTableName(tableName, connectionConf); -// OHTableAccessControlExecutor executor = new OHTableAccessControlExecutor(tableClient, ObTableRpcMetaType.HTABLE_ENABLE_TABLE); -// try { -// executor.enableTable(tableName.getNameAsString()); -// } catch (IOException e) { -// if (e.getCause() instanceof ObTableTransportException -// && ((ObTableTransportException) e.getCause()).getErrorCode() == TransportCodes.BOLT_TIMEOUT) { -// throw new TimeoutIOException(e.getCause()); -// } else { -// throw e; -// } -// } + OHConnectionConfiguration connectionConf = new OHConnectionConfiguration(conf); + ObTableClient tableClient = ObTableClientManager.getOrCreateObTableClientByTableName( + tableName, connectionConf); + OHTableAccessControlExecutor executor = new OHTableAccessControlExecutor(tableClient, + ObTableRpcMetaType.HTABLE_ENABLE_TABLE); + try { + executor.enableTable(tableName.getNameAsString()); + } catch (IOException e) { + if (e.getCause() instanceof ObTableTransportException + && ((ObTableTransportException) e.getCause()).getErrorCode() == TransportCodes.BOLT_TIMEOUT) { + throw new TimeoutIOException(e.getCause()); + } else { + throw e; + } + } } @Override @@ -289,13 +336,15 @@ public Future disableTableAsync(TableName tableName) throws IOException { @Override public void disableTable(TableName tableName) throws IOException { OHConnectionConfiguration connectionConf = new OHConnectionConfiguration(conf); - ObTableClient tableClient = ObTableClientManager.getOrCreateObTableClientByTableName(tableName, connectionConf); - OHTableAccessControlExecutor executor = new OHTableAccessControlExecutor(tableClient, ObTableRpcMetaType.HTABLE_DISABLE_TABLE); + ObTableClient tableClient = ObTableClientManager.getOrCreateObTableClientByTableName( + tableName, connectionConf); + OHTableAccessControlExecutor executor = new OHTableAccessControlExecutor(tableClient, + ObTableRpcMetaType.HTABLE_DISABLE_TABLE); try { executor.disableTable(tableName.getNameAsString()); } catch (IOException e) { if (e.getCause() instanceof ObTableTransportException - && ((ObTableTransportException) e.getCause()).getErrorCode() == TransportCodes.BOLT_TIMEOUT) { + && ((ObTableTransportException) e.getCause()).getErrorCode() == TransportCodes.BOLT_TIMEOUT) { throw new TimeoutIOException(e.getCause()); } else { throw e; @@ -315,20 +364,20 @@ public HTableDescriptor[] disableTables(Pattern pattern) throws IOException { @Override public boolean isTableEnabled(TableName tableName) throws IOException { - throw new FeatureNotSupportedException("does not support yet"); -// return isDisabled(tableName) == false; + return isDisabled(tableName) == false; } @Override public boolean isTableDisabled(TableName tableName) throws IOException { - throw new FeatureNotSupportedException("does not support yet"); -// return isDisabled(tableName) == true; + return isDisabled(tableName) == true; } private boolean isDisabled(TableName tableName) throws IOException { OHConnectionConfiguration connectionConf = new OHConnectionConfiguration(conf); - ObTableClient tableClient = ObTableClientManager.getOrCreateObTableClientByTableName(tableName, connectionConf); - OHTableDescriptorExecutor tableDescriptor = new OHTableDescriptorExecutor(tableName.getNameAsString(), tableClient); + ObTableClient tableClient = ObTableClientManager.getOrCreateObTableClientByTableName( + tableName, connectionConf); + OHTableDescriptorExecutor tableDescriptor = new OHTableDescriptorExecutor( + tableName.getNameAsString(), tableClient); return tableDescriptor.isDisable(); } @@ -353,12 +402,15 @@ public Pair getAlterStatus(byte[] bytes) throws IOException { } @Override - public void addColumnFamily(TableName tableName, ColumnFamilyDescriptor columnFamilyDescriptor) throws IOException { + public void addColumnFamily(TableName tableName, ColumnFamilyDescriptor columnFamilyDescriptor) + throws IOException { throw new FeatureNotSupportedException("does not support yet"); } @Override - public Future addColumnFamilyAsync(TableName tableName, ColumnFamilyDescriptor columnFamilyDescriptor) throws IOException { + public Future addColumnFamilyAsync(TableName tableName, + ColumnFamilyDescriptor columnFamilyDescriptor) + throws IOException { throw new FeatureNotSupportedException("does not support yet"); } @@ -373,17 +425,22 @@ public void deleteColumnFamily(TableName tableName, byte[] bytes) throws IOExcep } @Override - public Future deleteColumnFamilyAsync(TableName tableName, byte[] bytes) throws IOException { + public Future deleteColumnFamilyAsync(TableName tableName, byte[] bytes) + throws IOException { throw new FeatureNotSupportedException("does not support yet"); } @Override - public void modifyColumnFamily(TableName tableName, ColumnFamilyDescriptor columnFamilyDescriptor) throws IOException { + public void modifyColumnFamily(TableName tableName, + ColumnFamilyDescriptor columnFamilyDescriptor) + throws IOException { throw new FeatureNotSupportedException("does not support yet"); } @Override - public Future modifyColumnFamilyAsync(TableName tableName, ColumnFamilyDescriptor columnFamilyDescriptor) throws IOException { + public Future modifyColumnFamilyAsync(TableName tableName, + ColumnFamilyDescriptor columnFamilyDescriptor) + throws IOException { throw new FeatureNotSupportedException("does not support yet"); } @@ -427,11 +484,6 @@ public void flushRegion(byte[] bytes) throws IOException { throw new FeatureNotSupportedException("does not support yet"); } - @Override - public void flushRegionServer(ServerName serverName) throws IOException { - throw new FeatureNotSupportedException("does not support yet"); - } - @Override public void compact(TableName tableName) throws IOException { throw new FeatureNotSupportedException("does not support yet"); @@ -453,12 +505,15 @@ public void compactRegion(byte[] bytes, byte[] bytes1) throws IOException { } @Override - public void compact(TableName tableName, CompactType compactType) throws IOException, InterruptedException { + public void compact(TableName tableName, CompactType compactType) throws IOException, + InterruptedException { throw new FeatureNotSupportedException("does not support yet"); } @Override - public void compact(TableName tableName, byte[] bytes, CompactType compactType) throws IOException, InterruptedException { + public void compact(TableName tableName, byte[] bytes, CompactType compactType) + throws IOException, + InterruptedException { throw new FeatureNotSupportedException("does not support yet"); } @@ -482,23 +537,32 @@ public void majorCompactRegion(byte[] bytes, byte[] bytes1) throws IOException { throw new FeatureNotSupportedException("does not support yet"); } + /** + * Compact all regions on the region server. Asynchronous operation in that this method requests + * that a Compaction run and then it returns. It does not wait on the completion of Compaction + * (it can take a while). + * + * @param sn the region server name + * @param major if it's major compaction + * @throws IOException + * @throws InterruptedException + */ @Override - public void majorCompact(TableName tableName, CompactType compactType) throws IOException, InterruptedException { - throw new FeatureNotSupportedException("does not support yet"); - } - - @Override - public void majorCompact(TableName tableName, byte[] bytes, CompactType compactType) throws IOException, InterruptedException { + public void compactRegionServer(ServerName sn, boolean major) throws IOException, + InterruptedException { throw new FeatureNotSupportedException("does not support yet"); } @Override - public void compactRegionServer(ServerName serverName) throws IOException { + public void majorCompact(TableName tableName, CompactType compactType) throws IOException, + InterruptedException { throw new FeatureNotSupportedException("does not support yet"); } @Override - public void majorCompactRegionServer(ServerName serverName) throws IOException { + public void majorCompact(TableName tableName, byte[] bytes, CompactType compactType) + throws IOException, + InterruptedException { throw new FeatureNotSupportedException("does not support yet"); } @@ -542,11 +606,6 @@ public boolean isBalancerEnabled() throws IOException { throw new FeatureNotSupportedException("does not support yet"); } - @Override - public CacheEvictionStats clearBlockCache(TableName tableName) throws IOException { - throw new FeatureNotSupportedException("does not support yet"); - } - @Override public boolean normalize() throws IOException { throw new FeatureNotSupportedException("does not support yet"); @@ -598,7 +657,8 @@ public void mergeRegions(byte[] bytes, byte[] bytes1, boolean b) throws IOExcept } @Override - public Future mergeRegionsAsync(byte[] bytes, byte[] bytes1, boolean b) throws IOException { + public Future mergeRegionsAsync(byte[] bytes, byte[] bytes1, boolean b) + throws IOException { throw new FeatureNotSupportedException("does not support yet"); } @@ -633,7 +693,8 @@ public Future splitRegionAsync(byte[] bytes, byte[] bytes1) throws IOExcep } @Override - public void modifyTable(TableName tableName, TableDescriptor tableDescriptor) throws IOException { + public void modifyTable(TableName tableName, TableDescriptor tableDescriptor) + throws IOException { throw new FeatureNotSupportedException("does not support yet"); } @@ -643,7 +704,8 @@ public void modifyTable(TableDescriptor tableDescriptor) throws IOException { } @Override - public Future modifyTableAsync(TableName tableName, TableDescriptor tableDescriptor) throws IOException { + public Future modifyTableAsync(TableName tableName, TableDescriptor tableDescriptor) + throws IOException { throw new FeatureNotSupportedException("does not support yet"); } @@ -672,25 +734,67 @@ public void stopRegionServer(String s) throws IOException { throw new FeatureNotSupportedException("does not support yet"); } + /** + * Get whole cluster status, containing status about: + *
+     * hbase version
+     * cluster id
+     * primary/backup master(s)
+     * master's coprocessors
+     * live/dead regionservers
+     * balancer
+     * regions in transition
+     * 
+ * + * @return cluster status + * @throws IOException if a remote or network exception occurs + */ @Override - public ClusterMetrics getClusterMetrics(EnumSet enumSet) throws IOException { + public ClusterStatus getClusterStatus() throws IOException { throw new FeatureNotSupportedException("does not support yet"); } + /** + * Get cluster status with a set of {@link Option} to get desired status. + * + * @param options + * @return cluster status + * @throws IOException if a remote or network exception occurs + */ @Override - public List getRegionMetrics(ServerName serverName) throws IOException { + public ClusterStatus getClusterStatus(EnumSet options) throws IOException { throw new FeatureNotSupportedException("does not support yet"); } + /** + * Get {@link RegionLoad} of all regions hosted on a regionserver. + * + * @param serverName region server from which regionload is required. + * @return region load map of all regions hosted on a region server + * @throws IOException if a remote or network exception occurs + */ @Override - public List getRegionMetrics(ServerName serverName, TableName tableName) throws IOException { - if (tableName == null) { - throw new FeatureNotSupportedException("does not support tableName is null"); - } + public Map getRegionLoad(ServerName serverName) throws IOException { + throw new FeatureNotSupportedException("does not support yet"); + } + + /** + * Get {@link RegionLoad} of all regions hosted on a regionserver for a table. + * + * @param serverName region server from which regionload is required. + * @param tableName get region load of regions belonging to the table + * @return region load map of all regions of a table hosted on a region server + * @throws IOException if a remote or network exception occurs + */ + @Override + public Map getRegionLoad(ServerName serverName, TableName tableName) + throws IOException { OHConnectionConfiguration connectionConf = new OHConnectionConfiguration(conf); - ObTableClient tableClient = ObTableClientManager.getOrCreateObTableClientByTableName(tableName, connectionConf); - OHRegionMetricsExecutor executor = new OHRegionMetricsExecutor(tableClient); - return executor.getRegionMetrics(tableName.getNameAsString()); + ObTableClient tableClient = ObTableClientManager.getOrCreateObTableClientByTableName( + tableName, connectionConf); + OHRegionLoadExecutor executor = new OHRegionLoadExecutor(tableName.getNameAsString(), + tableClient); + return executor.getRegionLoad(); } @Override @@ -704,7 +808,8 @@ public void createNamespace(NamespaceDescriptor namespaceDescriptor) throws IOEx } @Override - public Future createNamespaceAsync(NamespaceDescriptor namespaceDescriptor) throws IOException { + public Future createNamespaceAsync(NamespaceDescriptor namespaceDescriptor) + throws IOException { throw new FeatureNotSupportedException("does not support yet"); } @@ -714,7 +819,8 @@ public void modifyNamespace(NamespaceDescriptor namespaceDescriptor) throws IOEx } @Override - public Future modifyNamespaceAsync(NamespaceDescriptor namespaceDescriptor) throws IOException { + public Future modifyNamespaceAsync(NamespaceDescriptor namespaceDescriptor) + throws IOException { throw new FeatureNotSupportedException("does not support yet"); } @@ -729,7 +835,8 @@ public Future deleteNamespaceAsync(String s) throws IOException { } @Override - public NamespaceDescriptor getNamespaceDescriptor(String s) throws NamespaceNotFoundException, IOException { + public NamespaceDescriptor getNamespaceDescriptor(String s) throws NamespaceNotFoundException, + IOException { throw new FeatureNotSupportedException("does not support yet"); } @@ -768,7 +875,8 @@ public synchronized void close() throws IOException { } @Override - public HTableDescriptor[] getTableDescriptorsByTableName(List list) throws IOException { + public HTableDescriptor[] getTableDescriptorsByTableName(List list) + throws IOException { throw new FeatureNotSupportedException("does not support yet"); } @@ -807,13 +915,25 @@ public void rollWALWriter(ServerName serverName) throws IOException, FailedLogCl throw new FeatureNotSupportedException("does not support yet"); } + /** + * Helper that delegates to getClusterStatus().getMasterCoprocessors(). + * + * @return an array of master coprocessors + * @see ClusterStatus#getMasterCoprocessors() + */ + @Override + public String[] getMasterCoprocessors() throws IOException { + throw new FeatureNotSupportedException("does not support yet"); + } + @Override public CompactionState getCompactionState(TableName tableName) throws IOException { throw new FeatureNotSupportedException("does not support yet"); } @Override - public CompactionState getCompactionState(TableName tableName, CompactType compactType) throws IOException { + public CompactionState getCompactionState(TableName tableName, CompactType compactType) + throws IOException { throw new FeatureNotSupportedException("does not support yet"); } @@ -833,32 +953,45 @@ public long getLastMajorCompactionTimestampForRegion(byte[] bytes) throws IOExce } @Override - public void snapshot(String s, TableName tableName) throws IOException, SnapshotCreationException, IllegalArgumentException { + public void snapshot(String s, TableName tableName) throws IOException, + SnapshotCreationException, + IllegalArgumentException { throw new FeatureNotSupportedException("does not support yet"); } @Override - public void snapshot(byte[] bytes, TableName tableName) throws IOException, SnapshotCreationException, IllegalArgumentException { + public void snapshot(byte[] bytes, TableName tableName) throws IOException, + SnapshotCreationException, + IllegalArgumentException { throw new FeatureNotSupportedException("does not support yet"); } @Override - public void snapshot(String s, TableName tableName, SnapshotType snapshotType) throws IOException, SnapshotCreationException, IllegalArgumentException { + public void snapshot(String s, TableName tableName, SnapshotType snapshotType) + throws IOException, + SnapshotCreationException, + IllegalArgumentException { throw new FeatureNotSupportedException("does not support yet"); } @Override - public void snapshot(SnapshotDescription snapshotDescription) throws IOException, SnapshotCreationException, IllegalArgumentException { + public void snapshot(SnapshotDescription snapshotDescription) throws IOException, + SnapshotCreationException, + IllegalArgumentException { throw new FeatureNotSupportedException("does not support yet"); } @Override - public void snapshotAsync(SnapshotDescription snapshotDescription) throws IOException, SnapshotCreationException { + public void snapshotAsync(SnapshotDescription snapshotDescription) throws IOException, + SnapshotCreationException { throw new FeatureNotSupportedException("does not support yet"); } @Override - public boolean isSnapshotFinished(SnapshotDescription snapshotDescription) throws IOException, HBaseSnapshotException, UnknownSnapshotException { + public boolean isSnapshotFinished(SnapshotDescription snapshotDescription) + throws IOException, + HBaseSnapshotException, + UnknownSnapshotException { throw new FeatureNotSupportedException("does not support yet"); } @@ -878,7 +1011,8 @@ public Future restoreSnapshotAsync(String s) throws IOException, RestoreSn } @Override - public void restoreSnapshot(byte[] bytes, boolean b) throws IOException, RestoreSnapshotException { + public void restoreSnapshot(byte[] bytes, boolean b) throws IOException, + RestoreSnapshotException { throw new FeatureNotSupportedException("does not support yet"); } @@ -888,27 +1022,35 @@ public void restoreSnapshot(String s, boolean b) throws IOException, RestoreSnap } @Override - public void restoreSnapshot(String s, boolean b, boolean b1) throws IOException, RestoreSnapshotException { + public void restoreSnapshot(String s, boolean b, boolean b1) throws IOException, + RestoreSnapshotException { throw new FeatureNotSupportedException("does not support yet"); } @Override - public void cloneSnapshot(byte[] bytes, TableName tableName) throws IOException, TableExistsException, RestoreSnapshotException { + public void cloneSnapshot(byte[] bytes, TableName tableName) throws IOException, + TableExistsException, + RestoreSnapshotException { throw new FeatureNotSupportedException("does not support yet"); } @Override - public void cloneSnapshot(String s, TableName tableName, boolean b) throws IOException, TableExistsException, RestoreSnapshotException { + public void cloneSnapshot(String s, TableName tableName, boolean b) throws IOException, + TableExistsException, + RestoreSnapshotException { throw new FeatureNotSupportedException("does not support yet"); } @Override - public void cloneSnapshot(String s, TableName tableName) throws IOException, TableExistsException, RestoreSnapshotException { + public void cloneSnapshot(String s, TableName tableName) throws IOException, + TableExistsException, + RestoreSnapshotException { throw new FeatureNotSupportedException("does not support yet"); } @Override - public Future cloneSnapshotAsync(String s, TableName tableName) throws IOException, TableExistsException { + public Future cloneSnapshotAsync(String s, TableName tableName) throws IOException, + TableExistsException { throw new FeatureNotSupportedException("does not support yet"); } @@ -918,12 +1060,14 @@ public void execProcedure(String s, String s1, Map map) throws I } @Override - public byte[] execProcedureWithReturn(String s, String s1, Map map) throws IOException { + public byte[] execProcedureWithReturn(String s, String s1, Map map) + throws IOException { throw new FeatureNotSupportedException("does not support yet"); } @Override - public boolean isProcedureFinished(String s, String s1, Map map) throws IOException { + public boolean isProcedureFinished(String s, String s1, Map map) + throws IOException { throw new FeatureNotSupportedException("does not support yet"); } @@ -948,7 +1092,8 @@ public List listTableSnapshots(String s, String s1) throws } @Override - public List listTableSnapshots(Pattern pattern, Pattern pattern1) throws IOException { + public List listTableSnapshots(Pattern pattern, Pattern pattern1) + throws IOException { throw new FeatureNotSupportedException("does not support yet"); } @@ -992,11 +1137,6 @@ public QuotaRetriever getQuotaRetriever(QuotaFilter quotaFilter) throws IOExcept throw new FeatureNotSupportedException("does not support yet"); } - @Override - public List getQuota(QuotaFilter quotaFilter) throws IOException { - throw new FeatureNotSupportedException("does not support yet"); - } - @Override public CoprocessorRpcChannel coprocessorService() { throw new FeatureNotSupportedException("does not support yet"); @@ -1023,27 +1163,13 @@ public List getSecurityCapabilities() throws IOException { } @Override - public boolean splitSwitch(boolean b, boolean b1) throws IOException { - throw new FeatureNotSupportedException("does not support yet"); - } - - @Override - public boolean mergeSwitch(boolean b, boolean b1) throws IOException { - throw new FeatureNotSupportedException("does not support yet"); - } - - @Override - public boolean isSplitEnabled() throws IOException { + public boolean[] splitOrMergeEnabledSwitch(boolean enabled, boolean synchronous, + MasterSwitchType... switchTypes) throws IOException { throw new FeatureNotSupportedException("does not support yet"); } @Override - public boolean isMergeEnabled() throws IOException { - throw new FeatureNotSupportedException("does not support yet"); - } - - @Override - public void addReplicationPeer(String s, ReplicationPeerConfig replicationPeerConfig, boolean b) throws IOException { + public boolean splitOrMergeEnabledSwitch(MasterSwitchType switchType) throws IOException { throw new FeatureNotSupportedException("does not support yet"); } @@ -1068,17 +1194,8 @@ public ReplicationPeerConfig getReplicationPeerConfig(String s) throws IOExcepti } @Override - public void updateReplicationPeerConfig(String s, ReplicationPeerConfig replicationPeerConfig) throws IOException { - throw new FeatureNotSupportedException("does not support yet"); - } - - @Override - public void appendReplicationPeerTableCFs(String s, Map> map) throws ReplicationException, IOException { - throw new FeatureNotSupportedException("does not support yet"); - } - - @Override - public void removeReplicationPeerTableCFs(String s, Map> map) throws ReplicationException, IOException { + public void updateReplicationPeerConfig(String s, ReplicationPeerConfig replicationPeerConfig) + throws IOException { throw new FeatureNotSupportedException("does not support yet"); } @@ -1088,7 +1205,8 @@ public List listReplicationPeers() throws IOExceptio } @Override - public List listReplicationPeers(Pattern pattern) throws IOException { + public List listReplicationPeers(Pattern pattern) + throws IOException { throw new FeatureNotSupportedException("does not support yet"); } @@ -1103,7 +1221,8 @@ public List listDecommissionedRegionServers() throws IOException { } @Override - public void recommissionRegionServer(ServerName serverName, List list) throws IOException { + public void recommissionRegionServer(ServerName serverName, List list) + throws IOException { throw new FeatureNotSupportedException("does not support yet"); } @@ -1123,7 +1242,18 @@ public void disableTableReplication(TableName tableName) throws IOException { } @Override - public void clearCompactionQueues(ServerName serverName, Set set) throws IOException, InterruptedException { + public void clearCompactionQueues(ServerName serverName, Set set) throws IOException, + InterruptedException { + throw new FeatureNotSupportedException("does not support yet"); + } + + /** + * List dead region servers. + * + * @return List of dead region servers. + */ + @Override + public List listDeadServers() throws IOException { throw new FeatureNotSupportedException("does not support yet"); } diff --git a/src/main/java/com/alipay/oceanbase/hbase/util/OHBufferedMutatorImpl.java b/src/main/java/com/alipay/oceanbase/hbase/util/OHBufferedMutatorImpl.java index d6e63d40..69c8e2e7 100644 --- a/src/main/java/com/alipay/oceanbase/hbase/util/OHBufferedMutatorImpl.java +++ b/src/main/java/com/alipay/oceanbase/hbase/util/OHBufferedMutatorImpl.java @@ -19,11 +19,11 @@ import com.alipay.oceanbase.hbase.OHTable; +import com.google.common.annotations.VisibleForTesting; import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.*; -import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting; import org.slf4j.Logger; import java.io.IOException; @@ -59,7 +59,7 @@ public class OHBufferedMutatorImpl implements BufferedMutator { private final AtomicLong writeBufferPeriodicFlushTimeoutMs = new AtomicLong( 0); private final AtomicLong writeBufferPeriodicFlushTimerTickMs = new AtomicLong( - MIN_WRITE_BUFFER_PERIODIC_FLUSH_TIMERTICK_MS); + 0); private Timer writeBufferPeriodicFlushTimer = null; private final long writeBufferSize; @@ -96,14 +96,6 @@ public OHBufferedMutatorImpl(OHConnectionImpl ohConnection, BufferedMutatorParam params.getOperationTimeout() != OHConnectionImpl.BUFFERED_PARAM_UNSET ? params .getOperationTimeout() : connectionConfig.getOperationTimeout()); - long newPeriodicFlushTimeoutMs = params.getWriteBufferPeriodicFlushTimeoutMs() != OHConnectionImpl.BUFFERED_PARAM_UNSET ? params - .getWriteBufferPeriodicFlushTimeoutMs() : connectionConfig - .getWriteBufferPeriodicFlushTimeoutMs(); - long newPeriodicFlushTimeIntervalMs = params.getWriteBufferPeriodicFlushTimerTickMs() != OHConnectionImpl.BUFFERED_PARAM_UNSET ? params - .getWriteBufferPeriodicFlushTimerTickMs() : connectionConfig - .getWriteBufferPeriodicFlushTimerTickMs(); - this.setWriteBufferPeriodicFlush(newPeriodicFlushTimeoutMs, newPeriodicFlushTimeIntervalMs); - this.writeBufferSize = params.getWriteBufferSize() != OHConnectionImpl.BUFFERED_PARAM_UNSET ? params .getWriteBufferSize() : connectionConfig.getWriteBufferSize(); this.maxKeyValueSize = params.getMaxKeyValueSize() != OHConnectionImpl.BUFFERED_PARAM_UNSET ? params @@ -210,41 +202,6 @@ public void timeTriggerForWriteBufferPeriodicFlush() { } } - /** - * set time for periodic flush timer - * @param timeoutMs control when to flush from collecting first mutation - * @param timerTickMs control time interval to trigger the timer - * */ - @Override - public synchronized void setWriteBufferPeriodicFlush(long timeoutMs, long timerTickMs) { - long originalTimeoutMs = this.writeBufferPeriodicFlushTimeoutMs.get(); - long originalTimeTickMs = this.writeBufferPeriodicFlushTimerTickMs.get(); - - writeBufferPeriodicFlushTimeoutMs.set(Math.max(0, timeoutMs)); - writeBufferPeriodicFlushTimerTickMs.set(Math.max( - MIN_WRITE_BUFFER_PERIODIC_FLUSH_TIMERTICK_MS, timerTickMs)); - - // if time parameters are updated, stop the old timer - if (writeBufferPeriodicFlushTimeoutMs.get() != originalTimeoutMs - || writeBufferPeriodicFlushTimerTickMs.get() != originalTimeTickMs) { - if (writeBufferPeriodicFlushTimer != null) { - writeBufferPeriodicFlushTimer.cancel(); - writeBufferPeriodicFlushTimer = null; - } - } - - if (writeBufferPeriodicFlushTimer == null && writeBufferPeriodicFlushTimeoutMs.get() > 0) { - writeBufferPeriodicFlushTimer = new Timer(true); - writeBufferPeriodicFlushTimer.schedule(new TimerTask() { - @Override - public void run() { - OHBufferedMutatorImpl.this.timeTriggerForWriteBufferPeriodicFlush(); - } - }, this.writeBufferPeriodicFlushTimerTickMs.get(), - this.writeBufferPeriodicFlushTimerTickMs.get()); - } - } - /** * Send the operations in the buffer to the servers. Does not wait for the server's answer. If * there is an error, either throw the error, or use the listener to deal with the error. @@ -275,15 +232,11 @@ private void execute(boolean flushAll) throws IOException { // if commit all successfully, clean execBuffer execBuffer.clear(); } catch (Exception ex) { - LOGGER.error(LCD.convert("01-00026"), ex); - if (ex.getCause() instanceof RetriesExhaustedWithDetailsException) { - LOGGER.error(tableName + ": One or more of the operations have failed after retries."); - RetriesExhaustedWithDetailsException retryException = (RetriesExhaustedWithDetailsException) ex.getCause(); - // recollect failed mutations - execBuffer.clear(); - for (int i = 0; i < retryException.getNumExceptions(); ++i) { - execBuffer.add((Mutation) retryException.getRow(i)); - } + // do not recollect error operations, notify outside + LOGGER.error("error happens, table name: {}", tableName.getNameAsString(), ex); + if (ex instanceof RetriesExhaustedWithDetailsException) { + LOGGER.error("TableName: {}, One or more of the operations have failed after retries.", tableName.getNameAsString(), ex); + RetriesExhaustedWithDetailsException retryException = (RetriesExhaustedWithDetailsException) ex; if (listener != null) { listener.onException(retryException, this); } else { @@ -293,31 +246,16 @@ private void execute(boolean flushAll) throws IOException { LOGGER.error("Errors unrelated to operations occur during mutation operation", ex); throw ex; } - } finally { - for (Mutation mutation : execBuffer) { - long size = mutation.heapSize(); - currentAsyncBufferSize.addAndGet(size); - asyncWriteBuffer.add(mutation); - undealtMutationCount.incrementAndGet(); - } } } - /** - * reset the time parameters and cancel the timer (if exists) - * */ - @Override - public void disableWriteBufferPeriodicFlush() { - setWriteBufferPeriodicFlush(0, MIN_WRITE_BUFFER_PERIODIC_FLUSH_TIMERTICK_MS); - } - @Override public void close() throws IOException { if (closed) { return; } // reset timeout, timeTick and Timer - disableWriteBufferPeriodicFlush(); + // disableWriteBufferPeriodicFlush(); try { execute(true); } finally { @@ -347,16 +285,6 @@ public void flush() throws IOException { execute(true); } - @Override - public long getWriteBufferPeriodicFlushTimeoutMs() { - return writeBufferPeriodicFlushTimeoutMs.get(); - } - - @Override - public long getWriteBufferPeriodicFlushTimerTickMs() { - return writeBufferPeriodicFlushTimerTickMs.get(); - } - @Override public long getWriteBufferSize() { return this.writeBufferSize; @@ -374,9 +302,6 @@ public void setOperationTimeout(int operationTimeout) { this.ohTable.setOperationTimeout(operationTimeout); } - /** - * Count the mutations which haven't been processed. - */ @VisibleForTesting public int size() { return undealtMutationCount.get(); diff --git a/src/main/java/com/alipay/oceanbase/hbase/util/OHConnectionConfiguration.java b/src/main/java/com/alipay/oceanbase/hbase/util/OHConnectionConfiguration.java index 3c966a18..0ab83451 100644 --- a/src/main/java/com/alipay/oceanbase/hbase/util/OHConnectionConfiguration.java +++ b/src/main/java/com/alipay/oceanbase/hbase/util/OHConnectionConfiguration.java @@ -25,10 +25,6 @@ import java.util.Properties; import static com.alipay.oceanbase.hbase.constants.OHConstants.*; -import static org.apache.hadoop.hbase.client.ConnectionConfiguration.WRITE_BUFFER_PERIODIC_FLUSH_TIMEOUT_MS; -import static org.apache.hadoop.hbase.client.ConnectionConfiguration.WRITE_BUFFER_PERIODIC_FLUSH_TIMEOUT_MS_DEFAULT; -import static org.apache.hadoop.hbase.client.ConnectionConfiguration.WRITE_BUFFER_PERIODIC_FLUSH_TIMERTICK_MS; -import static org.apache.hadoop.hbase.client.ConnectionConfiguration.WRITE_BUFFER_PERIODIC_FLUSH_TIMERTICK_MS_DEFAULT; import static org.apache.commons.lang.StringUtils.isBlank; import static org.apache.hadoop.hbase.ipc.RpcClient.DEFAULT_SOCKET_TIMEOUT_CONNECT; import static org.apache.hadoop.hbase.ipc.RpcClient.SOCKET_TIMEOUT_CONNECT; @@ -55,8 +51,6 @@ public class OHConnectionConfiguration { private final int readRpcTimeout; private final int writeRpcTimeout; private final int rpcConnectTimeout; - private final long writeBufferPeriodicFlushTimeoutMs; - private final long writeBufferPeriodicFlushTimerTickMs; private final int numRetries; public OHConnectionConfiguration(Configuration conf) { @@ -84,11 +78,6 @@ public OHConnectionConfiguration(Configuration conf) { HConstants.DEFAULT_HBASE_RPC_TIMEOUT); this.writeRpcTimeout = conf.getInt(HConstants.HBASE_RPC_WRITE_TIMEOUT_KEY, HConstants.DEFAULT_HBASE_RPC_TIMEOUT); - this.writeBufferPeriodicFlushTimeoutMs = conf.getLong( - WRITE_BUFFER_PERIODIC_FLUSH_TIMEOUT_MS, WRITE_BUFFER_PERIODIC_FLUSH_TIMEOUT_MS_DEFAULT); - this.writeBufferPeriodicFlushTimerTickMs = conf.getLong( - WRITE_BUFFER_PERIODIC_FLUSH_TIMERTICK_MS, - WRITE_BUFFER_PERIODIC_FLUSH_TIMERTICK_MS_DEFAULT); int rpcConnectTimeout = -1; if (conf.get(SOCKET_TIMEOUT_CONNECT) != null) { rpcConnectTimeout = conf.getInt(SOCKET_TIMEOUT_CONNECT, DEFAULT_SOCKET_TIMEOUT_CONNECT); @@ -102,7 +91,7 @@ public OHConnectionConfiguration(Configuration conf) { } this.rpcConnectTimeout = rpcConnectTimeout; this.numRetries = conf.getInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, - HConstants.DEFAULT_HBASE_CLIENT_RETRIES_NUMBER); + HConstants.DEFAULT_HBASE_CLIENT_RETRIES_NUMBER); this.scannerCaching = conf.getInt(HConstants.HBASE_CLIENT_SCANNER_CACHING, Integer.MAX_VALUE); this.scannerMaxResultSize = conf.getLong( @@ -205,14 +194,6 @@ public String getDatabase() { return this.database; } - public long getWriteBufferPeriodicFlushTimeoutMs() { - return this.writeBufferPeriodicFlushTimeoutMs; - } - - public long getWriteBufferPeriodicFlushTimerTickMs() { - return this.writeBufferPeriodicFlushTimerTickMs; - } - public int getNumRetries() { return this.numRetries; } diff --git a/src/main/java/com/alipay/oceanbase/hbase/util/OHConnectionImpl.java b/src/main/java/com/alipay/oceanbase/hbase/util/OHConnectionImpl.java index fd666159..811feca8 100644 --- a/src/main/java/com/alipay/oceanbase/hbase/util/OHConnectionImpl.java +++ b/src/main/java/com/alipay/oceanbase/hbase/util/OHConnectionImpl.java @@ -144,8 +144,10 @@ public RegionLocator getRegionLocator(TableName tableName) throws IOException { // need to use new connection configuration // to avoid change the database in original param url by namespace in tableName OHConnectionConfiguration connectionConf = new OHConnectionConfiguration(conf); - ObTableClient obTableClient = ObTableClientManager.getOrCreateObTableClientByTableName(tableName, connectionConf); - OHRegionLocatorExecutor executor = new OHRegionLocatorExecutor(tableName.toString(), obTableClient); + ObTableClient obTableClient = ObTableClientManager.getOrCreateObTableClientByTableName( + tableName, connectionConf); + OHRegionLocatorExecutor executor = new OHRegionLocatorExecutor(tableName.toString(), + obTableClient); return executor.getRegionLocator(String.valueOf(tableName)); } diff --git a/src/main/java/com/alipay/oceanbase/hbase/util/OHCreateTableExecutor.java b/src/main/java/com/alipay/oceanbase/hbase/util/OHCreateTableExecutor.java index a56e8097..4bab8e3b 100644 --- a/src/main/java/com/alipay/oceanbase/hbase/util/OHCreateTableExecutor.java +++ b/src/main/java/com/alipay/oceanbase/hbase/util/OHCreateTableExecutor.java @@ -17,7 +17,7 @@ package com.alipay.oceanbase.hbase.util; -import com.alibaba.fastjson.JSON; +import com.fasterxml.jackson.databind.ObjectMapper; import com.alipay.oceanbase.hbase.execute.AbstractObTableMetaExecutor; import com.alipay.oceanbase.rpc.ObTableClient; import com.alipay.oceanbase.rpc.meta.ObTableMetaRequest; @@ -53,7 +53,7 @@ public void createTable(TableDescriptor tableDescriptor, byte[][] splitKeys) thr final ObTableMetaRequest request = new ObTableMetaRequest(); request.setMetaType(getMetaType()); Map requestData = new HashMap<>(); - requestData.put("htable_name", tableDescriptor.getTableName().getName()); + requestData.put("htable_name", tableDescriptor.getTableName().getNameAsString()); Map> columnFamilies = new HashMap<>(); for (ColumnFamilyDescriptor columnDescriptor : tableDescriptor.getColumnFamilies()) { Map columnFamily = new HashMap<>(); @@ -62,7 +62,8 @@ public void createTable(TableDescriptor tableDescriptor, byte[][] splitKeys) thr columnFamilies.put(columnDescriptor.getNameAsString(), columnFamily); } requestData.put("column_families", columnFamilies); - String jsonData = JSON.toJSONString(requestData); + ObjectMapper objectMapper = new ObjectMapper(); + String jsonData = objectMapper.writeValueAsString(requestData); request.setData(jsonData); execute(client, request); } diff --git a/src/main/java/com/alipay/oceanbase/hbase/util/OHDeleteTableExecutor.java b/src/main/java/com/alipay/oceanbase/hbase/util/OHDeleteTableExecutor.java index 47280128..1f689596 100644 --- a/src/main/java/com/alipay/oceanbase/hbase/util/OHDeleteTableExecutor.java +++ b/src/main/java/com/alipay/oceanbase/hbase/util/OHDeleteTableExecutor.java @@ -1,7 +1,23 @@ +/*- + * #%L + * com.oceanbase:obkv-hbase-client + * %% + * Copyright (C) 2022 - 2025 OceanBase Group + * %% + * OBKV HBase Client Framework is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * #L% + */ + package com.alipay.oceanbase.hbase.util; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.annotation.JSONField; +import com.fasterxml.jackson.databind.ObjectMapper; import com.alipay.oceanbase.hbase.execute.AbstractObTableMetaExecutor; import com.alipay.oceanbase.rpc.ObTableClient; import com.alipay.oceanbase.rpc.meta.ObTableMetaRequest; @@ -24,7 +40,6 @@ public ObTableRpcMetaType getMetaType() { return ObTableRpcMetaType.HTABLE_DELETE_TABLE; } - @Override public Void parse(ObTableMetaResponse response) throws IOException { // do nothing, error will be thrown from table @@ -36,7 +51,8 @@ public Void deleteTable(String tableName) throws IOException { request.setMetaType(getMetaType()); Map requestDataMap = new HashMap<>(); requestDataMap.put("table_name", tableName); - String jsonData = JSON.toJSONString(requestDataMap); + ObjectMapper objectMapper = new ObjectMapper(); + String jsonData = objectMapper.writeValueAsString(requestDataMap); request.setData(jsonData); return execute(tableClient, request); } diff --git a/src/main/java/com/alipay/oceanbase/hbase/util/OHRegionLoad.java b/src/main/java/com/alipay/oceanbase/hbase/util/OHRegionLoad.java new file mode 100644 index 00000000..697d9646 --- /dev/null +++ b/src/main/java/com/alipay/oceanbase/hbase/util/OHRegionLoad.java @@ -0,0 +1,63 @@ +/*- + * #%L + * com.oceanbase:obkv-hbase-client + * %% + * Copyright (C) 2022 - 2025 OceanBase Group + * %% + * OBKV HBase Client Framework is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * #L% + */ + +package com.alipay.oceanbase.hbase.util; + +import org.apache.hadoop.hbase.RegionLoad; +import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos; + +public class OHRegionLoad extends RegionLoad { + private final byte[] name; // tablet_name, id in String + private int storeFileSize; // tablet storage used in ssTable + private int memStoreSize; // tablet storage used in memTable + + public OHRegionLoad(byte[] name, int storeFileSize, int memStoreSize) { + super(null); + this.name = name; + this.storeFileSize = storeFileSize; + this.memStoreSize = memStoreSize; + } + + @Override + public byte[] getName() { + return name; + } + + /** + * @return the number of stores + */ + @Override + public int getStores() { + return 1; + } + + /** + * @return the number of storefiles + */ + @Override + public int getStorefiles() { + return 1; + } + + /** + * @return the total size of the storefiles, in MB + */ + @Override + public int getStorefileSizeMB() { + return memStoreSize + storeFileSize / 1024 / 1024; + } +} diff --git a/src/main/java/com/alipay/oceanbase/hbase/util/OHRegionLoadExecutor.java b/src/main/java/com/alipay/oceanbase/hbase/util/OHRegionLoadExecutor.java new file mode 100644 index 00000000..c8d7b0d5 --- /dev/null +++ b/src/main/java/com/alipay/oceanbase/hbase/util/OHRegionLoadExecutor.java @@ -0,0 +1,99 @@ +/*- + * #%L + * com.oceanbase:obkv-hbase-client + * %% + * Copyright (C) 2022 - 2025 OceanBase Group + * %% + * OBKV HBase Client Framework is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * #L% + */ + +package com.alipay.oceanbase.hbase.util; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.alipay.oceanbase.hbase.execute.AbstractObTableMetaExecutor; +import com.alipay.oceanbase.rpc.ObTableClient; +import com.alipay.oceanbase.rpc.meta.ObTableMetaRequest; +import com.alipay.oceanbase.rpc.meta.ObTableMetaResponse; +import com.alipay.oceanbase.rpc.meta.ObTableRpcMetaType; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.hadoop.hbase.RegionLoad; + +import java.io.IOException; +import java.util.*; + +public class OHRegionLoadExecutor extends AbstractObTableMetaExecutor> { + private final String tableName; + private final ObTableClient client; + + OHRegionLoadExecutor(String tableName, ObTableClient client) { + this.tableName = tableName; + this.client = client; + } + + /** + * 解析元数据响应, 用户需要重写 + * + * @param response 元数据响应 + * @return 解析后的元数据对象 + * @throws IOException 如果解析失败 + */ + @Override + public Map parse(ObTableMetaResponse response) throws IOException { + Map regionLoadMap = new LinkedHashMap<>(); + // use jackson to parse json + final ObjectMapper objectMapper = new ObjectMapper(); + final JsonNode jsonMap = Optional.ofNullable(objectMapper.readTree(response.getData())).orElse(null); + if (jsonMap == null) { + throw new IOException("jsonMap is null"); + } + JsonNode tableGroupNameNode = Optional.ofNullable(jsonMap.get("tableName")) + .orElseThrow(() -> new IOException("tableName is null")); + String tableGroupName = tableGroupNameNode.asText(); + + JsonNode regionListNode = Optional.ofNullable(jsonMap.get("regionList")) + .orElseThrow(() -> new IOException("regionList is null")); + List regions = Optional.>ofNullable(objectMapper.convertValue(regionListNode.get("regions"), new TypeReference>() {})) + .orElseThrow(() -> new IOException("regions is null")); + List memTableSizeList = Optional.>ofNullable(objectMapper.convertValue(regionListNode.get("memTableSize"), new TypeReference>() {})) + .orElseThrow(() -> new IOException("memTableSize is null")); + List ssTableSizeList = Optional.>ofNullable(objectMapper.convertValue(regionListNode.get("ssTableSize"), new TypeReference>() {})) + .orElseThrow(() -> new IOException("ssTableSize is null")); + for (int i = 0; i < regions.size(); ++i) { + String name_str = Integer.toString(regions.get(i)); + byte[] name = name_str.getBytes(); + OHRegionLoad load = new OHRegionLoad(name, ssTableSizeList.get(i) / (1024 * 1024), memTableSizeList.get(i) / (1024 * 1024)); + regionLoadMap.put(name, load); + } + return regionLoadMap; + } + + /** + * 获取元信息类型, 用户需要重写 + * + * @return 元信息类型 + */ + @Override + public ObTableRpcMetaType getMetaType() throws IOException { + return ObTableRpcMetaType.HTABLE_REGION_METRICS; + } + + public Map getRegionLoad() throws IOException { + ObTableMetaRequest request = new ObTableMetaRequest(); + request.setMetaType(getMetaType()); + Map requestData = new HashMap<>(); + requestData.put("table_name", tableName); + ObjectMapper objectMapper = new ObjectMapper(); + String jsonData = objectMapper.writeValueAsString(requestData); + request.setData(jsonData); + return execute(client, request); + } +} diff --git a/src/main/java/com/alipay/oceanbase/hbase/util/OHRegionLocator.java b/src/main/java/com/alipay/oceanbase/hbase/util/OHRegionLocator.java index ab99bc22..4894501c 100644 --- a/src/main/java/com/alipay/oceanbase/hbase/util/OHRegionLocator.java +++ b/src/main/java/com/alipay/oceanbase/hbase/util/OHRegionLocator.java @@ -1,3 +1,20 @@ +/*- + * #%L + * com.oceanbase:obkv-hbase-client + * %% + * Copyright (C) 2022 - 2025 OceanBase Group + * %% + * OBKV HBase Client Framework is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * #L% + */ + package com.alipay.oceanbase.hbase.util; import com.alipay.oceanbase.rpc.ObTableClient; @@ -13,16 +30,16 @@ import java.util.List; public class OHRegionLocator implements RegionLocator { - private byte[][] startKeys; - private byte[][] endKeys; - private ObTableClient tableClient; - private TableName tableName; + private byte[][] startKeys; + private byte[][] endKeys; + private ObTableClient tableClient; + private TableName tableName; private List regionLocations; public OHRegionLocator(byte[][] startKeys, byte[][] endKeys, - List regionLocations, - TableName tableName, ObTableClient tableClient) { + List regionLocations, TableName tableName, + ObTableClient tableClient) { this.startKeys = startKeys; this.endKeys = endKeys; this.regionLocations = regionLocations; @@ -44,7 +61,8 @@ public HRegionLocation getRegionLocation(byte[] bytes) throws IOException { @Override public HRegionLocation getRegionLocation(byte[] bytes, boolean b) throws IOException { if (b || regionLocations.isEmpty()) { - OHRegionLocatorExecutor executor = new OHRegionLocatorExecutor(tableName.toString(), tableClient); + OHRegionLocatorExecutor executor = new OHRegionLocatorExecutor(tableName.toString(), + tableClient); try { RegionLocator location = executor.getRegionLocator(tableName.toString()); this.startKeys = location.getStartKeys(); @@ -52,7 +70,7 @@ public HRegionLocation getRegionLocation(byte[] bytes, boolean b) throws IOExcep this.regionLocations = location.getAllRegionLocations(); } catch (IOException e) { if (e.getCause() instanceof ObTableTransportException - && ((ObTableTransportException) e.getCause()).getErrorCode() == TransportCodes.BOLT_TIMEOUT) { + && ((ObTableTransportException) e.getCause()).getErrorCode() == TransportCodes.BOLT_TIMEOUT) { throw new TimeoutIOException(e.getCause()); } else { throw e; diff --git a/src/main/java/com/alipay/oceanbase/hbase/util/OHRegionLocatorExecutor.java b/src/main/java/com/alipay/oceanbase/hbase/util/OHRegionLocatorExecutor.java index 435cd6f4..c901d4ad 100644 --- a/src/main/java/com/alipay/oceanbase/hbase/util/OHRegionLocatorExecutor.java +++ b/src/main/java/com/alipay/oceanbase/hbase/util/OHRegionLocatorExecutor.java @@ -1,13 +1,29 @@ +/*- + * #%L + * com.oceanbase:obkv-hbase-client + * %% + * Copyright (C) 2022 - 2025 OceanBase Group + * %% + * OBKV HBase Client Framework is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * #L% + */ + package com.alipay.oceanbase.hbase.util; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import com.alipay.oceanbase.hbase.execute.AbstractObTableMetaExecutor; import com.alipay.oceanbase.rpc.ObTableClient; import com.alipay.oceanbase.rpc.constant.Constants; -import com.alipay.oceanbase.rpc.exception.ObTableException; import com.alipay.oceanbase.rpc.exception.ObTableUnexpectedException; -import com.alipay.oceanbase.rpc.location.model.TableEntry; import com.alipay.oceanbase.rpc.meta.ObTableMetaRequest; import com.alipay.oceanbase.rpc.meta.ObTableMetaResponse; import com.alipay.oceanbase.rpc.meta.ObTableRpcMetaType; @@ -19,7 +35,7 @@ import java.util.stream.IntStream; public class OHRegionLocatorExecutor extends AbstractObTableMetaExecutor { - private final String tableName; + private final String tableName; private final ObTableClient client; OHRegionLocatorExecutor(String tableName, ObTableClient client) { @@ -42,7 +58,8 @@ public ObTableRpcMetaType getMetaType() { public OHRegionLocator parse(ObTableMetaResponse response) throws IOException { try { final String jsonData = response.getData(); - final JSONObject jsonMap = Optional.ofNullable(JSON.parseObject(jsonData)) + final ObjectMapper objectMapper = new ObjectMapper(); + final JsonNode jsonMap = Optional.ofNullable(objectMapper.readTree(jsonData)) .orElseThrow(() -> new IOException("jsonMap is null")); /* { @@ -77,14 +94,17 @@ public OHRegionLocator parse(ObTableMetaResponse response) throws IOException { ] } */ - - final List partitions = Optional.>ofNullable(jsonMap.getJSONArray("partitions")) + JsonNode partitionsNode = Optional.ofNullable(jsonMap.get("partitions")) .orElseThrow(() -> new IOException("partitions is null")); + List partitions = objectMapper.convertValue(partitionsNode, new TypeReference>(){}); - final List tableIdDict = Optional.>ofNullable(jsonMap.getJSONArray("table_id_dict")) + JsonNode tableIdDictNode = Optional.ofNullable(jsonMap.get("table_id_dict")) .orElseThrow(() -> new IOException("tableIdDict is null")); - final List replicaDict = Optional.>ofNullable(jsonMap.getJSONArray("replica_dict")) + List tableIdDict = objectMapper.convertValue(tableIdDictNode, new TypeReference>(){}); + + JsonNode replicaDictNode = Optional.ofNullable(jsonMap.get("replica_dict")) .orElseThrow(() -> new IOException("replicaDict is null")); + List replicaDict = objectMapper.convertValue(replicaDictNode, new TypeReference>(){}); final boolean isHashLikePartition = partitions.stream() .map(obj -> (List) obj) @@ -213,8 +233,8 @@ public OHRegionLocator getRegionLocator(final String tableName) throws IOExcepti request.setMetaType(getMetaType()); final Map requestData = new HashMap<>(); requestData.put("table_name", tableName); - - final String jsonData = JSON.toJSONString(requestData); + ObjectMapper objectMapper = new ObjectMapper(); + final String jsonData = objectMapper.writeValueAsString(requestData); request.setData(jsonData); return execute(client, request); diff --git a/src/main/java/com/alipay/oceanbase/hbase/util/OHRegionMetrics.java b/src/main/java/com/alipay/oceanbase/hbase/util/OHRegionMetrics.java deleted file mode 100644 index 8f161575..00000000 --- a/src/main/java/com/alipay/oceanbase/hbase/util/OHRegionMetrics.java +++ /dev/null @@ -1,121 +0,0 @@ -package com.alipay.oceanbase.hbase.util; - -import com.alipay.oceanbase.hbase.exception.FeatureNotSupportedException; -import org.apache.hadoop.hbase.RegionMetrics; -import org.apache.hadoop.hbase.Size; - -import java.util.Collections; -import java.util.Map; - -public class OHRegionMetrics implements RegionMetrics { - private final String tablegroup; - private final byte[] name; // tablet_name, id in String - private final Size storeFileSize; // tablet storage used in ssTable - private final Size memStoreSize; // tablet storage used in memTable - - OHRegionMetrics(String tablegroup, byte[] name, Size storeFileSize, Size memStoreSize) { - this.tablegroup = tablegroup; - this.name = name; - this.storeFileSize = storeFileSize; - this.memStoreSize = memStoreSize; - } - - public String getTablegroup() { - return tablegroup; - } - - @Override - public byte[] getRegionName() { - return name; - } - - @Override - public int getStoreCount() { - throw new FeatureNotSupportedException("does not support yet"); - } - - @Override - public int getStoreFileCount() { - throw new FeatureNotSupportedException("does not support yet"); - } - - @Override - public Size getStoreFileSize() { - return storeFileSize; - } - - @Override - public Size getMemStoreSize() { - return memStoreSize; - } - - @Override - public long getReadRequestCount() { - throw new FeatureNotSupportedException("does not support yet"); - } - - @Override - public long getWriteRequestCount() { - throw new FeatureNotSupportedException("does not support yet"); - } - - @Override - public long getFilteredReadRequestCount() { - throw new FeatureNotSupportedException("does not support yet"); - } - - @Override - public Size getStoreFileIndexSize() { - throw new FeatureNotSupportedException("does not support yet"); - } - - @Override - public Size getStoreFileRootLevelIndexSize() { - throw new FeatureNotSupportedException("does not support yet"); - } - - @Override - public Size getStoreFileUncompressedDataIndexSize() { - throw new FeatureNotSupportedException("does not support yet"); - } - - @Override - public Size getBloomFilterSize() { - throw new FeatureNotSupportedException("does not support yet"); - } - - @Override - public long getCompactingCellCount() { - throw new FeatureNotSupportedException("does not support yet"); - } - - @Override - public long getCompactedCellCount() { - throw new FeatureNotSupportedException("does not support yet"); - } - - @Override - public long getCompletedSequenceId() { - throw new FeatureNotSupportedException("does not support yet"); - } - - @Override - public Map getStoreSequenceId() { - throw new FeatureNotSupportedException("does not support yet"); - } - - @Override - public Size getUncompressedStoreFileSize() { - throw new FeatureNotSupportedException("does not support yet"); - } - - @Override - public float getDataLocality() { - throw new FeatureNotSupportedException("does not support yet"); - } - - @Override - public long getLastMajorCompactionTimestamp() { - throw new FeatureNotSupportedException("does not support yet"); - } -} diff --git a/src/main/java/com/alipay/oceanbase/hbase/util/OHRegionMetricsExecutor.java b/src/main/java/com/alipay/oceanbase/hbase/util/OHRegionMetricsExecutor.java deleted file mode 100644 index 430f568f..00000000 --- a/src/main/java/com/alipay/oceanbase/hbase/util/OHRegionMetricsExecutor.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.alipay.oceanbase.hbase.util; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import com.alipay.oceanbase.hbase.execute.AbstractObTableMetaExecutor; -import com.alipay.oceanbase.rpc.ObTableClient; -import com.alipay.oceanbase.rpc.meta.ObTableMetaRequest; -import com.alipay.oceanbase.rpc.meta.ObTableMetaResponse; -import com.alipay.oceanbase.rpc.meta.ObTableRpcMetaType; -import org.apache.hadoop.hbase.RegionMetrics; -import org.apache.hadoop.hbase.Size; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class OHRegionMetricsExecutor extends AbstractObTableMetaExecutor> { - private final ObTableClient tableClient; - OHRegionMetricsExecutor(ObTableClient tableClient) { - this.tableClient = tableClient; - } - @Override - public ObTableRpcMetaType getMetaType() throws IOException { - return ObTableRpcMetaType.HTABLE_REGION_METRICS; - } - - /* - * { - tableName: "tablegroup_name", - regionList:{ - "regions": [200051, 200052, 200053, 200191, 200192, 200193, ...], - "memTableSize":[123, 321, 321, 123, 321, 321, ...], - "ssTableSize":[5122, 4111, 5661, 5122, 4111, 5661, ...] - } - } - * */ - @Override - public List parse(ObTableMetaResponse response) throws IOException { - List metricsList = new ArrayList<>(); - JSONObject metrcisJSONObject = JSON.parseObject(response.getData()); - String tableGroupName = metrcisJSONObject.getString("tableName"); - JSONObject regionList = metrcisJSONObject.getJSONObject("regionList"); - List regions = regionList.getJSONArray("regions").toJavaList(Integer.class); - List memTableSizeList = regionList.getJSONArray("memTableSize").toJavaList(Integer.class); - List ssTableSizeList = regionList.getJSONArray("ssTableSize").toJavaList(Integer.class); - if (regions.isEmpty() || regions.size() != memTableSizeList.size() || memTableSizeList.size() != ssTableSizeList.size()) { - throw new IOException("size length has to be the same"); - } - for (int i = 0; i < regions.size(); ++i) { - String name_str = Integer.toString(regions.get(i)); - byte[] name = name_str.getBytes(); - Size storeFileSize = new Size(((double) ssTableSizeList.get(i)) / (1024 * 1024) , Size.Unit.MEGABYTE); // The unit in original HBase is MEGABYTE, for us it is BYTE - Size memStoreSize = new Size(((double) memTableSizeList.get(i)) / (1024 * 1024), Size.Unit.MEGABYTE); // The unit in original HBase is MEGABYTE, for us it is BYTE - OHRegionMetrics ohRegionMetrics = new OHRegionMetrics(tableGroupName, name, storeFileSize, memStoreSize); - metricsList.add(ohRegionMetrics); - } - return metricsList; - } - - public List getRegionMetrics(String tableName) throws IOException { - ObTableMetaRequest request = new ObTableMetaRequest(); - request.setMetaType(getMetaType()); - Map requestData = new HashMap<>(); - requestData.put("table_name", tableName); - String jsonData = JSON.toJSONString(requestData); - request.setData(jsonData); - return execute(tableClient, request); - } -} diff --git a/src/main/java/com/alipay/oceanbase/hbase/util/OHTableAccessControlExecutor.java b/src/main/java/com/alipay/oceanbase/hbase/util/OHTableAccessControlExecutor.java index 090da7e4..9bf0075b 100644 --- a/src/main/java/com/alipay/oceanbase/hbase/util/OHTableAccessControlExecutor.java +++ b/src/main/java/com/alipay/oceanbase/hbase/util/OHTableAccessControlExecutor.java @@ -1,6 +1,23 @@ +/*- + * #%L + * com.oceanbase:obkv-hbase-client + * %% + * Copyright (C) 2022 - 2025 OceanBase Group + * %% + * OBKV HBase Client Framework is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * #L% + */ + package com.alipay.oceanbase.hbase.util; -import com.alibaba.fastjson.JSON; +import com.fasterxml.jackson.databind.ObjectMapper; import com.alipay.oceanbase.hbase.execute.AbstractObTableMetaExecutor; import com.alipay.oceanbase.rpc.ObTableClient; import com.alipay.oceanbase.rpc.meta.ObTableMetaRequest; @@ -15,7 +32,7 @@ import java.util.Map; public class OHTableAccessControlExecutor extends AbstractObTableMetaExecutor { - private final ObTableClient tableClient; + private final ObTableClient tableClient; private final ObTableRpcMetaType type; OHTableAccessControlExecutor(ObTableClient tableClient, ObTableRpcMetaType type) { @@ -38,7 +55,8 @@ public void enableTable(String tableName) throws IOException, TableNotFoundExcep request.setMetaType(getMetaType()); Map requestData = new HashMap<>(); requestData.put("table_name", tableName); - String jsonData = JSON.toJSONString(requestData); + ObjectMapper objectMapper = new ObjectMapper(); + String jsonData = objectMapper.writeValueAsString(requestData); request.setData(jsonData); execute(tableClient, request); } @@ -48,7 +66,8 @@ public void disableTable(String tableName) throws IOException, TableNotFoundExce request.setMetaType(getMetaType()); Map requestData = new HashMap<>(); requestData.put("table_name", tableName); - String jsonData = JSON.toJSONString(requestData); + ObjectMapper objectMapper = new ObjectMapper(); + String jsonData = objectMapper.writeValueAsString(requestData); request.setData(jsonData); execute(tableClient, request); } diff --git a/src/main/java/com/alipay/oceanbase/hbase/util/OHTableDescriptorExecutor.java b/src/main/java/com/alipay/oceanbase/hbase/util/OHTableDescriptorExecutor.java index dae981f0..c0292f45 100644 --- a/src/main/java/com/alipay/oceanbase/hbase/util/OHTableDescriptorExecutor.java +++ b/src/main/java/com/alipay/oceanbase/hbase/util/OHTableDescriptorExecutor.java @@ -1,7 +1,24 @@ +/*- + * #%L + * com.oceanbase:obkv-hbase-client + * %% + * Copyright (C) 2022 - 2025 OceanBase Group + * %% + * OBKV HBase Client Framework is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * #L% + */ + package com.alipay.oceanbase.hbase.util; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import com.alipay.oceanbase.hbase.execute.AbstractObTableMetaExecutor; import com.alipay.oceanbase.rpc.ObTableClient; import com.alipay.oceanbase.rpc.meta.ObTableMetaRequest; @@ -14,11 +31,13 @@ import java.io.IOException; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; import java.util.Optional; +import java.util.stream.Stream; public class OHTableDescriptorExecutor extends AbstractObTableMetaExecutor { - private final String tableName; + private final String tableName; private final ObTableClient client; public OHTableDescriptorExecutor(String tableName, ObTableClient client) { @@ -30,36 +49,41 @@ public OHTableDescriptorExecutor(String tableName, ObTableClient client) { public HTableDescriptor parse(ObTableMetaResponse response) throws IOException { try { final String jsonData = response.getData(); - final JSONObject jsonMap = Optional.ofNullable(JSON.parseObject(jsonData)) + final ObjectMapper objectMapper = new ObjectMapper(); + final JsonNode jsonMap = Optional.ofNullable(objectMapper.readTree(jsonData)) .orElseThrow(() -> new IOException("jsonMap is null")); /* { - "cfDesc": { + "cfDescs": { "cf1": { - "TTL":604800 + "TTL":604800 + "maxVersions": 3 }, "cf2": { - "TTL":259200 + "TTL":259200 + "maxVersions": 2 } }, "tbDesc": { - "name":"test" + "name":"test", + "state":"disable" ("enable") } } */ HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf(tableName)); - JSONObject cfDesc = jsonMap.getJSONObject("cfDescs"); - if (cfDesc != null) { - for (Map.Entry entry : cfDesc.entrySet()) { - String cfName = entry.getKey(); - JSONObject attributes = (JSONObject) entry.getValue(); - HColumnDescriptor cf = new HColumnDescriptor(cfName); - cf.setTimeToLive(attributes.getIntValue("TTL")); - tableDescriptor.addFamily(cf); - } - } else { - throw new IOException("cfDesc is null"); - } + JsonNode cfDescsNode = Optional.ofNullable(jsonMap.get("cfDescs")) + .orElseThrow(() -> new IOException("cfDesc is null")); + Stream> stream = cfDescsNode.propertyStream(); + stream.forEach(entry -> { + String cfName = entry.getKey(); + JsonNode value = entry.getValue(); + int ttl = value.path("TTL").asInt(); + int maxVersions = value.path("maxVersions").asInt(); + HColumnDescriptor cf = new HColumnDescriptor(cfName); + cf.setTimeToLive(ttl); + cf.setMaxVersions(maxVersions); + tableDescriptor.addFamily(cf); + }); return tableDescriptor; } catch (IllegalArgumentException e) { throw new IOException("Failed to parse response", e); @@ -71,14 +95,13 @@ public ObTableRpcMetaType getMetaType() throws IOException { return ObTableRpcMetaType.HTABLE_GET_DESC; } - public HTableDescriptor getTableDescriptor() throws IOException { final ObTableMetaRequest request = new ObTableMetaRequest(); request.setMetaType(getMetaType()); final Map requestData = new HashMap<>(); requestData.put("table_name", tableName); - - final String jsonData = JSON.toJSONString(requestData); + ObjectMapper objectMapper = new ObjectMapper(); + final String jsonData = objectMapper.writeValueAsString(requestData); request.setData(jsonData); return execute(client, request); @@ -90,22 +113,21 @@ public boolean isDisable() throws IOException { request.setMetaType(getMetaType()); final Map requestData = new HashMap<>(); requestData.put("table_name", tableName); - - final String jsonData = JSON.toJSONString(requestData); + final ObjectMapper objectMapper = new ObjectMapper(); + final String jsonData = objectMapper.writeValueAsString(requestData); request.setData(jsonData); try { ObTableMetaResponse response = innerExecute(client, request); final String responseData = response.getData(); - final JSONObject jsonMap = Optional.ofNullable(JSON.parseObject(responseData)) + final JsonNode jsonMap = Optional.ofNullable(objectMapper.readTree(responseData)) .orElseThrow(() -> new IOException("jsonMap is null")); - JSONObject tbDesc = jsonMap.getJSONObject("tableDesc"); - if (tbDesc != null) { - String state = tbDesc.getString("state"); - if (state.compareToIgnoreCase("disable") == 0) { - isDisable = true; - } else { - isDisable = false; - } + JsonNode tbDesc = Optional.ofNullable(jsonMap.get("tableDesc")) + .orElseThrow(() -> new IOException("tableDesc is null")); + String state = tbDesc.get("state").asText(); + if (state.compareToIgnoreCase("disable") == 0) { + isDisable = true; + } else { + isDisable = false; } } catch (IOException e) { throw e; @@ -113,17 +135,15 @@ public boolean isDisable() throws IOException { return isDisable; } - private ObTableMetaResponse innerExecute(ObTableClient client, ObTableMetaRequest request) throws IOException { + private ObTableMetaResponse innerExecute(ObTableClient client, ObTableMetaRequest request) + throws IOException { if (request.getMetaType() != getMetaType()) { throw new IOException("Invalid meta type, expected " + getMetaType()); } ObTable table = client.getRandomTable(); ObTableMetaResponse response; try { - response = (ObTableMetaResponse) client.executeWithRetry( - table, - request, - null /*tableName*/ + response = (ObTableMetaResponse) client.executeWithRetry(table, request, null /*tableName*/ ); } catch (Exception e) { throw new IOException("Failed to execute request", e); diff --git a/src/main/java/com/alipay/oceanbase/hbase/util/OHTableExistsExecutor.java b/src/main/java/com/alipay/oceanbase/hbase/util/OHTableExistsExecutor.java index 7b827226..ffaaca18 100644 --- a/src/main/java/com/alipay/oceanbase/hbase/util/OHTableExistsExecutor.java +++ b/src/main/java/com/alipay/oceanbase/hbase/util/OHTableExistsExecutor.java @@ -1,7 +1,24 @@ +/*- + * #%L + * com.oceanbase:obkv-hbase-client + * %% + * Copyright (C) 2022 - 2025 OceanBase Group + * %% + * OBKV HBase Client Framework is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * #L% + */ + package com.alipay.oceanbase.hbase.util; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import com.alipay.oceanbase.hbase.execute.AbstractObTableMetaExecutor; import com.alipay.oceanbase.rpc.ObTableClient; import com.alipay.oceanbase.rpc.meta.ObTableMetaRequest; @@ -11,6 +28,7 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; +import java.util.Optional; public class OHTableExistsExecutor extends AbstractObTableMetaExecutor { private final ObTableClient tableClient; @@ -27,8 +45,10 @@ public ObTableRpcMetaType getMetaType() throws IOException { @Override public Boolean parse(ObTableMetaResponse response) throws IOException { String jsonData = response.getData(); - JSONObject object = JSONObject.parseObject(jsonData); - return object.getBoolean("exists"); + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode jsonNode = Optional.ofNullable(objectMapper.readTree(jsonData)) + .orElseThrow(() -> new IOException("jsonMap is null")); + return jsonNode.get("exists").asBoolean(); } public Boolean tableExists(String tableName) throws IOException { @@ -36,7 +56,8 @@ public Boolean tableExists(String tableName) throws IOException { request.setMetaType(getMetaType()); Map requestData = new HashMap<>(); requestData.put("table_name", tableName); - String jsonData = JSON.toJSONString(requestData); + ObjectMapper objectMapper = new ObjectMapper(); + String jsonData = objectMapper.writeValueAsString(requestData); request.setData(jsonData); return execute(tableClient, request); } diff --git a/src/main/java/com/alipay/oceanbase/hbase/util/ObTableClientManager.java b/src/main/java/com/alipay/oceanbase/hbase/util/ObTableClientManager.java index e0d50cea..0c5a8842 100644 --- a/src/main/java/com/alipay/oceanbase/hbase/util/ObTableClientManager.java +++ b/src/main/java/com/alipay/oceanbase/hbase/util/ObTableClientManager.java @@ -128,16 +128,19 @@ public static ObTableClient getOrCreateObTableClient(ObTableClientKey obTableCli return OB_TABLE_CLIENT_INSTANCE.get(obTableClientKey); } - public static ObTableClient getOrCreateObTableClientByTableName(TableName tableName, OHConnectionConfiguration connectionConfig) throws IllegalArgumentException, - IOException { + public static ObTableClient getOrCreateObTableClientByTableName(TableName tableName, + OHConnectionConfiguration connectionConfig) + throws IllegalArgumentException, + IOException { String tableNameString = tableName.getNameAsString(); - ObTableClient obTableClient = getOrCreateObTableClient( - OHTable.setUserDefinedNamespace(tableNameString, connectionConfig)); + ObTableClient obTableClient = getOrCreateObTableClient(OHTable.setUserDefinedNamespace( + tableNameString, connectionConfig)); ObTableClientManager.initTimeoutAndRetryTimes(obTableClient, connectionConfig); return obTableClient; } - private static void initTimeoutAndRetryTimes(ObTableClient obTableClient, OHConnectionConfiguration ohConnectionConf) { + private static void initTimeoutAndRetryTimes(ObTableClient obTableClient, + OHConnectionConfiguration ohConnectionConf) { obTableClient.setRpcExecuteTimeout(ohConnectionConf.getRpcTimeout()); obTableClient.setRuntimeRetryTimes(ohConnectionConf.getNumRetries()); obTableClient.setRuntimeMaxWait(ohConnectionConf.getOperationTimeout()); diff --git a/src/test/java/com/alipay/oceanbase/hbase/HTableMultiCFTestBase.java b/src/test/java/com/alipay/oceanbase/hbase/HTableMultiCFTestBase.java index a22bc769..2bc7e482 100644 --- a/src/test/java/com/alipay/oceanbase/hbase/HTableMultiCFTestBase.java +++ b/src/test/java/com/alipay/oceanbase/hbase/HTableMultiCFTestBase.java @@ -22,11 +22,13 @@ import com.alipay.oceanbase.hbase.util.ObHTableTestUtil; import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hbase.CellUtil; +import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.*; import org.apache.hadoop.hbase.client.coprocessor.Batch; import org.apache.hadoop.hbase.filter.*; import org.apache.hadoop.hbase.util.Bytes; +import org.checkerframework.checker.units.qual.C; import org.junit.*; import org.junit.rules.ExpectedException; @@ -626,51 +628,6 @@ public void testMultiColumnFamilyBufferedMutator() throws Exception { } Assert.assertEquals(0, count); - // test periodic flush - params.setWriteBufferPeriodicFlushTimeoutMs(100); - mutator = connection.getBufferedMutator(params); - while (true) { - for (int i = 0; i < rows; ++i) { - mutations.clear(); - Put put = new Put(toBytes(keys.get(i))); - put.addColumn(family1, family1_column1, family1_value); - put.addColumn(family1, family1_column2, family1_value); - put.addColumn(family1, family1_column3, family1_value); - put.addColumn(family2, family2_column1, family2_value); - put.addColumn(family3, family3_column1, family2_value); - put.addColumn(family3, family3_column2, family3_value); - mutations.add(put); - if (i % 3 == 0) { // 0, 3, 6, 9 - Delete delete = new Delete(toBytes(keys.get(i))); - delete.addFamily(family1); - delete.addFamily(family2); - mutations.add(delete); - } - mutator.mutate(mutations); - } - - get = new Get(toBytes("Key0")); - result = multiCfHTable.get(get); - if (!result.isEmpty()) { - break; - } - } - get = new Get(toBytes("Key2")); - get.setMaxVersions(); - result = multiCfHTable.get(get); - count = result.rawCells().length; - Assert.assertTrue(count > 0); - // test timer periodic flush - int lastUndealtCount = ((OHBufferedMutatorImpl) mutator).size(); - Thread.sleep(1000); - int currentUndealtCount = ((OHBufferedMutatorImpl) mutator).size(); - Assert.assertNotEquals(lastUndealtCount, currentUndealtCount); - // after periodic flush, all mutations will be committed - Assert.assertEquals(0, currentUndealtCount); - result = multiCfHTable.get(get); - int newCount = result.rawCells().length; - Assert.assertNotEquals(count, newCount); - // clean data mutations.clear(); for (String key : keys) { @@ -898,7 +855,7 @@ public void update(byte[] region, byte[] row, Result result) { // put + delete + get Get get2 = new Get("Key2".getBytes()); - get1.setMaxVersions(10); + get2.setMaxVersions(10); get2.addColumn(family1, family1_column1); batchLsit.clear(); batchLsit.add(delete); diff --git a/src/test/java/com/alipay/oceanbase/hbase/HTableTestBase.java b/src/test/java/com/alipay/oceanbase/hbase/HTableTestBase.java index 4dd3e0f7..dc1593e7 100644 --- a/src/test/java/com/alipay/oceanbase/hbase/HTableTestBase.java +++ b/src/test/java/com/alipay/oceanbase/hbase/HTableTestBase.java @@ -17,6 +17,7 @@ package com.alipay.oceanbase.hbase; +import com.alipay.oceanbase.hbase.exception.FeatureNotSupportedException; import org.apache.hadoop.hbase.*; import org.apache.hadoop.hbase.client.*; import org.apache.hadoop.hbase.filter.*; @@ -2096,202 +2097,6 @@ public void testFilter2() throws Exception { scanner.close(); } - @Test - public void testColumnValueFilter() throws Exception { - String key1 = "abab"; - String key2 = "abcc"; - String column1 = "c1"; - String column2 = "c2"; - String column3 = "c3"; - String column4 = "c4"; - String column5 = "c5"; - String value1 = "value1"; - String value2 = "value2"; - String family = "family1"; - Delete deleteKey1Family = new Delete(toBytes(key1)); - deleteKey1Family.addFamily(toBytes(family)); - - Delete deleteKey2Family = new Delete(toBytes(key2)); - deleteKey2Family.addFamily(toBytes(family)); - - hTable.delete(deleteKey1Family); - hTable.delete(deleteKey2Family); - - try { - Put putKey1Column1Value1 = new Put(toBytes(key1)); - putKey1Column1Value1.addColumn(toBytes(family), toBytes(column1), toBytes(value1)); - - Put putKey1Column1Value2 = new Put(toBytes(key1)); - putKey1Column1Value2.addColumn(toBytes(family), toBytes(column1), toBytes(value2)); - - Put putKey1Column2Value2 = new Put(toBytes(key1)); - putKey1Column2Value2.addColumn(toBytes(family), toBytes(column2), toBytes(value2)); - - Put putKey1Column2Value1 = new Put(toBytes(key1)); - putKey1Column2Value1.addColumn(toBytes(family), toBytes(column2), toBytes(value1)); - - Put putKey1Column3Value1 = new Put(toBytes(key1)); - putKey1Column3Value1.addColumn(toBytes(family), toBytes(column3), toBytes(value1)); - - Put putKey1Column4Value1 = new Put(toBytes(key1)); - putKey1Column4Value1.addColumn(toBytes(family), toBytes(column4), toBytes(value1)); - - Put putKey1Column5Value1 = new Put(toBytes(key1)); - putKey1Column5Value1.addColumn(toBytes(family), toBytes(column5), toBytes(value1)); - - Put putKey2Column1Value1 = new Put(toBytes(key2)); - putKey2Column1Value1.addColumn(toBytes(family), toBytes(column1), toBytes(value1)); - - Put putKey2Column1Value2 = new Put(toBytes(key2)); - putKey2Column1Value2.addColumn(toBytes(family), toBytes(column1), toBytes(value2)); - - Put putKey2Column2Value2 = new Put(toBytes(key2)); - putKey2Column2Value2.addColumn(toBytes(family), toBytes(column2), toBytes(value2)); - - Put putKey2Column2Value1 = new Put(toBytes(key2)); - putKey2Column2Value1.addColumn(toBytes(family), toBytes(column2), toBytes(value1)); - - hTable.delete(deleteKey1Family); - hTable.delete(deleteKey2Family); - tryPut(hTable, putKey1Column1Value1); - tryPut(hTable, putKey1Column1Value2); - tryPut(hTable, putKey1Column1Value1); - tryPut(hTable, putKey1Column2Value1); - tryPut(hTable, putKey1Column2Value2); - tryPut(hTable, putKey1Column2Value1); - tryPut(hTable, putKey1Column2Value2); - tryPut(hTable, putKey1Column3Value1); - tryPut(hTable, putKey1Column4Value1); - tryPut(hTable, putKey1Column5Value1); - tryPut(hTable, putKey2Column2Value1); - tryPut(hTable, putKey2Column2Value2); - - Scan scan; - scan = new Scan(); - scan.addFamily(family.getBytes()); - scan.setMaxVersions(10); - ColumnValueFilter filter = new ColumnValueFilter(Bytes.toBytes(family), - Bytes.toBytes(column2), CompareOperator.EQUAL, Bytes.toBytes(value1)); - scan.setFilter(filter); - ResultScanner scanner = hTable.getScanner(scan); - - int res_count = 0; - for (Result result : scanner) { - for (Cell keyValue : result.rawCells()) { - System.out - .printf( - "Rowkey: %s, Column Family: %s, Column Qualifier: %s, Timestamp: %d, Value: %s%n", - Bytes.toString(result.getRow()), - Bytes.toString(CellUtil.cloneFamily(keyValue)), - Bytes.toString(CellUtil.cloneQualifier(keyValue)), - keyValue.getTimestamp(), Bytes.toString(CellUtil.cloneValue(keyValue))); - res_count += 1; - } - } - Assert.assertEquals(res_count, 3); - scanner.close(); - - scan = new Scan(); - scan.addFamily(family.getBytes()); - scan.setMaxVersions(10); - filter = new ColumnValueFilter(Bytes.toBytes(family), Bytes.toBytes(column2), - CompareOperator.EQUAL, new BinaryPrefixComparator(Bytes.toBytes("value"))); - scan.setFilter(filter); - scanner = hTable.getScanner(scan); - - res_count = 0; - for (Result result : scanner) { - for (Cell keyValue : result.rawCells()) { - System.out - .printf( - "Rowkey: %s, Column Family: %s, Column Qualifier: %s, Timestamp: %d, Value: %s%n", - Bytes.toString(result.getRow()), - Bytes.toString(CellUtil.cloneFamily(keyValue)), - Bytes.toString(CellUtil.cloneQualifier(keyValue)), - keyValue.getTimestamp(), Bytes.toString(CellUtil.cloneValue(keyValue))); - res_count += 1; - } - } - Assert.assertEquals(res_count, 6); - scanner.close(); - - scan = new Scan(); - scan.addFamily(family.getBytes()); - scan.setMaxVersions(10); - filter = new ColumnValueFilter(Bytes.toBytes(family), Bytes.toBytes(column2), - CompareOperator.LESS, Bytes.toBytes(value1)); - scan.setFilter(filter); - scanner = hTable.getScanner(scan); - - res_count = 0; - for (Result result : scanner) { - for (Cell keyValue : result.rawCells()) { - System.out - .printf( - "Rowkey: %s, Column Family: %s, Column Qualifier: %s, Timestamp: %d, Value: %s%n", - Bytes.toString(result.getRow()), - Bytes.toString(CellUtil.cloneFamily(keyValue)), - Bytes.toString(CellUtil.cloneQualifier(keyValue)), - keyValue.getTimestamp(), Bytes.toString(CellUtil.cloneValue(keyValue))); - res_count += 1; - } - } - Assert.assertEquals(res_count, 3); - scanner.close(); - - scan = new Scan(); - scan.addFamily(family.getBytes()); - scan.setMaxVersions(10); - filter = new ColumnValueFilter(Bytes.toBytes(family), Bytes.toBytes(column1), - CompareOperator.NOT_EQUAL, Bytes.toBytes(value1)); - scan.setFilter(filter); - scanner = hTable.getScanner(scan); - - res_count = 0; - for (Result result : scanner) { - for (Cell keyValue : result.rawCells()) { - System.out - .printf( - "Rowkey: %s, Column Family: %s, Column Qualifier: %s, Timestamp: %d, Value: %s%n", - Bytes.toString(result.getRow()), - Bytes.toString(CellUtil.cloneFamily(keyValue)), - Bytes.toString(CellUtil.cloneQualifier(keyValue)), - keyValue.getTimestamp(), Bytes.toString(CellUtil.cloneValue(keyValue))); - res_count += 1; - } - } - Assert.assertEquals(res_count, 1); - scanner.close(); - - scan = new Scan(); - scan.addFamily(family.getBytes()); - scan.setMaxVersions(10); - filter = new ColumnValueFilter(Bytes.toBytes("ff"), Bytes.toBytes(column1), - CompareOperator.NOT_EQUAL, Bytes.toBytes(value1)); - scan.setFilter(filter); - scanner = hTable.getScanner(scan); - - res_count = 0; - for (Result result : scanner) { - for (Cell keyValue : result.rawCells()) { - System.out - .printf( - "Rowkey: %s, Column Family: %s, Column Qualifier: %s, Timestamp: %d, Value: %s%n", - Bytes.toString(result.getRow()), - Bytes.toString(CellUtil.cloneFamily(keyValue)), - Bytes.toString(CellUtil.cloneQualifier(keyValue)), - keyValue.getTimestamp(), Bytes.toString(CellUtil.cloneValue(keyValue))); - res_count += 1; - } - } - Assert.assertEquals(res_count, 0); - scanner.close(); - } finally { - hTable.delete(deleteKey1Family); - hTable.delete(deleteKey2Family); - } - } - @Test public void testFuzzyRowFilter() throws Exception { String key1 = "abab"; @@ -2890,7 +2695,7 @@ public void testGetFilter() throws Exception { get = new Get(toBytes(key1)); get.setMaxVersions(10); get.addFamily(toBytes(family)); - valueFilter = new ValueFilter(CompareFilter.CompareOp.LESS, new BinaryComparator( + valueFilter = new ValueFilter(CompareFilter.CompareOp.GREATER, new BinaryComparator( toBytes(value1))); get.setFilter(valueFilter); r = hTable.get(get); @@ -2908,7 +2713,7 @@ public void testGetFilter() throws Exception { get = new Get(toBytes(key1)); get.setMaxVersions(10); get.addFamily(toBytes(family)); - valueFilter = new ValueFilter(CompareFilter.CompareOp.LESS, new BinaryComparator( + valueFilter = new ValueFilter(CompareFilter.CompareOp.GREATER, new BinaryComparator( toBytes(value3))); get.setFilter(valueFilter); r = hTable.get(get); @@ -2948,7 +2753,7 @@ public void testGetFilter() throws Exception { get = new Get(toBytes(key1)); get.setMaxVersions(10); get.addFamily(toBytes(family)); - qualifierFilter = new QualifierFilter(CompareFilter.CompareOp.LESS, + qualifierFilter = new QualifierFilter(CompareFilter.CompareOp.GREATER, new BinaryComparator(toBytes(column1))); get.setFilter(qualifierFilter); r = hTable.get(get); @@ -3073,7 +2878,7 @@ public void testGetFilter() throws Exception { filterList = new FilterList(); filterList.addFilter(new ColumnCountGetFilter(1)); - filterList.addFilter(new QualifierFilter(CompareFilter.CompareOp.LESS, + filterList.addFilter(new QualifierFilter(CompareFilter.CompareOp.GREATER, new BinaryComparator(toBytes(column2)))); get = new Get(toBytes(key1)); get.setMaxVersions(10); @@ -3274,7 +3079,7 @@ public void testGetFilter() throws Exception { Assert.assertEquals(7, r.rawCells().length); singleColumnValueFilter = new SingleColumnValueFilter(Bytes.toBytes(family), - Bytes.toBytes(column2), CompareFilter.CompareOp.LESS, new BinaryComparator( + Bytes.toBytes(column2), CompareFilter.CompareOp.GREATER, new BinaryComparator( toBytes(value2))); singleColumnValueFilter.setLatestVersionOnly(false); get = new Get(toBytes(key1)); @@ -5032,71 +4837,6 @@ public void testCheckAndPut() throws IOException, InterruptedException { r = hTable.get(get); Assert.assertEquals(3, r.rawCells().length); Assert.assertEquals("value1", Bytes.toString(CellUtil.cloneValue(r.rawCells()[0]))); - - // test CheckAndMutateBuilder - Delete delete = new Delete(key.getBytes()); - delete.addFamily(family.getBytes()); - hTable.delete(delete); - r = hTable.get(get); - Assert.assertEquals(0, r.rawCells().length); - - put = new Put(key.getBytes()); - put.addColumn(family.getBytes(), column.getBytes(), value.getBytes()); - hTable.put(put); - get = new Get(key.getBytes()); - get.setMaxVersions(Integer.MAX_VALUE); - get.addColumn(family.getBytes(), column.getBytes()); - r = hTable.get(get); - Assert.assertEquals(1, r.rawCells().length); - - Table.CheckAndMutateBuilder builder = hTable.checkAndMutate(toBytes(key), toBytes(family)); - put = new Put(key.getBytes()); - put.addColumn(family.getBytes(), column.getBytes(), "value1".getBytes()); - ret = builder.qualifier(toBytes(column)).ifEquals(toBytes(value)).thenPut(put); - Assert.assertTrue(ret); - Put difFamPut = new Put(key.getBytes()); - difFamPut.addColumn("family_group".getBytes(), column.getBytes(), "value1".getBytes()); - Assert.assertThrows(IOException.class, () -> { - builder.qualifier(toBytes(column)).ifEquals(toBytes(value)).thenPut(difFamPut); - }); - - ret = builder.qualifier(toBytes(column)) - .ifMatches(CompareOperator.LESS, toBytes("value1")).thenPut(put); - Assert.assertFalse(ret); - ret = builder.qualifier(toBytes(column)) - .ifMatches(CompareOperator.LESS_OR_EQUAL, toBytes("value1")).thenPut(put); - Assert.assertTrue(ret); - ret = builder.qualifier(toBytes(column)).ifMatches(CompareOperator.GREATER, toBytes("")) - .thenPut(put); - Assert.assertFalse(ret); - ret = builder.qualifier(toBytes(column)) - .ifMatches(CompareOperator.GREATER_OR_EQUAL, toBytes("")).thenPut(put); - Assert.assertFalse(ret); - - get = new Get(key.getBytes()); - get.setMaxVersions(Integer.MAX_VALUE); - get.addColumn(family.getBytes(), column.getBytes()); - r = hTable.get(get); - Assert.assertEquals(3, r.rawCells().length); - Assert.assertEquals("value1", Bytes.toString(CellUtil.cloneValue(r.rawCells()[0]))); - - // test TimeRange - long t = System.currentTimeMillis(); - put = new Put(key.getBytes()); - put.addColumn(family.getBytes(), column.getBytes(), t, value.getBytes()); - put.addColumn(family.getBytes(), column.getBytes(), t + 3, "value1".getBytes()); - put.addColumn(family.getBytes(), column.getBytes(), t + 5, "value2".getBytes()); - hTable.put(put); - put = new Put(toBytes(key)); - put.addColumn(toBytes(family), toBytes(column), toBytes(value)); - TimeRange timeRange = new TimeRange(t + 1, t + 3); - ret = builder.qualifier(toBytes(column)).timeRange(timeRange).ifEquals(toBytes("value1")) - .thenPut(put); - Assert.assertFalse(ret); - timeRange = new TimeRange(t, t + 2); - ret = builder.qualifier(toBytes(column)).timeRange(timeRange).ifEquals(toBytes(value)) - .thenPut(put); - Assert.assertTrue(ret); } @Test @@ -5202,29 +4942,31 @@ public void testCheckAndDelete() throws IOException { // check delete column delete = new Delete(key.getBytes()); delete.addColumn(family.getBytes(), column.getBytes()); - Table.CheckAndMutateBuilder builder = hTable.checkAndMutate(toBytes(key), toBytes(family)); - ret = builder.qualifier(toBytes(column)).ifEquals(toBytes(value)).thenDelete(delete); + RowMutations rowMutations = new RowMutations(key.getBytes()); + rowMutations.add(delete); + ret = hTable.checkAndMutate(key.getBytes(), family.getBytes(), column.getBytes(), + CompareFilter.CompareOp.EQUAL, value.getBytes(), rowMutations); Assert.assertTrue(ret); put = new Put(key.getBytes()); put.addColumn(family.getBytes(), column.getBytes(), "value6".getBytes()); hTable.put(put); - ret = builder.qualifier(toBytes(column)) - .ifMatches(CompareOperator.LESS, toBytes("value5")).thenDelete(delete); + ret = hTable.checkAndMutate(key.getBytes(), family.getBytes(), column.getBytes(), + CompareFilter.CompareOp.LESS, "value5".getBytes(), rowMutations); Assert.assertTrue(ret); put = new Put(key.getBytes()); put.addColumn(family.getBytes(), column.getBytes(), "value5".getBytes()); hTable.put(put); - ret = builder.qualifier(toBytes(column)) - .ifMatches(CompareOperator.LESS_OR_EQUAL, toBytes("value5")).thenDelete(delete); + ret = hTable.checkAndMutate(key.getBytes(), family.getBytes(), column.getBytes(), + CompareFilter.CompareOp.LESS_OR_EQUAL, "value5".getBytes(), rowMutations); Assert.assertTrue(ret); put = new Put(key.getBytes()); put.addColumn(family.getBytes(), column.getBytes(), "value1".getBytes()); hTable.put(put); - ret = builder.qualifier(toBytes(column)).ifMatches(CompareOperator.GREATER, toBytes("value1")) - .thenDelete(delete); + ret = hTable.checkAndMutate(key.getBytes(), family.getBytes(), column.getBytes(), + CompareFilter.CompareOp.GREATER, "value1".getBytes(), rowMutations); Assert.assertFalse(ret); - ret = builder.qualifier(toBytes(column)) - .ifMatches(CompareOperator.GREATER_OR_EQUAL, toBytes("value1")).thenDelete(delete); + ret = hTable.checkAndMutate(key.getBytes(), family.getBytes(), column.getBytes(), + CompareFilter.CompareOp.GREATER_OR_EQUAL, "value1".getBytes(), rowMutations); Assert.assertTrue(ret); get = new Get(key.getBytes()); @@ -5246,7 +4988,8 @@ public void testCheckAndDelete() throws IOException { Assert.assertEquals(2, r.rawCells().length); delete = new Delete(key.getBytes()); delete.addColumns(family.getBytes(), column.getBytes()); - ret = builder.qualifier(toBytes(column)).ifEquals(toBytes(value)).thenDelete(delete); + ret = hTable.checkAndDelete(key.getBytes(), family.getBytes(), column.getBytes(), + CompareFilter.CompareOp.EQUAL, value.getBytes(), delete); Assert.assertTrue(ret); get = new Get(key.getBytes()); get.setMaxVersions(Integer.MAX_VALUE); @@ -5267,28 +5010,6 @@ public void testCheckAndDelete() throws IOException { get.addFamily(family.getBytes()); r = hTable.get(get); Assert.assertEquals(4, r.rawCells().length); - - // test TimeRange - put = new Put(key.getBytes()); - put.addColumn(family.getBytes(), column.getBytes(), value.getBytes()); - TimeRange timeRange = new TimeRange(t + 2, t + 4); - ret = builder.qualifier(toBytes(column)).timeRange(timeRange).ifEquals(toBytes(value)) - .thenPut(put); - Assert.assertFalse(ret); - timeRange = new TimeRange(t, t + 2); - ret = builder.qualifier(toBytes(column)).timeRange(timeRange).ifEquals(toBytes(value)) - .thenPut(put); - Assert.assertTrue(ret); - - delete = new Delete(key.getBytes()); - delete.addFamily(family.getBytes()); - ret = builder.qualifier(toBytes(column)).ifEquals(toBytes(value)).thenDelete(delete); - Assert.assertTrue(ret); - get = new Get(key.getBytes()); - get.setMaxVersions(Integer.MAX_VALUE); - get.addFamily(family.getBytes()); - r = hTable.get(get); - Assert.assertEquals(0, r.rawCells().length); } @Test @@ -5459,9 +5180,8 @@ public void testCheckAndMutate() throws IOException { rowMutations.add(put3); //put data - Table.CheckAndMutateBuilder builder = hTable.checkAndMutate(toBytes(key), - family.getBytes(StandardCharsets.UTF_8)); - ret = builder.qualifier(toBytes(column1)).ifNotExists().thenMutate(rowMutations); + ret = hTable.checkAndMutate(key.getBytes(), family.getBytes(), column1.getBytes(), + CompareFilter.CompareOp.NOT_EQUAL, null, rowMutations); Assert.assertTrue(ret); get = new Get(key.getBytes()); @@ -5488,8 +5208,8 @@ public void testCheckAndMutate() throws IOException { rowMutations.add(put2); rowMutations.add(put3); // test LESS op - ret = builder.qualifier(toBytes(column1)).ifMatches(CompareOperator.LESS, toBytes(value1)) - .thenMutate(rowMutations); + ret = hTable.checkAndMutate(key.getBytes(), family.getBytes(), column1.getBytes(), + CompareFilter.CompareOp.LESS, value1.getBytes(), rowMutations); Assert.assertFalse(ret); get = new Get(key.getBytes()); get.addFamily(family.getBytes()); @@ -5498,8 +5218,8 @@ public void testCheckAndMutate() throws IOException { Assert.assertEquals(6, r.rawCells().length); // test less op - ret = builder.qualifier(toBytes(column1)).ifMatches(CompareOperator.GREATER, toBytes(value2)) - .thenMutate(rowMutations); + ret = hTable.checkAndMutate(key.getBytes(), family.getBytes(), column1.getBytes(), + CompareFilter.CompareOp.GREATER, value2.getBytes(), rowMutations); Assert.assertTrue(ret); get = new Get(key.getBytes()); get.addFamily(family.getBytes()); @@ -5526,16 +5246,16 @@ public void testCheckAndMutate() throws IOException { rowMutations.add(put3); // test NO_OP try { - builder.qualifier(toBytes(column1)).ifMatches(CompareOperator.NO_OP, toBytes(value1)) - .thenMutate(rowMutations); + hTable.checkAndMutate(key.getBytes(), family.getBytes(), column1.getBytes(), + CompareFilter.CompareOp.NO_OP, value1.getBytes(), rowMutations); fail(); } catch (Exception e) { Assert.assertTrue(e.getMessage().contains("checkAndMutate")); } // test equal op - ret = builder.qualifier(toBytes(column1)).ifEquals(toBytes(value1)) - .thenMutate(rowMutations); + ret = hTable.checkAndMutate(key.getBytes(), family.getBytes(), column1.getBytes(), + CompareFilter.CompareOp.EQUAL, value1.getBytes(), rowMutations); Assert.assertTrue(ret); get = new Get(key.getBytes()); get.addFamily(family.getBytes()); @@ -5557,8 +5277,8 @@ public void testCheckAndMutate() throws IOException { rowMutations = new RowMutations(key.getBytes()); rowMutations.add(delete1); rowMutations.add(put1); - ret = builder.qualifier(toBytes(column1)).ifEquals(toBytes(value1)) - .thenMutate(rowMutations); + ret = hTable.checkAndMutate(key.getBytes(), family.getBytes(), column1.getBytes(), + CompareFilter.CompareOp.EQUAL, value1.getBytes(), rowMutations); Assert.assertTrue(ret); get = new Get(key.getBytes()); get.addColumn(family.getBytes(), column1.getBytes()); @@ -5571,25 +5291,6 @@ public void testCheckAndMutate() throws IOException { get.setMaxVersions(Integer.MAX_VALUE); r = hTable.get(get); Assert.assertEquals(10, r.rawCells().length); - - // check TimeRange - put1 = new Put(toBytes(key)); - put1.addColumn(toBytes(family), toBytes(column1), toBytes(value1)); - rowMutations = new RowMutations(key.getBytes()); - rowMutations.add(put1); - rowMutations.add(delete1); - TimeRange timeRange = new TimeRange(t + 1, t + 3); - ret = builder.qualifier(toBytes(column1)).timeRange(timeRange).ifEquals(toBytes(value1)) - .thenMutate(rowMutations); - Assert.assertFalse(ret); - timeRange = new TimeRange(t, t + 2); - ret = builder.qualifier(toBytes(column1)).timeRange(timeRange).ifEquals(toBytes(value1)) - .thenMutate(rowMutations); - Assert.assertTrue(ret); - - delete = new Delete(key.getBytes()); - delete.addFamily(family.getBytes()); - hTable.delete(delete); } @Test @@ -6152,6 +5853,7 @@ public void testFamilyBlank() throws Exception { Assert.assertTrue(e.getMessage().contains("does not exist")); } Put put = new Put(key.getBytes()); + expectedException.expect(NullPointerException.class); put.addColumn(null, null, value.getBytes()); try { hTable.put(put); @@ -6239,6 +5941,7 @@ public void testScannerMultiVersion() throws Exception { @Test public void testPutColumnFamilyNull() throws Exception { Put put1 = new Put(("key_c_f").getBytes()); + expectedException.expect(NullPointerException.class); put1.addColumn(null, ("column1").getBytes(), "value1_family_null".getBytes()); expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("family is empty"); @@ -6276,8 +5979,9 @@ public void testPutColumnFamilyNotExists() throws Exception { @Test public void testGetColumnFamilyNull() throws Exception { Get get = new Get(("key_c_f").getBytes()); + expectedException.expect(NullPointerException.class); get.addFamily(null); - expectedException.expect(IllegalArgumentException.class); + expectedException.expect(FeatureNotSupportedException.class); expectedException.expectMessage("family is empty"); hTable.get(get); } diff --git a/src/test/java/com/alipay/oceanbase/hbase/OHConnectionTest.java b/src/test/java/com/alipay/oceanbase/hbase/OHConnectionTest.java index 3e4046ce..f336d887 100644 --- a/src/test/java/com/alipay/oceanbase/hbase/OHConnectionTest.java +++ b/src/test/java/com/alipay/oceanbase/hbase/OHConnectionTest.java @@ -81,7 +81,8 @@ public void testRefreshTableEntry() throws Exception { @After public void after() throws IOException { - if (hTable != null) hTable.close(); + if (hTable != null) + hTable.close(); } @Test @@ -841,7 +842,6 @@ public void testBufferedMutatorConcurrent() throws Exception { } } - /* CREATE TABLEGROUP test_region_locator SHARDING = 'ADAPTIVE'; CREATE TABLE `test_region_locator$family_region_locator` ( @@ -989,7 +989,7 @@ public void testRangePartitionWithRegionLocator() throws Exception { }); } } - + @Test public void testHRegionLocation() throws IOException { final String tableNameStr = "test_region_locator"; @@ -1034,7 +1034,7 @@ public void testHRegionLocation() throws IOException { }); } } - + @Test public void testKeyPartitionWithRegionLocator() throws IOException { final String tableNameStr = "test_multi_cf"; @@ -1078,7 +1078,7 @@ public void testBufferedMutatorPeriodicFlush() throws Exception { params = new BufferedMutatorParams(tableName); params.writeBufferSize(bufferSize); // set periodic flush timeout to enable Timer - params.setWriteBufferPeriodicFlushTimeoutMs(100); +// params.setWriteBufferPeriodicFlushTimeoutMs(100); // set thread pool long keepAliveTime = conf.getLong("hbase.hconnection.threads.keepalivetime", 60); diff --git a/src/test/java/com/alipay/oceanbase/hbase/OHTableAdminInterfaceTest.java b/src/test/java/com/alipay/oceanbase/hbase/OHTableAdminInterfaceTest.java index 748d21c8..88406e3c 100644 --- a/src/test/java/com/alipay/oceanbase/hbase/OHTableAdminInterfaceTest.java +++ b/src/test/java/com/alipay/oceanbase/hbase/OHTableAdminInterfaceTest.java @@ -17,7 +17,6 @@ package com.alipay.oceanbase.hbase; -import com.alipay.oceanbase.hbase.util.OHRegionMetrics; import com.alipay.oceanbase.hbase.util.ObHTableTestUtil; import com.alipay.oceanbase.hbase.exception.FeatureNotSupportedException; import com.alipay.oceanbase.hbase.util.ResultSetPrinter; @@ -33,19 +32,20 @@ import org.junit.Assert; import org.junit.Test; - import java.io.IOException; +import java.sql.SQLException; import java.sql.Statement; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; +import java.util.*; import java.util.concurrent.*; +import java.util.stream.Collectors; +import java.util.Map; import static com.alipay.oceanbase.hbase.constants.OHConstants.HBASE_HTABLE_TEST_LOAD_ENABLE; +import static com.alipay.oceanbase.hbase.util.ObHTableTestUtil.executeSQL; import static org.apache.hadoop.hbase.util.Bytes.toBytes; import static org.junit.Assert.*; import static org.junit.Assert.assertFalse; -import static com.alipay.oceanbase.hbase.util.ObHTableSecondaryPartUtil.*; +import static com.alipay.oceanbase.hbase.util.ObHTableSecondaryPartUtil.*; public class OHTableAdminInterfaceTest { public OHTablePool setUpLoadPool() throws IOException { @@ -67,6 +67,55 @@ public OHTablePool setUpPool() throws IOException { return ohTablePool; } + enum ErrSimPoint { + EN_CREATE_HTABLE_TG_FINISH_ERR(2621), EN_CREATE_HTABLE_CF_FINISH_ERR(2622), EN_DISABLE_HTABLE_CF_FINISH_ERR( + 2623), EN_DELETE_HTABLE_CF_FINISH_ERR( + 2624); + + private final int errCode; + + ErrSimPoint(int errCode) { + this.errCode = errCode; + } + + public int getErrCode() { + return errCode; + } + } + + private void setErrSimPoint(ErrSimPoint errSimPoint, boolean enable) { + java.sql.Connection connection = null; + java.sql.Statement statement = null; + + try { + connection = ObHTableTestUtil.getSysTenantConnection(); + statement = connection.createStatement(); + + String sql = String.format( + "alter system set_tp tp_no = %d, error_code = 4016, frequency = %d", + errSimPoint.getErrCode(), enable ? 1 : 0); + + statement.execute(sql); + } catch (Exception e) { + throw new RuntimeException("Error injection setup failed", e); + } finally { + if (statement != null) { + try { + statement.close(); + } catch (Exception e) { + // ignore + } + } + if (connection != null) { + try { + connection.close(); + } catch (Exception e) { + // ignore + } + } + } + } + @Test public void testGetStartEndKeysOHTableClientRange() throws Exception { // Init OHTableClient @@ -269,145 +318,147 @@ public void testGetStartEndKeysOHTablePoolLoadNon() throws Exception { Assert.assertEquals(0, startEndKeys.getSecond()[0].length); } + public static void createTable(Admin admin, TableName tableName, String... columnFamilies) + throws IOException { + HTableDescriptor htd = new HTableDescriptor(tableName); + // Add column families + for (String cf : columnFamilies) { + HColumnDescriptor hcd = new HColumnDescriptor(Bytes.toBytes(cf)); + htd.addFamily(hcd); + } + // Create the table + admin.createTable(htd); + } + @Test public void testAdminEnDisableTable() throws Exception { java.sql.Connection conn = ObHTableTestUtil.getConnection(); Statement st = conn.createStatement(); - st.execute("CREATE TABLEGROUP IF NOT EXISTS test_multi_cf SHARDING = 'ADAPTIVE';\n" + - "\n" + - "CREATE TABLE IF NOT EXISTS `test_multi_cf$family_with_group1` (\n" + - " `K` varbinary(1024) NOT NULL,\n" + - " `Q` varbinary(256) NOT NULL,\n" + - " `T` bigint(20) NOT NULL,\n" + - " `V` varbinary(1024) DEFAULT NULL,\n" + - " PRIMARY KEY (`K`, `Q`, `T`)\n" + - ") TABLEGROUP = test_multi_cf PARTITION BY KEY(`K`) PARTITIONS 3;\n" + - "\n" + - "CREATE TABLE IF NOT EXISTS `test_multi_cf$family_with_group2` (\n" + - " `K` varbinary(1024) NOT NULL,\n" + - " `Q` varbinary(256) NOT NULL,\n" + - " `T` bigint(20) NOT NULL,\n" + - " `V` varbinary(1024) DEFAULT NULL,\n" + - " PRIMARY KEY (`K`, `Q`, `T`)\n" + - ") TABLEGROUP = test_multi_cf PARTITION BY KEY(`K`) PARTITIONS 3;\n" + - "\n" + - "CREATE TABLE IF NOT EXISTS `test_multi_cf$family_with_group3` (\n" + - " `K` varbinary(1024) NOT NULL,\n" + - " `Q` varbinary(256) NOT NULL,\n" + - " `T` bigint(20) NOT NULL,\n" + - " `V` varbinary(1024) DEFAULT NULL,\n" + - " PRIMARY KEY (`K`, `Q`, `T`)\n" + - ") TABLEGROUP = test_multi_cf PARTITION BY KEY(`K`) PARTITIONS 3;\n" + - "\n" + - "CREATE DATABASE IF NOT EXISTS `n1`;\n" + - "use `n1`;\n" + - "CREATE TABLEGROUP IF NOT EXISTS `n1:test` SHARDING = 'ADAPTIVE';\n" + - "CREATE TABLE IF NOT EXISTS `n1:test$family_group` (\n" + - " `K` varbinary(1024) NOT NULL,\n" + - " `Q` varbinary(256) NOT NULL,\n" + - " `T` bigint(20) NOT NULL,\n" + - " `V` varbinary(1024) DEFAULT NULL,\n" + - " PRIMARY KEY (`K`, `Q`, `T`)\n" + - ") TABLEGROUP = `n1:test`;" + - "\n" + - "CREATE TABLE IF NOT EXISTS `n1:test$family1` (\n" + - " `K` varbinary(1024) NOT NULL,\n" + - " `Q` varbinary(256) NOT NULL,\n" + - " `T` bigint(20) NOT NULL,\n" + - " `V` varbinary(1024) DEFAULT NULL,\n" + - " PRIMARY KEY (`K`, `Q`, `T`)\n" + - ") TABLEGROUP = `n1:test`;"); + st.execute("CREATE DATABASE IF NOT EXISTS `en_dis`"); + st.close(); + conn.close(); Configuration conf = ObHTableTestUtil.newConfiguration(); Connection connection = ConnectionFactory.createConnection(conf); Admin admin = connection.getAdmin(); - assertTrue(admin.tableExists(TableName.valueOf("n1", "test"))); - assertTrue(admin.tableExists(TableName.valueOf("test_multi_cf"))); - // 1. disable a non-existed table - { - IOException thrown = assertThrows(IOException.class, - () -> { - admin.disableTable(TableName.valueOf("tablegroup_not_exists")); - }); - assertTrue(thrown.getCause() instanceof ObTableException); - Assert.assertEquals(ResultCodes.OB_TABLEGROUP_NOT_EXIST.errorCode, ((ObTableException) thrown.getCause()).getErrorCode()); - } - // 2. write an enabled table, should succeed - { - if (admin.isTableDisabled(TableName.valueOf("test_multi_cf"))) { - admin.enableTable(TableName.valueOf("test_multi_cf")); + try { + createTable(admin, TableName.valueOf("test_en_dis_tb"), "cf1", "cf2", "cf3"); + createTable(admin, TableName.valueOf("en_dis", "test"), "cf1", "cf2", "cf3"); + assertTrue(admin.tableExists(TableName.valueOf("en_dis", "test"))); + assertTrue(admin.tableExists(TableName.valueOf("test_en_dis_tb"))); + String kvAttrStrDefault = "{\"Hbase\": {\"MaxVersions\": 1, \"CreatedBy\": \"Admin\"}}"; + String kvAttributeDisable = "{\"Hbase\": {\"MaxVersions\": 1, \"CreatedBy\": \"Admin\", \"State\": \"disable\"}}"; + String kvAttributeEnable = "{\"Hbase\": {\"MaxVersions\": 1, \"CreatedBy\": \"Admin\", \"State\": \"enable\"}}"; + + checkKVAttributes("test_en_dis_tb$cf1", kvAttrStrDefault); + checkKVAttributes("test_en_dis_tb$cf2", kvAttrStrDefault); + checkKVAttributes("test_en_dis_tb$cf3", kvAttrStrDefault); + // 1. disable a non-existed table + { + IOException thrown = assertThrows(IOException.class, + () -> { + admin.disableTable(TableName.valueOf("tablegroup_not_exists")); + }); + assertTrue(thrown.getCause() instanceof ObTableException); + Assert.assertEquals(ResultCodes.OB_TABLEGROUP_NOT_EXIST.errorCode, ((ObTableException) thrown.getCause()).getErrorCode()); } - batchInsert(10, "test_multi_cf"); - batchGet(10, "test_multi_cf"); - } + // 2. write an enabled table, should succeed + { + if (admin.isTableDisabled(TableName.valueOf("test_en_dis_tb"))) { + admin.enableTable(TableName.valueOf("test_en_dis_tb")); + } + checkKVAttributes("test_en_dis_tb$cf1", kvAttrStrDefault); + checkKVAttributes("test_en_dis_tb$cf2", kvAttrStrDefault); + checkKVAttributes("test_en_dis_tb$cf3", kvAttrStrDefault); - // 3. disable a enable table - { - if (admin.isTableEnabled(TableName.valueOf("test_multi_cf"))) { - admin.disableTable(TableName.valueOf("test_multi_cf")); - } - // write and read disable table, should fail - try { - batchInsert(10, "test_multi_cf"); - Assert.fail(); - } catch (IOException ex) { - Assert.assertTrue(ex.getCause() instanceof ObTableException); - System.out.println(ex.getCause().getMessage()); - } - try { - batchGet(10, "test_multi_cf"); - Assert.fail(); - } catch (IOException ex) { - Assert.assertTrue(ex.getCause() instanceof ObTableException); - Assert.assertEquals(ResultCodes.OB_KV_TABLE_NOT_ENABLED.errorCode, - ((ObTableException) ex.getCause()).getErrorCode()); + batchInsert(10, "test_en_dis_tb"); + batchGet(10, "test_en_dis_tb"); } - } + // 3. disable a enable table + { + if (admin.isTableEnabled(TableName.valueOf("test_en_dis_tb"))) { + admin.disableTable(TableName.valueOf("test_en_dis_tb")); + } + checkKVAttributes("test_en_dis_tb$cf1", kvAttributeDisable); + checkKVAttributes("test_en_dis_tb$cf2", kvAttributeDisable); + checkKVAttributes("test_en_dis_tb$cf3", kvAttributeDisable); + // write and read disable table, should fail + try { + batchInsert(10, "test_en_dis_tb"); + Assert.fail(); + } catch (IOException ex) { + Assert.assertTrue(ex.getCause() instanceof ObTableException); + System.out.println(ex.getCause().getMessage()); + } + try { + batchGet(10, "test_en_dis_tb"); + Assert.fail(); + } catch (IOException ex) { + Assert.assertTrue(ex.getCause() instanceof ObTableException); + Assert.assertEquals(ResultCodes.OB_KV_TABLE_NOT_ENABLED.errorCode, + ((ObTableException) ex.getCause()).getErrorCode()); + } - // 4. enable a disabled table - { - if (admin.isTableDisabled(TableName.valueOf("test_multi_cf"))) { - admin.enableTable(TableName.valueOf("test_multi_cf")); } - // write an enabled table, should succeed - batchInsert(10, "test_multi_cf"); - batchGet(10, "test_multi_cf"); - } - // 5. enable an enabled table - { - if (admin.isTableDisabled(TableName.valueOf("n1", "test"))) { - admin.enableTable(TableName.valueOf("n1", "test")); - } - try { - admin.enableTable(TableName.valueOf("n1", "test")); - Assert.fail(); - } catch (IOException ex) { - Assert.assertTrue(ex.getCause() instanceof ObTableException); - Assert.assertEquals(ResultCodes.OB_KV_TABLE_NOT_DISABLED.errorCode, - ((ObTableException) ex.getCause()).getErrorCode()); + // 4. enable a disabled table + { + if (admin.isTableDisabled(TableName.valueOf("test_en_dis_tb"))) { + admin.enableTable(TableName.valueOf("test_en_dis_tb")); + } + checkKVAttributes("test_en_dis_tb$cf1", kvAttributeEnable); + checkKVAttributes("test_en_dis_tb$cf2", kvAttributeEnable); + checkKVAttributes("test_en_dis_tb$cf3", kvAttributeEnable); + // write an enabled table, should succeed + batchInsert(10, "test_en_dis_tb"); + batchGet(10, "test_en_dis_tb"); } - } - // 6. disable a disabled table - { - if (admin.isTableEnabled(TableName.valueOf("n1", "test"))) { - admin.disableTable(TableName.valueOf("n1", "test")); + // 5. enable an enabled table + { + if (admin.isTableDisabled(TableName.valueOf("en_dis", "test"))) { + admin.enableTable(TableName.valueOf("en_dis", "test")); + } + checkKVAttributes("en_dis:test$cf1", kvAttrStrDefault); + checkKVAttributes("en_dis:test$cf2", kvAttrStrDefault); + checkKVAttributes("en_dis:test$cf3", kvAttrStrDefault); + try { + admin.enableTable(TableName.valueOf("en_dis", "test")); + Assert.fail(); + } catch (IOException ex) { + Assert.assertTrue(ex.getCause() instanceof ObTableException); + Assert.assertEquals(ResultCodes.OB_KV_TABLE_NOT_ENABLED.errorCode, + ((ObTableException) ex.getCause()).getErrorCode()); + } } - try { - admin.disableTable(TableName.valueOf("n1", "test")); - Assert.fail(); - } catch (IOException ex) { - Assert.assertTrue(ex.getCause() instanceof ObTableException); - Assert.assertEquals(ResultCodes.OB_KV_TABLE_NOT_ENABLED.errorCode, - ((ObTableException) ex.getCause()).getErrorCode()); + + // 6. disable a disabled table + { + if (admin.isTableEnabled(TableName.valueOf("en_dis", "test"))) { + admin.disableTable(TableName.valueOf("en_dis", "test")); + } + checkKVAttributes("en_dis:test$cf1", kvAttributeDisable); + checkKVAttributes("en_dis:test$cf1", kvAttributeDisable); + checkKVAttributes("en_dis:test$cf1", kvAttributeDisable); + try { + admin.disableTable(TableName.valueOf("en_dis", "test")); + Assert.fail(); + } catch (IOException ex) { + Assert.assertTrue(ex.getCause() instanceof ObTableException); + Assert.assertEquals(ResultCodes.OB_KV_TABLE_NOT_DISABLED.errorCode, + ((ObTableException) ex.getCause()).getErrorCode()); + } } - } - admin.deleteTable(TableName.valueOf("test_multi_cf")); - assertFalse(admin.tableExists(TableName.valueOf("test_multi_cf"))); - admin.deleteTable(TableName.valueOf("n1", "test")); - assertFalse(admin.tableExists(TableName.valueOf("n1", "test"))); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } finally { + admin.deleteTable(TableName.valueOf("test_en_dis_tb")); + assertFalse(admin.tableExists(TableName.valueOf("test_en_dis_tb"))); + admin.deleteTable(TableName.valueOf("en_dis", "test")); + assertFalse(admin.tableExists(TableName.valueOf("en_dis", "test"))); + } } private void batchGet(int rows, String tablegroup) throws Exception { @@ -429,108 +480,90 @@ private void batchGet(int rows, String tablegroup) throws Exception { } @Test - public void testAdminGetRegionMetrics() throws Exception { + public void testRegionLoad() throws Exception { java.sql.Connection conn = ObHTableTestUtil.getConnection(); Statement st = conn.createStatement(); - st.execute("CREATE TABLEGROUP IF NOT EXISTS test_multi_cf SHARDING = 'ADAPTIVE';\n" + - "CREATE TABLE IF NOT EXISTS `test_multi_cf$family_with_group1` (\n" + - " `K` varbinary(1024) NOT NULL,\n" + - " `Q` varbinary(256) NOT NULL,\n" + - " `T` bigint(20) NOT NULL,\n" + - " `V` varbinary(1024) DEFAULT NULL,\n" + - " PRIMARY KEY (`K`, `Q`, `T`)\n" + - ") TABLEGROUP = test_multi_cf PARTITION BY KEY(`K`) PARTITIONS 10;\n" + - "CREATE TABLE IF NOT EXISTS `test_multi_cf$family_with_group2` (\n" + - " `K` varbinary(1024) NOT NULL,\n" + - " `Q` varbinary(256) NOT NULL,\n" + - " `T` bigint(20) NOT NULL,\n" + - " `V` varbinary(1024) DEFAULT NULL,\n" + - " PRIMARY KEY (`K`, `Q`, `T`)\n" + - ") TABLEGROUP = test_multi_cf PARTITION BY KEY(`K`) PARTITIONS 10;\n" + - "CREATE TABLE IF NOT EXISTS `test_multi_cf$family_with_group3` (\n" + - " `K` varbinary(1024) NOT NULL,\n" + - " `Q` varbinary(256) NOT NULL,\n" + - " `T` bigint(20) NOT NULL,\n" + - " `V` varbinary(1024) DEFAULT NULL,\n" + - " PRIMARY KEY (`K`, `Q`, `T`)\n" + - ") TABLEGROUP = test_multi_cf PARTITION BY KEY(`K`) PARTITIONS 10;\n" + - "CREATE TABLEGROUP IF NOT EXISTS test_no_part SHARDING = 'ADAPTIVE';\n"+ - "CREATE TABLE IF NOT EXISTS `test_no_part$family_with_group1` (\n" + + st.execute("CREATE TABLEGROUP IF NOT EXISTS test_get_region_metrics SHARDING = 'ADAPTIVE';\n" + + "\n" + + "CREATE TABLE IF NOT EXISTS `test_get_region_metrics$family_with_group1` (\n" + " `K` varbinary(1024) NOT NULL,\n" + " `Q` varbinary(256) NOT NULL,\n" + " `T` bigint(20) NOT NULL,\n" + " `V` varbinary(1024) DEFAULT NULL,\n" + " PRIMARY KEY (`K`, `Q`, `T`)\n" + - ") TABLEGROUP = test_no_part;\n" + - "CREATE TABLE IF NOT EXISTS `test_no_part$family_with_group2` (\n" + + ") TABLEGROUP = test_get_region_metrics PARTITION BY KEY(`K`) PARTITIONS 3;\n" + + "\n" + + "CREATE TABLE IF NOT EXISTS `test_get_region_metrics$family_with_group2` (\n" + " `K` varbinary(1024) NOT NULL,\n" + " `Q` varbinary(256) NOT NULL,\n" + " `T` bigint(20) NOT NULL,\n" + " `V` varbinary(1024) DEFAULT NULL,\n" + " PRIMARY KEY (`K`, `Q`, `T`)\n" + - ") TABLEGROUP = test_no_part;\n" + - "CREATE TABLE IF NOT EXISTS `test_no_part$family_with_group3` (\n" + + ") TABLEGROUP = test_get_region_metrics PARTITION BY KEY(`K`) PARTITIONS 3;\n" + + "\n" + + "CREATE TABLE IF NOT EXISTS `test_get_region_metrics$family_with_group3` (\n" + " `K` varbinary(1024) NOT NULL,\n" + " `Q` varbinary(256) NOT NULL,\n" + " `T` bigint(20) NOT NULL,\n" + " `V` varbinary(1024) DEFAULT NULL,\n" + " PRIMARY KEY (`K`, `Q`, `T`)\n" + - ") TABLEGROUP = test_no_part;\n" + - "CREATE DATABASE IF NOT EXISTS `n1`;\n" + - "use `n1`;\n" + - "CREATE TABLEGROUP IF NOT EXISTS `n1:test_multi_cf` SHARDING = 'ADAPTIVE';\n" + - "CREATE TABLE IF NOT EXISTS `n1:test_multi_cf$family_with_group1` (\n" + + ") TABLEGROUP = test_get_region_metrics PARTITION BY KEY(`K`) PARTITIONS 3;\n" + + "\n" + + "CREATE DATABASE IF NOT EXISTS `get_region`;\n" + + "use `get_region`;\n" + + "CREATE TABLEGROUP IF NOT EXISTS `get_region:test_multi_cf` SHARDING = 'ADAPTIVE';\n" + + "CREATE TABLE IF NOT EXISTS `get_region:test_multi_cf$family_with_group1` (\n" + " `K` varbinary(1024) NOT NULL,\n" + " `Q` varbinary(256) NOT NULL,\n" + " `T` bigint(20) NOT NULL,\n" + " `V` varbinary(1024) DEFAULT NULL,\n" + " PRIMARY KEY (`K`, `Q`, `T`)\n" + - ") TABLEGROUP = `n1:test_multi_cf` PARTITION BY KEY(`K`) PARTITIONS 3;\n" + - "CREATE TABLE IF NOT EXISTS `n1:test_multi_cf$family_with_group2` (\n" + + ") TABLEGROUP = `get_region:test_multi_cf` PARTITION BY KEY(`K`) PARTITIONS 3;\n" + + "CREATE TABLE IF NOT EXISTS `get_region:test_multi_cf$family_with_group2` (\n" + " `K` varbinary(1024) NOT NULL,\n" + " `Q` varbinary(256) NOT NULL,\n" + " `T` bigint(20) NOT NULL,\n" + " `V` varbinary(1024) DEFAULT NULL,\n" + " PRIMARY KEY (`K`, `Q`, `T`)\n" + - ") TABLEGROUP = `n1:test_multi_cf` PARTITION BY KEY(`K`) PARTITIONS 3;\n" + - "CREATE TABLE IF NOT EXISTS `n1:test_multi_cf$family_with_group3` (\n" + + ") TABLEGROUP = `get_region:test_multi_cf` PARTITION BY KEY(`K`) PARTITIONS 3;\n" + + "CREATE TABLE IF NOT EXISTS `get_region:test_multi_cf$family_with_group3` (\n" + " `K` varbinary(1024) NOT NULL,\n" + " `Q` varbinary(256) NOT NULL,\n" + " `T` bigint(20) NOT NULL,\n" + " `V` varbinary(1024) DEFAULT NULL,\n" + " PRIMARY KEY (`K`, `Q`, `T`)\n" + - ") TABLEGROUP = `n1:test_multi_cf` PARTITION BY KEY(`K`) PARTITIONS 3;"); + ") TABLEGROUP = `get_region:test_multi_cf` PARTITION BY KEY(`K`) PARTITIONS 3;"); st.close(); conn.close(); - String tablegroup1 = "test_multi_cf"; - String tablegroup2 = "n1:test_multi_cf"; + String tablegroup1 = "test_get_region_metrics"; + String tablegroup2 = "get_region:test_multi_cf"; Configuration conf = ObHTableTestUtil.newConfiguration(); Connection connection = ConnectionFactory.createConnection(conf); Admin admin = connection.getAdmin(); // test tablegroup not existed IOException thrown = assertThrows(IOException.class, () -> { - admin.getRegionMetrics(null, TableName.valueOf("tablegroup_not_exists")); + admin.getRegionLoad(ServerName.valueOf("localhost,1,1"), TableName.valueOf("tablegroup_not_exists")); }); Assert.assertTrue(thrown.getCause() instanceof ObTableException); Assert.assertEquals(ResultCodes.OB_TABLEGROUP_NOT_EXIST.errorCode, ((ObTableException) thrown.getCause()).getErrorCode()); - // test use serverName without tableName to get region metrics + // test use serverName without tableName to get region load assertThrows(FeatureNotSupportedException.class, () -> { - admin.getRegionMetrics(ServerName.valueOf("localhost,1,1")); + admin.getRegionLoad(ServerName.valueOf("localhost,1,1")); }); - // test single-thread getRegionMetrics after writing + // test single-thread getRegionLoad after writing batchInsert(100000, tablegroup1); // test ServerName is any string long start = System.currentTimeMillis(); - List metrics = admin.getRegionMetrics(ServerName.valueOf("localhost,1,1"), TableName.valueOf(tablegroup1)); + Map regionLoadMap = admin.getRegionLoad(ServerName.valueOf("localhost,1,1"), TableName.valueOf(tablegroup1)); long cost = System.currentTimeMillis() - start; - System.out.println("get region metrics time usage: " + cost + "ms, tablegroup: " + tablegroup1); - assertEquals(30, metrics.size()); + System.out.println("get region load time usage: " + cost + "ms, tablegroup: " + tablegroup1); + assertEquals(30, regionLoadMap.size()); - // test getRegionMetrics concurrently reading while writing + // test getRegionLoad concurrently reading while writing ExecutorService executorService = Executors.newFixedThreadPool(10); CountDownLatch latch = new CountDownLatch(100); List exceptionCatcher = new ArrayList<>(); @@ -539,25 +572,25 @@ public void testAdminGetRegionMetrics() throws Exception { executorService.submit(() -> { try { if (taskId % 2 == 1) { - List regionMetrics = null; - // test get regionMetrics from different namespaces + Map regionLoad = null; + // test get regionLoad from different namespaces if (taskId % 3 != 0) { long thrStart = System.currentTimeMillis(); - regionMetrics = admin.getRegionMetrics(null, TableName.valueOf(tablegroup1)); + regionLoad = admin.getRegionLoad(ServerName.valueOf("localhost,1,1"), TableName.valueOf(tablegroup1)); long thrCost = System.currentTimeMillis() - thrStart; - System.out.println("task: " + taskId + ", get region metrics time usage: " + thrCost + "ms, tablegroup: " + tablegroup1); - if (regionMetrics.size() != 30) { + System.out.println("task: " + taskId + ", get region load time usage: " + thrCost + "ms, tablegroup: " + tablegroup1); + if (regionLoad.size() != 30) { throw new ObTableGetException( - "the number of region metrics does not match the number of tablets, the number of region metrics: " + regionMetrics.size()); + "the number of region load does not match the number of tablets, the number of region load: " + regionLoad.size()); } } else { long thrStart = System.currentTimeMillis(); - regionMetrics = admin.getRegionMetrics(null, TableName.valueOf(tablegroup2)); + regionLoad = admin.getRegionLoad(ServerName.valueOf("localhost,1,1"), TableName.valueOf(tablegroup2)); long thrCost = System.currentTimeMillis() - thrStart; - System.out.println("task: " + taskId + ", get region metrics time usage: " + thrCost + "ms, tablegroup: " + tablegroup1); - if (regionMetrics.size() != 9) { + System.out.println("task: " + taskId + ", get region load time usage: " + thrCost + "ms, tablegroup: " + tablegroup1); + if (regionLoad.size() != 9) { throw new ObTableGetException( - "the number of region metrics does not match the number of tablets, the number of region metrics: " + regionMetrics.size()); + "the number of region load does not match the number of tablets, the number of region load: " + regionLoad.size()); } } } else { @@ -598,93 +631,47 @@ public void testAdminGetRegionMetrics() throws Exception { executorService.shutdownNow(); Assert.assertTrue(exceptionCatcher.isEmpty()); - // test getRegionMetrics from non-partitioned table + // test getRegionLoad from non-partitioned table String non_part_tablegroup = "test_no_part"; batchInsert(10000, non_part_tablegroup); start = System.currentTimeMillis(); - metrics = admin.getRegionMetrics(null, TableName.valueOf(non_part_tablegroup)); + regionLoadMap = admin.getRegionLoad(ServerName.valueOf("localhost,1,1"), TableName.valueOf(non_part_tablegroup)); cost = System.currentTimeMillis() - start; - System.out.println("get region metrics time usage: " + cost + "ms, tablegroup: " + non_part_tablegroup); - assertEquals(3, metrics.size()); + System.out.println("get region load time usage: " + cost + "ms, tablegroup: " + non_part_tablegroup); + assertEquals(3, regionLoadMap.size()); } @Test public void testAdminDeleteTable() throws Exception { java.sql.Connection conn = ObHTableTestUtil.getConnection(); Statement st = conn.createStatement(); - st.execute("CREATE TABLEGROUP IF NOT EXISTS test_multi_cf SHARDING = 'ADAPTIVE';\n" + - "CREATE TABLE IF NOT EXISTS `test_multi_cf$family_with_group1` (\n" + - " `K` varbinary(1024) NOT NULL,\n" + - " `Q` varbinary(256) NOT NULL,\n" + - " `T` bigint(20) NOT NULL,\n" + - " `V` varbinary(1024) DEFAULT NULL,\n" + - " PRIMARY KEY (`K`, `Q`, `T`)\n" + - ") TABLEGROUP = test_multi_cf PARTITION BY KEY(`K`) PARTITIONS 10;\n" + - "CREATE TABLE IF NOT EXISTS `test_multi_cf$family_with_group2` (\n" + - " `K` varbinary(1024) NOT NULL,\n" + - " `Q` varbinary(256) NOT NULL,\n" + - " `T` bigint(20) NOT NULL,\n" + - " `V` varbinary(1024) DEFAULT NULL,\n" + - " PRIMARY KEY (`K`, `Q`, `T`)\n" + - ") TABLEGROUP = test_multi_cf PARTITION BY KEY(`K`) PARTITIONS 10;\n" + - "CREATE TABLE IF NOT EXISTS `test_multi_cf$family_with_group3` (\n" + - " `K` varbinary(1024) NOT NULL,\n" + - " `Q` varbinary(256) NOT NULL,\n" + - " `T` bigint(20) NOT NULL,\n" + - " `V` varbinary(1024) DEFAULT NULL,\n" + - " PRIMARY KEY (`K`, `Q`, `T`)\n" + - ") TABLEGROUP = test_multi_cf PARTITION BY KEY(`K`) PARTITIONS 10;\n" + - "CREATE DATABASE IF NOT EXISTS `n1`;\n" + - "use `n1`;\n" + - "CREATE TABLEGROUP IF NOT EXISTS `n1:test_multi_cf` SHARDING = 'ADAPTIVE';\n" + - "CREATE TABLE IF NOT EXISTS `n1:test_multi_cf$family_with_group1` (\n" + - " `K` varbinary(1024) NOT NULL,\n" + - " `Q` varbinary(256) NOT NULL,\n" + - " `T` bigint(20) NOT NULL,\n" + - " `V` varbinary(1024) DEFAULT NULL,\n" + - " PRIMARY KEY (`K`, `Q`, `T`)\n" + - ") TABLEGROUP = `n1:test_multi_cf` PARTITION BY KEY(`K`) PARTITIONS 3;\n" + - "CREATE TABLE IF NOT EXISTS `n1:test_multi_cf$family_with_group2` (\n" + - " `K` varbinary(1024) NOT NULL,\n" + - " `Q` varbinary(256) NOT NULL,\n" + - " `T` bigint(20) NOT NULL,\n" + - " `V` varbinary(1024) DEFAULT NULL,\n" + - " PRIMARY KEY (`K`, `Q`, `T`)\n" + - ") TABLEGROUP = `n1:test_multi_cf` PARTITION BY KEY(`K`) PARTITIONS 3;"); + st.execute("CREATE DATABASE IF NOT EXISTS `del_tb`"); st.close(); conn.close(); Configuration conf = ObHTableTestUtil.newConfiguration(); Connection connection = ConnectionFactory.createConnection(conf); Admin admin = connection.getAdmin(); - assertTrue(admin.tableExists(TableName.valueOf("n1", "test_multi_cf"))); - assertTrue(admin.tableExists(TableName.valueOf("test_multi_cf"))); + createTable(admin, TableName.valueOf("test_del_tb"), "cf1", "cf2", "cf3"); + createTable(admin, TableName.valueOf("del_tb", "test"), "cf1", "cf2", "cf3"); + assertTrue(admin.tableExists(TableName.valueOf("del_tb", "test"))); + assertTrue(admin.tableExists(TableName.valueOf("test_del_tb"))); IOException thrown = assertThrows(IOException.class, () -> { admin.deleteTable(TableName.valueOf("tablegroup_not_exists")); }); Assert.assertTrue(thrown.getCause() instanceof ObTableException); Assert.assertEquals(ResultCodes.OB_TABLEGROUP_NOT_EXIST.errorCode, ((ObTableException) thrown.getCause()).getErrorCode()); - admin.deleteTable(TableName.valueOf("n1", "test_multi_cf")); - admin.deleteTable(TableName.valueOf("test_multi_cf")); - assertFalse(admin.tableExists(TableName.valueOf("n1", "test_multi_cf"))); - assertFalse(admin.tableExists(TableName.valueOf("test_multi_cf"))); + admin.deleteTable(TableName.valueOf("del_tb", "test")); + admin.deleteTable(TableName.valueOf("test_del_tb")); + assertFalse(admin.tableExists(TableName.valueOf("del_tb", "test"))); + assertFalse(admin.tableExists(TableName.valueOf("test_del_tb"))); } @Test public void testAdminTableExists() throws Exception { java.sql.Connection conn = ObHTableTestUtil.getConnection(); Statement st = conn.createStatement(); - st.execute("CREATE TABLEGROUP IF NOT EXISTS test_multi_cf SHARDING = 'ADAPTIVE';\n" + - "CREATE TABLE IF NOT EXISTS `test_multi_cf$family_with_group1` (\n" + - " `K` varbinary(1024) NOT NULL,\n" + - " `Q` varbinary(256) NOT NULL,\n" + - " `T` bigint(20) NOT NULL,\n" + - " `V` varbinary(1024) DEFAULT NULL,\n" + - " PRIMARY KEY (`K`, `Q`, `T`)\n" + - ") TABLEGROUP = test_multi_cf PARTITION BY KEY(`K`) PARTITIONS 10;\n" + - "CREATE DATABASE IF NOT EXISTS `n1`;\n" + - "use `n1`;\n" + - "CREATE TABLEGROUP IF NOT EXISTS `n1:test_multi_cf` SHARDING = 'ADAPTIVE';"); + st.execute("CREATE DATABASE IF NOT EXISTS `exist_tb`"); st.close(); conn.close(); Configuration conf = ObHTableTestUtil.newConfiguration(); @@ -696,14 +683,16 @@ public void testAdminTableExists() throws Exception { TableName.valueOf("random_string$"); }); Assert.assertFalse(admin.tableExists(TableName.valueOf("tablegroup_not_exists"))); - Assert.assertTrue(admin.tableExists(TableName.valueOf("n1", "test_multi_cf"))); - Assert.assertTrue(admin.tableExists(TableName.valueOf("test_multi_cf"))); + createTable(admin, TableName.valueOf("test_exist_tb"), "cf1", "cf2", "cf3"); + createTable(admin, TableName.valueOf("exist_tb", "test"), "cf1", "cf2", "cf3"); + Assert.assertTrue(admin.tableExists(TableName.valueOf("test_exist_tb"))); + Assert.assertTrue(admin.tableExists(TableName.valueOf("exist_tb", "test"))); } private void batchInsert(int rows, String tablegroup) throws Exception { - byte[] family1 = Bytes.toBytes("family_with_group1"); - byte[] family2 = Bytes.toBytes("family_with_group2"); - byte[] family3 = Bytes.toBytes("family_with_group3"); + byte[] family1 = Bytes.toBytes("cf1"); + byte[] family2 = Bytes.toBytes("cf2"); + byte[] family3 = Bytes.toBytes("cf3"); byte[] family1_column1 = "family1_column1".getBytes(); byte[] family1_column2 = "family1_column2".getBytes(); byte[] family1_column3 = "family1_column3".getBytes(); @@ -780,22 +769,22 @@ public void testCreateDeleteTable() throws Exception { assertTrue(admin.tableExists(tableName)); // TODO: show create table, need to be replace by getDescriptor java.sql.Connection conn = ObHTableTestUtil.getConnection(); - String selectSql = "show create table " + tableName.getNameAsString() + "$" + cf1; + String selectSql = "show create table " + tableName.getNameAsString() + "$" + + Bytes.toString(cf1); System.out.println("execute sql: " + selectSql); java.sql.ResultSet resultSet = conn.createStatement().executeQuery(selectSql); ResultSetPrinter.print(resultSet); - selectSql = "show create table " + tableName.getNameAsString() + "$" + cf2; + selectSql = "show create table " + tableName.getNameAsString() + "$" + Bytes.toString(cf2); System.out.println("execute sql: " + selectSql); resultSet = conn.createStatement().executeQuery(selectSql); ResultSetPrinter.print(resultSet); - selectSql = "show create table " + tableName.getNameAsString() + "$" + cf3; + selectSql = "show create table " + tableName.getNameAsString() + "$" + Bytes.toString(cf3); System.out.println("execute sql: " + selectSql); resultSet = conn.createStatement().executeQuery(selectSql); ResultSetPrinter.print(resultSet); - // 4. test put/get some data Table table = connection.getTable(tableName); Put put = new Put(toBytes("Key" + 1)); @@ -839,6 +828,7 @@ void testConcurCreateDelTablesHelper(List tableNames, Boolean ignoreE hcd1.setMaxVersions(1); hcd1.setTimeToLive(86400); HColumnDescriptor hcd3 = new HColumnDescriptor(cf3); + List originalColumnDescriptors = Arrays.asList(hcd1, hcd2, hcd3); // 1. generate create table task, one task per table List> tasks = new ArrayList<>(); @@ -846,11 +836,19 @@ void testConcurCreateDelTablesHelper(List tableNames, Boolean ignoreE int finalI = i; tasks.add(()->{ HTableDescriptor htd = new HTableDescriptor(tableNames.get(finalI)); - htd.addFamily(hcd1); - htd.addFamily(hcd2); - htd.addFamily(hcd3); + List columnDescriptors = new ArrayList<>(originalColumnDescriptors); + // 随机打乱列族顺序 + Collections.shuffle(columnDescriptors); + String shuffledCfNames = columnDescriptors.stream() + .map(hcd -> Bytes.toString(hcd.getName())) + .collect(Collectors.joining(", ")); + System.out.println("Table " + tableNames.get(finalI) + " shuffled column families: " + shuffledCfNames); + for (HColumnDescriptor hcd : columnDescriptors) { + htd.addFamily(hcd); + } try { admin.createTable(htd); + System.out.println("success to create table:" + tableNames.get(finalI)); } catch (Exception e) { System.out.println(e); if (!ignoreException) { @@ -891,9 +889,31 @@ void testConcurCreateDelTablesHelper(List tableNames, Boolean ignoreE } // 4. disable all tables; + List> disableTasks = new ArrayList<>(); + for (int i = 0; i < tableNums; i++) { + int finalI = i; + disableTasks.add(()->{ + try { + admin.disableTable(tableNames.get(finalI)); + System.out.println("success to disable table:" + tableNames.get(finalI)); + } catch (Exception e) { + System.out.println(e); + if (!ignoreException) { + throw e; + } + } + return null; + }); + } + ExecutorService disExecutorService = Executors.newFixedThreadPool(tableNums); + disExecutorService.invokeAll(disableTasks); + disExecutorService.shutdown(); + disExecutorService.awaitTermination(1, TimeUnit.MINUTES); + + assertTrue(admin.isTableDisabled(tableNames.get(0))); for (int i = 0; i < tableNames.size(); i++) { TableName tableName = tableNames.get(i); - admin.disableTable(tableName); + assertTrue(admin.isTableDisabled(tableName)); } // 5. generate delete table task @@ -903,6 +923,7 @@ void testConcurCreateDelTablesHelper(List tableNames, Boolean ignoreE delTasks.add(()->{ try { admin.deleteTable(tableNames.get(finalI)); + System.out.println("success to drop table:" + tableNames.get(finalI)); } catch (Exception e) { System.out.println(e); if (!ignoreException) { @@ -1033,4 +1054,329 @@ public void testConcurCreateDelPerf() throws Exception { duration = System.currentTimeMillis() - start; System.out.println("delete " + tableNums + " tables cost " + duration + " ms."); } + + @Test + public void testHTableDDLDefense() throws Exception { + TableName tableName = TableName.valueOf("testHTableDefense"); + byte[] cf1 = Bytes.toBytes("cf1"); + byte[] cf2 = Bytes.toBytes("cf2"); + Configuration conf = ObHTableTestUtil.newConfiguration(); + Connection connection = ConnectionFactory.createConnection(conf); + Admin admin = connection.getAdmin(); + + // 1. construct htable desc and column family desc + HColumnDescriptor hcd1 = new HColumnDescriptor(cf1); + hcd1.setMaxVersions(2); + hcd1.setTimeToLive(172800); + HColumnDescriptor hcd2 = new HColumnDescriptor(cf2); + hcd1.setMaxVersions(1); + hcd1.setTimeToLive(86400); + java.sql.Connection conn = ObHTableTestUtil.getConnection(); + + // 2. execute create table and check exists + try { + HTableDescriptor htd = new HTableDescriptor(tableName); + htd.addFamily(hcd1); + htd.addFamily(hcd2); + admin.createTable(htd); + assertTrue(admin.tableExists(tableName)); + + /// execute the following ddl stmt in created by admin table, should be prohibited + // 3. alter table add constraint + try { + executeSQL(conn, + "alter table testHTableDefense$cf1 ADD CONSTRAINT cons1 CHECK(T < 0)", true); + fail(); + } catch (SQLException e) { + Assert.assertEquals(1235, e.getErrorCode()); + Assert.assertEquals( + "table kv_attribute with '\"CreateBy\": \"Admin\"' not supported", + e.getMessage()); + } + + // 4. alter table add index + try { + executeSQL(conn, "alter table testHTableDefense$cf1 ADD INDEX idx_1(T)", true); + fail(); + } catch (SQLException e) { + Assert.assertEquals(1235, e.getErrorCode()); + Assert.assertEquals( + "table kv_attribute with '\"CreateBy\": \"Admin\"' not supported", + e.getMessage()); + } + + // 5. alter table modify column to lob + try { + executeSQL(conn, "alter table testHTableDefense$cf1 MODIFY COLUMN V LONGTEXT", true); + fail(); + } catch (SQLException e) { + Assert.assertEquals(1235, e.getErrorCode()); + Assert.assertEquals( + "table kv_attribute with '\"CreateBy\": \"Admin\"' not supported", + e.getMessage()); + } + + // 6. alter hbase admin table add fk + try { + executeSQL( + conn, + "alter table testHTableDefense$cf1 ADD CONSTRAINT hbase_fk_1 FOREIGN KEY(K) REFERENCES testHTableDefense$cf2(K)", + true); + fail(); + } catch (SQLException e) { + Assert.assertEquals(1235, e.getErrorCode()); + Assert.assertEquals( + "table kv_attribute with '\"CreateBy\": \"Admin\"' not supported", + e.getMessage()); + } + + // 7. create a normal table to refer to hbase admin table + try { + executeSQL( + conn, + "create table testHTableDefense_t1(a varbinary(1024) primary key, FOREIGN KEY(a) REFERENCES testHTableDefense$cf1(K));", + true); + fail(); + } catch (SQLException e) { + Assert.assertEquals(1235, e.getErrorCode()); + Assert.assertEquals( + "table kv_attribute with '\"CreateBy\": \"Admin\"' not supported", + e.getMessage()); + } + + // 8. alter a normal table to refer to hbase admin table + try { + executeSQL(conn, + "create table testHTableDefense_t2(a varbinary(1024) primary key)", true); + executeSQL( + conn, + "alter table testHTableDefense_t2 ADD CONSTRAINT hbase_fk_1 FOREIGN KEY(a) REFERENCES testHTableDefense$cf1(K);", + true); + fail(); + } catch (SQLException e) { + Assert.assertEquals(1235, e.getErrorCode()); + Assert.assertEquals( + "table kv_attribute with '\"CreateBy\": \"Admin\"' not supported", + e.getMessage()); + } + // 9. create a normal table A to refer to a table mock parent table B, and create table B using hbase admin + try { + executeSQL(conn, "SET foreign_key_checks = 0", true); + + executeSQL( + conn, + "create table testHTableDefense_t3(a varbinary(1024) primary key, FOREIGN KEY(a) REFERENCES testHTableDefense2$cf1(K));", + true); + HTableDescriptor htd2 = new HTableDescriptor( + TableName.valueOf("testHTableDefense2")); + HColumnDescriptor hcd4 = new HColumnDescriptor("cf1".getBytes()); + hcd4.setMaxVersions(2); + hcd4.setTimeToLive(172800); + htd2.addFamily(hcd4); + admin.createTable(htd2); + fail(); + } catch (Exception e) { + Assert.assertEquals(-4007, ((ObTableException) e.getCause()).getErrorCode()); + } + + // 10. create trigger + try { + executeSQL(conn, " CREATE TRIGGER hbase_trigger_1" + + " AFTER INSERT ON testHTableDefense$cf1 FOR EACH ROW" + + " BEGIN END", true); + fail(); + } catch (SQLException e) { + Assert.assertEquals(1235, e.getErrorCode()); + Assert.assertEquals( + "table kv_attribute with '\"CreateBy\": \"Admin\"' not supported", + e.getMessage()); + } + + // 11. create view + try { + executeSQL(conn, + " CREATE VIEW hbase_view_1 as select * from testHTableDefense$cf1", true); + fail(); + } catch (SQLException e) { + Assert.assertEquals(1235, e.getErrorCode()); + Assert.assertEquals( + "table kv_attribute with '\"CreateBy\": \"Admin\"' not supported", + e.getMessage()); + } + + // 12. alter view + try { + executeSQL(conn, "ALTER VIEW hbase_view_1 as select * from testHTableDefense$cf1", + true); + fail(); + } catch (SQLException e) { + Assert.assertEquals(1235, e.getErrorCode()); + Assert.assertEquals( + "table kv_attribute with '\"CreateBy\": \"Admin\"' not supported", + e.getMessage()); + } + + // 13. create index + try { + executeSQL(conn, + " CREATE INDEX testHTableDefense$cf1_idx_T on testHTableDefense$cf1(T)", true); + fail(); + } catch (SQLException e) { + Assert.assertEquals(1235, e.getErrorCode()); + Assert.assertEquals( + "table kv_attribute with '\"CreateBy\": \"Admin\"' not supported", + e.getMessage()); + } + + // 14. explicit create table and specify created_by:admin, should be prohibited + try { + executeSQL( + conn, + "CREATE TABLE testHTableDefense$cf3(a int primary key) kv_attributes ='{\"Hbase\": {\"CreatedBy\": \"Admin\"}}'", + true); + fail(); + } catch (SQLException e) { + Assert.assertEquals(1235, e.getErrorCode()); + Assert.assertEquals( + "table kv_attribute with '\"CreateBy\": \"Admin\"' not supported", + e.getMessage()); + } + + // 15. alter table to created_by:admin, should be prohibited + try { + executeSQL(conn, "CREATE TABLE testHTableDefense$cf3(a int primary key)", true); + executeSQL( + conn, + "alter table testHTableDefense$cf3 kv_attributes ='{\"Hbase\": {\"CreatedBy\": \"Admin\"}}'", + true); + fail(); + } catch (SQLException e) { + Assert.assertEquals(1235, e.getErrorCode()); + Assert.assertEquals("alter table kv attributes to created by admin not supported", + e.getMessage()); + // clean table + String sql3 = "drop table if exists testHTableDefense$cf3"; + System.out.println("execute sql: " + sql3); + conn.createStatement().execute(sql3); + } + + // 16. disable a htable did not created by admin is not suppported + try { + executeSQL(conn, "CREATE TABLEGROUP IF NOT EXISTS testHTableDefense2", true); + executeSQL( + conn, + "CREATE TABLE IF NOT EXISTS testHTableDefense2$cf4(a int primary key) kv_attributes ='{\"Hbase\": {}}' TABLEGROUP=testHTableDefense2", + true); + admin.disableTable(TableName.valueOf("testHTableDefense2")); + fail(); + } catch (Exception e) { + Assert.assertEquals(-4007, ((ObTableException) e.getCause()).getErrorCode()); + } + + // 17. delete a htable did not created by admin is not suppported + try { + executeSQL(conn, "CREATE TABLEGROUP IF NOT EXISTS testHTableDefense2", true); + executeSQL( + conn, + "CREATE TABLE IF NOT EXISTS testHTableDefense2$cf5(a int primary key) kv_attributes ='{\"Hbase\": {}}' TABLEGROUP=testHTableDefense2", + true); + admin.deleteTable(TableName.valueOf("testHTableDefense2")); + fail(); + } catch (Exception e) { + Assert.assertEquals(-4007, ((ObTableException) e.getCause()).getErrorCode()); + } + + } catch (Exception e) { + e.printStackTrace(); + assertTrue(false); + } finally { + admin.disableTable(tableName); + admin.deleteTable(tableName); + executeSQL(conn, "DROP TABLE IF EXISTS testHTableDefense2$cf4", true); + executeSQL(conn, "DROP TABLE IF EXISTS testHTableDefense2$cf5", true); + executeSQL(conn, "DROP TABLEGROUP IF EXISTS testHTableDefense2", true); + executeSQL(conn, "DROP TABLE IF EXISTS testHTableDefense_t1", true); + executeSQL(conn, "DROP TABLE IF EXISTS testHTableDefense_t2", true); + executeSQL(conn, "DROP TABLE IF EXISTS testHTableDefense_t3", true); + } + } + + void checkKVAttributes(String tableName, String kvAttributes) throws Exception { + java.sql.Connection conn = ObHTableTestUtil.getConnection(); + java.sql.ResultSet resultSet = conn.createStatement().executeQuery( + "select kv_attributes from oceanbase.__all_table where table_name = '" + tableName + + "'"); + resultSet.next(); + String value = resultSet.getString(1); + Assert.assertEquals(kvAttributes, value); + Assert.assertFalse(resultSet.next()); + } + + // NOTE: observer should build with `-DOB_ERRSIM=ON` option, otherwise the test will fail + // This test verifies error injection scenarios for table operations + @Test + public void testCreateTableInjectError() throws Exception { + Configuration conf = ObHTableTestUtil.newConfiguration(); + Connection connection = ConnectionFactory.createConnection(conf); + Admin admin = connection.getAdmin(); + + byte[] tableName = Bytes.toBytes("test_create_table_inject_error"); + byte[] cf1 = Bytes.toBytes("cf1"); + byte[] cf2 = Bytes.toBytes("cf2"); + byte[] cf3 = Bytes.toBytes("cf3"); + + HColumnDescriptor hcd1 = new HColumnDescriptor(cf1); + HColumnDescriptor hcd2 = new HColumnDescriptor(cf2); + HColumnDescriptor hcd3 = new HColumnDescriptor(cf3); + + HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(tableName)); + htd.addFamily(hcd1); + htd.addFamily(hcd2); + htd.addFamily(hcd3); + + // 1. open err EN_CREATE_HTABLE_TG_FINISH_ERR + setErrSimPoint(ErrSimPoint.EN_CREATE_HTABLE_TG_FINISH_ERR, true); + ObHTableTestUtil.executeIgnoreUnexpectedError(() -> admin.createTable(htd)); + assertFalse("Table should not exist after TG error injection", + admin.tableExists(TableName.valueOf(tableName))); + setErrSimPoint(ErrSimPoint.EN_CREATE_HTABLE_TG_FINISH_ERR, false); + + // 2. open err EN_CREATE_HTABLE_CF_FINISH_ERR + setErrSimPoint(ErrSimPoint.EN_CREATE_HTABLE_CF_FINISH_ERR, true); + ObHTableTestUtil.executeIgnoreUnexpectedError(() -> admin.createTable(htd)); + assertFalse("Table should not exist after CF error injection", + admin.tableExists(TableName.valueOf(tableName))); + setErrSimPoint(ErrSimPoint.EN_CREATE_HTABLE_CF_FINISH_ERR, false); + + // 3. create table without error + admin.createTable(htd); + assertTrue("Table should exist after normal creation", + admin.tableExists(TableName.valueOf(tableName))); + assertEquals("Table should have 3 column families", 3, + admin.getTableDescriptor(TableName.valueOf(tableName)).getFamilies().size()); + + // 4. open err EN_DISABLE_HTABLE_CF_FINISH_ERR + setErrSimPoint(ErrSimPoint.EN_DISABLE_HTABLE_CF_FINISH_ERR, true); + admin.disableTable(TableName.valueOf(tableName)); + assertFalse("Table should not be disabled after disable error injection", + admin.isTableDisabled(TableName.valueOf(tableName))); + setErrSimPoint(ErrSimPoint.EN_DISABLE_HTABLE_CF_FINISH_ERR, false); + + // 5. disable table without error + admin.disableTable(TableName.valueOf(tableName)); + assertTrue("Table should be disabled after normal disable", + admin.isTableDisabled(TableName.valueOf(tableName))); + + // 6. open err EN_DELETE_HTABLE_CF_FINISH_ERR + setErrSimPoint(ErrSimPoint.EN_DELETE_HTABLE_CF_FINISH_ERR, true); + admin.deleteTable(TableName.valueOf(tableName)); + assertTrue("Table should still exist after delete error injection", + admin.tableExists(TableName.valueOf(tableName))); + setErrSimPoint(ErrSimPoint.EN_DELETE_HTABLE_CF_FINISH_ERR, false); + + // 7. delete table without error + admin.deleteTable(TableName.valueOf(tableName)); + assertFalse("Table should not exist after normal delete", + admin.tableExists(TableName.valueOf(tableName))); + } } diff --git a/src/test/java/com/alipay/oceanbase/hbase/OHTableClientTest.java b/src/test/java/com/alipay/oceanbase/hbase/OHTableClientTest.java index ce1bc3a1..f69143bb 100644 --- a/src/test/java/com/alipay/oceanbase/hbase/OHTableClientTest.java +++ b/src/test/java/com/alipay/oceanbase/hbase/OHTableClientTest.java @@ -70,7 +70,6 @@ public void testNew() throws Exception { assertTrue(true); } - /* CREATE TABLEGROUP test_desc SHARDING = 'ADAPTIVE'; CREATE TABLE `test_desc$family1` ( diff --git a/src/test/java/com/alipay/oceanbase/hbase/OHTableTest.java b/src/test/java/com/alipay/oceanbase/hbase/OHTableTest.java index 009cda20..43403229 100644 --- a/src/test/java/com/alipay/oceanbase/hbase/OHTableTest.java +++ b/src/test/java/com/alipay/oceanbase/hbase/OHTableTest.java @@ -85,7 +85,6 @@ public void testNew() throws Exception { try { hTable1.getTableDescriptor(); - fail(); } catch (Exception e) { assertTrue(true); } diff --git a/src/test/java/com/alipay/oceanbase/hbase/filter/HBaseFilterUtilsTest.java b/src/test/java/com/alipay/oceanbase/hbase/filter/HBaseFilterUtilsTest.java index 3d49b929..bfbc4b87 100644 --- a/src/test/java/com/alipay/oceanbase/hbase/filter/HBaseFilterUtilsTest.java +++ b/src/test/java/com/alipay/oceanbase/hbase/filter/HBaseFilterUtilsTest.java @@ -208,15 +208,6 @@ public void testFuzzyRowFilter() throws IOException { Assert.assertArrayEquals("FuzzyRowFilter('abc','101','ddd','010')".getBytes(), HBaseFilterUtils.toParseableByteArray(filter)); } - @Test - public void testColumnValueFilter() throws IOException { - ColumnValueFilter filter = new ColumnValueFilter(Bytes.toBytes("cf"), Bytes.toBytes("q"), - CompareOperator.EQUAL, Bytes.toBytes("v")); - System.out.println(Bytes.toString(HBaseFilterUtils.toParseableByteArray(filter))); - Assert.assertArrayEquals("ColumnValueFilter('cf','q',=,'binary:v')".getBytes(), - HBaseFilterUtils.toParseableByteArray(filter)); - } - @Test public void testMultiRowRangeFilter() throws IOException { List ranges = new ArrayList<>(); diff --git a/src/test/java/com/alipay/oceanbase/hbase/secondary/OHTableSecondaryPartDeleteTest.java b/src/test/java/com/alipay/oceanbase/hbase/secondary/OHTableSecondaryPartDeleteTest.java index 8e1804e9..07606bae 100644 --- a/src/test/java/com/alipay/oceanbase/hbase/secondary/OHTableSecondaryPartDeleteTest.java +++ b/src/test/java/com/alipay/oceanbase/hbase/secondary/OHTableSecondaryPartDeleteTest.java @@ -571,7 +571,7 @@ public void testMultiCFDeleteFamily() throws Throwable { public void testMultiCFDeleteFamilyWithVersion() throws Throwable { FOR_EACH(group2tableNames, OHTableSecondaryPartDeleteTest::testMultiCFDeleteFamilyWithVersionImpl); } - + @Test public void testMultiCFDeleteFamilyVersion() throws Throwable { FOR_EACH(group2tableNames, OHTableSecondaryPartDeleteTest::testMultiCFDeleteFamilyVersionImpl); diff --git a/src/test/java/com/alipay/oceanbase/hbase/secondary/OHTableSecondaryPartTTLTest.java b/src/test/java/com/alipay/oceanbase/hbase/secondary/OHTableSecondaryPartTTLTest.java index 2bd69f1f..0ff6a31b 100644 --- a/src/test/java/com/alipay/oceanbase/hbase/secondary/OHTableSecondaryPartTTLTest.java +++ b/src/test/java/com/alipay/oceanbase/hbase/secondary/OHTableSecondaryPartTTLTest.java @@ -1,3 +1,20 @@ +/*- + * #%L + * com.oceanbase:obkv-hbase-client + * %% + * Copyright (C) 2022 - 2025 OceanBase Group + * %% + * OBKV HBase Client Framework is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * #L% + */ + package com.alipay.oceanbase.hbase.secondary; import com.alipay.oceanbase.hbase.OHTableClient; diff --git a/src/test/java/com/alipay/oceanbase/hbase/util/ObHTableSecondaryPartUtil.java b/src/test/java/com/alipay/oceanbase/hbase/util/ObHTableSecondaryPartUtil.java index 2ee37e4e..c1e4ede7 100644 --- a/src/test/java/com/alipay/oceanbase/hbase/util/ObHTableSecondaryPartUtil.java +++ b/src/test/java/com/alipay/oceanbase/hbase/util/ObHTableSecondaryPartUtil.java @@ -59,7 +59,7 @@ public static void createTables(TableTemplateManager.TableType type, List tableNames, Map> group2tableNames, boolean printSql) - throws Exception { + throws Exception { Connection conn = ObHTableTestUtil.getConnection(); // single cf table if (tableNames != null) { @@ -110,15 +110,15 @@ public static void alterTables(Connection conn, TableTemplateManager.TableType t System.out.println(sql); conn.createStatement().execute(sql); System.out.println("============= alter table: " + tableName + " table_group: " - + getTableName(tableName) + " =============\n" - + (printSql ? sql : "") - + " \n============= done =============\n"); + + getTableName(tableName) + " =============\n" + + (printSql ? sql : "") + + " \n============= done =============\n"); } catch (SQLSyntaxErrorException e) { if (!e.getMessage().contains("already exists")) { throw e; } else { System.out.println("============= table: " + tableName + " table_group: " - + getTableName(tableName) + " alter failed ============="); + + getTableName(tableName) + " alter failed ============="); } } } diff --git a/src/test/java/com/alipay/oceanbase/hbase/util/ObHTableTestUtil.java b/src/test/java/com/alipay/oceanbase/hbase/util/ObHTableTestUtil.java index b2c94e6c..f3bdc05a 100644 --- a/src/test/java/com/alipay/oceanbase/hbase/util/ObHTableTestUtil.java +++ b/src/test/java/com/alipay/oceanbase/hbase/util/ObHTableTestUtil.java @@ -35,29 +35,39 @@ public class ObHTableTestUtil { // please consult your dba for the following configuration. - public static String PARAM_URL = ""; - public static String FULL_USER_NAME = ""; - public static String PASSWORD = ""; - public static String SYS_USER_NAME = ""; - public static String SYS_PASSWORD = ""; - public static String ODP_ADDR = ""; - public static int ODP_PORT = 0; - public static boolean ODP_MODE = false; - public static String DATABASE = ""; - public static String JDBC_IP = ""; - public static String JDBC_PORT = ""; - public static String JDBC_DATABASE = ""; - public static String JDBC_URL = "jdbc:mysql://" + JDBC_IP + ":" + JDBC_PORT + "/ " - + JDBC_DATABASE + "?" + "useUnicode=TRUE&" - + "characterEncoding=utf-8&" - + "socketTimeout=3000000&" + "connectTimeout=60000"; - public static String SYS_JDBC_URL = "jdbc:mysql://" + JDBC_IP + ":" + JDBC_PORT + "/ " - + "oceanbase?" + "useUnicode=TRUE&" - + "characterEncoding=utf-8&" - + "socketTimeout=3000000&" + "connectTimeout=60000"; - - public static String SQL_FORMAT = "truncate %s"; - public static List tableNameList = new LinkedList(); + public static String PARAM_URL = ""; + public static String FULL_USER_NAME = ""; + public static String PASSWORD = ""; + public static String SYS_USER_NAME = ""; + public static String SYS_PASSWORD = ""; + public static String ODP_ADDR = ""; + public static int ODP_PORT = 0; + public static boolean ODP_MODE = false; + public static String DATABASE = ""; + public static String JDBC_IP = ""; + public static String JDBC_PORT = ""; + public static String JDBC_DATABASE = ""; + public static String JDBC_URL = "jdbc:mysql://" + JDBC_IP + ":" + JDBC_PORT + + "/ " + JDBC_DATABASE + "?" + + "useUnicode=TRUE&" + + "characterEncoding=utf-8&" + + "socketTimeout=3000000&" + + "connectTimeout=60000"; + public static String SYS_JDBC_URL = "jdbc:mysql://" + JDBC_IP + ":" + JDBC_PORT + + "/ " + "oceanbase?" + "useUnicode=TRUE&" + + "characterEncoding=utf-8&" + + "socketTimeout=3000000&" + + "connectTimeout=60000"; + public static String SYS_TENANT_JDBC_URL = "jdbc:mysql://" + JDBC_IP + ":" + JDBC_PORT + + "/ " + "oceanbase?" + "useUnicode=TRUE&" + + "characterEncoding=utf-8&" + + "socketTimeout=3000000&" + + "connectTimeout=60000"; + + public static String SYS_TENANT_USER_NAME = "root@sys"; + public static String SYS_TENANT_PASSWORD = ""; + public static String SQL_FORMAT = "truncate %s"; + public static List tableNameList = new LinkedList(); public static Connection conn; public static Statement stmt; @@ -172,6 +182,17 @@ static public Connection getSysConnection() { } } + static public Connection getSysTenantConnection() { + try { + Class.forName("com.mysql.cj.jdbc.Driver"); + Connection conn = DriverManager.getConnection(SYS_TENANT_JDBC_URL, + SYS_TENANT_USER_NAME, SYS_TENANT_PASSWORD); + return conn; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + @FunctionalInterface public interface CheckedConsumer { void accept(T t) throws Throwable; @@ -229,4 +250,47 @@ public static boolean secureCompare(byte[] a, byte[] b) { } return diff == 0; } -} \ No newline at end of file + + public static void executeSQL(Connection conn, String sql, boolean printSQL) + throws SQLException { + System.out.println("execute sql: " + sql); + conn.createStatement().execute(sql); + } + + @FunctionalInterface + public interface CheckedRunnable { + void run() throws Exception; + } + + public static void executeIgnoreUnexpectedError(CheckedRunnable operation) throws Exception { + executeIgnoreExpectedErrors(operation, "OB_ERR_UNEXPECTED"); + } + + public static void executeIgnoreExpectedErrors(CheckedRunnable operation, + String... expectedErrorMessages) + throws Exception { + try { + operation.run(); + } catch (Exception e) { + boolean shouldIgnore = false; + String[] messagesToCheck = { e.getMessage(), + e.getCause() != null ? e.getCause().getMessage() : null }; + + for (String expectedMessage : expectedErrorMessages) { + for (String actualMessage : messagesToCheck) { + if (actualMessage != null && actualMessage.contains(expectedMessage)) { + shouldIgnore = true; + break; + } + } + if (shouldIgnore) { + break; + } + } + + if (!shouldIgnore) { + throw e; + } + } + } +} diff --git a/src/test/java/com/alipay/oceanbase/hbase/util/TableTemplateManager.java b/src/test/java/com/alipay/oceanbase/hbase/util/TableTemplateManager.java index 2263bfcc..f315471d 100644 --- a/src/test/java/com/alipay/oceanbase/hbase/util/TableTemplateManager.java +++ b/src/test/java/com/alipay/oceanbase/hbase/util/TableTemplateManager.java @@ -46,66 +46,66 @@ public enum TableType { NON_PARTITIONED_TIME_CELL_TTL, // 时序表带CELL TTL列 } - public static List NORMAL_AND_SERIES_TABLES = Arrays - .asList( - NON_PARTITIONED_REGULAR, - NON_PARTITIONED_TIME_SERIES, - SINGLE_PARTITIONED_REGULAR, - SINGLE_PARTITIONED_TIME_SERIES, - SECONDARY_PARTITIONED_RANGE_KEY, - SECONDARY_PARTITIONED_RANGE_KEY_GEN, - SECONDARY_PARTITIONED_KEY_RANGE, - SECONDARY_PARTITIONED_KEY_RANGE_GEN, - SECONDARY_PARTITIONED_TIME_RANGE_KEY, - SECONDARY_PARTITIONED_TIME_KEY_RANGE); - - public static List NORMAL_PARTITIONED_TABLES = Arrays - .asList( - SINGLE_PARTITIONED_REGULAR, - SECONDARY_PARTITIONED_RANGE_KEY, - SECONDARY_PARTITIONED_RANGE_KEY_GEN, - SECONDARY_PARTITIONED_KEY_RANGE, - SECONDARY_PARTITIONED_KEY_RANGE_GEN); + public static List NORMAL_AND_SERIES_TABLES = Arrays + .asList( + NON_PARTITIONED_REGULAR, + NON_PARTITIONED_TIME_SERIES, + SINGLE_PARTITIONED_REGULAR, + SINGLE_PARTITIONED_TIME_SERIES, + SECONDARY_PARTITIONED_RANGE_KEY, + SECONDARY_PARTITIONED_RANGE_KEY_GEN, + SECONDARY_PARTITIONED_KEY_RANGE, + SECONDARY_PARTITIONED_KEY_RANGE_GEN, + SECONDARY_PARTITIONED_TIME_RANGE_KEY, + SECONDARY_PARTITIONED_TIME_KEY_RANGE); + + public static List NORMAL_PARTITIONED_TABLES = Arrays + .asList( + SINGLE_PARTITIONED_REGULAR, + SECONDARY_PARTITIONED_RANGE_KEY, + SECONDARY_PARTITIONED_RANGE_KEY_GEN, + SECONDARY_PARTITIONED_KEY_RANGE, + SECONDARY_PARTITIONED_KEY_RANGE_GEN); public static List NORMAL_SERIES_PARTITIONED_TABLES = Arrays - .asList( - SINGLE_PARTITIONED_TIME_SERIES, - SECONDARY_PARTITIONED_TIME_RANGE_KEY, - SECONDARY_PARTITIONED_TIME_KEY_RANGE); - - public static List SERIES_TABLES = Arrays - .asList( - NON_PARTITIONED_TIME_SERIES, - SINGLE_PARTITIONED_TIME_SERIES, - SECONDARY_PARTITIONED_TIME_RANGE_KEY, - SECONDARY_PARTITIONED_TIME_KEY_RANGE); - - public static List NORMAL_TABLES = Arrays - .asList( - NON_PARTITIONED_REGULAR, - SINGLE_PARTITIONED_REGULAR, - SECONDARY_PARTITIONED_RANGE_KEY, - SECONDARY_PARTITIONED_RANGE_KEY_GEN, - SECONDARY_PARTITIONED_KEY_RANGE, - SECONDARY_PARTITIONED_KEY_RANGE_GEN); - - public static List CELL_TTL_TABLES = Arrays - .asList( - NON_PARTITIONED_REGULAR_CELL_TTL, - SINGLE_PARTITIONED_REGULAR_CELL_TTL, - SECONDARY_PARTITIONED_RANGE_KEY_CELL_TTL, - SECONDARY_PARTITIONED_RANGE_KEY_GEN_CELL_TTL, - SECONDARY_PARTITIONED_KEY_RANGE_CELL_TTL, - SECONDARY_PARTITIONED_KEY_RANGE_GEN_CELL_TTL); - - public static List TIMESERIES_TABLES = Arrays - .asList( - NON_PARTITIONED_TIME_SERIES, - SINGLE_PARTITIONED_TIME_SERIES, - SECONDARY_PARTITIONED_TIME_RANGE_KEY, - SECONDARY_PARTITIONED_TIME_KEY_RANGE); - - private static final Map SQL_TEMPLATES = new EnumMap( - TableType.class); + .asList( + SINGLE_PARTITIONED_TIME_SERIES, + SECONDARY_PARTITIONED_TIME_RANGE_KEY, + SECONDARY_PARTITIONED_TIME_KEY_RANGE); + + public static List SERIES_TABLES = Arrays + .asList( + NON_PARTITIONED_TIME_SERIES, + SINGLE_PARTITIONED_TIME_SERIES, + SECONDARY_PARTITIONED_TIME_RANGE_KEY, + SECONDARY_PARTITIONED_TIME_KEY_RANGE); + + public static List NORMAL_TABLES = Arrays + .asList( + NON_PARTITIONED_REGULAR, + SINGLE_PARTITIONED_REGULAR, + SECONDARY_PARTITIONED_RANGE_KEY, + SECONDARY_PARTITIONED_RANGE_KEY_GEN, + SECONDARY_PARTITIONED_KEY_RANGE, + SECONDARY_PARTITIONED_KEY_RANGE_GEN); + + public static List CELL_TTL_TABLES = Arrays + .asList( + NON_PARTITIONED_REGULAR_CELL_TTL, + SINGLE_PARTITIONED_REGULAR_CELL_TTL, + SECONDARY_PARTITIONED_RANGE_KEY_CELL_TTL, + SECONDARY_PARTITIONED_RANGE_KEY_GEN_CELL_TTL, + SECONDARY_PARTITIONED_KEY_RANGE_CELL_TTL, + SECONDARY_PARTITIONED_KEY_RANGE_GEN_CELL_TTL); + + public static List TIMESERIES_TABLES = Arrays + .asList( + NON_PARTITIONED_TIME_SERIES, + SINGLE_PARTITIONED_TIME_SERIES, + SECONDARY_PARTITIONED_TIME_RANGE_KEY, + SECONDARY_PARTITIONED_TIME_KEY_RANGE); + + private static final Map SQL_TEMPLATES = new EnumMap( + TableType.class); static { // 普通表非分区表模版 @@ -297,55 +297,55 @@ public enum TableType { + ") TABLEGROUP = %s"); } - private static final Map ALTER_SQL_TEMPLATES = new EnumMap( - TableType.class); + private static final Map ALTER_SQL_TEMPLATES = new EnumMap( + TableType.class); static { // 普通表一级分区模板 ALTER_SQL_TEMPLATES.put(TableType.SINGLE_PARTITIONED_REGULAR, - "ALTER TABLE `%s` ALTER PARTITION p0 STORAGE_CACHE_POLICY='hot';"); + "ALTER TABLE `%s` ALTER PARTITION p0 STORAGE_CACHE_POLICY='hot';"); // 时序表一级分区模板 ALTER_SQL_TEMPLATES.put(TableType.SINGLE_PARTITIONED_TIME_SERIES, - "ALTER TABLE `%s` ALTER PARTITION p0 STORAGE_CACHE_POLICY='hot';"); + "ALTER TABLE `%s` ALTER PARTITION p0 STORAGE_CACHE_POLICY='hot';"); // 普通表RANGE-KEY分区(使用K) ALTER_SQL_TEMPLATES.put(TableType.SECONDARY_PARTITIONED_RANGE_KEY, - "ALTER TABLE `%s` ALTER SUBPARTITION p1sp0 STORAGE_CACHE_POLICY='hot';"); + "ALTER TABLE `%s` ALTER SUBPARTITION p1sp0 STORAGE_CACHE_POLICY='hot';"); // 合并GEN类型的注释处理 ALTER_SQL_TEMPLATES.put(TableType.SECONDARY_PARTITIONED_RANGE_KEY_GEN, - "ALTER TABLE `%s` ALTER SUBPARTITION p1sp0 STORAGE_CACHE_POLICY='hot';"); + "ALTER TABLE `%s` ALTER SUBPARTITION p1sp0 STORAGE_CACHE_POLICY='hot';"); // 普通表KEY-RANGE分区(使用K) ALTER_SQL_TEMPLATES.put(TableType.SECONDARY_PARTITIONED_KEY_RANGE, - "ALTER TABLE `%s` ALTER SUBPARTITION p1sp0 STORAGE_CACHE_POLICY='hot';"); + "ALTER TABLE `%s` ALTER SUBPARTITION p1sp0 STORAGE_CACHE_POLICY='hot';"); // 普通表KEY-RANGE分区(使用生成列) ALTER_SQL_TEMPLATES.put(TableType.SECONDARY_PARTITIONED_KEY_RANGE_GEN, - "ALTER TABLE `%s` ALTER SUBPARTITION p1sp0 STORAGE_CACHE_POLICY='hot';"); + "ALTER TABLE `%s` ALTER SUBPARTITION p1sp0 STORAGE_CACHE_POLICY='hot';"); // 时序表RANGE-KEY分区 ALTER_SQL_TEMPLATES.put(TableType.SECONDARY_PARTITIONED_TIME_RANGE_KEY, - "ALTER TABLE `%s` ALTER SUBPARTITION p1sp0 STORAGE_CACHE_POLICY='hot';"); + "ALTER TABLE `%s` ALTER SUBPARTITION p1sp0 STORAGE_CACHE_POLICY='hot';"); // 时序表KEY-RANGE分区 ALTER_SQL_TEMPLATES.put(TableType.SECONDARY_PARTITIONED_TIME_KEY_RANGE, - "ALTER TABLE `%s` ALTER SUBPARTITION p1sp0 STORAGE_CACHE_POLICY='hot';"); + "ALTER TABLE `%s` ALTER SUBPARTITION p1sp0 STORAGE_CACHE_POLICY='hot';"); /* ------------------ CELL TTL ----------------*/ ALTER_SQL_TEMPLATES.put(TableType.SINGLE_PARTITIONED_REGULAR_CELL_TTL, - "ALTER TABLE `%s` ALTER PARTITION p0 STORAGE_CACHE_POLICY='hot';"); + "ALTER TABLE `%s` ALTER PARTITION p0 STORAGE_CACHE_POLICY='hot';"); ALTER_SQL_TEMPLATES.put(TableType.SECONDARY_PARTITIONED_RANGE_KEY_CELL_TTL, - "ALTER TABLE `%s` ALTER SUBPARTITION p1sp0 STORAGE_CACHE_POLICY='hot';"); + "ALTER TABLE `%s` ALTER SUBPARTITION p1sp0 STORAGE_CACHE_POLICY='hot';"); ALTER_SQL_TEMPLATES.put(TableType.SECONDARY_PARTITIONED_RANGE_KEY_GEN_CELL_TTL, - "ALTER TABLE `%s` ALTER SUBPARTITION p1sp0 STORAGE_CACHE_POLICY='hot';"); + "ALTER TABLE `%s` ALTER SUBPARTITION p1sp0 STORAGE_CACHE_POLICY='hot';"); ALTER_SQL_TEMPLATES.put(TableType.SECONDARY_PARTITIONED_KEY_RANGE_CELL_TTL, - "ALTER TABLE `%s` ALTER SUBPARTITION p1sp0 STORAGE_CACHE_POLICY='hot';"); + "ALTER TABLE `%s` ALTER SUBPARTITION p1sp0 STORAGE_CACHE_POLICY='hot';"); ALTER_SQL_TEMPLATES.put(TableType.SECONDARY_PARTITIONED_KEY_RANGE_GEN_CELL_TTL, - "ALTER TABLE `%s` ALTER SUBPARTITION p1sp0 STORAGE_CACHE_POLICY='hot';"); + "ALTER TABLE `%s` ALTER SUBPARTITION p1sp0 STORAGE_CACHE_POLICY='hot';"); } public static String getCreateTableSQL(TableType type, String tableName,