HBASE-3650 HBA.delete can return too fast

git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1082204 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Jean-Daniel Cryans 2011-03-16 16:55:02 +00:00
parent 8963351fc1
commit a8beafc5cf
4 changed files with 65 additions and 54 deletions

View File

@ -167,6 +167,7 @@ Release 0.90.2 - Unreleased
HBASE-3639 FSUtils.getRootDir should qualify path
HBASE-3648 [replication] failover is sloppy with znodes
HBASE-3613 NPE in MemStoreFlusher
HBASE-3650 HBA.delete can return too fast
IMPROVEMENTS
HBASE-3542 MultiGet methods in Thrift

View File

@ -431,22 +431,15 @@ public class MetaReader {
}
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 {
metaServer.close(scannerid);
@ -494,9 +487,8 @@ public class MetaReader {
HRegionInterface metaServer =
getCatalogRegionInterface(catalogTracker, tableName);
List<HRegionInfo> regions = new ArrayList<HRegionInfo>();
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 @@ public class MetaReader {
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;
}
}
}
return regions;
@ -522,6 +509,27 @@ public class MetaReader {
}
}
/**
* 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
@ -545,8 +553,7 @@ public class MetaReader {
getCatalogRegionInterface(catalogTracker, tableNameBytes);
List<Pair<HRegionInfo, HServerAddress>> regions =
new ArrayList<Pair<HRegionInfo, HServerAddress>>();
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 @@ public class MetaReader {
if (data != null && data.size() > 0) {
Pair<HRegionInfo, HServerAddress> region = metaRowToRegionPair(data);
if (region == null) continue;
if (region.getFirst().getTableDesc().getNameAsString().equals(
tableName)) {
regions.add(region);
} else {
break;
}
}
}
return regions;

View File

@ -22,8 +22,6 @@ package org.apache.hadoop.hbase.client;
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.HMasterInterface;
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,40 +368,21 @@ public class HBaseAdmin implements Abortable {
} 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,
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) {
break;
}
boolean found = false;
for (Result r : values) {
NavigableMap<byte[], byte[]> infoValues =
r.getFamilyMap(HConstants.CATALOG_FAMILY);
for (Map.Entry<byte[], byte[]> 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) {
Result values = server.next(scannerId);
if (values == null) {
break;
}
} catch (IOException ex) {

View File

@ -130,4 +130,34 @@ public class TestMetaReaderEditor {
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());
}
}