diff --git a/example/simple-hbase-demo/src/main/java/com/oceanbase/example/SimpleHBaseClientDemo.java b/example/simple-hbase-demo/src/main/java/com/oceanbase/example/SimpleHBaseClientDemo.java
index 0ab3b588..e0ff821c 100644
--- a/example/simple-hbase-demo/src/main/java/com/oceanbase/example/SimpleHBaseClientDemo.java
+++ b/example/simple-hbase-demo/src/main/java/com/oceanbase/example/SimpleHBaseClientDemo.java
@@ -19,6 +19,8 @@
import com.alipay.oceanbase.hbase.OHTableClient;
import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.Cell;
+import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
@@ -49,7 +51,7 @@ public static void simpleTest() throws Exception {
byte[] rowKey = toBytes("rowKey1");
byte[] column = toBytes("column1");
Put put = new Put(rowKey);
- put.add(family, column, System.currentTimeMillis(), toBytes("value1"));
+ put.addColumn(family, column, System.currentTimeMillis(), toBytes("value1"));
hTable.put(put);
// 3. get data like hbase
@@ -58,7 +60,7 @@ public static void simpleTest() throws Exception {
Result r = hTable.get(get);
if (!r.isEmpty()) {
Cell cell = r.rawCells()[0];
- System.out.printf("column1: " + CellUtil.cloneQualifier(r));
+ System.out.printf("column1: " + CellUtil.cloneQualifier(cell));
}
// 4. close
diff --git a/pom.xml b/pom.xml
index 3b8fbf94..3e2e7667 100644
--- a/pom.xml
+++ b/pom.xml
@@ -54,7 +54,7 @@
${project.encoding}UTF-81.7.21
-
2.0.0
+ 2.0.1-SNAPSHOT
@@ -167,6 +167,10 @@
jersey-jsoncom.sun.jersey
+
+ jackson-databind
+ com.fasterxml.jackson.core
+
diff --git a/src/main/java/com/alipay/oceanbase/hbase/OHTable.java b/src/main/java/com/alipay/oceanbase/hbase/OHTable.java
index f66dcd8c..106058eb 100644
--- a/src/main/java/com/alipay/oceanbase/hbase/OHTable.java
+++ b/src/main/java/com/alipay/oceanbase/hbase/OHTable.java
@@ -220,8 +220,7 @@ public OHTable(Configuration configuration, String tableName) throws IOException
DEFAULT_HBASE_HTABLE_THREAD_KEEP_ALIVE_TIME);
this.executePool = createDefaultThreadPoolExecutor(1, maxThreads, keepAliveTime);
OHConnectionConfiguration ohConnectionConf = new OHConnectionConfiguration(configuration);
- int numRetries = configuration.getInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER,
- HConstants.DEFAULT_HBASE_CLIENT_RETRIES_NUMBER);
+ int numRetries = ohConnectionConf.getNumRetries();
this.obTableClient = ObTableClientManager.getOrCreateObTableClient(setUserDefinedNamespace(
this.tableNameString, ohConnectionConf));
this.obTableClient.setRpcExecuteTimeout(ohConnectionConf.getRpcTimeout());
@@ -273,8 +272,7 @@ public OHTable(Configuration configuration, final byte[] tableName,
this.executePool = executePool;
this.cleanupPoolOnClose = false;
OHConnectionConfiguration ohConnectionConf = new OHConnectionConfiguration(configuration);
- int numRetries = configuration.getInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER,
- HConstants.DEFAULT_HBASE_CLIENT_RETRIES_NUMBER);
+ int numRetries = ohConnectionConf.getNumRetries();
this.obTableClient = ObTableClientManager.getOrCreateObTableClient(setUserDefinedNamespace(
this.tableNameString, ohConnectionConf));
this.obTableClient.setRpcExecuteTimeout(ohConnectionConf.getRpcTimeout());
@@ -345,8 +343,7 @@ public OHTable(TableName tableName, Connection connection,
DEFAULT_HBASE_HTABLE_PUT_WRITE_BUFFER_CHECK);
this.writeBufferSize = connectionConfig.getWriteBufferSize();
this.tableName = tableName.getName();
- int numRetries = configuration.getInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER,
- HConstants.DEFAULT_HBASE_CLIENT_RETRIES_NUMBER);
+ int numRetries = connectionConfig.getNumRetries();
this.obTableClient = ObTableClientManager.getOrCreateObTableClient(setUserDefinedNamespace(
this.tableNameString, connectionConfig));
this.obTableClient.setRpcExecuteTimeout(rpcTimeout);
@@ -389,8 +386,7 @@ public OHTable(Connection connection, ObTableBuilderBase builder,
this.putWriteBufferCheck = this.configuration.getInt(HBASE_HTABLE_PUT_WRITE_BUFFER_CHECK,
DEFAULT_HBASE_HTABLE_PUT_WRITE_BUFFER_CHECK);
this.writeBufferSize = connectionConfig.getWriteBufferSize();
- int numRetries = configuration.getInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER,
- HConstants.DEFAULT_HBASE_CLIENT_RETRIES_NUMBER);
+ int numRetries = connectionConfig.getNumRetries();
this.obTableClient = ObTableClientManager.getOrCreateObTableClient(setUserDefinedNamespace(
this.tableNameString, connectionConfig));
this.obTableClient.setRpcExecuteTimeout(rpcTimeout);
@@ -462,7 +458,7 @@ private void finishSetUp() {
WRITE_BUFFER_SIZE_DEFAULT);
}
- private OHConnectionConfiguration setUserDefinedNamespace(String tableNameString,
+ public static OHConnectionConfiguration setUserDefinedNamespace(String tableNameString,
OHConnectionConfiguration ohConnectionConf)
throws IllegalArgumentException {
if (tableNameString.indexOf(':') != -1) {
@@ -503,13 +499,15 @@ public Configuration getConfiguration() {
}
@Override
- public HTableDescriptor getTableDescriptor() {
- throw new FeatureNotSupportedException("not supported yet.");
+ public HTableDescriptor getTableDescriptor() throws IOException {
+ OHTableDescriptorExecutor executor = new OHTableDescriptorExecutor(tableNameString, obTableClient);
+ return executor.getTableDescriptor();
}
@Override
public TableDescriptor getDescriptor() throws IOException {
- throw new FeatureNotSupportedException("not supported yet.");
+ OHTableDescriptorExecutor executor = new OHTableDescriptorExecutor(tableNameString, obTableClient);
+ return executor.getTableDescriptor();
}
/**
@@ -1950,6 +1948,8 @@ private ObTableQuery buildObTableQuery(ObHTableFilter filter, final Scan scan) {
HConstants.DEFAULT_HBASE_CLIENT_SCANNER_MAX_RESULT_SIZE));
obTableQuery.setObKVParams(buildOBKVParams(scan));
obTableQuery.setScanRangeColumns("K", "Q", "T");
+ byte[] hotOnly = scan.getAttribute(HBASE_HTABLE_QUERY_HOT_ONLY);
+ obTableQuery.setHotOnly(hotOnly != null && Arrays.equals(hotOnly, "true".getBytes()));
return obTableQuery;
}
@@ -1967,6 +1967,8 @@ private ObTableQuery buildObTableQuery(final Get get, Collection columnQ
}
obTableQuery.setObKVParams(buildOBKVParams(get));
obTableQuery.setScanRangeColumns("K", "Q", "T");
+ byte[] hotOnly = get.getAttribute(HBASE_HTABLE_QUERY_HOT_ONLY);
+ obTableQuery.setHotOnly(hotOnly != null && Arrays.equals(hotOnly, "true".getBytes()));
return obTableQuery;
}
diff --git a/src/main/java/com/alipay/oceanbase/hbase/OHTableClient.java b/src/main/java/com/alipay/oceanbase/hbase/OHTableClient.java
index 770d523c..8a2c2f89 100644
--- a/src/main/java/com/alipay/oceanbase/hbase/OHTableClient.java
+++ b/src/main/java/com/alipay/oceanbase/hbase/OHTableClient.java
@@ -223,7 +223,8 @@ public HTableDescriptor getTableDescriptor() throws IOException {
@Override
public TableDescriptor getDescriptor() throws IOException {
- return null;
+ checkStatus();
+ return ohTable.getDescriptor();
}
@Override
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 19311744..deb94f75 100644
--- a/src/main/java/com/alipay/oceanbase/hbase/constants/OHConstants.java
+++ b/src/main/java/com/alipay/oceanbase/hbase/constants/OHConstants.java
@@ -23,17 +23,17 @@
public final class OHConstants {
/**
- * ocenbase hbase root server http url
+ * oceanbase hbase root server http url
*/
public static final String HBASE_OCEANBASE_PARAM_URL = "hbase.oceanbase.paramURL";
/**
- * ocenbase hbase connect server username
+ * oceanbase hbase connect server username
*/
public static final String HBASE_OCEANBASE_FULL_USER_NAME = "hbase.oceanbase.fullUserName";
/**
- * ocenbase hbase connect server password
+ * oceanbase hbase connect server password
*/
public static final String HBASE_OCEANBASE_PASSWORD = "hbase.oceanbase.password";
@@ -48,39 +48,39 @@ public final class OHConstants {
public static final String HBASE_OCEANBASE_SYS_PASSWORD = "hbase.oceanbase.sysPassword";
/**
- * ocenbase hbase connect server password
+ * oceanbase hbase connect server password
*/
public static final String HBASE_OCEANBASE_BATCH_EXECUTOR = "hbase.oceanbase.batch.executor";
/**
- * ocenbase hbase connect server ODP address
+ * oceanbase hbase connect server ODP address
*/
public static final String HBASE_OCEANBASE_ODP_ADDR = "hbase.oceanbase.odpAddr";
/**
- * ocenbase hbase connect server ODP port
+ * oceanbase hbase connect server ODP port
*/
public static final String HBASE_OCEANBASE_ODP_PORT = "hbase.oceanbase.odpPort";
/**
- * ocenbase hbase connect server ODP mode
+ * oceanbase hbase connect server ODP mode
*/
public static final String HBASE_OCEANBASE_ODP_MODE = "hbase.oceanbase.odpMode";
/**
- * ocenbase hbase connect server database
+ * oceanbase hbase connect server database
*/
public static final String HBASE_OCEANBASE_DATABASE = "hbase.oceanbase.database";
/**
- * ocenbase hbase model rowkey column is consist of following column
+ * oceanbase hbase model rowkey column is consist of following column
* K, Q, T hbase value
*/
public static final String[] ROW_KEY_COLUMNS = new String[] { "K",
"Q", "T" };
/**
- * ocenbase hbase model value column is consist of following column
+ * oceanbase hbase model value column is consist of following column
* V hbase value
*/
public static final String[] V_COLUMNS = new String[] { "V" };
@@ -124,6 +124,11 @@ public final class OHConstants {
*/
public static final String DEFAULT_HBASE_HTABLE_TEST_LOAD_SUFFIX = "_t";
+ /**
+ * 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";
+
/*-------------------------------------------------------------------------------------------------------------*/
/**
diff --git a/src/main/java/com/alipay/oceanbase/hbase/execute/AbstractObTableMetaExecutor.java b/src/main/java/com/alipay/oceanbase/hbase/execute/AbstractObTableMetaExecutor.java
new file mode 100644
index 00000000..05b48b4a
--- /dev/null
+++ b/src/main/java/com/alipay/oceanbase/hbase/execute/AbstractObTableMetaExecutor.java
@@ -0,0 +1,49 @@
+/*-
+ * #%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.hbase.util.OHBaseExceptionUtil;
+import com.alipay.oceanbase.rpc.ObTableClient;
+import com.alipay.oceanbase.rpc.exception.ObTableException;
+import com.alipay.oceanbase.rpc.meta.ObTableMetaRequest;
+import com.alipay.oceanbase.rpc.meta.ObTableMetaResponse;
+import com.alipay.oceanbase.rpc.table.ObTable;
+
+import java.io.IOException;
+
+public abstract class AbstractObTableMetaExecutor implements ObTableMetaExecutor {
+
+ @Override
+ public T execute(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*/
+ );
+ } catch (Exception e) {
+ throw OHBaseExceptionUtil.convertTableException(e);
+ }
+ return parse(response);
+ }
+}
diff --git a/src/main/java/com/alipay/oceanbase/hbase/execute/ObTableMetaExecutor.java b/src/main/java/com/alipay/oceanbase/hbase/execute/ObTableMetaExecutor.java
new file mode 100644
index 00000000..d55ff275
--- /dev/null
+++ b/src/main/java/com/alipay/oceanbase/hbase/execute/ObTableMetaExecutor.java
@@ -0,0 +1,49 @@
+/*-
+ * #%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;
+import com.alipay.oceanbase.rpc.meta.ObTableMetaRequest;
+import com.alipay.oceanbase.rpc.meta.ObTableMetaResponse;
+import com.alipay.oceanbase.rpc.meta.ObTableRpcMetaType;
+
+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/util/OHAdmin.java b/src/main/java/com/alipay/oceanbase/hbase/util/OHAdmin.java
new file mode 100644
index 00000000..5cb7d92c
--- /dev/null
+++ b/src/main/java/com/alipay/oceanbase/hbase/util/OHAdmin.java
@@ -0,0 +1,1148 @@
+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 com.alipay.oceanbase.rpc.protocol.payload.ResultCodes;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.*;
+import org.apache.hadoop.hbase.client.*;
+import org.apache.hadoop.hbase.client.replication.TableCFs;
+import org.apache.hadoop.hbase.client.security.SecurityCapability;
+import org.apache.hadoop.hbase.exceptions.TimeoutIOException;
+import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
+import org.apache.hadoop.hbase.quotas.QuotaFilter;
+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;
+import org.apache.hadoop.hbase.snapshot.RestoreSnapshotException;
+import org.apache.hadoop.hbase.snapshot.SnapshotCreationException;
+import org.apache.hadoop.hbase.snapshot.UnknownSnapshotException;
+import org.apache.hadoop.hbase.util.Pair;
+
+import java.io.IOException;
+import java.util.*;
+import java.util.concurrent.Future;
+import java.util.regex.Pattern;
+
+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();
+ }
+
+ @Override
+ public int getOperationTimeout() {
+ return connection.getOHConnectionConfiguration().getOperationTimeout();
+ }
+
+ @Override
+ public void abort(String msg, Throwable t) {
+ // do nothing, just throw the message and exception
+ this.aborted = true;
+ throw new RuntimeException(msg, t);
+ }
+
+ @Override
+ public boolean isAborted() {
+ return this.aborted;
+ }
+
+ @Override
+ public Connection getConnection() {
+ return this.connection;
+ }
+
+ @Override
+ public boolean tableExists(TableName tableName) throws IOException {
+ 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
+ public HTableDescriptor[] listTables() throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public List listTableDescriptors() throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public HTableDescriptor[] listTables(Pattern pattern) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public List listTableDescriptors(Pattern pattern) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public HTableDescriptor[] listTables(String s) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public HTableDescriptor[] listTables(Pattern pattern, boolean b) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public List listTableDescriptors(Pattern pattern, boolean b) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public HTableDescriptor[] listTables(String s, boolean b) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public TableName[] listTableNames() throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public TableName[] listTableNames(Pattern pattern) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public TableName[] listTableNames(String s) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public TableName[] listTableNames(Pattern pattern, boolean b) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public TableName[] listTableNames(String s, boolean b) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ 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);
+ try {
+ return executor.getTableDescriptor();
+ } catch (IOException e) {
+ if (e.getCause() instanceof ObTableTransportException
+ && ((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);
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ @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);
+ try {
+ return executor.getTableDescriptor();
+ } catch (IOException e) {
+ if (e.getCause() instanceof ObTableTransportException
+ && ((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);
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ @Override
+ public void createTable(TableDescriptor tableDescriptor) throws IOException {
+ 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 {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void createTable(TableDescriptor tableDescriptor, byte[][] bytes) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public Future createTableAsync(TableDescriptor tableDescriptor, byte[][] bytes) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void deleteTable(TableName tableName) throws IOException {
+ 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
+ public Future deleteTableAsync(TableName tableName) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public HTableDescriptor[] deleteTables(String s) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public HTableDescriptor[] deleteTables(Pattern pattern) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void truncateTable(TableName tableName, boolean b) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public Future truncateTableAsync(TableName tableName, boolean b) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void enableTable(TableName tableName) throws IOException {
+ 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
+ public Future enableTableAsync(TableName tableName) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public HTableDescriptor[] enableTables(String s) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public HTableDescriptor[] enableTables(Pattern pattern) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public Future disableTableAsync(TableName tableName) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @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);
+ try {
+ executor.disableTable(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
+ public HTableDescriptor[] disableTables(String s) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public HTableDescriptor[] disableTables(Pattern pattern) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public boolean isTableEnabled(TableName tableName) throws IOException {
+ return isDisabled(tableName) == false;
+ }
+
+ @Override
+ public boolean isTableDisabled(TableName tableName) throws IOException {
+ 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);
+ return tableDescriptor.isDisable();
+ }
+
+ @Override
+ public boolean isTableAvailable(TableName tableName) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public boolean isTableAvailable(TableName tableName, byte[][] bytes) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public Pair getAlterStatus(TableName tableName) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public Pair getAlterStatus(byte[] bytes) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ 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 {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void deleteColumn(TableName tableName, byte[] bytes) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void deleteColumnFamily(TableName tableName, byte[] bytes) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ 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 {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public Future modifyColumnFamilyAsync(TableName tableName, ColumnFamilyDescriptor columnFamilyDescriptor) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void closeRegion(String s, String s1) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void closeRegion(byte[] bytes, String s) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public boolean closeRegionWithEncodedRegionName(String s, String s1) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void closeRegion(ServerName serverName, HRegionInfo hRegionInfo) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public List getOnlineRegions(ServerName serverName) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public List getRegions(ServerName serverName) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void flush(TableName tableName) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ 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");
+ }
+
+ @Override
+ public void compactRegion(byte[] bytes) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void compact(TableName tableName, byte[] bytes) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void compactRegion(byte[] bytes, byte[] bytes1) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ 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 {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void majorCompact(TableName tableName) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void majorCompactRegion(byte[] bytes) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void majorCompact(TableName tableName, byte[] bytes) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void majorCompactRegion(byte[] bytes, byte[] bytes1) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @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 {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void compactRegionServer(ServerName serverName) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void majorCompactRegionServer(ServerName serverName) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void move(byte[] bytes, byte[] bytes1) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void assign(byte[] bytes) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void unassign(byte[] bytes, boolean b) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void offline(byte[] bytes) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public boolean balancerSwitch(boolean b, boolean b1) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public boolean balance() throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public boolean balance(boolean b) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ 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");
+ }
+
+ @Override
+ public boolean isNormalizerEnabled() throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public boolean normalizerSwitch(boolean b) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public boolean catalogJanitorSwitch(boolean b) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public int runCatalogJanitor() throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public boolean isCatalogJanitorEnabled() throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public boolean cleanerChoreSwitch(boolean b) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public boolean runCleanerChore() throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public boolean isCleanerChoreEnabled() throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void mergeRegions(byte[] bytes, byte[] bytes1, boolean b) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public Future mergeRegionsAsync(byte[] bytes, byte[] bytes1, boolean b) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public Future mergeRegionsAsync(byte[][] bytes, boolean b) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void split(TableName tableName) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void splitRegion(byte[] bytes) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void split(TableName tableName, byte[] bytes) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void splitRegion(byte[] bytes, byte[] bytes1) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public Future splitRegionAsync(byte[] bytes, byte[] bytes1) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void modifyTable(TableName tableName, TableDescriptor tableDescriptor) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void modifyTable(TableDescriptor tableDescriptor) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public Future modifyTableAsync(TableName tableName, TableDescriptor tableDescriptor) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public Future modifyTableAsync(TableDescriptor tableDescriptor) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void shutdown() throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void stopMaster() throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public boolean isMasterInMaintenanceMode() throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void stopRegionServer(String s) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public ClusterMetrics getClusterMetrics(EnumSet enumSet) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public List getRegionMetrics(ServerName serverName) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public List getRegionMetrics(ServerName serverName, TableName tableName) throws IOException {
+ if (tableName == null) {
+ throw new FeatureNotSupportedException("does not support tableName is null");
+ }
+ OHConnectionConfiguration connectionConf = new OHConnectionConfiguration(conf);
+ ObTableClient tableClient = ObTableClientManager.getOrCreateObTableClientByTableName(tableName, connectionConf);
+ OHRegionMetricsExecutor executor = new OHRegionMetricsExecutor(tableClient);
+ return executor.getRegionMetrics(tableName.getNameAsString());
+ }
+
+ @Override
+ public Configuration getConfiguration() {
+ return connection.getConfiguration();
+ }
+
+ @Override
+ public void createNamespace(NamespaceDescriptor namespaceDescriptor) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public Future createNamespaceAsync(NamespaceDescriptor namespaceDescriptor) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void modifyNamespace(NamespaceDescriptor namespaceDescriptor) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public Future modifyNamespaceAsync(NamespaceDescriptor namespaceDescriptor) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void deleteNamespace(String s) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public Future deleteNamespaceAsync(String s) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public NamespaceDescriptor getNamespaceDescriptor(String s) throws NamespaceNotFoundException, IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public NamespaceDescriptor[] listNamespaceDescriptors() throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public HTableDescriptor[] listTableDescriptorsByNamespace(String s) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public List listTableDescriptorsByNamespace(byte[] bytes) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public TableName[] listTableNamesByNamespace(String s) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public List getTableRegions(TableName tableName) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public List getRegions(TableName tableName) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public synchronized void close() throws IOException {
+ }
+
+ @Override
+ public HTableDescriptor[] getTableDescriptorsByTableName(List list) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public List listTableDescriptors(List list) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public HTableDescriptor[] getTableDescriptors(List list) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public boolean abortProcedure(long l, boolean b) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public Future abortProcedureAsync(long l, boolean b) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public String getProcedures() throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public String getLocks() throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void rollWALWriter(ServerName serverName) throws IOException, FailedLogCloseException {
+ 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 {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public CompactionState getCompactionStateForRegion(byte[] bytes) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public long getLastMajorCompactionTimestamp(TableName tableName) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public long getLastMajorCompactionTimestampForRegion(byte[] bytes) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ 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 {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ 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 {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ 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 {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void restoreSnapshot(byte[] bytes) throws IOException, RestoreSnapshotException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void restoreSnapshot(String s) throws IOException, RestoreSnapshotException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public Future restoreSnapshotAsync(String s) throws IOException, RestoreSnapshotException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void restoreSnapshot(byte[] bytes, boolean b) throws IOException, RestoreSnapshotException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void restoreSnapshot(String s, boolean b) throws IOException, RestoreSnapshotException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ 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 {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ 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 {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public Future cloneSnapshotAsync(String s, TableName tableName) throws IOException, TableExistsException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void execProcedure(String s, String s1, Map map) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ 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 {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public List listSnapshots() throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public List listSnapshots(String s) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public List listSnapshots(Pattern pattern) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public List listTableSnapshots(String s, String s1) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public List listTableSnapshots(Pattern pattern, Pattern pattern1) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void deleteSnapshot(byte[] bytes) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void deleteSnapshot(String s) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void deleteSnapshots(String s) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void deleteSnapshots(Pattern pattern) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void deleteTableSnapshots(String s, String s1) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void deleteTableSnapshots(Pattern pattern, Pattern pattern1) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void setQuota(QuotaSettings quotaSettings) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public QuotaRetriever getQuotaRetriever(QuotaFilter quotaFilter) throws IOException {
+ 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");
+ }
+
+ @Override
+ public CoprocessorRpcChannel coprocessorService(ServerName serverName) {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void updateConfiguration(ServerName serverName) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void updateConfiguration() throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public List getSecurityCapabilities() throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @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 {
+ 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 {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void removeReplicationPeer(String s) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void enableReplicationPeer(String s) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void disableReplicationPeer(String s) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public ReplicationPeerConfig getReplicationPeerConfig(String s) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @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 {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public List listReplicationPeers() throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public List listReplicationPeers(Pattern pattern) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void decommissionRegionServers(List list, boolean b) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public List listDecommissionedRegionServers() throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void recommissionRegionServer(ServerName serverName, List list) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public List listReplicatedTableCFs() throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void enableTableReplication(TableName tableName) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void disableTableReplication(TableName tableName) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public void clearCompactionQueues(ServerName serverName, Set set) throws IOException, InterruptedException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+
+ @Override
+ public List clearDeadServers(List list) throws IOException {
+ throw new FeatureNotSupportedException("does not support yet");
+ }
+}
diff --git a/src/main/java/com/alipay/oceanbase/hbase/util/OHBaseExceptionUtil.java b/src/main/java/com/alipay/oceanbase/hbase/util/OHBaseExceptionUtil.java
new file mode 100644
index 00000000..7223ca90
--- /dev/null
+++ b/src/main/java/com/alipay/oceanbase/hbase/util/OHBaseExceptionUtil.java
@@ -0,0 +1,27 @@
+package com.alipay.oceanbase.hbase.util;
+
+import com.alipay.oceanbase.rpc.exception.ObTableException;
+import com.alipay.oceanbase.rpc.protocol.payload.ResultCodes;
+import org.apache.hadoop.hbase.*;
+
+import java.io.IOException;
+
+public class OHBaseExceptionUtil {
+ public static IOException convertTableException(Exception e) {
+ if (e instanceof ObTableException) {
+ final int errCode = ((ObTableException) e).getErrorCode();
+ if (errCode == ResultCodes.OB_KV_HBASE_TABLE_NOT_EXISTS.errorCode) {
+ return (TableNotFoundException) new TableNotFoundException(e.getMessage()).initCause(e);
+ } else if (errCode == ResultCodes.OB_KV_HBASE_TABLE_EXISTS.errorCode) {
+ return (TableExistsException) new TableExistsException(e.getMessage()).initCause(e);
+ } else if (errCode == ResultCodes.OB_KV_HBASE_NAMESPACE_NOT_FOUND.errorCode) {
+ return (NamespaceNotFoundException) new NamespaceNotFoundException(e.getMessage()).initCause(e);
+ } else if (errCode == ResultCodes.OB_KV_TABLE_NOT_ENABLED.errorCode) {
+ return (TableNotEnabledException) new TableNotEnabledException(e.getMessage()).initCause(e);
+ } else if (errCode == ResultCodes.OB_KV_TABLE_NOT_DISABLED.errorCode) {
+ return (TableNotDisabledException) new TableNotDisabledException(e.getMessage()).initCause(e);
+ }
+ }
+ return new IOException("Failed to execute request", e);
+ }
+}
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..76ddf9f7 100644
--- a/src/main/java/com/alipay/oceanbase/hbase/util/OHBufferedMutatorImpl.java
+++ b/src/main/java/com/alipay/oceanbase/hbase/util/OHBufferedMutatorImpl.java
@@ -275,15 +275,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,13 +289,6 @@ 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();
- }
}
}
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 9b98dd0b..3c966a18 100644
--- a/src/main/java/com/alipay/oceanbase/hbase/util/OHConnectionConfiguration.java
+++ b/src/main/java/com/alipay/oceanbase/hbase/util/OHConnectionConfiguration.java
@@ -57,6 +57,7 @@ public class OHConnectionConfiguration {
private final int rpcConnectTimeout;
private final long writeBufferPeriodicFlushTimeoutMs;
private final long writeBufferPeriodicFlushTimerTickMs;
+ private final int numRetries;
public OHConnectionConfiguration(Configuration conf) {
this.paramUrl = conf.get(HBASE_OCEANBASE_PARAM_URL);
@@ -100,6 +101,8 @@ public OHConnectionConfiguration(Configuration conf) {
}
}
this.rpcConnectTimeout = rpcConnectTimeout;
+ this.numRetries = conf.getInt(HConstants.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(
@@ -209,4 +212,8 @@ public long getWriteBufferPeriodicFlushTimeoutMs() {
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 41a0690a..fd666159 100644
--- a/src/main/java/com/alipay/oceanbase/hbase/util/OHConnectionImpl.java
+++ b/src/main/java/com/alipay/oceanbase/hbase/util/OHConnectionImpl.java
@@ -19,6 +19,7 @@
import com.alipay.oceanbase.hbase.OHTable;
import com.alipay.oceanbase.hbase.exception.FeatureNotSupportedException;
+import com.alipay.oceanbase.rpc.ObTableClient;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
@@ -140,12 +141,17 @@ public BufferedMutator getBufferedMutator(BufferedMutatorParams params) throws I
@Override
public RegionLocator getRegionLocator(TableName tableName) throws IOException {
- throw new FeatureNotSupportedException("not supported yet'");
+ // 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);
+ return executor.getRegionLocator(String.valueOf(tableName));
}
@Override
public Admin getAdmin() throws IOException {
- throw new FeatureNotSupportedException("not supported yet'");
+ return new OHAdmin(this);
}
private void shutdownBatchPool(ExecutorService pool) {
diff --git a/src/main/java/com/alipay/oceanbase/hbase/util/OHCreateTableExecutor.java b/src/main/java/com/alipay/oceanbase/hbase/util/OHCreateTableExecutor.java
new file mode 100644
index 00000000..4bab8e3b
--- /dev/null
+++ b/src/main/java/com/alipay/oceanbase/hbase/util/OHCreateTableExecutor.java
@@ -0,0 +1,70 @@
+/*-
+ * #%L
+ * OBKV HBase Client Framework
+ * %%
+ * Copyright (C) 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.databind.ObjectMapper;
+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.HColumnDescriptor;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor;
+import org.apache.hadoop.hbase.client.TableDescriptor;
+
+import java.io.IOException;
+import java.util.*;
+
+public class OHCreateTableExecutor extends AbstractObTableMetaExecutor {
+ private final ObTableClient client;
+
+ OHCreateTableExecutor(ObTableClient client) {
+ this.client = client;
+ }
+
+ @Override
+ public ObTableRpcMetaType getMetaType() {
+ return ObTableRpcMetaType.HTABLE_CREATE_TABLE;
+ }
+
+ @Override
+ public Void parse(ObTableMetaResponse response) throws IOException {
+ // success, do nothing
+ return null;
+ }
+
+ public void createTable(TableDescriptor tableDescriptor, byte[][] splitKeys) throws IOException {
+ final ObTableMetaRequest request = new ObTableMetaRequest();
+ request.setMetaType(getMetaType());
+ Map requestData = new HashMap<>();
+ requestData.put("htable_name", tableDescriptor.getTableName().getNameAsString());
+ Map> columnFamilies = new HashMap<>();
+ for (ColumnFamilyDescriptor columnDescriptor : tableDescriptor.getColumnFamilies()) {
+ Map columnFamily = new HashMap<>();
+ columnFamily.put("ttl", columnDescriptor.getTimeToLive());
+ columnFamily.put("max_version", columnDescriptor.getMaxVersions());
+ columnFamilies.put(columnDescriptor.getNameAsString(), columnFamily);
+ }
+ requestData.put("column_families", columnFamilies);
+ 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
new file mode 100644
index 00000000..1f689596
--- /dev/null
+++ b/src/main/java/com/alipay/oceanbase/hbase/util/OHDeleteTableExecutor.java
@@ -0,0 +1,59 @@
+/*-
+ * #%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.databind.ObjectMapper;
+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 java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class OHDeleteTableExecutor extends AbstractObTableMetaExecutor {
+ private final ObTableClient tableClient;
+
+ OHDeleteTableExecutor(ObTableClient tableClient) {
+ this.tableClient = tableClient;
+ }
+
+ @Override
+ public ObTableRpcMetaType getMetaType() {
+ return ObTableRpcMetaType.HTABLE_DELETE_TABLE;
+ }
+
+ @Override
+ public Void parse(ObTableMetaResponse response) throws IOException {
+ // do nothing, error will be thrown from table
+ return null;
+ }
+
+ public Void deleteTable(String tableName) throws IOException {
+ ObTableMetaRequest request = new ObTableMetaRequest();
+ request.setMetaType(getMetaType());
+ Map requestDataMap = new HashMap<>();
+ requestDataMap.put("table_name", tableName);
+ 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/OHRegionLocator.java b/src/main/java/com/alipay/oceanbase/hbase/util/OHRegionLocator.java
new file mode 100644
index 00000000..42ea4179
--- /dev/null
+++ b/src/main/java/com/alipay/oceanbase/hbase/util/OHRegionLocator.java
@@ -0,0 +1,142 @@
+/*-
+ * #%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.rpc.exception.ObTableTransportException;
+import org.apache.hadoop.hbase.HRegionLocation;
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.client.RegionLocator;
+import org.apache.hadoop.hbase.exceptions.TimeoutIOException;
+import org.apache.hadoop.hbase.util.Pair;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class OHRegionLocator implements RegionLocator {
+ private byte[][] startKeys;
+ private byte[][] endKeys;
+ private final ObTableClient tableClient;
+ private final TableName tableName;
+
+ private List> regionLocations;
+
+ public OHRegionLocator(byte[][] startKeys, byte[][] endKeys,
+ List> regionLocations, TableName tableName,
+ ObTableClient tableClient) {
+ this.startKeys = startKeys;
+ this.endKeys = endKeys;
+ this.regionLocations = regionLocations;
+ this.tableName = tableName;
+ this.tableClient = tableClient;
+ }
+
+ @Override
+ public HRegionLocation getRegionLocation(byte[] bytes) throws IOException {
+ // check if bytes is in the range of startKeys and endKeys
+ for (Pair pair : regionLocations) {
+ if (pair.getSecond() && pair.getFirst().getRegionInfo().containsRow(bytes)) {
+ return pair.getFirst();
+ }
+ }
+ return null;
+ }
+
+ public List> getRegionLocationPair() {
+ return regionLocations;
+ }
+
+ @Override
+ public HRegionLocation getRegionLocation(byte[] bytes, boolean b) throws IOException {
+ if (b || regionLocations.isEmpty()) {
+ OHRegionLocatorExecutor executor = new OHRegionLocatorExecutor(tableName.toString(),
+ tableClient);
+ try {
+ OHRegionLocator location = executor.getRegionLocator(tableName.toString());
+ this.startKeys = location.getStartKeys();
+ this.endKeys = location.getEndKeys();
+ this.regionLocations = location.getRegionLocationPair();
+ } catch (IOException e) {
+ if (e.getCause() instanceof ObTableTransportException
+ && ((ObTableTransportException) e.getCause()).getErrorCode() == TransportCodes.BOLT_TIMEOUT) {
+ throw new TimeoutIOException(e.getCause());
+ } else {
+ throw e;
+ }
+ }
+ }
+ return getRegionLocation(bytes);
+ }
+
+ @Override
+ public List getAllRegionLocations() throws IOException {
+ return regionLocations.stream().map(Pair::getFirst).collect(Collectors.toList());
+ }
+
+ /**
+ * Gets the starting row key for every region in the currently open table.
+ *
+ * This is mainly useful for the MapReduce integration.
+ *
+ * @return Array of region starting row keys
+ * @throws IOException if a remote or network exception occurs
+ */
+ @Override
+ public byte[][] getStartKeys() throws IOException {
+ return startKeys;
+ }
+
+ /**
+ * Gets the ending row key for every region in the currently open table.
+ *
+ * This is mainly useful for the MapReduce integration.
+ *
+ * @return Array of region ending row keys
+ * @throws IOException if a remote or network exception occurs
+ */
+ @Override
+ public byte[][] getEndKeys() throws IOException {
+ return endKeys;
+ }
+
+ /**
+ * Gets the starting and ending row keys for every region in the currently
+ * open table.
+ *
+ * This is mainly useful for the MapReduce integration.
+ *
+ * @return Pair of arrays of region starting and ending row keys
+ * @throws IOException if a remote or network exception occurs
+ */
+ @Override
+ public Pair getStartEndKeys() throws IOException {
+ return Pair.newPair(startKeys, endKeys);
+ }
+
+ @Override
+ public TableName getName() {
+ return tableName;
+ }
+
+ @Override
+ public void close() throws IOException {
+ return;
+ }
+}
diff --git a/src/main/java/com/alipay/oceanbase/hbase/util/OHRegionLocatorExecutor.java b/src/main/java/com/alipay/oceanbase/hbase/util/OHRegionLocatorExecutor.java
new file mode 100644
index 00000000..63978d6c
--- /dev/null
+++ b/src/main/java/com/alipay/oceanbase/hbase/util/OHRegionLocatorExecutor.java
@@ -0,0 +1,258 @@
+/*-
+ * #%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.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.ObTableUnexpectedException;
+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.*;
+import org.apache.hadoop.hbase.util.Pair;
+
+import java.io.IOException;
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+public class OHRegionLocatorExecutor extends AbstractObTableMetaExecutor {
+ private final String tableName;
+ private final ObTableClient client;
+
+ OHRegionLocatorExecutor(String tableName, ObTableClient client) {
+ this.tableName = tableName;
+ this.client = client;
+ }
+
+ @Override
+ public ObTableRpcMetaType getMetaType() {
+ return ObTableRpcMetaType.HTABLE_REGION_LOCATOR;
+ }
+
+ /**
+ * Parses the response and creates a region locator
+ * @param response response from the server
+ * @return OHRegionLocator
+ * @throws IOException if failed to parse the response
+ */
+ @Override
+ public OHRegionLocator parse(ObTableMetaResponse response) throws IOException {
+ try {
+ final String jsonData = response.getData();
+ final ObjectMapper objectMapper = new ObjectMapper();
+ final JsonNode jsonMap = Optional.ofNullable(objectMapper.readTree(jsonData))
+ .orElseThrow(() -> new IOException("jsonMap is null"));
+ /*
+ {
+ "table_id_dict": [1001, 1002],
+ "replica_dict": [
+ ["127.0.0.1", 2881],
+ ["127.0.0.2", 2882],
+ ["127.0.0.3", 2883]
+ ],
+ "partitions": [
+ // 表1001的3个分区,每个分区3副本
+ [0, 50001, "rowkey_1", 0, 1], // leader
+ [0, 50001, "rowkey_1", 1, 2], // follower
+ [0, 50001, "rowkey_1", 2, 2], // follower
+ [0, 50002, "rowkey_2", 0, 1],
+ [0, 50002, "rowkey_2", 1, 2],
+ [0, 50002, "rowkey_2", 2, 2],
+ [0, 50003, "rowkey_3", 0, 1],
+ [0, 50003, "rowkey_3", 1, 2],
+ [0, 50003, "rowkey_3", 2, 2],
+
+ // 表1002的3个分区,每个分区3副本
+ [1, 50004, "rowkey_1", 0, 1],
+ [1, 50004, "rowkey_1", 1, 2],
+ [1, 50004, "rowkey_1", 2, 2],
+ [1, 50005, "rowkey_2", 0, 1],
+ [1, 50005, "rowkey_2", 1, 2],
+ [1, 50005, "rowkey_2", 2, 2],
+ [1, 50006, "rowkey_3", 0, 1],
+ [1, 50006, "rowkey_3", 1, 2],
+ [1, 50006, "rowkey_3", 2, 2]
+ ]
+ }
+ */
+ JsonNode partitionsNode = Optional.ofNullable(jsonMap.get("partitions"))
+ .orElseThrow(() -> new IOException("partitions is null"));
+ List