View Javadoc

1   /**
2    * Copyright The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  package org.apache.hadoop.hbase.rsgroup;
21  
22  import static org.junit.Assert.assertEquals;
23  import static org.junit.Assert.assertFalse;
24  import static org.junit.Assert.assertTrue;
25  
26  import java.io.IOException;
27  import java.util.List;
28  import java.util.Map;
29  
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  import org.apache.hadoop.hbase.HColumnDescriptor;
33  import org.apache.hadoop.hbase.HRegionInfo;
34  import org.apache.hadoop.hbase.HTableDescriptor;
35  import org.apache.hadoop.hbase.NamespaceDescriptor;
36  import org.apache.hadoop.hbase.ServerName;
37  import org.apache.hadoop.hbase.TableName;
38  import org.apache.hadoop.hbase.Waiter;
39  import org.apache.hadoop.hbase.Waiter.Predicate;
40  import org.apache.hadoop.hbase.testclassification.MediumTests;
41  import org.apache.hadoop.hbase.util.Bytes;
42  import org.junit.After;
43  import org.junit.AfterClass;
44  import org.junit.Before;
45  import org.junit.BeforeClass;
46  import org.junit.Test;
47  import org.junit.experimental.categories.Category;
48  
49  import com.google.common.collect.Sets;
50  
51  @Category({MediumTests.class})
52  public class TestRSGroupsBalance extends TestRSGroupsBase {
53    protected static final Log LOG = LogFactory.getLog(TestRSGroupsBalance.class);
54  
55    @BeforeClass
56    public static void setUp() throws Exception {
57      setUpTestBeforeClass();
58    }
59  
60    @AfterClass
61    public static void tearDown() throws Exception {
62      tearDownAfterClass();
63    }
64  
65    @Before
66    public void beforeMethod() throws Exception {
67      setUpBeforeMethod();
68    }
69  
70    @After
71    public void afterMethod() throws Exception {
72      tearDownAfterMethod();
73    }
74  
75    @Test
76    public void testRSGroupBalancerSwitch() throws IOException {
77      //Balancer is initially off in the test, set to true and check
78      assertFalse(admin.setBalancerRunning(true, true));
79      assertTrue(admin.isBalancerEnabled());
80      //Set balancer off and check if it actually turned off
81      assertTrue(admin.setBalancerRunning(false,true));
82      assertFalse(admin.isBalancerEnabled());
83    }
84  
85    @Test
86    public void testGroupBalance() throws Exception {
87      LOG.info("testGroupBalance");
88      String newGroupName = getGroupName("testGroupBalance");
89      final RSGroupInfo newGroup = addGroup(rsGroupAdmin, newGroupName, 3);
90  
91      final TableName tableName = TableName.valueOf(tablePrefix+"_ns", "testGroupBalance");
92      admin.createNamespace(
93          NamespaceDescriptor.create(tableName.getNamespaceAsString())
94              .addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, newGroupName).build());
95      final byte[] familyNameBytes = Bytes.toBytes("f");
96      final HTableDescriptor desc = new HTableDescriptor(tableName);
97      desc.addFamily(new HColumnDescriptor("f"));
98      byte [] startKey = Bytes.toBytes("aaaaa");
99      byte [] endKey = Bytes.toBytes("zzzzz");
100     admin.createTable(desc, startKey, endKey, 6);
101     TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
102       @Override
103       public boolean evaluate() throws Exception {
104         List<String> regions = getTableRegionMap().get(tableName);
105         if (regions == null) {
106           return false;
107         }
108         return regions.size() >= 6;
109       }
110     });
111 
112     //make assignment uneven, move all regions to one server
113     Map<ServerName,List<String>> assignMap =
114         getTableServerRegionMap().get(tableName);
115     final ServerName first = assignMap.entrySet().iterator().next().getKey();
116     for(HRegionInfo region: admin.getTableRegions(tableName)) {
117       if(!assignMap.get(first).contains(region.getRegionNameAsString())) {
118         admin.move(region.getEncodedNameAsBytes(), Bytes.toBytes(first.getServerName()));
119       }
120     }
121     TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
122       @Override
123       public boolean evaluate() throws Exception {
124         Map<ServerName, List<String>> map = getTableServerRegionMap().get(tableName);
125         if (map == null) {
126           return true;
127         }
128         List<String> regions = map.get(first);
129         if (regions == null) {
130           return true;
131         }
132         return regions.size() >= 6;
133       }
134     });
135 
136     //balance the other group and make sure it doesn't affect the new group
137     rsGroupAdmin.balanceRSGroup(RSGroupInfo.DEFAULT_GROUP);
138     assertEquals(6, getTableServerRegionMap().get(tableName).get(first).size());
139 
140     rsGroupAdmin.balanceRSGroup(newGroupName);
141     TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
142       @Override
143       public boolean evaluate() throws Exception {
144         for (List<String> regions : getTableServerRegionMap().get(tableName).values()) {
145           if (2 != regions.size()) {
146             return false;
147           }
148         }
149         return true;
150       }
151     });
152 
153     assertTrue(observer.preBalanceRSGroupCalled);
154     assertTrue(observer.postBalanceRSGroupCalled);
155   }
156 
157   @Test
158   public void testMisplacedRegions() throws Exception {
159     final TableName tableName = TableName.valueOf(tablePrefix+"_testMisplacedRegions");
160     LOG.info("testMisplacedRegions");
161 
162     final RSGroupInfo RSGroupInfo = addGroup(rsGroupAdmin, "testMisplacedRegions", 1);
163 
164     TEST_UTIL.createMultiRegionTable(tableName, new byte[]{'f'}, 15);
165     TEST_UTIL.waitUntilAllRegionsAssigned(tableName);
166 
167     RSGroupAdminEndpoint.getGroupInfoManager()
168         .moveTables(Sets.newHashSet(tableName), RSGroupInfo.getName());
169 
170     assertTrue(rsGroupAdmin.balanceRSGroup(RSGroupInfo.getName()));
171 
172     TEST_UTIL.waitFor(60000, new Predicate<Exception>() {
173       @Override
174       public boolean evaluate() throws Exception {
175         ServerName serverName =
176             ServerName.valueOf(RSGroupInfo.getServers().iterator().next().toString(), 1);
177         return admin.getConnection().getAdmin()
178             .getOnlineRegions(serverName).size() == 15;
179       }
180     });
181   }
182 
183 }