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;