Index: src/java/org/apache/hadoop/hbase/client/HTable.java =================================================================== --- src/java/org/apache/hadoop/hbase/client/HTable.java (revision 656727) +++ src/java/org/apache/hadoop/hbase/client/HTable.java (working copy) @@ -35,6 +35,7 @@ import org.apache.hadoop.hbase.HRegionLocation; import org.apache.hadoop.hbase.HServerAddress; import org.apache.hadoop.hbase.HTableDescriptor; +import org.apache.hadoop.hbase.client.MetaScanner.MetaScannerVisitor; import org.apache.hadoop.hbase.filter.RowFilterInterface; import org.apache.hadoop.hbase.filter.StopRowFilter; import org.apache.hadoop.hbase.filter.WhileMatchRowFilter; @@ -42,6 +43,7 @@ import org.apache.hadoop.hbase.io.Cell; import org.apache.hadoop.hbase.io.RowResult; import org.apache.hadoop.hbase.ipc.HRegionInterface; +import org.apache.hadoop.hbase.util.MetaUtils; import org.apache.hadoop.hbase.util.Writables; import org.apache.hadoop.io.Text; @@ -56,6 +58,7 @@ protected final long pause; protected final int numRetries; protected Random rand; + protected HBaseConfiguration configuration; protected volatile boolean tableDoesNotExist; @@ -70,6 +73,7 @@ */ public HTable(HBaseConfiguration conf, Text tableName) throws IOException { this.connection = HConnectionManager.getConnection(conf); + this.configuration = conf; this.tableName = tableName; this.pause = conf.getLong("hbase.client.pause", 10 * 1000); this.numRetries = conf.getInt("hbase.client.retries.number", 5); @@ -121,62 +125,26 @@ */ @SuppressWarnings("null") public Text[] getStartKeys() throws IOException { - List keyList = new ArrayList(); - - long scannerId = -1L; - - Text startRow = new Text(tableName.toString() + ",,999999999999999"); - HRegionLocation metaLocation = null; - HRegionInterface server; + final List keyList = new ArrayList(); - // scan over the each meta region - do { - try{ - // turn the start row into a location - metaLocation = - connection.locateRegion(META_TABLE_NAME, startRow); + MetaScannerVisitor visitor = new MetaScannerVisitor() { - // connect to the server hosting the .META. region - server = - connection.getHRegionConnection(metaLocation.getServerAddress()); - - // open a scanner over the meta region - scannerId = server.openScanner( - metaLocation.getRegionInfo().getRegionName(), - new Text[]{COL_REGIONINFO}, tableName, LATEST_TIMESTAMP, - null); + public boolean processRow(RowResult rowResult,HRegionLocation metaLocation) throws IOException { - // iterate through the scanner, accumulating unique region names - while (true) { - RowResult values = server.next(scannerId); - if (values == null || values.size() == 0) { - break; - } - - HRegionInfo info = new HRegionInfo(); - info = (HRegionInfo) Writables.getWritable( - values.get(COL_REGIONINFO).getValue(), info); - - if (!info.getTableDesc().getName().equals(this.tableName)) { - break; - } - - if (info.isOffline() || info.isSplit()) { - continue; - } + HRegionInfo info = + Writables.getHRegionInfo(rowResult.get(COL_REGIONINFO)); + + if (!info.getTableDesc().getName().equals(tableName)) { + return false; + } + if (!(info.isOffline() || info.isSplit())) { keyList.add(info.getStartKey()); } - - // close that remote scanner - server.close(scannerId); - - // advance the startRow to the end key of the current region - startRow = metaLocation.getRegionInfo().getEndKey(); - } catch (IOException e) { - // need retry logic? - throw e; + return true; } - } while (startRow.compareTo(EMPTY_START_ROW) != 0); + + }; + MetaScanner.metaScan(configuration,visitor, new Text(tableName.toString() + ",,999999999999999"), tableName); return keyList.toArray(new Text[keyList.size()]); } @@ -188,63 +156,26 @@ */ @SuppressWarnings("null") public Map getRegionsInfo() throws IOException { - // TODO This code is a near exact copy of getStartKeys. To be refactored HBASE-626 - HashMap regionMap = new HashMap(); - - long scannerId = -1L; - - Text startRow = new Text(tableName.toString() + ",,999999999999999"); - HRegionLocation metaLocation = null; - HRegionInterface server; - // scan over the each meta region - do { - try{ - // turn the start row into a location - metaLocation = - connection.locateRegion(META_TABLE_NAME, startRow); + final HashMap regionMap = new HashMap(); + + MetaScannerVisitor visitor = new MetaScannerVisitor() { - // connect to the server hosting the .META. region - server = - connection.getHRegionConnection(metaLocation.getServerAddress()); - - // open a scanner over the meta region - scannerId = server.openScanner( - metaLocation.getRegionInfo().getRegionName(), - new Text[]{COL_REGIONINFO}, tableName, LATEST_TIMESTAMP, - null); + public boolean processRow(RowResult rowResult,HRegionLocation metaLocation) throws IOException { - // iterate through the scanner, accumulating regions and their regionserver - while (true) { - RowResult values = server.next(scannerId); - if (values == null || values.size() == 0) { - break; - } - - HRegionInfo info = new HRegionInfo(); - info = (HRegionInfo) Writables.getWritable( - values.get(COL_REGIONINFO).getValue(), info); - - if (!info.getTableDesc().getName().equals(this.tableName)) { - break; - } - - if (info.isOffline() || info.isSplit()) { - continue; - } + HRegionInfo info = + Writables.getHRegionInfo(rowResult.get(COL_REGIONINFO)); + if (!info.getTableDesc().getName().equals(tableName)) { + return false; + } + if (!(info.isOffline() || info.isSplit())) { regionMap.put(info, metaLocation.getServerAddress()); } - - // close that remote scanner - server.close(scannerId); - - // advance the startRow to the end key of the current region - startRow = metaLocation.getRegionInfo().getEndKey(); - } catch (IOException e) { - // need retry logic? - throw e; + return true; } - } while (startRow.compareTo(EMPTY_START_ROW) != 0); + + }; + MetaScanner.metaScan(configuration,visitor, new Text(tableName.toString() + ",,999999999999999"), tableName); return regionMap; } Index: src/java/org/apache/hadoop/hbase/client/MetaScanner.java =================================================================== --- src/java/org/apache/hadoop/hbase/client/MetaScanner.java (revision 0) +++ src/java/org/apache/hadoop/hbase/client/MetaScanner.java (revision 0) @@ -0,0 +1,89 @@ +package org.apache.hadoop.hbase.client; + +import java.io.IOException; + +import org.apache.hadoop.hbase.HBaseConfiguration; +import org.apache.hadoop.hbase.HConstants; +import org.apache.hadoop.hbase.HRegionLocation; +import org.apache.hadoop.hbase.io.RowResult; +import org.apache.hadoop.io.Text; + +/** + * Scanner class that contains the meta table scanning with + * a Retryable scanner. + */ + +class MetaScanner implements HConstants{ + + /** + * Scans the meta table and calls a visitor on each RowResult and uses + * a empty start row value and empty scanner row. + * @param configuration + * @param a custom visitor + * @throws IOException + */ + + public static void metaScan(HBaseConfiguration configuration, MetaScannerVisitor visitor) throws IOException{ + metaScan(configuration, visitor, EMPTY_START_ROW, EMPTY_START_ROW); + } + + /** + * Scans the meta table and calls a visitor on each RowResult. I uses a start row + * value to locate meta regions and a scanner row value to open the scanner. + * @param configuration + * @param visitor + * @param startRow + * @param scannerRow + * @throws IOException + */ + public static void metaScan(HBaseConfiguration configuration, MetaScannerVisitor visitor, Text startRow, Text scannerRow) throws IOException{ + HConnection connection = HConnectionManager.getConnection(configuration); + HRegionLocation metaLocation = null; + boolean toContinue = true; + // scan over the each meta region + do { + ScannerCallable callable = new ScannerCallable(connection, META_TABLE_NAME, + COL_REGIONINFO_ARRAY, scannerRow, LATEST_TIMESTAMP, null); + try { + // open scanner + connection.getRegionServerWithRetries(callable); + + metaLocation = + connection.locateRegion(META_TABLE_NAME, startRow); + + while (toContinue) { + RowResult values = connection.getRegionServerWithRetries(callable); + if (values == null || values.size() == 0) { + break; + } + toContinue = visitor.processRow(values, metaLocation); + } + // advance the startRow to the end key of the current region + startRow = callable.getHRegionInfo().getEndKey(); + } finally { + // close scanner + callable.setClose(); + connection.getRegionServerWithRetries(callable); + } + } while (startRow.compareTo(LAST_ROW) != 0); + } + + /** + * Visitor class called to process each row of the meta table + * + */ + protected interface MetaScannerVisitor { + + /** + * Visitor method that accepts a RowResult and the meta region + * location. Implementations can return false to stop the region's loop + * if it becomes unnecessary for some reason. + * @param rowResult + * @param metaLocation + * @return A boolean to know if it should continue to loop in the region + * @throws IOException + */ + public boolean processRow(RowResult rowResult, HRegionLocation metaLocation) throws IOException; + } + +} Index: src/java/org/apache/hadoop/hbase/client/HConnectionManager.java =================================================================== --- src/java/org/apache/hadoop/hbase/client/HConnectionManager.java (revision 656727) +++ src/java/org/apache/hadoop/hbase/client/HConnectionManager.java (working copy) @@ -31,6 +31,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.hbase.client.MetaScanner.MetaScannerVisitor; import org.apache.hadoop.hbase.ipc.HbaseRPC; import org.apache.hadoop.hbase.util.Writables; import org.apache.hadoop.io.Text; @@ -252,39 +253,24 @@ /** {@inheritDoc} */ public HTableDescriptor[] listTables() throws IOException { - HashSet uniqueTables = new HashSet(); - Text startRow = EMPTY_START_ROW; + final HashSet uniqueTables = new HashSet(); + + MetaScannerVisitor visitor = new MetaScannerVisitor() { - // scan over the each meta region - do { - ScannerCallable callable = new ScannerCallable(this, META_TABLE_NAME, - COL_REGIONINFO_ARRAY, startRow, LATEST_TIMESTAMP, null); - try { - // open scanner - getRegionServerWithRetries(callable); - // iterate through the scanner, accumulating unique table names - while (true) { - RowResult values = getRegionServerWithRetries(callable); - if (values == null || values.size() == 0) { - break; - } + public boolean processRow(RowResult rowResult,HRegionLocation metaLocation) throws IOException { + + HRegionInfo info = + Writables.getHRegionInfo(rowResult.get(COL_REGIONINFO)); - HRegionInfo info = - Writables.getHRegionInfo(values.get(COL_REGIONINFO)); - - // Only examine the rows where the startKey is zero length - if (info.getStartKey().getLength() == 0) { - uniqueTables.add(info.getTableDesc()); - } + // Only examine the rows where the startKey is zero length + if (info.getStartKey().getLength() == 0) { + uniqueTables.add(info.getTableDesc()); } - // advance the startRow to the end key of the current region - startRow = callable.getHRegionInfo().getEndKey(); - } finally { - // close scanner - callable.setClose(); - getRegionServerWithRetries(callable); + return true; } - } while (startRow.compareTo(LAST_ROW) != 0); + + }; + MetaScanner.metaScan(conf,visitor); return uniqueTables.toArray(new HTableDescriptor[uniqueTables.size()]); }