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 static org.junit.Assert.assertEquals;
22
23 import java.io.IOException;
24 import java.util.Collection;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Set;
30 import java.util.concurrent.atomic.AtomicInteger;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.apache.hadoop.conf.Configuration;
35 import org.apache.hadoop.hbase.HBaseTestingUtility;
36 import org.apache.hadoop.hbase.HColumnDescriptor;
37 import org.apache.hadoop.hbase.HConstants;
38 import org.apache.hadoop.hbase.HRegionInfo;
39 import org.apache.hadoop.hbase.HRegionLocation;
40 import org.apache.hadoop.hbase.HTableDescriptor;
41 import org.apache.hadoop.hbase.testclassification.MediumTests;
42 import org.apache.hadoop.hbase.RegionLocations;
43 import org.apache.hadoop.hbase.ServerName;
44 import org.apache.hadoop.hbase.TableName;
45 import org.apache.hadoop.hbase.MetaTableAccessor;
46 import org.apache.hadoop.hbase.MetaTableAccessor.Visitor;
47 import org.apache.hadoop.hbase.client.Admin;
48 import org.apache.hadoop.hbase.client.Connection;
49 import org.apache.hadoop.hbase.client.ConnectionFactory;
50 import org.apache.hadoop.hbase.client.Delete;
51 import org.apache.hadoop.hbase.client.HTable;
52 import org.apache.hadoop.hbase.client.RegionReplicaUtil;
53 import org.apache.hadoop.hbase.client.Result;
54 import org.apache.hadoop.hbase.client.Table;
55 import org.apache.hadoop.hbase.util.Bytes;
56 import org.junit.AfterClass;
57 import org.junit.BeforeClass;
58 import org.junit.Test;
59 import org.junit.experimental.categories.Category;
60
61 @Category(MediumTests.class)
62 public class TestMasterOperationsForRegionReplicas {
63 private static final Log LOG = LogFactory.getLog(TestRegionPlacement.class);
64 private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
65 private static Connection CONNECTION = null;
66 private static Admin ADMIN;
67 private static int numSlaves = 2;
68 private static Configuration conf;
69
70 @BeforeClass
71 public static void setupBeforeClass() throws Exception {
72 conf = TEST_UTIL.getConfiguration();
73 conf.setBoolean("hbase.tests.use.shortcircuit.reads", false);
74 TEST_UTIL.startMiniCluster(numSlaves);
75 CONNECTION = ConnectionFactory.createConnection(TEST_UTIL.getConfiguration());
76 ADMIN = CONNECTION.getAdmin();
77 while(ADMIN.getClusterStatus().getServers().size() < numSlaves) {
78 Thread.sleep(100);
79 }
80 }
81
82 @AfterClass
83 public static void tearDownAfterClass() throws Exception {
84 if (ADMIN != null) ADMIN.close();
85 if (CONNECTION != null && !CONNECTION.isClosed()) CONNECTION.close();
86 TEST_UTIL.shutdownMiniCluster();
87 }
88
89 @Test
90 public void testCreateTableWithSingleReplica() throws Exception {
91 final int numRegions = 3;
92 final int numReplica = 1;
93 final TableName table = TableName.valueOf("singleReplicaTable");
94 try {
95 HTableDescriptor desc = new HTableDescriptor(table);
96 desc.setRegionReplication(numReplica);
97 desc.addFamily(new HColumnDescriptor("family"));
98 ADMIN.createTable(desc, Bytes.toBytes("A"), Bytes.toBytes("Z"), numRegions);
99
100 validateNumberOfRowsInMeta(table, numRegions, ADMIN.getConnection());
101 List<HRegionInfo> hris = MetaTableAccessor.getTableRegions(TEST_UTIL.getZooKeeperWatcher(),
102 ADMIN.getConnection(), table);
103 assert(hris.size() == numRegions * numReplica);
104 } finally {
105 ADMIN.disableTable(table);
106 ADMIN.deleteTable(table);
107 }
108 }
109
110 @Test
111 public void testCreateTableWithMultipleReplicas() throws Exception {
112 final TableName table = TableName.valueOf("fooTable");
113 final int numRegions = 3;
114 final int numReplica = 2;
115 try {
116 HTableDescriptor desc = new HTableDescriptor(table);
117 desc.setRegionReplication(numReplica);
118 desc.addFamily(new HColumnDescriptor("family"));
119 ADMIN.createTable(desc, Bytes.toBytes("A"), Bytes.toBytes("Z"), numRegions);
120 TEST_UTIL.waitTableEnabled(table);
121 validateNumberOfRowsInMeta(table, numRegions, ADMIN.getConnection());
122
123 List<HRegionInfo> hris = MetaTableAccessor.getTableRegions(
124 TEST_UTIL.getZooKeeperWatcher(), ADMIN.getConnection(), table);
125 assert(hris.size() == numRegions * numReplica);
126
127 for (int i = 0; i < numRegions; i++) {
128 for (int j = 0; j < numReplica; j++) {
129 HRegionInfo replica = RegionReplicaUtil.getRegionInfoForReplica(hris.get(i), j);
130 RegionState state = TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager()
131 .getRegionStates().getRegionState(replica);
132 assert (state != null);
133 }
134 }
135
136 List<Result> metaRows = MetaTableAccessor.fullScanOfMeta(ADMIN.getConnection());
137 int numRows = 0;
138 for (Result result : metaRows) {
139 RegionLocations locations = MetaTableAccessor.getRegionLocations(result);
140 HRegionInfo hri = locations.getRegionLocation().getRegionInfo();
141 if (!hri.getTable().equals(table)) continue;
142 numRows += 1;
143 HRegionLocation[] servers = locations.getRegionLocations();
144
145 assert(servers.length == 2);
146 assert(!servers[0].equals(servers[1]));
147 }
148 assert(numRows == numRegions);
149
150
151
152 validateFromSnapshotFromMeta(TEST_UTIL, table, numRegions, numReplica,
153 ADMIN.getConnection());
154
155
156 ServerName master = TEST_UTIL.getHBaseClusterInterface().getClusterStatus().getMaster();
157 TEST_UTIL.getHBaseClusterInterface().stopMaster(master);
158 TEST_UTIL.getHBaseClusterInterface().waitForMasterToStop(master, 30000);
159 TEST_UTIL.getHBaseClusterInterface().startMaster(master.getHostname(), master.getPort());
160 TEST_UTIL.getHBaseClusterInterface().waitForActiveAndReadyMaster();
161 for (int i = 0; i < numRegions; i++) {
162 for (int j = 0; j < numReplica; j++) {
163 HRegionInfo replica = RegionReplicaUtil.getRegionInfoForReplica(hris.get(i), j);
164 RegionState state = TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager()
165 .getRegionStates().getRegionState(replica);
166 assert (state != null);
167 }
168 }
169 validateFromSnapshotFromMeta(TEST_UTIL, table, numRegions, numReplica,
170 ADMIN.getConnection());
171
172
173
174 TEST_UTIL.getConfiguration().setBoolean("hbase.master.startup.retainassign", true);
175 TEST_UTIL.shutdownMiniHBaseCluster();
176 TEST_UTIL.startMiniHBaseCluster(1, numSlaves);
177 TEST_UTIL.waitTableEnabled(table);
178 validateFromSnapshotFromMeta(TEST_UTIL, table, numRegions, numReplica,
179 ADMIN.getConnection());
180
181
182
183 TEST_UTIL.shutdownMiniHBaseCluster();
184 TEST_UTIL.startMiniHBaseCluster(1, 1);
185 TEST_UTIL.waitTableEnabled(table);
186 validateSingleRegionServerAssignment(ADMIN.getConnection(), numRegions, numReplica);
187 for (int i = 1; i < numSlaves; i++) {
188 TEST_UTIL.getMiniHBaseCluster().startRegionServer();
189 }
190
191
192 ADMIN.disableTable(table);
193 assert(ADMIN.isTableDisabled(table));
194
195 desc.setRegionReplication(numReplica + 1);
196 ADMIN.modifyTable(table, desc);
197 ADMIN.enableTable(table);
198 assert(ADMIN.isTableEnabled(table));
199 List<HRegionInfo> regions = TEST_UTIL.getMiniHBaseCluster().getMaster()
200 .getAssignmentManager().getRegionStates().getRegionsOfTable(table);
201 assert(regions.size() == numRegions * (numReplica + 1));
202
203
204 ADMIN.disableTable(table);
205 desc.setRegionReplication(numReplica);
206 ADMIN.modifyTable(table, desc);
207 ADMIN.enableTable(table);
208 assert(ADMIN.isTableEnabled(table));
209 regions = TEST_UTIL.getMiniHBaseCluster().getMaster()
210 .getAssignmentManager().getRegionStates().getRegionsOfTable(table);
211 assert(regions.size() == numRegions * numReplica);
212
213 hris = MetaTableAccessor.getTableRegions(TEST_UTIL.getZooKeeperWatcher(),
214 ADMIN.getConnection(), table);
215 assert(hris.size() == numRegions * numReplica);
216
217
218
219 Map<HRegionInfo, Integer> defaultReplicas = new HashMap<HRegionInfo, Integer>();
220 for (HRegionInfo hri : hris) {
221 Integer i;
222 HRegionInfo regionReplica0 = RegionReplicaUtil.getRegionInfoForDefaultReplica(hri);
223 defaultReplicas.put(regionReplica0,
224 (i = defaultReplicas.get(regionReplica0)) == null ? 1 : i + 1);
225 }
226 assert(defaultReplicas.size() == numRegions);
227 Collection<Integer> counts = new HashSet<Integer>(defaultReplicas.values());
228 assert(counts.size() == 1 && counts.contains(new Integer(numReplica)));
229 } finally {
230 ADMIN.disableTable(table);
231 ADMIN.deleteTable(table);
232 }
233 }
234
235
236 public void testIncompleteMetaTableReplicaInformation() throws Exception {
237 final TableName table = TableName.valueOf("fooTableTest1");
238 final int numRegions = 3;
239 final int numReplica = 2;
240 try {
241
242
243 HTableDescriptor desc = new HTableDescriptor(table);
244 desc.setRegionReplication(numReplica);
245 desc.addFamily(new HColumnDescriptor("family"));
246 ADMIN.createTable(desc, Bytes.toBytes("A"), Bytes.toBytes("Z"), numRegions);
247 TEST_UTIL.waitTableEnabled(table);
248 Set<byte[]> tableRows = new HashSet<byte[]>();
249 List<HRegionInfo> hris = MetaTableAccessor.getTableRegions(TEST_UTIL.getZooKeeperWatcher(),
250 ADMIN.getConnection(), table);
251 for (HRegionInfo hri : hris) {
252 tableRows.add(hri.getRegionName());
253 }
254 ADMIN.disableTable(table);
255
256
257 Table metaTable = new HTable(TableName.META_TABLE_NAME, ADMIN.getConnection());
258 for (byte[] row : tableRows) {
259 Delete deleteOneReplicaLocation = new Delete(row);
260 deleteOneReplicaLocation.deleteColumns(HConstants.CATALOG_FAMILY,
261 MetaTableAccessor.getServerColumn(1));
262 deleteOneReplicaLocation.deleteColumns(HConstants.CATALOG_FAMILY,
263 MetaTableAccessor.getSeqNumColumn(1));
264 deleteOneReplicaLocation.deleteColumns(HConstants.CATALOG_FAMILY,
265 MetaTableAccessor.getStartCodeColumn(1));
266 metaTable.delete(deleteOneReplicaLocation);
267 }
268 metaTable.close();
269
270
271 ADMIN.enableTable(table);
272 assert(ADMIN.isTableEnabled(table));
273 List<HRegionInfo> regions = TEST_UTIL.getMiniHBaseCluster().getMaster()
274 .getAssignmentManager().getRegionStates().getRegionsOfTable(table);
275 assert(regions.size() == numRegions * numReplica);
276 } finally {
277 ADMIN.disableTable(table);
278 ADMIN.deleteTable(table);
279 }
280 }
281
282 private String printRegions(List<HRegionInfo> regions) {
283 StringBuffer strBuf = new StringBuffer();
284 for (HRegionInfo r : regions) {
285 strBuf.append(" ____ " + r.toString());
286 }
287 return strBuf.toString();
288 }
289
290 private void validateNumberOfRowsInMeta(final TableName table, int numRegions,
291 Connection connection) throws IOException {
292 assert(ADMIN.tableExists(table));
293 final AtomicInteger count = new AtomicInteger();
294 Visitor visitor = new Visitor() {
295 @Override
296 public boolean visit(Result r) throws IOException {
297 if (HRegionInfo.getHRegionInfo(r).getTable().equals(table)) count.incrementAndGet();
298 return true;
299 }
300 };
301 MetaTableAccessor.fullScan(connection, visitor);
302 assert(count.get() == numRegions);
303 }
304
305 private void validateFromSnapshotFromMeta(HBaseTestingUtility util, TableName table,
306 int numRegions, int numReplica, Connection connection) throws IOException {
307 SnapshotOfRegionAssignmentFromMeta snapshot = new SnapshotOfRegionAssignmentFromMeta(
308 connection);
309 snapshot.initialize();
310 Map<HRegionInfo, ServerName> regionToServerMap = snapshot.getRegionToRegionServerMap();
311 assert(regionToServerMap.size() == numRegions * numReplica + 1);
312 Map<ServerName, List<HRegionInfo>> serverToRegionMap = snapshot.getRegionServerToRegionMap();
313 for (Map.Entry<ServerName, List<HRegionInfo>> entry : serverToRegionMap.entrySet()) {
314 if (entry.getKey().equals(util.getHBaseCluster().getMaster().getServerName())) {
315 continue;
316 }
317 List<HRegionInfo> regions = entry.getValue();
318 Set<byte[]> setOfStartKeys = new HashSet<byte[]>();
319 for (HRegionInfo region : regions) {
320 byte[] startKey = region.getStartKey();
321 if (region.getTable().equals(table)) {
322 setOfStartKeys.add(startKey);
323 LOG.info("--STARTKEY " + new String(startKey)+"--");
324 }
325 }
326
327
328 assertEquals(numRegions, setOfStartKeys.size());
329 }
330 }
331
332 private void validateSingleRegionServerAssignment(Connection connection, int numRegions,
333 int numReplica) throws IOException {
334 SnapshotOfRegionAssignmentFromMeta snapshot = new SnapshotOfRegionAssignmentFromMeta(
335 connection);
336 snapshot.initialize();
337 Map<HRegionInfo, ServerName> regionToServerMap = snapshot.getRegionToRegionServerMap();
338 assertEquals(regionToServerMap.size(), numRegions * numReplica + 1);
339 Map<ServerName, List<HRegionInfo>> serverToRegionMap = snapshot.getRegionServerToRegionMap();
340 assertEquals(serverToRegionMap.keySet().size(), 1);
341 for (Map.Entry<ServerName, List<HRegionInfo>> entry : serverToRegionMap.entrySet()) {
342 if (entry.getKey().equals(TEST_UTIL.getHBaseCluster().getMaster().getServerName())) {
343 continue;
344 }
345 assertEquals(entry.getValue().size(), numRegions * numReplica + 1);
346 }
347 }
348 }