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
commit a9a3573e20baf4135056778557ce0b12ad039568 Author: Darrel Schneider <[email protected]> AuthorDate: Thu May 28 22:55:14 2020 -0700 added getrange to CommandFunction --- .../redis/internal/executor/CommandFunction.java | 7 ++++ .../internal/executor/string/GetRangeExecutor.java | 36 ++++--------------- .../internal/executor/string/RedisString.java | 40 ++++++++++++++++++++++ .../executor/string/RedisStringCommands.java | 2 ++ .../RedisStringCommandsFunctionExecutor.java | 6 ++++ .../executor/string/RedisStringInRegion.java | 10 ++++++ 6 files changed, 71 insertions(+), 30 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 fc3072b..9be9e19 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 @@ -119,6 +119,13 @@ public class CommandFunction extends SingleResultRedisFunction { callable = () -> new RedisStringInRegion(localRegion).getset(key, value); break; } + case GETRANGE: { + Object[] argArgs = (Object[]) args[1]; + long start = (long) argArgs[0]; + long end = (long) argArgs[1]; + callable = () -> new RedisStringInRegion(localRegion).getrange(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/GetRangeExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/GetRangeExecutor.java index 123d558..bf81ae2 100755 --- a/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/GetRangeExecutor.java +++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/executor/string/GetRangeExecutor.java @@ -14,7 +14,6 @@ */ package org.apache.geode.redis.internal.executor.string; -import java.util.Arrays; import java.util.List; import org.apache.geode.redis.internal.ByteArrayWrapper; @@ -53,38 +52,15 @@ public class GetRangeExecutor extends StringExecutor { RedisStringCommands stringCommands = getRedisStringCommands(context); ByteArrayWrapper key = command.getKey(); - ByteArrayWrapper valueWrapper = stringCommands.get(key); - if (valueWrapper == null) { - command.setResponse(Coder.getEmptyStringResponse(context.getByteBufAllocator())); - return; - } + ByteArrayWrapper returnRange = stringCommands.getrange(key, start, end); - byte[] value = valueWrapper.toBytes(); - int length = value.length; - - start = getBoundedStartIndex(start, length); - end = getBoundedEndIndex(end, length); - - /* - * Can't 'start' at end of value - */ - if (start > end || start == length) { - command.setResponse(Coder.getEmptyStringResponse(context.getByteBufAllocator())); - return; - } - /* - * 1 is added to end because the end in copyOfRange is exclusive but in Redis it is inclusive - */ - if (end != length) { - end++; - } - byte[] returnRange = Arrays.copyOfRange(value, (int) start, (int) end); - if (returnRange == null || returnRange.length == 0) { + if (returnRange == null) { command.setResponse(Coder.getNilResponse(context.getByteBufAllocator())); - return; + } else if (returnRange.length() == 0) { + command.setResponse(Coder.getEmptyStringResponse(context.getByteBufAllocator())); + } else { + respondBulkStrings(command, context, returnRange); } - - respondBulkStrings(command, context, returnRange); } } 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 234efae..687d401 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 @@ -18,6 +18,7 @@ package org.apache.geode.redis.internal.executor.string; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; +import java.util.Arrays; import org.apache.geode.DataSerializer; import org.apache.geode.cache.Region; @@ -121,6 +122,45 @@ public class RedisString extends AbstractRedisData { } } + public ByteArrayWrapper getrange(long start, long end) { + int length = value.length(); + int boundedStart = getBoundedStartIndex(start, length); + int boundedEnd = getBoundedEndIndex(end, length); + + /* + * Can't 'start' at end of value + */ + if (boundedStart > boundedEnd || boundedStart == length) { + return new ByteArrayWrapper(new byte[0]); + } + /* + * 1 is added to end because the end in copyOfRange is exclusive but in Redis it is inclusive + */ + if (boundedEnd != length) { + boundedEnd++; + } + byte[] returnRange = Arrays.copyOfRange(value.toBytes(), boundedStart, boundedEnd); + return new ByteArrayWrapper(returnRange); + } + + private int getBoundedStartIndex(long index, int size) { + if (index >= 0L) { + return (int) Math.min(index, size); + } else { + return (int) Math.max(index + size, 0); + } + } + + private int getBoundedEndIndex(long index, int size) { + if (index >= 0L) { + return (int) Math.min(index, size); + } else { + return (int) Math.max(index + size, -1); + } + } + + + @Override public void toData(DataOutput out) throws IOException { super.toData(out); 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 bfbf2ce..6266cb0 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 @@ -32,4 +32,6 @@ public interface RedisStringCommands { long incrby(ByteArrayWrapper key, long increment); long decrby(ByteArrayWrapper key, long decrement); + + ByteArrayWrapper getrange(ByteArrayWrapper key, long start, long end); } 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 4c1fdf9..426f40c 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 @@ -18,6 +18,7 @@ import static org.apache.geode.redis.internal.RedisCommandType.APPEND; 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; +import static org.apache.geode.redis.internal.RedisCommandType.GETRANGE; import static org.apache.geode.redis.internal.RedisCommandType.GETSET; import static org.apache.geode.redis.internal.RedisCommandType.INCR; import static org.apache.geode.redis.internal.RedisCommandType.INCRBY; @@ -74,4 +75,9 @@ public class RedisStringCommandsFunctionExecutor implements RedisStringCommands public long decrby(ByteArrayWrapper key, long decrement) { return CommandFunction.execute(DECRBY, key, decrement, region); } + + @Override + public ByteArrayWrapper getrange(ByteArrayWrapper key, long start, long end) { + return CommandFunction.execute(GETRANGE, key, new Object[] {start, end}, 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 49b40f7..d6e1375 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 @@ -147,6 +147,16 @@ public class RedisStringInRegion extends RedisKeyInRegion implements RedisString return redisString.decrby(region, key, decrement); } + @Override + public ByteArrayWrapper getrange(ByteArrayWrapper key, long start, long end) { + RedisString redisString = getRedisString(key); + + if (redisString == null) { + return new ByteArrayWrapper(new byte[0]); + } + return redisString.getrange(start, end); + } + private boolean setnx(ByteArrayWrapper key, ByteArrayWrapper value, SetOptions options) { if (getRedisData(key) != null) { return false;
