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
;
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
);
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());
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();
97 LOG
.error("Entry " + this + " has no meta or hdfs region start key.");
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();
109 LOG
.error("Entry " + this + " has no meta or hdfs region start key.");
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
);
152 if (hdfsEntry
.hri
!= null) {
153 // already loaded data
157 FileSystem fs
= FileSystem
.get(conf
);
158 RegionInfo hri
= HRegionFileSystem
.loadRegionInfoFileContent(fs
, regionDir
);
159 LOG
.debug("RegionInfo read: " + hri
.toString());
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
);
172 // return the info from the first online/deployed hri
173 for (OnlineEntry e
: deployedEntries
) {
174 return e
.getRegionInfo().getTable();
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();
188 // return the info from the first online/deployed hri
189 for (OnlineEntry e
: deployedEntries
) {
190 return e
.getRegionInfo().getRegionNameAsString();
196 public byte[] getRegionName() {
197 if (metaEntry
!= null) {
198 return metaEntry
.getRegionName();
199 } else if (hdfsEntry
!= null) {
200 return hdfsEntry
.hri
.getRegionName();
202 // return the info from the first online/deployed hri
203 for (OnlineEntry e
: deployedEntries
) {
204 return e
.getRegionInfo().getRegionName();
210 public RegionInfo
getPrimaryHRIForDeployedReplica() {
211 return primaryHRIForDeployedReplica
;
214 public Path
getHdfsRegionDir() {
215 if (hdfsEntry
== null) {
218 return hdfsEntry
.regionDir
;
221 public boolean containsOnlyHdfsEdits() {
222 if (hdfsEntry
== null) {
225 return hdfsEntry
.hdfsOnlyEdits
;
228 public boolean isHdfsRegioninfoPresent() {
229 if (hdfsEntry
== null) {
232 return hdfsEntry
.hdfsRegioninfoFilePresent
;
235 public long getModTime() {
236 if (hdfsEntry
== null) {
239 return hdfsEntry
.regionDirModTime
;
242 public RegionInfo
getHdfsHRI() {
243 if (hdfsEntry
== null) {
246 return hdfsEntry
.hri
;
249 public void setSkipChecks(boolean skipChecks
) {
250 this.skipChecks
= skipChecks
;
253 public boolean isSkipChecks() {
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
) {
280 this.regionServer
= regionServer
;
281 this.modTime
= modTime
;
282 this.splitA
= splitA
;
283 this.splitB
= splitB
;
286 public ServerName
getRegionServer() {
287 return this.regionServer
;
291 public boolean equals(Object o
) {
292 boolean superEq
= super.equals(o
);
297 MetaEntry me
= (MetaEntry
) o
;
298 if (!regionServer
.equals(me
.regionServer
)) {
301 return (modTime
== me
.modTime
);
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
);
321 * Stores the regioninfo entries from HDFS
323 public static class HdfsEntry
{
325 Path regionDir
= null;
326 long regionDirModTime
= 0;
327 boolean hdfsRegioninfoFilePresent
= false;
328 boolean hdfsOnlyEdits
= false;
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() {
354 public ServerName
getServerName() {
359 public String
toString() {
360 return serverName
.toString() + ";" + regionInfo
.getRegionNameAsString();
364 final static Comparator
<HbckRegionInfo
> COMPARATOR
= new Comparator
<HbckRegionInfo
>() {
366 public int compare(HbckRegionInfo l
, HbckRegionInfo r
) {
372 int tableCompare
= l
.getTableName().compareTo(r
.getTableName());
373 if (tableCompare
!= 0) {
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(
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) {
400 if (l
.getHdfsEntry() == null && r
.getHdfsEntry() != null) {
403 // l.hdfsEntry must not be null
404 if (r
.getHdfsEntry() == null) {
407 // both l.hdfsEntry and r.hdfsEntry must not be null.
408 return Long
.compare(l
.getHdfsEntry().hri
.getRegionId(), r
.getHdfsEntry().hri
.getRegionId());