Skip to content

Commit e72ba8b

Browse files
authored
[close #540] rawkv: fix scan return empty set while exist empty key (#541) (#548)
* rawkv: cherry-pick fix-scan-empty-key Signed-off-by: iosmanthus <myosmanthustree@gmail.com> * rawkv: fix missing parameters Signed-off-by: iosmanthus <myosmanthustree@gmail.com>
1 parent fdb67bc commit e72ba8b

File tree

3 files changed

+69
-11
lines changed

3 files changed

+69
-11
lines changed

src/main/java/org/tikv/common/operation/iterator/RawScanIterator.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.tikv.kvproto.Kvrpcpb;
2929

3030
public class RawScanIterator extends ScanIterator {
31+
3132
private final BackOffer scanBackOffer;
3233

3334
public RawScanIterator(
@@ -65,11 +66,12 @@ TiRegion loadCurrentRegionToCache() throws GrpcException {
6566
}
6667
}
6768

68-
private boolean notEndOfScan() {
69-
return limit > 0
70-
&& !(processingLastBatch
71-
&& (index >= currentCache.size()
72-
|| Key.toRawKey(currentCache.get(index).getKey()).compareTo(endKey) >= 0));
69+
private boolean endOfScan() {
70+
if (!processingLastBatch) {
71+
return false;
72+
}
73+
ByteString lastKey = currentCache.get(index).getKey();
74+
return !lastKey.isEmpty() && Key.toRawKey(lastKey).compareTo(endKey) >= 0;
7375
}
7476

7577
boolean isCacheDrained() {
@@ -88,7 +90,7 @@ public boolean hasNext() {
8890
return false;
8991
}
9092
}
91-
return notEndOfScan();
93+
return !endOfScan();
9294
}
9395

9496
private Kvrpcpb.KvPair getCurrent() {

src/main/java/org/tikv/common/operation/iterator/ScanIterator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ boolean cacheLoadFails() {
8888
Key lastKey = Key.EMPTY;
8989
// Session should be single-threaded itself
9090
// so that we don't worry about conf change in the middle
91-
// of a transaction. Otherwise below code might lose data
91+
// of a transaction. Otherwise, below code might lose data
9292
if (currentCache.size() < limit) {
9393
startKey = curRegionEndKey;
9494
lastKey = Key.toRawKey(curRegionEndKey);

src/test/java/org/tikv/raw/RawKVClientTest.java

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,32 @@
11
package org.tikv.raw;
22

3-
import static org.junit.Assert.*;
3+
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.assertNotNull;
5+
import static org.junit.Assert.assertNull;
6+
import static org.junit.Assert.assertTrue;
47

8+
import com.google.common.collect.ImmutableList;
59
import com.google.protobuf.ByteString;
610
import java.io.IOException;
7-
import java.util.*;
8-
import java.util.concurrent.*;
11+
import java.util.ArrayList;
12+
import java.util.Arrays;
13+
import java.util.Comparator;
14+
import java.util.HashMap;
15+
import java.util.List;
16+
import java.util.Locale;
17+
import java.util.Map;
18+
import java.util.Random;
19+
import java.util.TreeMap;
20+
import java.util.concurrent.ExecutionException;
21+
import java.util.concurrent.ExecutorCompletionService;
22+
import java.util.concurrent.ExecutorService;
23+
import java.util.concurrent.Executors;
24+
import java.util.concurrent.TimeUnit;
25+
import java.util.concurrent.TimeoutException;
926
import java.util.stream.Collectors;
1027
import org.apache.commons.lang3.RandomStringUtils;
1128
import org.junit.After;
29+
import org.junit.Assert;
1230
import org.junit.Before;
1331
import org.junit.Test;
1432
import org.slf4j.Logger;
@@ -28,6 +46,7 @@
2846
import org.tikv.kvproto.Kvrpcpb;
2947

3048
public class RawKVClientTest extends BaseRawKVTest {
49+
3150
private static final String RAW_PREFIX = "raw_\u0001_";
3251
private static final int KEY_POOL_SIZE = 1000000;
3352
private static final int TEST_CASES = 10000;
@@ -360,6 +379,40 @@ private List<Kvrpcpb.KvPair> rawKeys() {
360379
return client.scan(RAW_START_KEY, RAW_END_KEY);
361380
}
362381

382+
@Test
383+
public void scanTestForIssue540() {
384+
ByteString splitKeyA = ByteString.copyFromUtf8("splitKeyA");
385+
ByteString splitKeyB = ByteString.copyFromUtf8("splitKeyB");
386+
int splitRegionBackoffMS = 12000;
387+
int scatterRegionBackoffMS = 30000;
388+
int scatterWaitMS = 300000;
389+
session.splitRegionAndScatter(
390+
ImmutableList.of(splitKeyA.toByteArray(), splitKeyB.toByteArray()),
391+
splitRegionBackoffMS,
392+
scatterRegionBackoffMS,
393+
scatterWaitMS);
394+
client.deleteRange(ByteString.EMPTY, ByteString.EMPTY);
395+
396+
client.put(ByteString.EMPTY, ByteString.EMPTY);
397+
client.put(splitKeyA, ByteString.EMPTY);
398+
Assert.assertEquals(0, client.scan(ByteString.EMPTY, 0).size());
399+
Assert.assertEquals(1, client.scan(ByteString.EMPTY, 1).size());
400+
Assert.assertEquals(2, client.scan(ByteString.EMPTY, 2).size());
401+
Assert.assertEquals(2, client.scan(ByteString.EMPTY, 3).size());
402+
403+
client.deleteRange(ByteString.EMPTY, ByteString.EMPTY);
404+
405+
client.put(ByteString.EMPTY, ByteString.EMPTY);
406+
client.put(splitKeyA, ByteString.EMPTY);
407+
client.put(splitKeyA.concat(ByteString.copyFromUtf8("1")), ByteString.EMPTY);
408+
client.put(splitKeyA.concat(ByteString.copyFromUtf8("2")), ByteString.EMPTY);
409+
client.put(splitKeyA.concat(ByteString.copyFromUtf8("3")), ByteString.EMPTY);
410+
client.put(splitKeyB.concat(ByteString.copyFromUtf8("1")), ByteString.EMPTY);
411+
Assert.assertEquals(6, client.scan(ByteString.EMPTY, 7).size());
412+
Assert.assertEquals(0, client.scan(ByteString.EMPTY, -1).size());
413+
client.deleteRange(ByteString.EMPTY, ByteString.EMPTY);
414+
}
415+
363416
@Test
364417
public void validate() {
365418
baseTest(100, 100, 100, 100, false, false, false, false, false);
@@ -449,7 +502,9 @@ private void prepare() {
449502
int i = cnt;
450503
completionService.submit(
451504
() -> {
452-
for (int j = 0; j < base; j++) checkDelete(remainingKeys.get(i * base + j).getKey());
505+
for (int j = 0; j < base; j++) {
506+
checkDelete(remainingKeys.get(i * base + j).getKey());
507+
}
453508
return null;
454509
});
455510
}
@@ -942,6 +997,7 @@ private static ByteString rawValue(String value) {
942997
}
943998

944999
private static class ByteStringComparator implements Comparator<ByteString> {
1000+
9451001
@Override
9461002
public int compare(ByteString startKey, ByteString endKey) {
9471003
return FastByteComparisons.compareTo(startKey.toByteArray(), endKey.toByteArray());

0 commit comments

Comments
 (0)