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.HBaseTestingUtil.countRows; 021import static org.apache.hadoop.hbase.regionserver.storefiletracker.StoreFileTrackerFactory.TRACKER_IMPL; 022import static org.junit.Assert.assertEquals; 023import static org.junit.Assert.assertFalse; 024import static org.junit.Assert.assertNotEquals; 025import static org.junit.Assert.assertNotNull; 026import static org.junit.Assert.assertNull; 027import static org.junit.Assert.assertTrue; 028import static org.junit.Assert.fail; 029 030import java.io.IOException; 031import java.util.ArrayList; 032import java.util.HashMap; 033import java.util.Iterator; 034import java.util.List; 035import java.util.Map; 036import org.apache.hadoop.hbase.HBaseClassTestRule; 037import org.apache.hadoop.hbase.HConstants; 038import org.apache.hadoop.hbase.HRegionLocation; 039import org.apache.hadoop.hbase.ServerName; 040import org.apache.hadoop.hbase.TableExistsException; 041import org.apache.hadoop.hbase.TableName; 042import org.apache.hadoop.hbase.TableNotFoundException; 043import org.apache.hadoop.hbase.master.HMaster; 044import org.apache.hadoop.hbase.master.assignment.AssignmentManager; 045import org.apache.hadoop.hbase.master.assignment.RegionStateNode; 046import org.apache.hadoop.hbase.regionserver.storefiletracker.StoreFileTrackerFactory; 047import org.apache.hadoop.hbase.testclassification.ClientTests; 048import org.apache.hadoop.hbase.testclassification.LargeTests; 049import org.apache.hadoop.hbase.util.Bytes; 050import org.junit.ClassRule; 051import org.junit.Test; 052import org.junit.experimental.categories.Category; 053import org.slf4j.Logger; 054import org.slf4j.LoggerFactory; 055 056@Category({ LargeTests.class, ClientTests.class }) 057public class TestAdmin extends TestAdminBase { 058 059 @ClassRule 060 public static final HBaseClassTestRule CLASS_RULE = HBaseClassTestRule.forClass(TestAdmin.class); 061 062 private static final Logger LOG = LoggerFactory.getLogger(TestAdmin.class); 063 064 @Test 065 public void testListTableDescriptors() throws IOException { 066 TableDescriptor metaTableDescriptor = 067 TEST_UTIL.getAdmin().getDescriptor(TableName.META_TABLE_NAME); 068 List<TableDescriptor> tableDescriptors = TEST_UTIL.getAdmin().listTableDescriptors(true); 069 assertTrue(tableDescriptors.contains(metaTableDescriptor)); 070 tableDescriptors = TEST_UTIL.getAdmin().listTableDescriptors(false); 071 assertFalse(tableDescriptors.contains(metaTableDescriptor)); 072 } 073 074 @Test 075 public void testCreateTable() throws IOException { 076 List<TableDescriptor> tables = ADMIN.listTableDescriptors(); 077 int numTables = tables.size(); 078 final TableName tableName = TableName.valueOf(name.getMethodName()); 079 TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY).close(); 080 tables = ADMIN.listTableDescriptors(); 081 assertEquals(numTables + 1, tables.size()); 082 assertTrue("Table must be enabled.", TEST_UTIL.getHBaseCluster().getMaster() 083 .getTableStateManager().isTableState(tableName, TableState.State.ENABLED)); 084 assertEquals(TableState.State.ENABLED, getStateFromMeta(tableName)); 085 } 086 087 @Test 088 public void testTruncateTable() throws IOException { 089 testTruncateTable(TableName.valueOf(name.getMethodName()), false); 090 } 091 092 @Test 093 public void testTruncateTablePreservingSplits() throws IOException { 094 testTruncateTable(TableName.valueOf(name.getMethodName()), true); 095 } 096 097 private void testTruncateTable(final TableName tableName, boolean preserveSplits) 098 throws IOException { 099 byte[][] splitKeys = new byte[2][]; 100 splitKeys[0] = Bytes.toBytes(4); 101 splitKeys[1] = Bytes.toBytes(8); 102 103 // Create & Fill the table 104 Table table = TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY, splitKeys); 105 try { 106 TEST_UTIL.loadNumericRows(table, HConstants.CATALOG_FAMILY, 0, 10); 107 assertEquals(10, countRows(table)); 108 } finally { 109 table.close(); 110 } 111 assertEquals(3, TEST_UTIL.getHBaseCluster().getRegions(tableName).size()); 112 113 // Truncate & Verify 114 ADMIN.disableTable(tableName); 115 ADMIN.truncateTable(tableName, preserveSplits); 116 table = TEST_UTIL.getConnection().getTable(tableName); 117 try { 118 assertEquals(0, countRows(table)); 119 } finally { 120 table.close(); 121 } 122 if (preserveSplits) { 123 assertEquals(3, TEST_UTIL.getHBaseCluster().getRegions(tableName).size()); 124 } else { 125 assertEquals(1, TEST_UTIL.getHBaseCluster().getRegions(tableName).size()); 126 } 127 } 128 129 @Test 130 public void testCreateTableNumberOfRegions() throws IOException, InterruptedException { 131 TableName table = TableName.valueOf(name.getMethodName()); 132 ColumnFamilyDescriptor cfd = ColumnFamilyDescriptorBuilder.of(HConstants.CATALOG_FAMILY); 133 ADMIN.createTable(TableDescriptorBuilder.newBuilder(table).setColumnFamily(cfd).build()); 134 List<HRegionLocation> regions; 135 try (RegionLocator l = TEST_UTIL.getConnection().getRegionLocator(table)) { 136 regions = l.getAllRegionLocations(); 137 assertEquals("Table should have only 1 region", 1, regions.size()); 138 } 139 140 TableName table2 = TableName.valueOf(table.getNameAsString() + "_2"); 141 ADMIN.createTable(TableDescriptorBuilder.newBuilder(table2).setColumnFamily(cfd).build(), 142 new byte[][] { new byte[] { 42 } }); 143 try (RegionLocator l = TEST_UTIL.getConnection().getRegionLocator(table2)) { 144 regions = l.getAllRegionLocations(); 145 assertEquals("Table should have only 2 region", 2, regions.size()); 146 } 147 148 TableName table3 = TableName.valueOf(table.getNameAsString() + "_3"); 149 ADMIN.createTable(TableDescriptorBuilder.newBuilder(table3).setColumnFamily(cfd).build(), 150 Bytes.toBytes("a"), Bytes.toBytes("z"), 3); 151 try (RegionLocator l = TEST_UTIL.getConnection().getRegionLocator(table3)) { 152 regions = l.getAllRegionLocations(); 153 assertEquals("Table should have only 3 region", 3, regions.size()); 154 } 155 156 TableName table4 = TableName.valueOf(table.getNameAsString() + "_4"); 157 try { 158 ADMIN.createTable(TableDescriptorBuilder.newBuilder(table4).setColumnFamily(cfd).build(), 159 Bytes.toBytes("a"), Bytes.toBytes("z"), 2); 160 fail("Should not be able to create a table with only 2 regions using this API."); 161 } catch (IllegalArgumentException eae) { 162 // Expected 163 } 164 165 TableName table5 = TableName.valueOf(table.getNameAsString() + "_5"); 166 ADMIN.createTable(TableDescriptorBuilder.newBuilder(table5).setColumnFamily(cfd).build(), 167 new byte[] { 1 }, new byte[] { 127 }, 16); 168 try (RegionLocator l = TEST_UTIL.getConnection().getRegionLocator(table5)) { 169 regions = l.getAllRegionLocations(); 170 assertEquals("Table should have 16 region", 16, regions.size()); 171 } 172 } 173 174 @Test 175 public void testCreateTableWithRegions() throws IOException, InterruptedException { 176 TableName table = TableName.valueOf(name.getMethodName()); 177 ColumnFamilyDescriptor cfd = ColumnFamilyDescriptorBuilder.of(HConstants.CATALOG_FAMILY); 178 byte[][] splitKeys = { new byte[] { 1, 1, 1 }, new byte[] { 2, 2, 2 }, new byte[] { 3, 3, 3 }, 179 new byte[] { 4, 4, 4 }, new byte[] { 5, 5, 5 }, new byte[] { 6, 6, 6 }, 180 new byte[] { 7, 7, 7 }, new byte[] { 8, 8, 8 }, new byte[] { 9, 9, 9 }, }; 181 int expectedRegions = splitKeys.length + 1; 182 183 ADMIN.createTable(TableDescriptorBuilder.newBuilder(table).setColumnFamily(cfd).build(), 184 splitKeys); 185 186 boolean tableAvailable = ADMIN.isTableAvailable(table); 187 assertTrue("Table should be created with splitKyes + 1 rows in META", tableAvailable); 188 189 List<HRegionLocation> regions; 190 Iterator<HRegionLocation> hris; 191 RegionInfo hri; 192 try (RegionLocator l = TEST_UTIL.getConnection().getRegionLocator(table)) { 193 regions = l.getAllRegionLocations(); 194 195 assertEquals( 196 "Tried to create " + expectedRegions + " regions " + "but only found " + regions.size(), 197 expectedRegions, regions.size()); 198 System.err.println("Found " + regions.size() + " regions"); 199 200 hris = regions.iterator(); 201 hri = hris.next().getRegion(); 202 assertTrue(hri.getStartKey() == null || hri.getStartKey().length == 0); 203 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[0])); 204 hri = hris.next().getRegion(); 205 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[0])); 206 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[1])); 207 hri = hris.next().getRegion(); 208 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[1])); 209 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[2])); 210 hri = hris.next().getRegion(); 211 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[2])); 212 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[3])); 213 hri = hris.next().getRegion(); 214 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[3])); 215 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[4])); 216 hri = hris.next().getRegion(); 217 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[4])); 218 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[5])); 219 hri = hris.next().getRegion(); 220 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[5])); 221 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[6])); 222 hri = hris.next().getRegion(); 223 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[6])); 224 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[7])); 225 hri = hris.next().getRegion(); 226 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[7])); 227 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[8])); 228 hri = hris.next().getRegion(); 229 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[8])); 230 assertTrue(hri.getEndKey() == null || hri.getEndKey().length == 0); 231 232 verifyRoundRobinDistribution(l, expectedRegions); 233 } 234 235 // Now test using start/end with a number of regions 236 237 // Use 80 bit numbers to make sure we aren't limited 238 byte[] startKey = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; 239 byte[] endKey = { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 }; 240 241 // Splitting into 10 regions, we expect (null,1) ... (9, null) 242 // with (1,2) (2,3) (3,4) (4,5) (5,6) (6,7) (7,8) (8,9) in the middle 243 244 expectedRegions = 10; 245 246 TableName table2 = TableName.valueOf(table.getNameAsString() + "_2"); 247 ADMIN.createTable(TableDescriptorBuilder.newBuilder(table2).setColumnFamily(cfd).build(), 248 startKey, endKey, expectedRegions); 249 250 try (RegionLocator l = TEST_UTIL.getConnection().getRegionLocator(table2)) { 251 regions = l.getAllRegionLocations(); 252 assertEquals( 253 "Tried to create " + expectedRegions + " regions " + "but only found " + regions.size(), 254 expectedRegions, regions.size()); 255 System.err.println("Found " + regions.size() + " regions"); 256 257 hris = regions.iterator(); 258 hri = hris.next().getRegion(); 259 assertTrue(hri.getStartKey() == null || hri.getStartKey().length == 0); 260 assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 })); 261 hri = hris.next().getRegion(); 262 assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 })); 263 assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 })); 264 hri = hris.next().getRegion(); 265 assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 })); 266 assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 })); 267 hri = hris.next().getRegion(); 268 assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 })); 269 assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 })); 270 hri = hris.next().getRegion(); 271 assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 })); 272 assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 })); 273 hri = hris.next().getRegion(); 274 assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 })); 275 assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 })); 276 hri = hris.next().getRegion(); 277 assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 })); 278 assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 })); 279 hri = hris.next().getRegion(); 280 assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 })); 281 assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 })); 282 hri = hris.next().getRegion(); 283 assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 })); 284 assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 })); 285 hri = hris.next().getRegion(); 286 assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 })); 287 assertTrue(hri.getEndKey() == null || hri.getEndKey().length == 0); 288 289 verifyRoundRobinDistribution(l, expectedRegions); 290 } 291 292 // Try once more with something that divides into something infinite 293 294 startKey = new byte[] { 0, 0, 0, 0, 0, 0 }; 295 endKey = new byte[] { 1, 0, 0, 0, 0, 0 }; 296 297 expectedRegions = 5; 298 299 TableName table3 = TableName.valueOf(table.getNameAsString() + "_3"); 300 ADMIN.createTable(TableDescriptorBuilder.newBuilder(table3).setColumnFamily(cfd).build(), 301 startKey, endKey, expectedRegions); 302 303 try (RegionLocator l = TEST_UTIL.getConnection().getRegionLocator(table3)) { 304 regions = l.getAllRegionLocations(); 305 assertEquals( 306 "Tried to create " + expectedRegions + " regions " + "but only found " + regions.size(), 307 expectedRegions, regions.size()); 308 System.err.println("Found " + regions.size() + " regions"); 309 310 verifyRoundRobinDistribution(l, expectedRegions); 311 } 312 313 // Try an invalid case where there are duplicate split keys 314 splitKeys = new byte[][] { new byte[] { 1, 1, 1 }, new byte[] { 2, 2, 2 }, 315 new byte[] { 3, 3, 3 }, new byte[] { 2, 2, 2 } }; 316 317 TableName table4 = TableName.valueOf(table.getNameAsString() + "_4"); 318 try { 319 ADMIN.createTable(TableDescriptorBuilder.newBuilder(table4).setColumnFamily(cfd).build(), 320 splitKeys); 321 assertTrue("Should not be able to create this table because of " + "duplicate split keys", 322 false); 323 } catch (IllegalArgumentException iae) { 324 // Expected 325 } 326 } 327 328 @Test 329 public void testCreateTableWithOnlyEmptyStartRow() throws IOException { 330 final byte[] tableName = Bytes.toBytes(name.getMethodName()); 331 byte[][] splitKeys = new byte[1][]; 332 splitKeys[0] = HConstants.EMPTY_BYTE_ARRAY; 333 TableDescriptor desc = TableDescriptorBuilder.newBuilder(TableName.valueOf(tableName)) 334 .setColumnFamily(ColumnFamilyDescriptorBuilder.of("col")).build(); 335 try { 336 ADMIN.createTable(desc, splitKeys); 337 fail("Test case should fail as empty split key is passed."); 338 } catch (IllegalArgumentException e) { 339 } 340 } 341 342 @Test 343 public void testCreateTableWithEmptyRowInTheSplitKeys() throws IOException { 344 final byte[] tableName = Bytes.toBytes(name.getMethodName()); 345 byte[][] splitKeys = new byte[3][]; 346 splitKeys[0] = Bytes.toBytes("region1"); 347 splitKeys[1] = HConstants.EMPTY_BYTE_ARRAY; 348 splitKeys[2] = Bytes.toBytes("region2"); 349 TableDescriptor desc = TableDescriptorBuilder.newBuilder(TableName.valueOf(tableName)) 350 .setColumnFamily(ColumnFamilyDescriptorBuilder.of("col")).build(); 351 try { 352 ADMIN.createTable(desc, splitKeys); 353 fail("Test case should fail as empty split key is passed."); 354 } catch (IllegalArgumentException e) { 355 LOG.info("Expected ", e); 356 } 357 } 358 359 private void verifyRoundRobinDistribution(RegionLocator regionLocator, int expectedRegions) 360 throws IOException { 361 int numRS = TEST_UTIL.getMiniHBaseCluster().getNumLiveRegionServers(); 362 List<HRegionLocation> regions = regionLocator.getAllRegionLocations(); 363 Map<ServerName, List<RegionInfo>> server2Regions = new HashMap<>(); 364 for (HRegionLocation loc : regions) { 365 ServerName server = loc.getServerName(); 366 List<RegionInfo> regs = server2Regions.get(server); 367 if (regs == null) { 368 regs = new ArrayList<>(); 369 server2Regions.put(server, regs); 370 } 371 regs.add(loc.getRegion()); 372 } 373 float average = (float) expectedRegions / numRS; 374 int min = (int) Math.floor(average); 375 int max = (int) Math.ceil(average); 376 for (List<RegionInfo> regionList : server2Regions.values()) { 377 assertTrue("numRS=" + numRS + ", min=" + min + ", max=" + max + ", size=" + regionList.size(), 378 regionList.size() == min || regionList.size() == max); 379 } 380 } 381 382 @Test 383 public void testCloneTableSchema() throws Exception { 384 final TableName tableName = TableName.valueOf(name.getMethodName()); 385 final TableName newTableName = TableName.valueOf(tableName.getNameAsString() + "_new"); 386 testCloneTableSchema(tableName, newTableName, false); 387 } 388 389 @Test 390 public void testCloneTableSchemaPreservingSplits() throws Exception { 391 final TableName tableName = TableName.valueOf(name.getMethodName()); 392 final TableName newTableName = TableName.valueOf(tableName.getNameAsString() + "_new"); 393 testCloneTableSchema(tableName, newTableName, true); 394 } 395 396 private void testCloneTableSchema(final TableName tableName, final TableName newTableName, 397 boolean preserveSplits) throws Exception { 398 byte[] FAMILY_0 = Bytes.toBytes("cf0"); 399 byte[] FAMILY_1 = Bytes.toBytes("cf1"); 400 byte[][] splitKeys = new byte[2][]; 401 splitKeys[0] = Bytes.toBytes(4); 402 splitKeys[1] = Bytes.toBytes(8); 403 int NUM_FAMILYS = 2; 404 int NUM_REGIONS = 3; 405 int BLOCK_SIZE = 1024; 406 int TTL = 86400; 407 boolean BLOCK_CACHE = false; 408 409 // Create the table 410 TableDescriptor tableDesc = TableDescriptorBuilder.newBuilder(tableName) 411 .setColumnFamily(ColumnFamilyDescriptorBuilder.of(FAMILY_0)) 412 .setColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder(FAMILY_1).setBlocksize(BLOCK_SIZE) 413 .setBlockCacheEnabled(BLOCK_CACHE).setTimeToLive(TTL).build()) 414 .build(); 415 ADMIN.createTable(tableDesc, splitKeys); 416 417 assertEquals(NUM_REGIONS, TEST_UTIL.getHBaseCluster().getRegions(tableName).size()); 418 assertTrue("Table should be created with splitKyes + 1 rows in META", 419 ADMIN.isTableAvailable(tableName)); 420 421 // clone & Verify 422 ADMIN.cloneTableSchema(tableName, newTableName, preserveSplits); 423 TableDescriptor newTableDesc = ADMIN.getDescriptor(newTableName); 424 425 assertEquals(NUM_FAMILYS, newTableDesc.getColumnFamilyCount()); 426 assertEquals(BLOCK_SIZE, newTableDesc.getColumnFamily(FAMILY_1).getBlocksize()); 427 assertEquals(BLOCK_CACHE, newTableDesc.getColumnFamily(FAMILY_1).isBlockCacheEnabled()); 428 assertEquals(TTL, newTableDesc.getColumnFamily(FAMILY_1).getTimeToLive()); 429 // HBASE-26246 introduced persist of store file tracker into table descriptor 430 tableDesc = TableDescriptorBuilder.newBuilder(tableDesc).setValue(TRACKER_IMPL, 431 StoreFileTrackerFactory.getStoreFileTrackerName(TEST_UTIL.getConfiguration())).build(); 432 TEST_UTIL.verifyTableDescriptorIgnoreTableName(tableDesc, newTableDesc); 433 434 if (preserveSplits) { 435 assertEquals(NUM_REGIONS, TEST_UTIL.getHBaseCluster().getRegions(newTableName).size()); 436 assertTrue("New table should be created with splitKyes + 1 rows in META", 437 ADMIN.isTableAvailable(newTableName)); 438 } else { 439 assertEquals(1, TEST_UTIL.getHBaseCluster().getRegions(newTableName).size()); 440 } 441 } 442 443 @Test 444 public void testCloneTableSchemaWithNonExistentSourceTable() throws Exception { 445 final TableName tableName = TableName.valueOf(name.getMethodName()); 446 final TableName newTableName = TableName.valueOf(tableName.getNameAsString() + "_new"); 447 // test for non-existent source table 448 try { 449 ADMIN.cloneTableSchema(tableName, newTableName, false); 450 fail("Should have failed to create a new table by cloning non-existent source table."); 451 } catch (TableNotFoundException ex) { 452 // expected 453 } 454 } 455 456 @Test 457 public void testCloneTableSchemaWithExistentDestinationTable() throws Exception { 458 final TableName tableName = TableName.valueOf(name.getMethodName()); 459 final TableName newTableName = TableName.valueOf(tableName.getNameAsString() + "_new"); 460 byte[] FAMILY_0 = Bytes.toBytes("cf0"); 461 TEST_UTIL.createTable(tableName, FAMILY_0); 462 TEST_UTIL.createTable(newTableName, FAMILY_0); 463 // test for existent destination table 464 try { 465 ADMIN.cloneTableSchema(tableName, newTableName, false); 466 fail("Should have failed to create a existent table."); 467 } catch (TableExistsException ex) { 468 // expected 469 } 470 } 471 472 @Test 473 public void testModifyTableOnTableWithRegionReplicas() throws Exception { 474 TableName tableName = TableName.valueOf(name.getMethodName()); 475 TableDescriptor desc = TableDescriptorBuilder.newBuilder(tableName) 476 .setColumnFamily(ColumnFamilyDescriptorBuilder.of(Bytes.toBytes("cf"))) 477 .setRegionReplication(5).build(); 478 479 ADMIN.createTable(desc); 480 481 int maxFileSize = 10000000; 482 TableDescriptor newDesc = 483 TableDescriptorBuilder.newBuilder(desc).setMaxFileSize(maxFileSize).build(); 484 485 ADMIN.modifyTable(newDesc); 486 TableDescriptor newTableDesc = ADMIN.getDescriptor(tableName); 487 assertEquals(maxFileSize, newTableDesc.getMaxFileSize()); 488 } 489 490 /** 491 * Verify schema modification takes. 492 */ 493 @Test 494 public void testOnlineChangeTableSchema() throws IOException, InterruptedException { 495 final TableName tableName = TableName.valueOf(name.getMethodName()); 496 List<TableDescriptor> tables = ADMIN.listTableDescriptors(); 497 int numTables = tables.size(); 498 TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY).close(); 499 tables = ADMIN.listTableDescriptors(); 500 assertEquals(numTables + 1, tables.size()); 501 // FIRST, do htabledescriptor changes. 502 TableDescriptor htd = ADMIN.getDescriptor(tableName); 503 // Make a copy and assert copy is good. 504 TableDescriptor copy = TableDescriptorBuilder.newBuilder(htd).build(); 505 assertEquals(htd, copy); 506 String key = "anyoldkey"; 507 assertNull(htd.getValue(key)); 508 // Now amend the copy. Introduce differences. 509 long newFlushSize = htd.getMemStoreFlushSize() / 2; 510 if (newFlushSize <= 0) { 511 newFlushSize = TableDescriptorBuilder.DEFAULT_MEMSTORE_FLUSH_SIZE / 2; 512 } 513 copy = TableDescriptorBuilder.newBuilder(copy).setMemStoreFlushSize(newFlushSize) 514 .setValue(key, key).build(); 515 ADMIN.modifyTable(copy); 516 TableDescriptor modifiedHtd = ADMIN.getDescriptor(tableName); 517 assertNotEquals(htd, modifiedHtd); 518 assertEquals(copy, modifiedHtd); 519 assertEquals(newFlushSize, modifiedHtd.getMemStoreFlushSize()); 520 assertEquals(key, modifiedHtd.getValue(key)); 521 522 // Now work on column family changes. 523 int countOfFamilies = modifiedHtd.getColumnFamilyCount(); 524 assertTrue(countOfFamilies > 0); 525 ColumnFamilyDescriptor hcd = modifiedHtd.getColumnFamilies()[0]; 526 int maxversions = hcd.getMaxVersions(); 527 int newMaxVersions = maxversions + 1; 528 hcd = ColumnFamilyDescriptorBuilder.newBuilder(hcd).setMaxVersions(newMaxVersions).build(); 529 byte[] hcdName = hcd.getName(); 530 ADMIN.modifyColumnFamily(tableName, hcd); 531 modifiedHtd = ADMIN.getDescriptor(tableName); 532 ColumnFamilyDescriptor modifiedHcd = modifiedHtd.getColumnFamily(hcdName); 533 assertEquals(newMaxVersions, modifiedHcd.getMaxVersions()); 534 535 // Try adding a column 536 assertFalse(ADMIN.isTableDisabled(tableName)); 537 String xtracolName = "xtracol"; 538 ColumnFamilyDescriptor xtracol = ColumnFamilyDescriptorBuilder 539 .newBuilder(Bytes.toBytes(xtracolName)).setValue(xtracolName, xtracolName).build(); 540 ADMIN.addColumnFamily(tableName, xtracol); 541 modifiedHtd = ADMIN.getDescriptor(tableName); 542 hcd = modifiedHtd.getColumnFamily(xtracol.getName()); 543 assertNotNull(hcd); 544 assertEquals(xtracolName, Bytes.toString(hcd.getValue(Bytes.toBytes(xtracolName)))); 545 546 // Delete the just-added column. 547 ADMIN.deleteColumnFamily(tableName, xtracol.getName()); 548 modifiedHtd = ADMIN.getDescriptor(tableName); 549 hcd = modifiedHtd.getColumnFamily(xtracol.getName()); 550 assertNull(hcd); 551 552 // Delete the table 553 ADMIN.disableTable(tableName); 554 ADMIN.deleteTable(tableName); 555 ADMIN.listTableDescriptors(); 556 assertFalse(ADMIN.tableExists(tableName)); 557 } 558 559 @Test 560 public void testUnknownServers() throws Exception { 561 TableName table = TableName.valueOf(name.getMethodName()); 562 ColumnFamilyDescriptor cfd = ColumnFamilyDescriptorBuilder.of(HConstants.CATALOG_FAMILY); 563 ADMIN.createTable(TableDescriptorBuilder.newBuilder(table).setColumnFamily(cfd).build()); 564 final List<RegionInfo> regions = ADMIN.getRegions(table); 565 HMaster master = TEST_UTIL.getHBaseCluster().getMaster(); 566 final AssignmentManager am = master.getAssignmentManager(); 567 RegionStateNode rsNode = am.getRegionStates().getRegionStateNode(regions.get(0)); 568 ServerName regionLocation = rsNode.getRegionLocation(); 569 rsNode.setRegionLocation(ServerName.valueOf("dummyserver", 1234, System.currentTimeMillis())); 570 try { 571 assertTrue(ADMIN.listUnknownServers().get(0).getHostname().equals("dummyserver")); 572 } finally { 573 rsNode.setRegionLocation(regionLocation); 574 } 575 assertTrue(ADMIN.listUnknownServers().isEmpty()); 576 } 577}