From 32534b653a86671fe108ad31e6039849b7af8e26 Mon Sep 17 00:00:00 2001 From: maochongxin Date: Sun, 6 Jul 2025 18:40:07 +0800 Subject: [PATCH] add test case for disable-before-delete-table; fix cases --- .../alipay/oceanbase/hbase/util/OHAdmin.java | 156 ++++++++++++------ .../hbase/OHTableAdminInterfaceTest.java | 69 +++++++- 2 files changed, 175 insertions(+), 50 deletions(-) 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 e6fab736..1e63a2e6 100644 --- a/src/main/java/com/alipay/oceanbase/hbase/util/OHAdmin.java +++ b/src/main/java/com/alipay/oceanbase/hbase/util/OHAdmin.java @@ -32,10 +32,56 @@ import java.util.concurrent.Future; import java.util.regex.Pattern; +import static com.alipay.oceanbase.rpc.protocol.payload.ResultCodes.*; + public class OHAdmin implements Admin { private boolean aborted = false; private final OHConnectionImpl connection; private final Configuration conf; + + @FunctionalInterface + private interface ExceptionHandler { + void handle(int errorCode, TableName tableName) throws IOException; + } + + private Throwable getRootCause(Throwable e) { + Throwable cause = e.getCause(); + while(cause != null && cause.getCause() != null) { + cause = cause.getCause(); + } + return cause; + } + + private void handleTimeoutException(Exception e) throws TimeoutIOException { + if (e.getCause() instanceof ObTableTransportException + && ((ObTableTransportException) e.getCause()).getErrorCode() == TransportCodes.BOLT_TIMEOUT) { + throw new TimeoutIOException(e.getCause()); + } + } + + private void handleObTableException(Exception e, TableName tableName, ExceptionHandler exceptionHandler) throws IOException { + if (e instanceof IOException) { + handleTimeoutException(e); + } + + Throwable cause = getRootCause(e); + + if (cause instanceof ObTableException) { + int errCode = ((ObTableException) cause).getErrorCode(); + try { + exceptionHandler.handle(errCode, tableName); + } catch (RuntimeException re) { + throw re; + } + } + + if (e instanceof IOException) { + throw (IOException) e; + } else { + throw new IOException(e); + } + } + OHAdmin(OHConnectionImpl connection) { this.connection = connection; this.conf = connection.getConfiguration(); @@ -72,10 +118,7 @@ public boolean tableExists(TableName tableName) throws IOException { 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(); - } + Throwable cause = getRootCause(e); if (cause instanceof ObTableException) { int errCode = ((ObTableException) cause).getErrorCode(); // if the original cause is database_not_exist, means namespace in tableName does not exist @@ -84,7 +127,11 @@ public boolean tableExists(TableName tableName) throws IOException { return false; } } - throw e; + if (e instanceof IOException) { + throw (IOException) e; + } else { + throw new IOException(e); + } } } @@ -161,14 +208,14 @@ public HTableDescriptor getTableDescriptor(TableName tableName) throws TableNotF 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; - } + handleObTableException(e, tableName, (errCode, argTableName) -> { + if (errCode == OB_KV_HBASE_TABLE_NOT_EXISTS.errorCode) { + throw new TableNotFoundException(argTableName); + } else if (errCode == OB_KV_HBASE_NAMESPACE_NOT_FOUND.errorCode) { + throw new NamespaceNotFoundException(argTableName.getNamespaceAsString()); + } + }); + throw e; // should never reach } } @@ -180,14 +227,14 @@ public TableDescriptor getDescriptor(TableName tableName) throws IOException { 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; - } + handleObTableException(e, tableName, (errCode, argTableName) -> { + if (errCode == OB_KV_HBASE_TABLE_NOT_EXISTS.errorCode) { + throw new TableNotFoundException(argTableName); + } else if (errCode == OB_KV_HBASE_NAMESPACE_NOT_FOUND.errorCode) { + throw new NamespaceNotFoundException(argTableName.getNamespaceAsString()); + } + }); + throw e; // should never reach } } @@ -199,12 +246,13 @@ public void createTable(TableDescriptor tableDescriptor) throws IOException { 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; - } + handleObTableException(e, tableDescriptor.getTableName(), (errCode, tableName) -> { + if (errCode == OB_KV_HBASE_TABLE_EXISTS.errorCode) { + throw new TableExistsException(tableName.getNameAsString()); + } else if (errCode == OB_KV_HBASE_NAMESPACE_NOT_FOUND.errorCode) { + throw new NamespaceNotFoundException(tableName.getNameAsString()); + } + }); } } @@ -231,12 +279,15 @@ public void deleteTable(TableName tableName) throws IOException { 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; - } + handleObTableException(e, tableName, (errCode, argTableName) -> { + if (errCode == OB_KV_HBASE_TABLE_NOT_EXISTS.errorCode) { + throw new TableNotFoundException(argTableName); + } else if (errCode == OB_KV_HBASE_NAMESPACE_NOT_FOUND.errorCode) { + throw new NamespaceNotFoundException(argTableName.getNamespaceAsString()); + } else if (errCode == OB_KV_TABLE_NOT_DISABLED.errorCode) { + throw new TableNotDisabledException(argTableName); + } + }); } } @@ -273,12 +324,13 @@ public void enableTable(TableName tableName) throws IOException { 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; - } + handleObTableException(e, tableName, (errCode, argTableName) -> { + if (errCode == OB_KV_HBASE_TABLE_NOT_EXISTS.errorCode) { + throw new TableNotFoundException(argTableName); + } else if (errCode == OB_KV_HBASE_NAMESPACE_NOT_FOUND.errorCode) { + throw new NamespaceNotFoundException(argTableName.getNamespaceAsString()); + } + }); } } @@ -310,12 +362,13 @@ public void disableTable(TableName tableName) throws IOException { 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; - } + handleObTableException(e, tableName, (errCode, argTableName) -> { + if (errCode == OB_KV_HBASE_TABLE_NOT_EXISTS.errorCode) { + throw new TableNotFoundException(argTableName); + } else if (errCode == OB_KV_HBASE_NAMESPACE_NOT_FOUND.errorCode) { + throw new NamespaceNotFoundException(argTableName.getNamespaceAsString()); + } + }); } } @@ -704,7 +757,18 @@ public List getRegionMetrics(ServerName serverName, TableName tab OHConnectionConfiguration connectionConf = new OHConnectionConfiguration(conf); ObTableClient tableClient = ObTableClientManager.getOrCreateObTableClientByTableName(tableName, connectionConf); OHRegionMetricsExecutor executor = new OHRegionMetricsExecutor(tableClient); - return executor.getRegionMetrics(tableName.getNameAsString()); + try { + return executor.getRegionMetrics(tableName.getNameAsString()); + } catch (Exception e) { + handleObTableException(e, tableName, (errCode, argTableName) -> { + if (errCode == OB_KV_HBASE_TABLE_NOT_EXISTS.errorCode) { + throw new TableNotFoundException(argTableName.getNameAsString()); + } else if (errCode == OB_KV_HBASE_NAMESPACE_NOT_FOUND.errorCode) { + throw new NamespaceNotFoundException(argTableName.getNamespaceAsString()); + } + }); + throw e; // should never reach + } } @Override diff --git a/src/test/java/com/alipay/oceanbase/hbase/OHTableAdminInterfaceTest.java b/src/test/java/com/alipay/oceanbase/hbase/OHTableAdminInterfaceTest.java index 1e771a3a..fef5f5fc 100644 --- a/src/test/java/com/alipay/oceanbase/hbase/OHTableAdminInterfaceTest.java +++ b/src/test/java/com/alipay/oceanbase/hbase/OHTableAdminInterfaceTest.java @@ -477,8 +477,14 @@ public void testAdminEnDisableTable() throws Exception { e.printStackTrace(); throw e; } finally { + if (admin.isTableEnabled(TableName.valueOf("test_en_dis_tb"))) { + admin.disableTable(TableName.valueOf("test_en_dis_tb")); + } admin.deleteTable(TableName.valueOf("test_en_dis_tb")); assertFalse(admin.tableExists(TableName.valueOf("test_en_dis_tb"))); + if (admin.isTableEnabled(TableName.valueOf("en_dis", "test"))) { + admin.disableTable(TableName.valueOf("en_dis", "test")); + } admin.deleteTable(TableName.valueOf("en_dis", "test")); assertFalse(admin.tableExists(TableName.valueOf("en_dis", "test"))); } @@ -580,7 +586,6 @@ public void testAdminGetRegionMetrics() throws Exception { " PRIMARY KEY (`K`, `Q`, `T`)\n" + ") TABLEGROUP = `get_region:test_multi_cf` PARTITION BY KEY(`K`) PARTITIONS 3;"); st.close(); - conn.close(); String tablegroup1 = "test_get_region_metrics"; String tablegroup2 = "get_region:test_multi_cf"; Configuration conf = ObHTableTestUtil.newConfiguration(); @@ -686,7 +691,7 @@ public void testAdminGetRegionMetrics() throws Exception { metrics = admin.getRegionMetrics(null, 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()); + assertEquals(1, metrics.size()); } catch (Exception e) { e.printStackTrace(); throw e; @@ -728,11 +733,20 @@ public void testAdminDeleteTable() throws Exception { assertTrue(admin.tableExists(TableName.valueOf("test_del_tb"))); IOException thrown = assertThrows(IOException.class, () -> { + if (admin.isTableEnabled(TableName.valueOf("tablegroup_not_exists"))) { + admin.disableTable(TableName.valueOf("tablegroup_not_exists")); + } admin.deleteTable(TableName.valueOf("tablegroup_not_exists")); }); Assert.assertTrue(thrown.getCause() instanceof ObTableException); Assert.assertEquals(ResultCodes.OB_KV_HBASE_TABLE_NOT_EXISTS.errorCode, ((ObTableException) thrown.getCause()).getErrorCode()); + if (admin.isTableEnabled(TableName.valueOf("del_tb", "test"))) { + admin.disableTable(TableName.valueOf("del_tb", "test")); + } admin.deleteTable(TableName.valueOf("del_tb", "test")); + if (admin.isTableEnabled(TableName.valueOf("test_del_tb"))) { + admin.disableTable(TableName.valueOf("test_del_tb")); + } admin.deleteTable(TableName.valueOf("test_del_tb")); assertFalse(admin.tableExists(TableName.valueOf("del_tb", "test"))); assertFalse(admin.tableExists(TableName.valueOf("test_del_tb"))); @@ -1459,6 +1473,9 @@ public void testCreateTableInjectError() throws Exception { if (admin.tableExists(TableName.valueOf(tableName))) { setErrSimPoint(ErrSimPoint.EN_DELETE_HTABLE_CF_FINISH_ERR, false); setErrSimPoint(ErrSimPoint.EN_DELETE_HTABLE_SKIP_CF_ERR, false); + if (admin.isTableEnabled(TableName.valueOf(tableName))) { + admin.disableTable(TableName.valueOf(tableName)); + } admin.deleteTable(TableName.valueOf(tableName)); } } @@ -1522,6 +1539,9 @@ public void testHbaseDDLException() throws Exception { } catch (Exception e) { Assert.assertEquals(e.getClass(), TableExistsException.class); } finally { + if (admin.isTableEnabled(TableName.valueOf("t1"))) { + admin.disableTable(TableName.valueOf("t1")); + } admin.deleteTable(TableName.valueOf("t1")); } @@ -1541,6 +1561,9 @@ public void testHbaseDDLException() throws Exception { } catch (Exception e) { Assert.assertEquals(e.getClass(), TableNotDisabledException.class); } finally { + if (admin.isTableEnabled(TableName.valueOf("t1"))) { + admin.disableTable(TableName.valueOf("t1")); + } admin.deleteTable(TableName.valueOf("t1")); } @@ -1581,6 +1604,9 @@ public void testHbaseDDLException() throws Exception { } catch (Exception e) { Assert.assertEquals(e.getClass(), TableExistsException.class); } finally { + if (admin.isTableEnabled(TableName.valueOf("t1"))) { + admin.disableTable(TableName.valueOf("t1")); + } admin.deleteTable(TableName.valueOf("t1")); } @@ -1600,6 +1626,9 @@ public void testHbaseDDLException() throws Exception { } catch (Exception e) { Assert.assertEquals(e.getClass(), TableNotDisabledException.class); } finally { + if (admin.isTableEnabled(TableName.valueOf("t1"))) { + admin.disableTable(TableName.valueOf("t1")); + } admin.deleteTable(TableName.valueOf("t1")); } @@ -1612,6 +1641,9 @@ public void testHbaseDDLException() throws Exception { } catch (Exception e) { Assert.assertEquals(e.getClass(), TableNotEnabledException.class); } finally { + if (admin.isTableEnabled(TableName.valueOf("t1"))) { + admin.disableTable(TableName.valueOf("t1")); + } admin.deleteTable(TableName.valueOf("t1")); } @@ -1635,8 +1667,8 @@ public void testCreateDropTableGroup() throws Exception { Connection connection = ConnectionFactory.createConnection(conf); Admin admin = connection.getAdmin(); java.sql.Connection conn = ObHTableTestUtil.getConnection(); - java.sql.Connection sysConn = ObHTableTestUtil.getSysConnection(); - String tenantName = "mysql"; + java.sql.Connection sysConn = ObHTableTestUtil.getSysTenantConnection(); + String tenantName = FULL_USER_NAME.split("@")[1].split("#")[0]; byte[] tableName = Bytes.toBytes("test_create_drop_tg_helper"); byte[] cf1 = Bytes.toBytes("cf1"); @@ -1657,6 +1689,9 @@ public void testCreateDropTableGroup() throws Exception { // 1. open err EN_DELETE_HTABLE_SKIP_CF_ERR, will skip delete cf table when delete hbase table // and the subsequent delete htable operations will return OB_TABLEGROUP_NOT_EMPTY + if (admin.isTableEnabled(TableName.valueOf(tableName))) { + admin.disableTable(TableName.valueOf(tableName)); + } setErrSimPoint(ErrSimPoint.EN_DELETE_HTABLE_SKIP_CF_ERR, true); ObHTableTestUtil.executeIgnoreExpectedErrors(() -> admin.deleteTable(TableName.valueOf(tableName)), "OB_TABLEGROUP_NOT_EMPTY"); assertTrue("Table should still exist after delete error injection", @@ -1682,6 +1717,9 @@ public void testCreateDropTableGroup() throws Exception { executeSQL(conn, "drop database if exists db_test_create_drop_tg_helper", true); executeSQL(sysConn, String.format("alter tenant %s set default tablegroup = null", tenantName), true); if (admin.tableExists(TableName.valueOf(tableName))) { + if (admin.isTableEnabled(TableName.valueOf(tableName))) { + admin.disableTable(TableName.valueOf(tableName)); + } setErrSimPoint(ErrSimPoint.EN_DELETE_HTABLE_SKIP_CF_ERR, false); admin.deleteTable(TableName.valueOf(tableName)); } @@ -1774,4 +1812,27 @@ public void testDDLStmtStr() throws Exception { } } } + + @Test + public void testDropEnabledTableFail() throws Exception { + Configuration conf = ObHTableTestUtil.newConfiguration(); + Connection connection = ConnectionFactory.createConnection(conf); + Admin admin = connection.getAdmin(); + + byte[] tableName = Bytes.toBytes("test_drop_enabled_table_fail"); + byte[] cf1 = Bytes.toBytes("cf1"); + HColumnDescriptor hcd1 = new HColumnDescriptor(cf1); + HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(tableName)); + htd.addFamily(hcd1); + try { + admin.createTable(htd); + admin.deleteTable(TableName.valueOf(tableName)); + fail(); + } catch (Exception e) { + assertTrue(true); + } + admin.disableTable(TableName.valueOf(tableName)); + admin.deleteTable(TableName.valueOf(tableName)); + Assert.assertFalse(admin.tableExists(TableName.valueOf(tableName))); + } }