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 if (useMetaReplicas) {
224 scan.setConsistency(Consistency.TIMELINE);
225 }
226 try (ResultScanner resultScanner = metaTable.getScanner(scan)) {
227 return resultScanner.next();
228 }
229 }
230
231
232
233
234
235
236
237
238
239 @Deprecated
240 public static HRegionInfo getHRegionInfo(Result data) {
241 return HRegionInfo.getHRegionInfo(data);
242 }
243
244
245
246
247
248
249
250
251
252
253
254 public static List<HRegionInfo> listAllRegions(Configuration conf, Connection connection,
255 final boolean offlined)
256 throws IOException {
257 final List<HRegionInfo> regions = new ArrayList<HRegionInfo>();
258 MetaScannerVisitor visitor = new MetaScannerVisitorBase() {
259 @Override
260 public boolean processRow(Result result) throws IOException {
261 if (result == null || result.isEmpty()) {
262 return true;
263 }
264
265 RegionLocations locations = MetaTableAccessor.getRegionLocations(result);
266 if (locations == null) return true;
267 for (HRegionLocation loc : locations.getRegionLocations()) {
268 if (loc != null) {
269 HRegionInfo regionInfo = loc.getRegionInfo();
270
271 if (regionInfo.isOffline() && !offlined) continue;
272 regions.add(regionInfo);
273 }
274 }
275 return true;
276 }
277 };
278 metaScan(connection, visitor);
279 return regions;
280 }
281
282
283
284
285
286
287
288
289
290
291 @Deprecated
292 public static NavigableMap<HRegionInfo, ServerName> allTableRegions(Configuration conf,
293 Connection connection, final TableName tableName, boolean offlined) throws IOException {
294 return allTableRegions(connection, tableName);
295 }
296
297
298
299
300
301
302
303
304 public static NavigableMap<HRegionInfo, ServerName> allTableRegions(
305 Connection connection, final TableName tableName) throws IOException {
306 final NavigableMap<HRegionInfo, ServerName> regions =
307 new TreeMap<HRegionInfo, ServerName>();
308 MetaScannerVisitor visitor = new TableMetaScannerVisitor(tableName) {
309 @Override
310 public boolean processRowInternal(Result result) throws IOException {
311 RegionLocations locations = MetaTableAccessor.getRegionLocations(result);
312 if (locations == null) return true;
313 for (HRegionLocation loc : locations.getRegionLocations()) {
314 if (loc != null) {
315 HRegionInfo regionInfo = loc.getRegionInfo();
316 regions.put(new UnmodifyableHRegionInfo(regionInfo), loc.getServerName());
317 }
318 }
319 return true;
320 }
321 };
322 metaScan(connection, visitor, tableName);
323 return regions;
324 }
325
326
327
328
329 public static List<RegionLocations> listTableRegionLocations(Configuration conf,
330 Connection connection, final TableName tableName) throws IOException {
331 final List<RegionLocations> regions = new ArrayList<RegionLocations>();
332 MetaScannerVisitor visitor = new TableMetaScannerVisitor(tableName) {
333 @Override
334 public boolean processRowInternal(Result result) throws IOException {
335 RegionLocations locations = MetaTableAccessor.getRegionLocations(result);
336 if (locations == null) return true;
337 regions.add(locations);
338 return true;
339 }
340 };
341 metaScan(connection, visitor, tableName);
342 return regions;
343 }
344
345
346
347
348 public interface MetaScannerVisitor extends Closeable {
349
350
351
352
353
354
355
356
357
358 boolean processRow(Result rowResult) throws IOException;
359 }
360
361 public static abstract class MetaScannerVisitorBase implements MetaScannerVisitor {
362 @Override
363 public void close() throws IOException {
364 }
365 }
366
367
368
369
370 public static abstract class DefaultMetaScannerVisitor
371 extends MetaScannerVisitorBase {
372
373 public DefaultMetaScannerVisitor() {
374 super();
375 }
376
377 public abstract boolean processRowInternal(Result rowResult) throws IOException;
378
379 @Override
380 public boolean processRow(Result rowResult) throws IOException {
381 HRegionInfo info = getHRegionInfo(rowResult);
382 if (info == null) {
383 return true;
384 }
385
386
387 if (!(info.isOffline() || info.isSplit())) {
388 return processRowInternal(rowResult);
389 }
390 return true;
391 }
392 }
393
394
395
396
397
398
399
400 public static abstract class TableMetaScannerVisitor extends DefaultMetaScannerVisitor {
401 private TableName tableName;
402
403 public TableMetaScannerVisitor(TableName tableName) {
404 super();
405 this.tableName = tableName;
406 }
407
408 @Override
409 public final boolean processRow(Result rowResult) throws IOException {
410 HRegionInfo info = getHRegionInfo(rowResult);
411 if (info == null) {
412 return true;
413 }
414 if (!(info.getTable().equals(tableName))) {
415 return false;
416 }
417 return super.processRow(rowResult);
418 }
419 }
420 }