001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.client; 019 020import static org.apache.hadoop.hbase.TableName.META_TABLE_NAME; 021import static org.apache.hadoop.hbase.regionserver.storefiletracker.StoreFileTrackerFactory.TRACKER_IMPL; 022import static org.hamcrest.CoreMatchers.instanceOf; 023import static org.hamcrest.MatcherAssert.assertThat; 024import static org.junit.jupiter.api.Assertions.assertEquals; 025import static org.junit.jupiter.api.Assertions.assertFalse; 026import static org.junit.jupiter.api.Assertions.assertTrue; 027import static org.junit.jupiter.api.Assertions.fail; 028 029import java.util.ArrayList; 030import java.util.Collections; 031import java.util.List; 032import java.util.concurrent.ExecutionException; 033import java.util.function.Supplier; 034import java.util.regex.Pattern; 035import org.apache.hadoop.hbase.ClientMetaTableAccessor; 036import org.apache.hadoop.hbase.DoNotRetryIOException; 037import org.apache.hadoop.hbase.HBaseParameterizedTestTemplate; 038import org.apache.hadoop.hbase.HRegionLocation; 039import org.apache.hadoop.hbase.TableName; 040import org.apache.hadoop.hbase.regionserver.storefiletracker.StoreFileTrackerFactory; 041import org.apache.hadoop.hbase.testclassification.ClientTests; 042import org.apache.hadoop.hbase.testclassification.LargeTests; 043import org.apache.hadoop.hbase.util.Bytes; 044import org.junit.jupiter.api.AfterAll; 045import org.junit.jupiter.api.BeforeAll; 046import org.junit.jupiter.api.Tag; 047import org.junit.jupiter.api.TestTemplate; 048 049/** 050 * Class to test asynchronous table admin operations. 051 * @see TestAsyncTableAdminApi2 This test and it used to be joined it was taking longer than our ten 052 * minute timeout so they were split. 053 */ 054@Tag(LargeTests.TAG) 055@Tag(ClientTests.TAG) 056@HBaseParameterizedTestTemplate(name = "{index}: policy = {0}") 057public class TestAsyncTableAdminApi3 extends TestAsyncAdminBase { 058 059 public TestAsyncTableAdminApi3(Supplier<AsyncAdmin> admin) { 060 super(admin); 061 } 062 063 @BeforeAll 064 public static void setUpBeforeClass() throws Exception { 065 TestAsyncAdminBase.setUpBeforeClass(); 066 } 067 068 @AfterAll 069 public static void tearDownAfterClass() throws Exception { 070 TestAsyncAdminBase.tearDownAfterClass(); 071 } 072 073 @TestTemplate 074 public void testTableExist() throws Exception { 075 boolean exist; 076 exist = admin.tableExists(tableName).get(); 077 assertFalse(exist); 078 TEST_UTIL.createTable(tableName, FAMILY); 079 exist = admin.tableExists(tableName).get(); 080 assertTrue(exist); 081 exist = admin.tableExists(TableName.META_TABLE_NAME).get(); 082 assertTrue(exist); 083 // meta table already exists 084 exist = admin.tableExists(TableName.META_TABLE_NAME).get(); 085 assertTrue(exist); 086 } 087 088 @TestTemplate 089 public void testListTables() throws Exception { 090 int numTables = admin.listTableDescriptors().get().size(); 091 final TableName tableName1 = TableName.valueOf(tableName.getNameAsString() + "1"); 092 final TableName tableName2 = TableName.valueOf(tableName.getNameAsString() + "2"); 093 final TableName tableName3 = TableName.valueOf(tableName.getNameAsString() + "3"); 094 TableName[] tables = new TableName[] { tableName1, tableName2, tableName3 }; 095 for (int i = 0; i < tables.length; i++) { 096 createTableWithDefaultConf(tables[i]); 097 } 098 099 List<TableDescriptor> tableDescs = admin.listTableDescriptors().get(); 100 int size = tableDescs.size(); 101 assertTrue(size >= tables.length); 102 for (int i = 0; i < tables.length && i < size; i++) { 103 boolean found = false; 104 for (int j = 0; j < size; j++) { 105 if (tableDescs.get(j).getTableName().equals(tables[i])) { 106 found = true; 107 break; 108 } 109 } 110 assertTrue(found, "Not found: " + tables[i]); 111 } 112 113 List<TableName> tableNames = admin.listTableNames().get(); 114 size = tableNames.size(); 115 assertTrue(size == (numTables + tables.length)); 116 for (int i = 0; i < tables.length && i < size; i++) { 117 boolean found = false; 118 for (int j = 0; j < size; j++) { 119 if (tableNames.get(j).equals(tables[i])) { 120 found = true; 121 break; 122 } 123 } 124 assertTrue(found, "Not found: " + tables[i]); 125 } 126 127 tableNames = new ArrayList<TableName>(tables.length + 1); 128 tableDescs = admin.listTableDescriptors(tableNames).get(); 129 size = tableDescs.size(); 130 assertEquals(0, size); 131 132 Collections.addAll(tableNames, tables); 133 tableNames.add(TableName.META_TABLE_NAME); 134 tableDescs = admin.listTableDescriptors(tableNames).get(); 135 size = tableDescs.size(); 136 assertEquals(tables.length + 1, size); 137 for (int i = 0, j = 0; i < tables.length && j < size; i++, j++) { 138 assertTrue(tableDescs.get(j).getTableName().equals(tables[i]), 139 "tableName should be equal in order"); 140 } 141 assertTrue(tableDescs.get(size - 1).getTableName().equals(TableName.META_TABLE_NAME)); 142 143 for (int i = 0; i < tables.length; i++) { 144 admin.disableTable(tables[i]).join(); 145 admin.deleteTable(tables[i]).join(); 146 } 147 148 tableDescs = admin.listTableDescriptors(true).get(); 149 assertTrue(tableDescs.size() > 0, "Not found system tables"); 150 tableNames = admin.listTableNames(true).get(); 151 assertTrue(tableNames.size() > 0, "Not found system tables"); 152 } 153 154 @TestTemplate 155 public void testGetTableDescriptor() throws Exception { 156 byte[][] families = { FAMILY, FAMILY_0, FAMILY_1 }; 157 TableDescriptorBuilder builder = TableDescriptorBuilder.newBuilder(tableName); 158 for (byte[] family : families) { 159 builder.setColumnFamily(ColumnFamilyDescriptorBuilder.of(family)); 160 } 161 TableDescriptor desc = builder.build(); 162 admin.createTable(desc).join(); 163 TableDescriptor confirmedHtd = admin.getDescriptor(tableName).get(); 164 // HBASE-26246 introduced persist of store file tracker into table descriptor 165 desc = TableDescriptorBuilder.newBuilder(desc).setValue(TRACKER_IMPL, 166 StoreFileTrackerFactory.getStoreFileTrackerName(TEST_UTIL.getConfiguration())).build(); 167 assertEquals(0, TableDescriptor.COMPARATOR.compare(desc, confirmedHtd)); 168 } 169 170 @TestTemplate 171 public void testDisableAndEnableTable() throws Exception { 172 createTableWithDefaultConf(tableName); 173 AsyncTable<?> table = ASYNC_CONN.getTable(tableName); 174 final byte[] row = Bytes.toBytes("row"); 175 final byte[] qualifier = Bytes.toBytes("qualifier"); 176 final byte[] value = Bytes.toBytes("value"); 177 Put put = new Put(row); 178 put.addColumn(FAMILY, qualifier, value); 179 table.put(put).join(); 180 Get get = new Get(row); 181 get.addColumn(FAMILY, qualifier); 182 table.get(get).get(); 183 184 this.admin.disableTable(tableName).join(); 185 assertTrue(TEST_UTIL.getHBaseCluster().getMaster().getTableStateManager() 186 .isTableState(tableName, TableState.State.DISABLED), "Table must be disabled."); 187 assertEquals(TableState.State.DISABLED, TestAsyncTableAdminApi.getStateFromMeta(tableName)); 188 189 // Test that table is disabled 190 get = new Get(row); 191 get.addColumn(FAMILY, qualifier); 192 boolean ok = false; 193 try { 194 table.get(get).get(); 195 } catch (ExecutionException e) { 196 ok = true; 197 } 198 ok = false; 199 // verify that scan encounters correct exception 200 try { 201 table.scanAll(new Scan()).get(); 202 } catch (ExecutionException e) { 203 ok = true; 204 } 205 assertTrue(ok); 206 this.admin.enableTable(tableName).join(); 207 assertTrue(TEST_UTIL.getHBaseCluster().getMaster().getTableStateManager() 208 .isTableState(tableName, TableState.State.ENABLED), "Table must be enabled."); 209 assertEquals(TableState.State.ENABLED, TestAsyncTableAdminApi.getStateFromMeta(tableName)); 210 211 // Test that table is enabled 212 try { 213 table.get(get).get(); 214 } catch (Exception e) { 215 ok = false; 216 } 217 assertTrue(ok); 218 // meta table can not be disabled. 219 try { 220 admin.disableTable(TableName.META_TABLE_NAME).get(); 221 fail("meta table can not be disabled"); 222 } catch (ExecutionException e) { 223 Throwable cause = e.getCause(); 224 assertThat(cause, instanceOf(DoNotRetryIOException.class)); 225 } 226 } 227 228 @TestTemplate 229 public void testDisableAndEnableTables() throws Exception { 230 final TableName tableName1 = TableName.valueOf(tableName.getNameAsString() + "1"); 231 final TableName tableName2 = TableName.valueOf(tableName.getNameAsString() + "2"); 232 createTableWithDefaultConf(tableName1); 233 createTableWithDefaultConf(tableName2); 234 AsyncTable<?> table1 = ASYNC_CONN.getTable(tableName1); 235 AsyncTable<?> table2 = ASYNC_CONN.getTable(tableName1); 236 237 final byte[] row = Bytes.toBytes("row"); 238 final byte[] qualifier = Bytes.toBytes("qualifier"); 239 final byte[] value = Bytes.toBytes("value"); 240 Put put = new Put(row); 241 put.addColumn(FAMILY, qualifier, value); 242 table1.put(put).join(); 243 table2.put(put).join(); 244 Get get = new Get(row); 245 get.addColumn(FAMILY, qualifier); 246 table1.get(get).get(); 247 table2.get(get).get(); 248 249 admin.listTableNames(Pattern.compile(tableName.getNameAsString() + ".*"), false).get() 250 .forEach(t -> admin.disableTable(t).join()); 251 252 // Test that tables are disabled 253 get = new Get(row); 254 get.addColumn(FAMILY, qualifier); 255 boolean ok = false; 256 try { 257 table1.get(get).get(); 258 } catch (ExecutionException e) { 259 ok = true; 260 } 261 assertTrue(ok); 262 263 ok = false; 264 try { 265 table2.get(get).get(); 266 } catch (ExecutionException e) { 267 ok = true; 268 } 269 assertTrue(ok); 270 assertEquals(TableState.State.DISABLED, TestAsyncTableAdminApi.getStateFromMeta(tableName1)); 271 assertEquals(TableState.State.DISABLED, TestAsyncTableAdminApi.getStateFromMeta(tableName2)); 272 273 admin.listTableNames(Pattern.compile(tableName.getNameAsString() + ".*"), false).get() 274 .forEach(t -> admin.enableTable(t).join()); 275 276 // Test that tables are enabled 277 try { 278 table1.get(get).get(); 279 } catch (Exception e) { 280 ok = false; 281 } 282 try { 283 table2.get(get).get(); 284 } catch (Exception e) { 285 ok = false; 286 } 287 assertTrue(ok); 288 assertEquals(TableState.State.ENABLED, TestAsyncTableAdminApi.getStateFromMeta(tableName1)); 289 assertEquals(TableState.State.ENABLED, TestAsyncTableAdminApi.getStateFromMeta(tableName2)); 290 } 291 292 @TestTemplate 293 public void testEnableTableRetainAssignment() throws Exception { 294 byte[][] splitKeys = { new byte[] { 1, 1, 1 }, new byte[] { 2, 2, 2 }, new byte[] { 3, 3, 3 }, 295 new byte[] { 4, 4, 4 }, new byte[] { 5, 5, 5 }, new byte[] { 6, 6, 6 }, 296 new byte[] { 7, 7, 7 }, new byte[] { 8, 8, 8 }, new byte[] { 9, 9, 9 } }; 297 int expectedRegions = splitKeys.length + 1; 298 createTableWithDefaultConf(tableName, splitKeys); 299 300 AsyncTable<AdvancedScanResultConsumer> metaTable = ASYNC_CONN.getTable(META_TABLE_NAME); 301 List<HRegionLocation> regions = 302 ClientMetaTableAccessor.getTableHRegionLocations(metaTable, tableName).get(); 303 assertEquals(expectedRegions, regions.size(), 304 "Tried to create " + expectedRegions + " regions " + "but only found " + regions.size()); 305 306 // Disable table. 307 admin.disableTable(tableName).join(); 308 // Enable table, use retain assignment to assign regions. 309 admin.enableTable(tableName).join(); 310 311 List<HRegionLocation> regions2 = 312 ClientMetaTableAccessor.getTableHRegionLocations(metaTable, tableName).get(); 313 // Check the assignment. 314 assertEquals(regions.size(), regions2.size()); 315 assertTrue(regions2.containsAll(regions)); 316 } 317 318 @TestTemplate 319 public void testIsTableEnabledAndDisabled() throws Exception { 320 createTableWithDefaultConf(tableName); 321 assertTrue(admin.isTableEnabled(tableName).get()); 322 assertFalse(admin.isTableDisabled(tableName).get()); 323 admin.disableTable(tableName).join(); 324 assertFalse(admin.isTableEnabled(tableName).get()); 325 assertTrue(admin.isTableDisabled(tableName).get()); 326 327 // meta table is always enabled 328 assertTrue(admin.isTableEnabled(TableName.META_TABLE_NAME).get()); 329 assertFalse(admin.isTableDisabled(TableName.META_TABLE_NAME).get()); 330 } 331 332 @TestTemplate 333 public void testIsTableAvailable() throws Exception { 334 createTableWithDefaultConf(tableName); 335 TEST_UTIL.waitTableAvailable(tableName); 336 assertTrue(admin.isTableAvailable(tableName).get()); 337 assertTrue(admin.isTableAvailable(TableName.META_TABLE_NAME).get()); 338 } 339}