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 private List<HRegionLocation> splitRegion(final HRegionInfo r)
171 throws IOException, InterruptedException {
172 List<HRegionLocation> locations = new ArrayList<>();
173
174 Admin admin = TEST_UTIL.getHBaseAdmin();
175 Connection connection = TEST_UTIL.getConnection();
176 admin.splitRegion(r.getEncodedNameAsBytes());
177 admin.close();
178 PairOfSameType<HRegionInfo> regions = waitOnDaughters(r);
179 if (regions != null) {
180 try (RegionLocator rl = connection.getRegionLocator(r.getTable())) {
181 locations.add(rl.getRegionLocation(regions.getFirst().getEncodedNameAsBytes()));
182 locations.add(rl.getRegionLocation(regions.getSecond().getEncodedNameAsBytes()));
183 }
184 return locations;
185 }
186 return locations;
187 }
188
189
190
191
192
193
194
195 private List<HRegionLocation> splitRegion(final HRegionInfo r, final byte[] splitPoint)
196 throws IOException, InterruptedException {
197 List<HRegionLocation> locations = new ArrayList<>();
198
199 Admin admin = TEST_UTIL.getHBaseAdmin();
200 Connection connection = TEST_UTIL.getConnection();
201 admin.splitRegion(r.getEncodedNameAsBytes(), splitPoint);
202 admin.close();
203 PairOfSameType<HRegionInfo> regions = waitOnDaughters(r);
204 if (regions != null) {
205 try (RegionLocator rl = connection.getRegionLocator(r.getTable())) {
206 locations.add(rl.getRegionLocation(regions.getFirst().getEncodedNameAsBytes()));
207 locations.add(rl.getRegionLocation(regions.getSecond().getEncodedNameAsBytes()));
208 }
209 return locations;
210 }
211 return locations;
212 }
213
214
215
216
217
218
219
220 private PairOfSameType<HRegionInfo> waitOnDaughters(final HRegionInfo r)
221 throws IOException {
222 long start = System.currentTimeMillis();
223 PairOfSameType<HRegionInfo> pair = null;
224 try (Connection conn = ConnectionFactory.createConnection(TEST_UTIL.getConfiguration());
225 Table metaTable = conn.getTable(TableName.META_TABLE_NAME)) {
226 Result result = null;
227 HRegionInfo region = null;
228 while ((System.currentTimeMillis() - start) < 60000) {
229 result = metaTable.get(new Get(r.getRegionName()));
230 if (result == null) {
231 break;
232 }
233 region = MetaTableAccessor.getHRegionInfo(result);
234 if (region.isSplitParent()) {
235 LOG.debug(region.toString() + " IS a parent!");
236 pair = MetaTableAccessor.getDaughterRegions(result);
237 break;
238 }
239 Threads.sleep(100);
240 }
241 if (pair == null || pair.getFirst() == null || pair.getSecond() == null) {
242 throw new IOException("Failed to get daughters, for parent region: " + r);
243 }
244 return pair;
245 }
246 }
247 }