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.webapp;
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 = (result != null)
070      ? MetaTableAccessor.getMergeRegionsWithName(result.rawCells())
071      : null;
072
073    if (result != null) {
074      PairOfSameType<RegionInfo> daughterRegions = MetaTableAccessor.getDaughterRegions(result);
075      this.splitRegionInfo = new LinkedHashMap<>();
076      if (daughterRegions.getFirst() != null) {
077        splitRegionInfo.put(HConstants.SPLITA_QUALIFIER_STR, daughterRegions.getFirst());
078      }
079      if (daughterRegions.getSecond() != null) {
080        splitRegionInfo.put(HConstants.SPLITB_QUALIFIER_STR, daughterRegions.getSecond());
081      }
082    } else {
083      this.splitRegionInfo = null;
084    }
085  }
086
087  public static List<RegionReplicaInfo> from(final Result result) {
088    if (result == null) {
089      return Collections.singletonList(null);
090    }
091
092    final RegionLocations locations = MetaTableAccessor.getRegionLocations(result);
093    if (locations == null) {
094      return Collections.singletonList(null);
095    }
096
097    return StreamSupport.stream(locations.spliterator(), false)
098      .map(location -> new RegionReplicaInfo(result, location))
099      .collect(Collectors.toList());
100  }
101
102  public byte[] getRow() {
103    return row;
104  }
105
106  public RegionInfo getRegionInfo() {
107    return regionInfo;
108  }
109
110  public byte[] getRegionName() {
111    return regionInfo != null ? regionInfo.getRegionName() : null;
112  }
113
114  public byte[] getStartKey() {
115    return regionInfo != null ? regionInfo.getStartKey() : null;
116  }
117
118  public byte[] getEndKey() {
119    return regionInfo != null ? regionInfo.getEndKey() : null;
120  }
121
122  public Integer getReplicaId() {
123    return regionInfo != null ? regionInfo.getReplicaId() : null;
124  }
125
126  public RegionState.State getRegionState() {
127    return regionState;
128  }
129
130  public ServerName getServerName() {
131    return serverName;
132  }
133
134  public long getSeqNum() {
135    return seqNum;
136  }
137
138  public ServerName getTargetServerName() {
139    return targetServerName;
140  }
141
142  public Map<String, RegionInfo> getMergeRegionInfo() {
143    return mergeRegionInfo;
144  }
145
146  public Map<String, RegionInfo> getSplitRegionInfo() {
147    return splitRegionInfo;
148  }
149
150  @Override
151  public boolean equals(Object other) {
152    if (this == other) {
153      return true;
154    }
155
156    if (other == null || getClass() != other.getClass()) {
157      return false;
158    }
159
160    RegionReplicaInfo that = (RegionReplicaInfo) other;
161
162    return new EqualsBuilder()
163      .append(row, that.row)
164      .append(regionInfo, that.regionInfo)
165      .append(regionState, that.regionState)
166      .append(serverName, that.serverName)
167      .append(seqNum, that.seqNum)
168      .append(targetServerName, that.targetServerName)
169      .append(mergeRegionInfo, that.mergeRegionInfo)
170      .append(splitRegionInfo, that.splitRegionInfo)
171      .isEquals();
172  }
173
174  @Override
175  public int hashCode() {
176    return new HashCodeBuilder(17, 37)
177      .append(row)
178      .append(regionInfo)
179      .append(regionState)
180      .append(serverName)
181      .append(seqNum)
182      .append(targetServerName)
183      .append(mergeRegionInfo)
184      .append(splitRegionInfo)
185      .toHashCode();
186  }
187
188  @Override
189  public String toString() {
190    return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
191      .append("row", Bytes.toStringBinary(row))
192      .append("regionInfo", regionInfo)
193      .append("regionState", regionState)
194      .append("serverName", serverName)
195      .append("seqNum", seqNum)
196      .append("transitioningOnServerName", targetServerName)
197      .append("merge*", mergeRegionInfo)
198      .append("split*", splitRegionInfo)
199      .toString();
200  }
201}