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;
20
21
22 import static org.junit.Assert.assertEquals;
23 import static org.junit.Assert.assertFalse;
24 import static org.junit.Assert.assertTrue;
25 import static org.junit.Assert.fail;
26
27 import java.io.IOException;
28 import java.util.Collection;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.apache.hadoop.conf.Configuration;
33 import org.apache.hadoop.hbase.TableName;
34 import org.apache.hadoop.hbase.HBaseTestingUtility;
35 import org.apache.hadoop.hbase.HConstants;
36 import org.apache.hadoop.hbase.HRegionInfo;
37 import org.apache.hadoop.hbase.MediumTests;
38 import org.apache.hadoop.hbase.MiniHBaseCluster;
39 import org.apache.hadoop.hbase.TableDescriptors;
40 import org.apache.hadoop.hbase.client.HTable;
41 import org.apache.hadoop.hbase.client.Put;
42 import org.apache.hadoop.hbase.client.Result;
43 import org.apache.hadoop.hbase.client.ResultScanner;
44 import org.apache.hadoop.hbase.client.Scan;
45 import org.apache.hadoop.hbase.client.Durability;
46 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
47 import org.apache.hadoop.hbase.regionserver.HRegionServer;
48 import org.apache.hadoop.hbase.util.Bytes;
49 import org.apache.hadoop.hbase.util.Threads;
50 import org.junit.AfterClass;
51 import org.junit.Assert;
52 import org.junit.Before;
53 import org.junit.BeforeClass;
54 import org.junit.Test;
55 import org.junit.experimental.categories.Category;
56 import org.mockito.Mockito;
57 import org.mockito.internal.util.reflection.Whitebox;
58
59
60
61
62 @Category(MediumTests.class)
63 public class TestZKBasedOpenCloseRegion {
64 private static final Log LOG = LogFactory.getLog(TestZKBasedOpenCloseRegion.class);
65 private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
66 private static final TableName TABLENAME =
67 TableName.valueOf("TestZKBasedOpenCloseRegion");
68 private static final byte [][] FAMILIES = new byte [][] {Bytes.toBytes("a"),
69 Bytes.toBytes("b"), Bytes.toBytes("c")};
70 private static int countOfRegions;
71
72 @BeforeClass public static void beforeAllTests() throws Exception {
73 Configuration c = TEST_UTIL.getConfiguration();
74 c.setBoolean("dfs.support.append", true);
75 c.setInt("hbase.regionserver.info.port", 0);
76 TEST_UTIL.startMiniCluster(2);
77 TEST_UTIL.createTable(TABLENAME, FAMILIES);
78 HTable t = new HTable(TEST_UTIL.getConfiguration(), TABLENAME);
79 countOfRegions = TEST_UTIL.createMultiRegions(t, getTestFamily());
80 waitUntilAllRegionsAssigned();
81 addToEachStartKey(countOfRegions);
82 t.close();
83 }
84
85 @AfterClass public static void afterAllTests() throws Exception {
86 TEST_UTIL.shutdownMiniCluster();
87 }
88
89 @Before public void setup() throws IOException {
90 if (TEST_UTIL.getHBaseCluster().getLiveRegionServerThreads().size() < 2) {
91
92 LOG.info("Started new server=" +
93 TEST_UTIL.getHBaseCluster().startRegionServer());
94
95 }
96 waitUntilAllRegionsAssigned();
97 waitOnRIT();
98 }
99
100
101
102
103
104 @Test (timeout=300000) public void testReOpenRegion()
105 throws Exception {
106 MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster();
107 LOG.info("Number of region servers = " +
108 cluster.getLiveRegionServerThreads().size());
109
110 int rsIdx = 0;
111 HRegionServer regionServer =
112 TEST_UTIL.getHBaseCluster().getRegionServer(rsIdx);
113 HRegionInfo hri = getNonMetaRegion(ProtobufUtil.getOnlineRegions(regionServer));
114 LOG.debug("Asking RS to close region " + hri.getRegionNameAsString());
115
116 LOG.info("Unassign " + hri.getRegionNameAsString());
117 cluster.getMaster().assignmentManager.unassign(hri);
118
119 while (!cluster.getMaster().assignmentManager.wasClosedHandlerCalled(hri)) {
120 Threads.sleep(100);
121 }
122
123 while (!cluster.getMaster().assignmentManager.wasOpenedHandlerCalled(hri)) {
124 Threads.sleep(100);
125 }
126
127 LOG.info("Done with testReOpenRegion");
128 }
129
130 private HRegionInfo getNonMetaRegion(final Collection<HRegionInfo> regions) {
131 HRegionInfo hri = null;
132 for (HRegionInfo i: regions) {
133 LOG.info(i.getRegionNameAsString());
134 if (!i.isMetaRegion()) {
135 hri = i;
136 break;
137 }
138 }
139 return hri;
140 }
141
142
143
144
145
146
147 @Test
148 public void testRSAlreadyProcessingRegion() throws Exception {
149 LOG.info("starting testRSAlreadyProcessingRegion");
150 MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster();
151
152 HRegionServer hr0 =
153 cluster.getLiveRegionServerThreads().get(0).getRegionServer();
154 HRegionServer hr1 =
155 cluster.getLiveRegionServerThreads().get(1).getRegionServer();
156 HRegionInfo hri = getNonMetaRegion(ProtobufUtil.getOnlineRegions(hr0));
157
158
159 hr1.getRegionsInTransitionInRS().putIfAbsent(hri.getEncodedNameAsBytes(), true);
160
161
162 TEST_UTIL.getHBaseAdmin().move(hri.getEncodedNameAsBytes(),
163 Bytes.toBytes(hr1.getServerName().toString()));
164
165
166 assertEquals(hr1.getOnlineRegion(hri.getEncodedNameAsBytes()), null);
167
168
169 hr1.getRegionsInTransitionInRS().remove(hri.getEncodedNameAsBytes());
170
171
172 hri = getNonMetaRegion(ProtobufUtil.getOnlineRegions(hr1));
173
174 TEST_UTIL.getHBaseAdmin().move(hri.getEncodedNameAsBytes(),
175 Bytes.toBytes(hr0.getServerName().toString()));
176
177 while (!cluster.getMaster().assignmentManager.wasOpenedHandlerCalled(hri)) {
178 Threads.sleep(100);
179 }
180
181
182 assertTrue(hr1.getOnlineRegion(hri.getEncodedNameAsBytes()) == null);
183
184 }
185
186 @Test (timeout=300000) public void testCloseRegion()
187 throws Exception {
188 LOG.info("Running testCloseRegion");
189 MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster();
190 LOG.info("Number of region servers = " + cluster.getLiveRegionServerThreads().size());
191
192 int rsIdx = 0;
193 HRegionServer regionServer = TEST_UTIL.getHBaseCluster().getRegionServer(rsIdx);
194 HRegionInfo hri = getNonMetaRegion(ProtobufUtil.getOnlineRegions(regionServer));
195 LOG.debug("Asking RS to close region " + hri.getRegionNameAsString());
196
197 cluster.getMaster().assignmentManager.unassign(hri);
198
199 while (!cluster.getMaster().assignmentManager.wasClosedHandlerCalled(hri)) {
200 Threads.sleep(100);
201 }
202 LOG.info("Done with testCloseRegion");
203 }
204
205 private void waitOnRIT() {
206
207
208 while (TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager().
209 getRegionStates().isRegionsInTransition()) {
210 LOG.info("Waiting on regions in transition: " +
211 TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager().
212 getRegionStates().getRegionsInTransition());
213 Threads.sleep(10);
214 }
215 }
216
217
218
219
220
221
222 @Test
223 public void testRegionOpenFailsDueToIOException() throws Exception {
224 HRegionInfo REGIONINFO = new HRegionInfo(TableName.valueOf("t"),
225 HConstants.EMPTY_START_ROW, HConstants.EMPTY_START_ROW);
226 HRegionServer regionServer = TEST_UTIL.getHBaseCluster().getRegionServer(0);
227 TableDescriptors htd = Mockito.mock(TableDescriptors.class);
228 Object orizinalState = Whitebox.getInternalState(regionServer,"tableDescriptors");
229 Whitebox.setInternalState(regionServer, "tableDescriptors", htd);
230 Mockito.doThrow(new IOException()).when(htd).get((TableName) Mockito.any());
231 try {
232 ProtobufUtil.openRegion(regionServer, REGIONINFO);
233 fail("It should throw IOException ");
234 } catch (IOException e) {
235 }
236 Whitebox.setInternalState(regionServer, "tableDescriptors", orizinalState);
237 assertFalse("Region should not be in RIT",
238 regionServer.getRegionsInTransitionInRS().containsKey(REGIONINFO.getEncodedNameAsBytes()));
239 }
240
241 private static void waitUntilAllRegionsAssigned()
242 throws IOException {
243 HTable meta = new HTable(TEST_UTIL.getConfiguration(), TableName.META_TABLE_NAME);
244 while (true) {
245 int rows = 0;
246 Scan scan = new Scan();
247 scan.addColumn(HConstants.CATALOG_FAMILY, HConstants.SERVER_QUALIFIER);
248 ResultScanner s = meta.getScanner(scan);
249 for (Result r = null; (r = s.next()) != null;) {
250 byte [] b =
251 r.getValue(HConstants.CATALOG_FAMILY, HConstants.SERVER_QUALIFIER);
252 if (b == null || b.length <= 0) {
253 break;
254 }
255 rows++;
256 }
257 s.close();
258
259 if (rows >= countOfRegions) {
260 break;
261 }
262 LOG.info("Found=" + rows);
263 Threads.sleep(1000);
264 }
265 meta.close();
266 }
267
268
269
270
271
272
273
274
275 private static int addToEachStartKey(final int expected) throws IOException {
276 HTable t = new HTable(TEST_UTIL.getConfiguration(), TABLENAME);
277 HTable meta = new HTable(TEST_UTIL.getConfiguration(),
278 TableName.META_TABLE_NAME);
279 int rows = 0;
280 Scan scan = new Scan();
281 scan.addColumn(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER);
282 ResultScanner s = meta.getScanner(scan);
283 for (Result r = null; (r = s.next()) != null;) {
284 HRegionInfo hri = HRegionInfo.getHRegionInfo(r);
285 if (hri == null) break;
286 if(!hri.getTableName().equals(TABLENAME)) {
287 continue;
288 }
289
290 byte [] row = getStartKey(hri);
291 Put p = new Put(row);
292 p.setDurability(Durability.SKIP_WAL);
293 p.add(getTestFamily(), getTestQualifier(), row);
294 t.put(p);
295 rows++;
296 }
297 s.close();
298 Assert.assertEquals(expected, rows);
299 t.close();
300 meta.close();
301 return rows;
302 }
303
304 private static byte [] getStartKey(final HRegionInfo hri) {
305 return Bytes.equals(HConstants.EMPTY_START_ROW, hri.getStartKey())?
306 Bytes.toBytes("aaa"): hri.getStartKey();
307 }
308
309 private static byte [] getTestFamily() {
310 return FAMILIES[0];
311 }
312
313 private static byte [] getTestQualifier() {
314 return getTestFamily();
315 }
316
317 public static void main(String args[]) throws Exception {
318 TestZKBasedOpenCloseRegion.beforeAllTests();
319
320 TestZKBasedOpenCloseRegion test = new TestZKBasedOpenCloseRegion();
321 test.setup();
322 test.testCloseRegion();
323
324 TestZKBasedOpenCloseRegion.afterAllTests();
325 }
326
327 }
328