This is an automated email from the ASF dual-hosted git repository.
ringles pushed a commit to branch
GEODE-9892-Create-Infrastructure-for-Redis-Lists
in repository https://gitbox.apache.org/repos/asf/geode.git
The following commit(s) were added to
refs/heads/GEODE-9892-Create-Infrastructure-for-Redis-Lists by this push:
new ec96801 Many radish tests working
ec96801 is described below
commit ec968015835ab98c3247cad58c3a4381654f9995
Author: Ray Ingles <[email protected]>
AuthorDate: Thu Jan 6 17:17:24 2022 -0500
Many radish tests working
---
.../redis/internal/commands/RedisCommandType.java | 8 +++
.../commands/executor/list/LPopExecutor.java | 70 ++++++++++++++++++++++
.../commands/executor/list/LPushExecutor.java | 43 +++++++++++++
.../geode/redis/internal/data/NullRedisList.java | 2 +-
.../internal/netty/ExecutionHandlerContext.java | 11 +++-
5 files changed, 132 insertions(+), 2 deletions(-)
diff --git
a/geode-for-redis/src/main/java/org/apache/geode/redis/internal/commands/RedisCommandType.java
b/geode-for-redis/src/main/java/org/apache/geode/redis/internal/commands/RedisCommandType.java
index fa53a4d..b2cd57e 100755
---
a/geode-for-redis/src/main/java/org/apache/geode/redis/internal/commands/RedisCommandType.java
+++
b/geode-for-redis/src/main/java/org/apache/geode/redis/internal/commands/RedisCommandType.java
@@ -76,6 +76,8 @@ import
org.apache.geode.redis.internal.commands.executor.key.RestoreExecutor;
import org.apache.geode.redis.internal.commands.executor.key.ScanExecutor;
import org.apache.geode.redis.internal.commands.executor.key.TTLExecutor;
import org.apache.geode.redis.internal.commands.executor.key.TypeExecutor;
+import org.apache.geode.redis.internal.commands.executor.list.LPopExecutor;
+import org.apache.geode.redis.internal.commands.executor.list.LPushExecutor;
import
org.apache.geode.redis.internal.commands.executor.pubsub.PsubscribeExecutor;
import org.apache.geode.redis.internal.commands.executor.pubsub.PubSubExecutor;
import
org.apache.geode.redis.internal.commands.executor.pubsub.PublishExecutor;
@@ -285,6 +287,12 @@ public enum RedisCommandType {
ZUNIONSTORE(new ZUnionStoreExecutor(), SUPPORTED,
new Parameter().min(4).flags(WRITE, DENYOOM, MOVABLEKEYS)),
+ /************** Lists *****************/
+
+ LPUSH(new LPushExecutor(), SUPPORTED, new Parameter().min(3).flags(WRITE,
DENYOOM, FAST)),
+ LPOP(new LPopExecutor(), SUPPORTED,
+ new Parameter().min(2).max(3, ERROR_SYNTAX).flags(WRITE, FAST)),
+
/************* Server *****************/
COMMAND(new COMMANDCommandExecutor(), SUPPORTED, new
Parameter().min(1).firstKey(0).flags(RANDOM,
LOADING, STALE)),
diff --git
a/geode-for-redis/src/main/java/org/apache/geode/redis/internal/commands/executor/list/LPopExecutor.java
b/geode-for-redis/src/main/java/org/apache/geode/redis/internal/commands/executor/list/LPopExecutor.java
new file mode 100755
index 0000000..447ae32
--- /dev/null
+++
b/geode-for-redis/src/main/java/org/apache/geode/redis/internal/commands/executor/list/LPopExecutor.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache
License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express
+ * or implied. See the License for the specific language governing permissions
and limitations under
+ * the License.
+ */
+package org.apache.geode.redis.internal.commands.executor.list;
+
+
+import static
org.apache.geode.redis.internal.RedisConstants.ERROR_VALUE_MUST_BE_POSITIVE;
+import static org.apache.geode.redis.internal.netty.Coder.bytesToLong;
+import static org.apache.geode.redis.internal.netty.Coder.narrowLongToInt;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.geode.cache.Region;
+import org.apache.geode.redis.internal.commands.Command;
+import org.apache.geode.redis.internal.commands.executor.CommandExecutor;
+import org.apache.geode.redis.internal.commands.executor.RedisResponse;
+import org.apache.geode.redis.internal.data.RedisData;
+import org.apache.geode.redis.internal.data.RedisKey;
+import org.apache.geode.redis.internal.netty.ExecutionHandlerContext;
+
+public class LPopExecutor implements CommandExecutor {
+
+ @Override
+ public RedisResponse executeCommand(Command command, ExecutionHandlerContext
context) {
+ List<byte[]> commandElems = command.getProcessedCommand();
+ boolean isCountPassed = false;
+ int popCount;
+
+ if (commandElems.size() == 3) {
+ isCountPassed = true;
+ try {
+ popCount = narrowLongToInt(bytesToLong(commandElems.get(2)));
+ } catch (NumberFormatException nex) {
+ return RedisResponse.error(ERROR_VALUE_MUST_BE_POSITIVE);
+ }
+ if (popCount < 0) {
+ return RedisResponse.error(ERROR_VALUE_MUST_BE_POSITIVE);
+ }
+ } else {
+ popCount = 1;
+ }
+
+ Region<RedisKey, RedisData> region = context.getRegion();
+ RedisKey key = command.getKey();
+ Collection<byte[]> popped = context.listLockedExecute(key, false,
+ list -> list.lpop(region, key, popCount));
+
+ if (popped.isEmpty() && !isCountPassed) {
+ return RedisResponse.nil();
+ }
+
+ if (!isCountPassed) {
+ return RedisResponse.bulkString(popped.iterator().next());
+ }
+
+ return RedisResponse.array(popped, true);
+ }
+}
diff --git
a/geode-for-redis/src/main/java/org/apache/geode/redis/internal/commands/executor/list/LPushExecutor.java
b/geode-for-redis/src/main/java/org/apache/geode/redis/internal/commands/executor/list/LPushExecutor.java
new file mode 100755
index 0000000..2449c2b
--- /dev/null
+++
b/geode-for-redis/src/main/java/org/apache/geode/redis/internal/commands/executor/list/LPushExecutor.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache
License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express
+ * or implied. See the License for the specific language governing permissions
and limitations under
+ * the License.
+ */
+package org.apache.geode.redis.internal.commands.executor.list;
+
+import org.apache.geode.cache.Region;
+import org.apache.geode.redis.internal.commands.Command;
+import org.apache.geode.redis.internal.commands.executor.CommandExecutor;
+import org.apache.geode.redis.internal.commands.executor.RedisResponse;
+import org.apache.geode.redis.internal.data.RedisData;
+import org.apache.geode.redis.internal.data.RedisKey;
+import org.apache.geode.redis.internal.netty.ExecutionHandlerContext;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class LPushExecutor implements CommandExecutor {
+
+ @Override
+ public RedisResponse executeCommand(Command command, ExecutionHandlerContext
context) {
+ List<byte[]> commandElements = command.getProcessedCommand();
+ Region<RedisKey, RedisData> region = context.getRegion();
+ RedisKey key = command.getKey();
+
+ List<byte[]> elementsToAdd = new ArrayList<>(commandElements.subList(2,
commandElements.size()));
+
+ long entriesAdded = context.listLockedExecute(key, false,
+ list -> list.lpush(elementsToAdd, region, key));
+
+ return RedisResponse.integer(entriesAdded);
+ }
+}
diff --git
a/geode-for-redis/src/main/java/org/apache/geode/redis/internal/data/NullRedisList.java
b/geode-for-redis/src/main/java/org/apache/geode/redis/internal/data/NullRedisList.java
index 55a4b74..306b019 100644
---
a/geode-for-redis/src/main/java/org/apache/geode/redis/internal/data/NullRedisList.java
+++
b/geode-for-redis/src/main/java/org/apache/geode/redis/internal/data/NullRedisList.java
@@ -43,7 +43,7 @@ class NullRedisList extends RedisList {
@Override
public Collection<byte[]> lpop(Region<RedisKey, RedisData> region, RedisKey
key, int popCount) {
- return emptyList();
+ return null;
}
@Override
diff --git
a/geode-for-redis/src/main/java/org/apache/geode/redis/internal/netty/ExecutionHandlerContext.java
b/geode-for-redis/src/main/java/org/apache/geode/redis/internal/netty/ExecutionHandlerContext.java
index 1011eb7..7c2de2c 100644
---
a/geode-for-redis/src/main/java/org/apache/geode/redis/internal/netty/ExecutionHandlerContext.java
+++
b/geode-for-redis/src/main/java/org/apache/geode/redis/internal/netty/ExecutionHandlerContext.java
@@ -57,6 +57,7 @@ import org.apache.geode.redis.internal.data.RedisDataType;
import org.apache.geode.redis.internal.data.RedisDataTypeMismatchException;
import org.apache.geode.redis.internal.data.RedisHash;
import org.apache.geode.redis.internal.data.RedisKey;
+import org.apache.geode.redis.internal.data.RedisList;
import org.apache.geode.redis.internal.data.RedisSet;
import org.apache.geode.redis.internal.data.RedisSortedSet;
import org.apache.geode.redis.internal.data.RedisString;
@@ -483,17 +484,25 @@ public class ExecutionHandlerContext extends
ChannelInboundHandlerAdapter {
return
getRegionProvider().getTypedRedisData(RedisDataType.REDIS_SORTED_SET, key,
updateStats);
}
-
public <R> R setLockedExecute(RedisKey key, boolean updateStats,
FailableFunction<RedisSet, R> function) {
return getRegionProvider().lockedExecute(key,
() -> function.apply(getRedisSet(key, updateStats)));
}
+ public <R> R listLockedExecute(RedisKey key, boolean updateStats,
+ FailableFunction<RedisList, R> function) {
+ return getRegionProvider().lockedExecute(key,
+ () -> function.apply(getRedisList(key, updateStats)));
+ }
+
public RedisSet getRedisSet(RedisKey key, boolean updateStats) {
return getRegionProvider().getTypedRedisData(RedisDataType.REDIS_SET, key,
updateStats);
}
+ public RedisList getRedisList(RedisKey key, boolean updateStats) {
+ return getRegionProvider().getTypedRedisData(RedisDataType.REDIS_LIST,
key, updateStats);
+ }
public <R> R dataLockedExecute(RedisKey key, boolean updateStats,
FailableFunction<RedisData, R> function) {