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
.assertTrue
;
24 import static org
.junit
.Assert
.fail
;
26 import java
.io
.IOException
;
27 import org
.apache
.hadoop
.fs
.FileStatus
;
28 import org
.apache
.hadoop
.fs
.Path
;
29 import org
.apache
.hadoop
.hbase
.HBaseClassTestRule
;
30 import org
.apache
.hadoop
.hbase
.HBaseTestingUtility
;
31 import org
.apache
.hadoop
.hbase
.HRegionInfo
;
32 import org
.apache
.hadoop
.hbase
.TableName
;
33 import org
.apache
.hadoop
.hbase
.client
.RegionInfo
;
34 import org
.apache
.hadoop
.hbase
.client
.RegionInfoBuilder
;
35 import org
.apache
.hadoop
.hbase
.client
.TableDescriptor
;
36 import org
.apache
.hadoop
.hbase
.client
.TableDescriptorBuilder
;
37 import org
.apache
.hadoop
.hbase
.exceptions
.DeserializationException
;
38 import org
.apache
.hadoop
.hbase
.testclassification
.RegionServerTests
;
39 import org
.apache
.hadoop
.hbase
.testclassification
.SmallTests
;
40 import org
.apache
.hadoop
.hbase
.util
.Bytes
;
41 import org
.apache
.hadoop
.hbase
.util
.FSTableDescriptors
;
42 import org
.apache
.hadoop
.hbase
.util
.MD5Hash
;
43 import org
.junit
.ClassRule
;
44 import org
.junit
.Rule
;
45 import org
.junit
.Test
;
46 import org
.junit
.experimental
.categories
.Category
;
47 import org
.junit
.rules
.TestName
;
49 import org
.apache
.hbase
.thirdparty
.com
.google
.protobuf
.UnsafeByteOperations
;
51 import org
.apache
.hadoop
.hbase
.shaded
.protobuf
.ProtobufUtil
;
52 import org
.apache
.hadoop
.hbase
.shaded
.protobuf
.generated
.HBaseProtos
;
54 @Category({RegionServerTests
.class, SmallTests
.class})
55 public class TestRegionInfoBuilder
{
58 public static final HBaseClassTestRule CLASS_RULE
=
59 HBaseClassTestRule
.forClass(TestRegionInfoBuilder
.class);
62 public TestName name
= new TestName();
65 public void testBuilder() {
66 TableName tn
= TableName
.valueOf("test");
67 RegionInfoBuilder builder
= RegionInfoBuilder
.newBuilder(tn
);
68 byte[] startKey
= Bytes
.toBytes("a");
69 builder
.setStartKey(startKey
);
70 byte[] endKey
= Bytes
.toBytes("z");
71 builder
.setEndKey(endKey
);
73 builder
.setRegionId(1);
75 builder
.setReplicaId(replicaId
);
76 boolean offline
= true;
77 builder
.setOffline(offline
);
78 boolean isSplit
= true;
79 builder
.setSplit(isSplit
);
80 RegionInfo ri
= builder
.build();
82 assertEquals(tn
, ri
.getTable());
83 assertArrayEquals(startKey
, ri
.getStartKey());
84 assertArrayEquals(endKey
, ri
.getEndKey());
85 assertEquals(regionId
, ri
.getRegionId());
86 assertEquals(replicaId
, ri
.getReplicaId());
87 assertEquals(offline
, ri
.isOffline());
88 assertEquals(isSplit
, ri
.isSplit());
92 public void testPb() throws DeserializationException
{
93 RegionInfo ri
= RegionInfoBuilder
.FIRST_META_REGIONINFO
;
94 byte [] bytes
= RegionInfo
.toByteArray(ri
);
95 RegionInfo pbri
= RegionInfo
.parseFrom(bytes
);
96 assertTrue(RegionInfo
.COMPARATOR
.compare(ri
, pbri
) == 0);
100 public void testReadAndWriteRegionInfoFile() throws IOException
, InterruptedException
{
101 HBaseTestingUtility htu
= new HBaseTestingUtility();
102 RegionInfo ri
= RegionInfoBuilder
.FIRST_META_REGIONINFO
;
103 Path basedir
= htu
.getDataTestDir();
104 // Create a region. That'll write the .regioninfo file.
105 FSTableDescriptors fsTableDescriptors
= new FSTableDescriptors(htu
.getConfiguration());
106 FSTableDescriptors
.tryUpdateMetaTableDescriptor(htu
.getConfiguration());
107 HRegion r
= HBaseTestingUtility
.createRegionAndWAL(convert(ri
), basedir
, htu
.getConfiguration(),
108 fsTableDescriptors
.get(TableName
.META_TABLE_NAME
));
109 // Get modtime on the file.
110 long modtime
= getModTime(r
);
111 HBaseTestingUtility
.closeRegionAndWAL(r
);
113 r
= HRegion
.openHRegion(basedir
, convert(ri
), fsTableDescriptors
.get(TableName
.META_TABLE_NAME
),
114 null, htu
.getConfiguration());
115 // Ensure the file is not written for a second time.
116 long modtime2
= getModTime(r
);
117 assertEquals(modtime
, modtime2
);
118 // Now load the file.
119 RegionInfo deserializedRi
= HRegionFileSystem
.loadRegionInfoFileContent(
120 r
.getRegionFileSystem().getFileSystem(), r
.getRegionFileSystem().getRegionDir());
121 HBaseTestingUtility
.closeRegionAndWAL(r
);
124 long getModTime(final HRegion r
) throws IOException
{
125 FileStatus
[] statuses
= r
.getRegionFileSystem().getFileSystem().listStatus(
126 new Path(r
.getRegionFileSystem().getRegionDir(), HRegionFileSystem
.REGION_INFO_FILE
));
127 assertTrue(statuses
!= null && statuses
.length
== 1);
128 return statuses
[0].getModificationTime();
132 public void testCreateRegionInfoName() throws Exception
{
133 final String tableName
= name
.getMethodName();
134 final TableName tn
= TableName
.valueOf(tableName
);
135 String startKey
= "startkey";
136 final byte[] sk
= Bytes
.toBytes(startKey
);
139 // old format region name
140 byte [] name
= RegionInfo
.createRegionName(tn
, sk
, id
, false);
141 String nameStr
= Bytes
.toString(name
);
142 assertEquals(tableName
+ "," + startKey
+ "," + id
, nameStr
);
145 // new format region name.
146 String md5HashInHex
= MD5Hash
.getMD5AsHex(name
);
147 assertEquals(RegionInfo
.MD5_HEX_LENGTH
, md5HashInHex
.length());
148 name
= RegionInfo
.createRegionName(tn
, sk
, id
, true);
149 nameStr
= Bytes
.toString(name
);
150 assertEquals(tableName
+ "," + startKey
+ ","
151 + id
+ "." + md5HashInHex
+ ".",
156 public void testContainsRange() {
157 TableDescriptor tableDesc
= TableDescriptorBuilder
.newBuilder(
158 TableName
.valueOf(name
.getMethodName())).build();
159 RegionInfo ri
= RegionInfoBuilder
.newBuilder(tableDesc
.getTableName())
160 .setStartKey(Bytes
.toBytes("a"))
161 .setEndKey(Bytes
.toBytes("g")).build();
162 // Single row range at start of region
163 assertTrue(ri
.containsRange(Bytes
.toBytes("a"), Bytes
.toBytes("a")));
164 // Fully contained range
165 assertTrue(ri
.containsRange(Bytes
.toBytes("b"), Bytes
.toBytes("c")));
166 // Range overlapping start of region
167 assertTrue(ri
.containsRange(Bytes
.toBytes("a"), Bytes
.toBytes("c")));
168 // Fully contained single-row range
169 assertTrue(ri
.containsRange(Bytes
.toBytes("c"), Bytes
.toBytes("c")));
170 // Range that overlaps end key and hence doesn't fit
171 assertFalse(ri
.containsRange(Bytes
.toBytes("a"), Bytes
.toBytes("g")));
172 // Single row range on end key
173 assertFalse(ri
.containsRange(Bytes
.toBytes("g"), Bytes
.toBytes("g")));
174 // Single row range entirely outside
175 assertFalse(ri
.containsRange(Bytes
.toBytes("z"), Bytes
.toBytes("z")));
179 ri
.containsRange(Bytes
.toBytes("z"), Bytes
.toBytes("a"));
180 fail("Invalid range did not throw IAE");
181 } catch (IllegalArgumentException iae
) {
186 public void testLastRegionCompare() {
187 TableDescriptor tableDesc
= TableDescriptorBuilder
188 .newBuilder(TableName
.valueOf(name
.getMethodName())).build();
189 RegionInfo rip
= RegionInfoBuilder
.newBuilder(tableDesc
.getTableName())
190 .setStartKey(Bytes
.toBytes("a"))
191 .setEndKey(new byte[0]).build();
192 RegionInfo ric
= RegionInfoBuilder
.newBuilder(tableDesc
.getTableName())
193 .setStartKey(Bytes
.toBytes("a"))
194 .setEndKey(Bytes
.toBytes("b")).build();
195 assertTrue(RegionInfo
.COMPARATOR
.compare(rip
, ric
) > 0);
199 public void testMetaTables() {
200 assertTrue(RegionInfoBuilder
.FIRST_META_REGIONINFO
.isMetaRegion());
204 public void testComparator() {
205 final TableName tableName
= TableName
.valueOf(name
.getMethodName());
206 byte[] empty
= new byte[0];
207 RegionInfo older
= RegionInfoBuilder
.newBuilder(tableName
)
211 .setRegionId(0L).build();
212 RegionInfo newer
= RegionInfoBuilder
.newBuilder(tableName
)
216 .setRegionId(1L).build();
217 assertTrue(RegionInfo
.COMPARATOR
.compare(older
, newer
) < 0);
218 assertTrue(RegionInfo
.COMPARATOR
.compare(newer
, older
) > 0);
219 assertTrue(RegionInfo
.COMPARATOR
.compare(older
, older
) == 0);
220 assertTrue(RegionInfo
.COMPARATOR
.compare(newer
, newer
) == 0);
224 public void testRegionNameForRegionReplicas() throws Exception
{
225 String tableName
= name
.getMethodName();
226 final TableName tn
= TableName
.valueOf(tableName
);
227 String startKey
= "startkey";
228 final byte[] sk
= Bytes
.toBytes(startKey
);
231 // assert with only the region name without encoding
233 // primary, replicaId = 0
234 byte [] name
= RegionInfo
.createRegionName(tn
, sk
, Bytes
.toBytes(id
), 0, false);
235 String nameStr
= Bytes
.toString(name
);
236 assertEquals(tableName
+ "," + startKey
+ "," + id
, nameStr
);
239 name
= RegionInfo
.createRegionName(tn
, sk
, Bytes
.toBytes(id
), 1, false);
240 nameStr
= Bytes
.toString(name
);
241 assertEquals(tableName
+ "," + startKey
+ "," + id
+ "_" +
242 String
.format(RegionInfo
.REPLICA_ID_FORMAT
, 1), nameStr
);
245 name
= RegionInfo
.createRegionName(tn
, sk
, Bytes
.toBytes(id
), 0xFFFF, false);
246 nameStr
= Bytes
.toString(name
);
247 assertEquals(tableName
+ "," + startKey
+ "," + id
+ "_" +
248 String
.format(RegionInfo
.REPLICA_ID_FORMAT
, 0xFFFF), nameStr
);
252 public void testParseName() throws IOException
{
253 final TableName tableName
= TableName
.valueOf(name
.getMethodName());
254 byte[] startKey
= Bytes
.toBytes("startKey");
255 long regionId
= System
.currentTimeMillis();
258 // test without replicaId
259 byte[] regionName
= RegionInfo
.createRegionName(tableName
, startKey
, regionId
, false);
261 byte[][] fields
= RegionInfo
.parseRegionName(regionName
);
262 assertArrayEquals(Bytes
.toString(fields
[0]),tableName
.getName(), fields
[0]);
263 assertArrayEquals(Bytes
.toString(fields
[1]),startKey
, fields
[1]);
264 assertArrayEquals(Bytes
.toString(fields
[2]), Bytes
.toBytes(Long
.toString(regionId
)),fields
[2]);
265 assertEquals(3, fields
.length
);
267 // test with replicaId
268 regionName
= RegionInfo
.createRegionName(tableName
, startKey
, regionId
,
271 fields
= RegionInfo
.parseRegionName(regionName
);
272 assertArrayEquals(Bytes
.toString(fields
[0]),tableName
.getName(), fields
[0]);
273 assertArrayEquals(Bytes
.toString(fields
[1]),startKey
, fields
[1]);
274 assertArrayEquals(Bytes
.toString(fields
[2]), Bytes
.toBytes(Long
.toString(regionId
)),fields
[2]);
275 assertArrayEquals(Bytes
.toString(fields
[3]), Bytes
.toBytes(
276 String
.format(RegionInfo
.REPLICA_ID_FORMAT
, replicaId
)), fields
[3]);
280 public void testConvert() {
281 final TableName tableName
= TableName
.valueOf("ns1:" + name
.getMethodName());
282 byte[] startKey
= Bytes
.toBytes("startKey");
283 byte[] endKey
= Bytes
.toBytes("endKey");
284 boolean split
= false;
285 long regionId
= System
.currentTimeMillis();
289 RegionInfo ri
= RegionInfoBuilder
.newBuilder(tableName
)
290 .setStartKey(startKey
)
293 .setRegionId(regionId
)
294 .setReplicaId(replicaId
).build();
296 // convert two times, compare
297 RegionInfo convertedRi
= ProtobufUtil
.toRegionInfo(ProtobufUtil
.toRegionInfo(ri
));
299 assertEquals(ri
, convertedRi
);
301 // test convert RegionInfo without replicaId
302 HBaseProtos
.RegionInfo info
= HBaseProtos
.RegionInfo
.newBuilder()
303 .setTableName(HBaseProtos
.TableName
.newBuilder()
304 .setQualifier(UnsafeByteOperations
.unsafeWrap(tableName
.getQualifier()))
305 .setNamespace(UnsafeByteOperations
.unsafeWrap(tableName
.getNamespace()))
307 .setStartKey(UnsafeByteOperations
.unsafeWrap(startKey
))
308 .setEndKey(UnsafeByteOperations
.unsafeWrap(endKey
))
310 .setRegionId(regionId
)
313 convertedRi
= ProtobufUtil
.toRegionInfo(info
);
314 RegionInfo expectedRi
= RegionInfoBuilder
.newBuilder(tableName
)
315 .setStartKey(startKey
)
318 .setRegionId(regionId
)
319 .setReplicaId(0).build();
321 assertEquals(expectedRi
, convertedRi
);
324 // Duplicated method in TestRegionInfoDisplay too.
325 private HRegionInfo
convert(RegionInfo ri
) {
326 HRegionInfo hri
= new HRegionInfo(
327 ri
.getTable(), ri
.getStartKey(), ri
.getEndKey(), ri
.isSplit(), ri
.getRegionId());
328 hri
.setOffline(ri
.isOffline());