1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.client;
21
22 import java.io.Closeable;
23 import java.io.IOException;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.NavigableMap;
27 import java.util.TreeMap;
28
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31 import org.apache.hadoop.hbase.classification.InterfaceAudience;
32 import org.apache.hadoop.conf.Configuration;
33 import org.apache.hadoop.hbase.HConstants;
34 import org.apache.hadoop.hbase.HRegionInfo;
35 import org.apache.hadoop.hbase.HRegionLocation;
36 import org.apache.hadoop.hbase.MetaTableAccessor;
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.TableNotFoundException;
41 import org.apache.hadoop.hbase.util.Bytes;
42 import org.apache.hadoop.hbase.util.ExceptionUtil;
43
44
45
46
47
48
49
50
51
52
53
54
55 @InterfaceAudience.Private
56
57 public class MetaScanner {
58 private static final Log LOG = LogFactory.getLog(MetaScanner.class);
59
60
61
62
63
64
65
66
67
68
69
70 public static void metaScan(Connection connection,
71 MetaScannerVisitor visitor) throws IOException {
72 metaScan(connection, visitor, null, null, Integer.MAX_VALUE);
73 }
74
75
76
77
78
79
80
81
82
83
84
85 public static void metaScan(Connection connection,
86 MetaScannerVisitor visitor, TableName userTableName) throws IOException {
87 metaScan(connection, visitor, userTableName, null, Integer.MAX_VALUE,
88 TableName.META_TABLE_NAME);
89 }
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110 public static void metaScan(Connection connection,
111 MetaScannerVisitor visitor, TableName userTableName, byte[] row,
112 int rowLimit)
113 throws IOException {
114 metaScan(connection, visitor, userTableName, row, rowLimit, TableName
115 .META_TABLE_NAME);
116 }
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134 static void metaScan(Connection connection,
135 final MetaScannerVisitor visitor, final TableName tableName,
136 final byte[] row, final int rowLimit, final TableName metaTableName)
137 throws IOException {
138
139 int rowUpperLimit = rowLimit > 0 ? rowLimit: Integer.MAX_VALUE;
140
141 byte[] startRow;
142
143
144
145
146
147
148 try (Table metaTable = new HTable(metaTableName, connection, null)) {
149 if (row != null) {
150
151 Result startRowResult = getClosestRowOrBefore(metaTable, tableName, row,
152 connection.getConfiguration().getBoolean(HConstants.USE_META_REPLICAS,
153 HConstants.DEFAULT_USE_META_REPLICAS));
154 if (startRowResult == null) {
155 throw new TableNotFoundException("Cannot find row in " + metaTable.getName() +
156 " for table: " + tableName + ", row=" + Bytes.toStringBinary(row));
157 }
158 HRegionInfo regionInfo = getHRegionInfo(startRowResult);
159 if (regionInfo == null) {
160 throw new IOException("HRegionInfo was null or empty in Meta for " +
161 tableName + ", row=" + Bytes.toStringBinary(row));
162 }
163 byte[] rowBefore = regionInfo.getStartKey();
164 startRow = HRegionInfo.createRegionName(tableName, rowBefore, HConstants.ZEROES, false);
165 } else if (tableName == null || tableName.getName().length == 0) {
166
167 startRow = HConstants.EMPTY_START_ROW;
168 } else {
169
170 startRow = HRegionInfo.createRegionName(tableName, HConstants.EMPTY_START_ROW,
171 HConstants.ZEROES, false);
172 }
173 final Scan scan = new Scan(startRow).addFamily(HConstants.CATALOG_FAMILY);
174 int scannerCaching = connection.getConfiguration()
175 .getInt(HConstants.HBASE_META_SCANNER_CACHING,
176 HConstants.DEFAULT_HBASE_META_SCANNER_CACHING);
177 if (connection.getConfiguration().getBoolean(HConstants.USE_META_REPLICAS,
178 HConstants.DEFAULT_USE_META_REPLICAS)) {
179 scan.setConsistency(Consistency.TIMELINE);
180 }
181 if (rowUpperLimit <= scannerCaching) {
182 scan.setSmall(true);
183 }
184 int rows = Math.min(rowLimit, scannerCaching);
185 scan.setCaching(rows);
186 if (LOG.isTraceEnabled()) {
187 LOG.trace("Scanning " + metaTableName.getNameAsString() + " starting at row=" +
188 Bytes.toStringBinary(startRow) + " for max=" + rowUpperLimit + " with caching=" + rows);
189 }
190
191 try (ResultScanner resultScanner = metaTable.getScanner(scan)) {
192 Result result;
193 int processedRows = 0;
194 while ((result = resultScanner.next()) != null) {
195 if (visitor != null) {
196 if (!visitor.processRow(result)) break;
197 }
198 processedRows++;
199 if (processedRows >= rowUpperLimit) break;
200 }
201 }
202 } finally {
203 if (visitor != null) {
204 try {
205 visitor.close();
206 } catch (Throwable t) {
207 ExceptionUtil.rethrowIfInterrupt(t);
208 LOG.debug("Got exception in closing the meta scanner visitor", t);
209 }
210 }
211 }
212 }
213
214
215
216
217
218 private static Result getClosestRowOrBefore(final Table metaTable, final TableName userTableName,
219 final byte [] row, boolean useMetaReplicas)
220 throws IOException {
221 byte[] searchRow = HRegionInfo.createRegionName(userTableName, row, HConstants.NINES, false);
222 Scan scan = Scan.createGetClosestRowOrBeforeReverseScan(searchRow);
223
224
225
226 scan.addFamily(HConstants.CATALOG_FAMILY);
227 if (useMetaReplicas) {
228 scan.setConsistency(Consistency.TIMELINE);
229 }
230 try (ResultScanner resultScanner = metaTable.getScanner(scan)) {
231 return resultScanner.next();
232 }
233 }
234
235
236
237
238
239
240
241
242
243 @Deprecated
244 public static HRegionInfo getHRegionInfo(Result data) {
245 return HRegionInfo.getHRegionInfo(data);
246 }
247
248
249
250
251
252
253
254
255
256
257
258 public static List<HRegionInfo> listAllRegions(Configuration conf, Connection connection,
259 final boolean offlined)
260 throws IOException {
261 final List<HRegionInfo> regions = new ArrayList<HRegionInfo>();
262 MetaScannerVisitor visitor = new MetaScannerVisitorBase() {
263 @Override
264 public boolean processRow(Result result) throws IOException {
265 if (result == null || result.isEmpty()) {
266 return true;
267 }
268
269 RegionLocations locations = MetaTableAccessor.getRegionLocations(result);
270 if (locations == null) return true;
271 for (HRegionLocation loc : locations.getRegionLocations()) {
272 if (loc != null) {
273 HRegionInfo regionInfo = loc.getRegionInfo();
274
275 if (regionInfo.isOffline() && !offlined) continue;
276 regions.add(regionInfo);
277 }
278 }
279 return true;
280 }
281 };
282 metaScan(connection, visitor);
283 return regions;
284 }
285
286
287
288
289
290
291
292
293
294
295 @Deprecated
296 public static NavigableMap<HRegionInfo, ServerName> allTableRegions(Configuration conf,
297 Connection connection, final TableName tableName, boolean offlined) throws IOException {
298 return allTableRegions(connection, tableName);
299 }
300
301
302
303
304
305
306
307
308 public static NavigableMap<HRegionInfo, ServerName> allTableRegions(
309 Connection connection, final TableName tableName) throws IOException {
310 final NavigableMap<HRegionInfo, ServerName> regions =
311 new TreeMap<HRegionInfo, ServerName>();
312 MetaScannerVisitor visitor = new TableMetaScannerVisitor(tableName) {
313 @Override
314 public boolean processRowInternal(Result result) throws IOException {
315 RegionLocations locations = MetaTableAccessor.getRegionLocations(result);
316 if (locations == null) return true;
317 for (HRegionLocation loc : locations.getRegionLocations()) {
318 if (loc != null) {
319 HRegionInfo regionInfo = loc.getRegionInfo();
320 regions.put(new UnmodifyableHRegionInfo(regionInfo), loc.getServerName());
321 }
322 }
323 return true;
324 }
325 };
326 metaScan(connection, visitor, tableName);
327 return regions;
328 }
329
330
331
332
333 public static List<RegionLocations> listTableRegionLocations(Configuration conf,
334 Connection connection, final TableName tableName) throws IOException {
335 final List<RegionLocations> regions = new ArrayList<RegionLocations>();
336 MetaScannerVisitor visitor = new TableMetaScannerVisitor(tableName) {
337 @Override
338 public boolean processRowInternal(Result result) throws IOException {
339 RegionLocations locations = MetaTableAccessor.getRegionLocations(result);
340 if (locations == null) return true;
341 regions.add(locations);
342 return true;
343 }
344 };
345 metaScan(connection, visitor, tableName);
346 return regions;
347 }
348
349
350
351
352 public interface MetaScannerVisitor extends Closeable {
353
354
355
356
357
358
359
360
361
362 boolean processRow(Result rowResult) throws IOException;
363 }
364
365 public static abstract class MetaScannerVisitorBase implements MetaScannerVisitor {
366 @Override
367 public void close() throws IOException {
368 }
369 }
370
371
372
373
374 public static abstract class DefaultMetaScannerVisitor
375 extends MetaScannerVisitorBase {
376
377 public DefaultMetaScannerVisitor() {
378 super();
379 }
380
381 public abstract boolean processRowInternal(Result rowResult) throws IOException;
382
383 @Override
384 public boolean processRow(Result rowResult) throws IOException {
385 HRegionInfo info = getHRegionInfo(rowResult);
386 if (info == null) {
387 return true;
388 }
389
390
391 if (!(info.isOffline() || info.isSplit())) {
392 return processRowInternal(rowResult);
393 }
394 return true;
395 }
396 }
397
398
399
400
401
402
403
404 public static abstract class TableMetaScannerVisitor extends DefaultMetaScannerVisitor {
405 private TableName tableName;
406
407 public TableMetaScannerVisitor(TableName tableName) {
408 super();
409 this.tableName = tableName;
410 }
411
412 @Override
413 public final boolean processRow(Result rowResult) throws IOException {
414 HRegionInfo info = getHRegionInfo(rowResult);
415 if (info == null) {
416 return true;
417 }
418 if (!(info.getTable().equals(tableName))) {
419 return false;
420 }
421 return super.processRow(rowResult);
422 }
423 }
424 }