HBASE-23912 Resolve the TODO of FSTableDescriptor's construct method (#1225)
[hbase.git] / hbase-server / src / test / java / org / apache / hadoop / hbase / regionserver / TestHRegionInfo.java
blobf9e2d5a921905be4fcf5e7b2a71487430cbcd8e9
1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 package org.apache.hadoop.hbase.regionserver;
20 import static org.junit.Assert.assertArrayEquals;
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertFalse;
23 import static org.junit.Assert.assertNotEquals;
24 import static org.junit.Assert.assertTrue;
25 import static org.junit.Assert.fail;
27 import java.io.IOException;
28 import org.apache.hadoop.conf.Configuration;
29 import org.apache.hadoop.fs.FileStatus;
30 import org.apache.hadoop.fs.Path;
31 import org.apache.hadoop.hbase.HBaseClassTestRule;
32 import org.apache.hadoop.hbase.HBaseTestingUtility;
33 import org.apache.hadoop.hbase.HRegionInfo;
34 import org.apache.hadoop.hbase.HTableDescriptor;
35 import org.apache.hadoop.hbase.TableName;
36 import org.apache.hadoop.hbase.client.RegionInfo;
37 import org.apache.hadoop.hbase.client.RegionInfoBuilder;
38 import org.apache.hadoop.hbase.exceptions.DeserializationException;
39 import org.apache.hadoop.hbase.master.RegionState;
40 import org.apache.hadoop.hbase.testclassification.RegionServerTests;
41 import org.apache.hadoop.hbase.testclassification.SmallTests;
42 import org.apache.hadoop.hbase.util.Bytes;
43 import org.apache.hadoop.hbase.util.FSTableDescriptors;
44 import org.apache.hadoop.hbase.util.MD5Hash;
45 import org.junit.Assert;
46 import org.junit.ClassRule;
47 import org.junit.Rule;
48 import org.junit.Test;
49 import org.junit.experimental.categories.Category;
50 import org.junit.rules.TestName;
52 import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations;
54 import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;
56 @Category({RegionServerTests.class, SmallTests.class})
57 public class TestHRegionInfo {
59 @ClassRule
60 public static final HBaseClassTestRule CLASS_RULE =
61 HBaseClassTestRule.forClass(TestHRegionInfo.class);
63 @Rule
64 public TestName name = new TestName();
66 @Test
67 public void testIsStart() {
68 assertTrue(RegionInfoBuilder.FIRST_META_REGIONINFO.isFirst());
69 org.apache.hadoop.hbase.client.RegionInfo ri =
70 org.apache.hadoop.hbase.client.RegionInfoBuilder.newBuilder(TableName.META_TABLE_NAME).
71 setStartKey(Bytes.toBytes("not_start")).build();
72 assertFalse(ri.isFirst());
75 @Test
76 public void testIsEnd() {
77 assertTrue(RegionInfoBuilder.FIRST_META_REGIONINFO.isFirst());
78 org.apache.hadoop.hbase.client.RegionInfo ri =
79 org.apache.hadoop.hbase.client.RegionInfoBuilder.newBuilder(TableName.META_TABLE_NAME).
80 setEndKey(Bytes.toBytes("not_end")).build();
81 assertFalse(ri.isLast());
84 @Test
85 public void testIsNext() {
86 byte [] bytes = Bytes.toBytes("row");
87 org.apache.hadoop.hbase.client.RegionInfo ri =
88 org.apache.hadoop.hbase.client.RegionInfoBuilder.newBuilder(TableName.META_TABLE_NAME).
89 setEndKey(bytes).build();
90 org.apache.hadoop.hbase.client.RegionInfo ri2 =
91 org.apache.hadoop.hbase.client.RegionInfoBuilder.newBuilder(TableName.META_TABLE_NAME).
92 setStartKey(bytes).build();
93 assertFalse(ri.isNext(RegionInfoBuilder.FIRST_META_REGIONINFO));
94 assertTrue(ri.isNext(ri2));
97 @Test
98 public void testIsOverlap() {
99 byte [] a = Bytes.toBytes("a");
100 byte [] b = Bytes.toBytes("b");
101 byte [] c = Bytes.toBytes("c");
102 byte [] d = Bytes.toBytes("d");
103 org.apache.hadoop.hbase.client.RegionInfo all =
104 RegionInfoBuilder.FIRST_META_REGIONINFO;
105 org.apache.hadoop.hbase.client.RegionInfo ari =
106 org.apache.hadoop.hbase.client.RegionInfoBuilder.newBuilder(TableName.META_TABLE_NAME).
107 setEndKey(a).build();
108 org.apache.hadoop.hbase.client.RegionInfo abri =
109 org.apache.hadoop.hbase.client.RegionInfoBuilder.newBuilder(TableName.META_TABLE_NAME).
110 setStartKey(a).setEndKey(b).build();
111 org.apache.hadoop.hbase.client.RegionInfo adri =
112 org.apache.hadoop.hbase.client.RegionInfoBuilder.newBuilder(TableName.META_TABLE_NAME).
113 setStartKey(a).setEndKey(d).build();
114 org.apache.hadoop.hbase.client.RegionInfo cdri =
115 org.apache.hadoop.hbase.client.RegionInfoBuilder.newBuilder(TableName.META_TABLE_NAME).
116 setStartKey(c).setEndKey(d).build();
117 org.apache.hadoop.hbase.client.RegionInfo dri =
118 org.apache.hadoop.hbase.client.RegionInfoBuilder.newBuilder(TableName.META_TABLE_NAME).
119 setStartKey(d).build();
120 assertTrue(all.isOverlap(all));
121 assertTrue(all.isOverlap(abri));
122 assertFalse(abri.isOverlap(cdri));
123 assertTrue(all.isOverlap(ari));
124 assertFalse(ari.isOverlap(abri));
125 assertFalse(ari.isOverlap(abri));
126 assertTrue(ari.isOverlap(all));
127 assertTrue(dri.isOverlap(all));
128 assertTrue(abri.isOverlap(adri));
129 assertFalse(dri.isOverlap(ari));
130 assertTrue(abri.isOverlap(adri));
131 assertTrue(adri.isOverlap(abri));
134 @Test
135 public void testPb() throws DeserializationException {
136 HRegionInfo hri = HRegionInfo.FIRST_META_REGIONINFO;
137 byte [] bytes = hri.toByteArray();
138 HRegionInfo pbhri = HRegionInfo.parseFrom(bytes);
139 assertTrue(hri.equals(pbhri));
142 @Test
143 public void testReadAndWriteHRegionInfoFile() throws IOException, InterruptedException {
144 HBaseTestingUtility htu = new HBaseTestingUtility();
145 HRegionInfo hri = HRegionInfo.FIRST_META_REGIONINFO;
146 Path basedir = htu.getDataTestDir();
147 // Create a region. That'll write the .regioninfo file.
148 FSTableDescriptors fsTableDescriptors = new FSTableDescriptors(htu.getConfiguration());
149 FSTableDescriptors.tryUpdateMetaTableDescriptor(htu.getConfiguration());
150 HRegion r = HBaseTestingUtility.createRegionAndWAL(hri, basedir, htu.getConfiguration(),
151 fsTableDescriptors.get(TableName.META_TABLE_NAME));
152 // Get modtime on the file.
153 long modtime = getModTime(r);
154 HBaseTestingUtility.closeRegionAndWAL(r);
155 Thread.sleep(1001);
156 r = HRegion.openHRegion(basedir, hri, fsTableDescriptors.get(TableName.META_TABLE_NAME),
157 null, htu.getConfiguration());
158 // Ensure the file is not written for a second time.
159 long modtime2 = getModTime(r);
160 assertEquals(modtime, modtime2);
161 // Now load the file.
162 org.apache.hadoop.hbase.client.RegionInfo deserializedHri = HRegionFileSystem.loadRegionInfoFileContent(
163 r.getRegionFileSystem().getFileSystem(), r.getRegionFileSystem().getRegionDir());
164 assertTrue(org.apache.hadoop.hbase.client.RegionInfo.COMPARATOR.compare(hri, deserializedHri) == 0);
165 HBaseTestingUtility.closeRegionAndWAL(r);
168 long getModTime(final HRegion r) throws IOException {
169 FileStatus[] statuses = r.getRegionFileSystem().getFileSystem().listStatus(
170 new Path(r.getRegionFileSystem().getRegionDir(), HRegionFileSystem.REGION_INFO_FILE));
171 assertTrue(statuses != null && statuses.length == 1);
172 return statuses[0].getModificationTime();
175 @Test
176 public void testCreateHRegionInfoName() throws Exception {
177 final String tableName = name.getMethodName();
178 final TableName tn = TableName.valueOf(tableName);
179 String startKey = "startkey";
180 final byte[] sk = Bytes.toBytes(startKey);
181 String id = "id";
183 // old format region name
184 byte [] name = HRegionInfo.createRegionName(tn, sk, id, false);
185 String nameStr = Bytes.toString(name);
186 assertEquals(tableName + "," + startKey + "," + id, nameStr);
189 // new format region name.
190 String md5HashInHex = MD5Hash.getMD5AsHex(name);
191 assertEquals(HRegionInfo.MD5_HEX_LENGTH, md5HashInHex.length());
192 name = HRegionInfo.createRegionName(tn, sk, id, true);
193 nameStr = Bytes.toString(name);
194 assertEquals(tableName + "," + startKey + ","
195 + id + "." + md5HashInHex + ".",
196 nameStr);
199 @Test
200 public void testContainsRange() {
201 HTableDescriptor tableDesc = new HTableDescriptor(TableName.valueOf(name.getMethodName()));
202 HRegionInfo hri = new HRegionInfo(
203 tableDesc.getTableName(), Bytes.toBytes("a"), Bytes.toBytes("g"));
204 // Single row range at start of region
205 assertTrue(hri.containsRange(Bytes.toBytes("a"), Bytes.toBytes("a")));
206 // Fully contained range
207 assertTrue(hri.containsRange(Bytes.toBytes("b"), Bytes.toBytes("c")));
208 // Range overlapping start of region
209 assertTrue(hri.containsRange(Bytes.toBytes("a"), Bytes.toBytes("c")));
210 // Fully contained single-row range
211 assertTrue(hri.containsRange(Bytes.toBytes("c"), Bytes.toBytes("c")));
212 // Range that overlaps end key and hence doesn't fit
213 assertFalse(hri.containsRange(Bytes.toBytes("a"), Bytes.toBytes("g")));
214 // Single row range on end key
215 assertFalse(hri.containsRange(Bytes.toBytes("g"), Bytes.toBytes("g")));
216 // Single row range entirely outside
217 assertFalse(hri.containsRange(Bytes.toBytes("z"), Bytes.toBytes("z")));
219 // Degenerate range
220 try {
221 hri.containsRange(Bytes.toBytes("z"), Bytes.toBytes("a"));
222 fail("Invalid range did not throw IAE");
223 } catch (IllegalArgumentException iae) {
227 @Test
228 public void testLastRegionCompare() {
229 HTableDescriptor tableDesc = new HTableDescriptor(TableName.valueOf(name.getMethodName()));
230 HRegionInfo hrip = new HRegionInfo(
231 tableDesc.getTableName(), Bytes.toBytes("a"), new byte[0]);
232 HRegionInfo hric = new HRegionInfo(
233 tableDesc.getTableName(), Bytes.toBytes("a"), Bytes.toBytes("b"));
234 assertTrue(hrip.compareTo(hric) > 0);
237 @Test
238 public void testMetaTables() {
239 assertTrue(HRegionInfo.FIRST_META_REGIONINFO.isMetaRegion());
242 @SuppressWarnings("SelfComparison")
243 @Test
244 public void testComparator() {
245 final TableName tableName = TableName.valueOf(name.getMethodName());
246 byte[] empty = new byte[0];
247 HRegionInfo older = new HRegionInfo(tableName, empty, empty, false, 0L);
248 HRegionInfo newer = new HRegionInfo(tableName, empty, empty, false, 1L);
249 assertTrue(older.compareTo(newer) < 0);
250 assertTrue(newer.compareTo(older) > 0);
251 assertEquals(0, older.compareTo(older));
252 assertEquals(0, newer.compareTo(newer));
254 HRegionInfo a = new HRegionInfo(TableName.valueOf("a"), null, null);
255 HRegionInfo b = new HRegionInfo(TableName.valueOf("b"), null, null);
256 assertNotEquals(0, a.compareTo(b));
257 HTableDescriptor t = new HTableDescriptor(TableName.valueOf("t"));
258 byte [] midway = Bytes.toBytes("midway");
259 a = new HRegionInfo(t.getTableName(), null, midway);
260 b = new HRegionInfo(t.getTableName(), midway, null);
261 assertTrue(a.compareTo(b) < 0);
262 assertTrue(b.compareTo(a) > 0);
263 assertEquals(a, a);
264 assertEquals(0, a.compareTo(a));
265 a = new HRegionInfo(t.getTableName(), Bytes.toBytes("a"), Bytes.toBytes("d"));
266 b = new HRegionInfo(t.getTableName(), Bytes.toBytes("e"), Bytes.toBytes("g"));
267 assertTrue(a.compareTo(b) < 0);
268 a = new HRegionInfo(t.getTableName(), Bytes.toBytes("aaaa"), Bytes.toBytes("dddd"));
269 b = new HRegionInfo(t.getTableName(), Bytes.toBytes("e"), Bytes.toBytes("g"));
270 assertTrue(a.compareTo(b) < 0);
271 a = new HRegionInfo(t.getTableName(), Bytes.toBytes("aaaa"), Bytes.toBytes("dddd"));
272 b = new HRegionInfo(t.getTableName(), Bytes.toBytes("aaaa"), Bytes.toBytes("eeee"));
273 assertTrue(a.compareTo(b) < 0);
277 @Test
278 public void testRegionNameForRegionReplicas() throws Exception {
279 String tableName = name.getMethodName();
280 final TableName tn = TableName.valueOf(tableName);
281 String startKey = "startkey";
282 final byte[] sk = Bytes.toBytes(startKey);
283 String id = "id";
285 // assert with only the region name without encoding
287 // primary, replicaId = 0
288 byte [] name = HRegionInfo.createRegionName(tn, sk, Bytes.toBytes(id), 0, false);
289 String nameStr = Bytes.toString(name);
290 assertEquals(tableName + "," + startKey + "," + id, nameStr);
292 // replicaId = 1
293 name = HRegionInfo.createRegionName(tn, sk, Bytes.toBytes(id), 1, false);
294 nameStr = Bytes.toString(name);
295 assertEquals(tableName + "," + startKey + "," + id + "_" +
296 String.format(HRegionInfo.REPLICA_ID_FORMAT, 1), nameStr);
298 // replicaId = max
299 name = HRegionInfo.createRegionName(tn, sk, Bytes.toBytes(id), 0xFFFF, false);
300 nameStr = Bytes.toString(name);
301 assertEquals(tableName + "," + startKey + "," + id + "_" +
302 String.format(HRegionInfo.REPLICA_ID_FORMAT, 0xFFFF), nameStr);
305 @Test
306 public void testParseName() throws IOException {
307 final TableName tableName = TableName.valueOf(name.getMethodName());
308 byte[] startKey = Bytes.toBytes("startKey");
309 long regionId = System.currentTimeMillis();
310 int replicaId = 42;
312 // test without replicaId
313 byte[] regionName = HRegionInfo.createRegionName(tableName, startKey, regionId, false);
315 byte[][] fields = HRegionInfo.parseRegionName(regionName);
316 assertArrayEquals(Bytes.toString(fields[0]),tableName.getName(), fields[0]);
317 assertArrayEquals(Bytes.toString(fields[1]),startKey, fields[1]);
318 assertArrayEquals(Bytes.toString(fields[2]), Bytes.toBytes(Long.toString(regionId)),fields[2]);
319 assertEquals(3, fields.length);
321 // test with replicaId
322 regionName = HRegionInfo.createRegionName(tableName, startKey, regionId,
323 replicaId, false);
325 fields = HRegionInfo.parseRegionName(regionName);
326 assertArrayEquals(Bytes.toString(fields[0]),tableName.getName(), fields[0]);
327 assertArrayEquals(Bytes.toString(fields[1]),startKey, fields[1]);
328 assertArrayEquals(Bytes.toString(fields[2]), Bytes.toBytes(Long.toString(regionId)),fields[2]);
329 assertArrayEquals(Bytes.toString(fields[3]), Bytes.toBytes(
330 String.format(HRegionInfo.REPLICA_ID_FORMAT, replicaId)), fields[3]);
333 @Test
334 public void testConvert() {
335 final TableName tableName = TableName.valueOf("ns1:" + name.getMethodName());
336 byte[] startKey = Bytes.toBytes("startKey");
337 byte[] endKey = Bytes.toBytes("endKey");
338 boolean split = false;
339 long regionId = System.currentTimeMillis();
340 int replicaId = 42;
343 HRegionInfo hri = new HRegionInfo(tableName, startKey, endKey, split,
344 regionId, replicaId);
346 // convert two times, compare
347 HRegionInfo convertedHri = HRegionInfo.convert(HRegionInfo.convert(hri));
349 assertEquals(hri, convertedHri);
351 // test convert RegionInfo without replicaId
352 HBaseProtos.RegionInfo info = HBaseProtos.RegionInfo.newBuilder()
353 .setTableName(HBaseProtos.TableName.newBuilder()
354 .setQualifier(UnsafeByteOperations.unsafeWrap(tableName.getQualifier()))
355 .setNamespace(UnsafeByteOperations.unsafeWrap(tableName.getNamespace()))
356 .build())
357 .setStartKey(UnsafeByteOperations.unsafeWrap(startKey))
358 .setEndKey(UnsafeByteOperations.unsafeWrap(endKey))
359 .setSplit(split)
360 .setRegionId(regionId)
361 .build();
363 convertedHri = HRegionInfo.convert(info);
364 HRegionInfo expectedHri = new HRegionInfo(tableName, startKey, endKey, split,
365 regionId, 0); // expecting default replicaId
367 assertEquals(expectedHri, convertedHri);
369 @Test
370 public void testRegionDetailsForDisplay() throws IOException {
371 byte[] startKey = new byte[] {0x01, 0x01, 0x02, 0x03};
372 byte[] endKey = new byte[] {0x01, 0x01, 0x02, 0x04};
373 Configuration conf = new Configuration();
374 conf.setBoolean("hbase.display.keys", false);
375 HRegionInfo h = new HRegionInfo(TableName.valueOf(name.getMethodName()), startKey, endKey);
376 checkEquality(h, conf);
377 // check HRIs with non-default replicaId
378 h = new HRegionInfo(TableName.valueOf(name.getMethodName()), startKey, endKey, false,
379 System.currentTimeMillis(), 1);
380 checkEquality(h, conf);
381 Assert.assertArrayEquals(HRegionInfo.HIDDEN_END_KEY,
382 HRegionInfo.getEndKeyForDisplay(h, conf));
383 Assert.assertArrayEquals(HRegionInfo.HIDDEN_START_KEY,
384 HRegionInfo.getStartKeyForDisplay(h, conf));
386 RegionState state = RegionState.createForTesting(h, RegionState.State.OPEN);
387 String descriptiveNameForDisplay =
388 HRegionInfo.getDescriptiveNameFromRegionStateForDisplay(state, conf);
389 checkDescriptiveNameEquality(descriptiveNameForDisplay,state.toDescriptiveString(), startKey);
391 conf.setBoolean("hbase.display.keys", true);
392 Assert.assertArrayEquals(endKey, HRegionInfo.getEndKeyForDisplay(h, conf));
393 Assert.assertArrayEquals(startKey, HRegionInfo.getStartKeyForDisplay(h, conf));
394 Assert.assertEquals(state.toDescriptiveString(),
395 HRegionInfo.getDescriptiveNameFromRegionStateForDisplay(state, conf));
398 private void checkDescriptiveNameEquality(String descriptiveNameForDisplay, String origDesc,
399 byte[] startKey) {
400 // except for the "hidden-start-key" substring everything else should exactly match
401 String firstPart = descriptiveNameForDisplay.substring(0,
402 descriptiveNameForDisplay.indexOf(new String(HRegionInfo.HIDDEN_START_KEY)));
403 String secondPart = descriptiveNameForDisplay.substring(
404 descriptiveNameForDisplay.indexOf(new String(HRegionInfo.HIDDEN_START_KEY)) +
405 HRegionInfo.HIDDEN_START_KEY.length);
406 String firstPartOrig = origDesc.substring(0,
407 origDesc.indexOf(Bytes.toStringBinary(startKey)));
408 String secondPartOrig = origDesc.substring(
409 origDesc.indexOf(Bytes.toStringBinary(startKey)) +
410 Bytes.toStringBinary(startKey).length());
411 assert(firstPart.equals(firstPartOrig));
412 assert(secondPart.equals(secondPartOrig));
415 private void checkEquality(HRegionInfo h, Configuration conf) throws IOException {
416 byte[] modifiedRegionName = HRegionInfo.getRegionNameForDisplay(h, conf);
417 byte[][] modifiedRegionNameParts = HRegionInfo.parseRegionName(modifiedRegionName);
418 byte[][] regionNameParts = HRegionInfo.parseRegionName(h.getRegionName());
420 //same number of parts
421 assert(modifiedRegionNameParts.length == regionNameParts.length);
423 for (int i = 0; i < regionNameParts.length; i++) {
424 // all parts should match except for [1] where in the modified one,
425 // we should have "hidden_start_key"
426 if (i != 1) {
427 Assert.assertArrayEquals(regionNameParts[i], modifiedRegionNameParts[i]);
428 } else {
429 assertNotEquals(regionNameParts[i][0], modifiedRegionNameParts[i][0]);
430 Assert.assertArrayEquals(modifiedRegionNameParts[1],
431 HRegionInfo.getStartKeyForDisplay(h, conf));