1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.hadoop.hbase.client;
22
23 import java.io.IOException;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.NavigableMap;
28 import java.util.TreeMap;
29 import java.util.TreeSet;
30
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.apache.hadoop.conf.Configuration;
34 import org.apache.hadoop.hbase.HConstants;
35 import org.apache.hadoop.hbase.HRegionInfo;
36 import org.apache.hadoop.hbase.HServerAddress;
37 import org.apache.hadoop.hbase.ServerName;
38 import org.apache.hadoop.hbase.TableNotFoundException;
39 import org.apache.hadoop.hbase.client.HConnectionManager.HConnectable;
40 import org.apache.hadoop.hbase.util.Addressing;
41 import org.apache.hadoop.hbase.util.Bytes;
42 import org.apache.hadoop.hbase.util.Writables;
43
44
45
46
47
48
49
50
51
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);
66 }
67
68
69
70
71
72
73
74
75
76
77
78 public static void metaScan(Configuration configuration,
79 MetaScannerVisitor visitor, byte [] userTableName)
80 throws IOException {
81 metaScan(configuration, visitor, userTableName, null, Integer.MAX_VALUE);
82 }
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99 public static void metaScan(Configuration configuration,
100 MetaScannerVisitor visitor, byte [] userTableName, byte[] row,
101 int rowLimit)
102 throws IOException {
103 metaScan(configuration, visitor, userTableName, row, rowLimit,
104 HConstants.META_TABLE_NAME);
105 }
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123 public static void metaScan(Configuration configuration,
124 final MetaScannerVisitor visitor, final byte[] tableName,
125 final byte[] row, final int rowLimit, final byte[] metaTableName)
126 throws IOException {
127 HConnectionManager.execute(new HConnectable<Void>(configuration) {
128 @Override
129 public Void connect(HConnection connection) throws IOException {
130 metaScan(conf, connection, visitor, tableName, row, rowLimit,
131 metaTableName);
132 return null;
133 }
134 });
135 }
136
137 private static void metaScan(Configuration configuration, HConnection connection,
138 MetaScannerVisitor visitor, byte [] tableName, byte[] row,
139 int rowLimit, final byte [] metaTableName)
140 throws IOException {
141 int rowUpperLimit = rowLimit > 0 ? rowLimit: Integer.MAX_VALUE;
142
143
144
145 byte[] startRow;
146 if (row != null) {
147
148 assert tableName != null;
149 byte[] searchRow =
150 HRegionInfo.createRegionName(tableName, row, HConstants.NINES,
151 false);
152
153 HTable metaTable = new HTable(configuration, HConstants.META_TABLE_NAME);
154 Result startRowResult = metaTable.getRowOrBefore(searchRow,
155 HConstants.CATALOG_FAMILY);
156 if (startRowResult == null) {
157 throw new TableNotFoundException("Cannot find row in .META. for table: "
158 + Bytes.toString(tableName) + ", row=" + Bytes.toStringBinary(searchRow));
159 }
160 byte[] value = startRowResult.getValue(HConstants.CATALOG_FAMILY,
161 HConstants.REGIONINFO_QUALIFIER);
162 if (value == null || value.length == 0) {
163 throw new IOException("HRegionInfo was null or empty in Meta for " +
164 Bytes.toString(tableName) + ", row=" + Bytes.toStringBinary(searchRow));
165 }
166 HRegionInfo regionInfo = Writables.getHRegionInfo(value);
167
168 byte[] rowBefore = regionInfo.getStartKey();
169 startRow = HRegionInfo.createRegionName(tableName, rowBefore,
170 HConstants.ZEROES, false);
171 } else if (tableName == null || tableName.length == 0) {
172
173 startRow = HConstants.EMPTY_START_ROW;
174 } else {
175
176 startRow = HRegionInfo.createRegionName(
177 tableName, HConstants.EMPTY_START_ROW, HConstants.ZEROES, false);
178 }
179
180
181 ScannerCallable callable;
182 int rows = Math.min(rowLimit, configuration.getInt(
183 HConstants.HBASE_META_SCANNER_CACHING,
184 HConstants.DEFAULT_HBASE_META_SCANNER_CACHING));
185 do {
186 final Scan scan = new Scan(startRow).addFamily(HConstants.CATALOG_FAMILY);
187 if (LOG.isDebugEnabled()) {
188 LOG.debug("Scanning " + Bytes.toString(metaTableName) +
189 " starting at row=" + Bytes.toStringBinary(startRow) + " for max=" +
190 rowUpperLimit + " rows using " + connection.toString());
191 }
192 callable = new ScannerCallable(connection, metaTableName, scan);
193
194 connection.getRegionServerWithRetries(callable);
195
196 int processedRows = 0;
197 try {
198 callable.setCaching(rows);
199 done: do {
200 if (processedRows >= rowUpperLimit) {
201 break;
202 }
203
204 Result [] rrs = connection.getRegionServerWithRetries(callable);
205 if (rrs == null || rrs.length == 0 || rrs[0].size() == 0) {
206 break;
207 }
208 for (Result rr : rrs) {
209 if (processedRows >= rowUpperLimit) {
210 break done;
211 }
212 if (!visitor.processRow(rr))
213 break done;
214 processedRows++;
215 }
216
217 } while(true);
218
219 startRow = callable.getHRegionInfo().getEndKey();
220 } finally {
221
222 callable.setClose();
223 connection.getRegionServerWithRetries(callable);
224 }
225 } while (Bytes.compareTo(startRow, HConstants.LAST_ROW) != 0);
226 }
227
228
229
230
231
232
233
234 public static List<HRegionInfo> listAllRegions(Configuration conf)
235 throws IOException {
236 return listAllRegions(conf, true);
237 }
238
239
240
241
242
243
244
245
246
247 public static List<HRegionInfo> listAllRegions(Configuration conf, final boolean offlined)
248 throws IOException {
249 final List<HRegionInfo> regions = new ArrayList<HRegionInfo>();
250 MetaScannerVisitor visitor = new MetaScannerVisitor() {
251 @Override
252 public boolean processRow(Result result) throws IOException {
253 if (result == null || result.isEmpty()) {
254 return true;
255 }
256 byte [] bytes = result.getValue(HConstants.CATALOG_FAMILY,
257 HConstants.REGIONINFO_QUALIFIER);
258 if (bytes == null) {
259 LOG.warn("Null REGIONINFO_QUALIFIER: " + result);
260 return true;
261 }
262 HRegionInfo regionInfo = Writables.getHRegionInfo(bytes);
263
264 if (regionInfo.isOffline() && !offlined) return true;
265 regions.add(regionInfo);
266 return true;
267 }
268 };
269 metaScan(conf, visitor);
270 return regions;
271 }
272
273
274
275
276
277
278
279
280
281 public static NavigableMap<HRegionInfo, ServerName> allTableRegions(Configuration conf, final byte [] tablename, final boolean offlined)
282 throws IOException {
283 final NavigableMap<HRegionInfo, ServerName> regions =
284 new TreeMap<HRegionInfo, ServerName>();
285 MetaScannerVisitor visitor = new MetaScannerVisitor() {
286 @Override
287 public boolean processRow(Result rowResult) throws IOException {
288 HRegionInfo info = Writables.getHRegionInfo(
289 rowResult.getValue(HConstants.CATALOG_FAMILY,
290 HConstants.REGIONINFO_QUALIFIER));
291 if (!(Bytes.equals(info.getTableName(), tablename))) {
292 return false;
293 }
294 byte [] value = rowResult.getValue(HConstants.CATALOG_FAMILY,
295 HConstants.SERVER_QUALIFIER);
296 String hostAndPort = null;
297 if (value != null && value.length > 0) {
298 hostAndPort = Bytes.toString(value);
299 }
300 value = rowResult.getValue(HConstants.CATALOG_FAMILY,
301 HConstants.STARTCODE_QUALIFIER);
302 long startcode = -1L;
303 if (value != null && value.length > 0) startcode = Bytes.toLong(value);
304 if (!(info.isOffline() || info.isSplit())) {
305 ServerName sn = null;
306 if (hostAndPort != null && hostAndPort.length() > 0) {
307 sn = new ServerName(hostAndPort, startcode);
308 }
309 regions.put(new UnmodifyableHRegionInfo(info), sn);
310 }
311 return true;
312 }
313 };
314 metaScan(conf, visitor, tablename);
315 return regions;
316 }
317
318
319
320
321 public interface MetaScannerVisitor {
322
323
324
325
326
327
328
329
330
331 public boolean processRow(Result rowResult) throws IOException;
332 }
333 }