/** * Initialize namespace state cache by scanning meta table. */ private void initialize() throws IOException { List<NamespaceDescriptor> namespaces = this.master.listNamespaceDescriptors(); for (NamespaceDescriptor namespace : namespaces) { addNamespace(namespace.getName()); List<TableName> tables = this.master.listTableNamesByNamespace(namespace.getName()); for (TableName table : tables) { if (table.isSystemTable()) { continue; } int regionCount = 0; Map<HRegionInfo, ServerName> regions = MetaScanner.allTableRegions(this.master.getConnection(), table); for (HRegionInfo info : regions.keySet()) { if (!info.isSplit()) { regionCount++; } } addTable(table, regionCount); } } LOG.info("Finished updating state of " + nsStateCache.size() + " namespaces. "); initialized = true; }
/** * Return the region and current deployment for the region containing * the given row. If the region cannot be found, returns null. If it * is found, but not currently deployed, the second element of the pair * may be null. */ @VisibleForTesting // Used by TestMaster. Pair<HRegionInfo, ServerName> getTableRegionForRow( final TableName tableName, final byte [] rowKey) throws IOException { final AtomicReference<Pair<HRegionInfo, ServerName>> result = new AtomicReference<Pair<HRegionInfo, ServerName>>(null); MetaScannerVisitor visitor = new MetaScannerVisitorBase() { @Override public boolean processRow(Result data) throws IOException { if (data == null || data.size() <= 0) { return true; } Pair<HRegionInfo, ServerName> pair = HRegionInfo.getHRegionInfoAndServerName(data); if (pair == null) { return false; } if (!pair.getFirst().getTable().equals(tableName)) { return false; } result.set(pair); return true; } }; MetaScanner.metaScan(clusterConnection, visitor, tableName, rowKey, 1); return result.get(); }
private static int countMetaRegions(final HMaster master, final TableName tableName) throws IOException { final AtomicInteger actualRegCount = new AtomicInteger(0); final MetaScannerVisitor visitor = new MetaScannerVisitorBase() { @Override public boolean processRow(Result rowResult) throws IOException { RegionLocations list = MetaTableAccessor.getRegionLocations(rowResult); if (list == null) { LOG.warn("No serialized HRegionInfo in " + rowResult); return true; } HRegionLocation l = list.getRegionLocation(); if (l == null) { return true; } if (!l.getRegionInfo().getTable().equals(tableName)) { return false; } if (l.getRegionInfo().isOffline() || l.getRegionInfo().isSplit()) return true; HRegionLocation[] locations = list.getRegionLocations(); for (HRegionLocation location : locations) { if (location == null) continue; ServerName serverName = location.getServerName(); // Make sure that regions are assigned to server if (serverName != null && serverName.getHostAndPort() != null) { actualRegCount.incrementAndGet(); } } return true; } }; MetaScanner.metaScan(master.getConnection(), visitor, tableName); return actualRegCount.get(); }
/** verify region boundaries obtained from MetaScanner */ void verifyRegionsUsingMetaScanner() throws Exception { //MetaScanner.allTableRegions() NavigableMap<HRegionInfo, ServerName> regions = MetaScanner.allTableRegions(connection, tableName); verifyTableRegions(regions.keySet()); //MetaScanner.listAllRegions() List<HRegionInfo> regionList = MetaScanner.listAllRegions(conf, connection, false); verifyTableRegions(Sets.newTreeSet(regionList)); }
/** * Scans META and returns a number of scanned rows, and * an ordered map of split parents. */ Pair<Integer, Map<HRegionInfo, Result>> getSplitParents() throws IOException { // TODO: Only works with single .META. region currently. Fix. final AtomicInteger count = new AtomicInteger(0); // Keep Map of found split parents. There are candidates for cleanup. // Use a comparator that has split parents come before its daughters. final Map<HRegionInfo, Result> splitParents = new TreeMap<HRegionInfo, Result>(new SplitParentFirstComparator()); // This visitor collects split parents and counts rows in the .META. table MetaScannerVisitor visitor = new MetaScanner.BlockingMetaScannerVisitor(server.getConfiguration()) { @Override public boolean processRowInternal(Result r) throws IOException { if (r == null || r.isEmpty()) return true; count.incrementAndGet(); HRegionInfo info = getHRegionInfo(r); if (info == null) return true; // Keep scanning if (info.isSplitParent()) splitParents.put(info, r); // Returning true means "keep scanning" return true; } }; // Run full scan of .META. catalog table passing in our custom visitor MetaScanner.metaScan(server.getConfiguration(), visitor); return new Pair<Integer, Map<HRegionInfo, Result>>(count.get(), splitParents); }
/** * Return the region and current deployment for the region containing * the given row. If the region cannot be found, returns null. If it * is found, but not currently deployed, the second element of the pair * may be null. */ Pair<HRegionInfo, ServerName> getTableRegionForRow( final byte [] tableName, final byte [] rowKey) throws IOException { final AtomicReference<Pair<HRegionInfo, ServerName>> result = new AtomicReference<Pair<HRegionInfo, ServerName>>(null); MetaScannerVisitor visitor = new MetaScannerVisitorBase() { @Override public boolean processRow(Result data) throws IOException { if (data == null || data.size() <= 0) { return true; } Pair<HRegionInfo, ServerName> pair = MetaReader.parseCatalogResult(data); if (pair == null) { return false; } if (!Bytes.equals(pair.getFirst().getTableName(), tableName)) { return false; } result.set(pair); return true; } }; MetaScanner.metaScan(conf, visitor, tableName, rowKey, 1); return result.get(); }
/** verify region boundaries obtained from MetaScanner */ void verifyRegionsUsingMetaScanner() throws Exception { //MetaScanner.allTableRegions() NavigableMap<HRegionInfo, ServerName> regions = MetaScanner.allTableRegions(conf, null, tableName, false); verifyTableRegions(regions.keySet()); //MetaScanner.listAllRegions() List<HRegionInfo> regionList = MetaScanner.listAllRegions(conf, false); verifyTableRegions(Sets.newTreeSet(regionList)); }
/** * Return the region and current deployment for the region containing * the given row. If the region cannot be found, returns null. If it * is found, but not currently deployed, the second element of the pair * may be null. */ @VisibleForTesting // Used by TestMaster. Pair<HRegionInfo, ServerName> getTableRegionForRow( final TableName tableName, final byte[] rowKey) throws IOException { final AtomicReference<Pair<HRegionInfo, ServerName>> result = new AtomicReference<Pair<HRegionInfo, ServerName>>(null); MetaScannerVisitor visitor = new MetaScannerVisitorBase() { @Override public boolean processRow(Result data) throws IOException { if (data == null || data.size() <= 0) { return true; } Pair<HRegionInfo, ServerName> pair = HRegionInfo.getHRegionInfoAndServerName(data); if (pair == null) { return false; } if (!pair.getFirst().getTable().equals(tableName)) { return false; } result.set(pair); return true; } }; MetaScanner.metaScan(clusterConnection, visitor, tableName, rowKey, 1); return result.get(); }
/** * Return the region and current deployment for the region containing * the given row. If the region cannot be found, returns null. If it * is found, but not currently deployed, the second element of the pair * may be null. */ Pair<HRegionInfo, ServerName> getTableRegionForRow( final TableName tableName, final byte [] rowKey) throws IOException { final AtomicReference<Pair<HRegionInfo, ServerName>> result = new AtomicReference<Pair<HRegionInfo, ServerName>>(null); MetaScannerVisitor visitor = new MetaScannerVisitorBase() { @Override public boolean processRow(Result data) throws IOException { if (data == null || data.size() <= 0) { return true; } Pair<HRegionInfo, ServerName> pair = HRegionInfo.getHRegionInfoAndServerName(data); if (pair == null) { return false; } if (!pair.getFirst().getTable().equals(tableName)) { return false; } result.set(pair); return true; } }; MetaScanner.metaScan(conf, visitor, tableName, rowKey, 1); return result.get(); }
/** * Return the region and current deployment for the region containing * the given row. If the region cannot be found, returns null. If it * is found, but not currently deployed, the second element of the pair * may be null. */ Pair<HRegionInfo, ServerName> getTableRegionForRow( final byte [] tableName, final byte [] rowKey) throws IOException { final AtomicReference<Pair<HRegionInfo, ServerName>> result = new AtomicReference<Pair<HRegionInfo, ServerName>>(null); MetaScannerVisitor visitor = new MetaScannerVisitor() { @Override public boolean processRow(Result data) throws IOException { if (data == null || data.size() <= 0) { return true; } Pair<HRegionInfo, ServerName> pair = MetaReader.parseCatalogResult(data); if (pair == null) { return false; } if (!Bytes.equals(pair.getFirst().getTableName(), tableName)) { return false; } result.set(pair); return true; } }; MetaScanner.metaScan(conf, visitor, tableName, rowKey, 1); return result.get(); }
protected List<HRegionInfo> scanMetaWithGivenUtil(Configuration conf, String tableName) throws IOException { HTable meta = new HTable(conf, HConstants.META_TABLE_NAME); try { Scan scan = new Scan(); scan.addFamily(HConstants.CATALOG_FAMILY); ResultScanner s = meta.getScanner(scan); List<HRegionInfo> regionInfos = new ArrayList<HRegionInfo>(); try { Result r; while ((r = s.next()) != null) { Assert.assertTrue(r != null); byte[] b = r.getValue(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER); HRegionInfo info = MetaScanner.getHRegionInfo(r); System.out.println(info.getTable().getNameAsString()); if (info.getTable().getNameAsString().startsWith(tableName)) { regionInfos.add(info); } } return regionInfos; } finally { s.close(); } } finally { meta.close(); } }
/** verify region boundaries obtained from MetaScanner */ void verifyRegionsUsingMetaScanner() throws Exception { //MetaScanner.allTableRegions() NavigableMap<HRegionInfo, ServerName> regions = MetaScanner.allTableRegions(conf, tableName, false); verifyTableRegions(regions.keySet()); //MetaScanner.listAllRegions() List<HRegionInfo> regionList = MetaScanner.listAllRegions(conf, false); verifyTableRegions(Sets.newTreeSet(regionList)); }
/** * Return the region and current deployment for the region containing * the given row. If the region cannot be found, returns null. If it * is found, but not currently deployed, the second element of the pair * may be null. */ Pair<HRegionInfo, ServerName> getTableRegionForRow( final byte [] tableName, final byte [] rowKey) throws IOException { final AtomicReference<Pair<HRegionInfo, ServerName>> result = new AtomicReference<Pair<HRegionInfo, ServerName>>(null); MetaScannerVisitor visitor = new MetaScannerVisitorBase() { @Override public boolean processRow(Result data) throws IOException { if (data == null || data.size() <= 0) { return true; } Pair<HRegionInfo, ServerName> pair = HRegionInfo.getHRegionInfoAndServerName(data); if (pair == null) { return false; } if (!Bytes.equals(pair.getFirst().getTableName(), tableName)) { return false; } result.set(pair); return true; } }; MetaScanner.metaScan(conf, visitor, tableName, rowKey, 1); return result.get(); }
/** * Scans hbase:meta and returns a number of scanned rows, and a map of merged * regions, and an ordered map of split parents. if the given table name is * null, return merged regions and split parents of all tables, else only the * specified table * @param tableName null represents all tables * @return triple of scanned rows, and map of merged regions, and map of split * parent regioninfos * @throws IOException */ Triple<Integer, Map<HRegionInfo, Result>, Map<HRegionInfo, Result>> getMergedRegionsAndSplitParents( final TableName tableName) throws IOException { final boolean isTableSpecified = (tableName != null); // TODO: Only works with single hbase:meta region currently. Fix. final AtomicInteger count = new AtomicInteger(0); // Keep Map of found split parents. There are candidates for cleanup. // Use a comparator that has split parents come before its daughters. final Map<HRegionInfo, Result> splitParents = new TreeMap<HRegionInfo, Result>(new SplitParentFirstComparator()); final Map<HRegionInfo, Result> mergedRegions = new TreeMap<HRegionInfo, Result>(); // This visitor collects split parents and counts rows in the hbase:meta table MetaScannerVisitor visitor = new MetaScanner.MetaScannerVisitorBase() { @Override public boolean processRow(Result r) throws IOException { if (r == null || r.isEmpty()) return true; count.incrementAndGet(); HRegionInfo info = HRegionInfo.getHRegionInfo(r); if (info == null) return true; // Keep scanning if (isTableSpecified && info.getTable().compareTo(tableName) > 0) { // Another table, stop scanning return false; } if (info.isSplitParent()) splitParents.put(info, r); if (r.getValue(HConstants.CATALOG_FAMILY, HConstants.MERGEA_QUALIFIER) != null) { mergedRegions.put(info, r); } // Returning true means "keep scanning" return true; } }; // Run full scan of hbase:meta catalog table passing in our custom visitor with // the start row MetaScanner.metaScan(this.connection, visitor, tableName); return new Triple<Integer, Map<HRegionInfo, Result>, Map<HRegionInfo, Result>>( count.get(), mergedRegions, splitParents); }
public void checkRegionBoundaries() { try { ByteArrayComparator comparator = new ByteArrayComparator(); List<HRegionInfo> regions = MetaScanner.listAllRegions(getConf(), connection, false); final RegionBoundariesInformation currentRegionBoundariesInformation = new RegionBoundariesInformation(); Path hbaseRoot = FSUtils.getRootDir(getConf()); for (HRegionInfo regionInfo : regions) { Path tableDir = FSUtils.getTableDir(hbaseRoot, regionInfo.getTable()); currentRegionBoundariesInformation.regionName = regionInfo.getRegionName(); // For each region, get the start and stop key from the META and compare them to the // same information from the Stores. Path path = new Path(tableDir, regionInfo.getEncodedName()); FileSystem fs = path.getFileSystem(getConf()); FileStatus[] files = fs.listStatus(path); // For all the column families in this region... byte[] storeFirstKey = null; byte[] storeLastKey = null; for (FileStatus file : files) { String fileName = file.getPath().toString(); fileName = fileName.substring(fileName.lastIndexOf("/") + 1); if (!fileName.startsWith(".") && !fileName.endsWith("recovered.edits")) { FileStatus[] storeFiles = fs.listStatus(file.getPath()); // For all the stores in this column family. for (FileStatus storeFile : storeFiles) { HFile.Reader reader = HFile.createReader(fs, storeFile.getPath(), new CacheConfig( getConf()), getConf()); if ((reader.getFirstKey() != null) && ((storeFirstKey == null) || (comparator.compare(storeFirstKey, reader.getFirstKey()) > 0))) { storeFirstKey = reader.getFirstKey(); } if ((reader.getLastKey() != null) && ((storeLastKey == null) || (comparator.compare(storeLastKey, reader.getLastKey())) < 0)) { storeLastKey = reader.getLastKey(); } reader.close(); } } } currentRegionBoundariesInformation.metaFirstKey = regionInfo.getStartKey(); currentRegionBoundariesInformation.metaLastKey = regionInfo.getEndKey(); currentRegionBoundariesInformation.storesFirstKey = keyOnly(storeFirstKey); currentRegionBoundariesInformation.storesLastKey = keyOnly(storeLastKey); if (currentRegionBoundariesInformation.metaFirstKey.length == 0) currentRegionBoundariesInformation.metaFirstKey = null; if (currentRegionBoundariesInformation.metaLastKey.length == 0) currentRegionBoundariesInformation.metaLastKey = null; // For a region to be correct, we need the META start key to be smaller or equal to the // smallest start key from all the stores, and the start key from the next META entry to // be bigger than the last key from all the current stores. First region start key is null; // Last region end key is null; some regions can be empty and not have any store. boolean valid = true; // Checking start key. if ((currentRegionBoundariesInformation.storesFirstKey != null) && (currentRegionBoundariesInformation.metaFirstKey != null)) { valid = valid && comparator.compare(currentRegionBoundariesInformation.storesFirstKey, currentRegionBoundariesInformation.metaFirstKey) >= 0; } // Checking stop key. if ((currentRegionBoundariesInformation.storesLastKey != null) && (currentRegionBoundariesInformation.metaLastKey != null)) { valid = valid && comparator.compare(currentRegionBoundariesInformation.storesLastKey, currentRegionBoundariesInformation.metaLastKey) < 0; } if (!valid) { errors.reportError(ERROR_CODE.BOUNDARIES_ERROR, "Found issues with regions boundaries", tablesInfo.get(regionInfo.getTable())); LOG.warn("Region's boundaries not alligned between stores and META for:"); LOG.warn(currentRegionBoundariesInformation); } } } catch (IOException e) { LOG.error(e); } }
/** * Test mission REGIONINFO_QUALIFIER in hbase:meta */ @Test (timeout=180000) public void testMissingRegionInfoQualifier() throws Exception { Connection connection = ConnectionFactory.createConnection(conf); TableName table = TableName.valueOf("testMissingRegionInfoQualifier"); try { setupTable(table); // Mess it up by removing the RegionInfo for one region. final List<Delete> deletes = new LinkedList<Delete>(); Table meta = connection.getTable(TableName.META_TABLE_NAME, hbfsckExecutorService); MetaScanner.metaScan(connection, new MetaScanner.MetaScannerVisitor() { @Override public boolean processRow(Result rowResult) throws IOException { HRegionInfo hri = MetaTableAccessor.getHRegionInfo(rowResult); if (hri != null && !hri.getTable().isSystemTable()) { Delete delete = new Delete(rowResult.getRow()); delete.addColumn(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER); deletes.add(delete); } return true; } @Override public void close() throws IOException { } }); meta.delete(deletes); // Mess it up by creating a fake hbase:meta entry with no associated RegionInfo meta.put(new Put(Bytes.toBytes(table + ",,1361911384013.810e28f59a57da91c66")).add( HConstants.CATALOG_FAMILY, HConstants.SERVER_QUALIFIER, Bytes.toBytes("node1:60020"))); meta.put(new Put(Bytes.toBytes(table + ",,1361911384013.810e28f59a57da91c66")).add( HConstants.CATALOG_FAMILY, HConstants.STARTCODE_QUALIFIER, Bytes.toBytes(1362150791183L))); meta.close(); HBaseFsck hbck = doFsck(conf, false); assertTrue(hbck.getErrors().getErrorList().contains(ERROR_CODE.EMPTY_META_CELL)); // fix reference file hbck = doFsck(conf, true); // check that reference file fixed assertFalse(hbck.getErrors().getErrorList().contains(ERROR_CODE.EMPTY_META_CELL)); } finally { cleanupTable(table); } connection.close(); }
public void checkRegionBoundaries() { try { ByteArrayComparator comparator = new ByteArrayComparator(); List<HRegionInfo> regions = MetaScanner.listAllRegions(getConf(), false); final RegionBoundariesInformation currentRegionBoundariesInformation = new RegionBoundariesInformation(); for (HRegionInfo regionInfo : regions) { currentRegionBoundariesInformation.regionName = regionInfo.getRegionName(); // For each region, get the start and stop key from the META and compare them to the // same information from the Stores. Path path = new Path(getConf().get(HConstants.HBASE_DIR) + "/" + Bytes.toString(regionInfo.getTableName()) + "/" + regionInfo.getEncodedName() + "/"); FileSystem fs = path.getFileSystem(getConf()); FileStatus[] files = fs.listStatus(path); // For all the column families in this region... byte[] storeFirstKey = null; byte[] storeLastKey = null; for (FileStatus file : files) { String fileName = file.getPath().toString(); fileName = fileName.substring(fileName.lastIndexOf("/") + 1); if (!fileName.startsWith(".") && !fileName.endsWith("recovered.edits")) { FileStatus[] storeFiles = fs.listStatus(file.getPath()); // For all the stores in this column family. for (FileStatus storeFile : storeFiles) { HFile.Reader reader = HFile.createReader(fs, storeFile.getPath(), new CacheConfig( getConf())); if ((reader.getFirstKey() != null) && ((storeFirstKey == null) || (comparator.compare(storeFirstKey, reader.getFirstKey()) > 0))) { storeFirstKey = reader.getFirstKey(); } if ((reader.getLastKey() != null) && ((storeLastKey == null) || (comparator.compare(storeLastKey, reader.getLastKey())) < 0)) { storeLastKey = reader.getLastKey(); } reader.close(); } } } currentRegionBoundariesInformation.metaFirstKey = regionInfo.getStartKey(); currentRegionBoundariesInformation.metaLastKey = regionInfo.getEndKey(); currentRegionBoundariesInformation.storesFirstKey = keyOnly(storeFirstKey); currentRegionBoundariesInformation.storesLastKey = keyOnly(storeLastKey); if (currentRegionBoundariesInformation.metaFirstKey.length == 0) currentRegionBoundariesInformation.metaFirstKey = null; if (currentRegionBoundariesInformation.metaLastKey.length == 0) currentRegionBoundariesInformation.metaLastKey = null; // For a region to be correct, we need the META start key to be smaller or equal to the // smallest start key from all the stores, and the start key from the next META entry to // be bigger than the last key from all the current stores. First region start key is null; // Last region end key is null; some regions can be empty and not have any store. boolean valid = true; // Checking start key. if ((currentRegionBoundariesInformation.storesFirstKey != null) && (currentRegionBoundariesInformation.metaFirstKey != null)) { valid = valid && comparator.compare(currentRegionBoundariesInformation.storesFirstKey, currentRegionBoundariesInformation.metaFirstKey) >= 0; } // Checking stop key. if ((currentRegionBoundariesInformation.storesLastKey != null) && (currentRegionBoundariesInformation.metaLastKey != null)) { valid = valid && comparator.compare(currentRegionBoundariesInformation.storesLastKey, currentRegionBoundariesInformation.metaLastKey) < 0; } if (!valid) { errors.reportError(ERROR_CODE.BOUNDARIES_ERROR, "Found issues with regions boundaries", tablesInfo.get(Bytes.toString(regionInfo.getTableName()))); LOG.warn("Region's boundaries not alligned between stores and META for:"); LOG.warn(currentRegionBoundariesInformation); } } } catch (IOException e) { LOG.error(e); } }
/** * Scan .META. and -ROOT-, adding all regions found to the regionInfo map. * @throws IOException if an error is encountered */ boolean loadMetaEntries() throws IOException { // get a list of all regions from the master. This involves // scanning the META table if (!recordRootRegion()) { // Will remove later if we can fix it errors.reportError("Fatal error: unable to get root region location. Exiting..."); return false; } MetaScannerVisitor visitor = new MetaScannerVisitorBase() { int countRecord = 1; // comparator to sort KeyValues with latest modtime final Comparator<KeyValue> comp = new Comparator<KeyValue>() { public int compare(KeyValue k1, KeyValue k2) { return (int)(k1.getTimestamp() - k2.getTimestamp()); } }; public boolean processRow(Result result) throws IOException { try { // record the latest modification of this META record long ts = Collections.max(result.list(), comp).getTimestamp(); Pair<HRegionInfo, ServerName> pair = MetaReader.parseCatalogResult(result); if (pair == null || pair.getFirst() == null) { emptyRegionInfoQualifiers.add(result); return true; } ServerName sn = null; if (pair.getSecond() != null) { sn = pair.getSecond(); } HRegionInfo hri = pair.getFirst(); if (!(isTableIncluded(hri.getTableNameAsString()) || hri.isMetaRegion() || hri.isRootRegion())) { return true; } PairOfSameType<HRegionInfo> daughters = MetaReader.getDaughterRegions(result); MetaEntry m = new MetaEntry(hri, sn, ts, daughters.getFirst(), daughters.getSecond()); HbckInfo hbInfo = new HbckInfo(m); HbckInfo previous = regionInfoMap.put(hri.getEncodedName(), hbInfo); if (previous != null) { throw new IOException("Two entries in META are same " + previous); } // show proof of progress to the user, once for every 100 records. if (countRecord % 100 == 0) { errors.progress(); } countRecord++; return true; } catch (RuntimeException e) { LOG.error("Result=" + result); throw e; } } }; // Scan -ROOT- to pick up META regions MetaScanner.metaScan(getConf(), null, visitor, null, null, Integer.MAX_VALUE, HConstants.ROOT_TABLE_NAME); if (!checkMetaOnly) { // Scan .META. to pick up user regions MetaScanner.metaScan(getConf(), visitor); } errors.print(""); return true; }