jhutchison commented on a change in pull request #5954:
URL: https://github.com/apache/geode/pull/5954#discussion_r577727315
##########
File path:
geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisHash.java
##########
@@ -203,49 +261,120 @@ public int hstrlen(ByteArrayWrapper field) {
return new ArrayList<>(hash.keySet());
}
- public Pair<BigInteger, List<Object>> hscan(Pattern matchPattern, int count,
BigInteger cursor) {
- List<Object> returnList = new ArrayList<Object>();
- int size = hash.size();
- BigInteger beforeCursor = new BigInteger("0");
- int numElements = 0;
- int i = -1;
- for (Map.Entry<ByteArrayWrapper, ByteArrayWrapper> entry :
hash.entrySet()) {
- ByteArrayWrapper key = entry.getKey();
- ByteArrayWrapper value = entry.getValue();
- i++;
- if (beforeCursor.compareTo(cursor) < 0) {
- beforeCursor = beforeCursor.add(new BigInteger("1"));
+ public Pair<BigInteger, List<Object>> hscan(UUID clientID, Pattern
matchPattern,
+ int count,
+ BigInteger cursorParameter) {
+
+ int startCursor = cursorParameter.intValue();
+
+ List<ByteArrayWrapper> keysToScan = getSnapShotOfKeySet(clientID);
+
+ List<Object> resultList =
+ getResultList(keysToScan, startCursor, count, matchPattern);
+
+ int indexOfLast = resultList.size() - 1;
+ int numberOfIterationsCompleted =
Integer.parseInt(resultList.get(indexOfLast).toString());
+ resultList.remove(indexOfLast);
+
+ int returnCursorValueAsInt =
+ getCursorValueToReturn(startCursor, numberOfIterationsCompleted,
keysToScan);
+
+ if (returnCursorValueAsInt == 0) {
+ removeHSCANSnapshot(clientID);
+ }
+ return new ImmutablePair<>(BigInteger.valueOf(returnCursorValueAsInt),
resultList);
+ }
+
+ private void removeHSCANSnapshot(UUID clientID) {
+ this.hScanSnapShots.remove(clientID);
+ this.hScanSnapShotCreationTimes.remove(clientID);
+
+ if (this.hScanSnapShots.isEmpty()) {
+ shutDownHscanSnapshotScheduledRemoval();
+ }
+ }
+
+ private List<Object> getResultList(List<ByteArrayWrapper> keysSnapShot,
+ int startCursor,
+ int count,
+ Pattern matchPattern) {
+
+ int indexOfKeys = 0;
+
+ List<Object> resultList = new ArrayList<>();
+
+ for (ByteArrayWrapper key : keysSnapShot) {
+
+ if (indexOfKeys < startCursor) {
+ indexOfKeys++;
+ continue;
+ }
+
+ indexOfKeys++;
+
+ ByteArrayWrapper value = hash.get(key);
+ if (value == null) {
continue;
}
if (matchPattern != null) {
if (matchPattern.matcher(key.toString()).matches()) {
- returnList.add(key);
- returnList.add(value);
- numElements++;
+ resultList.add(key);
+ resultList.add(value);
}
} else {
- returnList.add(key);
- returnList.add(value);
- numElements++;
+ resultList.add(key);
+ resultList.add(value);
}
- if (numElements == count) {
+ if ((indexOfKeys - startCursor) == count) {
Review comment:
As per Redis docs, the match is applied after the count of elements are
received. So if Matching parameter is passed in, then resultSize might not be
what we want, if we are mirroring native Redis. We could do it
differently...not sure if we need to mirror redis here?
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]