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