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
{
60 public static final HBaseClassTestRule CLASS_RULE
=
61 HBaseClassTestRule
.forClass(TestHRegionInfo
.class);
64 public TestName name
= new TestName();
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());
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());
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
));
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
));
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
));
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
);
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();
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
);
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
+ ".",
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")));
221 hri
.containsRange(Bytes
.toBytes("z"), Bytes
.toBytes("a"));
222 fail("Invalid range did not throw IAE");
223 } catch (IllegalArgumentException iae
) {
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);
238 public void testMetaTables() {
239 assertTrue(HRegionInfo
.FIRST_META_REGIONINFO
.isMetaRegion());
242 @SuppressWarnings("SelfComparison")
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);
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);
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
);
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
);
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
);
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
);
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();
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
,
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]);
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();
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()))
357 .setStartKey(UnsafeByteOperations
.unsafeWrap(startKey
))
358 .setEndKey(UnsafeByteOperations
.unsafeWrap(endKey
))
360 .setRegionId(regionId
)
363 convertedHri
= HRegionInfo
.convert(info
);
364 HRegionInfo expectedHri
= new HRegionInfo(tableName
, startKey
, endKey
, split
,
365 regionId
, 0); // expecting default replicaId
367 assertEquals(expectedHri
, convertedHri
);
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
,
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"
427 Assert
.assertArrayEquals(regionNameParts
[i
], modifiedRegionNameParts
[i
]);
429 assertNotEquals(regionNameParts
[i
][0], modifiedRegionNameParts
[i
][0]);
430 Assert
.assertArrayEquals(modifiedRegionNameParts
[1],
431 HRegionInfo
.getStartKeyForDisplay(h
, conf
));