001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.client; 019 020import java.util.List; 021import java.util.concurrent.CompletableFuture; 022import java.util.stream.Collectors; 023import org.apache.hadoop.hbase.HConstants; 024import org.apache.hadoop.hbase.HRegionLocation; 025import org.apache.hadoop.hbase.TableName; 026import org.apache.hadoop.hbase.util.Pair; 027import org.apache.yetus.audience.InterfaceAudience; 028 029/** 030 * The asynchronous version of RegionLocator. 031 * <p> 032 * Usually the implementations will not throw any exception directly, you need to get the exception 033 * from the returned {@link CompletableFuture}. 034 * @since 2.0.0 035 */ 036@InterfaceAudience.Public 037public interface AsyncTableRegionLocator { 038 039 /** 040 * Gets the fully qualified table name instance of the table whose region we want to locate. 041 */ 042 TableName getName(); 043 044 /** 045 * Finds the region on which the given row is being served. Does not reload the cache. 046 * <p/> 047 * Returns the location of the region to which the row belongs. 048 * @param row Row to find. 049 */ 050 default CompletableFuture<HRegionLocation> getRegionLocation(byte[] row) { 051 return getRegionLocation(row, false); 052 } 053 054 /** 055 * Finds the region on which the given row is being served. 056 * <p/> 057 * Returns the location of the region to which the row belongs. 058 * @param row Row to find. 059 * @param reload true to reload information or false to use cached information 060 */ 061 default CompletableFuture<HRegionLocation> getRegionLocation(byte[] row, boolean reload) { 062 return getRegionLocation(row, RegionInfo.DEFAULT_REPLICA_ID, reload); 063 } 064 065 /** 066 * Finds the region with the given <code>replicaId</code> on which the given row is being served. 067 * <p/> 068 * Returns the location of the region with the given <code>replicaId</code> to which the row 069 * belongs. 070 * @param row Row to find. 071 * @param replicaId the replica id of the region 072 */ 073 default CompletableFuture<HRegionLocation> getRegionLocation(byte[] row, int replicaId) { 074 return getRegionLocation(row, replicaId, false); 075 } 076 077 /** 078 * Finds the region with the given <code>replicaId</code> on which the given row is being served. 079 * <p/> 080 * Returns the location of the region with the given <code>replicaId</code> to which the row 081 * belongs. 082 * @param row Row to find. 083 * @param replicaId the replica id of the region 084 * @param reload true to reload information or false to use cached information 085 */ 086 CompletableFuture<HRegionLocation> getRegionLocation(byte[] row, int replicaId, boolean reload); 087 088 /** 089 * Find all the replicas for the region on which the given row is being served. 090 * @param row Row to find. 091 * @return Locations for all the replicas of the row. 092 */ 093 default CompletableFuture<List<HRegionLocation>> getRegionLocations(byte[] row) { 094 return getRegionLocations(row, false); 095 } 096 097 /** 098 * Find all the replicas for the region on which the given row is being served. 099 * @param row Row to find. 100 * @param reload true to reload information or false to use cached information 101 * @return Locations for all the replicas of the row. 102 */ 103 CompletableFuture<List<HRegionLocation>> getRegionLocations(byte[] row, boolean reload); 104 105 /** 106 * Retrieves all of the regions associated with this table. 107 * <p/> 108 * Usually we will go to meta table directly in this method so there is no {@code reload} 109 * parameter. 110 * <p/> 111 * Notice that the location for region replicas other than the default replica are also returned. 112 * @return a {@link List} of all regions associated with this table. 113 */ 114 CompletableFuture<List<HRegionLocation>> getAllRegionLocations(); 115 116 /** 117 * Bulk lookup of region locations from {@code hbase:meta} in a single RPC, starting at 118 * {@code startKey} (region start-key boundary, inclusive) and returning at most {@code limit} 119 * regions in start-key order. 120 * <p/> 121 * The returned list includes all replicas of each region (matching 122 * {@link #getAllRegionLocations()}), and the result is also written to the connection's region 123 * location cache. 124 * <p/> 125 * Ordering: regions are returned in ascending region start-key order (the natural order of 126 * {@code hbase:meta} rows for a single table). Within each region, replicas are returned in 127 * ascending replica-id order (replica 0, then 1, then 2, ...). Split parents are filtered out, 128 * which may cause a page to contain fewer than {@code limit} regions but never disturbs ordering 129 * of the survivors. 130 * <p/> 131 * To page through all regions of a table, call repeatedly passing 132 * {@code last.getRegion().getEndKey()} as the next {@code startKey}, where {@code last} is the 133 * final element of the previous response. All replicas of a region share the same 134 * {@link RegionInfo}, so the last entry's end key is the correct cursor regardless of which 135 * replica it is. Pass {@code null} for the first call. Stop paging when the returned list is 136 * empty or when the last region's end key is {@link HConstants#EMPTY_END_ROW} (zero-length) - 137 * that signals the end of the table; passing it back in would re-scan from the beginning since by 138 * convention an empty start key means "from the first region". 139 * <p/> 140 * Unlike {@link #getAllRegionLocations()}, this method performs at most one RPC against 141 * {@code hbase:meta} per invocation, so its latency is bounded by {@code limit} rather than table 142 * size. The single-RPC behavior is best-effort: if the response would exceed 143 * {@code hbase.client.scanner.max.result.size} (default 2 MB), the server may split the slice 144 * across multiple {@code ScannerNext} RPCs. For typical meta row sizes and default caching this 145 * rarely fires, but callers passing large {@code limit} values against clusters with replicas or 146 * heavy meta rows should treat single-RPC as a soft guarantee, not absolute. Note that this 147 * method does not coordinate with other in-flight meta lookups on the connection - aggregate 148 * pacing across concurrent callers is the caller's responsibility. 149 * <p/> 150 * This method is optional. Implementations that cannot support paginated lookups will return a 151 * future that completes exceptionally with {@link UnsupportedOperationException} (the default 152 * behavior); callers should fall back to {@link #getAllRegionLocations()} in that case. 153 * @param startKey region start-key to begin scanning from (inclusive); {@code null} or empty 154 * starts from the first region 155 * @param limit maximum number of regions to return. If <= 0, falls back to 156 * {@code hbase.meta.scanner.caching} - this is a SOFT cap on a single page, NOT 157 * "all regions"; tables larger than the cap still require the caller to keep 158 * paging via {@code last.getRegion().getEndKey()}. 159 * @return up to {@code limit} {@link HRegionLocation}s in start-key order, possibly empty when no 160 * more regions exist; errors are reported via the returned future 161 */ 162 default CompletableFuture<List<HRegionLocation>> getRegionLocationsPage(byte[] startKey, 163 int limit) { 164 CompletableFuture<List<HRegionLocation>> failed = new CompletableFuture<>(); 165 failed.completeExceptionally(new UnsupportedOperationException( 166 "getRegionLocationsPage(byte[], int) is not supported by this AsyncTableRegionLocator;" 167 + " fall back to getAllRegionLocations()")); 168 return failed; 169 } 170 171 /** 172 * Gets the starting row key for every region in the currently open table. 173 * <p> 174 * This is mainly useful for the MapReduce integration. 175 * @return Array of region starting row keys 176 */ 177 default CompletableFuture<List<byte[]>> getStartKeys() { 178 return getStartEndKeys().thenApply( 179 startEndKeys -> startEndKeys.stream().map(Pair::getFirst).collect(Collectors.toList())); 180 } 181 182 /** 183 * Gets the ending row key for every region in the currently open table. 184 * <p> 185 * This is mainly useful for the MapReduce integration. 186 * @return Array of region ending row keys 187 */ 188 default CompletableFuture<List<byte[]>> getEndKeys() { 189 return getStartEndKeys().thenApply( 190 startEndKeys -> startEndKeys.stream().map(Pair::getSecond).collect(Collectors.toList())); 191 } 192 193 /** 194 * Gets the starting and ending row keys for every region in the currently open table. 195 * <p> 196 * This is mainly useful for the MapReduce integration. 197 * @return Pair of arrays of region starting and ending row keys 198 */ 199 default CompletableFuture<List<Pair<byte[], byte[]>>> getStartEndKeys() { 200 return getAllRegionLocations().thenApply( 201 locs -> locs.stream().filter(loc -> RegionReplicaUtil.isDefaultReplica(loc.getRegion())) 202 .map(HRegionLocation::getRegion).map(r -> Pair.newPair(r.getStartKey(), r.getEndKey())) 203 .collect(Collectors.toList())); 204 } 205 206 /** 207 * Clear all the entries in the region location cache. 208 * <p/> 209 * This may cause performance issue so use it with caution. 210 */ 211 void clearRegionLocationCache(); 212}