3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 package org
.apache
.hadoop
.hbase
.util
;
21 import java
.io
.IOException
;
22 import java
.util
.HashMap
;
25 import java
.util
.concurrent
.atomic
.AtomicInteger
;
27 import org
.apache
.yetus
.audience
.InterfaceAudience
;
28 import org
.slf4j
.Logger
;
29 import org
.slf4j
.LoggerFactory
;
30 import org
.apache
.hadoop
.fs
.BlockLocation
;
31 import org
.apache
.hadoop
.fs
.FileStatus
;
32 import org
.apache
.hadoop
.fs
.FileSystem
;
33 import org
.apache
.hadoop
.fs
.Path
;
34 import org
.apache
.hadoop
.hbase
.util
.FSUtils
;
37 * Thread that walks over the filesystem, and computes the mappings
38 * Region -> BestHost and Region -> {@code Map<HostName, fractional-locality-of-region>}
41 @InterfaceAudience.Private
42 class FSRegionScanner
implements Runnable
{
43 static private final Logger LOG
= LoggerFactory
.getLogger(FSRegionScanner
.class);
45 private Path regionPath
;
48 * The file system used
50 private FileSystem fs
;
53 * Maps each region to the RS with highest locality for that region.
55 private final Map
<String
,String
> regionToBestLocalityRSMapping
;
58 * Maps region encoded names to maps of hostnames to fractional locality of
59 * that region on that host.
61 private Map
<String
, Map
<String
, Float
>> regionDegreeLocalityMapping
;
63 FSRegionScanner(FileSystem fs
, Path regionPath
,
64 Map
<String
, String
> regionToBestLocalityRSMapping
,
65 Map
<String
, Map
<String
, Float
>> regionDegreeLocalityMapping
) {
67 this.regionPath
= regionPath
;
68 this.regionToBestLocalityRSMapping
= regionToBestLocalityRSMapping
;
69 this.regionDegreeLocalityMapping
= regionDegreeLocalityMapping
;
75 // empty the map for each region
76 Map
<String
, AtomicInteger
> blockCountMap
= new HashMap
<>();
79 String tableName
= regionPath
.getParent().getName();
80 int totalBlkCount
= 0;
83 FileStatus
[] cfList
= fs
.listStatus(regionPath
, new FSUtils
.FamilyDirFilter(fs
));
88 // for each cf, get all the blocks information
89 for (FileStatus cfStatus
: cfList
) {
90 if (!cfStatus
.isDirectory()) {
91 // skip because this is not a CF directory
95 FileStatus
[] storeFileLists
= fs
.listStatus(cfStatus
.getPath());
96 if (null == storeFileLists
) {
100 for (FileStatus storeFile
: storeFileLists
) {
101 BlockLocation
[] blkLocations
=
102 fs
.getFileBlockLocations(storeFile
, 0, storeFile
.getLen());
103 if (null == blkLocations
) {
107 totalBlkCount
+= blkLocations
.length
;
108 for(BlockLocation blk
: blkLocations
) {
109 for (String host
: blk
.getHosts()) {
110 AtomicInteger count
= blockCountMap
.get(host
);
112 count
= new AtomicInteger(0);
113 blockCountMap
.put(host
, count
);
115 count
.incrementAndGet();
121 if (regionToBestLocalityRSMapping
!= null) {
122 int largestBlkCount
= 0;
123 String hostToRun
= null;
124 for (Map
.Entry
<String
, AtomicInteger
> entry
: blockCountMap
.entrySet()) {
125 String host
= entry
.getKey();
127 int tmp
= entry
.getValue().get();
128 if (tmp
> largestBlkCount
) {
129 largestBlkCount
= tmp
;
134 // empty regions could make this null
135 if (null == hostToRun
) {
139 if (hostToRun
.endsWith(".")) {
140 hostToRun
= hostToRun
.substring(0, hostToRun
.length()-1);
142 String name
= tableName
+ ":" + regionPath
.getName();
143 synchronized (regionToBestLocalityRSMapping
) {
144 regionToBestLocalityRSMapping
.put(name
, hostToRun
);
148 if (regionDegreeLocalityMapping
!= null && totalBlkCount
> 0) {
149 Map
<String
, Float
> hostLocalityMap
= new HashMap
<>();
150 for (Map
.Entry
<String
, AtomicInteger
> entry
: blockCountMap
.entrySet()) {
151 String host
= entry
.getKey();
152 if (host
.endsWith(".")) {
153 host
= host
.substring(0, host
.length() - 1);
155 // Locality is fraction of blocks local to this host.
156 float locality
= ((float)entry
.getValue().get()) / totalBlkCount
;
157 hostLocalityMap
.put(host
, locality
);
159 // Put the locality map into the result map, keyed by the encoded name
161 regionDegreeLocalityMapping
.put(regionPath
.getName(), hostLocalityMap
);
163 } catch (IOException e
) {
164 LOG
.warn("Problem scanning file system", e
);
165 } catch (RuntimeException e
) {
166 LOG
.warn("Problem scanning file system", e
);