Skip to content

Commit c40166f

Browse files
bbeaudreaultJenkins
authored andcommitted
HBASE-27580 Reverse scan over rows with tags throw exceptions when using DataBlockEncoding (apache#5006)
Signed-off-by: Duo Zhang <zhangduo@apache.org> (cherry picked from commit 447846d) Change-Id: Icea11ec91c629d69e6a972f4dea7e87cf24eb863
1 parent 128958b commit c40166f

File tree

2 files changed

+83
-1
lines changed

2 files changed

+83
-1
lines changed

hbase-common/src/main/java/org/apache/hadoop/hbase/io/encoding/BufferedDataBlockEncoder.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,15 @@ public void rewind() {
789789
currentBuffer.rewind();
790790
if (tagCompressionContext != null) {
791791
tagCompressionContext.clear();
792+
// Prior seekToKeyInBlock may have reset this to false if we fell back to previous
793+
// seeker state. This is an optimization so we don't have to uncompress tags again when
794+
// reading last state.
795+
// In case of rewind, we are starting from the beginning of the buffer, so we need
796+
// to uncompress any tags we see.
797+
// It may make sense to reset this in setCurrentBuffer as well, but we seem to only call
798+
// setCurrentBuffer after StoreFileScanner.seekAtOrAfter which calls next to consume the
799+
// seeker state. Rewind is called by seekBefore, which doesn't and leaves us in this state.
800+
current.uncompressTags = true;
792801
}
793802
decodeFirst();
794803
current.setKey(current.keyBuffer, current.memstoreTS);
@@ -815,7 +824,7 @@ protected void decodeTags() {
815824
try {
816825
current.tagsCompressedLength = tagCompressionContext.uncompressTags(currentBuffer,
817826
current.tagsBuffer, 0, current.tagsLength);
818-
} catch (IOException e) {
827+
} catch (Exception e) {
819828
throw new RuntimeException("Exception while uncompressing tags", e);
820829
}
821830
} else {

hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestTags.java

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@
4141
import org.apache.hadoop.hbase.Tag;
4242
import org.apache.hadoop.hbase.client.Admin;
4343
import org.apache.hadoop.hbase.client.Append;
44+
import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
4445
import org.apache.hadoop.hbase.client.CompactionState;
46+
import org.apache.hadoop.hbase.client.Connection;
47+
import org.apache.hadoop.hbase.client.ConnectionFactory;
4548
import org.apache.hadoop.hbase.client.Durability;
4649
import org.apache.hadoop.hbase.client.Increment;
4750
import org.apache.hadoop.hbase.client.Mutation;
@@ -50,6 +53,7 @@
5053
import org.apache.hadoop.hbase.client.ResultScanner;
5154
import org.apache.hadoop.hbase.client.Scan;
5255
import org.apache.hadoop.hbase.client.Table;
56+
import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
5357
import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
5458
import org.apache.hadoop.hbase.coprocessor.ObserverContext;
5559
import org.apache.hadoop.hbase.coprocessor.RegionCoprocessor;
@@ -68,6 +72,8 @@
6872
import org.junit.Test;
6973
import org.junit.experimental.categories.Category;
7074
import org.junit.rules.TestName;
75+
import org.slf4j.Logger;
76+
import org.slf4j.LoggerFactory;
7177

7278
/**
7379
* Class that test tags
@@ -78,6 +84,8 @@ public class TestTags {
7884
@ClassRule
7985
public static final HBaseClassTestRule CLASS_RULE = HBaseClassTestRule.forClass(TestTags.class);
8086

87+
private static final Logger LOG = LoggerFactory.getLogger(TestTags.class);
88+
8189
static boolean useFilter = false;
8290

8391
private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
@@ -104,6 +112,71 @@ public void tearDown() {
104112
useFilter = false;
105113
}
106114

115+
/**
116+
* Test that we can do reverse scans when writing tags and using DataBlockEncoding. Fails with an
117+
* exception for PREFIX, DIFF, and FAST_DIFF prior to HBASE-27580
118+
*/
119+
@Test
120+
public void testReverseScanWithDBE() throws IOException {
121+
byte[] family = Bytes.toBytes("0");
122+
123+
Configuration conf = new Configuration(TEST_UTIL.getConfiguration());
124+
conf.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 1);
125+
126+
try (Connection connection = ConnectionFactory.createConnection(conf)) {
127+
for (DataBlockEncoding encoding : DataBlockEncoding.values()) {
128+
testReverseScanWithDBE(connection, encoding, family);
129+
}
130+
}
131+
}
132+
133+
private void testReverseScanWithDBE(Connection conn, DataBlockEncoding encoding, byte[] family)
134+
throws IOException {
135+
LOG.info("Running test with DBE={}", encoding);
136+
TableName tableName = TableName.valueOf(TEST_NAME.getMethodName() + "-" + encoding);
137+
TEST_UTIL.createTable(TableDescriptorBuilder.newBuilder(tableName)
138+
.setColumnFamily(
139+
ColumnFamilyDescriptorBuilder.newBuilder(family).setDataBlockEncoding(encoding).build())
140+
.build(), null);
141+
142+
Table table = conn.getTable(tableName);
143+
144+
int maxRows = 10;
145+
byte[] val1 = new byte[10];
146+
byte[] val2 = new byte[10];
147+
Bytes.random(val1);
148+
Bytes.random(val2);
149+
150+
for (int i = 0; i < maxRows; i++) {
151+
if (i == maxRows / 2) {
152+
TEST_UTIL.flush(tableName);
153+
}
154+
table.put(new Put(Bytes.toBytes(i)).addColumn(family, Bytes.toBytes(1), val1)
155+
.addColumn(family, Bytes.toBytes(2), val2).setTTL(600_000));
156+
}
157+
158+
TEST_UTIL.flush(table.getName());
159+
160+
Scan scan = new Scan();
161+
scan.setReversed(true);
162+
163+
try (ResultScanner scanner = table.getScanner(scan)) {
164+
for (int i = maxRows - 1; i >= 0; i--) {
165+
Result row = scanner.next();
166+
assertEquals(2, row.size());
167+
168+
Cell cell1 = row.getColumnLatestCell(family, Bytes.toBytes(1));
169+
assertTrue(CellUtil.matchingRows(cell1, Bytes.toBytes(i)));
170+
assertTrue(CellUtil.matchingValue(cell1, val1));
171+
172+
Cell cell2 = row.getColumnLatestCell(family, Bytes.toBytes(2));
173+
assertTrue(CellUtil.matchingRows(cell2, Bytes.toBytes(i)));
174+
assertTrue(CellUtil.matchingValue(cell2, val2));
175+
}
176+
}
177+
178+
}
179+
107180
@Test
108181
public void testTags() throws Exception {
109182
Table table = null;

0 commit comments

Comments
 (0)