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.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.getTableName() == null) return true;
107 if (disabledTables.contains(
108 hri.getTableName())) 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 private static HTable getHTable(final CatalogTracker catalogTracker,
163 final TableName tableName)
164 throws IOException {
165
166
167 org.apache.hadoop.hbase.client.HConnection c = catalogTracker.getConnection();
168 if (c == null) throw new NullPointerException("No connection");
169 return new HTable(catalogTracker.getConnection().getConfiguration(), tableName);
170 }
171
172
173
174
175
176
177
178 static HTable getCatalogHTable(final CatalogTracker catalogTracker)
179 throws IOException {
180 return getMetaHTable(catalogTracker);
181 }
182
183
184
185
186
187
188
189 static HTable getMetaHTable(final CatalogTracker ct)
190 throws IOException {
191 return getHTable(ct, TableName.META_TABLE_NAME);
192 }
193
194
195
196
197
198
199 private static Result get(final HTable t, final Get g) throws IOException {
200 try {
201 return t.get(g);
202 } finally {
203 t.close();
204 }
205 }
206
207
208
209
210
211
212
213
214 static ServerName readRegionLocation(CatalogTracker catalogTracker,
215 byte [] regionName)
216 throws IOException {
217 Pair<HRegionInfo, ServerName> pair = getRegion(catalogTracker, regionName);
218 return (pair == null || pair.getSecond() == null)? null: pair.getSecond();
219 }
220
221
222
223
224
225
226
227
228 public static Pair<HRegionInfo, ServerName> getRegion(
229 CatalogTracker catalogTracker, byte [] regionName)
230 throws IOException {
231 Get get = new Get(regionName);
232 get.addFamily(HConstants.CATALOG_FAMILY);
233 Result r = get(getCatalogHTable(catalogTracker), get);
234 return (r == null || r.isEmpty())? null: HRegionInfo.getHRegionInfoAndServerName(r);
235 }
236
237
238
239
240
241
242
243
244 public static Result getRegionResult(CatalogTracker catalogTracker,
245 byte[] regionName) throws IOException {
246 Get get = new Get(regionName);
247 get.addFamily(HConstants.CATALOG_FAMILY);
248 return get(getCatalogHTable(catalogTracker), get);
249 }
250
251
252
253
254
255
256 public static Pair<HRegionInfo, HRegionInfo> getRegionsFromMergeQualifier(
257 CatalogTracker catalogTracker, byte[] regionName) throws IOException {
258 Result result = getRegionResult(catalogTracker, regionName);
259 HRegionInfo mergeA = HRegionInfo.getHRegionInfo(result,
260 HConstants.MERGEA_QUALIFIER);
261 HRegionInfo mergeB = HRegionInfo.getHRegionInfo(result,
262 HConstants.MERGEB_QUALIFIER);
263 if (mergeA == null && mergeB == null) {
264 return null;
265 }
266 return new Pair<HRegionInfo, HRegionInfo>(mergeA, mergeB);
267 }
268
269
270
271
272
273
274
275
276
277 public static boolean tableExists(CatalogTracker catalogTracker,
278 final TableName tableName)
279 throws IOException {
280 if (tableName.equals(HTableDescriptor.META_TABLEDESC.getTableName())) {
281
282 return true;
283 }
284
285 CollectingVisitor<HRegionInfo> visitor = new CollectingVisitor<HRegionInfo>() {
286 private HRegionInfo current = null;
287
288 @Override
289 public boolean visit(Result r) throws IOException {
290 this.current =
291 HRegionInfo.getHRegionInfo(r, HConstants.REGIONINFO_QUALIFIER);
292 if (this.current == null) {
293 LOG.warn("No serialized HRegionInfo in " + r);
294 return true;
295 }
296 if (!isInsideTable(this.current, tableName)) return false;
297
298 super.visit(r);
299
300 return false;
301 }
302
303 @Override
304 void add(Result r) {
305
306 this.results.add(this.current);
307 }
308 };
309 fullScan(catalogTracker, visitor, getTableStartRowForMeta(tableName));
310
311 return visitor.getResults().size() >= 1;
312 }
313
314
315
316
317
318
319
320
321 public static List<HRegionInfo> getTableRegions(CatalogTracker catalogTracker,
322 TableName tableName)
323 throws IOException {
324 return getTableRegions(catalogTracker, tableName, false);
325 }
326
327
328
329
330
331
332
333
334
335
336 public static List<HRegionInfo> getTableRegions(CatalogTracker catalogTracker,
337 TableName tableName, final boolean excludeOfflinedSplitParents)
338 throws IOException {
339 List<Pair<HRegionInfo, ServerName>> result = null;
340 try {
341 result = getTableRegionsAndLocations(catalogTracker, tableName,
342 excludeOfflinedSplitParents);
343 } catch (InterruptedException e) {
344 throw new RuntimeException(e);
345 }
346 return getListOfHRegionInfos(result);
347 }
348
349 static List<HRegionInfo> getListOfHRegionInfos(final List<Pair<HRegionInfo, ServerName>> pairs) {
350 if (pairs == null || pairs.isEmpty()) return null;
351 List<HRegionInfo> result = new ArrayList<HRegionInfo>(pairs.size());
352 for (Pair<HRegionInfo, ServerName> pair: pairs) {
353 result.add(pair.getFirst());
354 }
355 return result;
356 }
357
358
359
360
361
362
363
364 static boolean isInsideTable(final HRegionInfo current, final TableName tableName) {
365 return tableName.equals(current.getTableName());
366 }
367
368
369
370
371
372
373 static byte [] getTableStartRowForMeta(TableName tableName) {
374 byte [] startRow = new byte[tableName.getName().length + 2];
375 System.arraycopy(tableName.getName(), 0, startRow, 0, tableName.getName().length);
376 startRow[startRow.length - 2] = HConstants.DELIMITER;
377 startRow[startRow.length - 1] = HConstants.DELIMITER;
378 return startRow;
379 }
380
381
382
383
384
385
386
387
388
389
390 public static Scan getScanForTableName(TableName tableName) {
391 String strName = tableName.getNameAsString();
392
393 byte[] startKey = Bytes.toBytes(strName + ",,");
394
395 byte[] stopKey = Bytes.toBytes(strName + " ,,");
396
397 Scan scan = new Scan(startKey);
398 scan.setStopRow(stopKey);
399 return scan;
400 }
401
402
403
404
405
406
407
408
409 public static List<Pair<HRegionInfo, ServerName>>
410 getTableRegionsAndLocations(CatalogTracker catalogTracker, TableName tableName)
411 throws IOException, InterruptedException {
412 return getTableRegionsAndLocations(catalogTracker, tableName,
413 true);
414 }
415
416
417
418
419
420
421
422
423 public static List<Pair<HRegionInfo, ServerName>>
424 getTableRegionsAndLocations(final CatalogTracker catalogTracker,
425 final TableName tableName, final boolean excludeOfflinedSplitParents)
426 throws IOException, InterruptedException {
427 if (tableName.equals(TableName.META_TABLE_NAME)) {
428
429 ServerName serverName = catalogTracker.getMetaLocation();
430 List<Pair<HRegionInfo, ServerName>> list =
431 new ArrayList<Pair<HRegionInfo, ServerName>>();
432 list.add(new Pair<HRegionInfo, ServerName>(HRegionInfo.FIRST_META_REGIONINFO,
433 serverName));
434 return list;
435 }
436
437 CollectingVisitor<Pair<HRegionInfo, ServerName>> visitor =
438 new CollectingVisitor<Pair<HRegionInfo, ServerName>>() {
439 private Pair<HRegionInfo, ServerName> current = null;
440
441 @Override
442 public boolean visit(Result r) throws IOException {
443 HRegionInfo hri =
444 HRegionInfo.getHRegionInfo(r, HConstants.REGIONINFO_QUALIFIER);
445 if (hri == null) {
446 LOG.warn("No serialized HRegionInfo in " + r);
447 return true;
448 }
449 if (!isInsideTable(hri, tableName)) return false;
450 if (excludeOfflinedSplitParents && hri.isSplitParent()) return true;
451 ServerName sn = HRegionInfo.getServerName(r);
452
453 this.current = new Pair<HRegionInfo, ServerName>(hri, sn);
454
455 return super.visit(r);
456 }
457
458 @Override
459 void add(Result r) {
460 this.results.add(this.current);
461 }
462 };
463 fullScan(catalogTracker, visitor, getTableStartRowForMeta(tableName));
464 return visitor.getResults();
465 }
466
467
468
469
470
471
472
473
474 public static NavigableMap<HRegionInfo, Result>
475 getServerUserRegions(CatalogTracker catalogTracker, final ServerName serverName)
476 throws IOException {
477 final NavigableMap<HRegionInfo, Result> hris = new TreeMap<HRegionInfo, Result>();
478
479
480 CollectingVisitor<Result> v = new CollectingVisitor<Result>() {
481 @Override
482 void add(Result r) {
483 if (r == null || r.isEmpty()) return;
484 ServerName sn = HRegionInfo.getServerName(r);
485 if (sn != null && sn.equals(serverName)) this.results.add(r);
486 }
487 };
488 fullScan(catalogTracker, v);
489 List<Result> results = v.getResults();
490 if (results != null && !results.isEmpty()) {
491
492 for (Result r: results) {
493 Pair<HRegionInfo, ServerName> p = HRegionInfo.getHRegionInfoAndServerName(r);
494 if (p != null && p.getFirst() != null) hris.put(p.getFirst(), r);
495 }
496 }
497 return hris;
498 }
499
500 public static void fullScanMetaAndPrint(final CatalogTracker catalogTracker)
501 throws IOException {
502 Visitor v = new Visitor() {
503 @Override
504 public boolean visit(Result r) throws IOException {
505 if (r == null || r.isEmpty()) return true;
506 LOG.info("fullScanMetaAndPrint.Current Meta Row: " + r);
507 HRegionInfo hrim = HRegionInfo.getHRegionInfo(r);
508 LOG.info("fullScanMetaAndPrint.HRI Print= " + hrim);
509 return true;
510 }
511 };
512 fullScan(catalogTracker, v);
513 }
514
515
516
517
518
519
520
521
522
523
524 public static void fullScan(CatalogTracker catalogTracker,
525 final Visitor visitor, final byte [] startrow)
526 throws IOException {
527 Scan scan = new Scan();
528 if (startrow != null) scan.setStartRow(startrow);
529 if (startrow == null) {
530 int caching = catalogTracker.getConnection().getConfiguration()
531 .getInt(HConstants.HBASE_META_SCANNER_CACHING, 100);
532 scan.setCaching(caching);
533 }
534 scan.addFamily(HConstants.CATALOG_FAMILY);
535 HTable metaTable = getMetaHTable(catalogTracker);
536 ResultScanner scanner = metaTable.getScanner(scan);
537 try {
538 Result data;
539 while((data = scanner.next()) != null) {
540 if (data.isEmpty()) continue;
541
542 if (!visitor.visit(data)) break;
543 }
544 } finally {
545 scanner.close();
546 metaTable.close();
547 }
548 return;
549 }
550
551
552
553
554 public interface Visitor {
555
556
557
558
559
560
561 boolean visit(final Result r) throws IOException;
562 }
563
564
565
566
567 static abstract class CollectingVisitor<T> implements Visitor {
568 final List<T> results = new ArrayList<T>();
569 @Override
570 public boolean visit(Result r) throws IOException {
571 if (r == null || r.isEmpty()) return true;
572 add(r);
573 return true;
574 }
575
576 abstract void add(Result r);
577
578
579
580
581
582 List<T> getResults() {
583 return this.results;
584 }
585 }
586
587
588
589
590 static class CollectAllVisitor extends CollectingVisitor<Result> {
591 @Override
592 void add(Result r) {
593 this.results.add(r);
594 }
595 }
596
597
598
599
600
601
602
603
604 public static int getRegionCount(final Configuration c, final String tableName) throws IOException {
605 HTable t = new HTable(c, tableName);
606 try {
607 return t.getRegionLocations().size();
608 } finally {
609 t.close();
610 }
611 }
612 }