1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.master.normalizer;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.apache.hadoop.hbase.HBaseIOException;
24 import org.apache.hadoop.hbase.HRegionInfo;
25 import org.apache.hadoop.hbase.RegionLoad;
26 import org.apache.hadoop.hbase.ServerName;
27 import org.apache.hadoop.hbase.TableName;
28 import org.apache.hadoop.hbase.master.MasterServices;
29 import org.apache.hadoop.hbase.testclassification.SmallTests;
30 import org.apache.hadoop.hbase.util.Bytes;
31 import org.junit.BeforeClass;
32 import org.junit.Test;
33 import org.junit.experimental.categories.Category;
34 import org.mockito.Mockito;
35
36 import java.util.ArrayList;
37 import java.util.HashMap;
38 import java.util.List;
39 import java.util.Map;
40
41 import static org.junit.Assert.assertEquals;
42 import static org.junit.Assert.assertTrue;
43 import static org.mockito.Matchers.any;
44 import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
45 import static org.mockito.Mockito.when;
46
47
48
49
50 @Category(SmallTests.class)
51 public class TestSimpleRegionNormalizer {
52 private static final Log LOG = LogFactory.getLog(TestSimpleRegionNormalizer.class);
53
54 private static RegionNormalizer normalizer;
55
56
57 private static MasterServices masterServices;
58
59 @BeforeClass
60 public static void beforeAllTests() throws Exception {
61 normalizer = new SimpleRegionNormalizer();
62 }
63
64 @Test
65 public void testNoNormalizationForMetaTable() throws HBaseIOException {
66 TableName testTable = TableName.META_TABLE_NAME;
67 List<HRegionInfo> hris = new ArrayList<>();
68 Map<byte[], Integer> regionSizes = new HashMap<>();
69
70 setupMocksForNormalizer(regionSizes, hris);
71 List<NormalizationPlan> plans = normalizer.computePlanForTable(testTable);
72 assertTrue(plans == null);
73 }
74
75 @Test
76 public void testNoNormalizationIfTooFewRegions() throws HBaseIOException {
77 TableName testTable = TableName.valueOf("testSplitOfSmallRegion");
78 List<HRegionInfo> hris = new ArrayList<>();
79 Map<byte[], Integer> regionSizes = new HashMap<>();
80
81 HRegionInfo hri1 = new HRegionInfo(testTable, Bytes.toBytes("aaa"), Bytes.toBytes("bbb"));
82 hris.add(hri1);
83 regionSizes.put(hri1.getRegionName(), 10);
84
85 HRegionInfo hri2 = new HRegionInfo(testTable, Bytes.toBytes("bbb"), Bytes.toBytes("ccc"));
86 hris.add(hri2);
87 regionSizes.put(hri2.getRegionName(), 15);
88
89 setupMocksForNormalizer(regionSizes, hris);
90 List<NormalizationPlan> plans = normalizer.computePlanForTable(testTable);
91 assertTrue(plans == null);
92 }
93
94 @Test
95 public void testNoNormalizationOnNormalizedCluster() throws HBaseIOException {
96 TableName testTable = TableName.valueOf("testSplitOfSmallRegion");
97 List<HRegionInfo> hris = new ArrayList<>();
98 Map<byte[], Integer> regionSizes = new HashMap<>();
99
100 HRegionInfo hri1 = new HRegionInfo(testTable, Bytes.toBytes("aaa"), Bytes.toBytes("bbb"));
101 hris.add(hri1);
102 regionSizes.put(hri1.getRegionName(), 10);
103
104 HRegionInfo hri2 = new HRegionInfo(testTable, Bytes.toBytes("bbb"), Bytes.toBytes("ccc"));
105 hris.add(hri2);
106 regionSizes.put(hri2.getRegionName(), 15);
107
108 HRegionInfo hri3 = new HRegionInfo(testTable, Bytes.toBytes("ccc"), Bytes.toBytes("ddd"));
109 hris.add(hri3);
110 regionSizes.put(hri3.getRegionName(), 8);
111
112 HRegionInfo hri4 = new HRegionInfo(testTable, Bytes.toBytes("ddd"), Bytes.toBytes("eee"));
113 hris.add(hri4);
114 regionSizes.put(hri4.getRegionName(), 10);
115
116 setupMocksForNormalizer(regionSizes, hris);
117 List<NormalizationPlan> plans = normalizer.computePlanForTable(testTable);
118 assertTrue(plans == null);
119 }
120
121 @Test
122 public void testMergeOfSmallRegions() throws HBaseIOException {
123 TableName testTable = TableName.valueOf("testMergeOfSmallRegions");
124 List<HRegionInfo> hris = new ArrayList<>();
125 Map<byte[], Integer> regionSizes = new HashMap<>();
126
127 HRegionInfo hri1 = new HRegionInfo(testTable, Bytes.toBytes("aaa"), Bytes.toBytes("bbb"));
128 hris.add(hri1);
129 regionSizes.put(hri1.getRegionName(), 15);
130
131 HRegionInfo hri2 = new HRegionInfo(testTable, Bytes.toBytes("bbb"), Bytes.toBytes("ccc"));
132 hris.add(hri2);
133 regionSizes.put(hri2.getRegionName(), 5);
134
135 HRegionInfo hri3 = new HRegionInfo(testTable, Bytes.toBytes("ccc"), Bytes.toBytes("ddd"));
136 hris.add(hri3);
137 regionSizes.put(hri3.getRegionName(), 5);
138
139 HRegionInfo hri4 = new HRegionInfo(testTable, Bytes.toBytes("ddd"), Bytes.toBytes("eee"));
140 hris.add(hri4);
141 regionSizes.put(hri4.getRegionName(), 15);
142
143 HRegionInfo hri5 = new HRegionInfo(testTable, Bytes.toBytes("eee"), Bytes.toBytes("fff"));
144 hris.add(hri5);
145 regionSizes.put(hri5.getRegionName(), 16);
146
147 setupMocksForNormalizer(regionSizes, hris);
148 List<NormalizationPlan> plans = normalizer.computePlanForTable(testTable);
149
150 NormalizationPlan plan = plans.get(0);
151 assertTrue(plan instanceof MergeNormalizationPlan);
152 assertEquals(hri2, ((MergeNormalizationPlan) plan).getFirstRegion());
153 assertEquals(hri3, ((MergeNormalizationPlan) plan).getSecondRegion());
154 }
155
156
157 @Test
158 public void testMergeOfSecondSmallestRegions() throws HBaseIOException {
159 TableName testTable = TableName.valueOf("testMergeOfSmallRegions");
160 List<HRegionInfo> hris = new ArrayList<>();
161 Map<byte[], Integer> regionSizes = new HashMap<>();
162
163 HRegionInfo hri1 = new HRegionInfo(testTable, Bytes.toBytes("aaa"), Bytes.toBytes("bbb"));
164 hris.add(hri1);
165 regionSizes.put(hri1.getRegionName(), 1);
166
167 HRegionInfo hri2 = new HRegionInfo(testTable, Bytes.toBytes("bbb"), Bytes.toBytes("ccc"));
168 hris.add(hri2);
169 regionSizes.put(hri2.getRegionName(), 10000);
170
171 HRegionInfo hri3 = new HRegionInfo(testTable, Bytes.toBytes("ccc"), Bytes.toBytes("ddd"));
172 hris.add(hri3);
173 regionSizes.put(hri3.getRegionName(), 10000);
174
175 HRegionInfo hri4 = new HRegionInfo(testTable, Bytes.toBytes("ddd"), Bytes.toBytes("eee"));
176 hris.add(hri4);
177 regionSizes.put(hri4.getRegionName(), 10000);
178
179 HRegionInfo hri5 = new HRegionInfo(testTable, Bytes.toBytes("eee"), Bytes.toBytes("fff"));
180 hris.add(hri5);
181 regionSizes.put(hri5.getRegionName(), 2700);
182
183 HRegionInfo hri6 = new HRegionInfo(testTable, Bytes.toBytes("fff"), Bytes.toBytes("ggg"));
184 hris.add(hri6);
185 regionSizes.put(hri6.getRegionName(), 2700);
186
187 setupMocksForNormalizer(regionSizes, hris);
188 List<NormalizationPlan> plans = normalizer.computePlanForTable(testTable);
189 NormalizationPlan plan = plans.get(0);
190
191 assertTrue(plan instanceof MergeNormalizationPlan);
192 assertEquals(hri5, ((MergeNormalizationPlan) plan).getFirstRegion());
193 assertEquals(hri6, ((MergeNormalizationPlan) plan).getSecondRegion());
194 }
195
196 @Test
197 public void testMergeOfSmallNonAdjacentRegions() throws HBaseIOException {
198 TableName testTable = TableName.valueOf("testMergeOfSmallRegions");
199 List<HRegionInfo> hris = new ArrayList<>();
200 Map<byte[], Integer> regionSizes = new HashMap<>();
201
202 HRegionInfo hri1 = new HRegionInfo(testTable, Bytes.toBytes("aaa"), Bytes.toBytes("bbb"));
203 hris.add(hri1);
204 regionSizes.put(hri1.getRegionName(), 15);
205
206 HRegionInfo hri2 = new HRegionInfo(testTable, Bytes.toBytes("bbb"), Bytes.toBytes("ccc"));
207 hris.add(hri2);
208 regionSizes.put(hri2.getRegionName(), 5);
209
210 HRegionInfo hri3 = new HRegionInfo(testTable, Bytes.toBytes("ccc"), Bytes.toBytes("ddd"));
211 hris.add(hri3);
212 regionSizes.put(hri3.getRegionName(), 16);
213
214 HRegionInfo hri4 = new HRegionInfo(testTable, Bytes.toBytes("ddd"), Bytes.toBytes("eee"));
215 hris.add(hri4);
216 regionSizes.put(hri4.getRegionName(), 15);
217
218 HRegionInfo hri5 = new HRegionInfo(testTable, Bytes.toBytes("ddd"), Bytes.toBytes("eee"));
219 hris.add(hri4);
220 regionSizes.put(hri5.getRegionName(), 5);
221
222 setupMocksForNormalizer(regionSizes, hris);
223 List<NormalizationPlan> plans = normalizer.computePlanForTable(testTable);
224
225 assertTrue(plans == null);
226 }
227
228 @Test
229 public void testSplitOfLargeRegion() throws HBaseIOException {
230 TableName testTable = TableName.valueOf("testSplitOfLargeRegion");
231 List<HRegionInfo> hris = new ArrayList<>();
232 Map<byte[], Integer> regionSizes = new HashMap<>();
233
234 HRegionInfo hri1 = new HRegionInfo(testTable, Bytes.toBytes("aaa"), Bytes.toBytes("bbb"));
235 hris.add(hri1);
236 regionSizes.put(hri1.getRegionName(), 8);
237
238 HRegionInfo hri2 = new HRegionInfo(testTable, Bytes.toBytes("bbb"), Bytes.toBytes("ccc"));
239 hris.add(hri2);
240 regionSizes.put(hri2.getRegionName(), 6);
241
242 HRegionInfo hri3 = new HRegionInfo(testTable, Bytes.toBytes("ccc"), Bytes.toBytes("ddd"));
243 hris.add(hri3);
244 regionSizes.put(hri3.getRegionName(), 10);
245
246 HRegionInfo hri4 = new HRegionInfo(testTable, Bytes.toBytes("ddd"), Bytes.toBytes("eee"));
247 hris.add(hri4);
248 regionSizes.put(hri4.getRegionName(), 30);
249
250 setupMocksForNormalizer(regionSizes, hris);
251 List<NormalizationPlan> plans = normalizer.computePlanForTable(testTable);
252 NormalizationPlan plan = plans.get(0);
253
254 assertTrue(plan instanceof SplitNormalizationPlan);
255 assertEquals(hri4, ((SplitNormalizationPlan) plan).getRegionInfo());
256 }
257
258 protected void setupMocksForNormalizer(Map<byte[], Integer> regionSizes,
259 List<HRegionInfo> hris) {
260 masterServices = Mockito.mock(MasterServices.class, RETURNS_DEEP_STUBS);
261
262
263 ServerName sn = ServerName.valueOf("localhost", -1, 1L);
264 when(masterServices.getAssignmentManager().getRegionStates().
265 getRegionsOfTable(any(TableName.class))).thenReturn(hris);
266 when(masterServices.getAssignmentManager().getRegionStates().
267 getRegionServerOfRegion(any(HRegionInfo.class))).thenReturn(sn);
268
269 for (Map.Entry<byte[], Integer> region : regionSizes.entrySet()) {
270 RegionLoad regionLoad = Mockito.mock(RegionLoad.class);
271 when(regionLoad.getName()).thenReturn(region.getKey());
272 when(regionLoad.getStorefileSizeMB()).thenReturn(region.getValue());
273
274 when(masterServices.getServerManager().getLoad(sn).
275 getRegionsLoad().get(region.getKey())).thenReturn(regionLoad);
276 }
277
278 normalizer.setMasterServices(masterServices);
279 }
280 }