1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.client;
21
22
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertFalse;
25 import static org.junit.Assert.assertTrue;
26
27 import java.io.IOException;
28 import java.util.ArrayList;
29 import java.util.HashMap;
30 import java.util.Iterator;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.concurrent.atomic.AtomicBoolean;
34 import java.util.concurrent.atomic.AtomicInteger;
35
36 import org.apache.commons.logging.Log;
37 import org.apache.commons.logging.LogFactory;
38 import org.apache.hadoop.hbase.HBaseTestingUtility;
39 import org.apache.hadoop.hbase.HColumnDescriptor;
40 import org.apache.hadoop.hbase.HConstants;
41 import org.apache.hadoop.hbase.HRegionInfo;
42 import org.apache.hadoop.hbase.HServerAddress;
43 import org.apache.hadoop.hbase.HTableDescriptor;
44 import org.apache.hadoop.hbase.NotServingRegionException;
45 import org.apache.hadoop.hbase.TableExistsException;
46 import org.apache.hadoop.hbase.TableNotDisabledException;
47 import org.apache.hadoop.hbase.TableNotFoundException;
48 import org.apache.hadoop.hbase.executor.EventHandler;
49 import org.apache.hadoop.hbase.executor.ExecutorService;
50 import org.apache.hadoop.hbase.executor.EventHandler.EventType;
51 import org.apache.hadoop.hbase.master.AssignmentManager;
52 import org.apache.hadoop.hbase.master.MasterServices;
53 import org.apache.hadoop.hbase.util.Bytes;
54 import org.junit.AfterClass;
55 import org.junit.Before;
56 import org.junit.BeforeClass;
57 import org.junit.Test;
58
59
60
61
62
63
64
65 public class TestAdmin {
66 final Log LOG = LogFactory.getLog(getClass());
67 private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
68 private HBaseAdmin admin;
69
70 @BeforeClass
71 public static void setUpBeforeClass() throws Exception {
72 TEST_UTIL.getConfiguration().setInt("hbase.regionserver.msginterval", 100);
73 TEST_UTIL.getConfiguration().setInt("hbase.client.pause", 250);
74 TEST_UTIL.getConfiguration().setInt("hbase.client.retries.number", 6);
75 TEST_UTIL.startMiniCluster(3);
76 }
77
78 @AfterClass
79 public static void tearDownAfterClass() throws Exception {
80 TEST_UTIL.shutdownMiniCluster();
81 }
82
83 @Before
84 public void setUp() throws Exception {
85 this.admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
86 }
87
88 @Test
89 public void testDisableAndEnableTable() throws IOException {
90 final byte [] row = Bytes.toBytes("row");
91 final byte [] qualifier = Bytes.toBytes("qualifier");
92 final byte [] value = Bytes.toBytes("value");
93 final byte [] table = Bytes.toBytes("testDisableAndEnableTable");
94 HTable ht = TEST_UTIL.createTable(table, HConstants.CATALOG_FAMILY);
95 Put put = new Put(row);
96 put.add(HConstants.CATALOG_FAMILY, qualifier, value);
97 ht.put(put);
98 Get get = new Get(row);
99 get.addColumn(HConstants.CATALOG_FAMILY, qualifier);
100 ht.get(get);
101
102 this.admin.disableTable(table);
103
104
105 get = new Get(row);
106 get.addColumn(HConstants.CATALOG_FAMILY, qualifier);
107 boolean ok = false;
108 try {
109 ht.get(get);
110 } catch (NotServingRegionException e) {
111 ok = true;
112 } catch (RetriesExhaustedException e) {
113 ok = true;
114 }
115 assertTrue(ok);
116 this.admin.enableTable(table);
117
118
119 try {
120 ht.get(get);
121 } catch (RetriesExhaustedException e) {
122 ok = false;
123 }
124 assertTrue(ok);
125 }
126
127 @Test
128 public void testCreateTable() throws IOException {
129 HTableDescriptor [] tables = admin.listTables();
130 int numTables = tables.length;
131 TEST_UTIL.createTable(Bytes.toBytes("testCreateTable"),
132 HConstants.CATALOG_FAMILY);
133 tables = this.admin.listTables();
134 assertEquals(numTables + 1, tables.length);
135 }
136
137 @Test
138 public void testGetTableDescriptor() throws IOException {
139 HColumnDescriptor fam1 = new HColumnDescriptor("fam1");
140 HColumnDescriptor fam2 = new HColumnDescriptor("fam2");
141 HColumnDescriptor fam3 = new HColumnDescriptor("fam3");
142 HTableDescriptor htd = new HTableDescriptor("myTestTable");
143 htd.addFamily(fam1);
144 htd.addFamily(fam2);
145 htd.addFamily(fam3);
146 this.admin.createTable(htd);
147 HTable table = new HTable(TEST_UTIL.getConfiguration(), "myTestTable");
148 HTableDescriptor confirmedHtd = table.getTableDescriptor();
149 assertEquals(htd.compareTo(confirmedHtd), 0);
150 }
151
152
153
154
155
156 @Test
157 public void testChangeTableSchema() throws IOException {
158 final byte [] tableName = Bytes.toBytes("changeTableSchema");
159 HTableDescriptor [] tables = admin.listTables();
160 int numTables = tables.length;
161 TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY);
162 tables = this.admin.listTables();
163 assertEquals(numTables + 1, tables.length);
164
165
166 HTableDescriptor htd = this.admin.getTableDescriptor(tableName);
167
168 HTableDescriptor copy = new HTableDescriptor(htd);
169 assertTrue(htd.equals(copy));
170
171 long newFlushSize = htd.getMemStoreFlushSize() / 2;
172 copy.setMemStoreFlushSize(newFlushSize);
173 final String key = "anyoldkey";
174 assertTrue(htd.getValue(key) == null);
175 copy.setValue(key, key);
176 boolean expectedException = false;
177 try {
178 this.admin.modifyTable(tableName, copy);
179 } catch (TableNotDisabledException re) {
180 expectedException = true;
181 }
182 assertTrue(expectedException);
183 this.admin.disableTable(tableName);
184 assertTrue(this.admin.isTableDisabled(tableName));
185 modifyTable(tableName, copy);
186 HTableDescriptor modifiedHtd = this.admin.getTableDescriptor(tableName);
187
188 assertFalse(htd.equals(modifiedHtd));
189 assertTrue(copy.equals(modifiedHtd));
190 assertEquals(newFlushSize, modifiedHtd.getMemStoreFlushSize());
191 assertEquals(key, modifiedHtd.getValue(key));
192
193
194 this.admin.enableTable(tableName);
195 assertFalse(this.admin.isTableDisabled(tableName));
196
197
198 int countOfFamilies = modifiedHtd.getFamilies().size();
199 assertTrue(countOfFamilies > 0);
200 HColumnDescriptor hcd = modifiedHtd.getFamilies().iterator().next();
201 int maxversions = hcd.getMaxVersions();
202 final int newMaxVersions = maxversions + 1;
203 hcd.setMaxVersions(newMaxVersions);
204 final byte [] hcdName = hcd.getName();
205 expectedException = false;
206 try {
207 this.admin.modifyColumn(tableName, hcd);
208 } catch (TableNotDisabledException re) {
209 expectedException = true;
210 }
211 assertTrue(expectedException);
212 this.admin.disableTable(tableName);
213 assertTrue(this.admin.isTableDisabled(tableName));
214
215 this.admin.modifyColumn(tableName, hcd);
216 modifiedHtd = this.admin.getTableDescriptor(tableName);
217 HColumnDescriptor modifiedHcd = modifiedHtd.getFamily(hcdName);
218 assertEquals(newMaxVersions, modifiedHcd.getMaxVersions());
219
220
221
222 this.admin.enableTable(tableName);
223 assertFalse(this.admin.isTableDisabled(tableName));
224 final String xtracolName = "xtracol";
225 HColumnDescriptor xtracol = new HColumnDescriptor(xtracolName);
226 xtracol.setValue(xtracolName, xtracolName);
227 try {
228 this.admin.addColumn(tableName, xtracol);
229 } catch (TableNotDisabledException re) {
230 expectedException = true;
231 }
232 assertTrue(expectedException);
233 this.admin.disableTable(tableName);
234 assertTrue(this.admin.isTableDisabled(tableName));
235 this.admin.addColumn(tableName, xtracol);
236 modifiedHtd = this.admin.getTableDescriptor(tableName);
237 hcd = modifiedHtd.getFamily(xtracol.getName());
238 assertTrue(hcd != null);
239 assertTrue(hcd.getValue(xtracolName).equals(xtracolName));
240
241
242 this.admin.deleteColumn(tableName, xtracol.getName());
243 modifiedHtd = this.admin.getTableDescriptor(tableName);
244 hcd = modifiedHtd.getFamily(xtracol.getName());
245 assertTrue(hcd == null);
246
247
248 this.admin.deleteTable(tableName);
249 this.admin.listTables();
250 assertFalse(this.admin.tableExists(tableName));
251 }
252
253
254
255
256
257
258
259 private void modifyTable(final byte [] tableName, final HTableDescriptor htd)
260 throws IOException {
261 MasterServices services = TEST_UTIL.getMiniHBaseCluster().getMaster();
262 ExecutorService executor = services.getExecutorService();
263 AtomicBoolean done = new AtomicBoolean(false);
264 executor.registerListener(EventType.C_M_MODIFY_TABLE, new DoneListener(done));
265 this.admin.modifyTable(tableName, htd);
266 while (!done.get()) {
267 synchronized (done) {
268 try {
269 done.wait(1000);
270 } catch (InterruptedException e) {
271 e.printStackTrace();
272 }
273 }
274 }
275 executor.unregisterListener(EventType.C_M_MODIFY_TABLE);
276 }
277
278
279
280
281 static class DoneListener implements EventHandler.EventHandlerListener {
282 private final AtomicBoolean done;
283
284 DoneListener(final AtomicBoolean done) {
285 super();
286 this.done = done;
287 }
288
289 @Override
290 public void afterProcess(EventHandler event) {
291 this.done.set(true);
292 synchronized (this.done) {
293
294 this.done.notifyAll();
295 }
296 }
297
298 @Override
299 public void beforeProcess(EventHandler event) {
300
301 }
302 }
303
304 protected void verifyRoundRobinDistribution(HTable ht, int expectedRegions) throws IOException {
305 MasterServices services = TEST_UTIL.getMiniHBaseCluster().getMaster();
306 AssignmentManager am = services.getAssignmentManager();
307 Map<HRegionInfo,HServerAddress> regions = ht.getRegionsInfo();
308 for (HRegionInfo regionInfo : regions.keySet()) {
309 try {
310 am.waitForAssignment(regionInfo);
311 } catch (InterruptedException e) {
312 LOG.info("Interrupted waiting for region to be assigned during " +
313 "create table call", e);
314 Thread.currentThread().interrupt();
315 return;
316 }
317 }
318 int numRS = ht.getCurrentNrHRS();
319 regions = ht.getRegionsInfo();
320 Map<HServerAddress, List<HRegionInfo>> server2Regions = new HashMap<HServerAddress, List<HRegionInfo>>();
321 for (Map.Entry<HRegionInfo,HServerAddress> entry : regions.entrySet()) {
322 HServerAddress server = entry.getValue();
323 List<HRegionInfo> regs = server2Regions.get(server);
324 if (regs == null) {
325 regs = new ArrayList<HRegionInfo>();
326 server2Regions.put(server, regs);
327 }
328 regs.add(entry.getKey());
329 }
330 float average = (float) expectedRegions/numRS;
331 int min = (int)Math.floor(average);
332 int max = (int)Math.ceil(average);
333 for (List<HRegionInfo> regionList : server2Regions.values()) {
334 assertTrue(regionList.size() == min || regionList.size() == max);
335 }
336 }
337
338 @Test
339 public void testCreateTableWithRegions() throws IOException, InterruptedException {
340
341 byte[] tableName = Bytes.toBytes("testCreateTableWithRegions");
342
343 byte [][] splitKeys = {
344 new byte [] { 1, 1, 1 },
345 new byte [] { 2, 2, 2 },
346 new byte [] { 3, 3, 3 },
347 new byte [] { 4, 4, 4 },
348 new byte [] { 5, 5, 5 },
349 new byte [] { 6, 6, 6 },
350 new byte [] { 7, 7, 7 },
351 new byte [] { 8, 8, 8 },
352 new byte [] { 9, 9, 9 },
353 };
354 int expectedRegions = splitKeys.length + 1;
355
356 HTableDescriptor desc = new HTableDescriptor(tableName);
357 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
358 admin.createTable(desc, splitKeys);
359
360 HTable ht = new HTable(TEST_UTIL.getConfiguration(), tableName);
361 Map<HRegionInfo,HServerAddress> regions = ht.getRegionsInfo();
362 assertEquals("Tried to create " + expectedRegions + " regions " +
363 "but only found " + regions.size(),
364 expectedRegions, regions.size());
365 System.err.println("Found " + regions.size() + " regions");
366
367 Iterator<HRegionInfo> hris = regions.keySet().iterator();
368 HRegionInfo hri = hris.next();
369 assertTrue(hri.getStartKey() == null || hri.getStartKey().length == 0);
370 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[0]));
371 hri = hris.next();
372 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[0]));
373 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[1]));
374 hri = hris.next();
375 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[1]));
376 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[2]));
377 hri = hris.next();
378 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[2]));
379 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[3]));
380 hri = hris.next();
381 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[3]));
382 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[4]));
383 hri = hris.next();
384 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[4]));
385 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[5]));
386 hri = hris.next();
387 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[5]));
388 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[6]));
389 hri = hris.next();
390 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[6]));
391 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[7]));
392 hri = hris.next();
393 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[7]));
394 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[8]));
395 hri = hris.next();
396 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[8]));
397 assertTrue(hri.getEndKey() == null || hri.getEndKey().length == 0);
398
399 verifyRoundRobinDistribution(ht, expectedRegions);
400
401
402
403
404 byte [] startKey = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
405 byte [] endKey = { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 };
406
407
408
409
410 expectedRegions = 10;
411
412 byte [] TABLE_2 = Bytes.add(tableName, Bytes.toBytes("_2"));
413
414 desc = new HTableDescriptor(TABLE_2);
415 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
416 admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
417 admin.createTable(desc, startKey, endKey, expectedRegions);
418
419 ht = new HTable(TEST_UTIL.getConfiguration(), TABLE_2);
420 regions = ht.getRegionsInfo();
421 assertEquals("Tried to create " + expectedRegions + " regions " +
422 "but only found " + regions.size(),
423 expectedRegions, regions.size());
424 System.err.println("Found " + regions.size() + " regions");
425
426 hris = regions.keySet().iterator();
427 hri = hris.next();
428 assertTrue(hri.getStartKey() == null || hri.getStartKey().length == 0);
429 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {1,1,1,1,1,1,1,1,1,1}));
430 hri = hris.next();
431 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {1,1,1,1,1,1,1,1,1,1}));
432 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {2,2,2,2,2,2,2,2,2,2}));
433 hri = hris.next();
434 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {2,2,2,2,2,2,2,2,2,2}));
435 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {3,3,3,3,3,3,3,3,3,3}));
436 hri = hris.next();
437 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {3,3,3,3,3,3,3,3,3,3}));
438 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {4,4,4,4,4,4,4,4,4,4}));
439 hri = hris.next();
440 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {4,4,4,4,4,4,4,4,4,4}));
441 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {5,5,5,5,5,5,5,5,5,5}));
442 hri = hris.next();
443 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {5,5,5,5,5,5,5,5,5,5}));
444 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {6,6,6,6,6,6,6,6,6,6}));
445 hri = hris.next();
446 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {6,6,6,6,6,6,6,6,6,6}));
447 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {7,7,7,7,7,7,7,7,7,7}));
448 hri = hris.next();
449 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {7,7,7,7,7,7,7,7,7,7}));
450 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {8,8,8,8,8,8,8,8,8,8}));
451 hri = hris.next();
452 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {8,8,8,8,8,8,8,8,8,8}));
453 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {9,9,9,9,9,9,9,9,9,9}));
454 hri = hris.next();
455 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {9,9,9,9,9,9,9,9,9,9}));
456 assertTrue(hri.getEndKey() == null || hri.getEndKey().length == 0);
457
458 verifyRoundRobinDistribution(ht, expectedRegions);
459
460
461
462 startKey = new byte [] { 0, 0, 0, 0, 0, 0 };
463 endKey = new byte [] { 1, 0, 0, 0, 0, 0 };
464
465 expectedRegions = 5;
466
467 byte [] TABLE_3 = Bytes.add(tableName, Bytes.toBytes("_3"));
468
469 desc = new HTableDescriptor(TABLE_3);
470 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
471 admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
472 admin.createTable(desc, startKey, endKey, expectedRegions);
473
474 ht = new HTable(TEST_UTIL.getConfiguration(), TABLE_3);
475 regions = ht.getRegionsInfo();
476 assertEquals("Tried to create " + expectedRegions + " regions " +
477 "but only found " + regions.size(),
478 expectedRegions, regions.size());
479 System.err.println("Found " + regions.size() + " regions");
480
481 verifyRoundRobinDistribution(ht, expectedRegions);
482
483
484 splitKeys = new byte [][] {
485 new byte [] { 1, 1, 1 },
486 new byte [] { 2, 2, 2 },
487 new byte [] { 3, 3, 3 },
488 new byte [] { 2, 2, 2 }
489 };
490
491 byte [] TABLE_4 = Bytes.add(tableName, Bytes.toBytes("_4"));
492 desc = new HTableDescriptor(TABLE_4);
493 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
494 admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
495 try {
496 admin.createTable(desc, splitKeys);
497 assertTrue("Should not be able to create this table because of " +
498 "duplicate split keys", false);
499 } catch(IllegalArgumentException iae) {
500
501 }
502 }
503
504 @Test
505 public void testTableExist() throws IOException {
506 final byte [] table = Bytes.toBytes("testTableExist");
507 boolean exist = false;
508 exist = this.admin.tableExists(table);
509 assertEquals(false, exist);
510 TEST_UTIL.createTable(table, HConstants.CATALOG_FAMILY);
511 exist = this.admin.tableExists(table);
512 assertEquals(true, exist);
513 }
514
515
516
517
518
519
520 @Test
521 public void testForceSplit() throws Exception {
522 splitTest(null);
523 splitTest(Bytes.toBytes("pwn"));
524 }
525
526 void splitTest(byte[] splitPoint) throws Exception {
527 byte [] familyName = HConstants.CATALOG_FAMILY;
528 byte [] tableName = Bytes.toBytes("testForceSplit");
529 assertFalse(admin.tableExists(tableName));
530 final HTable table = TEST_UTIL.createTable(tableName, familyName);
531 try {
532 byte[] k = new byte[3];
533 int rowCount = 0;
534 for (byte b1 = 'a'; b1 < 'z'; b1++) {
535 for (byte b2 = 'a'; b2 < 'z'; b2++) {
536 for (byte b3 = 'a'; b3 < 'z'; b3++) {
537 k[0] = b1;
538 k[1] = b2;
539 k[2] = b3;
540 Put put = new Put(k);
541 put.add(familyName, new byte[0], k);
542 table.put(put);
543 rowCount++;
544 }
545 }
546 }
547
548
549 Map<HRegionInfo,HServerAddress> m = table.getRegionsInfo();
550 System.out.println("Initial regions (" + m.size() + "): " + m);
551 assertTrue(m.size() == 1);
552
553
554 Scan scan = new Scan();
555 ResultScanner scanner = table.getScanner(scan);
556 int rows = 0;
557 for(@SuppressWarnings("unused") Result result : scanner) {
558 rows++;
559 }
560 scanner.close();
561 assertEquals(rowCount, rows);
562
563
564 scan = new Scan();
565 scanner = table.getScanner(scan);
566
567 scanner.next();
568
569 final AtomicInteger count = new AtomicInteger(0);
570 Thread t = new Thread("CheckForSplit") {
571 public void run() {
572 for (int i = 0; i < 20; i++) {
573 try {
574 sleep(1000);
575 } catch (InterruptedException e) {
576 continue;
577 }
578
579 Map<HRegionInfo, HServerAddress> regions = null;
580 try {
581 regions = table.getRegionsInfo();
582 } catch (IOException e) {
583 e.printStackTrace();
584 }
585 if (regions == null) continue;
586 count.set(regions.size());
587 if (count.get() >= 2) break;
588 LOG.debug("Cycle waiting on split");
589 }
590 }
591 };
592 t.start();
593
594 this.admin.split(tableName, splitPoint);
595 t.join();
596
597
598 rows = 1;
599 for (@SuppressWarnings("unused") Result result : scanner) {
600 rows++;
601 if (rows > rowCount) {
602 scanner.close();
603 assertTrue("Scanned more than expected (" + rowCount + ")", false);
604 }
605 }
606 scanner.close();
607 assertEquals(rowCount, rows);
608
609 if (splitPoint != null) {
610
611 Map<HRegionInfo, HServerAddress> regions = null;
612 try {
613 regions = table.getRegionsInfo();
614 } catch (IOException e) {
615 e.printStackTrace();
616 }
617 assertEquals(2, regions.size());
618 HRegionInfo[] r = regions.keySet().toArray(new HRegionInfo[0]);
619 assertEquals(Bytes.toString(splitPoint),
620 Bytes.toString(r[0].getEndKey()));
621 assertEquals(Bytes.toString(splitPoint),
622 Bytes.toString(r[1].getStartKey()));
623 LOG.debug("Properly split on " + Bytes.toString(splitPoint));
624 }
625 } finally {
626 TEST_UTIL.deleteTable(tableName);
627 }
628 }
629
630
631
632
633
634 @Test (expected=IllegalArgumentException.class)
635 public void testEmptyHHTableDescriptor() throws IOException {
636 this.admin.createTable(new HTableDescriptor());
637 }
638
639 @Test
640 public void testEnableDisableAddColumnDeleteColumn() throws Exception {
641 byte [] tableName = Bytes.toBytes("testMasterAdmin");
642 TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY);
643 this.admin.disableTable(tableName);
644 try {
645 new HTable(TEST_UTIL.getConfiguration(), tableName);
646 } catch (org.apache.hadoop.hbase.client.RegionOfflineException e) {
647
648 }
649 this.admin.addColumn(tableName, new HColumnDescriptor("col2"));
650 this.admin.enableTable(tableName);
651 try {
652 this.admin.deleteColumn(tableName, Bytes.toBytes("col2"));
653 } catch(TableNotDisabledException e) {
654
655 }
656 this.admin.disableTable(tableName);
657 this.admin.deleteColumn(tableName, Bytes.toBytes("col2"));
658 this.admin.deleteTable(tableName);
659 }
660
661 @Test
662 public void testCreateBadTables() throws IOException {
663 String msg = null;
664 try {
665 this.admin.createTable(HTableDescriptor.ROOT_TABLEDESC);
666 } catch (IllegalArgumentException e) {
667 msg = e.toString();
668 }
669 assertTrue("Unexcepted exception message " + msg, msg != null &&
670 msg.startsWith(IllegalArgumentException.class.getName()) &&
671 msg.contains(HTableDescriptor.ROOT_TABLEDESC.getNameAsString()));
672 msg = null;
673 try {
674 this.admin.createTable(HTableDescriptor.META_TABLEDESC);
675 } catch(IllegalArgumentException e) {
676 msg = e.toString();
677 }
678 assertTrue("Unexcepted exception message " + msg, msg != null &&
679 msg.startsWith(IllegalArgumentException.class.getName()) &&
680 msg.contains(HTableDescriptor.META_TABLEDESC.getNameAsString()));
681
682
683 final HTableDescriptor threadDesc =
684 new HTableDescriptor("threaded_testCreateBadTables");
685 threadDesc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
686 int count = 10;
687 Thread [] threads = new Thread [count];
688 final AtomicInteger successes = new AtomicInteger(0);
689 final AtomicInteger failures = new AtomicInteger(0);
690 final HBaseAdmin localAdmin = this.admin;
691 for (int i = 0; i < count; i++) {
692 threads[i] = new Thread(Integer.toString(i)) {
693 @Override
694 public void run() {
695 try {
696 localAdmin.createTable(threadDesc);
697 successes.incrementAndGet();
698 } catch (TableExistsException e) {
699 failures.incrementAndGet();
700 } catch (IOException e) {
701 throw new RuntimeException("Failed threaded create" + getName(), e);
702 }
703 }
704 };
705 }
706 for (int i = 0; i < count; i++) {
707 threads[i].start();
708 }
709 for (int i = 0; i < count; i++) {
710 while(threads[i].isAlive()) {
711 try {
712 Thread.sleep(1000);
713 } catch (InterruptedException e) {
714
715 }
716 }
717 }
718
719
720 assertEquals(1, successes.get());
721 assertEquals(count - 1, failures.get());
722 }
723
724
725
726
727
728 @Test
729 public void testTableNameClash() throws Exception {
730 String name = "testTableNameClash";
731 admin.createTable(new HTableDescriptor(name + "SOMEUPPERCASE"));
732 admin.createTable(new HTableDescriptor(name));
733
734 new HTable(TEST_UTIL.getConfiguration(), name);
735 }
736
737
738
739
740
741 @Test
742 public void testReadOnlyTable() throws Exception {
743 byte [] name = Bytes.toBytes("testReadOnlyTable");
744 HTable table = TEST_UTIL.createTable(name, HConstants.CATALOG_FAMILY);
745 byte[] value = Bytes.toBytes("somedata");
746
747 Put put = new Put(value);
748 put.add(HConstants.CATALOG_FAMILY, HConstants.CATALOG_FAMILY, value);
749 table.put(put);
750 }
751
752
753
754
755
756
757 @Test
758 public void testTableNames() throws IOException {
759 byte[][] illegalNames = new byte[][] {
760 Bytes.toBytes("-bad"),
761 Bytes.toBytes(".bad"),
762 HConstants.ROOT_TABLE_NAME,
763 HConstants.META_TABLE_NAME
764 };
765 for (int i = 0; i < illegalNames.length; i++) {
766 try {
767 new HTableDescriptor(illegalNames[i]);
768 throw new IOException("Did not detect '" +
769 Bytes.toString(illegalNames[i]) + "' as an illegal user table name");
770 } catch (IllegalArgumentException e) {
771
772 }
773 }
774 byte[] legalName = Bytes.toBytes("g-oo.d");
775 try {
776 new HTableDescriptor(legalName);
777 } catch (IllegalArgumentException e) {
778 throw new IOException("Legal user table name: '" +
779 Bytes.toString(legalName) + "' caused IllegalArgumentException: " +
780 e.getMessage());
781 }
782 }
783
784
785
786
787
788 @Test (expected=TableExistsException.class)
789 public void testTableNotFoundExceptionWithATable() throws IOException {
790 final byte [] name = Bytes.toBytes("testTableNotFoundExceptionWithATable");
791 TEST_UTIL.createTable(name, HConstants.CATALOG_FAMILY);
792 TEST_UTIL.createTable(name, HConstants.CATALOG_FAMILY);
793 }
794
795
796
797
798
799 @Test (expected=TableNotFoundException.class)
800 public void testTableNotFoundExceptionWithoutAnyTables() throws IOException {
801 new HTable(TEST_UTIL.getConfiguration(),
802 "testTableNotFoundExceptionWithoutAnyTables");
803 }
804
805 @Test
806 public void testHundredsOfTable() throws IOException{
807 final int times = 100;
808 HColumnDescriptor fam1 = new HColumnDescriptor("fam1");
809 HColumnDescriptor fam2 = new HColumnDescriptor("fam2");
810 HColumnDescriptor fam3 = new HColumnDescriptor("fam3");
811
812 for(int i = 0; i < times; i++) {
813 HTableDescriptor htd = new HTableDescriptor("table"+i);
814 htd.addFamily(fam1);
815 htd.addFamily(fam2);
816 htd.addFamily(fam3);
817 this.admin.createTable(htd);
818 }
819
820 for(int i = 0; i < times; i++) {
821 String tableName = "table"+i;
822 this.admin.disableTable(tableName);
823 byte [] tableNameBytes = Bytes.toBytes(tableName);
824 assertTrue(this.admin.isTableDisabled(tableNameBytes));
825 this.admin.enableTable(tableName);
826 assertFalse(this.admin.isTableDisabled(tableNameBytes));
827 this.admin.disableTable(tableName);
828 assertTrue(this.admin.isTableDisabled(tableNameBytes));
829 this.admin.deleteTable(tableName);
830 }
831 }
832 }