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