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.master;
20  
21  import java.io.IOException;
22  import java.util.ArrayList;
23  import java.util.Arrays;
24  import java.util.HashMap;
25  import java.util.HashSet;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.Set;
29  import java.util.TreeMap;
30  
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  import org.apache.hadoop.hbase.classification.InterfaceAudience;
34  import org.apache.hadoop.hbase.HConstants;
35  import org.apache.hadoop.hbase.HRegionInfo;
36  import org.apache.hadoop.hbase.HRegionLocation;
37  import org.apache.hadoop.hbase.RegionLocations;
38  import org.apache.hadoop.hbase.ServerName;
39  import org.apache.hadoop.hbase.TableName;
40  import org.apache.hadoop.hbase.MetaTableAccessor;
41  import org.apache.hadoop.hbase.MetaTableAccessor.Visitor;
42  import org.apache.hadoop.hbase.client.Connection;
43  import org.apache.hadoop.hbase.client.Result;
44  import org.apache.hadoop.hbase.master.balancer.FavoredNodeAssignmentHelper;
45  import org.apache.hadoop.hbase.master.balancer.FavoredNodesPlan;
46  
47  /**
48   * Used internally for reading meta and constructing datastructures that are
49   * then queried, for things like regions to regionservers, table to regions, etc.
50   * It also records the favored nodes mapping for regions.
51   *
52   */
53  @InterfaceAudience.Private
54  public class SnapshotOfRegionAssignmentFromMeta {
55    private static final Log LOG = LogFactory.getLog(SnapshotOfRegionAssignmentFromMeta.class
56        .getName());
57  
58    private final Connection connection;
59  
60    /** the table name to region map */
61    private final Map<TableName, List<HRegionInfo>> tableToRegionMap;
62    /** the region to region server map */
63    //private final Map<HRegionInfo, ServerName> regionToRegionServerMap;
64    private Map<HRegionInfo, ServerName> regionToRegionServerMap;
65    /** the region name to region info map */
66    private final Map<String, HRegionInfo> regionNameToRegionInfoMap;
67  
68    /** the regionServer to region map */
69    private final Map<ServerName, List<HRegionInfo>> regionServerToRegionMap;
70    /** the existing assignment plan in the hbase:meta region */
71    private final FavoredNodesPlan existingAssignmentPlan;
72    private final Set<TableName> disabledTables;
73    private final boolean excludeOfflinedSplitParents;
74  
75    public SnapshotOfRegionAssignmentFromMeta(Connection connection) {
76      this(connection, new HashSet<TableName>(), false);
77    }
78  
79    public SnapshotOfRegionAssignmentFromMeta(Connection connection, Set<TableName> disabledTables,
80        boolean excludeOfflinedSplitParents) {
81      this.connection = connection;
82      tableToRegionMap = new HashMap<TableName, List<HRegionInfo>>();
83      regionToRegionServerMap = new HashMap<HRegionInfo, ServerName>();
84      regionServerToRegionMap = new HashMap<ServerName, List<HRegionInfo>>();
85      regionNameToRegionInfoMap = new TreeMap<String, HRegionInfo>();
86      existingAssignmentPlan = new FavoredNodesPlan();
87      this.disabledTables = disabledTables;
88      this.excludeOfflinedSplitParents = excludeOfflinedSplitParents;
89    }
90  
91    /**
92     * Initialize the region assignment snapshot by scanning the hbase:meta table
93     * @throws IOException
94     */
95    public void initialize() throws IOException {
96      LOG.info("Start to scan the hbase:meta for the current region assignment " +
97        "snappshot");
98      // TODO: at some point this code could live in the MetaTableAccessor
99      Visitor v = new Visitor() {
100       @Override
101       public boolean visit(Result result) throws IOException {
102         try {
103           if (result ==  null || result.isEmpty()) return true;
104           RegionLocations rl = MetaTableAccessor.getRegionLocations(result);
105           if (rl == null) return true;
106           HRegionInfo hri = rl.getRegionLocation(0).getRegionInfo();
107           if (hri == null) return true;
108           if (hri.getTable() == null) return true;
109           if (disabledTables.contains(hri.getTable())) {
110             return true;
111           }
112           // Are we to include split parents in the list?
113           if (excludeOfflinedSplitParents && hri.isSplit()) return true;
114           HRegionLocation[] hrls = rl.getRegionLocations();
115 
116           // Add the current assignment to the snapshot for all replicas
117           for (int i = 0; i < hrls.length; i++) {
118             if (hrls[i] == null) continue;
119             hri = hrls[i].getRegionInfo();
120             if (hri == null) continue;
121             addAssignment(hri, hrls[i].getServerName());
122             addRegion(hri);
123           }
124 
125           // the code below is to handle favored nodes
126           byte[] favoredNodes = result.getValue(HConstants.CATALOG_FAMILY,
127               FavoredNodeAssignmentHelper.FAVOREDNODES_QUALIFIER);
128           if (favoredNodes == null) return true;
129           // Add the favored nodes into assignment plan
130           ServerName[] favoredServerList =
131               FavoredNodeAssignmentHelper.getFavoredNodesList(favoredNodes);
132           // Add the favored nodes into assignment plan
133           existingAssignmentPlan.updateFavoredNodesMap(hri,
134               Arrays.asList(favoredServerList));
135           return true;
136         } catch (RuntimeException e) {
137           LOG.error("Catche remote exception " + e.getMessage() +
138               " when processing" + result);
139           throw e;
140         }
141       }
142     };
143     // Scan hbase:meta to pick up user regions
144     MetaTableAccessor.fullScan(connection, v);
145     //regionToRegionServerMap = regions;
146     LOG.info("Finished to scan the hbase:meta for the current region assignment" +
147       "snapshot");
148   }
149 
150   private void addRegion(HRegionInfo regionInfo) {
151     // Process the region name to region info map
152     regionNameToRegionInfoMap.put(regionInfo.getRegionNameAsString(), regionInfo);
153 
154     // Process the table to region map
155     TableName tableName = regionInfo.getTable();
156     List<HRegionInfo> regionList = tableToRegionMap.get(tableName);
157     if (regionList == null) {
158       regionList = new ArrayList<HRegionInfo>();
159     }
160     // Add the current region info into the tableToRegionMap
161     regionList.add(regionInfo);
162     tableToRegionMap.put(tableName, regionList);
163   }
164 
165   private void addAssignment(HRegionInfo regionInfo, ServerName server) {
166     // Process the region to region server map
167     regionToRegionServerMap.put(regionInfo, server);
168 
169     if (server == null) return;
170 
171     // Process the region server to region map
172     List<HRegionInfo> regionList = regionServerToRegionMap.get(server);
173     if (regionList == null) {
174       regionList = new ArrayList<HRegionInfo>();
175     }
176     regionList.add(regionInfo);
177     regionServerToRegionMap.put(server, regionList);
178   }
179 
180   /**
181    * Get the regioninfo for a region
182    * @return the regioninfo
183    */
184   public Map<String, HRegionInfo> getRegionNameToRegionInfoMap() {
185     return this.regionNameToRegionInfoMap;
186   }
187 
188   /**
189    * Get regions for tables
190    * @return a mapping from table to regions
191    */
192   public Map<TableName, List<HRegionInfo>> getTableToRegionMap() {
193     return tableToRegionMap;
194   }
195 
196   /**
197    * Get region to region server map
198    * @return region to region server map
199    */
200   public Map<HRegionInfo, ServerName> getRegionToRegionServerMap() {
201     return regionToRegionServerMap;
202   }
203 
204   /**
205    * Get regionserver to region map
206    * @return regionserver to region map
207    */
208   public Map<ServerName, List<HRegionInfo>> getRegionServerToRegionMap() {
209     return regionServerToRegionMap;
210   }
211 
212   /**
213    * Get the favored nodes plan
214    * @return the existing favored nodes plan
215    */
216   public FavoredNodesPlan getExistingAssignmentPlan() {
217     return this.existingAssignmentPlan;
218   }
219 
220   /**
221    * Get the table set
222    * @return the table set
223    */
224   public Set<TableName> getTableSet() {
225     return this.tableToRegionMap.keySet();
226   }
227 }