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.classification.InterfaceAudience;
32 import org.apache.hadoop.conf.Configuration;
33 import org.apache.hadoop.hbase.TableName;
34 import org.apache.hadoop.hbase.HConstants;
35 import org.apache.hadoop.hbase.HRegionInfo;
36 import org.apache.hadoop.hbase.ServerName;
37 import org.apache.hadoop.hbase.TableNotFoundException;
38 import org.apache.hadoop.hbase.util.Bytes;
39
40
41
42
43
44
45
46
47
48
49
50
51 @InterfaceAudience.Private
52 public class MetaScanner {
53 private static final Log LOG = LogFactory.getLog(MetaScanner.class);
54
55
56
57
58
59
60
61
62 public static void metaScan(Configuration configuration,
63 MetaScannerVisitor visitor)
64 throws IOException {
65 metaScan(configuration, visitor, null, null, Integer.MAX_VALUE);
66 }
67
68
69
70
71
72
73
74
75
76
77
78
79 public static void metaScan(Configuration configuration, HConnection connection,
80 MetaScannerVisitor visitor, TableName userTableName)
81 throws IOException {
82 metaScan(configuration, connection, visitor, userTableName, null, Integer.MAX_VALUE,
83 TableName.META_TABLE_NAME);
84 }
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101 public static void metaScan(Configuration configuration,
102 MetaScannerVisitor visitor, TableName userTableName, byte[] row,
103 int rowLimit)
104 throws IOException {
105 metaScan(configuration, null, visitor, userTableName, row, rowLimit,
106 TableName.META_TABLE_NAME);
107 }
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126 public static void metaScan(Configuration configuration, HConnection connection,
127 final MetaScannerVisitor visitor, final TableName tableName,
128 final byte[] row, final int rowLimit, final TableName metaTableName)
129 throws IOException {
130 int rowUpperLimit = rowLimit > 0 ? rowLimit: Integer.MAX_VALUE;
131 HTable metaTable;
132 if (connection == null) {
133 metaTable = new HTable(configuration, TableName.META_TABLE_NAME, null);
134 } else {
135 metaTable = new HTable(TableName.META_TABLE_NAME, connection, null);
136 }
137
138 byte[] startRow;
139 ResultScanner scanner = null;
140 try {
141 if (row != null) {
142
143 byte[] searchRow = HRegionInfo.createRegionName(tableName, row, HConstants.NINES, false);
144 Result startRowResult = metaTable.getRowOrBefore(searchRow, HConstants.CATALOG_FAMILY);
145 if (startRowResult == null) {
146 throw new TableNotFoundException("Cannot find row in "+ TableName
147 .META_TABLE_NAME.getNameAsString()+" for table: "
148 + tableName + ", row=" + Bytes.toStringBinary(searchRow));
149 }
150 HRegionInfo regionInfo = getHRegionInfo(startRowResult);
151 if (regionInfo == null) {
152 throw new IOException("HRegionInfo was null or empty in Meta for " +
153 tableName + ", row=" + Bytes.toStringBinary(searchRow));
154 }
155 byte[] rowBefore = regionInfo.getStartKey();
156 startRow = HRegionInfo.createRegionName(tableName, rowBefore, HConstants.ZEROES, false);
157 } else if (tableName == null || tableName.getName().length == 0) {
158
159 startRow = HConstants.EMPTY_START_ROW;
160 } else {
161
162 startRow = HRegionInfo.createRegionName(tableName, HConstants.EMPTY_START_ROW,
163 HConstants.ZEROES, false);
164 }
165 final Scan scan = new Scan(startRow).addFamily(HConstants.CATALOG_FAMILY);
166 int rows = Math.min(rowLimit, configuration.getInt(HConstants.HBASE_META_SCANNER_CACHING,
167 HConstants.DEFAULT_HBASE_META_SCANNER_CACHING));
168 scan.setCaching(rows);
169 if (LOG.isTraceEnabled()) {
170 LOG.trace("Scanning " + metaTableName.getNameAsString() + " starting at row=" +
171 Bytes.toStringBinary(startRow) + " for max=" + rowUpperLimit + " with caching=" + rows);
172 }
173
174 scanner = metaTable.getScanner(scan);
175 Result result = null;
176 int processedRows = 0;
177 while ((result = scanner.next()) != null) {
178 if (visitor != null) {
179 if (!visitor.processRow(result)) break;
180 }
181 processedRows++;
182 if (processedRows >= rowUpperLimit) break;
183 }
184 } finally {
185 if (scanner != null) {
186 try {
187 scanner.close();
188 } catch (Throwable t) {
189 LOG.debug("Got exception in closing the result scanner", t);
190 }
191 }
192 if (visitor != null) {
193 try {
194 visitor.close();
195 } catch (Throwable t) {
196 LOG.debug("Got exception in closing the meta scanner visitor", t);
197 }
198 }
199 if (metaTable != null) {
200 try {
201 metaTable.close();
202 } catch (Throwable t) {
203 LOG.debug("Got exception in closing the meta table", t);
204 }
205 }
206 }
207 }
208
209
210
211
212
213
214
215
216 public static HRegionInfo getHRegionInfo(Result data) {
217 return HRegionInfo.getHRegionInfo(data);
218 }
219
220
221
222
223
224
225
226
227
228
229
230 public static List<HRegionInfo> listAllRegions(Configuration conf, final boolean offlined)
231 throws IOException {
232 final List<HRegionInfo> regions = new ArrayList<HRegionInfo>();
233 MetaScannerVisitor visitor = new DefaultMetaScannerVisitor() {
234 @Override
235 public boolean processRowInternal(Result result) throws IOException {
236 if (result == null || result.isEmpty()) {
237 return true;
238 }
239
240 HRegionInfo regionInfo = getHRegionInfo(result);
241 if (regionInfo == null) {
242 LOG.warn("Null REGIONINFO_QUALIFIER: " + result);
243 return true;
244 }
245
246
247 if (regionInfo.isOffline() && !offlined) return true;
248 regions.add(regionInfo);
249 return true;
250 }
251 };
252 metaScan(conf, visitor);
253 return regions;
254 }
255
256
257
258
259
260
261
262
263
264 public static NavigableMap<HRegionInfo, ServerName> allTableRegions(Configuration conf,
265 HConnection connection, final TableName tableName,
266 final boolean offlined) throws IOException {
267 final NavigableMap<HRegionInfo, ServerName> regions =
268 new TreeMap<HRegionInfo, ServerName>();
269 MetaScannerVisitor visitor = new TableMetaScannerVisitor(tableName) {
270 @Override
271 public boolean processRowInternal(Result rowResult) throws IOException {
272 HRegionInfo info = getHRegionInfo(rowResult);
273 ServerName serverName = HRegionInfo.getServerName(rowResult);
274 regions.put(new UnmodifyableHRegionInfo(info), serverName);
275 return true;
276 }
277 };
278 metaScan(conf, connection, visitor, tableName);
279 return regions;
280 }
281
282
283
284
285 public interface MetaScannerVisitor extends Closeable {
286
287
288
289
290
291
292
293
294
295 boolean processRow(Result rowResult) throws IOException;
296 }
297
298 public static abstract class MetaScannerVisitorBase implements MetaScannerVisitor {
299 @Override
300 public void close() throws IOException {
301 }
302 }
303
304
305
306
307 public static abstract class DefaultMetaScannerVisitor
308 extends MetaScannerVisitorBase {
309
310 public DefaultMetaScannerVisitor() {
311 super();
312 }
313
314 public abstract boolean processRowInternal(Result rowResult) throws IOException;
315
316 @Override
317 public boolean processRow(Result rowResult) throws IOException {
318 HRegionInfo info = getHRegionInfo(rowResult);
319 if (info == null) {
320 return true;
321 }
322
323
324 if (!(info.isOffline() || info.isSplit())) {
325 return processRowInternal(rowResult);
326 }
327 return true;
328 }
329 }
330
331
332
333
334
335
336
337 public static abstract class TableMetaScannerVisitor extends DefaultMetaScannerVisitor {
338 private TableName tableName;
339
340 public TableMetaScannerVisitor(TableName tableName) {
341 super();
342 this.tableName = tableName;
343 }
344
345 @Override
346 public final boolean processRow(Result rowResult) throws IOException {
347 HRegionInfo info = getHRegionInfo(rowResult);
348 if (info == null) {
349 return true;
350 }
351 if (!(info.getTable().equals(tableName))) {
352 return false;
353 }
354 return super.processRow(rowResult);
355 }
356 }
357 }