1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.catalog;
19
20 import org.apache.commons.logging.Log;
21 import org.apache.commons.logging.LogFactory;
22 import org.apache.hadoop.classification.InterfaceAudience;
23 import org.apache.hadoop.conf.Configuration;
24 import org.apache.hadoop.hbase.TableName;
25 import org.apache.hadoop.hbase.HConstants;
26 import org.apache.hadoop.hbase.HRegionInfo;
27 import org.apache.hadoop.hbase.HTableDescriptor;
28 import org.apache.hadoop.hbase.ServerName;
29 import org.apache.hadoop.hbase.client.Get;
30 import org.apache.hadoop.hbase.client.HTable;
31 import org.apache.hadoop.hbase.client.Result;
32 import org.apache.hadoop.hbase.client.ResultScanner;
33 import org.apache.hadoop.hbase.client.Scan;
34 import org.apache.hadoop.hbase.util.Bytes;
35 import org.apache.hadoop.hbase.util.Pair;
36
37 import java.io.IOException;
38 import java.io.InterruptedIOException;
39 import java.util.ArrayList;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.NavigableMap;
43 import java.util.Set;
44 import java.util.TreeMap;
45
46
47
48
49 @InterfaceAudience.Private
50 public class MetaReader {
51
52
53
54 private static final Log LOG = LogFactory.getLog(MetaReader.class);
55
56 static final byte [] META_REGION_PREFIX;
57 static {
58
59
60 int len = HRegionInfo.FIRST_META_REGIONINFO.getRegionName().length - 2;
61 META_REGION_PREFIX = new byte [len];
62 System.arraycopy(HRegionInfo.FIRST_META_REGIONINFO.getRegionName(), 0,
63 META_REGION_PREFIX, 0, len);
64 }
65
66
67
68
69
70
71
72
73
74
75
76 public static Map<HRegionInfo, ServerName> fullScan(
77 CatalogTracker catalogTracker, final Set<TableName> disabledTables)
78 throws IOException {
79 return fullScan(catalogTracker, disabledTables, false);
80 }
81
82
83
84
85
86
87
88
89
90
91
92
93
94 public static Map<HRegionInfo, ServerName> fullScan(
95 CatalogTracker catalogTracker, final Set<TableName> disabledTables,
96 final boolean excludeOfflinedSplitParents)
97 throws IOException {
98 final Map<HRegionInfo, ServerName> regions =
99 new TreeMap<HRegionInfo, ServerName>();
100 Visitor v = new Visitor() {
101 @Override
102 public boolean visit(Result r) throws IOException {
103 if (r == null || r.isEmpty()) return true;
104 Pair<HRegionInfo, ServerName> region = HRegionInfo.getHRegionInfoAndServerName(r);
105 HRegionInfo hri = region.getFirst();
106 if (hri == null) return true;
107 if (hri.getTable() == null) return true;
108 if (disabledTables.contains(
109 hri.getTable())) return true;
110
111 if (excludeOfflinedSplitParents && hri.isSplitParent()) return true;
112 regions.put(hri, region.getSecond());
113 return true;
114 }
115 };
116 fullScan(catalogTracker, v);
117 return regions;
118 }
119
120
121
122
123
124
125 public static List<Result> fullScan(CatalogTracker catalogTracker)
126 throws IOException {
127 CollectAllVisitor v = new CollectAllVisitor();
128 fullScan(catalogTracker, v, null);
129 return v.getResults();
130 }
131
132
133
134
135
136
137 public static List<Result> fullScanOfMeta(CatalogTracker catalogTracker)
138 throws IOException {
139 CollectAllVisitor v = new CollectAllVisitor();
140 fullScan(catalogTracker, v, null);
141 return v.getResults();
142 }
143
144
145
146
147
148
149
150 public static void fullScan(CatalogTracker catalogTracker,
151 final Visitor visitor)
152 throws IOException {
153 fullScan(catalogTracker, visitor, null);
154 }
155
156
157
158
159
160
161
162
163 private static HTable getHTable(final CatalogTracker catalogTracker,
164 final TableName tableName)
165 throws IOException {
166
167
168 org.apache.hadoop.hbase.client.HConnection c = catalogTracker.getConnection();
169 if (c == null) throw new NullPointerException("No connection");
170 return new HTable(tableName, c);
171 }
172
173
174
175
176
177
178
179 static HTable getCatalogHTable(final CatalogTracker catalogTracker)
180 throws IOException {
181 return getMetaHTable(catalogTracker);
182 }
183
184
185
186
187
188
189
190 static HTable getMetaHTable(final CatalogTracker ct)
191 throws IOException {
192 return getHTable(ct, TableName.META_TABLE_NAME);
193 }
194
195
196
197
198
199
200 private static Result get(final HTable t, final Get g) throws IOException {
201 try {
202 return t.get(g);
203 } finally {
204 t.close();
205 }
206 }
207
208
209
210
211
212
213
214
215 static ServerName readRegionLocation(CatalogTracker catalogTracker,
216 byte [] regionName)
217 throws IOException {
218 Pair<HRegionInfo, ServerName> pair = getRegion(catalogTracker, regionName);
219 return (pair == null || pair.getSecond() == null)? null: pair.getSecond();
220 }
221
222
223
224
225
226
227
228
229 public static Pair<HRegionInfo, ServerName> getRegion(
230 CatalogTracker catalogTracker, byte [] regionName)
231 throws IOException {
232 Get get = new Get(regionName);
233 get.addFamily(HConstants.CATALOG_FAMILY);
234 Result r = get(getCatalogHTable(catalogTracker), get);
235 return (r == null || r.isEmpty())? null: HRegionInfo.getHRegionInfoAndServerName(r);
236 }
237
238
239
240
241
242
243
244
245 public static Result getRegionResult(CatalogTracker catalogTracker,
246 byte[] regionName) throws IOException {
247 Get get = new Get(regionName);
248 get.addFamily(HConstants.CATALOG_FAMILY);
249 return get(getCatalogHTable(catalogTracker), get);
250 }
251
252
253
254
255
256
257 public static Pair<HRegionInfo, HRegionInfo> getRegionsFromMergeQualifier(
258 CatalogTracker catalogTracker, byte[] regionName) throws IOException {
259 Result result = getRegionResult(catalogTracker, regionName);
260 HRegionInfo mergeA = HRegionInfo.getHRegionInfo(result,
261 HConstants.MERGEA_QUALIFIER);
262 HRegionInfo mergeB = HRegionInfo.getHRegionInfo(result,
263 HConstants.MERGEB_QUALIFIER);
264 if (mergeA == null && mergeB == null) {
265 return null;
266 }
267 return new Pair<HRegionInfo, HRegionInfo>(mergeA, mergeB);
268 }
269
270
271
272
273
274
275
276
277
278 public static boolean tableExists(CatalogTracker catalogTracker,
279 final TableName tableName)
280 throws IOException {
281 if (tableName.equals(HTableDescriptor.META_TABLEDESC.getTableName())) {
282
283 return true;
284 }
285
286 CollectingVisitor<HRegionInfo> visitor = new CollectingVisitor<HRegionInfo>() {
287 private HRegionInfo current = null;
288
289 @Override
290 public boolean visit(Result r) throws IOException {
291 this.current =
292 HRegionInfo.getHRegionInfo(r, HConstants.REGIONINFO_QUALIFIER);
293 if (this.current == null) {
294 LOG.warn("No serialized HRegionInfo in " + r);
295 return true;
296 }
297 if (!isInsideTable(this.current, tableName)) return false;
298
299 super.visit(r);
300
301 return false;
302 }
303
304 @Override
305 void add(Result r) {
306
307 this.results.add(this.current);
308 }
309 };
310 fullScan(catalogTracker, visitor, getTableStartRowForMeta(tableName));
311
312 return visitor.getResults().size() >= 1;
313 }
314
315
316
317
318
319
320
321
322 public static List<HRegionInfo> getTableRegions(CatalogTracker catalogTracker,
323 TableName tableName)
324 throws IOException {
325 return getTableRegions(catalogTracker, tableName, false);
326 }
327
328
329
330
331
332
333
334
335
336
337 public static List<HRegionInfo> getTableRegions(CatalogTracker catalogTracker,
338 TableName tableName, final boolean excludeOfflinedSplitParents)
339 throws IOException {
340 List<Pair<HRegionInfo, ServerName>> result = null;
341 try {
342 result = getTableRegionsAndLocations(catalogTracker, tableName,
343 excludeOfflinedSplitParents);
344 } catch (InterruptedException e) {
345 throw (InterruptedIOException)new InterruptedIOException().initCause(e);
346 }
347 return getListOfHRegionInfos(result);
348 }
349
350 static List<HRegionInfo> getListOfHRegionInfos(final List<Pair<HRegionInfo, ServerName>> pairs) {
351 if (pairs == null || pairs.isEmpty()) return null;
352 List<HRegionInfo> result = new ArrayList<HRegionInfo>(pairs.size());
353 for (Pair<HRegionInfo, ServerName> pair: pairs) {
354 result.add(pair.getFirst());
355 }
356 return result;
357 }
358
359
360
361
362
363
364
365 static boolean isInsideTable(final HRegionInfo current, final TableName tableName) {
366 return tableName.equals(current.getTable());
367 }
368
369
370
371
372
373
374 static byte [] getTableStartRowForMeta(TableName tableName) {
375 byte [] startRow = new byte[tableName.getName().length + 2];
376 System.arraycopy(tableName.getName(), 0, startRow, 0, tableName.getName().length);
377 startRow[startRow.length - 2] = HConstants.DELIMITER;
378 startRow[startRow.length - 1] = HConstants.DELIMITER;
379 return startRow;
380 }
381
382
383
384
385
386
387
388
389
390
391 public static Scan getScanForTableName(TableName tableName) {
392 String strName = tableName.getNameAsString();
393
394 byte[] startKey = Bytes.toBytes(strName + ",,");
395
396 byte[] stopKey = Bytes.toBytes(strName + " ,,");
397
398 Scan scan = new Scan(startKey);
399 scan.setStopRow(stopKey);
400 return scan;
401 }
402
403
404
405
406
407
408
409
410 public static List<Pair<HRegionInfo, ServerName>>
411 getTableRegionsAndLocations(CatalogTracker catalogTracker, TableName tableName)
412 throws IOException, InterruptedException {
413 return getTableRegionsAndLocations(catalogTracker, tableName,
414 true);
415 }
416
417
418
419
420
421
422
423
424 public static List<Pair<HRegionInfo, ServerName>>
425 getTableRegionsAndLocations(final CatalogTracker catalogTracker,
426 final TableName tableName, final boolean excludeOfflinedSplitParents)
427 throws IOException, InterruptedException {
428 if (tableName.equals(TableName.META_TABLE_NAME)) {
429
430 ServerName serverName = catalogTracker.getMetaLocation();
431 List<Pair<HRegionInfo, ServerName>> list =
432 new ArrayList<Pair<HRegionInfo, ServerName>>();
433 list.add(new Pair<HRegionInfo, ServerName>(HRegionInfo.FIRST_META_REGIONINFO,
434 serverName));
435 return list;
436 }
437
438 CollectingVisitor<Pair<HRegionInfo, ServerName>> visitor =
439 new CollectingVisitor<Pair<HRegionInfo, ServerName>>() {
440 private Pair<HRegionInfo, ServerName> current = null;
441
442 @Override
443 public boolean visit(Result r) throws IOException {
444 HRegionInfo hri =
445 HRegionInfo.getHRegionInfo(r, HConstants.REGIONINFO_QUALIFIER);
446 if (hri == null) {
447 LOG.warn("No serialized HRegionInfo in " + r);
448 return true;
449 }
450 if (!isInsideTable(hri, tableName)) return false;
451 if (excludeOfflinedSplitParents && hri.isSplitParent()) return true;
452 ServerName sn = HRegionInfo.getServerName(r);
453
454 this.current = new Pair<HRegionInfo, ServerName>(hri, sn);
455
456 return super.visit(r);
457 }
458
459 @Override
460 void add(Result r) {
461 this.results.add(this.current);
462 }
463 };
464 fullScan(catalogTracker, visitor, getTableStartRowForMeta(tableName));
465 return visitor.getResults();
466 }
467
468
469
470
471
472
473
474
475 public static NavigableMap<HRegionInfo, Result>
476 getServerUserRegions(CatalogTracker catalogTracker, final ServerName serverName)
477 throws IOException {
478 final NavigableMap<HRegionInfo, Result> hris = new TreeMap<HRegionInfo, Result>();
479
480
481 CollectingVisitor<Result> v = new CollectingVisitor<Result>() {
482 @Override
483 void add(Result r) {
484 if (r == null || r.isEmpty()) return;
485 ServerName sn = HRegionInfo.getServerName(r);
486 if (sn != null && sn.equals(serverName)) this.results.add(r);
487 }
488 };
489 fullScan(catalogTracker, v);
490 List<Result> results = v.getResults();
491 if (results != null && !results.isEmpty()) {
492
493 for (Result r: results) {
494 Pair<HRegionInfo, ServerName> p = HRegionInfo.getHRegionInfoAndServerName(r);
495 if (p != null && p.getFirst() != null) hris.put(p.getFirst(), r);
496 }
497 }
498 return hris;
499 }
500
501 public static void fullScanMetaAndPrint(final CatalogTracker catalogTracker)
502 throws IOException {
503 Visitor v = new Visitor() {
504 @Override
505 public boolean visit(Result r) throws IOException {
506 if (r == null || r.isEmpty()) return true;
507 LOG.info("fullScanMetaAndPrint.Current Meta Row: " + r);
508 HRegionInfo hrim = HRegionInfo.getHRegionInfo(r);
509 LOG.info("fullScanMetaAndPrint.HRI Print= " + hrim);
510 return true;
511 }
512 };
513 fullScan(catalogTracker, v);
514 }
515
516
517
518
519
520
521
522
523
524
525 public static void fullScan(CatalogTracker catalogTracker,
526 final Visitor visitor, final byte [] startrow)
527 throws IOException {
528 Scan scan = new Scan();
529 if (startrow != null) scan.setStartRow(startrow);
530 if (startrow == null) {
531 int caching = catalogTracker.getConnection().getConfiguration()
532 .getInt(HConstants.HBASE_META_SCANNER_CACHING, 100);
533 scan.setCaching(caching);
534 }
535 scan.addFamily(HConstants.CATALOG_FAMILY);
536 HTable metaTable = getMetaHTable(catalogTracker);
537 ResultScanner scanner = null;
538 try {
539 scanner = metaTable.getScanner(scan);
540 Result data;
541 while((data = scanner.next()) != null) {
542 if (data.isEmpty()) continue;
543
544 if (!visitor.visit(data)) break;
545 }
546 } finally {
547 if (scanner != null) scanner.close();
548 metaTable.close();
549 }
550 return;
551 }
552
553
554
555
556 public interface Visitor {
557
558
559
560
561
562
563 boolean visit(final Result r) throws IOException;
564 }
565
566
567
568
569 static abstract class CollectingVisitor<T> implements Visitor {
570 final List<T> results = new ArrayList<T>();
571 @Override
572 public boolean visit(Result r) throws IOException {
573 if (r == null || r.isEmpty()) return true;
574 add(r);
575 return true;
576 }
577
578 abstract void add(Result r);
579
580
581
582
583
584 List<T> getResults() {
585 return this.results;
586 }
587 }
588
589
590
591
592 static class CollectAllVisitor extends CollectingVisitor<Result> {
593 @Override
594 void add(Result r) {
595 this.results.add(r);
596 }
597 }
598
599
600
601
602
603
604
605
606 public static int getRegionCount(final Configuration c, final String tableName) throws IOException {
607 HTable t = new HTable(c, tableName);
608 try {
609 return t.getRegionLocations().size();
610 } finally {
611 t.close();
612 }
613 }
614 }