HBASE-2823 Entire Row Deletes not stored in Row+Col Bloom

git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@982472 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Michael Stack 2010-08-05 05:16:10 +00:00
parent 37af9aab2e
commit 25ffbc5f11
3 changed files with 61 additions and 2 deletions

View File

@ -469,6 +469,8 @@ Release 0.21.0 - Unreleased
HBASE-2871 Make "start|stop" commands symmetric for Master & Cluster HBASE-2871 Make "start|stop" commands symmetric for Master & Cluster
(Nicolas Spiegelberg via Stack) (Nicolas Spiegelberg via Stack)
HBASE-2901 HBASE-2461 broke build HBASE-2901 HBASE-2461 broke build
HBASE-2823 Entire Row Deletes not stored in Row+Col Bloom
(Alexander Georgiev via Stack)
IMPROVEMENTS IMPROVEMENTS
HBASE-1760 Cleanup TODOs in HTable HBASE-1760 Cleanup TODOs in HTable

View File

@ -694,6 +694,13 @@ public class StoreFile {
if (bloomType != BloomType.NONE && conf != null) { if (bloomType != BloomType.NONE && conf != null) {
float err = conf.getFloat(IO_STOREFILE_BLOOM_ERROR_RATE, (float)0.01); float err = conf.getFloat(IO_STOREFILE_BLOOM_ERROR_RATE, (float)0.01);
// Since in row+col blooms we have 2 calls to shouldSeek() instead of 1
// and the false positives are adding up, we should keep the error rate
// twice as low in order to maintain the number of false positives as
// desired by the user
if (bloomType == BloomType.ROWCOL) {
err /= 2;
}
int maxFold = conf.getInt(IO_STOREFILE_BLOOM_MAX_FOLD, 7); int maxFold = conf.getInt(IO_STOREFILE_BLOOM_MAX_FOLD, 7);
this.bloomFilter = new ByteBloomFilter(maxKeys, err, this.bloomFilter = new ByteBloomFilter(maxKeys, err,
@ -800,7 +807,6 @@ public class StoreFile {
byte [] result = new byte[rl + ql]; byte [] result = new byte[rl + ql];
System.arraycopy(kv.getBuffer(), ro, result, 0, rl); System.arraycopy(kv.getBuffer(), ro, result, 0, rl);
System.arraycopy(kv.getBuffer(), qo, result, rl, ql); System.arraycopy(kv.getBuffer(), qo, result, rl, ql);
this.bloomFilter.add(result); this.bloomFilter.add(result);
break; break;
default: default:
@ -943,8 +949,18 @@ public class StoreFile {
try { try {
ByteBuffer bloom = reader.getMetaBlock(BLOOM_FILTER_DATA_KEY, true); ByteBuffer bloom = reader.getMetaBlock(BLOOM_FILTER_DATA_KEY, true);
if (bloom != null) { if (bloom != null) {
if (this.bloomFilterType == BloomType.ROWCOL) {
// Since a Row Delete is essentially a DeleteFamily applied to all
// columns, a file might be skipped if using row+col Bloom filter.
// In order to ensure this file is included an additional check is
// required looking only for a row bloom.
return this.bloomFilter.contains(key, bloom) ||
this.bloomFilter.contains(row, bloom);
}
else {
return this.bloomFilter.contains(key, bloom); return this.bloomFilter.contains(key, bloom);
} }
}
} catch (IOException e) { } catch (IOException e) {
LOG.error("Error reading bloom filter data -- proceeding without", LOG.error("Error reading bloom filter data -- proceeding without",
e); e);

View File

@ -2723,6 +2723,47 @@ public class TestHRegion extends HBaseTestCase {
checkOneCell(kvs[3], FAMILY, 0, 0, 1); checkOneCell(kvs[3], FAMILY, 0, 0, 1);
} }
/**
* Testcase to cover bug-fix for HBASE-2823
* Ensures correct delete when issuing delete row
* on columns with bloom filter set to row+col (BloomType.ROWCOL)
*/
public void testDeleteRowWithBloomFilter() throws IOException {
byte [] tableName = Bytes.toBytes("testDeleteRowWithBloomFilter");
byte [] familyName = Bytes.toBytes("familyName");
// Create Table
HColumnDescriptor hcd = new HColumnDescriptor(familyName, Integer.MAX_VALUE,
HColumnDescriptor.DEFAULT_COMPRESSION, false, true,
HColumnDescriptor.DEFAULT_TTL, "rowcol");
HTableDescriptor htd = new HTableDescriptor(tableName);
htd.addFamily(hcd);
HRegionInfo info = new HRegionInfo(htd, null, null, false);
Path path = new Path(DIR + "TestDeleteRowWithBloomFilter");
region = HRegion.createHRegion(info, path, conf);
// Insert some data
byte row[] = Bytes.toBytes("row1");
byte col[] = Bytes.toBytes("col1");
Put put = new Put(row);
put.add(familyName, col, 1, Bytes.toBytes("SomeRandomValue"));
region.put(put);
region.flushcache();
Delete del = new Delete(row);
region.delete(del, null, true);
region.flushcache();
// Get remaining rows (should have none)
Get get = new Get(row);
get.addColumn(familyName, col);
KeyValue[] keyValues = region.get(get, null).raw();
assertTrue(keyValues.length == 0);
}
private void putData(int startRow, int numRows, byte [] qf, private void putData(int startRow, int numRows, byte [] qf,
byte [] ...families) byte [] ...families)
throws IOException { throws IOException {