1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.regionserver;
21
22 import org.apache.hadoop.hbase.HBaseTestingUtility;
23 import org.apache.hadoop.hbase.HConstants;
24 import org.apache.hadoop.hbase.HRegionInfo;
25 import org.apache.hadoop.hbase.HTableDescriptor;
26 import org.apache.hadoop.hbase.MediumTests;
27 import org.apache.hadoop.hbase.NotServingRegionException;
28 import org.apache.hadoop.hbase.client.HTable;
29 import org.apache.hadoop.hbase.client.Put;
30 import org.apache.hadoop.hbase.executor.EventType;
31 import org.apache.hadoop.hbase.protobuf.RequestConverter;
32 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos;
33 import org.apache.hadoop.hbase.regionserver.handler.OpenRegionHandler;
34 import org.apache.hadoop.hbase.util.Bytes;
35 import org.apache.hadoop.hbase.zookeeper.ZKAssign;
36 import org.junit.After;
37 import org.junit.AfterClass;
38 import org.junit.Assert;
39 import org.junit.BeforeClass;
40 import org.junit.Test;
41 import org.junit.experimental.categories.Category;
42
43 import com.google.protobuf.ServiceException;
44
45
46
47
48
49 @Category(MediumTests.class)
50 public class TestRegionServerNoMaster {
51
52 private static final int NB_SERVERS = 1;
53 private static HTable table;
54 private static final byte[] row = "ee".getBytes();
55
56 private static HRegionInfo hri;
57
58 private static byte[] regionName;
59 private static final HBaseTestingUtility HTU = new HBaseTestingUtility();
60
61
62 @BeforeClass
63 public static void before() throws Exception {
64 HTU.startMiniCluster(NB_SERVERS);
65 final byte[] tableName = Bytes.toBytes(TestRegionServerNoMaster.class.getSimpleName());
66
67
68 table = HTU.createTable(tableName, HConstants.CATALOG_FAMILY);
69 Put p = new Put(row);
70 p.add(HConstants.CATALOG_FAMILY, row, row);
71 table.put(p);
72
73 hri = table.getRegionLocation(row, false).getRegionInfo();
74 regionName = hri.getRegionName();
75
76
77 HTU.getHBaseCluster().getMaster().stopMaster();
78 }
79
80 @AfterClass
81 public static void afterClass() throws Exception {
82 table.close();
83 HTU.shutdownMiniCluster();
84 }
85
86 @After
87 public void after() throws Exception {
88
89
90
91 ZKAssign.deleteNodeFailSilent(HTU.getZooKeeperWatcher(), hri);
92 }
93
94
95 private static HRegionServer getRS() {
96 return HTU.getHBaseCluster().getLiveRegionServerThreads().get(0).getRegionServer();
97 }
98
99
100
101
102
103 private void reopenRegion() throws Exception {
104
105 ZKAssign.createNodeOffline(HTU.getZooKeeperWatcher(), hri, getRS().getServerName());
106
107 AdminProtos.OpenRegionRequest orr = RequestConverter.buildOpenRegionRequest(hri, 0, null);
108 AdminProtos.OpenRegionResponse responseOpen = getRS().openRegion(null, orr);
109 Assert.assertTrue(responseOpen.getOpeningStateCount() == 1);
110 Assert.assertTrue(responseOpen.getOpeningState(0).
111 equals(AdminProtos.OpenRegionResponse.RegionOpeningState.OPENED));
112
113
114 checkRegionIsOpened();
115 }
116
117 private void checkRegionIsOpened() throws Exception {
118
119 while (!getRS().getRegionsInTransitionInRS().isEmpty()) {
120 Thread.sleep(1);
121 }
122
123 Assert.assertTrue(getRS().getRegion(regionName).isAvailable());
124
125 Assert.assertTrue(
126 ZKAssign.deleteOpenedNode(HTU.getZooKeeperWatcher(), hri.getEncodedName()));
127 }
128
129
130 private void checkRegionIsClosed() throws Exception {
131
132 while (!getRS().getRegionsInTransitionInRS().isEmpty()) {
133 Thread.sleep(1);
134 }
135
136 try {
137 Assert.assertFalse(getRS().getRegion(regionName).isAvailable());
138 } catch (NotServingRegionException expected) {
139
140 }
141
142
143 }
144
145
146
147
148
149 private void closeNoZK() throws Exception {
150
151 AdminProtos.CloseRegionRequest crr =
152 RequestConverter.buildCloseRegionRequest(regionName, false);
153 AdminProtos.CloseRegionResponse responseClose = getRS().closeRegion(null, crr);
154 Assert.assertTrue(responseClose.getClosed());
155
156
157 checkRegionIsClosed();
158 }
159
160
161 @Test(timeout = 60000)
162 public void testCloseByRegionServer() throws Exception {
163 closeNoZK();
164 reopenRegion();
165 }
166
167 @Test(timeout = 60000)
168 public void testCloseByMasterWithoutZNode() throws Exception {
169
170
171 AdminProtos.CloseRegionRequest crr = RequestConverter.buildCloseRegionRequest(
172 regionName, true);
173 AdminProtos.CloseRegionResponse responseClose = getRS().closeRegion(null, crr);
174 Assert.assertTrue(responseClose.getClosed());
175
176
177 while (!getRS().getRegionsInTransitionInRS().isEmpty()) {
178 Thread.sleep(1);
179 }
180
181
182 Assert.assertTrue("The close should have failed", getRS().getRegion(regionName).isAvailable());
183 }
184
185 @Test(timeout = 60000)
186 public void testOpenCloseByMasterWithZNode() throws Exception {
187
188 ZKAssign.createNodeClosing(HTU.getZooKeeperWatcher(), hri, getRS().getServerName());
189
190 AdminProtos.CloseRegionRequest crr = RequestConverter.buildCloseRegionRequest(
191 regionName, true);
192 AdminProtos.CloseRegionResponse responseClose = getRS().closeRegion(null, crr);
193 Assert.assertTrue(responseClose.getClosed());
194
195 checkRegionIsClosed();
196
197 ZKAssign.deleteClosedNode(HTU.getZooKeeperWatcher(), hri.getEncodedName());
198
199 reopenRegion();
200 }
201
202
203
204
205
206
207
208
209
210
211
212 @Test(timeout = 60000)
213 public void testMultipleOpen() throws Exception {
214
215
216 closeNoZK();
217 checkRegionIsClosed();
218
219
220 ZKAssign.createNodeOffline(HTU.getZooKeeperWatcher(), hri, getRS().getServerName());
221
222
223 for (int i = 0; i < 10; i++) {
224 AdminProtos.OpenRegionRequest orr = RequestConverter.buildOpenRegionRequest(hri, 0, null);
225 AdminProtos.OpenRegionResponse responseOpen = getRS().openRegion(null, orr);
226 Assert.assertTrue(responseOpen.getOpeningStateCount() == 1);
227
228 AdminProtos.OpenRegionResponse.RegionOpeningState ors = responseOpen.getOpeningState(0);
229 Assert.assertTrue("request " + i + " failed",
230 ors.equals(AdminProtos.OpenRegionResponse.RegionOpeningState.OPENED) ||
231 ors.equals(AdminProtos.OpenRegionResponse.RegionOpeningState.ALREADY_OPENED)
232 );
233 }
234
235 checkRegionIsOpened();
236 }
237
238 @Test
239 public void testOpenClosingRegion() throws Exception {
240 Assert.assertTrue(getRS().getRegion(regionName).isAvailable());
241
242 try {
243
244 getRS().regionsInTransitionInRS.put(hri.getEncodedNameAsBytes(), Boolean.FALSE);
245 AdminProtos.OpenRegionRequest orr = RequestConverter.buildOpenRegionRequest(hri, 0, null);
246 getRS().openRegion(null, orr);
247 Assert.fail("The closing region should not be opened");
248 } catch (ServiceException se) {
249 Assert.assertTrue("The region should be already in transition",
250 se.getCause() instanceof RegionAlreadyInTransitionException);
251 } finally {
252 getRS().regionsInTransitionInRS.remove(hri.getEncodedNameAsBytes());
253 }
254 }
255
256 @Test(timeout = 60000)
257 public void testMultipleCloseFromMaster() throws Exception {
258
259
260 ZKAssign.createNodeClosing(HTU.getZooKeeperWatcher(), hri, getRS().getServerName());
261 for (int i = 0; i < 10; i++) {
262 AdminProtos.CloseRegionRequest crr =
263 RequestConverter.buildCloseRegionRequest(regionName, 0, null, true);
264 try {
265 AdminProtos.CloseRegionResponse responseClose = getRS().closeRegion(null, crr);
266 Assert.assertEquals("The first request should succeeds", 0, i);
267 Assert.assertTrue("request " + i + " failed",
268 responseClose.getClosed() || responseClose.hasClosed());
269 } catch (ServiceException se) {
270 Assert.assertTrue("The next queries should throw an exception.", i > 0);
271 }
272 }
273
274 checkRegionIsClosed();
275
276 Assert.assertTrue(
277 ZKAssign.deleteClosedNode(HTU.getZooKeeperWatcher(), hri.getEncodedName())
278 );
279
280 reopenRegion();
281 }
282
283
284
285
286 @Test(timeout = 60000)
287 public void testCancelOpeningWithoutZK() throws Exception {
288
289 closeNoZK();
290 checkRegionIsClosed();
291
292
293 ZKAssign.createNodeOffline(HTU.getZooKeeperWatcher(), hri, getRS().getServerName());
294 getRS().getRegionsInTransitionInRS().put(hri.getEncodedNameAsBytes(), Boolean.TRUE);
295
296
297 AdminProtos.CloseRegionRequest crr =
298 RequestConverter.buildCloseRegionRequest(regionName, false);
299 try {
300 getRS().closeRegion(null, crr);
301 Assert.assertTrue(false);
302 } catch (ServiceException expected) {
303 }
304
305
306 Assert.assertEquals(Boolean.FALSE, getRS().getRegionsInTransitionInRS().get(
307 hri.getEncodedNameAsBytes()));
308
309
310 HTableDescriptor htd = getRS().tableDescriptors.get(hri.getTableName());
311 getRS().service.submit(new OpenRegionHandler(getRS(), getRS(), hri, htd, 0));
312
313
314 checkRegionIsClosed();
315
316
317 Assert.assertTrue(ZKAssign.deleteNode(
318 getRS().getZooKeeperWatcher(), hri.getEncodedName(),
319 EventType.RS_ZK_REGION_FAILED_OPEN, 1)
320 );
321
322 reopenRegion();
323 }
324
325
326
327
328
329 @Test(timeout = 60000)
330 public void testCancelOpeningWithZK() throws Exception {
331
332 closeNoZK();
333 checkRegionIsClosed();
334
335
336 getRS().getRegionsInTransitionInRS().put(hri.getEncodedNameAsBytes(), Boolean.TRUE);
337
338
339 ZKAssign.createNodeClosing(HTU.getZooKeeperWatcher(), hri, getRS().getServerName());
340 AdminProtos.CloseRegionRequest crr =
341 RequestConverter.buildCloseRegionRequest(regionName, false);
342 try {
343 getRS().closeRegion(null, crr);
344 Assert.assertTrue(false);
345 } catch (ServiceException expected) {
346 Assert.assertTrue(expected.getCause() instanceof NotServingRegionException);
347 }
348
349
350 Assert.assertTrue(ZKAssign.deleteNode(
351 getRS().getZooKeeperWatcher(), hri.getEncodedName(),
352 EventType.M_ZK_REGION_CLOSING, 0)
353 );
354
355
356 Assert.assertEquals(Boolean.FALSE, getRS().getRegionsInTransitionInRS().get(
357 hri.getEncodedNameAsBytes()));
358
359
360
361
362
363
364 HTableDescriptor htd = getRS().tableDescriptors.get(hri.getTableName());
365 getRS().service.submit(new OpenRegionHandler(getRS(), getRS(), hri, htd, 0));
366
367
368 checkRegionIsClosed();
369
370
371 Assert.assertEquals(-1, ZKAssign.getVersion(HTU.getZooKeeperWatcher(), hri));
372
373 reopenRegion();
374 }
375 }