You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by zj...@apache.org on 2013/04/28 10:13:10 UTC
svn commit: r1476731 - in /hbase/branches/0.95:
hbase-prefix-tree/src/main/java/org/apache/hadoop/hbase/codec/prefixtree/PrefixTreeSeeker.java
hbase-server/src/test/java/org/apache/hadoop/hbase/io/encoding/TestPrefixTreeEncoding.java
Author: zjushch
Date: Sun Apr 28 08:13:10 2013
New Revision: 1476731
URL: http://svn.apache.org/r1476731
Log:
HBASE-8436 SeekBefore returns wrong result with PREFIX_TREE Encoding
Modified:
hbase/branches/0.95/hbase-prefix-tree/src/main/java/org/apache/hadoop/hbase/codec/prefixtree/PrefixTreeSeeker.java
hbase/branches/0.95/hbase-server/src/test/java/org/apache/hadoop/hbase/io/encoding/TestPrefixTreeEncoding.java
Modified: hbase/branches/0.95/hbase-prefix-tree/src/main/java/org/apache/hadoop/hbase/codec/prefixtree/PrefixTreeSeeker.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.95/hbase-prefix-tree/src/main/java/org/apache/hadoop/hbase/codec/prefixtree/PrefixTreeSeeker.java?rev=1476731&r1=1476730&r2=1476731&view=diff
==============================================================================
--- hbase/branches/0.95/hbase-prefix-tree/src/main/java/org/apache/hadoop/hbase/codec/prefixtree/PrefixTreeSeeker.java (original)
+++ hbase/branches/0.95/hbase-prefix-tree/src/main/java/org/apache/hadoop/hbase/codec/prefixtree/PrefixTreeSeeker.java Sun Apr 28 08:13:10 2013
@@ -91,6 +91,9 @@ public class PrefixTreeSeeker implements
*/
@Override
public KeyValue getKeyValue() {
+ if (ptSearcher.current() == null) {
+ return null;
+ }
return KeyValueUtil.copyToNewKeyValue(ptSearcher.current());
}
@@ -163,14 +166,14 @@ public class PrefixTreeSeeker implements
*/
protected int seekToOrBeforeUsingPositionAtOrBefore(byte[] keyOnlyBytes, int offset, int length,
- boolean forceBeforeOnExactMatch){
+ boolean seekBefore){
// this does a deep copy of the key byte[] because the CellSearcher interface wants a Cell
KeyValue kv = KeyValue.createKeyValueFromKey(keyOnlyBytes, offset, length);
CellScannerPosition position = ptSearcher.seekForwardToOrBefore(kv);
if(CellScannerPosition.AT == position){
- if (forceBeforeOnExactMatch) {
+ if (seekBefore) {
ptSearcher.previous();
return 1;
}
@@ -182,7 +185,7 @@ public class PrefixTreeSeeker implements
protected int seekToOrBeforeUsingPositionAtOrAfter(byte[] keyOnlyBytes, int offset, int length,
- boolean forceBeforeOnExactMatch){
+ boolean seekBefore){
// this does a deep copy of the key byte[] because the CellSearcher interface wants a Cell
KeyValue kv = KeyValue.createKeyValueFromKey(keyOnlyBytes, offset, length);
@@ -190,7 +193,7 @@ public class PrefixTreeSeeker implements
CellScannerPosition position = ptSearcher.seekForwardToOrAfter(kv);
if(CellScannerPosition.AT == position){
- if (forceBeforeOnExactMatch) {
+ if (seekBefore) {
ptSearcher.previous();
return 1;
}
@@ -206,6 +209,9 @@ public class PrefixTreeSeeker implements
}
if(position == CellScannerPosition.AFTER_LAST){
+ if (seekBefore) {
+ ptSearcher.previous();
+ }
return 1;
}
Modified: hbase/branches/0.95/hbase-server/src/test/java/org/apache/hadoop/hbase/io/encoding/TestPrefixTreeEncoding.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.95/hbase-server/src/test/java/org/apache/hadoop/hbase/io/encoding/TestPrefixTreeEncoding.java?rev=1476731&r1=1476730&r2=1476731&view=diff
==============================================================================
--- hbase/branches/0.95/hbase-server/src/test/java/org/apache/hadoop/hbase/io/encoding/TestPrefixTreeEncoding.java (original)
+++ hbase/branches/0.95/hbase-server/src/test/java/org/apache/hadoop/hbase/io/encoding/TestPrefixTreeEncoding.java Sun Apr 28 08:13:10 2013
@@ -18,6 +18,9 @@
*/
package org.apache.hadoop.hbase.io.encoding;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import java.io.ByteArrayOutputStream;
@@ -57,9 +60,54 @@ public class TestPrefixTreeEncoding {
private ConcurrentSkipListSet<KeyValue> kvset = new ConcurrentSkipListSet<KeyValue>(
KeyValue.COMPARATOR);
+ private static boolean formatRowNum = false;
+
@Before
public void setUp() throws Exception {
kvset.clear();
+ formatRowNum = false;
+ }
+
+ @Test
+ public void testSeekBeforeWithFixedData() throws Exception {
+ formatRowNum = true;
+ PrefixTreeCodec encoder = new PrefixTreeCodec();
+ int batchId = numBatchesWritten++;
+ ByteBuffer dataBuffer = generateFixedTestData(kvset, batchId, false);
+ HFileBlockEncodingContext blkEncodingCtx = new HFileBlockDefaultEncodingContext(
+ Algorithm.NONE, DataBlockEncoding.PREFIX_TREE, new byte[0]);
+ encoder.encodeKeyValues(dataBuffer, false, blkEncodingCtx);
+ EncodedSeeker seeker = encoder.createSeeker(KeyValue.KEY_COMPARATOR, false);
+ byte[] onDiskBytes = blkEncodingCtx.getOnDiskBytesWithHeader();
+ ByteBuffer readBuffer = ByteBuffer.wrap(onDiskBytes,
+ DataBlockEncoding.ID_SIZE, onDiskBytes.length
+ - DataBlockEncoding.ID_SIZE);
+ seeker.setCurrentBuffer(readBuffer);
+
+ // Seek before the first keyvalue;
+ KeyValue seekKey = KeyValue.createFirstDeleteFamilyOnRow(
+ getRowKey(batchId, 0), CF_BYTES);
+ seeker.seekToKeyInBlock(seekKey.getBuffer(), seekKey.getKeyOffset(),
+ seekKey.getKeyLength(), true);
+ assertEquals(null, seeker.getKeyValue());
+
+ // Seek before the middle keyvalue;
+ seekKey = KeyValue.createFirstDeleteFamilyOnRow(
+ getRowKey(batchId, NUM_ROWS_PER_BATCH / 3), CF_BYTES);
+ seeker.seekToKeyInBlock(seekKey.getBuffer(), seekKey.getKeyOffset(),
+ seekKey.getKeyLength(), true);
+ assertNotNull(seeker.getKeyValue());
+ assertArrayEquals(getRowKey(batchId, NUM_ROWS_PER_BATCH / 3 - 1), seeker
+ .getKeyValue().getRow());
+
+ // Seek before the last keyvalue;
+ seekKey = KeyValue.createFirstDeleteFamilyOnRow(Bytes.toBytes("zzzz"),
+ CF_BYTES);
+ seeker.seekToKeyInBlock(seekKey.getBuffer(), seekKey.getKeyOffset(),
+ seekKey.getKeyLength(), true);
+ assertNotNull(seeker.getKeyValue());
+ assertArrayEquals(getRowKey(batchId, NUM_ROWS_PER_BATCH - 1), seeker
+ .getKeyValue().getRow());
}
@Test
@@ -157,10 +205,16 @@ public class TestPrefixTreeEncoding {
private static ByteBuffer generateFixedTestData(
ConcurrentSkipListSet<KeyValue> kvset, int batchId) throws Exception {
+ return generateFixedTestData(kvset, batchId, true);
+ }
+
+ private static ByteBuffer generateFixedTestData(
+ ConcurrentSkipListSet<KeyValue> kvset, int batchId, boolean partial)
+ throws Exception {
ByteArrayOutputStream baosInMemory = new ByteArrayOutputStream();
DataOutputStream userDataStream = new DataOutputStream(baosInMemory);
for (int i = 0; i < NUM_ROWS_PER_BATCH; ++i) {
- if (i / 10 % 2 == 1) continue;
+ if (partial && i / 10 % 2 == 1) continue;
for (int j = 0; j < NUM_COLS_PER_ROW; ++j) {
KeyValue kv = new KeyValue(getRowKey(batchId, i), CF_BYTES,
getQualifier(j), getValue(batchId, i, j));
@@ -204,7 +258,8 @@ public class TestPrefixTreeEncoding {
}
private static byte[] getRowKey(int batchId, int i) {
- return Bytes.toBytes("batch" + batchId + "_row" + i);
+ return Bytes.toBytes("batch" + batchId + "_row"
+ + (formatRowNum ? String.format("%04d", i) : i));
}
private static byte[] getQualifier(int j) {