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.io.Closeable;
021import java.io.IOException;
022import java.util.List;
023import java.util.stream.Collectors;
024import org.apache.hadoop.hbase.HConstants;
025import org.apache.hadoop.hbase.HRegionLocation;
026import org.apache.hadoop.hbase.TableName;
027import org.apache.hadoop.hbase.util.Pair;
028import org.apache.yetus.audience.InterfaceAudience;
029
030/**
031 * Used to view region location information for a single HBase table. Obtain an instance from an
032 * {@link Connection}.
033 * @see ConnectionFactory
034 * @see Connection
035 * @see Table
036 * @since 0.99.0
037 */
038@InterfaceAudience.Public
039public interface RegionLocator extends Closeable {
040
041  /**
042   * Configuration for Region Locator's mode when meta replica is configured. Valid values are:
043   * HedgedRead, LoadBalance, None
044   */
045  String LOCATOR_META_REPLICAS_MODE = "hbase.locator.meta.replicas.mode";
046
047  /**
048   * Configuration for meta replica selector when Region Locator's LoadBalance mode is configured.
049   * The default value is org.apache.hadoop.hbase.client.CatalogReplicaLoadBalanceSimpleSelector.
050   */
051  String LOCATOR_META_REPLICAS_MODE_LOADBALANCE_SELECTOR =
052    "hbase.locator.meta.replicas.mode.loadbalance.selector";
053
054  /**
055   * Finds the region on which the given row is being served. Does not reload the cache.
056   * @param row Row to find.
057   * @return Location of the row.
058   * @throws IOException if a remote or network exception occurs
059   */
060  default HRegionLocation getRegionLocation(byte[] row) throws IOException {
061    return getRegionLocation(row, false);
062  }
063
064  /**
065   * Finds the region on which the given row is being served.
066   * @param row    Row to find.
067   * @param reload true to reload information or false to use cached information
068   * @return Location of the row.
069   * @throws IOException if a remote or network exception occurs
070   */
071  default HRegionLocation getRegionLocation(byte[] row, boolean reload) throws IOException {
072    return getRegionLocation(row, RegionInfo.DEFAULT_REPLICA_ID, reload);
073  }
074
075  /**
076   * Finds the region with the given replica id on which the given row is being served.
077   * @param row       Row to find.
078   * @param replicaId the replica id
079   * @return Location of the row.
080   * @throws IOException if a remote or network exception occurs
081   */
082  default HRegionLocation getRegionLocation(byte[] row, int replicaId) throws IOException {
083    return getRegionLocation(row, replicaId, false);
084  }
085
086  /**
087   * Finds the region with the given replica id on which the given row is being served.
088   * @param row       Row to find.
089   * @param replicaId the replica id
090   * @param reload    true to reload information or false to use cached information
091   * @return Location of the row.
092   * @throws IOException if a remote or network exception occurs
093   */
094  HRegionLocation getRegionLocation(byte[] row, int replicaId, boolean reload) throws IOException;
095
096  /**
097   * Find all the replicas for the region on which the given row is being served.
098   * @param row Row to find.
099   * @return Locations for all the replicas of the row.
100   * @throws IOException if a remote or network exception occurs
101   */
102  default List<HRegionLocation> getRegionLocations(byte[] row) throws IOException {
103    return getRegionLocations(row, false);
104  }
105
106  /**
107   * Find all the replicas for the region on which the given row is being served.
108   * @param row    Row to find.
109   * @param reload true to reload information or false to use cached information
110   * @return Locations for all the replicas of the row.
111   * @throws IOException if a remote or network exception occurs
112   */
113  List<HRegionLocation> getRegionLocations(byte[] row, boolean reload) throws IOException;
114
115  /**
116   * Clear all the entries in the region location cache.
117   * <p/>
118   * This may cause performance issue so use it with caution.
119   */
120  void clearRegionLocationCache();
121
122  /**
123   * Retrieves all of the regions associated with this table.
124   * <p/>
125   * Usually we will go to meta table directly in this method so there is no {@code reload}
126   * parameter.
127   * <p/>
128   * Notice that the location for region replicas other than the default replica are also returned.
129   * @return a {@link List} of all regions associated with this table.
130   * @throws IOException if a remote or network exception occurs
131   */
132  List<HRegionLocation> getAllRegionLocations() throws IOException;
133
134  /**
135   * Bulk lookup of region locations from {@code hbase:meta} in a single RPC, starting at
136   * {@code startKey} (region start-key boundary, inclusive) and returning at most {@code limit}
137   * regions in start-key order.
138   * <p/>
139   * The returned list includes all replicas of each region (matching
140   * {@link #getAllRegionLocations()}), and the result is also written to the connection's region
141   * location cache.
142   * <p/>
143   * Ordering: regions are returned in ascending region start-key order (the natural order of
144   * {@code hbase:meta} rows for a single table). Within each region, replicas are returned in
145   * ascending replica-id order (replica 0, then 1, then 2, ...). Split parents are filtered out,
146   * which may cause a page to contain fewer than {@code limit} regions but never disturbs ordering
147   * of the survivors.
148   * <p/>
149   * To page through all regions of a table, call repeatedly passing
150   * {@code last.getRegion().getEndKey()} as the next {@code startKey}, where {@code last} is the
151   * final element of the previous response. All replicas of a region share the same
152   * {@link RegionInfo}, so the last entry's end key is the correct cursor regardless of which
153   * replica it is. Pass {@code null} for the first call. Stop paging when the returned list is
154   * empty or when the last region's end key is {@link HConstants#EMPTY_END_ROW} (zero-length) -
155   * that signals the end of the table; passing it back in would re-scan from the beginning since by
156   * convention an empty start key means "from the first region".
157   * <p/>
158   * Unlike {@link #getAllRegionLocations()}, this method performs at most one RPC against
159   * {@code hbase:meta} per invocation, so its latency is bounded by {@code limit} rather than table
160   * size. The single-RPC behavior is best-effort: if the response would exceed
161   * {@code hbase.client.scanner.max.result.size} (default 2 MB), the server may split the slice
162   * across multiple {@code ScannerNext} RPCs. For typical meta row sizes and default caching this
163   * rarely fires, but callers passing large {@code limit} values against clusters with replicas or
164   * heavy meta rows should treat single-RPC as a soft guarantee, not absolute.
165   * <p/>
166   * This method is optional. Implementations that cannot support paginated lookups should throw
167   * {@link UnsupportedOperationException} (the default behavior); callers should fall back to
168   * {@link #getAllRegionLocations()} in that case.
169   * @param startKey region start-key to begin scanning from (inclusive); {@code null} or empty
170   *                 starts from the first region
171   * @param limit    maximum number of regions to return. If &lt;= 0, falls back to
172   *                 {@code hbase.meta.scanner.caching} - this is a SOFT cap on a single page, NOT
173   *                 "all regions"; tables larger than the cap still require the caller to keep
174   *                 paging via {@code last.getRegion().getEndKey()}.
175   * @return up to {@code limit} {@link HRegionLocation}s in start-key order, possibly empty when no
176   *         more regions exist
177   * @throws IOException                   if a remote or network exception occurs
178   * @throws UnsupportedOperationException if this implementation does not support paginated lookups
179   */
180  default List<HRegionLocation> getRegionLocationsPage(byte[] startKey, int limit)
181    throws IOException {
182    throw new UnsupportedOperationException(
183      "getRegionLocationsPage(byte[], int) is not supported by this RegionLocator;"
184        + " fall back to getAllRegionLocations()");
185  }
186
187  /**
188   * Gets the starting row key for every region in the currently open table.
189   * <p>
190   * This is mainly useful for the MapReduce integration.
191   * @return Array of region starting row keys
192   * @throws IOException if a remote or network exception occurs
193   */
194  default byte[][] getStartKeys() throws IOException {
195    return getStartEndKeys().getFirst();
196  }
197
198  /**
199   * Gets the ending row key for every region in the currently open table.
200   * <p>
201   * This is mainly useful for the MapReduce integration.
202   * @return Array of region ending row keys
203   * @throws IOException if a remote or network exception occurs
204   */
205  default byte[][] getEndKeys() throws IOException {
206    return getStartEndKeys().getSecond();
207  }
208
209  /**
210   * Gets the starting and ending row keys for every region in the currently open table.
211   * <p>
212   * This is mainly useful for the MapReduce integration.
213   * @return Pair of arrays of region starting and ending row keys
214   * @throws IOException if a remote or network exception occurs
215   */
216  default Pair<byte[][], byte[][]> getStartEndKeys() throws IOException {
217    List<HRegionLocation> regions = getAllRegionLocations().stream()
218      .filter(loc -> RegionReplicaUtil.isDefaultReplica(loc.getRegion()))
219      .collect(Collectors.toList());
220    byte[][] startKeys = new byte[regions.size()][];
221    byte[][] endKeys = new byte[regions.size()][];
222    for (int i = 0, n = regions.size(); i < n; i++) {
223      RegionInfo region = regions.get(i).getRegion();
224      startKeys[i] = region.getStartKey();
225      endKeys[i] = region.getEndKey();
226    }
227    return Pair.newPair(startKeys, endKeys);
228  }
229
230  /**
231   * Gets the fully qualified table name instance of this table.
232   */
233  TableName getName();
234}