[ 
https://issues.apache.org/jira/browse/GEODE-8864?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17283318#comment-17283318
 ] 

ASF GitHub Bot commented on GEODE-8864:
---------------------------------------

jhutchison commented on a change in pull request #5954:
URL: https://github.com/apache/geode/pull/5954#discussion_r574772775



##########
File path: 
geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisHash.java
##########
@@ -203,49 +261,142 @@ 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()) {
+  public Pair<BigInteger, List<Object>> hscan(UUID clientID, Pattern 
matchPattern,
+      int count,
+      BigInteger cursorParameter) {
+
+    int startCursor = cursorParameter.intValue();
+
+    System.out.println("hscan receiving startCursor: " + startCursor);
+
+    List<ByteArrayWrapper> keysForScan = getSnapShotOfKeySet(clientID);
+
+    keysForScan = keysForScan.subList(startCursor, keysForScan.size());
+    Map<ByteArrayWrapper, ByteArrayWrapper> dataForKeySnapShot = 
getDataForKeys(keysForScan);
+
+
+    List<Object> resultList =
+        getResultList(matchPattern, count, dataForKeySnapShot);
+
+    int indexOfLast = resultList.size() - 1;
+    int numberOfIterationsCompleted = 
Integer.parseInt(resultList.get(indexOfLast).toString());
+    resultList.remove(indexOfLast);
+
+
+    BigInteger returnCursorValue =
+        getCursorValueToReturn(count, startCursor, 
numberOfIterationsCompleted);
+
+    if (returnCursorValue.intValue() == 0) {
+      removeHSCANSnapshot(clientID);
+    }
+
+    System.out.println("hscan returning Cursor: " + returnCursorValue);
+
+    // returnCursorValue = new BigInteger(String.valueOf(0));
+
+    return new ImmutablePair<>(returnCursorValue, resultList);
+  }
+
+  private void removeHSCANSnapshot(UUID clientID) {
+    this.hScanSnapShots.remove(clientID);
+    this.hScanSnapShotCreationTimes.remove(clientID);
+
+    if (this.hScanSnapShots.isEmpty()) {
+      shutDownHscanSnapshotScheduledRemoval();
+    }
+  }
+
+  private List<Object> getResultList(Pattern matchPattern, int count,
+      Map<ByteArrayWrapper, ByteArrayWrapper> dataForKeySnapShot) {
+
+    int currentCursor = 0;
+    List<Object> resultList = new ArrayList<>();
+
+    for (Map.Entry<ByteArrayWrapper, ByteArrayWrapper> entry : 
dataForKeySnapShot.entrySet()) {
+
+      if (count == currentCursor) {
+        break;
+      }
+
+      currentCursor++;
+
       ByteArrayWrapper key = entry.getKey();
       ByteArrayWrapper value = entry.getValue();
-      i++;
-      if (beforeCursor.compareTo(cursor) < 0) {
-        beforeCursor = beforeCursor.add(new BigInteger("1"));
-        continue;
-      }
 
       if (matchPattern != null) {
-        if (matchPattern.matcher(key.toString()).matches()) {
-          returnList.add(key);
-          returnList.add(value);
-          numElements++;
-        }
+        addMatches(matchPattern, resultList, key, value);

Review comment:
       done

##########
File path: 
geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisHash.java
##########
@@ -203,49 +261,142 @@ 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()) {
+  public Pair<BigInteger, List<Object>> hscan(UUID clientID, Pattern 
matchPattern,
+      int count,
+      BigInteger cursorParameter) {
+
+    int startCursor = cursorParameter.intValue();
+
+    System.out.println("hscan receiving startCursor: " + startCursor);
+
+    List<ByteArrayWrapper> keysForScan = getSnapShotOfKeySet(clientID);
+
+    keysForScan = keysForScan.subList(startCursor, keysForScan.size());
+    Map<ByteArrayWrapper, ByteArrayWrapper> dataForKeySnapShot = 
getDataForKeys(keysForScan);
+
+
+    List<Object> resultList =
+        getResultList(matchPattern, count, dataForKeySnapShot);
+
+    int indexOfLast = resultList.size() - 1;
+    int numberOfIterationsCompleted = 
Integer.parseInt(resultList.get(indexOfLast).toString());
+    resultList.remove(indexOfLast);
+
+
+    BigInteger returnCursorValue =
+        getCursorValueToReturn(count, startCursor, 
numberOfIterationsCompleted);
+
+    if (returnCursorValue.intValue() == 0) {
+      removeHSCANSnapshot(clientID);
+    }
+
+    System.out.println("hscan returning Cursor: " + returnCursorValue);
+
+    // returnCursorValue = new BigInteger(String.valueOf(0));
+
+    return new ImmutablePair<>(returnCursorValue, resultList);
+  }
+
+  private void removeHSCANSnapshot(UUID clientID) {
+    this.hScanSnapShots.remove(clientID);
+    this.hScanSnapShotCreationTimes.remove(clientID);
+
+    if (this.hScanSnapShots.isEmpty()) {
+      shutDownHscanSnapshotScheduledRemoval();
+    }
+  }
+
+  private List<Object> getResultList(Pattern matchPattern, int count,
+      Map<ByteArrayWrapper, ByteArrayWrapper> dataForKeySnapShot) {
+
+    int currentCursor = 0;
+    List<Object> resultList = new ArrayList<>();
+
+    for (Map.Entry<ByteArrayWrapper, ByteArrayWrapper> entry : 
dataForKeySnapShot.entrySet()) {
+
+      if (count == currentCursor) {
+        break;
+      }
+
+      currentCursor++;
+
       ByteArrayWrapper key = entry.getKey();
       ByteArrayWrapper value = entry.getValue();
-      i++;
-      if (beforeCursor.compareTo(cursor) < 0) {
-        beforeCursor = beforeCursor.add(new BigInteger("1"));
-        continue;
-      }
 
       if (matchPattern != null) {
-        if (matchPattern.matcher(key.toString()).matches()) {
-          returnList.add(key);
-          returnList.add(value);
-          numElements++;
-        }
+        addMatches(matchPattern, resultList, key, value);
       } else {
-        returnList.add(key);
-        returnList.add(value);
-        numElements++;
+        resultList.add(key);
+        resultList.add(value);
       }
+    }
+    resultList.add(new 
ByteArrayWrapper(String.valueOf(currentCursor).getBytes()));
+    return resultList;
+  }
 
-      if (numElements == count) {
-        break;
-      }
+  private void addMatches(Pattern matchPattern, List<Object> returnList,
+      ByteArrayWrapper key,
+      ByteArrayWrapper value) {
+    if (matchPattern.matcher(key.toString()).matches()) {
+      returnList.add(key);
+      returnList.add(value);
     }
+  }
 
-    Pair<BigInteger, List<Object>> scanResult;
-    if (i >= size - 1) {
-      scanResult = new ImmutablePair<>(new BigInteger("0"), returnList);
-    } else {
-      scanResult = new ImmutablePair<>(new BigInteger(String.valueOf(i + 1)), 
returnList);
+  @SuppressWarnings("unchecked")
+  private Map<ByteArrayWrapper, ByteArrayWrapper> getDataForKeys(
+      List<ByteArrayWrapper> keysForScan) {
+    Map<ByteArrayWrapper, ByteArrayWrapper> dataMap = new HashMap<>();
+
+    keysForScan.forEach(key -> {
+      ByteArrayWrapper value = this.hash.get(key);
+      dataMap.put(key, value);
+    });
+
+    return dataMap;
+  }
+
+  // either increment the cursor by the num,ber iterations we did, or
+  // if we're at the end, we return 0
+  // numberOfIterations < count is assumed, is ther a better way?
+
+  private BigInteger getCursorValueToReturn(int count, int startCursor,
+      int numberOfIterationsCompleted) {
+
+    if (numberOfIterationsCompleted < count) {
+      return BigInteger.valueOf(0);

Review comment:
       done




----------------------------------------------------------------
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:
us...@infra.apache.org


> finish implementation of Redis HScan Command
> --------------------------------------------
>
>                 Key: GEODE-8864
>                 URL: https://issues.apache.org/jira/browse/GEODE-8864
>             Project: Geode
>          Issue Type: New Feature
>          Components: redis
>            Reporter: John Hutchison
>            Priority: Major
>              Labels: pull-request-available
>




--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to