001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.master.janitor; 019 020import java.util.ArrayList; 021import java.util.List; 022import java.util.Map; 023import java.util.TreeMap; 024import org.apache.hadoop.hbase.ServerName; 025import org.apache.hadoop.hbase.client.RegionInfo; 026import org.apache.hadoop.hbase.client.Result; 027import org.apache.hadoop.hbase.master.janitor.CatalogJanitor.SplitParentFirstComparator; 028import org.apache.hadoop.hbase.util.Bytes; 029import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 030import org.apache.hadoop.hbase.util.Pair; 031import org.apache.yetus.audience.InterfaceAudience; 032 033/** 034 * Report made by ReportMakingVisitor 035 */ 036@InterfaceAudience.Private 037public class CatalogJanitorReport { 038 private final long now = EnvironmentEdgeManager.currentTime(); 039 040 // Keep Map of found split parents. These are candidates for cleanup. 041 // Use a comparator that has split parents come before its daughters. 042 final Map<RegionInfo, Result> splitParents = new TreeMap<>(new SplitParentFirstComparator()); 043 final Map<RegionInfo, Result> mergedRegions = new TreeMap<>(RegionInfo.COMPARATOR); 044 int count = 0; 045 046 final List<Pair<RegionInfo, RegionInfo>> holes = new ArrayList<>(); 047 final List<Pair<RegionInfo, RegionInfo>> overlaps = new ArrayList<>(); 048 049 /** 050 * TODO: If CatalogJanitor finds an 'Unknown Server', it should 'fix' it by queuing a 051 * {@link org.apache.hadoop.hbase.master.procedure.HBCKServerCrashProcedure} for found server for 052 * it to clean up meta. 053 */ 054 final List<Pair<RegionInfo, ServerName>> unknownServers = new ArrayList<>(); 055 056 final List<byte[]> emptyRegionInfo = new ArrayList<>(); 057 058 public long getCreateTime() { 059 return this.now; 060 } 061 062 public List<Pair<RegionInfo, RegionInfo>> getHoles() { 063 return this.holes; 064 } 065 066 /** 067 * @return Overlap pairs found as we scanned hbase:meta; ordered by hbase:meta table sort. Pairs 068 * of overlaps may have overlap with subsequent pairs. 069 * @see MetaFixer#calculateMerges(int, List) where we aggregate overlaps for a single 'merge' 070 * call. 071 */ 072 public List<Pair<RegionInfo, RegionInfo>> getOverlaps() { 073 return this.overlaps; 074 } 075 076 public Map<RegionInfo, Result> getMergedRegions() { 077 return this.mergedRegions; 078 } 079 080 public List<Pair<RegionInfo, ServerName>> getUnknownServers() { 081 return unknownServers; 082 } 083 084 public List<byte[]> getEmptyRegionInfo() { 085 return emptyRegionInfo; 086 } 087 088 /** Returns True if an 'empty' lastReport -- no problems found. */ 089 public boolean isEmpty() { 090 return this.holes.isEmpty() && this.overlaps.isEmpty() && this.unknownServers.isEmpty() 091 && this.emptyRegionInfo.isEmpty(); 092 } 093 094 @Override 095 public String toString() { 096 StringBuilder sb = new StringBuilder(); 097 for (Pair<RegionInfo, RegionInfo> p : this.holes) { 098 if (sb.length() > 0) { 099 sb.append(", "); 100 } 101 sb.append("hole=").append(p.getFirst().getRegionNameAsString()).append("/") 102 .append(p.getSecond().getRegionNameAsString()); 103 } 104 for (Pair<RegionInfo, RegionInfo> p : this.overlaps) { 105 if (sb.length() > 0) { 106 sb.append(", "); 107 } 108 sb.append("overlap=").append(p.getFirst().getRegionNameAsString()).append("/") 109 .append(p.getSecond().getRegionNameAsString()); 110 } 111 for (byte[] r : this.emptyRegionInfo) { 112 if (sb.length() > 0) { 113 sb.append(", "); 114 } 115 sb.append("empty=").append(Bytes.toStringBinary(r)); 116 } 117 for (Pair<RegionInfo, ServerName> p : this.unknownServers) { 118 if (sb.length() > 0) { 119 sb.append(", "); 120 } 121 sb.append("unknown_server=").append(p.getSecond()).append("/") 122 .append(p.getFirst().getRegionNameAsString()); 123 } 124 return sb.toString(); 125 } 126}