001/** 002* 003* Licensed to the Apache Software Foundation (ASF) under one 004* or more contributor license agreements. See the NOTICE file 005* distributed with this work for additional information 006* regarding copyright ownership. The ASF licenses this file 007* to you under the Apache License, Version 2.0 (the 008* "License"); you may not use this file except in compliance 009* with the License. You may obtain a copy of the License at 010* 011* http://www.apache.org/licenses/LICENSE-2.0 012* 013* Unless required by applicable law or agreed to in writing, software 014* distributed under the License is distributed on an "AS IS" BASIS, 015* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016* See the License for the specific language governing permissions and 017* limitations under the License. 018*/ 019package org.apache.hadoop.hbase.client; 020 021import java.io.IOException; 022import java.util.ArrayList; 023import java.util.List; 024 025import org.apache.hadoop.conf.Configuration; 026import org.apache.hadoop.hbase.HRegionInfo; 027import org.apache.hadoop.hbase.HRegionLocation; 028import org.apache.hadoop.hbase.MetaTableAccessor; 029import org.apache.hadoop.hbase.RegionLocations; 030import org.apache.hadoop.hbase.TableName; 031import org.apache.hadoop.hbase.util.Pair; 032import org.apache.yetus.audience.InterfaceAudience; 033import org.apache.yetus.audience.InterfaceStability; 034 035import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting; 036 037/** 038 * An implementation of {@link RegionLocator}. Used to view region location information for a single 039 * HBase table. Lightweight. Get as needed and just close when done. Instances of this class SHOULD 040 * NOT be constructed directly. Obtain an instance via {@link Connection}. See 041 * {@link ConnectionFactory} class comment for an example of how. 042 * 043 * <p> This class is thread safe 044 */ 045@InterfaceAudience.Private 046@InterfaceStability.Stable 047public class HRegionLocator implements RegionLocator { 048 049 private final TableName tableName; 050 private final ClusterConnection connection; 051 052 public HRegionLocator(TableName tableName, ClusterConnection connection) { 053 this.connection = connection; 054 this.tableName = tableName; 055 } 056 057 /** 058 * {@inheritDoc} 059 */ 060 @Override 061 public void close() throws IOException { 062 // This method is required by the RegionLocator interface. This implementation does not have any 063 // persistent state, so there is no need to do anything here. 064 } 065 066 /** 067 * {@inheritDoc} 068 */ 069 @Override 070 public HRegionLocation getRegionLocation(final byte [] row) 071 throws IOException { 072 return connection.getRegionLocation(tableName, row, false); 073 } 074 075 /** 076 * {@inheritDoc} 077 */ 078 @Override 079 public HRegionLocation getRegionLocation(final byte [] row, boolean reload) 080 throws IOException { 081 return connection.getRegionLocation(tableName, row, reload); 082 } 083 084 @Override 085 public List<HRegionLocation> getAllRegionLocations() throws IOException { 086 TableName tableName = getName(); 087 ArrayList<HRegionLocation> regions = new ArrayList<>(); 088 for (RegionLocations locations : listRegionLocations()) { 089 for (HRegionLocation location : locations.getRegionLocations()) { 090 regions.add(location); 091 } 092 connection.cacheLocation(tableName, locations); 093 } 094 return regions; 095 } 096 097 /** 098 * {@inheritDoc} 099 */ 100 @Override 101 public byte[][] getStartKeys() throws IOException { 102 return getStartEndKeys().getFirst(); 103 } 104 105 /** 106 * {@inheritDoc} 107 */ 108 @Override 109 public byte[][] getEndKeys() throws IOException { 110 return getStartEndKeys().getSecond(); 111 } 112 113 /** 114 * {@inheritDoc} 115 */ 116 @Override 117 public Pair<byte[][], byte[][]> getStartEndKeys() throws IOException { 118 return getStartEndKeys(listRegionLocations()); 119 } 120 121 @VisibleForTesting 122 Pair<byte[][], byte[][]> getStartEndKeys(List<RegionLocations> regions) { 123 final byte[][] startKeyList = new byte[regions.size()][]; 124 final byte[][] endKeyList = new byte[regions.size()][]; 125 126 for (int i = 0; i < regions.size(); i++) { 127 HRegionInfo region = regions.get(i).getRegionLocation().getRegionInfo(); 128 startKeyList[i] = region.getStartKey(); 129 endKeyList[i] = region.getEndKey(); 130 } 131 132 return new Pair<>(startKeyList, endKeyList); 133 } 134 135 @Override 136 public TableName getName() { 137 return this.tableName; 138 } 139 140 @VisibleForTesting 141 List<RegionLocations> listRegionLocations() throws IOException { 142 final List<RegionLocations> regions = new ArrayList<>(); 143 MetaTableAccessor.Visitor visitor = new MetaTableAccessor.TableVisitorBase(tableName) { 144 @Override 145 public boolean visitInternal(Result result) throws IOException { 146 RegionLocations locations = MetaTableAccessor.getRegionLocations(result); 147 if (locations == null) return true; 148 regions.add(locations); 149 return true; 150 } 151 }; 152 MetaTableAccessor.scanMetaForTableRegions(connection, visitor, tableName); 153 return regions; 154 } 155 156 public Configuration getConfiguration() { 157 return connection.getConfiguration(); 158 } 159}