001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.regionserver; 019 020import static org.junit.Assert.assertArrayEquals; 021import static org.junit.Assert.assertEquals; 022import static org.junit.Assert.assertFalse; 023import static org.junit.Assert.assertNotEquals; 024import static org.junit.Assert.assertTrue; 025import static org.junit.Assert.fail; 026 027import java.io.IOException; 028import org.apache.hadoop.fs.FileStatus; 029import org.apache.hadoop.fs.Path; 030import org.apache.hadoop.hbase.HBaseClassTestRule; 031import org.apache.hadoop.hbase.HBaseTestingUtility; 032import org.apache.hadoop.hbase.HRegionInfo; 033import org.apache.hadoop.hbase.HTableDescriptor; 034import org.apache.hadoop.hbase.TableName; 035import org.apache.hadoop.hbase.client.RegionInfoBuilder; 036import org.apache.hadoop.hbase.exceptions.DeserializationException; 037import org.apache.hadoop.hbase.testclassification.RegionServerTests; 038import org.apache.hadoop.hbase.testclassification.SmallTests; 039import org.apache.hadoop.hbase.util.Bytes; 040import org.apache.hadoop.hbase.util.FSTableDescriptors; 041import org.apache.hadoop.hbase.util.MD5Hash; 042import org.junit.ClassRule; 043import org.junit.Rule; 044import org.junit.Test; 045import org.junit.experimental.categories.Category; 046import org.junit.rules.TestName; 047 048import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations; 049 050import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos; 051 052@Category({RegionServerTests.class, SmallTests.class}) 053public class TestHRegionInfo { 054 055 @ClassRule 056 public static final HBaseClassTestRule CLASS_RULE = 057 HBaseClassTestRule.forClass(TestHRegionInfo.class); 058 059 @Rule 060 public TestName name = new TestName(); 061 062 @Test 063 public void testIsStart() { 064 assertTrue(RegionInfoBuilder.FIRST_META_REGIONINFO.isFirst()); 065 org.apache.hadoop.hbase.client.RegionInfo ri = 066 org.apache.hadoop.hbase.client.RegionInfoBuilder.newBuilder(TableName.META_TABLE_NAME). 067 setStartKey(Bytes.toBytes("not_start")).build(); 068 assertFalse(ri.isFirst()); 069 } 070 071 @Test 072 public void testIsEnd() { 073 assertTrue(RegionInfoBuilder.FIRST_META_REGIONINFO.isFirst()); 074 org.apache.hadoop.hbase.client.RegionInfo ri = 075 org.apache.hadoop.hbase.client.RegionInfoBuilder.newBuilder(TableName.META_TABLE_NAME). 076 setEndKey(Bytes.toBytes("not_end")).build(); 077 assertFalse(ri.isLast()); 078 } 079 080 @Test 081 public void testIsNext() { 082 byte [] bytes = Bytes.toBytes("row"); 083 org.apache.hadoop.hbase.client.RegionInfo ri = 084 org.apache.hadoop.hbase.client.RegionInfoBuilder.newBuilder(TableName.META_TABLE_NAME). 085 setEndKey(bytes).build(); 086 org.apache.hadoop.hbase.client.RegionInfo ri2 = 087 org.apache.hadoop.hbase.client.RegionInfoBuilder.newBuilder(TableName.META_TABLE_NAME). 088 setStartKey(bytes).build(); 089 assertFalse(ri.isNext(RegionInfoBuilder.FIRST_META_REGIONINFO)); 090 assertTrue(ri.isNext(ri2)); 091 } 092 093 @Test 094 public void testIsOverlap() { 095 byte [] a = Bytes.toBytes("a"); 096 byte [] b = Bytes.toBytes("b"); 097 byte [] c = Bytes.toBytes("c"); 098 byte [] d = Bytes.toBytes("d"); 099 org.apache.hadoop.hbase.client.RegionInfo all = 100 RegionInfoBuilder.FIRST_META_REGIONINFO; 101 org.apache.hadoop.hbase.client.RegionInfo ari = 102 org.apache.hadoop.hbase.client.RegionInfoBuilder.newBuilder(TableName.META_TABLE_NAME). 103 setEndKey(a).build(); 104 org.apache.hadoop.hbase.client.RegionInfo abri = 105 org.apache.hadoop.hbase.client.RegionInfoBuilder.newBuilder(TableName.META_TABLE_NAME). 106 setStartKey(a).setEndKey(b).build(); 107 org.apache.hadoop.hbase.client.RegionInfo adri = 108 org.apache.hadoop.hbase.client.RegionInfoBuilder.newBuilder(TableName.META_TABLE_NAME). 109 setStartKey(a).setEndKey(d).build(); 110 org.apache.hadoop.hbase.client.RegionInfo cdri = 111 org.apache.hadoop.hbase.client.RegionInfoBuilder.newBuilder(TableName.META_TABLE_NAME). 112 setStartKey(c).setEndKey(d).build(); 113 org.apache.hadoop.hbase.client.RegionInfo dri = 114 org.apache.hadoop.hbase.client.RegionInfoBuilder.newBuilder(TableName.META_TABLE_NAME). 115 setStartKey(d).build(); 116 assertTrue(all.isOverlap(all)); 117 assertTrue(all.isOverlap(abri)); 118 assertFalse(abri.isOverlap(cdri)); 119 assertTrue(all.isOverlap(ari)); 120 assertFalse(ari.isOverlap(abri)); 121 assertFalse(ari.isOverlap(abri)); 122 assertTrue(ari.isOverlap(all)); 123 assertTrue(dri.isOverlap(all)); 124 assertTrue(abri.isOverlap(adri)); 125 assertFalse(dri.isOverlap(ari)); 126 assertTrue(abri.isOverlap(adri)); 127 } 128 129 @Test 130 public void testPb() throws DeserializationException { 131 HRegionInfo hri = HRegionInfo.FIRST_META_REGIONINFO; 132 byte [] bytes = hri.toByteArray(); 133 HRegionInfo pbhri = HRegionInfo.parseFrom(bytes); 134 assertTrue(hri.equals(pbhri)); 135 } 136 137 @Test 138 public void testReadAndWriteHRegionInfoFile() throws IOException, InterruptedException { 139 HBaseTestingUtility htu = new HBaseTestingUtility(); 140 HRegionInfo hri = HRegionInfo.FIRST_META_REGIONINFO; 141 Path basedir = htu.getDataTestDir(); 142 // Create a region. That'll write the .regioninfo file. 143 FSTableDescriptors fsTableDescriptors = new FSTableDescriptors(htu.getConfiguration()); 144 HRegion r = HBaseTestingUtility.createRegionAndWAL(hri, basedir, htu.getConfiguration(), 145 fsTableDescriptors.get(TableName.META_TABLE_NAME)); 146 // Get modtime on the file. 147 long modtime = getModTime(r); 148 HBaseTestingUtility.closeRegionAndWAL(r); 149 Thread.sleep(1001); 150 r = HRegion.openHRegion(basedir, hri, fsTableDescriptors.get(TableName.META_TABLE_NAME), 151 null, htu.getConfiguration()); 152 // Ensure the file is not written for a second time. 153 long modtime2 = getModTime(r); 154 assertEquals(modtime, modtime2); 155 // Now load the file. 156 org.apache.hadoop.hbase.client.RegionInfo deserializedHri = HRegionFileSystem.loadRegionInfoFileContent( 157 r.getRegionFileSystem().getFileSystem(), r.getRegionFileSystem().getRegionDir()); 158 assertTrue(org.apache.hadoop.hbase.client.RegionInfo.COMPARATOR.compare(hri, deserializedHri) == 0); 159 HBaseTestingUtility.closeRegionAndWAL(r); 160 } 161 162 long getModTime(final HRegion r) throws IOException { 163 FileStatus[] statuses = r.getRegionFileSystem().getFileSystem().listStatus( 164 new Path(r.getRegionFileSystem().getRegionDir(), HRegionFileSystem.REGION_INFO_FILE)); 165 assertTrue(statuses != null && statuses.length == 1); 166 return statuses[0].getModificationTime(); 167 } 168 169 @Test 170 public void testCreateHRegionInfoName() throws Exception { 171 final String tableName = name.getMethodName(); 172 final TableName tn = TableName.valueOf(tableName); 173 String startKey = "startkey"; 174 final byte[] sk = Bytes.toBytes(startKey); 175 String id = "id"; 176 177 // old format region name 178 byte [] name = HRegionInfo.createRegionName(tn, sk, id, false); 179 String nameStr = Bytes.toString(name); 180 assertEquals(tableName + "," + startKey + "," + id, nameStr); 181 182 183 // new format region name. 184 String md5HashInHex = MD5Hash.getMD5AsHex(name); 185 assertEquals(HRegionInfo.MD5_HEX_LENGTH, md5HashInHex.length()); 186 name = HRegionInfo.createRegionName(tn, sk, id, true); 187 nameStr = Bytes.toString(name); 188 assertEquals(tableName + "," + startKey + "," 189 + id + "." + md5HashInHex + ".", 190 nameStr); 191 } 192 193 @Test 194 public void testContainsRange() { 195 HTableDescriptor tableDesc = new HTableDescriptor(TableName.valueOf(name.getMethodName())); 196 HRegionInfo hri = new HRegionInfo( 197 tableDesc.getTableName(), Bytes.toBytes("a"), Bytes.toBytes("g")); 198 // Single row range at start of region 199 assertTrue(hri.containsRange(Bytes.toBytes("a"), Bytes.toBytes("a"))); 200 // Fully contained range 201 assertTrue(hri.containsRange(Bytes.toBytes("b"), Bytes.toBytes("c"))); 202 // Range overlapping start of region 203 assertTrue(hri.containsRange(Bytes.toBytes("a"), Bytes.toBytes("c"))); 204 // Fully contained single-row range 205 assertTrue(hri.containsRange(Bytes.toBytes("c"), Bytes.toBytes("c"))); 206 // Range that overlaps end key and hence doesn't fit 207 assertFalse(hri.containsRange(Bytes.toBytes("a"), Bytes.toBytes("g"))); 208 // Single row range on end key 209 assertFalse(hri.containsRange(Bytes.toBytes("g"), Bytes.toBytes("g"))); 210 // Single row range entirely outside 211 assertFalse(hri.containsRange(Bytes.toBytes("z"), Bytes.toBytes("z"))); 212 213 // Degenerate range 214 try { 215 hri.containsRange(Bytes.toBytes("z"), Bytes.toBytes("a")); 216 fail("Invalid range did not throw IAE"); 217 } catch (IllegalArgumentException iae) { 218 } 219 } 220 221 @Test 222 public void testLastRegionCompare() { 223 HTableDescriptor tableDesc = new HTableDescriptor(TableName.valueOf(name.getMethodName())); 224 HRegionInfo hrip = new HRegionInfo( 225 tableDesc.getTableName(), Bytes.toBytes("a"), new byte[0]); 226 HRegionInfo hric = new HRegionInfo( 227 tableDesc.getTableName(), Bytes.toBytes("a"), Bytes.toBytes("b")); 228 assertTrue(hrip.compareTo(hric) > 0); 229 } 230 231 @Test 232 public void testMetaTables() { 233 assertTrue(HRegionInfo.FIRST_META_REGIONINFO.isMetaRegion()); 234 } 235 236 @SuppressWarnings("SelfComparison") 237 @Test 238 public void testComparator() { 239 final TableName tableName = TableName.valueOf(name.getMethodName()); 240 byte[] empty = new byte[0]; 241 HRegionInfo older = new HRegionInfo(tableName, empty, empty, false, 0L); 242 HRegionInfo newer = new HRegionInfo(tableName, empty, empty, false, 1L); 243 assertTrue(older.compareTo(newer) < 0); 244 assertTrue(newer.compareTo(older) > 0); 245 assertEquals(0, older.compareTo(older)); 246 assertEquals(0, newer.compareTo(newer)); 247 248 HRegionInfo a = new HRegionInfo(TableName.valueOf("a"), null, null); 249 HRegionInfo b = new HRegionInfo(TableName.valueOf("b"), null, null); 250 assertNotEquals(0, a.compareTo(b)); 251 HTableDescriptor t = new HTableDescriptor(TableName.valueOf("t")); 252 byte [] midway = Bytes.toBytes("midway"); 253 a = new HRegionInfo(t.getTableName(), null, midway); 254 b = new HRegionInfo(t.getTableName(), midway, null); 255 assertTrue(a.compareTo(b) < 0); 256 assertTrue(b.compareTo(a) > 0); 257 assertEquals(a, a); 258 assertEquals(0, a.compareTo(a)); 259 a = new HRegionInfo(t.getTableName(), Bytes.toBytes("a"), Bytes.toBytes("d")); 260 b = new HRegionInfo(t.getTableName(), Bytes.toBytes("e"), Bytes.toBytes("g")); 261 assertTrue(a.compareTo(b) < 0); 262 a = new HRegionInfo(t.getTableName(), Bytes.toBytes("aaaa"), Bytes.toBytes("dddd")); 263 b = new HRegionInfo(t.getTableName(), Bytes.toBytes("e"), Bytes.toBytes("g")); 264 assertTrue(a.compareTo(b) < 0); 265 a = new HRegionInfo(t.getTableName(), Bytes.toBytes("aaaa"), Bytes.toBytes("dddd")); 266 b = new HRegionInfo(t.getTableName(), Bytes.toBytes("aaaa"), Bytes.toBytes("eeee")); 267 assertTrue(a.compareTo(b) < 0); 268 269 } 270 271 @Test 272 public void testRegionNameForRegionReplicas() throws Exception { 273 String tableName = name.getMethodName(); 274 final TableName tn = TableName.valueOf(tableName); 275 String startKey = "startkey"; 276 final byte[] sk = Bytes.toBytes(startKey); 277 String id = "id"; 278 279 // assert with only the region name without encoding 280 281 // primary, replicaId = 0 282 byte [] name = HRegionInfo.createRegionName(tn, sk, Bytes.toBytes(id), 0, false); 283 String nameStr = Bytes.toString(name); 284 assertEquals(tableName + "," + startKey + "," + id, nameStr); 285 286 // replicaId = 1 287 name = HRegionInfo.createRegionName(tn, sk, Bytes.toBytes(id), 1, false); 288 nameStr = Bytes.toString(name); 289 assertEquals(tableName + "," + startKey + "," + id + "_" + 290 String.format(HRegionInfo.REPLICA_ID_FORMAT, 1), nameStr); 291 292 // replicaId = max 293 name = HRegionInfo.createRegionName(tn, sk, Bytes.toBytes(id), 0xFFFF, false); 294 nameStr = Bytes.toString(name); 295 assertEquals(tableName + "," + startKey + "," + id + "_" + 296 String.format(HRegionInfo.REPLICA_ID_FORMAT, 0xFFFF), nameStr); 297 } 298 299 @Test 300 public void testParseName() throws IOException { 301 final TableName tableName = TableName.valueOf(name.getMethodName()); 302 byte[] startKey = Bytes.toBytes("startKey"); 303 long regionId = System.currentTimeMillis(); 304 int replicaId = 42; 305 306 // test without replicaId 307 byte[] regionName = HRegionInfo.createRegionName(tableName, startKey, regionId, false); 308 309 byte[][] fields = HRegionInfo.parseRegionName(regionName); 310 assertArrayEquals(Bytes.toString(fields[0]),tableName.getName(), fields[0]); 311 assertArrayEquals(Bytes.toString(fields[1]),startKey, fields[1]); 312 assertArrayEquals(Bytes.toString(fields[2]), Bytes.toBytes(Long.toString(regionId)),fields[2]); 313 assertEquals(3, fields.length); 314 315 // test with replicaId 316 regionName = HRegionInfo.createRegionName(tableName, startKey, regionId, 317 replicaId, false); 318 319 fields = HRegionInfo.parseRegionName(regionName); 320 assertArrayEquals(Bytes.toString(fields[0]),tableName.getName(), fields[0]); 321 assertArrayEquals(Bytes.toString(fields[1]),startKey, fields[1]); 322 assertArrayEquals(Bytes.toString(fields[2]), Bytes.toBytes(Long.toString(regionId)),fields[2]); 323 assertArrayEquals(Bytes.toString(fields[3]), Bytes.toBytes( 324 String.format(HRegionInfo.REPLICA_ID_FORMAT, replicaId)), fields[3]); 325 } 326 327 @Test 328 public void testConvert() { 329 final TableName tableName = TableName.valueOf("ns1:" + name.getMethodName()); 330 byte[] startKey = Bytes.toBytes("startKey"); 331 byte[] endKey = Bytes.toBytes("endKey"); 332 boolean split = false; 333 long regionId = System.currentTimeMillis(); 334 int replicaId = 42; 335 336 337 HRegionInfo hri = new HRegionInfo(tableName, startKey, endKey, split, 338 regionId, replicaId); 339 340 // convert two times, compare 341 HRegionInfo convertedHri = HRegionInfo.convert(HRegionInfo.convert(hri)); 342 343 assertEquals(hri, convertedHri); 344 345 // test convert RegionInfo without replicaId 346 HBaseProtos.RegionInfo info = HBaseProtos.RegionInfo.newBuilder() 347 .setTableName(HBaseProtos.TableName.newBuilder() 348 .setQualifier(UnsafeByteOperations.unsafeWrap(tableName.getQualifier())) 349 .setNamespace(UnsafeByteOperations.unsafeWrap(tableName.getNamespace())) 350 .build()) 351 .setStartKey(UnsafeByteOperations.unsafeWrap(startKey)) 352 .setEndKey(UnsafeByteOperations.unsafeWrap(endKey)) 353 .setSplit(split) 354 .setRegionId(regionId) 355 .build(); 356 357 convertedHri = HRegionInfo.convert(info); 358 HRegionInfo expectedHri = new HRegionInfo(tableName, startKey, endKey, split, 359 regionId, 0); // expecting default replicaId 360 361 assertEquals(expectedHri, convertedHri); 362 } 363} 364