HBASE-4509 [hbck] Improve region map output
git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1177900 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
a4532fbd3f
commit
15e66a3ab5
|
@ -705,6 +705,8 @@ Release 0.90.5 - Unreleased
|
|||
(Jonathan Hsieh)
|
||||
HBASE-4506 [hbck] Allow HBaseFsck to be instantiated without connecting
|
||||
(Jonathan Hsieh)
|
||||
HBASE-4509 [hbck] Improve region map output
|
||||
(Jonathan Hsieh)
|
||||
|
||||
Release 0.90.4 - August 10, 2011
|
||||
|
||||
|
|
|
@ -72,6 +72,7 @@ import org.apache.zookeeper.KeeperException;
|
|||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.TreeMultimap;
|
||||
|
||||
/**
|
||||
* Check consistency among the in-memory states of the master and the
|
||||
|
@ -583,6 +584,10 @@ public class HBaseFsck {
|
|||
final List<HbckInfo> backwards = new ArrayList<HbckInfo>();
|
||||
final RegionSplitCalculator<HbckInfo> sc = new RegionSplitCalculator<HbckInfo>(cmp);
|
||||
|
||||
// key = start split, values = set of splits in problem group
|
||||
final Multimap<byte[], HbckInfo> overlapGroups =
|
||||
TreeMultimap.create(RegionSplitCalculator.BYTES_COMPARATOR, cmp);
|
||||
|
||||
TInfo(String name) {
|
||||
this.tableName = name;
|
||||
deployedOn = new TreeSet <ServerName>();
|
||||
|
@ -629,26 +634,44 @@ public class HBaseFsck {
|
|||
* @return false if there are errors
|
||||
*/
|
||||
public boolean checkRegionChain() {
|
||||
|
||||
int originalErrorsCount = errors.getErrorList().size();
|
||||
Multimap<byte[], HbckInfo> regions = sc.calcCoverage();
|
||||
SortedSet<byte[]> splits = sc.getSplits();
|
||||
|
||||
byte[] prevKey = null;
|
||||
for (byte[] key: splits) {
|
||||
byte[] problemKey = null;
|
||||
for (byte[] key : splits) {
|
||||
Collection<HbckInfo> ranges = regions.get(key);
|
||||
if (prevKey == null && !Bytes.equals(key, HConstants.EMPTY_BYTE_ARRAY)) {
|
||||
for (HbckInfo rng : ranges) {
|
||||
// TODO offline fix region hole.
|
||||
|
||||
errors.reportError(ERROR_CODE.FIRST_REGION_STARTKEY_NOT_EMPTY,
|
||||
"First region should start with an empty key.",
|
||||
"First region should start with an empty key. When HBase is "
|
||||
+ "online, create a new regio to plug the hole using hbck -fix",
|
||||
this, rng);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the startkeys are different
|
||||
if (ranges.size() > 1) {
|
||||
|
||||
if (ranges.size() == 1) {
|
||||
// this split key is ok -- no overlap, not a hole.
|
||||
if (problemKey != null) {
|
||||
LOG.warn("reached end of problem group: " + Bytes.toStringBinary(key));
|
||||
}
|
||||
problemKey = null; // fell through, no more problem.
|
||||
} else if (ranges.size() > 1) {
|
||||
// set the new problem key group name, if already have problem key, just
|
||||
// keep using it.
|
||||
if (problemKey == null) {
|
||||
// only for overlap regions.
|
||||
LOG.warn("Naming new problem group: " + Bytes.toStringBinary(key));
|
||||
problemKey = key;
|
||||
}
|
||||
overlapGroups.putAll(problemKey, ranges);
|
||||
|
||||
// record errors
|
||||
ArrayList<HbckInfo> subRange = new ArrayList<HbckInfo>(ranges);
|
||||
// this dumb and n^2 but this shouldn't happen often
|
||||
// this dumb and n^2 but this shouldn't happen often
|
||||
for (HbckInfo r1 : ranges) {
|
||||
subRange.remove(r1);
|
||||
for (HbckInfo r2 : subRange) {
|
||||
|
@ -661,30 +684,42 @@ public class HBaseFsck {
|
|||
"Multiple regions have the same startkey: "
|
||||
+ Bytes.toStringBinary(key), this, r2);
|
||||
} else {
|
||||
// overlap
|
||||
errors.reportError(ERROR_CODE.OVERLAP_IN_REGION_CHAIN,
|
||||
"There is an overlap in the region chain.",
|
||||
this, r1);
|
||||
// overlap
|
||||
errors.reportError(ERROR_CODE.OVERLAP_IN_REGION_CHAIN,
|
||||
"There is an overlap in the region chain.",
|
||||
this, r1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ranges.size() == 0) {
|
||||
|
||||
} else if (ranges.size() == 0) {
|
||||
if (problemKey != null) {
|
||||
LOG.warn("reached end of problem group: " + Bytes.toStringBinary(key));
|
||||
}
|
||||
problemKey = null;
|
||||
|
||||
byte[] holeStopKey = sc.getSplits().higher(key);
|
||||
// if higher key is null we reached the top.
|
||||
if (holeStopKey != null) {
|
||||
// hole
|
||||
errors.reportError(ERROR_CODE.HOLE_IN_REGION_CHAIN,
|
||||
"There is a hole in the region chain between "
|
||||
+ Bytes.toString(key) + " and " + Bytes.toString(holeStopKey));
|
||||
"There is a hole in the region chain between "
|
||||
+ Bytes.toStringBinary(key) + " and "
|
||||
+ Bytes.toStringBinary(holeStopKey)
|
||||
+ ". When HBase is online, create a new regioninfo and region "
|
||||
+ "dir to plug the hole.");
|
||||
}
|
||||
}
|
||||
}
|
||||
prevKey = key;
|
||||
}
|
||||
|
||||
if (details) {
|
||||
// do full region split map dump
|
||||
dump(sc.getSplits(), regions);
|
||||
dump(splits, regions);
|
||||
dumpOverlapProblems(overlapGroups);
|
||||
System.out.println("There are " + overlapGroups.keySet().size()
|
||||
+ " problem groups with " + overlapGroups.size()
|
||||
+ " problem regions");
|
||||
}
|
||||
return errors.getErrorList().size() == originalErrorsCount;
|
||||
}
|
||||
|
@ -695,7 +730,7 @@ public class HBaseFsck {
|
|||
* @param splits
|
||||
* @param regions
|
||||
*/
|
||||
void dump(TreeSet<byte[]> splits, Multimap<byte[], HbckInfo> regions) {
|
||||
void dump(SortedSet<byte[]> splits, Multimap<byte[], HbckInfo> regions) {
|
||||
// we display this way because the last end key should be displayed as well.
|
||||
for (byte[] k : splits) {
|
||||
System.out.print(Bytes.toString(k) + ":\t");
|
||||
|
@ -706,7 +741,23 @@ public class HBaseFsck {
|
|||
System.out.println();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void dumpOverlapProblems(Multimap<byte[], HbckInfo> regions) {
|
||||
// we display this way because the last end key should be displayed as
|
||||
// well.
|
||||
for (byte[] k : regions.keySet()) {
|
||||
System.out.print(Bytes.toStringBinary(k) + ":\n");
|
||||
for (HbckInfo r : regions.get(k)) {
|
||||
System.out.print("[ " + r.toString() + ", "
|
||||
+ Bytes.toStringBinary(r.getEndKey()) + "]\n");
|
||||
}
|
||||
System.out.println("----");
|
||||
}
|
||||
}
|
||||
|
||||
public Multimap<byte[], HbckInfo> getOverlapGroups(String table) {
|
||||
return tablesInfo.get(table).overlapGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -899,7 +950,7 @@ public class HBaseFsck {
|
|||
/**
|
||||
* Maintain information about a particular region.
|
||||
*/
|
||||
static class HbckInfo implements KeyRange {
|
||||
public static class HbckInfo implements KeyRange {
|
||||
boolean onlyEdits = false;
|
||||
MetaEntry metaEntry = null;
|
||||
FileStatus foundRegionDir = null;
|
||||
|
|
|
@ -75,21 +75,23 @@ public class TestHBaseFsck {
|
|||
TEST_UTIL.shutdownMiniCluster();
|
||||
}
|
||||
|
||||
private List<ERROR_CODE> doFsck(boolean fix) throws Exception {
|
||||
private HBaseFsck doFsck(boolean fix) throws Exception {
|
||||
HBaseFsck fsck = new HBaseFsck(conf);
|
||||
fsck.connect();
|
||||
fsck.displayFullReport(); // i.e. -details
|
||||
fsck.setTimeLag(0);
|
||||
fsck.setFixErrors(fix);
|
||||
fsck.doWork();
|
||||
return fsck.getErrors().getErrorList();
|
||||
return fsck;
|
||||
}
|
||||
|
||||
private void assertNoErrors(List<ERROR_CODE> errs) throws Exception {
|
||||
private void assertNoErrors(HBaseFsck fsck) throws Exception {
|
||||
List<ERROR_CODE> errs = fsck.getErrors().getErrorList();
|
||||
assertEquals(0, errs.size());
|
||||
}
|
||||
|
||||
private void assertErrors(List<ERROR_CODE> errs, ERROR_CODE[] expectedErrors) {
|
||||
private void assertErrors(HBaseFsck fsck, ERROR_CODE[] expectedErrors) {
|
||||
List<ERROR_CODE> errs = fsck.getErrors().getErrorList();
|
||||
assertEquals(Arrays.asList(expectedErrors), errs);
|
||||
}
|
||||
|
||||
|
@ -237,10 +239,15 @@ public class TestHBaseFsck {
|
|||
assertNoErrors(doFsck(false));
|
||||
String table = "tableClean";
|
||||
try {
|
||||
setupTable(table);
|
||||
HBaseFsck hbck = doFsck(false);
|
||||
assertNoErrors(hbck);
|
||||
|
||||
setupTable(table);
|
||||
|
||||
// We created 1 table, should be fine
|
||||
assertNoErrors(doFsck(false));
|
||||
hbck = doFsck( false);
|
||||
assertNoErrors(hbck);
|
||||
assertEquals(0, hbck.getOverlapGroups(table).size());
|
||||
} finally {
|
||||
deleteTable(table);
|
||||
}
|
||||
|
@ -263,9 +270,10 @@ public class TestHBaseFsck {
|
|||
TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager()
|
||||
.waitForAssignment(hriDupe);
|
||||
|
||||
assertErrors(doFsck(false),
|
||||
new ERROR_CODE[] { ERROR_CODE.DUPE_STARTKEYS,
|
||||
HBaseFsck hbck = doFsck(false);
|
||||
assertErrors(hbck, new ERROR_CODE[] { ERROR_CODE.DUPE_STARTKEYS,
|
||||
ERROR_CODE.DUPE_STARTKEYS});
|
||||
assertEquals(2, hbck.getOverlapGroups(table).size());
|
||||
} finally {
|
||||
deleteTable(table);
|
||||
}
|
||||
|
@ -286,9 +294,12 @@ public class TestHBaseFsck {
|
|||
TEST_UTIL.getHBaseCluster().getMaster().assignRegion(hriOverlap);
|
||||
TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager()
|
||||
.waitForAssignment(hriOverlap);
|
||||
assertErrors(doFsck(false), new ERROR_CODE[] {
|
||||
|
||||
HBaseFsck hbck = doFsck(false);
|
||||
assertErrors(hbck, new ERROR_CODE[] {
|
||||
ERROR_CODE.OVERLAP_IN_REGION_CHAIN,
|
||||
ERROR_CODE.OVERLAP_IN_REGION_CHAIN });
|
||||
assertEquals(3, hbck.getOverlapGroups(table).size());
|
||||
} finally {
|
||||
deleteTable(table);
|
||||
}
|
||||
|
@ -313,8 +324,11 @@ public class TestHBaseFsck {
|
|||
TEST_UTIL.getHBaseAdmin().disableTable(table);
|
||||
deleteRegion(conf, tbl.getTableDescriptor(), Bytes.toBytes("C"), Bytes.toBytes(""));
|
||||
TEST_UTIL.getHBaseAdmin().enableTable(table);
|
||||
assertErrors(doFsck(false),
|
||||
new ERROR_CODE[] { ERROR_CODE.HOLE_IN_REGION_CHAIN });
|
||||
|
||||
HBaseFsck hbck = doFsck(false);
|
||||
assertErrors(hbck, new ERROR_CODE[] { ERROR_CODE.HOLE_IN_REGION_CHAIN });
|
||||
// holes are separate from overlap groups
|
||||
assertEquals(0, hbck.getOverlapGroups(table).size());
|
||||
} finally {
|
||||
deleteTable(table);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue