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.balancer;
20
21 import static org.junit.Assert.assertFalse;
22 import static org.junit.Assert.assertTrue;
23
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.SortedMap;
29 import java.util.TreeMap;
30
31 import org.apache.hadoop.conf.Configuration;
32 import org.apache.hadoop.hbase.TableName;
33 import org.apache.hadoop.hbase.HRegionInfo;
34 import org.apache.hadoop.hbase.SmallTests;
35 import org.apache.hadoop.hbase.ServerName;
36 import org.apache.hadoop.hbase.master.RackManager;
37 import org.apache.hadoop.hbase.util.Bytes;
38 import org.apache.hadoop.hbase.util.Triple;
39 import org.junit.BeforeClass;
40 import org.junit.Test;
41 import org.junit.experimental.categories.Category;
42 import org.mockito.Mockito;
43
44 @Category(SmallTests.class)
45 public class TestFavoredNodeAssignmentHelper {
46
47 private static List<ServerName> servers = new ArrayList<ServerName>();
48 private static Map<String, List<ServerName>> rackToServers = new HashMap<String,
49 List<ServerName>>();
50 private static RackManager rackManager = Mockito.mock(RackManager.class);
51
52 @BeforeClass
53 public static void setupBeforeClass() throws Exception {
54
55
56 for (int i = 0; i < 40; i++) {
57 ServerName server = ServerName.valueOf("foo" + i + ":1234", -1);
58 if (i < 10) {
59 Mockito.when(rackManager.getRack(server)).thenReturn("rack1");
60 if (rackToServers.get("rack1") == null) {
61 List<ServerName> servers = new ArrayList<ServerName>();
62 rackToServers.put("rack1", servers);
63 }
64 rackToServers.get("rack1").add(server);
65 }
66 if (i >= 10 && i < 20) {
67 Mockito.when(rackManager.getRack(server)).thenReturn("rack2");
68 if (rackToServers.get("rack2") == null) {
69 List<ServerName> servers = new ArrayList<ServerName>();
70 rackToServers.put("rack2", servers);
71 }
72 rackToServers.get("rack2").add(server);
73 }
74 if (i >= 20 && i < 30) {
75 Mockito.when(rackManager.getRack(server)).thenReturn("rack3");
76 if (rackToServers.get("rack3") == null) {
77 List<ServerName> servers = new ArrayList<ServerName>();
78 rackToServers.put("rack3", servers);
79 }
80 rackToServers.get("rack3").add(server);
81 }
82 servers.add(server);
83 }
84 }
85
86
87
88
89 private static List<ServerName> getServersFromRack(Map<String, Integer> rackToServerCount) {
90 List<ServerName> chosenServers = new ArrayList<ServerName>();
91 for (Map.Entry<String, Integer> entry : rackToServerCount.entrySet()) {
92 List<ServerName> servers = rackToServers.get(entry.getKey());
93 for (int i = 0; i < entry.getValue(); i++) {
94 chosenServers.add(servers.get(i));
95 }
96 }
97 return chosenServers;
98 }
99
100 @Test
101 public void testSmallCluster() {
102
103
104 Map<String,Integer> rackToServerCount = new HashMap<String,Integer>();
105 rackToServerCount.put("rack1", 2);
106 List<ServerName> servers = getServersFromRack(rackToServerCount);
107 FavoredNodeAssignmentHelper helper = new FavoredNodeAssignmentHelper(servers,
108 new Configuration());
109 assertFalse(helper.canPlaceFavoredNodes());
110 }
111
112 @Test
113 public void testPlacePrimaryRSAsRoundRobin() {
114
115
116 primaryRSPlacement(6, null, 10, 10, 10);
117
118 primaryRSPlacement(600, null, 10, 10, 10);
119 }
120
121 @Test
122 public void testRoundRobinAssignmentsWithUnevenSizedRacks() {
123
124
125 primaryRSPlacement(6, null, 10, 10, 10);
126 primaryRSPlacement(600, null, 10, 10, 5);
127 primaryRSPlacement(600, null, 10, 5, 10);
128 primaryRSPlacement(600, null, 5, 10, 10);
129 primaryRSPlacement(500, null, 10, 10, 5);
130 primaryRSPlacement(500, null, 10, 5, 10);
131 primaryRSPlacement(500, null, 5, 10, 10);
132 primaryRSPlacement(500, null, 9, 7, 8);
133 primaryRSPlacement(500, null, 8, 7, 9);
134 primaryRSPlacement(500, null, 7, 9, 8);
135 primaryRSPlacement(459, null, 7, 9, 8);
136 }
137
138 @Test
139 public void testSecondaryAndTertiaryPlacementWithSingleRack() {
140
141
142 Map<String,Integer> rackToServerCount = new HashMap<String,Integer>();
143 rackToServerCount.put("rack1", 10);
144
145 Triple<Map<HRegionInfo, ServerName>, FavoredNodeAssignmentHelper, List<HRegionInfo>>
146 primaryRSMapAndHelper = secondaryAndTertiaryRSPlacementHelper(60000, rackToServerCount);
147 FavoredNodeAssignmentHelper helper = primaryRSMapAndHelper.getSecond();
148 Map<HRegionInfo, ServerName> primaryRSMap = primaryRSMapAndHelper.getFirst();
149 List<HRegionInfo> regions = primaryRSMapAndHelper.getThird();
150 Map<HRegionInfo, ServerName[]> secondaryAndTertiaryMap =
151 helper.placeSecondaryAndTertiaryRS(primaryRSMap);
152
153
154 for (HRegionInfo region : regions) {
155 ServerName[] secondaryAndTertiaryServers = secondaryAndTertiaryMap.get(region);
156 assertTrue(!secondaryAndTertiaryServers[0].equals(primaryRSMap.get(region)));
157 assertTrue(!secondaryAndTertiaryServers[1].equals(primaryRSMap.get(region)));
158 assertTrue(!secondaryAndTertiaryServers[0].equals(secondaryAndTertiaryServers[1]));
159 }
160 }
161
162 @Test
163 public void testSecondaryAndTertiaryPlacementWithSingleServer() {
164
165
166 Map<String,Integer> rackToServerCount = new HashMap<String,Integer>();
167 rackToServerCount.put("rack1", 1);
168 Triple<Map<HRegionInfo, ServerName>, FavoredNodeAssignmentHelper, List<HRegionInfo>>
169 primaryRSMapAndHelper = secondaryAndTertiaryRSPlacementHelper(1, rackToServerCount);
170 FavoredNodeAssignmentHelper helper = primaryRSMapAndHelper.getSecond();
171 Map<HRegionInfo, ServerName> primaryRSMap = primaryRSMapAndHelper.getFirst();
172 List<HRegionInfo> regions = primaryRSMapAndHelper.getThird();
173
174 Map<HRegionInfo, ServerName[]> secondaryAndTertiaryMap =
175 helper.placeSecondaryAndTertiaryRS(primaryRSMap);
176
177 assertTrue(secondaryAndTertiaryMap.get(regions.get(0)) == null);
178 }
179
180 @Test
181 public void testSecondaryAndTertiaryPlacementWithMultipleRacks() {
182
183
184 Map<String,Integer> rackToServerCount = new HashMap<String,Integer>();
185 rackToServerCount.put("rack1", 10);
186 rackToServerCount.put("rack2", 10);
187
188 Triple<Map<HRegionInfo, ServerName>, FavoredNodeAssignmentHelper, List<HRegionInfo>>
189 primaryRSMapAndHelper = secondaryAndTertiaryRSPlacementHelper(60000, rackToServerCount);
190 FavoredNodeAssignmentHelper helper = primaryRSMapAndHelper.getSecond();
191 Map<HRegionInfo, ServerName> primaryRSMap = primaryRSMapAndHelper.getFirst();
192
193 assertTrue(primaryRSMap.size() == 60000);
194 Map<HRegionInfo, ServerName[]> secondaryAndTertiaryMap =
195 helper.placeSecondaryAndTertiaryRS(primaryRSMap);
196 assertTrue(secondaryAndTertiaryMap.size() == 60000);
197
198
199 for (Map.Entry<HRegionInfo, ServerName[]> entry : secondaryAndTertiaryMap.entrySet()) {
200 ServerName[] allServersForRegion = entry.getValue();
201 String primaryRSRack = rackManager.getRack(primaryRSMap.get(entry.getKey()));
202 String secondaryRSRack = rackManager.getRack(allServersForRegion[0]);
203 String tertiaryRSRack = rackManager.getRack(allServersForRegion[1]);
204 assertTrue(!primaryRSRack.equals(secondaryRSRack));
205 assertTrue(secondaryRSRack.equals(tertiaryRSRack));
206 }
207 }
208
209 @Test
210 public void testSecondaryAndTertiaryPlacementWithLessThanTwoServersInRacks() {
211
212
213 Map<String,Integer> rackToServerCount = new HashMap<String,Integer>();
214 rackToServerCount.put("rack1", 1);
215 rackToServerCount.put("rack2", 1);
216 Triple<Map<HRegionInfo, ServerName>, FavoredNodeAssignmentHelper, List<HRegionInfo>>
217 primaryRSMapAndHelper = secondaryAndTertiaryRSPlacementHelper(6, rackToServerCount);
218 FavoredNodeAssignmentHelper helper = primaryRSMapAndHelper.getSecond();
219 Map<HRegionInfo, ServerName> primaryRSMap = primaryRSMapAndHelper.getFirst();
220 List<HRegionInfo> regions = primaryRSMapAndHelper.getThird();
221 assertTrue(primaryRSMap.size() == 6);
222 Map<HRegionInfo, ServerName[]> secondaryAndTertiaryMap =
223 helper.placeSecondaryAndTertiaryRS(primaryRSMap);
224 for (HRegionInfo region : regions) {
225
226 assertTrue(secondaryAndTertiaryMap.get(region) == null);
227 }
228 }
229
230 @Test
231 public void testSecondaryAndTertiaryPlacementWithMoreThanOneServerInPrimaryRack() {
232
233
234
235
236
237 Map<String,Integer> rackToServerCount = new HashMap<String,Integer>();
238 rackToServerCount.put("rack1", 2);
239 rackToServerCount.put("rack2", 1);
240 Triple<Map<HRegionInfo, ServerName>, FavoredNodeAssignmentHelper, List<HRegionInfo>>
241 primaryRSMapAndHelper = secondaryAndTertiaryRSPlacementHelper(6, rackToServerCount);
242 FavoredNodeAssignmentHelper helper = primaryRSMapAndHelper.getSecond();
243 Map<HRegionInfo, ServerName> primaryRSMap = primaryRSMapAndHelper.getFirst();
244 List<HRegionInfo> regions = primaryRSMapAndHelper.getThird();
245 assertTrue(primaryRSMap.size() == 6);
246 Map<HRegionInfo, ServerName[]> secondaryAndTertiaryMap =
247 helper.placeSecondaryAndTertiaryRS(primaryRSMap);
248 for (HRegionInfo region : regions) {
249 ServerName s = primaryRSMap.get(region);
250 ServerName secondaryRS = secondaryAndTertiaryMap.get(region)[0];
251 ServerName tertiaryRS = secondaryAndTertiaryMap.get(region)[1];
252 if (rackManager.getRack(s).equals("rack1")) {
253 assertTrue(rackManager.getRack(secondaryRS).equals("rack2") &&
254 rackManager.getRack(tertiaryRS).equals("rack1"));
255 }
256 if (rackManager.getRack(s).equals("rack2")) {
257 assertTrue(rackManager.getRack(secondaryRS).equals("rack1") &&
258 rackManager.getRack(tertiaryRS).equals("rack1"));
259 }
260 }
261 }
262
263 private Triple<Map<HRegionInfo, ServerName>, FavoredNodeAssignmentHelper, List<HRegionInfo>>
264 secondaryAndTertiaryRSPlacementHelper(
265 int regionCount, Map<String, Integer> rackToServerCount) {
266 Map<HRegionInfo, ServerName> primaryRSMap = new HashMap<HRegionInfo, ServerName>();
267 List<ServerName> servers = getServersFromRack(rackToServerCount);
268 FavoredNodeAssignmentHelper helper = new FavoredNodeAssignmentHelper(servers, rackManager);
269 Map<ServerName, List<HRegionInfo>> assignmentMap =
270 new HashMap<ServerName, List<HRegionInfo>>();
271 helper.initialize();
272
273 List<HRegionInfo> regions = new ArrayList<HRegionInfo>(regionCount);
274 for (int i = 0; i < regionCount; i++) {
275 HRegionInfo region = new HRegionInfo(TableName.valueOf("foobar"),
276 Bytes.toBytes(i), Bytes.toBytes(i + 1));
277 regions.add(region);
278 }
279
280 helper.placePrimaryRSAsRoundRobin(assignmentMap, primaryRSMap, regions);
281 return new Triple<Map<HRegionInfo, ServerName>, FavoredNodeAssignmentHelper, List<HRegionInfo>>
282 (primaryRSMap, helper, regions);
283 }
284
285 private void primaryRSPlacement(int regionCount, Map<HRegionInfo, ServerName> primaryRSMap,
286 int firstRackSize, int secondRackSize, int thirdRackSize) {
287 Map<String,Integer> rackToServerCount = new HashMap<String,Integer>();
288 rackToServerCount.put("rack1", firstRackSize);
289 rackToServerCount.put("rack2", secondRackSize);
290 rackToServerCount.put("rack3", thirdRackSize);
291 List<ServerName> servers = getServersFromRack(rackToServerCount);
292 FavoredNodeAssignmentHelper helper = new FavoredNodeAssignmentHelper(servers,
293 rackManager);
294 helper.initialize();
295
296 assertTrue(helper.canPlaceFavoredNodes());
297
298 Map<ServerName, List<HRegionInfo>> assignmentMap =
299 new HashMap<ServerName, List<HRegionInfo>>();
300 if (primaryRSMap == null) primaryRSMap = new HashMap<HRegionInfo, ServerName>();
301
302 List<HRegionInfo> regions = new ArrayList<HRegionInfo>(regionCount);
303 for (int i = 0; i < regionCount; i++) {
304 HRegionInfo region = new HRegionInfo(TableName.valueOf("foobar"),
305 Bytes.toBytes(i), Bytes.toBytes(i + 1));
306 regions.add(region);
307 }
308
309 helper.placePrimaryRSAsRoundRobin(assignmentMap, primaryRSMap, regions);
310
311
312 int regionsOnRack1 = 0;
313 int regionsOnRack2 = 0;
314 int regionsOnRack3 = 0;
315 for (HRegionInfo region : regions) {
316 if (rackManager.getRack(primaryRSMap.get(region)).equals("rack1")) {
317 regionsOnRack1++;
318 } else if (rackManager.getRack(primaryRSMap.get(region)).equals("rack2")) {
319 regionsOnRack2++;
320 } else if (rackManager.getRack(primaryRSMap.get(region)).equals("rack3")) {
321 regionsOnRack3++;
322 }
323 }
324
325
326 checkNumRegions(regionCount, firstRackSize, secondRackSize, thirdRackSize, regionsOnRack1,
327 regionsOnRack2, regionsOnRack3, assignmentMap);
328 }
329
330 private void checkNumRegions(int regionCount, int firstRackSize, int secondRackSize,
331 int thirdRackSize, int regionsOnRack1, int regionsOnRack2, int regionsOnRack3,
332 Map<ServerName, List<HRegionInfo>> assignmentMap) {
333
334
335
336
337 SortedMap<Integer, Integer> rackMap = new TreeMap<Integer, Integer>();
338 rackMap.put(firstRackSize, 1);
339 rackMap.put(secondRackSize, 2);
340 rackMap.put(thirdRackSize, 3);
341 SortedMap<Integer, Integer> regionMap = new TreeMap<Integer, Integer>();
342 regionMap.put(regionsOnRack1, 1);
343 regionMap.put(regionsOnRack2, 2);
344 regionMap.put(regionsOnRack3, 3);
345 assertTrue(printProportions(firstRackSize, secondRackSize, thirdRackSize,
346 regionsOnRack1, regionsOnRack2, regionsOnRack3),
347 rackMap.get(firstRackSize) == regionMap.get(regionsOnRack1));
348 assertTrue(printProportions(firstRackSize, secondRackSize, thirdRackSize,
349 regionsOnRack1, regionsOnRack2, regionsOnRack3),
350 rackMap.get(secondRackSize) == regionMap.get(regionsOnRack2));
351 assertTrue(printProportions(firstRackSize, secondRackSize, thirdRackSize,
352 regionsOnRack1, regionsOnRack2, regionsOnRack3),
353 rackMap.get(thirdRackSize) == regionMap.get(regionsOnRack3));
354 }
355
356 private String printProportions(int firstRackSize, int secondRackSize,
357 int thirdRackSize, int regionsOnRack1, int regionsOnRack2, int regionsOnRack3) {
358 return "The rack sizes " + firstRackSize + " " + secondRackSize
359 + " " + thirdRackSize + " " + regionsOnRack1 + " " + regionsOnRack2 +
360 " " + regionsOnRack3;
361 }
362 }