HBASE-6562 Fake KVs are sometimes passed to filters
git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1373650 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
8d7218bf31
commit
c3d1bb07f8
|
@ -1156,6 +1156,14 @@ public class KeyValue implements Writable, HeapSize {
|
|||
HConstants.LATEST_TIMESTAMP_BYTES, 0, Bytes.SIZEOF_LONG);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if this is a "fake" KV created for internal seeking purposes,
|
||||
* which should not be seen by user code
|
||||
*/
|
||||
public boolean isInternal() {
|
||||
byte type = getType();
|
||||
return type == Type.Minimum.code || type == Type.Maximum.code;
|
||||
}
|
||||
/**
|
||||
* @param now Time to set into <code>this</code> IFF timestamp ==
|
||||
* {@link HConstants#LATEST_TIMESTAMP} (else, its a noop).
|
||||
|
|
|
@ -3567,14 +3567,15 @@ public class HRegion implements HeapSize { // , Writable{
|
|||
rpcCall.throwExceptionIfCallerDisconnected();
|
||||
}
|
||||
|
||||
byte [] currentRow = peekRow();
|
||||
KeyValue kv = this.storeHeap.peek();
|
||||
byte [] currentRow = kv == null ? null : kv.getRow();
|
||||
if (isStopRow(currentRow)) {
|
||||
if (filter != null && filter.hasFilterRow()) {
|
||||
filter.filterRow(results);
|
||||
}
|
||||
|
||||
return false;
|
||||
} else if (filterRowKey(currentRow)) {
|
||||
} else if (kv != null && !kv.isInternal() && filterRowKey(currentRow)) {
|
||||
nextRow(currentRow);
|
||||
} else {
|
||||
byte [] nextRow;
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.hadoop.hbase.client;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.apache.hadoop.hbase.*;
|
||||
import org.apache.hadoop.hbase.filter.*;
|
||||
import org.apache.hadoop.hbase.regionserver.HRegion;
|
||||
import org.apache.hadoop.hbase.regionserver.RegionScanner;
|
||||
import org.apache.hadoop.hbase.util.Bytes;
|
||||
import org.apache.hadoop.hbase.util.FSUtils;
|
||||
import org.junit.*;
|
||||
import org.junit.experimental.categories.Category;
|
||||
|
||||
/**
|
||||
* Make sure the fake KVs created internally are never user visible
|
||||
* (not even to filters)
|
||||
*/
|
||||
@Category(SmallTests.class)
|
||||
public class TestFakeKeyInFilter extends BinaryComparator {
|
||||
protected static HBaseTestingUtility UTIL = new HBaseTestingUtility();
|
||||
|
||||
public TestFakeKeyInFilter() {
|
||||
super(Bytes.toBytes("foo"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(byte[] value, int offset, int length) {
|
||||
if (value.length == 0) {
|
||||
throw new RuntimeException("Found mysterious empty row");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple way to verify the scenario.
|
||||
* There are no KVs with an empty row key in the
|
||||
* table, yet such a KV is presented to the filter.
|
||||
*/
|
||||
@Test
|
||||
public void testForEmptyRowKey() throws Exception {
|
||||
byte[] table = Bytes.toBytes("testForEmptyRowKey");
|
||||
byte[] row = Bytes.toBytes("myRow");
|
||||
byte[] cf = Bytes.toBytes("myFamily");
|
||||
byte[] cq = Bytes.toBytes("myColumn");
|
||||
HTableDescriptor desc = new HTableDescriptor(table);
|
||||
desc.addFamily(new HColumnDescriptor(cf));
|
||||
HRegionInfo hri = new HRegionInfo(desc.getName(), null, null);
|
||||
HRegion region = HRegion.createHRegion(hri, FSUtils.getRootDir(UTIL.getConfiguration()), UTIL.getConfiguration(), desc);
|
||||
Put put = new Put(row);
|
||||
put.add(cf, cq, cq);
|
||||
region.put(put);
|
||||
region.flushcache();
|
||||
Scan scan = new Scan();
|
||||
scan.addColumn(cf, cq);
|
||||
WritableByteArrayComparable comparable = new TestFakeKeyInFilter();
|
||||
Filter filter = new RowFilter(CompareFilter.CompareOp.EQUAL, comparable);
|
||||
scan.setFilter(filter);
|
||||
RegionScanner scanner = region.getScanner(scan);
|
||||
scanner.next(new ArrayList<KeyValue>());
|
||||
scanner.close();
|
||||
region.close();
|
||||
}
|
||||
|
||||
@org.junit.Rule
|
||||
public org.apache.hadoop.hbase.ResourceCheckerJUnitRule cu =
|
||||
new org.apache.hadoop.hbase.ResourceCheckerJUnitRule();
|
||||
}
|
Loading…
Reference in New Issue