This is an automated email from the ASF dual-hosted git repository.

dschneider pushed a commit to branch more-string-work
in repository https://gitbox.apache.org/repos/asf/geode.git


The following commit(s) were added to refs/heads/more-string-work by this push:
     new 36193eb  CommandFunction now supports bitcount
36193eb is described below

commit 36193eb18b4e52ea959b81bc344a2775923533a8
Author: Darrel Schneider <[email protected]>
AuthorDate: Thu May 28 23:55:11 2020 -0700

    CommandFunction now supports bitcount
---
 .../redis/internal/executor/CommandFunction.java   |  11 +
 .../internal/executor/string/BitCountExecutor.java |  64 +----
 .../internal/executor/string/RedisString.java      | 292 +++++++++++++++++++++
 .../executor/string/RedisStringCommands.java       |   4 +
 .../RedisStringCommandsFunctionExecutor.java       |  11 +
 .../executor/string/RedisStringInRegion.java       |  20 ++
 6 files changed, 352 insertions(+), 50 deletions(-)

diff --git 
a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/CommandFunction.java
 
b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/CommandFunction.java
index 9be9e19..1dc5aef 100644
--- 
a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/CommandFunction.java
+++ 
b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/CommandFunction.java
@@ -126,6 +126,17 @@ public class CommandFunction extends 
SingleResultRedisFunction {
         callable = () -> new RedisStringInRegion(localRegion).getrange(key, 
start, end);
         break;
       }
+      case BITCOUNT: {
+        Object[] argArgs = (Object[]) args[1];
+        if (argArgs == null) {
+          callable = () -> new RedisStringInRegion(localRegion).bitcount(key);
+        } else {
+          int start = (int) argArgs[0];
+          int end = (int) argArgs[1];
+          callable = () -> new RedisStringInRegion(localRegion).bitcount(key, 
start, end);
+        }
+        break;
+      }
       case INCR:
         callable = () -> new RedisStringInRegion(localRegion).incr(key);
         break;
diff --git 
a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/BitCountExecutor.java
 
b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/BitCountExecutor.java
index a5be9dc..e8a8f61 100755
--- 
a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/BitCountExecutor.java
+++ 
b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/BitCountExecutor.java
@@ -38,63 +38,27 @@ public class BitCountExecutor extends StringExecutor {
 
     ByteArrayWrapper key = command.getKey();
     RedisStringCommands stringCommands = getRedisStringCommands(context);
-    ByteArrayWrapper wrapper = stringCommands.get(key);
-    if (wrapper == null) {
-      
command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), 0));
-      return;
-    }
-    byte[] value = wrapper.toBytes();
-
-    long startL = 0;
-    long endL = value.length - 1;
+    long result;
 
     if (commandElems.size() == 4) {
+      int start;
+      int end;
       try {
-        startL = Coder.bytesToLong(commandElems.get(2));
-        endL = Coder.bytesToLong(commandElems.get(3));
+        start = Math.toIntExact(Coder.bytesToLong(commandElems.get(2)));
+        end = Math.toIntExact(Coder.bytesToLong(commandElems.get(3)));
       } catch (NumberFormatException e) {
         
command.setResponse(Coder.getErrorResponse(context.getByteBufAllocator(), 
ERROR_NOT_INT));
         return;
+      } catch (ArithmeticException ex) {
+        command.setResponse(
+            Coder.getErrorResponse(context.getByteBufAllocator(),
+                RedisConstants.ERROR_OUT_OF_RANGE));
+        return;
       }
+      result = stringCommands.bitcount(key, start, end);
+    } else {
+      result = stringCommands.bitcount(key);
     }
-    if (startL > Integer.MAX_VALUE || endL > Integer.MAX_VALUE) {
-      command.setResponse(
-          Coder.getErrorResponse(context.getByteBufAllocator(), 
RedisConstants.ERROR_OUT_OF_RANGE));
-      return;
-    }
-
-    int start = (int) startL;
-    int end = (int) endL;
-    if (start < 0) {
-      start += value.length;
-    }
-    if (end < 0) {
-      end += value.length;
-    }
-
-    if (start < 0) {
-      start = 0;
-    }
-    if (end < 0) {
-      end = 0;
-    }
-
-    if (end > value.length - 1) {
-      end = value.length - 1;
-    }
-
-    if (end < start || start >= value.length) {
-      
command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), 0));
-      return;
-    }
-
-    long setBits = 0;
-    for (int j = start; j <= end; j++) {
-      setBits += Integer.bitCount(0xFF & value[j]); // 0xFF keeps same bit 
sequence as the byte as
-    }
-    // opposed to keeping the same value
-
-    
command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), 
setBits));
+    
command.setResponse(Coder.getIntegerResponse(context.getByteBufAllocator(), 
result));
   }
-
 }
diff --git 
a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisString.java
 
b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisString.java
index 687d401..0311d13 100644
--- 
a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisString.java
+++ 
b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisString.java
@@ -159,6 +159,298 @@ public class RedisString extends AbstractRedisData {
     }
   }
 
+  public long bitcount(int start, int end) {
+    if (start < 0) {
+      start += value.length();
+    }
+    if (end < 0) {
+      end += value.length();
+    }
+
+    if (start < 0) {
+      start = 0;
+    }
+    if (end < 0) {
+      end = 0;
+    }
+
+    if (end > value.length() - 1) {
+      end = value.length() - 1;
+    }
+
+    if (end < start || start >= value.length()) {
+      return 0;
+    }
+
+    long setBits = 0;
+    for (int j = start; j <= end; j++) {
+      setBits += bitcountTable[0xFF & value.toBytes()[j]];
+    }
+    return setBits;
+  }
+
+  public long bitcount() {
+    return bitcount(0, value.length() - 1);
+  }
+
+  private static final byte[] bitcountTable = {
+      0, // 0x0
+      1, // 0x1
+      1, // 0x2
+      2, // 0x3
+      1, // 0x4
+      2, // 0x5
+      2, // 0x6
+      3, // 0x7
+      1, // 0x8
+      2, // 0x9
+      2, // 0xa
+      3, // 0xb
+      2, // 0xc
+      3, // 0xd
+      3, // 0xe
+      4, // 0xf
+      1, // 0x10
+      2, // 0x11
+      2, // 0x12
+      3, // 0x13
+      2, // 0x14
+      3, // 0x15
+      3, // 0x16
+      4, // 0x17
+      2, // 0x18
+      3, // 0x19
+      3, // 0x1a
+      4, // 0x1b
+      3, // 0x1c
+      4, // 0x1d
+      4, // 0x1e
+      5, // 0x1f
+      1, // 0x20
+      2, // 0x21
+      2, // 0x22
+      3, // 0x23
+      2, // 0x24
+      3, // 0x25
+      3, // 0x26
+      4, // 0x27
+      2, // 0x28
+      3, // 0x29
+      3, // 0x2a
+      4, // 0x2b
+      3, // 0x2c
+      4, // 0x2d
+      4, // 0x2e
+      5, // 0x2f
+      2, // 0x30
+      3, // 0x31
+      3, // 0x32
+      4, // 0x33
+      3, // 0x34
+      4, // 0x35
+      4, // 0x36
+      5, // 0x37
+      3, // 0x38
+      4, // 0x39
+      4, // 0x3a
+      5, // 0x3b
+      4, // 0x3c
+      5, // 0x3d
+      5, // 0x3e
+      6, // 0x3f
+      1, // 0x40
+      2, // 0x41
+      2, // 0x42
+      3, // 0x43
+      2, // 0x44
+      3, // 0x45
+      3, // 0x46
+      4, // 0x47
+      2, // 0x48
+      3, // 0x49
+      3, // 0x4a
+      4, // 0x4b
+      3, // 0x4c
+      4, // 0x4d
+      4, // 0x4e
+      5, // 0x4f
+      2, // 0x50
+      3, // 0x51
+      3, // 0x52
+      4, // 0x53
+      3, // 0x54
+      4, // 0x55
+      4, // 0x56
+      5, // 0x57
+      3, // 0x58
+      4, // 0x59
+      4, // 0x5a
+      5, // 0x5b
+      4, // 0x5c
+      5, // 0x5d
+      5, // 0x5e
+      6, // 0x5f
+      2, // 0x60
+      3, // 0x61
+      3, // 0x62
+      4, // 0x63
+      3, // 0x64
+      4, // 0x65
+      4, // 0x66
+      5, // 0x67
+      3, // 0x68
+      4, // 0x69
+      4, // 0x6a
+      5, // 0x6b
+      4, // 0x6c
+      5, // 0x6d
+      5, // 0x6e
+      6, // 0x6f
+      3, // 0x70
+      4, // 0x71
+      4, // 0x72
+      5, // 0x73
+      4, // 0x74
+      5, // 0x75
+      5, // 0x76
+      6, // 0x77
+      4, // 0x78
+      5, // 0x79
+      5, // 0x7a
+      6, // 0x7b
+      5, // 0x7c
+      6, // 0x7d
+      6, // 0x7e
+      7, // 0x7f
+      1, // 0x80
+      2, // 0x81
+      2, // 0x82
+      3, // 0x83
+      2, // 0x84
+      3, // 0x85
+      3, // 0x86
+      4, // 0x87
+      2, // 0x88
+      3, // 0x89
+      3, // 0x8a
+      4, // 0x8b
+      3, // 0x8c
+      4, // 0x8d
+      4, // 0x8e
+      5, // 0x8f
+      2, // 0x90
+      3, // 0x91
+      3, // 0x92
+      4, // 0x93
+      3, // 0x94
+      4, // 0x95
+      4, // 0x96
+      5, // 0x97
+      3, // 0x98
+      4, // 0x99
+      4, // 0x9a
+      5, // 0x9b
+      4, // 0x9c
+      5, // 0x9d
+      5, // 0x9e
+      6, // 0x9f
+      2, // 0xa0
+      3, // 0xa1
+      3, // 0xa2
+      4, // 0xa3
+      3, // 0xa4
+      4, // 0xa5
+      4, // 0xa6
+      5, // 0xa7
+      3, // 0xa8
+      4, // 0xa9
+      4, // 0xaa
+      5, // 0xab
+      4, // 0xac
+      5, // 0xad
+      5, // 0xae
+      6, // 0xaf
+      3, // 0xb0
+      4, // 0xb1
+      4, // 0xb2
+      5, // 0xb3
+      4, // 0xb4
+      5, // 0xb5
+      5, // 0xb6
+      6, // 0xb7
+      4, // 0xb8
+      5, // 0xb9
+      5, // 0xba
+      6, // 0xbb
+      5, // 0xbc
+      6, // 0xbd
+      6, // 0xbe
+      7, // 0xbf
+      2, // 0xc0
+      3, // 0xc1
+      3, // 0xc2
+      4, // 0xc3
+      3, // 0xc4
+      4, // 0xc5
+      4, // 0xc6
+      5, // 0xc7
+      3, // 0xc8
+      4, // 0xc9
+      4, // 0xca
+      5, // 0xcb
+      4, // 0xcc
+      5, // 0xcd
+      5, // 0xce
+      6, // 0xcf
+      3, // 0xd0
+      4, // 0xd1
+      4, // 0xd2
+      5, // 0xd3
+      4, // 0xd4
+      5, // 0xd5
+      5, // 0xd6
+      6, // 0xd7
+      4, // 0xd8
+      5, // 0xd9
+      5, // 0xda
+      6, // 0xdb
+      5, // 0xdc
+      6, // 0xdd
+      6, // 0xde
+      7, // 0xdf
+      3, // 0xe0
+      4, // 0xe1
+      4, // 0xe2
+      5, // 0xe3
+      4, // 0xe4
+      5, // 0xe5
+      5, // 0xe6
+      6, // 0xe7
+      4, // 0xe8
+      5, // 0xe9
+      5, // 0xea
+      6, // 0xeb
+      5, // 0xec
+      6, // 0xed
+      6, // 0xee
+      7, // 0xef
+      4, // 0xf0
+      5, // 0xf1
+      5, // 0xf2
+      6, // 0xf3
+      5, // 0xf4
+      6, // 0xf5
+      6, // 0xf6
+      7, // 0xf7
+      5, // 0xf8
+      6, // 0xf9
+      6, // 0xfa
+      7, // 0xfb
+      6, // 0xfc
+      7, // 0xfd
+      7, // 0xfe
+      8 // 0xff
+  };
 
 
   @Override
diff --git 
a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisStringCommands.java
 
b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisStringCommands.java
index 6266cb0..5438cc5 100644
--- 
a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisStringCommands.java
+++ 
b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisStringCommands.java
@@ -34,4 +34,8 @@ public interface RedisStringCommands {
   long decrby(ByteArrayWrapper key, long decrement);
 
   ByteArrayWrapper getrange(ByteArrayWrapper key, long start, long end);
+
+  long bitcount(ByteArrayWrapper key, int start, int end);
+
+  long bitcount(ByteArrayWrapper key);
 }
diff --git 
a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisStringCommandsFunctionExecutor.java
 
b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisStringCommandsFunctionExecutor.java
index 426f40c..4eed8d0 100644
--- 
a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisStringCommandsFunctionExecutor.java
+++ 
b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisStringCommandsFunctionExecutor.java
@@ -15,6 +15,7 @@
 package org.apache.geode.redis.internal.executor.string;
 
 import static org.apache.geode.redis.internal.RedisCommandType.APPEND;
+import static org.apache.geode.redis.internal.RedisCommandType.BITCOUNT;
 import static org.apache.geode.redis.internal.RedisCommandType.DECR;
 import static org.apache.geode.redis.internal.RedisCommandType.DECRBY;
 import static org.apache.geode.redis.internal.RedisCommandType.GET;
@@ -80,4 +81,14 @@ public class RedisStringCommandsFunctionExecutor implements 
RedisStringCommands
   public ByteArrayWrapper getrange(ByteArrayWrapper key, long start, long end) 
{
     return CommandFunction.execute(GETRANGE, key, new Object[] {start, end}, 
region);
   }
+
+  @Override
+  public long bitcount(ByteArrayWrapper key, int start, int end) {
+    return CommandFunction.execute(BITCOUNT, key, new Object[] {start, end}, 
region);
+  }
+
+  @Override
+  public long bitcount(ByteArrayWrapper key) {
+    return CommandFunction.execute(BITCOUNT, key, null, region);
+  }
 }
diff --git 
a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisStringInRegion.java
 
b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisStringInRegion.java
index d6e1375..ddc355d 100644
--- 
a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisStringInRegion.java
+++ 
b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/RedisStringInRegion.java
@@ -157,6 +157,26 @@ public class RedisStringInRegion extends RedisKeyInRegion 
implements RedisString
     return redisString.getrange(start, end);
   }
 
+  @Override
+  public long bitcount(ByteArrayWrapper key, int start, int end) {
+    RedisString redisString = getRedisString(key);
+
+    if (redisString == null) {
+      return 0;
+    }
+    return redisString.bitcount(start, end);
+  }
+
+  @Override
+  public long bitcount(ByteArrayWrapper key) {
+    RedisString redisString = getRedisString(key);
+
+    if (redisString == null) {
+      return 0;
+    }
+    return redisString.bitcount();
+  }
+
   private boolean setnx(ByteArrayWrapper key, ByteArrayWrapper value, 
SetOptions options) {
     if (getRedisData(key) != null) {
       return false;

Reply via email to