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