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.http;
019
020import java.util.Collections;
021import java.util.LinkedHashMap;
022import java.util.List;
023import java.util.Map;
024import java.util.stream.Collectors;
025import java.util.stream.StreamSupport;
026import org.apache.commons.lang3.builder.EqualsBuilder;
027import org.apache.commons.lang3.builder.HashCodeBuilder;
028import org.apache.commons.lang3.builder.ToStringBuilder;
029import org.apache.commons.lang3.builder.ToStringStyle;
030import org.apache.hadoop.hbase.HConstants;
031import org.apache.hadoop.hbase.HRegionLocation;
032import org.apache.hadoop.hbase.MetaTableAccessor;
033import org.apache.hadoop.hbase.RegionLocations;
034import org.apache.hadoop.hbase.ServerName;
035import org.apache.hadoop.hbase.client.RegionInfo;
036import org.apache.hadoop.hbase.client.Result;
037import org.apache.hadoop.hbase.master.RegionState;
038import org.apache.hadoop.hbase.master.assignment.RegionStateStore;
039import org.apache.hadoop.hbase.util.Bytes;
040import org.apache.hadoop.hbase.util.PairOfSameType;
041import org.apache.yetus.audience.InterfaceAudience;
042
043/**
044 * A POJO that consolidates the information about a single region replica that's stored in meta.
045 */
046@InterfaceAudience.Private
047public final class RegionReplicaInfo {
048  private final byte[] row;
049  private final RegionInfo regionInfo;
050  private final RegionState.State regionState;
051  private final ServerName serverName;
052  private final long seqNum;
053  /** See {@link org.apache.hadoop.hbase.HConstants#SERVERNAME_QUALIFIER_STR}. */
054  private final ServerName targetServerName;
055  private final Map<String, RegionInfo> mergeRegionInfo;
056  private final Map<String, RegionInfo> splitRegionInfo;
057
058  private RegionReplicaInfo(final Result result, final HRegionLocation location) {
059    this.row = result != null ? result.getRow() : null;
060    this.regionInfo = location != null ? location.getRegion() : null;
061    this.regionState = (result != null && regionInfo != null)
062      ? RegionStateStore.getRegionState(result, regionInfo)
063      : null;
064    this.serverName = location != null ? location.getServerName() : null;
065    this.seqNum = (location != null) ? location.getSeqNum() : HConstants.NO_SEQNUM;
066    this.targetServerName = (result != null && regionInfo != null)
067      ? MetaTableAccessor.getTargetServerName(result, regionInfo.getReplicaId())
068      : null;
069    this.mergeRegionInfo =
070      (result != null) ? MetaTableAccessor.getMergeRegionsWithName(result.rawCells()) : null;
071
072    if (result != null) {
073      PairOfSameType<RegionInfo> daughterRegions = MetaTableAccessor.getDaughterRegions(result);
074      this.splitRegionInfo = new LinkedHashMap<>();
075      if (daughterRegions.getFirst() != null) {
076        splitRegionInfo.put(HConstants.SPLITA_QUALIFIER_STR, daughterRegions.getFirst());
077      }
078      if (daughterRegions.getSecond() != null) {
079        splitRegionInfo.put(HConstants.SPLITB_QUALIFIER_STR, daughterRegions.getSecond());
080      }
081    } else {
082      this.splitRegionInfo = null;
083    }
084  }
085
086  public static List<RegionReplicaInfo> from(final Result result) {
087    if (result == null) {
088      return Collections.singletonList(null);
089    }
090
091    final RegionLocations locations = MetaTableAccessor.getRegionLocations(result);
092    if (locations == null) {
093      return Collections.singletonList(null);
094    }
095
096    return StreamSupport.stream(locations.spliterator(), false)
097      .map(location -> new RegionReplicaInfo(result, location)).collect(Collectors.toList());
098  }
099
100  public byte[] getRow() {
101    return row;
102  }
103
104  public RegionInfo getRegionInfo() {
105    return regionInfo;
106  }
107
108  public byte[] getRegionName() {
109    return regionInfo != null ? regionInfo.getRegionName() : null;
110  }
111
112  public byte[] getStartKey() {
113    return regionInfo != null ? regionInfo.getStartKey() : null;
114  }
115
116  public byte[] getEndKey() {
117    return regionInfo != null ? regionInfo.getEndKey() : null;
118  }
119
120  public Integer getReplicaId() {
121    return regionInfo != null ? regionInfo.getReplicaId() : null;
122  }
123
124  public RegionState.State getRegionState() {
125    return regionState;
126  }
127
128  public ServerName getServerName() {
129    return serverName;
130  }
131
132  public long getSeqNum() {
133    return seqNum;
134  }
135
136  public ServerName getTargetServerName() {
137    return targetServerName;
138  }
139
140  public Map<String, RegionInfo> getMergeRegionInfo() {
141    return mergeRegionInfo;
142  }
143
144  public Map<String, RegionInfo> getSplitRegionInfo() {
145    return splitRegionInfo;
146  }
147
148  @Override
149  public boolean equals(Object other) {
150    if (this == other) {
151      return true;
152    }
153
154    if (other == null || getClass() != other.getClass()) {
155      return false;
156    }
157
158    RegionReplicaInfo that = (RegionReplicaInfo) other;
159
160    return new EqualsBuilder().append(row, that.row).append(regionInfo, that.regionInfo)
161      .append(regionState, that.regionState).append(serverName, that.serverName)
162      .append(seqNum, that.seqNum).append(targetServerName, that.targetServerName)
163      .append(mergeRegionInfo, that.mergeRegionInfo).append(splitRegionInfo, that.splitRegionInfo)
164      .isEquals();
165  }
166
167  @Override
168  public int hashCode() {
169    return new HashCodeBuilder(17, 37).append(row).append(regionInfo).append(regionState)
170      .append(serverName).append(seqNum).append(targetServerName).append(mergeRegionInfo)
171      .append(splitRegionInfo).toHashCode();
172  }
173
174  @Override
175  public String toString() {
176    return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
177      .append("row", Bytes.toStringBinary(row)).append("regionInfo", regionInfo)
178      .append("regionState", regionState).append("serverName", serverName).append("seqNum", seqNum)
179      .append("transitioningOnServerName", targetServerName).append("merge*", mergeRegionInfo)
180      .append("split*", splitRegionInfo).toString();
181  }
182}