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.hbase.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.ServerName;
28 import org.apache.hadoop.hbase.client.Get;
29 import org.apache.hadoop.hbase.client.HTable;
30 import org.apache.hadoop.hbase.client.Result;
31 import org.apache.hadoop.hbase.client.ResultScanner;
32 import org.apache.hadoop.hbase.client.Scan;
33 import org.apache.hadoop.hbase.util.Bytes;
34 import org.apache.hadoop.hbase.util.Pair;
35
36 import java.io.IOException;
37 import java.io.InterruptedIOException;
38 import java.util.ArrayList;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.NavigableMap;
42 import java.util.Set;
43 import java.util.TreeMap;
44
45
46
47
48 @InterfaceAudience.Private
49 public class MetaReader {
50
51
52
53 private static final Log LOG = LogFactory.getLog(MetaReader.class);
54
55 static final byte [] META_REGION_PREFIX;
56 static {
57
58
59 int len = HRegionInfo.FIRST_META_REGIONINFO.getRegionName().length - 2;
60 META_REGION_PREFIX = new byte [len];
61 System.arraycopy(HRegionInfo.FIRST_META_REGIONINFO.getRegionName(), 0,
62 META_REGION_PREFIX, 0, len);
63 }
64
65
66
67
68
69
70
71
72
73
74
75 public static Map<HRegionInfo, ServerName> fullScan(
76 CatalogTracker catalogTracker, final Set<TableName> disabledTables)
77 throws IOException {
78 return fullScan(catalogTracker, disabledTables, false);
79 }
80
81
82
83
84
85
86
87
88
89
90
91
92
93 public static Map<HRegionInfo, ServerName> fullScan(
94 CatalogTracker catalogTracker, final Set<TableName> disabledTables,
95 final boolean excludeOfflinedSplitParents)
96 throws IOException {
97 final Map<HRegionInfo, ServerName> regions =
98 new TreeMap<HRegionInfo, ServerName>();
99 Visitor v = new Visitor() {
100 @Override
101 public boolean visit(Result r) throws IOException {
102 if (r == null || r.isEmpty()) return true;
103 Pair<HRegionInfo, ServerName> region = HRegionInfo.getHRegionInfoAndServerName(r);
104 HRegionInfo hri = region.getFirst();
105 if (hri == null) return true;
106 if (hri.getTable() == null) return true;
107 if (disabledTables.contains(
108 hri.getTable())) return true;
109
110 if (excludeOfflinedSplitParents && hri.isSplitParent()) return true;
111 regions.put(hri, region.getSecond());
112 return true;
113 }
114 };
115 fullScan(catalogTracker, v);
116 return regions;
117 }
118
119
120
121
122
123
124 public static List<Result> fullScan(CatalogTracker catalogTracker)
125 throws IOException {
126 CollectAllVisitor v = new CollectAllVisitor();
127 fullScan(catalogTracker, v, null);
128 return v.getResults();
129 }
130
131
132
133
134
135
136 public static List<Result> fullScanOfMeta(CatalogTracker catalogTracker)
137 throws IOException {
138 CollectAllVisitor v = new CollectAllVisitor();
139 fullScan(catalogTracker, v, null);
140 return v.getResults();
141 }
142
143
144
145
146
147
148
149 public static void fullScan(CatalogTracker catalogTracker,
150 final Visitor visitor)
151 throws IOException {
152 fullScan(catalogTracker, visitor, null);
153 }
154
155
156
157
158
159
160
161
162 @SuppressWarnings("deprecation")
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(TableName.META_TABLE_NAME)) {
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 if (HRegionInfo.getHRegionInfo(r) == null) return;
486 ServerName sn = HRegionInfo.getServerName(r);
487 if (sn != null && sn.equals(serverName)) {
488 this.results.add(r);
489 }
490 }
491 };
492 fullScan(catalogTracker, v);
493 List<Result> results = v.getResults();
494 if (results != null && !results.isEmpty()) {
495
496 for (Result r: results) {
497 HRegionInfo hri = HRegionInfo.getHRegionInfo(r);
498 if (hri != null) hris.put(hri, r);
499 }
500 }
501 return hris;
502 }
503
504 public static void fullScanMetaAndPrint(final CatalogTracker catalogTracker)
505 throws IOException {
506 Visitor v = new Visitor() {
507 @Override
508 public boolean visit(Result r) throws IOException {
509 if (r == null || r.isEmpty()) return true;
510 LOG.info("fullScanMetaAndPrint.Current Meta Row: " + r);
511 HRegionInfo hrim = HRegionInfo.getHRegionInfo(r);
512 LOG.info("fullScanMetaAndPrint.HRI Print= " + hrim);
513 return true;
514 }
515 };
516 fullScan(catalogTracker, v);
517 }
518
519
520
521
522
523
524
525
526
527
528 public static void fullScan(CatalogTracker catalogTracker,
529 final Visitor visitor, final byte [] startrow)
530 throws IOException {
531 Scan scan = new Scan();
532 if (startrow != null) scan.setStartRow(startrow);
533 if (startrow == null) {
534 int caching = catalogTracker.getConnection().getConfiguration()
535 .getInt(HConstants.HBASE_META_SCANNER_CACHING, 100);
536 scan.setCaching(caching);
537 }
538 scan.addFamily(HConstants.CATALOG_FAMILY);
539 HTable metaTable = getMetaHTable(catalogTracker);
540 ResultScanner scanner = null;
541 try {
542 scanner = metaTable.getScanner(scan);
543 Result data;
544 while((data = scanner.next()) != null) {
545 if (data.isEmpty()) continue;
546
547 if (!visitor.visit(data)) break;
548 }
549 } finally {
550 if (scanner != null) scanner.close();
551 metaTable.close();
552 }
553 return;
554 }
555
556
557
558
559 public interface Visitor {
560
561
562
563
564
565
566 boolean visit(final Result r) throws IOException;
567 }
568
569
570
571
572 static abstract class CollectingVisitor<T> implements Visitor {
573 final List<T> results = new ArrayList<T>();
574 @Override
575 public boolean visit(Result r) throws IOException {
576 if (r == null || r.isEmpty()) return true;
577 add(r);
578 return true;
579 }
580
581 abstract void add(Result r);
582
583
584
585
586
587 List<T> getResults() {
588 return this.results;
589 }
590 }
591
592
593
594
595 static class CollectAllVisitor extends CollectingVisitor<Result> {
596 @Override
597 void add(Result r) {
598 this.results.add(r);
599 }
600 }
601
602
603
604
605
606
607
608
609 public static int getRegionCount(final Configuration c, final String tableName) throws IOException {
610 HTable t = new HTable(c, tableName);
611 try {
612 return t.getRegionLocations().size();
613 } finally {
614 t.close();
615 }
616 }
617 }