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