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 com.google.common.collect.Lists;
27  
28  import java.io.IOException;
29  import java.util.Set;
30  
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  import org.apache.hadoop.hbase.HColumnDescriptor;
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.client.ClusterConnection;
40  import org.apache.hadoop.hbase.master.HMaster;
41  import org.apache.hadoop.hbase.net.Address;
42  import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
43  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos;
44  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetServerInfoRequest;
45  import org.apache.hadoop.hbase.testclassification.MediumTests;
46  import org.apache.hadoop.hbase.util.Bytes;
47  import org.junit.After;
48  import org.junit.AfterClass;
49  import org.junit.Assert;
50  import org.junit.Before;
51  import org.junit.BeforeClass;
52  import org.junit.Test;
53  import org.junit.experimental.categories.Category;
54  
55  @Category({MediumTests.class})
56  public class TestRSGroupsBasics extends TestRSGroupsBase {
57    protected static final Log LOG = LogFactory.getLog(TestRSGroupsBasics.class);
58  
59    @BeforeClass
60    public static void setUp() throws Exception {
61      setUpTestBeforeClass();
62    }
63  
64    @AfterClass
65    public static void tearDown() throws Exception {
66      tearDownAfterClass();
67    }
68  
69    @Before
70    public void beforeMethod() throws Exception {
71      setUpBeforeMethod();
72    }
73  
74    @After
75    public void afterMethod() throws Exception {
76      tearDownAfterMethod();
77    }
78  
79    @Test
80    public void testBasicStartUp() throws IOException {
81      RSGroupInfo defaultInfo = rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP);
82      assertEquals(NUM_SLAVES_BASE, defaultInfo.getServers().size());
83      // Assignment of meta, namespace and rsgroup regions.
84      int count = master.getAssignmentManager().getRegionStates().getRegionAssignments().size();
85      // 3 (meta, namespace and rsgroup)
86      assertEquals(3, count);
87    }
88  
89    @Test
90    public void testCreateAndDrop() throws Exception {
91      LOG.info("testCreateAndDrop");
92      final TableName tableName = TableName.valueOf(tablePrefix + "_testCreateAndDrop");
93      TEST_UTIL.createTable(tableName, Bytes.toBytes("cf"));
94      //wait for created table to be assigned
95      TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
96        @Override
97        public boolean evaluate() throws Exception {
98          return getTableRegionMap().get(tableName) != null;
99        }
100     });
101     TEST_UTIL.deleteTable(tableName);
102   }
103 
104   @Test
105   public void testCreateMultiRegion() throws IOException {
106     LOG.info("testCreateMultiRegion");
107     TableName tableName = TableName.valueOf(tablePrefix + "_testCreateMultiRegion");
108     byte[] end = {1,3,5,7,9};
109     byte[] start = {0,2,4,6,8};
110     byte[][] f = {Bytes.toBytes("f")};
111     TEST_UTIL.createTable(tableName, f,1,start,end,10);
112   }
113 
114   @Test
115   public void testNamespaceCreateAndAssign() throws Exception {
116     LOG.info("testNamespaceCreateAndAssign");
117     String nsName = tablePrefix+"_foo";
118     final TableName tableName = TableName.valueOf(nsName, tablePrefix + "_testCreateAndAssign");
119     RSGroupInfo appInfo = addGroup(rsGroupAdmin, "appInfo", 1);
120     admin.createNamespace(NamespaceDescriptor.create(nsName)
121         .addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, "appInfo").build());
122     final HTableDescriptor desc = new HTableDescriptor(tableName);
123     desc.addFamily(new HColumnDescriptor("f"));
124     admin.createTable(desc);
125     //wait for created table to be assigned
126     TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
127       @Override
128       public boolean evaluate() throws Exception {
129         return getTableRegionMap().get(desc.getTableName()) != null;
130       }
131     });
132     ServerName targetServer =
133         ServerName.parseServerName(appInfo.getServers().iterator().next().toString());
134     AdminProtos.AdminService.BlockingInterface rs = admin.getConnection().getAdmin(targetServer);
135     //verify it was assigned to the right group
136     Assert.assertEquals(1, ProtobufUtil.getOnlineRegions(rs).size());
137   }
138 
139   @Test
140   public void testDefaultNamespaceCreateAndAssign() throws Exception {
141     LOG.info("testDefaultNamespaceCreateAndAssign");
142     final byte[] tableName = Bytes.toBytes(tablePrefix + "_testCreateAndAssign");
143     admin.modifyNamespace(NamespaceDescriptor.create("default")
144         .addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, "default").build());
145     final HTableDescriptor desc = new HTableDescriptor(tableName);
146     desc.addFamily(new HColumnDescriptor("f"));
147     admin.createTable(desc);
148     //wait for created table to be assigned
149     TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
150       @Override
151       public boolean evaluate() throws Exception {
152         return getTableRegionMap().get(desc.getTableName()) != null;
153       }
154     });
155   }
156 
157   @Test
158   public void testCloneSnapshot() throws Exception {
159     final TableName tableName = TableName.valueOf(tablePrefix+"_testCloneSnapshot");
160     LOG.info("testCloneSnapshot");
161 
162     byte[] FAMILY = Bytes.toBytes("test");
163     String snapshotName = tableName.getNameAsString() + "_snap";
164     TableName clonedTableName = TableName.valueOf(tableName.getNameAsString() + "_clone");
165 
166     // create base table
167     TEST_UTIL.createTable(tableName, FAMILY);
168 
169     // create snapshot
170     admin.snapshot(snapshotName, tableName);
171 
172     // clone
173     admin.cloneSnapshot(snapshotName, clonedTableName);
174   }
175 
176   @Test
177   public void testClearDeadServers() throws Exception {
178     // move region servers from default group to new group
179     final int serverCountToMoveToNewGroup = 3;
180     final RSGroupInfo newGroup =
181         addGroup(rsGroupAdmin, "testClearDeadServers", serverCountToMoveToNewGroup);
182 
183     // stop 1 region server in new group
184     ServerName serverToStop = ServerName.parseServerName(
185         newGroup.getServers().iterator().next().toString());
186     AdminProtos.AdminService.BlockingInterface regionServerToStop =
187         ((ClusterConnection) admin.getConnection()).getAdmin(serverToStop);
188     try {
189       serverToStop = ProtobufUtil.toServerName(regionServerToStop.getServerInfo(null,
190           GetServerInfoRequest.newBuilder().build()).getServerInfo().getServerName());
191       //stopping may cause an exception
192       //due to the connection loss
193       regionServerToStop.stopServer(null,
194           AdminProtos.StopServerRequest.newBuilder().setReason("Die").build());
195     } catch(Exception e) {
196     }
197 
198     // wait for the stopped region server to show up in dead server list
199     final HMaster master = TEST_UTIL.getHBaseCluster().getMaster();
200     TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
201       @Override
202       public boolean evaluate() throws Exception {
203         return !master.getServerManager().areDeadServersInProgress()
204             && cluster.getClusterStatus().getDeadServerNames().size() > 0;
205       }
206     });
207 
208     // verify
209     assertFalse(cluster.getClusterStatus().getServers().contains(serverToStop));
210     assertTrue(cluster.getClusterStatus().getDeadServerNames().contains(serverToStop));
211     assertTrue(newGroup.getServers().contains(serverToStop.getAddress()));
212 
213     // clear dead servers list
214     // We need to retry here because the clearDeadServers() RPC may race with currently processing
215     // dead servers in the ServerManager and might not succeed.
216     final ServerName finalServerToStop = serverToStop;
217     TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
218       @Override
219       public boolean evaluate() throws Exception {
220         return admin.clearDeadServers(Lists.newArrayList(finalServerToStop)).isEmpty();
221       }
222     });
223     // verify if the stopped region server gets cleared and removed from the group
224     Set<Address> newGroupServers = rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getServers();
225     assertFalse(newGroupServers.contains(serverToStop.getAddress()));
226     assertEquals(serverCountToMoveToNewGroup - 1 /* 1 stopped */, newGroupServers.size());
227   }
228 }