HBASE-23949 refactor loadBalancer implements for rsgroup balance by table to achieve...
[hbase.git] / hbase-server / src / main / java / org / apache / hadoop / hbase / util / HbckRegionInfo.java
blobde1d17942fccd8e0034b336e9937bf972c8c3175
1 /**
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 package org.apache.hadoop.hbase.util;
20 import java.io.IOException;
21 import java.util.Arrays;
22 import java.util.Comparator;
23 import java.util.List;
25 import org.apache.hadoop.conf.Configuration;
26 import org.apache.hadoop.fs.FileSystem;
27 import org.apache.hadoop.fs.Path;
28 import org.apache.hadoop.hbase.HRegionInfo;
29 import org.apache.hadoop.hbase.ServerName;
30 import org.apache.hadoop.hbase.TableName;
31 import org.apache.hadoop.hbase.client.RegionInfo;
32 import org.apache.hadoop.hbase.client.RegionReplicaUtil;
33 import org.apache.hadoop.hbase.regionserver.HRegionFileSystem;
34 import org.apache.yetus.audience.InterfaceAudience;
35 import org.apache.yetus.audience.InterfaceStability;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
39 import org.apache.hbase.thirdparty.com.google.common.base.Joiner;
40 import org.apache.hbase.thirdparty.com.google.common.collect.Lists;
42 /**
43 * Maintain information about a particular region. It gathers information
44 * from three places -- HDFS, META, and region servers.
46 @InterfaceAudience.Private
47 @InterfaceStability.Evolving
48 public class HbckRegionInfo implements KeyRange {
49 private static final Logger LOG = LoggerFactory.getLogger(HbckRegionInfo.class.getName());
51 private MetaEntry metaEntry = null; // info in META
52 private HdfsEntry hdfsEntry = null; // info in HDFS
53 private List<OnlineEntry> deployedEntries = Lists.newArrayList(); // on Region Server
54 private List<ServerName> deployedOn = Lists.newArrayList(); // info on RS's
55 private boolean skipChecks = false; // whether to skip further checks to this region info.
56 private boolean isMerged = false;// whether this region has already been merged into another one
57 private int deployedReplicaId = RegionInfo.DEFAULT_REPLICA_ID;
58 private RegionInfo primaryHRIForDeployedReplica = null;
60 public HbckRegionInfo(MetaEntry metaEntry) {
61 this.metaEntry = metaEntry;
64 public synchronized int getReplicaId() {
65 return metaEntry != null? metaEntry.getReplicaId(): deployedReplicaId;
68 public synchronized void addServer(RegionInfo regionInfo, ServerName serverName) {
69 OnlineEntry rse = new OnlineEntry(regionInfo, serverName) ;
70 this.deployedEntries.add(rse);
71 this.deployedOn.add(serverName);
72 // save the replicaId that we see deployed in the cluster
73 this.deployedReplicaId = regionInfo.getReplicaId();
74 this.primaryHRIForDeployedReplica =
75 RegionReplicaUtil.getRegionInfoForDefaultReplica(regionInfo);
78 @Override
79 public synchronized String toString() {
80 StringBuilder sb = new StringBuilder();
81 sb.append("{ meta => ");
82 sb.append((metaEntry != null)? metaEntry.getRegionNameAsString() : "null");
83 sb.append(", hdfs => " + getHdfsRegionDir());
84 sb.append(", deployed => " + Joiner.on(", ").join(deployedEntries));
85 sb.append(", replicaId => " + getReplicaId());
86 sb.append(" }");
87 return sb.toString();
90 @Override
91 public byte[] getStartKey() {
92 if (this.metaEntry != null) {
93 return this.metaEntry.getStartKey();
94 } else if (this.hdfsEntry != null) {
95 return this.hdfsEntry.hri.getStartKey();
96 } else {
97 LOG.error("Entry " + this + " has no meta or hdfs region start key.");
98 return null;
102 @Override
103 public byte[] getEndKey() {
104 if (this.metaEntry != null) {
105 return this.metaEntry.getEndKey();
106 } else if (this.hdfsEntry != null) {
107 return this.hdfsEntry.hri.getEndKey();
108 } else {
109 LOG.error("Entry " + this + " has no meta or hdfs region start key.");
110 return null;
114 public MetaEntry getMetaEntry() {
115 return this.metaEntry;
118 public void setMetaEntry(MetaEntry metaEntry) {
119 this.metaEntry = metaEntry;
122 public HdfsEntry getHdfsEntry() {
123 return this.hdfsEntry;
126 public void setHdfsEntry(HdfsEntry hdfsEntry) {
127 this.hdfsEntry = hdfsEntry;
130 public List<OnlineEntry> getOnlineEntries() {
131 return this.deployedEntries;
134 public List<ServerName> getDeployedOn() {
135 return this.deployedOn;
139 * Read the .regioninfo file from the file system. If there is no
140 * .regioninfo, add it to the orphan hdfs region list.
142 public void loadHdfsRegioninfo(Configuration conf) throws IOException {
143 Path regionDir = getHdfsRegionDir();
144 if (regionDir == null) {
145 if (getReplicaId() == RegionInfo.DEFAULT_REPLICA_ID) {
146 // Log warning only for default/ primary replica with no region dir
147 LOG.warn("No HDFS region dir found: " + this + " meta=" + metaEntry);
149 return;
152 if (hdfsEntry.hri != null) {
153 // already loaded data
154 return;
157 FileSystem fs = FileSystem.get(conf);
158 RegionInfo hri = HRegionFileSystem.loadRegionInfoFileContent(fs, regionDir);
159 LOG.debug("RegionInfo read: " + hri.toString());
160 hdfsEntry.hri = hri;
163 public TableName getTableName() {
164 if (this.metaEntry != null) {
165 return this.metaEntry.getTable();
166 } else if (this.hdfsEntry != null) {
167 // we are only guaranteed to have a path and not an HRI for hdfsEntry,
168 // so we get the name from the Path
169 Path tableDir = this.hdfsEntry.regionDir.getParent();
170 return FSUtils.getTableName(tableDir);
171 } else {
172 // return the info from the first online/deployed hri
173 for (OnlineEntry e : deployedEntries) {
174 return e.getRegionInfo().getTable();
176 return null;
180 public String getRegionNameAsString() {
181 if (metaEntry != null) {
182 return metaEntry.getRegionNameAsString();
183 } else if (hdfsEntry != null) {
184 if (hdfsEntry.hri != null) {
185 return hdfsEntry.hri.getRegionNameAsString();
187 } else {
188 // return the info from the first online/deployed hri
189 for (OnlineEntry e : deployedEntries) {
190 return e.getRegionInfo().getRegionNameAsString();
193 return null;
196 public byte[] getRegionName() {
197 if (metaEntry != null) {
198 return metaEntry.getRegionName();
199 } else if (hdfsEntry != null) {
200 return hdfsEntry.hri.getRegionName();
201 } else {
202 // return the info from the first online/deployed hri
203 for (OnlineEntry e : deployedEntries) {
204 return e.getRegionInfo().getRegionName();
206 return null;
210 public RegionInfo getPrimaryHRIForDeployedReplica() {
211 return primaryHRIForDeployedReplica;
214 public Path getHdfsRegionDir() {
215 if (hdfsEntry == null) {
216 return null;
218 return hdfsEntry.regionDir;
221 public boolean containsOnlyHdfsEdits() {
222 if (hdfsEntry == null) {
223 return false;
225 return hdfsEntry.hdfsOnlyEdits;
228 public boolean isHdfsRegioninfoPresent() {
229 if (hdfsEntry == null) {
230 return false;
232 return hdfsEntry.hdfsRegioninfoFilePresent;
235 public long getModTime() {
236 if (hdfsEntry == null) {
237 return 0;
239 return hdfsEntry.regionDirModTime;
242 public RegionInfo getHdfsHRI() {
243 if (hdfsEntry == null) {
244 return null;
246 return hdfsEntry.hri;
249 public void setSkipChecks(boolean skipChecks) {
250 this.skipChecks = skipChecks;
253 public boolean isSkipChecks() {
254 return skipChecks;
257 public void setMerged(boolean isMerged) {
258 this.isMerged = isMerged;
261 public boolean isMerged() {
262 return this.isMerged;
266 * Stores the regioninfo entries scanned from META
268 public static class MetaEntry extends HRegionInfo {
269 ServerName regionServer; // server hosting this region
270 long modTime; // timestamp of most recent modification metadata
271 RegionInfo splitA, splitB; //split daughters
273 public MetaEntry(RegionInfo rinfo, ServerName regionServer, long modTime) {
274 this(rinfo, regionServer, modTime, null, null);
277 public MetaEntry(RegionInfo rinfo, ServerName regionServer, long modTime,
278 RegionInfo splitA, RegionInfo splitB) {
279 super(rinfo);
280 this.regionServer = regionServer;
281 this.modTime = modTime;
282 this.splitA = splitA;
283 this.splitB = splitB;
286 public ServerName getRegionServer() {
287 return this.regionServer;
290 @Override
291 public boolean equals(Object o) {
292 boolean superEq = super.equals(o);
293 if (!superEq) {
294 return superEq;
297 MetaEntry me = (MetaEntry) o;
298 if (!regionServer.equals(me.regionServer)) {
299 return false;
301 return (modTime == me.modTime);
304 @Override
305 public int hashCode() {
306 int hash = Arrays.hashCode(getRegionName());
307 hash = (int) (hash ^ getRegionId());
308 hash ^= Arrays.hashCode(getStartKey());
309 hash ^= Arrays.hashCode(getEndKey());
310 hash ^= Boolean.valueOf(isOffline()).hashCode();
311 hash ^= getTable().hashCode();
312 if (regionServer != null) {
313 hash ^= regionServer.hashCode();
315 hash = (int) (hash ^ modTime);
316 return hash;
321 * Stores the regioninfo entries from HDFS
323 public static class HdfsEntry {
324 RegionInfo hri;
325 Path regionDir = null;
326 long regionDirModTime = 0;
327 boolean hdfsRegioninfoFilePresent = false;
328 boolean hdfsOnlyEdits = false;
330 HdfsEntry() {
333 public HdfsEntry(Path regionDir) {
334 this.regionDir = regionDir;
339 * Stores the regioninfo retrieved from Online region servers.
341 static class OnlineEntry {
342 private RegionInfo regionInfo;
343 private ServerName serverName;
345 OnlineEntry(RegionInfo regionInfo, ServerName serverName) {
346 this.regionInfo = regionInfo;
347 this.serverName = serverName;
350 public RegionInfo getRegionInfo() {
351 return regionInfo;
354 public ServerName getServerName() {
355 return serverName;
358 @Override
359 public String toString() {
360 return serverName.toString() + ";" + regionInfo.getRegionNameAsString();
364 final static Comparator<HbckRegionInfo> COMPARATOR = new Comparator<HbckRegionInfo>() {
365 @Override
366 public int compare(HbckRegionInfo l, HbckRegionInfo r) {
367 if (l == r) {
368 // same instance
369 return 0;
372 int tableCompare = l.getTableName().compareTo(r.getTableName());
373 if (tableCompare != 0) {
374 return tableCompare;
377 int startComparison = RegionSplitCalculator.BYTES_COMPARATOR.compare(
378 l.getStartKey(), r.getStartKey());
379 if (startComparison != 0) {
380 return startComparison;
383 // Special case for absolute endkey
384 byte[] endKey = r.getEndKey();
385 endKey = (endKey.length == 0) ? null : endKey;
386 byte[] endKey2 = l.getEndKey();
387 endKey2 = (endKey2.length == 0) ? null : endKey2;
388 int endComparison = RegionSplitCalculator.BYTES_COMPARATOR.compare(
389 endKey2, endKey);
391 if (endComparison != 0) {
392 return endComparison;
395 // use regionId as tiebreaker.
396 // Null is considered after all possible values so make it bigger.
397 if (l.getHdfsEntry() == null && r.getHdfsEntry() == null) {
398 return 0;
400 if (l.getHdfsEntry() == null && r.getHdfsEntry() != null) {
401 return 1;
403 // l.hdfsEntry must not be null
404 if (r.getHdfsEntry() == null) {
405 return -1;
407 // both l.hdfsEntry and r.hdfsEntry must not be null.
408 return Long.compare(l.getHdfsEntry().hri.getRegionId(), r.getHdfsEntry().hri.getRegionId());