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.assertTrue;
25 import static org.junit.Assert.fail;
26
27 import java.io.IOException;
28 import java.util.Iterator;
29 import java.util.Map;
30 import java.util.concurrent.atomic.AtomicInteger;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.apache.hadoop.hbase.HBaseTestingUtility;
35 import org.apache.hadoop.hbase.HColumnDescriptor;
36 import org.apache.hadoop.hbase.HConstants;
37 import org.apache.hadoop.hbase.HRegionInfo;
38 import org.apache.hadoop.hbase.HServerAddress;
39 import org.apache.hadoop.hbase.HTableDescriptor;
40 import org.apache.hadoop.hbase.TableExistsException;
41 import org.apache.hadoop.hbase.TableNotDisabledException;
42 import org.apache.hadoop.hbase.TableNotFoundException;
43 import org.apache.hadoop.hbase.util.Bytes;
44 import org.junit.AfterClass;
45 import org.junit.Before;
46 import org.junit.BeforeClass;
47 import org.junit.Test;
48
49
50
51
52
53
54
55 public class TestAdmin {
56 final Log LOG = LogFactory.getLog(getClass());
57 private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
58 private HBaseAdmin admin;
59
60 @BeforeClass
61 public static void setUpBeforeClass() throws Exception {
62 TEST_UTIL.getConfiguration().setInt("hbase.regionserver.msginterval", 100);
63 TEST_UTIL.getConfiguration().setInt("hbase.client.pause", 250);
64 TEST_UTIL.getConfiguration().setInt("hbase.client.retries.number", 6);
65 TEST_UTIL.startMiniCluster(3);
66 }
67
68 @AfterClass
69 public static void tearDownAfterClass() throws Exception {
70 TEST_UTIL.shutdownMiniCluster();
71 }
72
73 @Before
74 public void setUp() throws Exception {
75 this.admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
76 }
77
78 @Test
79 public void testCreateTable() throws IOException {
80 HTableDescriptor [] tables = admin.listTables();
81 int numTables = tables.length;
82 TEST_UTIL.createTable(Bytes.toBytes("testCreateTable"),
83 HConstants.CATALOG_FAMILY);
84 tables = this.admin.listTables();
85 assertEquals(numTables + 1, tables.length);
86 }
87
88 @Test
89 public void testCreateTableWithRegions() throws IOException {
90
91 byte[] tableName = Bytes.toBytes("testCreateTableWithRegions");
92
93 byte [][] splitKeys = {
94 new byte [] { 1, 1, 1 },
95 new byte [] { 2, 2, 2 },
96 new byte [] { 3, 3, 3 },
97 new byte [] { 4, 4, 4 },
98 new byte [] { 5, 5, 5 },
99 new byte [] { 6, 6, 6 },
100 new byte [] { 7, 7, 7 },
101 new byte [] { 8, 8, 8 },
102 new byte [] { 9, 9, 9 },
103 };
104 int expectedRegions = splitKeys.length + 1;
105
106 HTableDescriptor desc = new HTableDescriptor(tableName);
107 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
108 admin.createTable(desc, splitKeys);
109
110 HTable ht = new HTable(TEST_UTIL.getConfiguration(), tableName);
111 Map<HRegionInfo,HServerAddress> regions = ht.getRegionsInfo();
112 assertEquals("Tried to create " + expectedRegions + " regions " +
113 "but only found " + regions.size(),
114 expectedRegions, regions.size());
115 System.err.println("Found " + regions.size() + " regions");
116
117 Iterator<HRegionInfo> hris = regions.keySet().iterator();
118 HRegionInfo hri = hris.next();
119 assertTrue(hri.getStartKey() == null || hri.getStartKey().length == 0);
120 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[0]));
121 hri = hris.next();
122 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[0]));
123 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[1]));
124 hri = hris.next();
125 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[1]));
126 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[2]));
127 hri = hris.next();
128 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[2]));
129 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[3]));
130 hri = hris.next();
131 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[3]));
132 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[4]));
133 hri = hris.next();
134 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[4]));
135 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[5]));
136 hri = hris.next();
137 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[5]));
138 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[6]));
139 hri = hris.next();
140 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[6]));
141 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[7]));
142 hri = hris.next();
143 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[7]));
144 assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[8]));
145 hri = hris.next();
146 assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[8]));
147 assertTrue(hri.getEndKey() == null || hri.getEndKey().length == 0);
148
149
150
151
152 byte [] startKey = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
153 byte [] endKey = { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 };
154
155
156
157
158 expectedRegions = 10;
159
160 byte [] TABLE_2 = Bytes.add(tableName, Bytes.toBytes("_2"));
161
162 desc = new HTableDescriptor(TABLE_2);
163 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
164 admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
165 admin.createTable(desc, startKey, endKey, expectedRegions);
166
167 ht = new HTable(TEST_UTIL.getConfiguration(), TABLE_2);
168 regions = ht.getRegionsInfo();
169 assertEquals("Tried to create " + expectedRegions + " regions " +
170 "but only found " + regions.size(),
171 expectedRegions, regions.size());
172 System.err.println("Found " + regions.size() + " regions");
173
174 hris = regions.keySet().iterator();
175 hri = hris.next();
176 assertTrue(hri.getStartKey() == null || hri.getStartKey().length == 0);
177 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {1,1,1,1,1,1,1,1,1,1}));
178 hri = hris.next();
179 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {1,1,1,1,1,1,1,1,1,1}));
180 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {2,2,2,2,2,2,2,2,2,2}));
181 hri = hris.next();
182 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {2,2,2,2,2,2,2,2,2,2}));
183 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {3,3,3,3,3,3,3,3,3,3}));
184 hri = hris.next();
185 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {3,3,3,3,3,3,3,3,3,3}));
186 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {4,4,4,4,4,4,4,4,4,4}));
187 hri = hris.next();
188 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {4,4,4,4,4,4,4,4,4,4}));
189 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {5,5,5,5,5,5,5,5,5,5}));
190 hri = hris.next();
191 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {5,5,5,5,5,5,5,5,5,5}));
192 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {6,6,6,6,6,6,6,6,6,6}));
193 hri = hris.next();
194 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {6,6,6,6,6,6,6,6,6,6}));
195 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {7,7,7,7,7,7,7,7,7,7}));
196 hri = hris.next();
197 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {7,7,7,7,7,7,7,7,7,7}));
198 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {8,8,8,8,8,8,8,8,8,8}));
199 hri = hris.next();
200 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {8,8,8,8,8,8,8,8,8,8}));
201 assertTrue(Bytes.equals(hri.getEndKey(), new byte [] {9,9,9,9,9,9,9,9,9,9}));
202 hri = hris.next();
203 assertTrue(Bytes.equals(hri.getStartKey(), new byte [] {9,9,9,9,9,9,9,9,9,9}));
204 assertTrue(hri.getEndKey() == null || hri.getEndKey().length == 0);
205
206
207
208 startKey = new byte [] { 0, 0, 0, 0, 0, 0 };
209 endKey = new byte [] { 1, 0, 0, 0, 0, 0 };
210
211 expectedRegions = 5;
212
213 byte [] TABLE_3 = Bytes.add(tableName, Bytes.toBytes("_3"));
214
215 desc = new HTableDescriptor(TABLE_3);
216 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
217 admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
218 admin.createTable(desc, startKey, endKey, expectedRegions);
219
220 ht = new HTable(TEST_UTIL.getConfiguration(), TABLE_3);
221 regions = ht.getRegionsInfo();
222 assertEquals("Tried to create " + expectedRegions + " regions " +
223 "but only found " + regions.size(),
224 expectedRegions, regions.size());
225 System.err.println("Found " + regions.size() + " regions");
226
227
228 splitKeys = new byte [][] {
229 new byte [] { 1, 1, 1 },
230 new byte [] { 2, 2, 2 },
231 new byte [] { 3, 3, 3 },
232 new byte [] { 2, 2, 2 }
233 };
234
235 byte [] TABLE_4 = Bytes.add(tableName, Bytes.toBytes("_4"));
236 desc = new HTableDescriptor(TABLE_4);
237 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
238 admin = new HBaseAdmin(TEST_UTIL.getConfiguration());
239 try {
240 admin.createTable(desc, splitKeys);
241 assertTrue("Should not be able to create this table because of " +
242 "duplicate split keys", false);
243 } catch(IllegalArgumentException iae) {
244
245 }
246 }
247
248 @Test
249 public void testDisableAndEnableTable() throws IOException {
250 final byte [] row = Bytes.toBytes("row");
251 final byte [] qualifier = Bytes.toBytes("qualifier");
252 final byte [] value = Bytes.toBytes("value");
253 final byte [] table = Bytes.toBytes("testDisableAndEnableTable");
254 HTable ht = TEST_UTIL.createTable(table, HConstants.CATALOG_FAMILY);
255 Put put = new Put(row);
256 put.add(HConstants.CATALOG_FAMILY, qualifier, value);
257 ht.put(put);
258
259 this.admin.disableTable(table);
260
261
262 Get get = new Get(row);
263 get.addColumn(HConstants.CATALOG_FAMILY, qualifier);
264 boolean ok = false;
265 try {
266 ht.get(get);
267 } catch (RetriesExhaustedException e) {
268 ok = true;
269 }
270 assertEquals(true, ok);
271 this.admin.enableTable(table);
272
273
274 try {
275 ht.get(get);
276 } catch (RetriesExhaustedException e) {
277 ok = false;
278 }
279 assertEquals(true, ok);
280 }
281
282 @Test
283 public void testTableExist() throws IOException {
284 final byte [] table = Bytes.toBytes("testTableExist");
285 boolean exist = false;
286 exist = this.admin.tableExists(table);
287 assertEquals(false, exist);
288 TEST_UTIL.createTable(table, HConstants.CATALOG_FAMILY);
289 exist = this.admin.tableExists(table);
290 assertEquals(true, exist);
291 }
292
293
294
295
296
297
298 @Test
299 public void testForceSplit() throws Exception {
300 byte [] familyName = HConstants.CATALOG_FAMILY;
301 byte [] tableName = Bytes.toBytes("testForceSplit");
302 final HTable table = TEST_UTIL.createTable(tableName, familyName);
303 byte[] k = new byte[3];
304 int rowCount = 0;
305 for (byte b1 = 'a'; b1 < 'z'; b1++) {
306 for (byte b2 = 'a'; b2 < 'z'; b2++) {
307 for (byte b3 = 'a'; b3 < 'z'; b3++) {
308 k[0] = b1;
309 k[1] = b2;
310 k[2] = b3;
311 Put put = new Put(k);
312 put.add(familyName, new byte[0], k);
313 table.put(put);
314 rowCount++;
315 }
316 }
317 }
318
319
320 Map<HRegionInfo,HServerAddress> m = table.getRegionsInfo();
321 System.out.println("Initial regions (" + m.size() + "): " + m);
322 assertTrue(m.size() == 1);
323
324
325 Scan scan = new Scan();
326 ResultScanner scanner = table.getScanner(scan);
327 int rows = 0;
328 for(@SuppressWarnings("unused") Result result : scanner) {
329 rows++;
330 }
331 scanner.close();
332 assertEquals(rowCount, rows);
333
334
335 scan = new Scan();
336 scanner = table.getScanner(scan);
337
338 scanner.next();
339
340 final AtomicInteger count = new AtomicInteger(0);
341 Thread t = new Thread("CheckForSplit") {
342 public void run() {
343 for (int i = 0; i < 20; i++) {
344 try {
345 sleep(1000);
346 } catch (InterruptedException e) {
347 continue;
348 }
349
350 Map<HRegionInfo, HServerAddress> regions = null;
351 try {
352 regions = table.getRegionsInfo();
353 } catch (IOException e) {
354 e.printStackTrace();
355 }
356 if (regions == null) continue;
357 count.set(regions.size());
358 if (count.get() >= 2) break;
359 LOG.debug("Cycle waiting on split");
360 }
361 }
362 };
363 t.start();
364
365 admin.split(Bytes.toString(tableName));
366 t.join();
367
368
369 rows = 1;
370 for (@SuppressWarnings("unused") Result result : scanner) {
371 rows++;
372 if (rows > rowCount) {
373 scanner.close();
374 assertTrue("Scanned more than expected (" + rowCount + ")", false);
375 }
376 }
377 scanner.close();
378 assertEquals(rowCount, rows);
379 }
380
381
382
383
384
385 @Test (expected=IllegalArgumentException.class)
386 public void testEmptyHHTableDescriptor() throws IOException {
387 this.admin.createTable(new HTableDescriptor());
388 }
389
390 @Test
391 public void testEnableDisableAddColumnDeleteColumn() throws Exception {
392 byte [] tableName = Bytes.toBytes("testMasterAdmin");
393 TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY);
394 this.admin.disableTable(tableName);
395 try {
396 new HTable(TEST_UTIL.getConfiguration(), tableName);
397 } catch (org.apache.hadoop.hbase.client.RegionOfflineException e) {
398
399 }
400 this.admin.addColumn(tableName, new HColumnDescriptor("col2"));
401 this.admin.enableTable(tableName);
402 try {
403 this.admin.deleteColumn(tableName, Bytes.toBytes("col2"));
404 } catch(TableNotDisabledException e) {
405
406 }
407 this.admin.disableTable(tableName);
408 this.admin.deleteColumn(tableName, Bytes.toBytes("col2"));
409 this.admin.deleteTable(tableName);
410 }
411
412 @Test
413 public void testCreateBadTables() throws IOException {
414 String msg = null;
415 try {
416 this.admin.createTable(HTableDescriptor.ROOT_TABLEDESC);
417 } catch (IllegalArgumentException e) {
418 msg = e.toString();
419 }
420 assertTrue("Unexcepted exception message " + msg, msg != null &&
421 msg.startsWith(IllegalArgumentException.class.getName()) &&
422 msg.contains(HTableDescriptor.ROOT_TABLEDESC.getNameAsString()));
423 msg = null;
424 try {
425 this.admin.createTable(HTableDescriptor.META_TABLEDESC);
426 } catch(IllegalArgumentException e) {
427 msg = e.toString();
428 }
429 assertTrue("Unexcepted exception message " + msg, msg != null &&
430 msg.startsWith(IllegalArgumentException.class.getName()) &&
431 msg.contains(HTableDescriptor.META_TABLEDESC.getNameAsString()));
432
433
434 final HTableDescriptor threadDesc =
435 new HTableDescriptor("threaded_testCreateBadTables");
436 threadDesc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY));
437 int count = 10;
438 Thread [] threads = new Thread [count];
439 final AtomicInteger successes = new AtomicInteger(0);
440 final AtomicInteger failures = new AtomicInteger(0);
441 final HBaseAdmin localAdmin = this.admin;
442 for (int i = 0; i < count; i++) {
443 threads[i] = new Thread(Integer.toString(i)) {
444 @Override
445 public void run() {
446 try {
447 localAdmin.createTable(threadDesc);
448 successes.incrementAndGet();
449 } catch (TableExistsException e) {
450 failures.incrementAndGet();
451 } catch (IOException e) {
452 throw new RuntimeException("Failed threaded create" + getName(), e);
453 }
454 }
455 };
456 }
457 for (int i = 0; i < count; i++) {
458 threads[i].start();
459 }
460 for (int i = 0; i < count; i++) {
461 while(threads[i].isAlive()) {
462 try {
463 Thread.sleep(1000);
464 } catch (InterruptedException e) {
465
466 }
467 }
468 }
469
470
471 assertEquals(1, successes.get());
472 assertEquals(count - 1, failures.get());
473 }
474
475
476
477
478
479 @Test
480 public void testTableNameClash() throws Exception {
481 String name = "testTableNameClash";
482 admin.createTable(new HTableDescriptor(name + "SOMEUPPERCASE"));
483 admin.createTable(new HTableDescriptor(name));
484
485 new HTable(TEST_UTIL.getConfiguration(), name);
486 }
487
488
489
490
491
492 @Test
493 public void testReadOnlyTable() throws Exception {
494 byte [] name = Bytes.toBytes("testReadOnlyTable");
495 HTable table = TEST_UTIL.createTable(name, HConstants.CATALOG_FAMILY);
496 byte[] value = Bytes.toBytes("somedata");
497
498 Put put = new Put(value);
499 put.add(HConstants.CATALOG_FAMILY, HConstants.CATALOG_FAMILY, value);
500 table.put(put);
501 }
502
503
504
505
506
507
508 @Test
509 public void testTableNames() throws IOException {
510 byte[][] illegalNames = new byte[][] {
511 Bytes.toBytes("-bad"),
512 Bytes.toBytes(".bad"),
513 HConstants.ROOT_TABLE_NAME,
514 HConstants.META_TABLE_NAME
515 };
516 for (int i = 0; i < illegalNames.length; i++) {
517 try {
518 new HTableDescriptor(illegalNames[i]);
519 throw new IOException("Did not detect '" +
520 Bytes.toString(illegalNames[i]) + "' as an illegal user table name");
521 } catch (IllegalArgumentException e) {
522
523 }
524 }
525 byte[] legalName = Bytes.toBytes("g-oo.d");
526 try {
527 new HTableDescriptor(legalName);
528 } catch (IllegalArgumentException e) {
529 throw new IOException("Legal user table name: '" +
530 Bytes.toString(legalName) + "' caused IllegalArgumentException: " +
531 e.getMessage());
532 }
533 }
534
535
536
537
538
539 @Test (expected=TableExistsException.class)
540 public void testTableNotFoundExceptionWithATable() throws IOException {
541 final byte [] name = Bytes.toBytes("testTableNotFoundExceptionWithATable");
542 TEST_UTIL.createTable(name, HConstants.CATALOG_FAMILY);
543 TEST_UTIL.createTable(name, HConstants.CATALOG_FAMILY);
544 }
545
546
547
548
549
550 @Test (expected=TableNotFoundException.class)
551 public void testTableNotFoundExceptionWithoutAnyTables() throws IOException {
552 new HTable(TEST_UTIL.getConfiguration(),
553 "testTableNotFoundExceptionWithoutAnyTables");
554 }
555
556 @Test
557 public void testHundredsOfTable() throws IOException{
558 final int times = 100;
559 HColumnDescriptor fam1 = new HColumnDescriptor("fam1");
560 HColumnDescriptor fam2 = new HColumnDescriptor("fam2");
561 HColumnDescriptor fam3 = new HColumnDescriptor("fam3");
562
563 for(int i = 0; i < times; i++) {
564 HTableDescriptor htd = new HTableDescriptor("table"+i);
565 htd.addFamily(fam1);
566 htd.addFamily(fam2);
567 htd.addFamily(fam3);
568 this.admin.createTable(htd);
569 }
570
571 for(int i = 0; i < times; i++) {
572 String tableName = "table"+i;
573 this.admin.disableTable(tableName);
574 this.admin.enableTable(tableName);
575 this.admin.disableTable(tableName);
576 this.admin.deleteTable(tableName);
577 }
578 }
579
580 @Test
581 public void testGetTableDescriptor() throws IOException {
582 HColumnDescriptor fam1 = new HColumnDescriptor("fam1");
583 HColumnDescriptor fam2 = new HColumnDescriptor("fam2");
584 HColumnDescriptor fam3 = new HColumnDescriptor("fam3");
585 HTableDescriptor htd = new HTableDescriptor("myTestTable");
586 htd.addFamily(fam1);
587 htd.addFamily(fam2);
588 htd.addFamily(fam3);
589 this.admin.createTable(htd);
590 HTable table = new HTable("myTestTable");
591 HTableDescriptor confirmedHtd = table.getTableDescriptor();
592
593 assertEquals(htd.compareTo(confirmedHtd), 0);
594 }
595 }
596