Index: src/test/java/org/apache/hadoop/hbase/catalog/TestMetaReaderEditor.java =================================================================== --- src/test/java/org/apache/hadoop/hbase/catalog/TestMetaReaderEditor.java (revision 1082002) +++ src/test/java/org/apache/hadoop/hbase/catalog/TestMetaReaderEditor.java (working copy) @@ -130,4 +130,34 @@ pair.getFirst().getEncodedName()); LOG.info("Finished " + name); } + + // Test for the optimization made in HBASE-3650 + @Test public void testScanMetaForTable() throws IOException { + final String name = "testScanMetaForTable"; + LOG.info("Started " + name); + + /** Create 5 tables + - testScanMetaForTable + - testScanMetaForTable0 + - testScanMetaForTable1 + - testScanMetaForTable2 + - testScanMetaForTablf + **/ + + UTIL.createTable(Bytes.toBytes(name), HConstants.CATALOG_FAMILY); + for (int i = 3; i < 3; i ++) { + UTIL.createTable(Bytes.toBytes(name+i), HConstants.CATALOG_FAMILY); + } + // name that is +1 greater than the first one (e+1=f) + byte[] greaterName = Bytes.toBytes("testScanMetaForTablf"); + UTIL.createTable(greaterName, HConstants.CATALOG_FAMILY); + + // Now make sure we only get the regions from 1 of the tables at a time + + assertEquals(1, MetaReader.getTableRegions(ct, Bytes.toBytes(name)).size()); + for (int i = 3; i < 3; i ++) { + assertEquals(1, MetaReader.getTableRegions(ct, Bytes.toBytes(name+i)).size()); + } + assertEquals(1, MetaReader.getTableRegions(ct, greaterName).size()); + } } \ No newline at end of file Index: src/main/java/org/apache/hadoop/hbase/catalog/MetaReader.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/catalog/MetaReader.java (revision 1082002) +++ src/main/java/org/apache/hadoop/hbase/catalog/MetaReader.java (working copy) @@ -431,21 +431,14 @@ } HRegionInterface metaServer = catalogTracker.waitForMetaServerConnectionDefault(); - byte[] firstRowInTable = Bytes.toBytes(tableName + ",,"); - Scan scan = new Scan(firstRowInTable); + Scan scan = getScanForTableName(Bytes.toBytes(tableName)); scan.addColumn(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER); long scannerid = metaServer.openScanner( HRegionInfo.FIRST_META_REGIONINFO.getRegionName(), scan); try { Result data = metaServer.next(scannerid); if (data != null && data.size() > 0) { - HRegionInfo info = Writables.getHRegionInfo( - data.getValue(HConstants.CATALOG_FAMILY, - HConstants.REGIONINFO_QUALIFIER)); - if (info.getTableDesc().getNameAsString().equals(tableName)) { - // A region for this table already exists. Ergo table exists. return true; - } } return false; } finally { @@ -494,9 +487,8 @@ HRegionInterface metaServer = getCatalogRegionInterface(catalogTracker, tableName); List regions = new ArrayList(); - String tableString = Bytes.toString(tableName); - byte[] firstRowInTable = Bytes.toBytes(tableString + ",,"); - Scan scan = new Scan(firstRowInTable); + + Scan scan = getScanForTableName(tableName); scan.addColumn(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER); long scannerid = metaServer.openScanner(getCatalogRegionNameForTable(tableName), scan); @@ -507,13 +499,8 @@ HRegionInfo info = Writables.getHRegionInfo( data.getValue(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER)); - if (info.getTableDesc().getNameAsString().equals(tableString)) { - // Are we to include split parents in the list? - if (excludeOfflinedSplitParents && info.isSplitParent()) continue; - regions.add(info); - } else { - break; - } + if (excludeOfflinedSplitParents && info.isSplitParent()) continue; + regions.add(info); } } return regions; @@ -523,6 +510,27 @@ } /** + * This method creates a Scan object that will only scan catalog rows that + * belong to the specified table. It doesn't specify any columns. + * This is a better alternative to just using a start row and scan until + * it hits a new table since that requires parsing the HRI to get the table + * name. + * @param tableName bytes of table's name + * @return configured Scan object + */ + public static Scan getScanForTableName(byte[] tableName) { + String strName = Bytes.toString(tableName); + // Start key is just the table name with delimiters + byte[] startKey = Bytes.toBytes(strName + ",,"); + // Stop key appends the smallest possible char to the table name + byte[] stopKey = Bytes.toBytes(strName + " ,,"); + + Scan scan = new Scan(startKey); + scan.setStopRow(stopKey); + return scan; + } + + /** * @param catalogTracker * @param tableName * @return Return list of regioninfos and server addresses. @@ -545,8 +553,7 @@ getCatalogRegionInterface(catalogTracker, tableNameBytes); List> regions = new ArrayList>(); - byte[] firstRowInTable = Bytes.toBytes(tableName + ",,"); - Scan scan = new Scan(firstRowInTable); + Scan scan = getScanForTableName(tableNameBytes); scan.addFamily(HConstants.CATALOG_FAMILY); long scannerid = metaServer.openScanner(getCatalogRegionNameForTable(tableNameBytes), scan); @@ -556,12 +563,7 @@ if (data != null && data.size() > 0) { Pair region = metaRowToRegionPair(data); if (region == null) continue; - if (region.getFirst().getTableDesc().getNameAsString().equals( - tableName)) { - regions.add(region); - } else { - break; - } + regions.add(region); } } return regions; Index: src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java (revision 1082002) +++ src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java (working copy) @@ -22,8 +22,6 @@ import java.io.IOException; import java.util.Arrays; import java.util.List; -import java.util.Map; -import java.util.NavigableMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -49,7 +47,6 @@ import org.apache.hadoop.hbase.ipc.HRegionInterface; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Pair; -import org.apache.hadoop.hbase.util.Writables; import org.apache.hadoop.ipc.RemoteException; /** @@ -371,42 +368,23 @@ } catch (RemoteException e) { throw RemoteExceptionHandler.decodeRemoteException(e); } - final int batchCount = this.conf.getInt("hbase.admin.scanner.caching", 10); // Wait until all regions deleted HRegionInterface server = connection.getHRegionConnection(firstMetaServer.getServerAddress()); - HRegionInfo info = new HRegionInfo(); for (int tries = 0; tries < (this.numRetries * this.retryLongerMultiplier); tries++) { long scannerId = -1L; try { - Scan scan = new Scan().addColumn(HConstants.CATALOG_FAMILY, - HConstants.REGIONINFO_QUALIFIER); + + Scan scan = MetaReader.getScanForTableName(tableName); + scan.addColumn(HConstants.CATALOG_FAMILY, + HConstants.REGIONINFO_QUALIFIER); scannerId = server.openScanner( firstMetaServer.getRegionInfo().getRegionName(), scan); // Get a batch at a time. - Result [] values = server.next(scannerId, batchCount); - if (values == null || values.length == 0) { + Result values = server.next(scannerId); + if (values == null) { break; } - boolean found = false; - for (Result r : values) { - NavigableMap infoValues = - r.getFamilyMap(HConstants.CATALOG_FAMILY); - for (Map.Entry e : infoValues.entrySet()) { - if (Bytes.equals(e.getKey(), HConstants.REGIONINFO_QUALIFIER)) { - info = (HRegionInfo) Writables.getWritable(e.getValue(), info); - if (Bytes.equals(info.getTableDesc().getName(), tableName)) { - found = true; - } else { - found = false; - break; - } - } - } - } - if (!found) { - break; - } } catch (IOException ex) { if(tries == numRetries - 1) { // no more tries left if (ex instanceof RemoteException) {