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}