1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.util;
21
22 import static org.apache.hadoop.hbase.util.HBaseFsck.ErrorReporter.ERROR_CODE;
23 import static org.junit.Assert.assertArrayEquals;
24 import static org.junit.Assert.assertEquals;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.hadoop.conf.Configuration;
29 import org.apache.hadoop.fs.FileStatus;
30 import org.apache.hadoop.fs.FileSystem;
31 import org.apache.hadoop.fs.Path;
32 import org.apache.hadoop.hbase.*;
33 import org.apache.hadoop.hbase.client.*;
34 import org.apache.hadoop.hbase.ipc.HRegionInterface;
35 import org.junit.BeforeClass;
36 import org.junit.Test;
37
38 import java.io.IOException;
39 import java.util.ArrayList;
40 import java.util.Arrays;
41 import java.util.List;
42 import java.util.Random;
43
44 public class TestHBaseFsck {
45
46 final Log LOG = LogFactory.getLog(getClass());
47 private final static HBaseTestingUtility TEST_UTIL =
48 new HBaseTestingUtility();
49 private final static Configuration conf = TEST_UTIL.getConfiguration();
50 private final static byte[] TABLE = Bytes.toBytes("table");
51 private final static byte[] FAM = Bytes.toBytes("fam");
52
53 @BeforeClass
54 public static void setUpBeforeClass() throws Exception {
55 TEST_UTIL.startMiniCluster(3);
56 }
57
58 private List doFsck(boolean fix) throws Exception {
59 HBaseFsck fsck = new HBaseFsck(conf);
60 fsck.displayFullReport();
61 fsck.setTimeLag(0);
62 fsck.setFixErrors(fix);
63 fsck.doWork();
64 return fsck.getErrors().getErrorList();
65 }
66
67 private void assertNoErrors(List errs) throws Exception {
68 assertEquals(0, errs.size());
69 }
70
71 private void assertErrors(List errs, ERROR_CODE[] expectedErrors) {
72 assertEquals(Arrays.asList(expectedErrors), errs);
73 }
74
75 @Test
76 public void testHBaseFsck() throws Exception {
77 assertNoErrors(doFsck(false));
78
79 TEST_UTIL.createTable(TABLE, FAM);
80
81
82 assertNoErrors(doFsck(false));
83
84
85
86 HTable meta = new HTable(conf, HTableDescriptor.META_TABLEDESC.getName());
87 ResultScanner scanner = meta.getScanner(new Scan());
88
89 resforloop:
90 for (Result res : scanner) {
91 long startCode = Bytes.toLong(res.getValue(HConstants.CATALOG_FAMILY,
92 HConstants.STARTCODE_QUALIFIER));
93
94 for (JVMClusterUtil.RegionServerThread rs :
95 TEST_UTIL.getHBaseCluster().getRegionServerThreads()) {
96
97 HServerInfo hsi = rs.getRegionServer().getServerInfo();
98
99
100 if (startCode != hsi.getStartCode()) {
101 Put put = new Put(res.getRow());
102 put.add(HConstants.CATALOG_FAMILY, HConstants.SERVER_QUALIFIER,
103 Bytes.toBytes(hsi.getHostnamePort()));
104 put.add(HConstants.CATALOG_FAMILY, HConstants.STARTCODE_QUALIFIER,
105 Bytes.toBytes(hsi.getStartCode()));
106 meta.put(put);
107 break resforloop;
108 }
109 }
110 }
111
112
113 assertErrors(doFsck(true), new ERROR_CODE[]{
114 ERROR_CODE.SERVER_DOES_NOT_MATCH_META});
115 Thread.sleep(15000);
116
117
118 assertNoErrors(doFsck(false));
119
120
121 new HTable(conf, TABLE).getScanner(new Scan());
122 }
123
124 private HRegionInfo createRegion(Configuration conf, final HTableDescriptor
125 htd, byte[] startKey, byte[] endKey)
126 throws IOException {
127 HTable meta = new HTable(conf, HConstants.META_TABLE_NAME);
128 HRegionInfo hri = new HRegionInfo(htd, startKey, endKey);
129 Put put = new Put(hri.getRegionName());
130 put.add(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER,
131 Writables.getBytes(hri));
132 meta.put(put);
133 return hri;
134 }
135
136 @Test
137
138
139
140 public void testHBaseFsckMeta() throws Exception {
141 assertNoErrors(doFsck(false));
142
143 HTable tbl = TEST_UTIL.createTable(Bytes.toBytes("table2"), FAM);
144
145 HRegionInfo hriOrig = tbl.getRegionsInfo().keySet().iterator().next();
146 HServerAddress rsAddressOrig = tbl.getRegionsInfo().get(hriOrig);
147
148 byte[][] startKeys = new byte[][]{
149 HConstants.EMPTY_BYTE_ARRAY,
150 Bytes.toBytes("A"),
151 Bytes.toBytes("B"),
152 Bytes.toBytes("C")
153 };
154 TEST_UTIL.createMultiRegions(conf, tbl, FAM, startKeys);
155 Path rootDir = new Path(conf.get(HConstants.HBASE_DIR));
156 FileSystem fs = rootDir.getFileSystem(conf);
157 Path p = new Path(rootDir + "/table2", hriOrig.getEncodedName());
158 fs.delete(p, true);
159
160 Thread.sleep(1 * 1000);
161 ArrayList servers = new ArrayList();
162 servers.add(rsAddressOrig);
163 HBaseFsckRepair.fixDupeAssignment(conf, hriOrig, servers);
164
165
166 assertNoErrors(doFsck(false));
167
168
169 HRegionInfo hriDupe = createRegion(conf, tbl.getTableDescriptor(),
170 Bytes.toBytes("A"), Bytes.toBytes("A2"));
171 TEST_UTIL.getHBaseCluster().getMaster().assignRegion(hriDupe);
172 TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager()
173 .waitForAssignment(hriDupe);
174 assertErrors(doFsck(false), new ERROR_CODE[]{ERROR_CODE.DUPE_STARTKEYS});
175
176
177 HRegionInfo hriOverlap = createRegion(conf, tbl.getTableDescriptor(),
178 Bytes.toBytes("A2"), Bytes.toBytes("B2"));
179 TEST_UTIL.getHBaseCluster().getMaster().assignRegion(hriOverlap);
180 TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager()
181 .waitForAssignment(hriOverlap);
182 assertErrors(doFsck(false), new ERROR_CODE[]{
183 ERROR_CODE.DUPE_STARTKEYS, ERROR_CODE.OVERLAP_IN_REGION_CHAIN,
184 ERROR_CODE.OVERLAP_IN_REGION_CHAIN});
185
186
187 HRegionInfo hriHole = createRegion(conf, tbl.getTableDescriptor(),
188 Bytes.toBytes("D"), Bytes.toBytes("E"));
189 TEST_UTIL.getHBaseCluster().getMaster().assignRegion(hriHole);
190 TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager()
191 .waitForAssignment(hriHole);
192
193 assertErrors(doFsck(false), new ERROR_CODE[]{ ERROR_CODE.DUPE_STARTKEYS,
194 ERROR_CODE.OVERLAP_IN_REGION_CHAIN, ERROR_CODE.OVERLAP_IN_REGION_CHAIN,
195 ERROR_CODE.HOLE_IN_REGION_CHAIN });
196
197 }
198
199 }