1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.master.balancer;
19
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertTrue;
22 import static org.mockito.Mockito.mock;
23 import static org.mockito.Mockito.when;
24
25 import java.util.ArrayList;
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Set;
30 import java.util.TreeMap;
31 import java.util.TreeSet;
32
33 import org.apache.commons.lang.ArrayUtils;
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36 import org.apache.hadoop.conf.Configuration;
37 import org.apache.hadoop.hbase.HBaseConfiguration;
38 import org.apache.hadoop.hbase.HRegionInfo;
39 import org.apache.hadoop.hbase.testclassification.MediumTests;
40 import org.apache.hadoop.hbase.ServerName;
41 import org.apache.hadoop.hbase.master.LoadBalancer;
42 import org.apache.hadoop.hbase.master.RegionPlan;
43 import org.apache.hadoop.hbase.master.balancer.BaseLoadBalancer.Cluster;
44 import org.junit.BeforeClass;
45 import org.junit.Test;
46 import org.junit.experimental.categories.Category;
47
48 import com.google.common.collect.Lists;
49
50 @Category(MediumTests.class)
51 public class TestBaseLoadBalancer extends BalancerTestBase {
52
53 private static LoadBalancer loadBalancer;
54 private static final Log LOG = LogFactory.getLog(TestStochasticLoadBalancer.class);
55
56 int[][] regionsAndServersMocks = new int[][] {
57
58 new int[] { 0, 0 }, new int[] { 0, 1 }, new int[] { 1, 1 }, new int[] { 2, 1 },
59 new int[] { 10, 1 }, new int[] { 1, 2 }, new int[] { 2, 2 }, new int[] { 3, 2 },
60 new int[] { 1, 3 }, new int[] { 2, 3 }, new int[] { 3, 3 }, new int[] { 25, 3 },
61 new int[] { 2, 10 }, new int[] { 2, 100 }, new int[] { 12, 10 }, new int[] { 12, 100 }, };
62
63 @BeforeClass
64 public static void beforeAllTests() throws Exception {
65 Configuration conf = HBaseConfiguration.create();
66 loadBalancer = new MockBalancer();
67 loadBalancer.setConf(conf);
68 }
69
70 public static class MockBalancer extends BaseLoadBalancer {
71
72 @Override
73 public List<RegionPlan> balanceCluster(Map<ServerName, List<HRegionInfo>> clusterState) {
74 return null;
75 }
76
77 }
78
79
80
81
82
83
84
85
86 @Test
87 public void testImmediateAssignment() throws Exception {
88 for (int[] mock : regionsAndServersMocks) {
89 LOG.debug("testImmediateAssignment with " + mock[0] + " regions and " + mock[1] + " servers");
90 List<HRegionInfo> regions = randomRegions(mock[0]);
91 List<ServerAndLoad> servers = randomServers(mock[1], 0);
92 List<ServerName> list = getListOfServerNames(servers);
93 Map<HRegionInfo, ServerName> assignments = loadBalancer.immediateAssignment(regions, list);
94 assertImmediateAssignment(regions, list, assignments);
95 returnRegions(regions);
96 returnServers(list);
97 }
98 }
99
100
101
102
103
104
105
106 private void assertImmediateAssignment(List<HRegionInfo> regions, List<ServerName> servers,
107 Map<HRegionInfo, ServerName> assignments) {
108 for (HRegionInfo region : regions) {
109 assertTrue(assignments.containsKey(region));
110 }
111 }
112
113
114
115
116
117
118
119
120
121 @Test
122 public void testBulkAssignment() throws Exception {
123 for (int[] mock : regionsAndServersMocks) {
124 LOG.debug("testBulkAssignment with " + mock[0] + " regions and " + mock[1] + " servers");
125 List<HRegionInfo> regions = randomRegions(mock[0]);
126 List<ServerAndLoad> servers = randomServers(mock[1], 0);
127 List<ServerName> list = getListOfServerNames(servers);
128 Map<ServerName, List<HRegionInfo>> assignments =
129 loadBalancer.roundRobinAssignment(regions, list);
130 float average = (float) regions.size() / servers.size();
131 int min = (int) Math.floor(average);
132 int max = (int) Math.ceil(average);
133 if (assignments != null && !assignments.isEmpty()) {
134 for (List<HRegionInfo> regionList : assignments.values()) {
135 assertTrue(regionList.size() == min || regionList.size() == max);
136 }
137 }
138 returnRegions(regions);
139 returnServers(list);
140 }
141 }
142
143
144
145
146
147
148 @Test
149 public void testRetainAssignment() throws Exception {
150
151 List<ServerAndLoad> servers = randomServers(10, 10);
152 List<HRegionInfo> regions = randomRegions(100);
153 Map<HRegionInfo, ServerName> existing = new TreeMap<HRegionInfo, ServerName>();
154 for (int i = 0; i < regions.size(); i++) {
155 ServerName sn = servers.get(i % servers.size()).getServerName();
156
157
158 ServerName snWithOldStartCode =
159 ServerName.valueOf(sn.getHostname(), sn.getPort(), sn.getStartcode() - 10);
160 existing.put(regions.get(i), snWithOldStartCode);
161 }
162 List<ServerName> listOfServerNames = getListOfServerNames(servers);
163 Map<ServerName, List<HRegionInfo>> assignment =
164 loadBalancer.retainAssignment(existing, listOfServerNames);
165 assertRetainedAssignment(existing, listOfServerNames, assignment);
166
167
168 List<ServerAndLoad> servers2 = new ArrayList<ServerAndLoad>(servers);
169 servers2.add(randomServer(10));
170 servers2.add(randomServer(10));
171 listOfServerNames = getListOfServerNames(servers2);
172 assignment = loadBalancer.retainAssignment(existing, listOfServerNames);
173 assertRetainedAssignment(existing, listOfServerNames, assignment);
174
175
176 List<ServerAndLoad> servers3 = new ArrayList<ServerAndLoad>(servers);
177 servers3.remove(0);
178 servers3.remove(0);
179 listOfServerNames = getListOfServerNames(servers3);
180 assignment = loadBalancer.retainAssignment(existing, listOfServerNames);
181 assertRetainedAssignment(existing, listOfServerNames, assignment);
182 }
183
184 private List<ServerName> getListOfServerNames(final List<ServerAndLoad> sals) {
185 List<ServerName> list = new ArrayList<ServerName>();
186 for (ServerAndLoad e : sals) {
187 list.add(e.getServerName());
188 }
189 return list;
190 }
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205 private void assertRetainedAssignment(Map<HRegionInfo, ServerName> existing,
206 List<ServerName> servers, Map<ServerName, List<HRegionInfo>> assignment) {
207
208 Set<ServerName> onlineServerSet = new TreeSet<ServerName>(servers);
209 Set<HRegionInfo> assignedRegions = new TreeSet<HRegionInfo>();
210 for (Map.Entry<ServerName, List<HRegionInfo>> a : assignment.entrySet()) {
211 assertTrue("Region assigned to server that was not listed as online",
212 onlineServerSet.contains(a.getKey()));
213 for (HRegionInfo r : a.getValue())
214 assignedRegions.add(r);
215 }
216 assertEquals(existing.size(), assignedRegions.size());
217
218
219 Set<String> onlineHostNames = new TreeSet<String>();
220 for (ServerName s : servers) {
221 onlineHostNames.add(s.getHostname());
222 }
223
224 for (Map.Entry<ServerName, List<HRegionInfo>> a : assignment.entrySet()) {
225 ServerName assignedTo = a.getKey();
226 for (HRegionInfo r : a.getValue()) {
227 ServerName address = existing.get(r);
228 if (address != null && onlineHostNames.contains(address.getHostname())) {
229
230
231
232 assertEquals(address.getHostname(), assignedTo.getHostname());
233 }
234 }
235 }
236 }
237
238 @Test
239 public void testClusterServersWithSameHostPort() {
240
241
242 List<ServerName> servers = getListOfServerNames(randomServers(10, 10));
243 List<HRegionInfo> regions = randomRegions(101);
244 Map<ServerName, List<HRegionInfo>> clusterState = new HashMap<ServerName, List<HRegionInfo>>();
245
246 assignRegions(regions, servers, clusterState);
247
248
249 List<ServerName> oldServers = new ArrayList<ServerName>(servers.size());
250 for (ServerName sn : servers) {
251
252 oldServers.add(ServerName.valueOf(sn.getHostname(), sn.getPort(), sn.getStartcode() - 10));
253 }
254
255 regions = randomRegions(9);
256 assignRegions(regions, oldServers, clusterState);
257
258
259 BaseLoadBalancer.Cluster cluster = new Cluster(clusterState, null, null);
260 assertEquals(101 + 9, cluster.numRegions);
261 assertEquals(10, cluster.numServers);
262 }
263
264 private void assignRegions(List<HRegionInfo> regions, List<ServerName> servers,
265 Map<ServerName, List<HRegionInfo>> clusterState) {
266 for (int i = 0; i < regions.size(); i++) {
267 ServerName sn = servers.get(i % servers.size());
268 List<HRegionInfo> regionsOfServer = clusterState.get(sn);
269 if (regionsOfServer == null) {
270 regionsOfServer = new ArrayList<HRegionInfo>(10);
271 clusterState.put(sn, regionsOfServer);
272 }
273
274 regionsOfServer.add(regions.get(i));
275 }
276 }
277
278 @Test
279 public void testClusterRegionLocations() {
280
281 List<ServerName> servers = getListOfServerNames(randomServers(10, 10));
282 List<HRegionInfo> regions = randomRegions(101);
283 Map<ServerName, List<HRegionInfo>> clusterState = new HashMap<ServerName, List<HRegionInfo>>();
284
285 assignRegions(regions, servers, clusterState);
286
287
288 RegionLocationFinder locationFinder = mock(RegionLocationFinder.class);
289
290
291
292 when(locationFinder.getTopBlockLocations(regions.get(0))).thenReturn(
293 Lists.newArrayList(servers.get(0)));
294 when(locationFinder.getTopBlockLocations(regions.get(1))).thenReturn(
295 Lists.newArrayList(servers.get(0), servers.get(1)));
296 when(locationFinder.getTopBlockLocations(regions.get(42))).thenReturn(
297 Lists.newArrayList(servers.get(4), servers.get(9), servers.get(5)));
298 when(locationFinder.getTopBlockLocations(regions.get(43))).thenReturn(
299 Lists.newArrayList(ServerName.valueOf("foo", 0, 0)));
300
301 BaseLoadBalancer.Cluster cluster = new Cluster(clusterState, null, locationFinder);
302
303 int r0 = ArrayUtils.indexOf(cluster.regions, regions.get(0));
304 int r1 = ArrayUtils.indexOf(cluster.regions, regions.get(1));
305 int r10 = ArrayUtils.indexOf(cluster.regions, regions.get(10));
306 int r42 = ArrayUtils.indexOf(cluster.regions, regions.get(42));
307 int r43 = ArrayUtils.indexOf(cluster.regions, regions.get(43));
308
309 int s0 = cluster.serversToIndex.get(servers.get(0).getHostAndPort());
310 int s1 = cluster.serversToIndex.get(servers.get(1).getHostAndPort());
311 int s4 = cluster.serversToIndex.get(servers.get(4).getHostAndPort());
312 int s5 = cluster.serversToIndex.get(servers.get(5).getHostAndPort());
313 int s9 = cluster.serversToIndex.get(servers.get(9).getHostAndPort());
314
315
316 assertEquals(1, cluster.regionLocations[r0].length);
317 assertEquals(s0, cluster.regionLocations[r0][0]);
318
319
320 assertEquals(2, cluster.regionLocations[r1].length);
321 assertEquals(s0, cluster.regionLocations[r1][0]);
322 assertEquals(s1, cluster.regionLocations[r1][1]);
323
324
325 assertEquals(0, cluster.regionLocations[r10].length);
326
327
328 assertEquals(3, cluster.regionLocations[r42].length);
329 assertEquals(s4, cluster.regionLocations[r42][0]);
330 assertEquals(s9, cluster.regionLocations[r42][1]);
331 assertEquals(s5, cluster.regionLocations[r42][2]);
332
333
334 assertEquals(1, cluster.regionLocations[r43].length);
335 assertEquals(-1, cluster.regionLocations[r43][0]);
336 }
337
338 }