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