View Javadoc

1   /**
2    *
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
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
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.
18   */
19  package org.apache.hadoop.hbase.util;
20  
21  import java.io.IOException;
22  import java.util.HashMap;
23  import java.util.Map;
24  
25  import java.util.concurrent.atomic.AtomicInteger;
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  import org.apache.hadoop.hbase.classification.InterfaceAudience;
29  import org.apache.hadoop.fs.BlockLocation;
30  import org.apache.hadoop.fs.FileStatus;
31  import org.apache.hadoop.fs.FileSystem;
32  import org.apache.hadoop.fs.Path;
33  import org.apache.hadoop.hbase.HConstants;
34  import org.apache.hadoop.hbase.util.FSUtils;
35  
36  /**
37   * Thread that walks over the filesystem, and computes the mappings
38   * <Region -> BestHost> and <Region -> Map<HostName, fractional-locality-of-region>>
39   *
40   */
41  @InterfaceAudience.Private
42  class FSRegionScanner implements Runnable {
43    static private final Log LOG = LogFactory.getLog(FSRegionScanner.class);
44  
45    private Path regionPath;
46  
47    /**
48     * The file system used
49     */
50    private FileSystem fs;
51  
52    /**
53     * Maps each region to the RS with highest locality for that region.
54     */
55    private Map<String,String> regionToBestLocalityRSMapping;
56  
57    /**
58     * Maps region encoded names to maps of hostnames to fractional locality of
59     * that region on that host.
60     */
61    private Map<String, Map<String, Float>> regionDegreeLocalityMapping;
62  
63    FSRegionScanner(FileSystem fs, Path regionPath,
64                    Map<String, String> regionToBestLocalityRSMapping,
65                    Map<String, Map<String, Float>> regionDegreeLocalityMapping) {
66      this.fs = fs;
67      this.regionPath = regionPath;
68      this.regionToBestLocalityRSMapping = regionToBestLocalityRSMapping;
69      this.regionDegreeLocalityMapping = regionDegreeLocalityMapping;
70    }
71  
72    @Override
73    public void run() {
74      try {
75        // empty the map for each region
76        Map<String, AtomicInteger> blockCountMap = new HashMap<String, AtomicInteger>();
77  
78        //get table name
79        String tableName = regionPath.getParent().getName();
80        int totalBlkCount = 0;
81  
82        // ignore null
83        FileStatus[] cfList = fs.listStatus(regionPath, new FSUtils.FamilyDirFilter(fs));
84        if (null == cfList) {
85          return;
86        }
87  
88        // for each cf, get all the blocks information
89        for (FileStatus cfStatus : cfList) {
90          if (!cfStatus.isDir()) {
91            // skip because this is not a CF directory
92            continue;
93          }
94  
95          FileStatus[] storeFileLists = fs.listStatus(cfStatus.getPath());
96          if (null == storeFileLists) {
97            continue;
98          }
99  
100         for (FileStatus storeFile : storeFileLists) {
101           BlockLocation[] blkLocations =
102             fs.getFileBlockLocations(storeFile, 0, storeFile.getLen());
103           if (null == blkLocations) {
104             continue;
105           }
106 
107           totalBlkCount += blkLocations.length;
108           for(BlockLocation blk: blkLocations) {
109             for (String host: blk.getHosts()) {
110               AtomicInteger count = blockCountMap.get(host);
111               if (count == null) {
112                 count = new AtomicInteger(0);
113                 blockCountMap.put(host, count);
114               }
115               count.incrementAndGet();
116             }
117           }
118         }
119       }
120 
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();
126 
127           int tmp = entry.getValue().get();
128           if (tmp > largestBlkCount) {
129             largestBlkCount = tmp;
130             hostToRun = host;
131           }
132         }
133 
134         // empty regions could make this null
135         if (null == hostToRun) {
136           return;
137         }
138 
139         if (hostToRun.endsWith(".")) {
140           hostToRun = hostToRun.substring(0, hostToRun.length()-1);
141         }
142         String name = tableName + ":" + regionPath.getName();
143         synchronized (regionToBestLocalityRSMapping) {
144           regionToBestLocalityRSMapping.put(name,  hostToRun);
145         }
146       }
147 
148       if (regionDegreeLocalityMapping != null && totalBlkCount > 0) {
149         Map<String, Float> hostLocalityMap = new HashMap<String, Float>();
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);
154           }
155           // Locality is fraction of blocks local to this host.
156           float locality = ((float)entry.getValue().get()) / totalBlkCount;
157           hostLocalityMap.put(host, locality);
158         }
159         // Put the locality map into the result map, keyed by the encoded name
160         // of the region.
161         regionDegreeLocalityMapping.put(regionPath.getName(), hostLocalityMap);
162       }
163     } catch (IOException e) {
164       LOG.warn("Problem scanning file system", e);
165     } catch (RuntimeException e) {
166       LOG.warn("Problem scanning file system", e);
167     }
168   }
169 }