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 java.io.IOException;
21 import java.util.ArrayList;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.NavigableMap;
25 import java.util.Set;
26 import java.util.TreeMap;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.apache.hadoop.hbase.HConstants;
31 import org.apache.hadoop.hbase.HRegionInfo;
32 import org.apache.hadoop.hbase.HTableDescriptor;
33 import org.apache.hadoop.hbase.NotServingRegionException;
34 import org.apache.hadoop.hbase.ServerName;
35 import org.apache.hadoop.hbase.client.Get;
36 import org.apache.hadoop.hbase.client.HTable;
37 import org.apache.hadoop.hbase.client.Result;
38 import org.apache.hadoop.hbase.client.ResultScanner;
39 import org.apache.hadoop.hbase.client.Scan;
40 import org.apache.hadoop.hbase.ipc.HRegionInterface;
41 import org.apache.hadoop.hbase.util.Bytes;
42 import org.apache.hadoop.hbase.util.Pair;
43 import org.apache.hadoop.hbase.util.Writables;
44 import org.apache.hadoop.ipc.RemoteException;
45
46
47
48
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 private static boolean isRootTableRow(final byte [] row) {
70 if (row.length < META_REGION_PREFIX.length + 2
71
72 return false;
73 }
74
75
76 return Bytes.equals(row, 0, META_REGION_PREFIX.length,
77 META_REGION_PREFIX, 0, META_REGION_PREFIX.length);
78 }
79
80
81
82
83
84
85
86
87
88
89
90 public static Map<HRegionInfo, ServerName> fullScan(
91 CatalogTracker catalogTracker, final Set<String> disabledTables)
92 throws IOException {
93 return fullScan(catalogTracker, disabledTables, false);
94 }
95
96
97
98
99
100
101
102
103
104
105
106
107
108 public static Map<HRegionInfo, ServerName> fullScan(
109 CatalogTracker catalogTracker, final Set<String> disabledTables,
110 final boolean excludeOfflinedSplitParents)
111 throws IOException {
112 final Map<HRegionInfo, ServerName> regions =
113 new TreeMap<HRegionInfo, ServerName>();
114 Visitor v = new Visitor() {
115 @Override
116 public boolean visit(Result r) throws IOException {
117 if (r == null || r.isEmpty()) return true;
118 Pair<HRegionInfo, ServerName> region = parseCatalogResult(r);
119 if (region == null) return true;
120 HRegionInfo hri = region.getFirst();
121 if (disabledTables.contains(
122 hri.getTableNameAsString())) return true;
123
124 if (excludeOfflinedSplitParents && hri.isSplitParent()) return true;
125 regions.put(hri, region.getSecond());
126 return true;
127 }
128 };
129 fullScan(catalogTracker, v);
130 return regions;
131 }
132
133
134
135
136
137
138 public static List<Result> fullScan(CatalogTracker catalogTracker)
139 throws IOException {
140 CollectAllVisitor v = new CollectAllVisitor();
141 fullScan(catalogTracker, v, null);
142 return v.getResults();
143 }
144
145
146
147
148
149
150 public static List<Result> fullScanOfRoot(CatalogTracker catalogTracker)
151 throws IOException {
152 CollectAllVisitor v = new CollectAllVisitor();
153 fullScan(catalogTracker, v, null, true);
154 return v.getResults();
155 }
156
157
158
159
160
161
162
163 public static void fullScan(CatalogTracker catalogTracker,
164 final Visitor visitor)
165 throws IOException {
166 fullScan(catalogTracker, visitor, null);
167 }
168
169
170
171
172
173
174
175
176
177
178 public static void fullScan(CatalogTracker catalogTracker,
179 final Visitor visitor, final byte [] startrow)
180 throws IOException {
181 fullScan(catalogTracker, visitor, startrow, false);
182 }
183
184
185
186
187
188
189
190
191 private static HTable getHTable(final CatalogTracker catalogTracker,
192 final byte [] tableName)
193 throws IOException {
194
195
196 org.apache.hadoop.hbase.client.HConnection c = catalogTracker.getConnection();
197 if (c == null) throw new NullPointerException("No connection");
198 return new HTable(catalogTracker.getConnection().getConfiguration(), tableName);
199 }
200
201
202
203
204
205
206
207
208 static HTable getCatalogHTable(final CatalogTracker catalogTracker,
209 final byte [] row)
210 throws IOException {
211 return isRootTableRow(row)?
212 getRootHTable(catalogTracker):
213 getMetaHTable(catalogTracker);
214 }
215
216
217
218
219
220
221
222 static HTable getMetaHTable(final CatalogTracker ct)
223 throws IOException {
224 return getHTable(ct, HConstants.META_TABLE_NAME);
225 }
226
227
228
229
230
231
232
233 static HTable getRootHTable(final CatalogTracker ct)
234 throws IOException {
235 return getHTable(ct, HConstants.ROOT_TABLE_NAME);
236 }
237
238
239
240
241
242
243 private static Result get(final HTable t, final Get g) throws IOException {
244 try {
245 return t.get(g);
246 } finally {
247 t.close();
248 }
249 }
250
251
252
253
254
255
256
257
258 public static ServerName readMetaLocation(HRegionInterface metaServer)
259 throws IOException {
260 return readLocation(metaServer, CatalogTracker.ROOT_REGION_NAME,
261 CatalogTracker.META_REGION_NAME);
262 }
263
264
265
266
267
268
269
270
271
272 static ServerName getMetaRegionLocation(final CatalogTracker ct)
273 throws IOException {
274 return MetaReader.readRegionLocation(ct, CatalogTracker.META_REGION_NAME);
275 }
276
277
278
279
280
281
282
283
284 static ServerName readRegionLocation(CatalogTracker catalogTracker,
285 byte [] regionName)
286 throws IOException {
287 Pair<HRegionInfo, ServerName> pair = getRegion(catalogTracker, regionName);
288 return (pair == null || pair.getSecond() == null)? null: pair.getSecond();
289 }
290
291
292 private static ServerName readLocation(HRegionInterface metaServer,
293 byte [] catalogRegionName, byte [] regionName)
294 throws IOException {
295 Result r = null;
296 try {
297 r = metaServer.get(catalogRegionName,
298 new Get(regionName).
299 addColumn(HConstants.CATALOG_FAMILY,
300 HConstants.SERVER_QUALIFIER).
301 addColumn(HConstants.CATALOG_FAMILY,
302 HConstants.STARTCODE_QUALIFIER));
303 } catch (java.net.SocketTimeoutException e) {
304
305
306 } catch (java.net.SocketException e) {
307
308
309 } catch (RemoteException re) {
310 IOException ioe = re.unwrapRemoteException();
311 if (ioe instanceof NotServingRegionException) {
312
313
314 } else if (ioe.getMessage().contains("Server not running")) {
315
316 } else {
317 throw re;
318 }
319 } catch (IOException e) {
320 if (e.getCause() != null && e.getCause() instanceof IOException &&
321 e.getCause().getMessage() != null &&
322 e.getCause().getMessage().contains("Connection reset by peer")) {
323
324
325 } else {
326 throw e;
327 }
328 }
329 if (r == null || r.isEmpty()) {
330 return null;
331 }
332 return getServerNameFromCatalogResult(r);
333 }
334
335
336
337
338
339
340
341
342 public static Pair<HRegionInfo, ServerName> getRegion(
343 CatalogTracker catalogTracker, byte [] regionName)
344 throws IOException {
345 Get get = new Get(regionName);
346 get.addFamily(HConstants.CATALOG_FAMILY);
347 Result r = get(getCatalogHTable(catalogTracker, regionName), get);
348 return (r == null || r.isEmpty())? null: parseCatalogResult(r);
349 }
350
351
352
353
354
355
356
357 public static ServerName getServerNameFromCatalogResult(final Result r) {
358 byte[] value = r.getValue(HConstants.CATALOG_FAMILY,
359 HConstants.SERVER_QUALIFIER);
360 if (value == null || value.length == 0) return null;
361 String hostAndPort = Bytes.toString(value);
362 value = r.getValue(HConstants.CATALOG_FAMILY,
363 HConstants.STARTCODE_QUALIFIER);
364 if (value == null || value.length == 0) return null;
365 return new ServerName(hostAndPort, Bytes.toLong(value));
366 }
367
368
369
370
371
372
373
374
375
376 public static Pair<HRegionInfo, ServerName> parseCatalogResult(final Result r)
377 throws IOException {
378 HRegionInfo info =
379 parseHRegionInfoFromCatalogResult(r, HConstants.REGIONINFO_QUALIFIER);
380 ServerName sn = getServerNameFromCatalogResult(r);
381 return new Pair<HRegionInfo, ServerName>(info, sn);
382 }
383
384
385
386
387
388
389
390
391
392
393
394
395 public static HRegionInfo parseHRegionInfoFromCatalogResult(final Result r,
396 byte [] qualifier)
397 throws IOException {
398 byte [] bytes = r.getValue(HConstants.CATALOG_FAMILY, qualifier);
399 if (bytes == null || bytes.length <= 0) return null;
400 return Writables.getHRegionInfoOrNull(bytes);
401 }
402
403
404
405
406
407
408
409
410
411 public static boolean tableExists(CatalogTracker catalogTracker,
412 String tableName)
413 throws IOException {
414 if (tableName.equals(HTableDescriptor.ROOT_TABLEDESC.getNameAsString()) ||
415 tableName.equals(HTableDescriptor.META_TABLEDESC.getNameAsString())) {
416
417 return true;
418 }
419 final byte [] tableNameBytes = Bytes.toBytes(tableName);
420
421 CollectingVisitor<HRegionInfo> visitor = new CollectingVisitor<HRegionInfo>() {
422 private HRegionInfo current = null;
423
424 @Override
425 public boolean visit(Result r) throws IOException {
426 this.current =
427 parseHRegionInfoFromCatalogResult(r, HConstants.REGIONINFO_QUALIFIER);
428 if (this.current == null) {
429 LOG.warn("No serialized HRegionInfo in " + r);
430 return true;
431 }
432 if (!isInsideTable(this.current, tableNameBytes)) return false;
433 if (this.current.isSplitParent()) return true;
434
435 super.visit(r);
436
437 return false;
438 }
439
440 @Override
441 void add(Result r) {
442
443 this.results.add(this.current);
444 }
445 };
446 fullScan(catalogTracker, visitor, getTableStartRowForMeta(tableNameBytes));
447
448 return visitor.getResults().size() >= 1;
449 }
450
451
452
453
454
455
456
457
458 public static List<HRegionInfo> getTableRegions(CatalogTracker catalogTracker,
459 byte [] tableName)
460 throws IOException {
461 return getTableRegions(catalogTracker, tableName, false);
462 }
463
464
465
466
467
468
469
470
471
472
473 public static List<HRegionInfo> getTableRegions(CatalogTracker catalogTracker,
474 byte [] tableName, final boolean excludeOfflinedSplitParents)
475 throws IOException {
476 List<Pair<HRegionInfo, ServerName>> result = null;
477 try {
478 result = getTableRegionsAndLocations(catalogTracker, tableName,
479 excludeOfflinedSplitParents);
480 } catch (InterruptedException e) {
481 throw new RuntimeException(e);
482 }
483 return getListOfHRegionInfos(result);
484 }
485
486 static List<HRegionInfo> getListOfHRegionInfos(final List<Pair<HRegionInfo, ServerName>> pairs) {
487 if (pairs == null || pairs.isEmpty()) return null;
488 List<HRegionInfo> result = new ArrayList<HRegionInfo>(pairs.size());
489 for (Pair<HRegionInfo, ServerName> pair: pairs) {
490 result.add(pair.getFirst());
491 }
492 return result;
493 }
494
495
496
497
498
499
500
501 static boolean isInsideTable(final HRegionInfo current, final byte [] tableName) {
502 return Bytes.equals(tableName, current.getTableName());
503 }
504
505
506
507
508
509
510 static byte [] getTableStartRowForMeta(final byte [] tableName) {
511 byte [] startRow = new byte[tableName.length + 2];
512 System.arraycopy(tableName, 0, startRow, 0, tableName.length);
513 startRow[startRow.length - 2] = HRegionInfo.DELIMITER;
514 startRow[startRow.length - 1] = HRegionInfo.DELIMITER;
515 return startRow;
516 }
517
518
519
520
521
522
523
524
525
526
527 public static Scan getScanForTableName(byte[] tableName) {
528 String strName = Bytes.toString(tableName);
529
530 byte[] startKey = Bytes.toBytes(strName + ",,");
531
532 byte[] stopKey = Bytes.toBytes(strName + " ,,");
533
534 Scan scan = new Scan(startKey);
535 scan.setStopRow(stopKey);
536 return scan;
537 }
538
539
540
541
542
543
544
545
546 public static List<Pair<HRegionInfo, ServerName>>
547 getTableRegionsAndLocations(CatalogTracker catalogTracker, String tableName)
548 throws IOException, InterruptedException {
549 return getTableRegionsAndLocations(catalogTracker, Bytes.toBytes(tableName),
550 true);
551 }
552
553
554
555
556
557
558
559
560 public static List<Pair<HRegionInfo, ServerName>>
561 getTableRegionsAndLocations(final CatalogTracker catalogTracker,
562 final byte [] tableName, final boolean excludeOfflinedSplitParents)
563 throws IOException, InterruptedException {
564 if (Bytes.equals(tableName, HConstants.ROOT_TABLE_NAME)) {
565
566 ServerName serverName = catalogTracker.getRootLocation();
567 List<Pair<HRegionInfo, ServerName>> list =
568 new ArrayList<Pair<HRegionInfo, ServerName>>();
569 list.add(new Pair<HRegionInfo, ServerName>(HRegionInfo.ROOT_REGIONINFO,
570 serverName));
571 return list;
572 }
573
574 CollectingVisitor<Pair<HRegionInfo, ServerName>> visitor =
575 new CollectingVisitor<Pair<HRegionInfo, ServerName>>() {
576 private Pair<HRegionInfo, ServerName> current = null;
577
578 @Override
579 public boolean visit(Result r) throws IOException {
580 HRegionInfo hri =
581 parseHRegionInfoFromCatalogResult(r, HConstants.REGIONINFO_QUALIFIER);
582 if (hri == null) {
583 LOG.warn("No serialized HRegionInfo in " + r);
584 return true;
585 }
586 if (!isInsideTable(hri, tableName)) return false;
587 if (excludeOfflinedSplitParents && hri.isSplitParent()) return true;
588 ServerName sn = getServerNameFromCatalogResult(r);
589
590 this.current = new Pair<HRegionInfo, ServerName>(hri, sn);
591
592 return super.visit(r);
593 }
594
595 @Override
596 void add(Result r) {
597 this.results.add(this.current);
598 }
599 };
600 fullScan(catalogTracker, visitor, getTableStartRowForMeta(tableName),
601 Bytes.equals(tableName, HConstants.META_TABLE_NAME));
602 return visitor.getResults();
603 }
604
605
606
607
608
609
610
611
612 public static NavigableMap<HRegionInfo, Result>
613 getServerUserRegions(CatalogTracker catalogTracker, final ServerName serverName)
614 throws IOException {
615 final NavigableMap<HRegionInfo, Result> hris = new TreeMap<HRegionInfo, Result>();
616
617
618 CollectingVisitor<Result> v = new CollectingVisitor<Result>() {
619 @Override
620 void add(Result r) {
621 if (r == null || r.isEmpty()) return;
622 ServerName sn = getServerNameFromCatalogResult(r);
623 if (sn != null && sn.equals(serverName)) this.results.add(r);
624 }
625 };
626 fullScan(catalogTracker, v);
627 List<Result> results = v.getResults();
628 if (results != null && !results.isEmpty()) {
629
630 for (Result r: results) {
631 Pair<HRegionInfo, ServerName> p = parseCatalogResult(r);
632 if (p != null && p.getFirst() != null) hris.put(p.getFirst(), r);
633 }
634 }
635 return hris;
636 }
637
638 public static void fullScanMetaAndPrint(final CatalogTracker catalogTracker)
639 throws IOException {
640 Visitor v = new Visitor() {
641 @Override
642 public boolean visit(Result r) throws IOException {
643 if (r == null || r.isEmpty()) return true;
644 LOG.info("fullScanMetaAndPrint.Current Meta Row: " + r);
645 HRegionInfo hrim = MetaEditor.getHRegionInfo(r);
646 LOG.info("fullScanMetaAndPrint.HRI Print= " + hrim);
647 return true;
648 }
649 };
650 fullScan(catalogTracker, v);
651 }
652
653
654
655
656
657
658
659
660
661
662
663 public static void fullScan(HRegionInterface hRegionInterface,
664 Visitor visitor, final byte[] regionName,
665 byte[] startrow) throws IOException {
666 if (hRegionInterface == null) return;
667 Scan scan = new Scan();
668 if (startrow != null) scan.setStartRow(startrow);
669 scan.addFamily(HConstants.CATALOG_FAMILY);
670 long scannerid = hRegionInterface.openScanner(regionName, scan);
671 try {
672 Result data;
673 while((data = hRegionInterface.next(scannerid)) != null) {
674 if (!data.isEmpty()) visitor.visit(data);
675 }
676 } finally {
677 hRegionInterface.close(scannerid);
678 }
679 return;
680 }
681
682
683
684
685
686
687
688
689
690
691
692 static void fullScan(CatalogTracker catalogTracker,
693 final Visitor visitor, final byte [] startrow, final boolean scanRoot)
694 throws IOException {
695 Scan scan = new Scan();
696 if (startrow != null) scan.setStartRow(startrow);
697 scan.addFamily(HConstants.CATALOG_FAMILY);
698 HTable metaTable = scanRoot?
699 getRootHTable(catalogTracker): getMetaHTable(catalogTracker);
700 ResultScanner scanner = metaTable.getScanner(scan);
701 try {
702 Result data;
703 while((data = scanner.next()) != null) {
704 if (data.isEmpty()) continue;
705
706 if (!visitor.visit(data)) break;
707 }
708 } finally {
709 scanner.close();
710 metaTable.close();
711 }
712 return;
713 }
714
715
716
717
718 public interface Visitor {
719
720
721
722
723
724
725 public boolean visit(final Result r) throws IOException;
726 }
727
728
729
730
731 static abstract class CollectingVisitor<T> implements Visitor {
732 final List<T> results = new ArrayList<T>();
733 @Override
734 public boolean visit(Result r) throws IOException {
735 if (r == null || r.isEmpty()) return true;
736 add(r);
737 return true;
738 }
739
740 abstract void add(Result r);
741
742
743
744
745
746 List<T> getResults() {
747 return this.results;
748 }
749 }
750
751
752
753
754 static class CollectAllVisitor extends CollectingVisitor<Result> {
755 @Override
756 void add(Result r) {
757 this.results.add(r);
758 }
759 }
760 }