1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase;
20
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertFalse;
23 import static org.junit.Assert.assertNotNull;
24 import static org.junit.Assert.assertNull;
25 import static org.junit.Assert.assertTrue;
26
27 import java.io.IOException;
28 import java.util.List;
29 import java.util.Random;
30
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.apache.hadoop.conf.Configuration;
34 import org.apache.hadoop.hbase.client.Admin;
35 import org.apache.hadoop.hbase.client.Connection;
36 import org.apache.hadoop.hbase.client.ConnectionFactory;
37 import org.apache.hadoop.hbase.client.Get;
38 import org.apache.hadoop.hbase.client.HTable;
39 import org.apache.hadoop.hbase.client.RegionLocator;
40 import org.apache.hadoop.hbase.client.Result;
41 import org.apache.hadoop.hbase.client.Table;
42 import org.apache.hadoop.hbase.testclassification.MediumTests;
43 import org.apache.hadoop.hbase.util.Bytes;
44 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
45 import org.apache.hadoop.hbase.util.Pair;
46 import org.junit.AfterClass;
47 import org.junit.Assert;
48 import org.junit.BeforeClass;
49 import org.junit.Test;
50 import org.junit.experimental.categories.Category;
51
52 import com.google.common.collect.Lists;
53
54
55
56
57 @Category(MediumTests.class)
58 public class TestMetaTableAccessor {
59 private static final Log LOG = LogFactory.getLog(TestMetaTableAccessor.class);
60 private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
61 private static Connection connection;
62 private Random random = new Random();
63
64 @BeforeClass public static void beforeClass() throws Exception {
65 UTIL.startMiniCluster(3);
66
67 Configuration c = new Configuration(UTIL.getConfiguration());
68
69
70 c.setLong("hbase.client.pause", 1000);
71 c.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 10);
72 connection = ConnectionFactory.createConnection(c);
73 }
74
75 @AfterClass public static void afterClass() throws Exception {
76 connection.close();
77 UTIL.shutdownMiniCluster();
78 }
79
80
81
82
83
84
85
86
87 @Test public void testRetrying()
88 throws IOException, InterruptedException {
89 final TableName name =
90 TableName.valueOf("testRetrying");
91 LOG.info("Started " + name);
92 HTable t = UTIL.createMultiRegionTable(name, HConstants.CATALOG_FAMILY);
93 int regionCount = -1;
94 try (RegionLocator r = t.getRegionLocator()) {
95 regionCount = r.getStartKeys().length;
96 }
97
98 final List<HRegionInfo> regions =
99 testGettingTableRegions(connection, name, regionCount);
100 MetaTask reader = new MetaTask(connection, "reader") {
101 @Override
102 void metaTask() throws Throwable {
103 testGetRegion(connection, regions.get(0));
104 LOG.info("Read " + regions.get(0).getEncodedName());
105 }
106 };
107 MetaTask writer = new MetaTask(connection, "writer") {
108 @Override
109 void metaTask() throws Throwable {
110 MetaTableAccessor.addRegionToMeta(connection, regions.get(0));
111 LOG.info("Wrote " + regions.get(0).getEncodedName());
112 }
113 };
114 reader.start();
115 writer.start();
116
117
118
119
120 final long timeOut = 180000;
121 long startTime = System.currentTimeMillis();
122
123 try {
124
125 assertTrue(reader.isProgressing());
126 assertTrue(writer.isProgressing());
127
128
129
130 for (int i = 0; i < 2; i++) {
131 LOG.info("Restart=" + i);
132 UTIL.ensureSomeRegionServersAvailable(2);
133 int index = -1;
134 do {
135 index = UTIL.getMiniHBaseCluster().getServerWithMeta();
136 } while (index == -1 &&
137 startTime + timeOut < System.currentTimeMillis());
138
139 if (index != -1){
140 UTIL.getMiniHBaseCluster().abortRegionServer(index);
141 UTIL.getMiniHBaseCluster().waitOnRegionServer(index);
142 }
143 }
144
145 assertTrue("reader: " + reader.toString(), reader.isProgressing());
146 assertTrue("writer: " + writer.toString(), writer.isProgressing());
147 } catch (IOException e) {
148 throw e;
149 } finally {
150 reader.stop = true;
151 writer.stop = true;
152 reader.join();
153 writer.join();
154 t.close();
155 }
156 long exeTime = System.currentTimeMillis() - startTime;
157 assertTrue("Timeout: test took " + exeTime / 1000 + " sec", exeTime < timeOut);
158 }
159
160
161
162
163 abstract static class MetaTask extends Thread {
164 boolean stop = false;
165 int count = 0;
166 Throwable t = null;
167 final Connection connection;
168
169 MetaTask(final Connection connection, final String name) {
170 super(name);
171 this.connection = connection;
172 }
173
174 @Override
175 public void run() {
176 try {
177 while(!this.stop) {
178 LOG.info("Before " + this.getName()+ ", count=" + this.count);
179 metaTask();
180 this.count += 1;
181 LOG.info("After " + this.getName() + ", count=" + this.count);
182 Thread.sleep(100);
183 }
184 } catch (Throwable t) {
185 LOG.info(this.getName() + " failed", t);
186 this.t = t;
187 }
188 }
189
190 boolean isProgressing() throws InterruptedException {
191 int currentCount = this.count;
192 while(currentCount == this.count) {
193 if (!isAlive()) return false;
194 if (this.t != null) return false;
195 Thread.sleep(10);
196 }
197 return true;
198 }
199
200 @Override
201 public String toString() {
202 return "count=" + this.count + ", t=" +
203 (this.t == null? "null": this.t.toString());
204 }
205
206 abstract void metaTask() throws Throwable;
207 }
208
209 @Test public void testGetRegionsCatalogTables()
210 throws IOException, InterruptedException {
211 List<HRegionInfo> regions =
212 MetaTableAccessor.getTableRegions(UTIL.getZooKeeperWatcher(),
213 connection, TableName.META_TABLE_NAME);
214 assertTrue(regions.size() >= 1);
215 assertTrue(MetaTableAccessor.getTableRegionsAndLocations(UTIL.getZooKeeperWatcher(),
216 connection,TableName.META_TABLE_NAME).size() >= 1);
217 }
218
219 @Test public void testTableExists() throws IOException {
220 final TableName name =
221 TableName.valueOf("testTableExists");
222 assertFalse(MetaTableAccessor.tableExists(connection, name));
223 UTIL.createTable(name, HConstants.CATALOG_FAMILY);
224 assertTrue(MetaTableAccessor.tableExists(connection, name));
225 Admin admin = UTIL.getHBaseAdmin();
226 admin.disableTable(name);
227 admin.deleteTable(name);
228 assertFalse(MetaTableAccessor.tableExists(connection, name));
229 assertTrue(MetaTableAccessor.tableExists(connection,
230 TableName.META_TABLE_NAME));
231 }
232
233 @Test public void testGetRegion() throws IOException, InterruptedException {
234 final String name = "testGetRegion";
235 LOG.info("Started " + name);
236
237 Pair<HRegionInfo, ServerName> pair =
238 MetaTableAccessor.getRegion(connection, Bytes.toBytes("nonexistent-region"));
239 assertNull(pair);
240 LOG.info("Finished " + name);
241 }
242
243
244 @Test public void testScanMetaForTable()
245 throws IOException, InterruptedException {
246 final TableName name =
247 TableName.valueOf("testScanMetaForTable");
248 LOG.info("Started " + name);
249
250
251
252
253
254
255 UTIL.createTable(name, HConstants.CATALOG_FAMILY);
256
257 TableName greaterName =
258 TableName.valueOf("testScanMetaForTablf");
259 UTIL.createTable(greaterName, HConstants.CATALOG_FAMILY);
260
261
262
263 assertEquals(1, MetaTableAccessor.getTableRegions(UTIL.getZooKeeperWatcher(),
264 connection, name).size());
265 assertEquals(1, MetaTableAccessor.getTableRegions(UTIL.getZooKeeperWatcher(),
266 connection, greaterName).size());
267 }
268
269 private static List<HRegionInfo> testGettingTableRegions(final Connection connection,
270 final TableName name, final int regionCount)
271 throws IOException, InterruptedException {
272 List<HRegionInfo> regions = MetaTableAccessor.getTableRegions(UTIL.getZooKeeperWatcher(),
273 connection, name);
274 assertEquals(regionCount, regions.size());
275 Pair<HRegionInfo, ServerName> pair =
276 MetaTableAccessor.getRegion(connection, regions.get(0).getRegionName());
277 assertEquals(regions.get(0).getEncodedName(),
278 pair.getFirst().getEncodedName());
279 return regions;
280 }
281
282 private static void testGetRegion(final Connection connection,
283 final HRegionInfo region)
284 throws IOException, InterruptedException {
285 Pair<HRegionInfo, ServerName> pair =
286 MetaTableAccessor.getRegion(connection, region.getRegionName());
287 assertEquals(region.getEncodedName(),
288 pair.getFirst().getEncodedName());
289 }
290
291 @Test
292 public void testParseReplicaIdFromServerColumn() {
293 String column1 = HConstants.SERVER_QUALIFIER_STR;
294 assertEquals(0, MetaTableAccessor.parseReplicaIdFromServerColumn(Bytes.toBytes(column1)));
295 String column2 = column1 + MetaTableAccessor.META_REPLICA_ID_DELIMITER;
296 assertEquals(-1, MetaTableAccessor.parseReplicaIdFromServerColumn(Bytes.toBytes(column2)));
297 String column3 = column2 + "00";
298 assertEquals(-1, MetaTableAccessor.parseReplicaIdFromServerColumn(Bytes.toBytes(column3)));
299 String column4 = column3 + "2A";
300 assertEquals(42, MetaTableAccessor.parseReplicaIdFromServerColumn(Bytes.toBytes(column4)));
301 String column5 = column4 + "2A";
302 assertEquals(-1, MetaTableAccessor.parseReplicaIdFromServerColumn(Bytes.toBytes(column5)));
303 String column6 = HConstants.STARTCODE_QUALIFIER_STR;
304 assertEquals(-1, MetaTableAccessor.parseReplicaIdFromServerColumn(Bytes.toBytes(column6)));
305 }
306
307 @Test
308 public void testMetaReaderGetColumnMethods() {
309 Assert.assertArrayEquals(HConstants.SERVER_QUALIFIER, MetaTableAccessor.getServerColumn(0));
310 Assert.assertArrayEquals(Bytes.toBytes(HConstants.SERVER_QUALIFIER_STR
311 + MetaTableAccessor.META_REPLICA_ID_DELIMITER + "002A"),
312 MetaTableAccessor.getServerColumn(42));
313
314 Assert.assertArrayEquals(HConstants.STARTCODE_QUALIFIER,
315 MetaTableAccessor.getStartCodeColumn(0));
316 Assert.assertArrayEquals(Bytes.toBytes(HConstants.STARTCODE_QUALIFIER_STR
317 + MetaTableAccessor.META_REPLICA_ID_DELIMITER + "002A"),
318 MetaTableAccessor.getStartCodeColumn(42));
319
320 Assert.assertArrayEquals(HConstants.SEQNUM_QUALIFIER,
321 MetaTableAccessor.getSeqNumColumn(0));
322 Assert.assertArrayEquals(Bytes.toBytes(HConstants.SEQNUM_QUALIFIER_STR
323 + MetaTableAccessor.META_REPLICA_ID_DELIMITER + "002A"),
324 MetaTableAccessor.getSeqNumColumn(42));
325 }
326
327 @Test
328 public void testMetaLocationsForRegionReplicas() throws IOException {
329 ServerName serverName0 = ServerName.valueOf("foo", 60010, random.nextLong());
330 ServerName serverName1 = ServerName.valueOf("bar", 60010, random.nextLong());
331 ServerName serverName100 = ServerName.valueOf("baz", 60010, random.nextLong());
332
333 long regionId = System.currentTimeMillis();
334 HRegionInfo primary = new HRegionInfo(TableName.valueOf("table_foo"),
335 HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW, false, regionId, 0);
336 HRegionInfo replica1 = new HRegionInfo(TableName.valueOf("table_foo"),
337 HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW, false, regionId, 1);
338 HRegionInfo replica100 = new HRegionInfo(TableName.valueOf("table_foo"),
339 HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW, false, regionId, 100);
340
341 long seqNum0 = random.nextLong();
342 long seqNum1 = random.nextLong();
343 long seqNum100 = random.nextLong();
344
345
346 Table meta = MetaTableAccessor.getMetaHTable(connection);
347 try {
348 MetaTableAccessor.updateRegionLocation(connection, primary, serverName0, seqNum0, -1);
349
350
351 assertMetaLocation(meta, primary.getRegionName(), serverName0, seqNum0, 0, true);
352
353
354 MetaTableAccessor.updateRegionLocation(connection, replica1, serverName1, seqNum1, -1);
355
356 assertMetaLocation(meta, primary.getRegionName(), serverName0, seqNum0, 0, true);
357
358 assertMetaLocation(meta, primary.getRegionName(), serverName1, seqNum1, 1, true);
359
360
361 MetaTableAccessor.updateRegionLocation(connection, replica100, serverName100, seqNum100, -1);
362
363 assertMetaLocation(meta, primary.getRegionName(), serverName0, seqNum0, 0, true);
364
365 assertMetaLocation(meta, primary.getRegionName(), serverName1, seqNum1, 1, true);
366
367 assertMetaLocation(meta, primary.getRegionName(), serverName100, seqNum100, 100, true);
368 } finally {
369 meta.close();
370 }
371 }
372
373 public static void assertMetaLocation(Table meta, byte[] row, ServerName serverName,
374 long seqNum, int replicaId, boolean checkSeqNum) throws IOException {
375 Get get = new Get(row);
376 Result result = meta.get(get);
377 assertTrue(Bytes.equals(
378 result.getValue(HConstants.CATALOG_FAMILY, MetaTableAccessor.getServerColumn(replicaId)),
379 Bytes.toBytes(serverName.getHostAndPort())));
380 assertTrue(Bytes.equals(
381 result.getValue(HConstants.CATALOG_FAMILY, MetaTableAccessor.getStartCodeColumn(replicaId)),
382 Bytes.toBytes(serverName.getStartcode())));
383 if (checkSeqNum) {
384 assertTrue(Bytes.equals(
385 result.getValue(HConstants.CATALOG_FAMILY, MetaTableAccessor.getSeqNumColumn(replicaId)),
386 Bytes.toBytes(seqNum)));
387 }
388 }
389
390 public static void assertEmptyMetaLocation(Table meta, byte[] row, int replicaId)
391 throws IOException {
392 Get get = new Get(row);
393 Result result = meta.get(get);
394 Cell serverCell = result.getColumnLatestCell(HConstants.CATALOG_FAMILY,
395 MetaTableAccessor.getServerColumn(replicaId));
396 Cell startCodeCell = result.getColumnLatestCell(HConstants.CATALOG_FAMILY,
397 MetaTableAccessor.getStartCodeColumn(replicaId));
398 assertNotNull(serverCell);
399 assertNotNull(startCodeCell);
400 assertEquals(0, serverCell.getValueLength());
401 assertEquals(0, startCodeCell.getValueLength());
402 }
403
404 @Test
405 public void testMetaLocationForRegionReplicasIsAddedAtTableCreation() throws IOException {
406 long regionId = System.currentTimeMillis();
407 HRegionInfo primary = new HRegionInfo(TableName.valueOf("table_foo"),
408 HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW, false, regionId, 0);
409
410 Table meta = MetaTableAccessor.getMetaHTable(connection);
411 try {
412 List<HRegionInfo> regionInfos = Lists.newArrayList(primary);
413 MetaTableAccessor.addRegionsToMeta(connection, regionInfos, 3);
414
415 assertEmptyMetaLocation(meta, primary.getRegionName(), 1);
416 assertEmptyMetaLocation(meta, primary.getRegionName(), 2);
417 } finally {
418 meta.close();
419 }
420 }
421
422 @Test
423 public void testMetaLocationForRegionReplicasIsAddedAtRegionSplit() throws IOException {
424 long regionId = System.currentTimeMillis();
425 ServerName serverName0 = ServerName.valueOf("foo", 60010, random.nextLong());
426 HRegionInfo parent = new HRegionInfo(TableName.valueOf("table_foo"),
427 HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW, false, regionId, 0);
428 HRegionInfo splitA = new HRegionInfo(TableName.valueOf("table_foo"),
429 HConstants.EMPTY_START_ROW, Bytes.toBytes("a"), false, regionId+1, 0);
430 HRegionInfo splitB = new HRegionInfo(TableName.valueOf("table_foo"),
431 Bytes.toBytes("a"), HConstants.EMPTY_END_ROW, false, regionId+1, 0);
432
433
434 Table meta = MetaTableAccessor.getMetaHTable(connection);
435 try {
436 List<HRegionInfo> regionInfos = Lists.newArrayList(parent);
437 MetaTableAccessor.addRegionsToMeta(connection, regionInfos, 3);
438
439 MetaTableAccessor.splitRegion(connection, parent, splitA, splitB, serverName0, 3);
440
441 assertEmptyMetaLocation(meta, splitA.getRegionName(), 1);
442 assertEmptyMetaLocation(meta, splitA.getRegionName(), 2);
443 assertEmptyMetaLocation(meta, splitB.getRegionName(), 1);
444 assertEmptyMetaLocation(meta, splitB.getRegionName(), 2);
445 } finally {
446 meta.close();
447 }
448 }
449
450 @Test
451 public void testMetaLocationForRegionReplicasIsAddedAtRegionMerge() throws IOException {
452 long regionId = System.currentTimeMillis();
453 ServerName serverName0 = ServerName.valueOf("foo", 60010, random.nextLong());
454
455 HRegionInfo parentA = new HRegionInfo(TableName.valueOf("table_foo"),
456 Bytes.toBytes("a"), HConstants.EMPTY_END_ROW, false, regionId, 0);
457 HRegionInfo parentB = new HRegionInfo(TableName.valueOf("table_foo"),
458 HConstants.EMPTY_START_ROW, Bytes.toBytes("a"), false, regionId, 0);
459 HRegionInfo merged = new HRegionInfo(TableName.valueOf("table_foo"),
460 HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW, false, regionId+1, 0);
461
462 Table meta = MetaTableAccessor.getMetaHTable(connection);
463 try {
464 List<HRegionInfo> regionInfos = Lists.newArrayList(parentA, parentB);
465 MetaTableAccessor.addRegionsToMeta(connection, regionInfos, 3);
466
467 MetaTableAccessor.mergeRegions(connection, merged, parentA, parentB, serverName0, 3,
468 HConstants.LATEST_TIMESTAMP);
469
470 assertEmptyMetaLocation(meta, merged.getRegionName(), 1);
471 assertEmptyMetaLocation(meta, merged.getRegionName(), 2);
472 } finally {
473 meta.close();
474 }
475 }
476
477
478
479
480 @Test
481 public void testMastersSystemTimeIsUsedInUpdateLocations() throws IOException {
482 long regionId = System.currentTimeMillis();
483 HRegionInfo regionInfo = new HRegionInfo(TableName.valueOf("table_foo"),
484 HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW, false, regionId, 0);
485
486 ServerName sn = ServerName.valueOf("bar", 0, 0);
487 Table meta = MetaTableAccessor.getMetaHTable(connection);
488 try {
489 List<HRegionInfo> regionInfos = Lists.newArrayList(regionInfo);
490 MetaTableAccessor.addRegionsToMeta(connection, regionInfos, 1);
491
492 long masterSystemTime = EnvironmentEdgeManager.currentTime() + 123456789;
493 MetaTableAccessor.updateRegionLocation(connection, regionInfo, sn, 1, masterSystemTime);
494
495 Get get = new Get(regionInfo.getRegionName());
496 Result result = meta.get(get);
497 Cell serverCell = result.getColumnLatestCell(HConstants.CATALOG_FAMILY,
498 MetaTableAccessor.getServerColumn(0));
499 Cell startCodeCell = result.getColumnLatestCell(HConstants.CATALOG_FAMILY,
500 MetaTableAccessor.getStartCodeColumn(0));
501 Cell seqNumCell = result.getColumnLatestCell(HConstants.CATALOG_FAMILY,
502 MetaTableAccessor.getSeqNumColumn(0));
503 assertNotNull(serverCell);
504 assertNotNull(startCodeCell);
505 assertNotNull(seqNumCell);
506 assertTrue(serverCell.getValueLength() > 0);
507 assertTrue(startCodeCell.getValueLength() > 0);
508 assertTrue(seqNumCell.getValueLength() > 0);
509 assertEquals(masterSystemTime, serverCell.getTimestamp());
510 assertEquals(masterSystemTime, startCodeCell.getTimestamp());
511 assertEquals(masterSystemTime, seqNumCell.getTimestamp());
512 } finally {
513 meta.close();
514 }
515 }
516
517 @Test
518 public void testMastersSystemTimeIsUsedInMergeRegions() throws IOException {
519 long regionId = System.currentTimeMillis();
520 HRegionInfo regionInfoA = new HRegionInfo(TableName.valueOf("table_foo"),
521 HConstants.EMPTY_START_ROW, new byte[] {'a'}, false, regionId, 0);
522 HRegionInfo regionInfoB = new HRegionInfo(TableName.valueOf("table_foo"),
523 new byte[] {'a'}, HConstants.EMPTY_END_ROW, false, regionId, 0);
524 HRegionInfo mergedRegionInfo = new HRegionInfo(TableName.valueOf("table_foo"),
525 HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW, false, regionId, 0);
526
527 ServerName sn = ServerName.valueOf("bar", 0, 0);
528 Table meta = MetaTableAccessor.getMetaHTable(connection);
529 try {
530 List<HRegionInfo> regionInfos = Lists.newArrayList(regionInfoA, regionInfoB);
531 MetaTableAccessor.addRegionsToMeta(connection, regionInfos, 1);
532
533
534
535
536 long serverNameTime = EnvironmentEdgeManager.currentTime() + 100000000;
537 long masterSystemTime = EnvironmentEdgeManager.currentTime() + 123456789;
538
539
540 MetaTableAccessor.updateRegionLocation(connection, regionInfoA, sn, 1, serverNameTime);
541
542
543 Get get = new Get(mergedRegionInfo.getRegionName());
544 Result result = meta.get(get);
545 Cell serverCell = result.getColumnLatestCell(HConstants.CATALOG_FAMILY,
546 MetaTableAccessor.getServerColumn(0));
547 assertNotNull(serverCell);
548 assertEquals(serverNameTime, serverCell.getTimestamp());
549
550
551 MetaTableAccessor.mergeRegions(connection, mergedRegionInfo,
552 regionInfoA, regionInfoB, sn, 1, masterSystemTime);
553
554 result = meta.get(get);
555 serverCell = result.getColumnLatestCell(HConstants.CATALOG_FAMILY,
556 MetaTableAccessor.getServerColumn(0));
557 Cell startCodeCell = result.getColumnLatestCell(HConstants.CATALOG_FAMILY,
558 MetaTableAccessor.getStartCodeColumn(0));
559 Cell seqNumCell = result.getColumnLatestCell(HConstants.CATALOG_FAMILY,
560 MetaTableAccessor.getSeqNumColumn(0));
561 assertNull(serverCell);
562 assertNull(startCodeCell);
563 assertNull(seqNumCell);
564 } finally {
565 meta.close();
566 }
567 }
568 }
569