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