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 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.List;
24
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27 import org.apache.hadoop.conf.Configuration;
28 import org.apache.hadoop.hbase.*;
29 import org.apache.hadoop.hbase.client.*;
30 import org.apache.hadoop.hbase.testclassification.MasterTests;
31 import org.apache.hadoop.hbase.testclassification.MediumTests;
32 import org.apache.hadoop.hbase.util.Bytes;
33 import org.apache.hadoop.hbase.util.PairOfSameType;
34 import org.apache.hadoop.hbase.util.Threads;
35 import static org.junit.Assert.assertFalse;
36 import static org.junit.Assert.assertTrue;
37 import org.junit.AfterClass;
38 import org.junit.BeforeClass;
39 import org.junit.Rule;
40 import org.junit.Test;
41 import org.junit.experimental.categories.Category;
42
43 import org.junit.rules.TestName;
44 import org.junit.rules.TestRule;
45
46 import static org.junit.Assert.assertNotNull;
47
48 @Category({MasterTests.class, MediumTests.class})
49 public class TestCatalogJanitorInMemoryStates {
50 private static final Log LOG = LogFactory.getLog(TestCatalogJanitorInMemoryStates.class);
51 @Rule public final TestRule timeout = CategoryBasedTimeout.builder().
52 withTimeout(this.getClass()).withLookingForStuckThread(true).build();
53 @Rule public final TestName name = new TestName();
54 protected final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
55 private static byte [] ROW = Bytes.toBytes("testRow");
56 private static byte [] FAMILY = Bytes.toBytes("testFamily");
57 private static byte [] QUALIFIER = Bytes.toBytes("testQualifier");
58 private static byte [] VALUE = Bytes.toBytes("testValue");
59
60
61
62
63 @BeforeClass
64 public static void setUpBeforeClass() throws Exception {
65 Configuration conf = TEST_UTIL.getConfiguration();
66 TEST_UTIL.startMiniCluster(1);
67 }
68
69
70
71
72 @AfterClass
73 public static void tearDownAfterClass() throws Exception {
74 TEST_UTIL.shutdownMiniCluster();
75 }
76
77
78
79
80 @Test(timeout = 180000)
81 public void testInMemoryParentCleanup() throws IOException, InterruptedException {
82 final AssignmentManager am = TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager();
83 final ServerManager sm = TEST_UTIL.getHBaseCluster().getMaster().getServerManager();
84 final CatalogJanitor janitor = TEST_UTIL.getHBaseCluster().getMaster().catalogJanitorChore;
85
86 Admin admin = TEST_UTIL.getHBaseAdmin();
87 admin.enableCatalogJanitor(false);
88
89 final TableName tableName = TableName.valueOf(name.getMethodName());
90 Table t = TEST_UTIL.createTable(tableName, FAMILY);
91 int rowCount = TEST_UTIL.loadTable(t, FAMILY, false);
92
93 RegionLocator locator = TEST_UTIL.getConnection().getRegionLocator(tableName);
94 List<HRegionLocation> allRegionLocations = locator.getAllRegionLocations();
95
96
97 HRegionLocation parent = allRegionLocations.get(0);
98 List<HRegionLocation> daughters = splitRegion(parent.getRegionInfo());
99 LOG.info("Parent region: " + parent);
100 LOG.info("Daughter regions: " + daughters);
101 assertNotNull("Should have found daughter regions for " + parent, daughters);
102
103 assertTrue("Parent region should exist in RegionStates",
104 am.getRegionStates().isRegionInRegionStates(parent.getRegionInfo()));
105 assertTrue("Parent region should exist in ServerManager",
106 sm.isRegionInServerManagerStates(parent.getRegionInfo()));
107
108
109 Result r = MetaMockingUtil.getMetaTableRowResult(parent.getRegionInfo(), null,
110 daughters.get(0).getRegionInfo(), daughters.get(1).getRegionInfo());
111
112 Thread.sleep(5000);
113 janitor.cleanParent(parent.getRegionInfo(), r);
114 Thread.sleep(5000);
115 assertFalse("Parent region should have been removed from RegionStates",
116 am.getRegionStates().isRegionInRegionStates(parent.getRegionInfo()));
117 assertFalse("Parent region should have been removed from ServerManager",
118 sm.isRegionInServerManagerStates(parent.getRegionInfo()));
119
120 }
121
122
123
124
125
126 @Test(timeout = 180000)
127 public void testInMemoryForReplicaParentCleanup() throws Exception {
128 final AssignmentManager am = TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager();
129 final CatalogJanitor janitor = TEST_UTIL.getHBaseCluster().getMaster().catalogJanitorChore;
130
131 final TableName tableName = TableName.valueOf("testInMemoryForReplicaParentCleanup");
132 HTableDescriptor hdt = TEST_UTIL.createTableDescriptor(tableName.getNameAsString());
133 hdt.setRegionReplication(2);
134 TEST_UTIL.createTable(hdt, new byte[][] { FAMILY }, TEST_UTIL.getConfiguration());
135
136 RegionLocator locator = TEST_UTIL.getConnection().getRegionLocator(tableName);
137 List<HRegionLocation> allRegionLocations = locator.getAllRegionLocations();
138
139
140 assertTrue(allRegionLocations.size() == 2);
141
142 final HRegionLocation primaryParentRegion
143 = RegionReplicaUtil.isDefaultReplica(
144 allRegionLocations.get(0).getRegionInfo().getReplicaId()) ? allRegionLocations.get(0)
145 : allRegionLocations.get(1);
146 final HRegionLocation replicaParentRegion
147 = RegionReplicaUtil.isDefaultReplica(
148 allRegionLocations.get(0).getRegionInfo().getReplicaId()) ? allRegionLocations.get(1)
149 : allRegionLocations.get(0);
150
151 assertNotNull("Should have found daughter regions for " + primaryParentRegion,
152 splitRegion(primaryParentRegion.getRegionInfo(), Bytes.toBytes("a")));
153
154 TEST_UTIL.waitFor(60 * 1000, new Waiter.Predicate<Exception>() {
155 @Override
156 public boolean evaluate() throws Exception {
157 return !am.getRegionStates().existsInServerHoldings(primaryParentRegion.getServerName(),
158 primaryParentRegion.getRegionInfo()) &&
159 !am.getRegionStates().existsInServerHoldings(replicaParentRegion.getServerName(),
160 replicaParentRegion.getRegionInfo());
161 }
162 });
163 }
164
165
166
167
168
169
170
171 private List<HRegionLocation> splitRegion(final HRegionInfo r)
172 throws IOException, InterruptedException {
173 List<HRegionLocation> locations = new ArrayList<>();
174
175 Admin admin = TEST_UTIL.getHBaseAdmin();
176 Connection connection = TEST_UTIL.getConnection();
177 admin.splitRegion(r.getEncodedNameAsBytes());
178 admin.close();
179 PairOfSameType<HRegionInfo> regions = waitOnDaughters(r);
180 if (regions != null) {
181 try (RegionLocator rl = connection.getRegionLocator(r.getTable())) {
182 locations.add(rl.getRegionLocation(regions.getFirst().getEncodedNameAsBytes()));
183 locations.add(rl.getRegionLocation(regions.getSecond().getEncodedNameAsBytes()));
184 }
185 return locations;
186 }
187 return locations;
188 }
189
190
191
192
193
194
195
196 private List<HRegionLocation> splitRegion(final HRegionInfo r, final byte[] splitPoint)
197 throws IOException, InterruptedException {
198 List<HRegionLocation> locations = new ArrayList<>();
199
200 Admin admin = TEST_UTIL.getHBaseAdmin();
201 Connection connection = TEST_UTIL.getConnection();
202 admin.splitRegion(r.getEncodedNameAsBytes(), splitPoint);
203 admin.close();
204 PairOfSameType<HRegionInfo> regions = waitOnDaughters(r);
205 if (regions != null) {
206 try (RegionLocator rl = connection.getRegionLocator(r.getTable())) {
207 locations.add(rl.getRegionLocation(regions.getFirst().getEncodedNameAsBytes()));
208 locations.add(rl.getRegionLocation(regions.getSecond().getEncodedNameAsBytes()));
209 }
210 return locations;
211 }
212 return locations;
213 }
214
215
216
217
218
219
220
221 private PairOfSameType<HRegionInfo> waitOnDaughters(final HRegionInfo r)
222 throws IOException {
223 long start = System.currentTimeMillis();
224 PairOfSameType<HRegionInfo> pair = null;
225 try (Connection conn = ConnectionFactory.createConnection(TEST_UTIL.getConfiguration());
226 Table metaTable = conn.getTable(TableName.META_TABLE_NAME)) {
227 Result result = null;
228 HRegionInfo region = null;
229 while ((System.currentTimeMillis() - start) < 60000) {
230 result = metaTable.get(new Get(r.getRegionName()));
231 if (result == null) {
232 break;
233 }
234 region = MetaTableAccessor.getHRegionInfo(result);
235 if (region.isSplitParent()) {
236 LOG.debug(region.toString() + " IS a parent!");
237 pair = MetaTableAccessor.getDaughterRegions(result);
238 break;
239 }
240 Threads.sleep(100);
241 }
242 if (pair == null || pair.getFirst() == null || pair.getSecond() == null) {
243 throw new IOException("Failed to get daughters, for parent region: " + r);
244 }
245 return pair;
246 }
247 }
248 }