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 55635d1 Actually builds 55635d1 is described below commit 55635d1be5a0b7ce5cda4cc8d204b033fd5d385a Author: Ray Ingles <ring...@vmware.com> AuthorDate: Tue Jan 4 17:21:30 2022 -0500 Actually builds --- .../internal/data/NullRedisDataStructures.java | 1 + .../geode/redis/internal/data/NullRedisList.java | 48 +--------- .../geode/redis/internal/data/RedisDataType.java | 2 + .../geode/redis/internal/data/RedisList.java | 105 ++++----------------- .../internal/data/collections/SizeableList.java | 69 ++++++++++++++ 5 files changed, 94 insertions(+), 131 deletions(-) diff --git a/geode-for-redis/src/main/java/org/apache/geode/redis/internal/data/NullRedisDataStructures.java b/geode-for-redis/src/main/java/org/apache/geode/redis/internal/data/NullRedisDataStructures.java index e0e750e..5f16975 100644 --- a/geode-for-redis/src/main/java/org/apache/geode/redis/internal/data/NullRedisDataStructures.java +++ b/geode-for-redis/src/main/java/org/apache/geode/redis/internal/data/NullRedisDataStructures.java @@ -20,4 +20,5 @@ public class NullRedisDataStructures { public static final NullRedisSortedSet NULL_REDIS_SORTED_SET = new NullRedisSortedSet(); public static final NullRedisHash NULL_REDIS_HASH = new NullRedisHash(); public static final NullRedisData NULL_REDIS_DATA = new NullRedisData(); + public static final NullRedisList NULL_REDIS_LIST = new NullRedisList(); } 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 1e1f1cf..ced1c7e 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 @@ -16,20 +16,12 @@ package org.apache.geode.redis.internal.data; -import static java.util.Collections.emptyList; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.apache.geode.cache.Region; +import java.util.ArrayList; class NullRedisList extends RedisList { NullRedisList() { - super(new HashSet<>()); + super(new ArrayList<>()); } @Override @@ -37,40 +29,4 @@ class NullRedisList extends RedisList { return true; } - @Override - public Collection<byte[]> spop(Region<RedisKey, RedisData> region, RedisKey key, int popCount) { - return emptyList(); - } - - @Override - public Collection<byte[]> srandmember(int count) { - return emptyList(); - } - - @Override - public boolean sismember(byte[] member) { - return false; - } - - @Override - public int scard() { - return 0; - } - - @Override - public long sadd(List<byte[]> membersToAdd, Region<RedisKey, RedisData> region, RedisKey key) { - region.create(key, new RedisSet(membersToAdd)); - return membersToAdd.size(); - } - - @Override - public long srem(List<byte[]> membersToRemove, Region<RedisKey, RedisData> region, RedisKey key) { - return 0; - } - - @Override - public Set<byte[]> smembers() { - // some callers want to be able to modify the set returned - return Collections.emptySet(); - } } diff --git a/geode-for-redis/src/main/java/org/apache/geode/redis/internal/data/RedisDataType.java b/geode-for-redis/src/main/java/org/apache/geode/redis/internal/data/RedisDataType.java index e44eafe..dfb26c6 100755 --- a/geode-for-redis/src/main/java/org/apache/geode/redis/internal/data/RedisDataType.java +++ b/geode-for-redis/src/main/java/org/apache/geode/redis/internal/data/RedisDataType.java @@ -18,6 +18,7 @@ package org.apache.geode.redis.internal.data; import static org.apache.geode.redis.internal.data.NullRedisDataStructures.NULL_REDIS_DATA; import static org.apache.geode.redis.internal.data.NullRedisDataStructures.NULL_REDIS_HASH; +import static org.apache.geode.redis.internal.data.NullRedisDataStructures.NULL_REDIS_LIST; import static org.apache.geode.redis.internal.data.NullRedisDataStructures.NULL_REDIS_SET; import static org.apache.geode.redis.internal.data.NullRedisDataStructures.NULL_REDIS_SORTED_SET; import static org.apache.geode.redis.internal.data.NullRedisDataStructures.NULL_REDIS_STRING; @@ -28,6 +29,7 @@ public enum RedisDataType { REDIS_STRING("string", NULL_REDIS_STRING), REDIS_HASH("hash", NULL_REDIS_HASH), REDIS_SET("set", NULL_REDIS_SET), + REDIS_LIST("list", NULL_REDIS_LIST), REDIS_SORTED_SET("sortedset", NULL_REDIS_SORTED_SET); private final String toStringValue; diff --git a/geode-for-redis/src/main/java/org/apache/geode/redis/internal/data/RedisList.java b/geode-for-redis/src/main/java/org/apache/geode/redis/internal/data/RedisList.java index 6a3bfbd..a4a2e89 100644 --- a/geode-for-redis/src/main/java/org/apache/geode/redis/internal/data/RedisList.java +++ b/geode-for-redis/src/main/java/org/apache/geode/redis/internal/data/RedisList.java @@ -18,23 +18,15 @@ package org.apache.geode.redis.internal.data; import static java.util.Collections.emptyList; import static org.apache.geode.internal.JvmSizeUtils.memoryOverhead; -import static org.apache.geode.redis.internal.data.RedisDataType.REDIS_SET; +import static org.apache.geode.redis.internal.data.RedisDataType.REDIS_LIST; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; -import java.math.BigInteger; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.Objects; -import java.util.Random; -import java.util.Set; - -import it.unimi.dsi.fastutil.bytes.ByteArrays; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; import org.apache.geode.DataSerializer; import org.apache.geode.annotations.VisibleForTesting; @@ -42,31 +34,17 @@ import org.apache.geode.cache.Region; import org.apache.geode.internal.serialization.DeserializationContext; import org.apache.geode.internal.serialization.KnownVersion; import org.apache.geode.internal.serialization.SerializationContext; -import org.apache.geode.redis.internal.commands.executor.GlobPattern; -import org.apache.geode.redis.internal.data.collections.SizeableObjectOpenCustomHashSet; +import org.apache.geode.redis.internal.data.collections.SizeableList; import org.apache.geode.redis.internal.data.delta.AddByteArrays; import org.apache.geode.redis.internal.data.delta.RemoveByteArrays; -import org.apache.geode.redis.internal.data.delta.ReplaceByteArrays; -import org.apache.geode.redis.internal.services.RegionProvider; public class RedisList extends AbstractRedisData { protected static final int REDIS_LIST_OVERHEAD = memoryOverhead(RedisList.class); - private List elements; - - public RedisList(Collection<byte[]> elements) { - this.elements = new ArrayList(elements.size()); - for (byte[] member : elements) { - appendElement(member); - } - } - - public RedisList(List members) { - this.elements = members; - } + private ElementList elements; - public RedisList(int expectedSize) { - elements = new ArrayList(expectedSize); + public RedisList(Collection<byte[]> collection) { + this.elements = new ElementList(collection); } /** @@ -82,7 +60,7 @@ public class RedisList extends AbstractRedisData { * @return the number of members actually added */ public long lpush(List<byte[]> elementsToAdd, Region<RedisKey, RedisData> region, RedisKey key) { - for (byte[] element: elementsToAdd) { + for (byte[] element : elementsToAdd) { prependElement(element); } int elementsAdded = elementsToAdd.size(); @@ -111,7 +89,7 @@ public class RedisList extends AbstractRedisData { List<byte[]> popped = new ArrayList<>(); while (popped.size() < popCount) { - popped.add((byte[]) elements.remove(0)); + popped.add(elements.remove(0)); } if (!popped.isEmpty()) { storeChanges(region, key, new RemoveByteArrays(popped)); @@ -119,6 +97,9 @@ public class RedisList extends AbstractRedisData { return popped; } + /** + * @return the number of elements in the list + */ public int llen() { return elements.size(); } @@ -133,12 +114,6 @@ public class RedisList extends AbstractRedisData { membersRemove(bytes); } - @Override - public void applyReplaceByteArraysDelta(MemberSet members) { - persistNoDelta(); - this.elements = members; - } - /** * Since GII (getInitialImage) can come in and call toData while other threads * are modifying this object, the striped executor will not protect toData. @@ -159,7 +134,7 @@ public class RedisList extends AbstractRedisData { throws IOException, ClassNotFoundException { super.fromData(in, context); int size = DataSerializer.readPrimitiveInt(in); - elements = new MemberSet(size); + elements = new ElementList(size); for (int i = 0; i < size; ++i) { elements.add(DataSerializer.readByteArray(in)); } @@ -186,44 +161,9 @@ public class RedisList extends AbstractRedisData { return elements.remove(memberToRemove); } - public long sadd(List<byte[]> membersToAdd, Region<RedisKey, RedisData> region, RedisKey key) { - membersToAdd.removeIf(memberToAdd -> !appendElement(memberToAdd)); - int membersAdded = membersToAdd.size(); - if (membersAdded != 0) { - storeChanges(region, key, new AddByteArrays(membersToAdd)); - } - return membersAdded; - } - - /** - * @param membersToRemove members to remove from this set; NOTE this list may by - * modified by this call - * @param region the region this instance is stored in - * @param key the name of the set to remove from - * @return the number of members actually removed - */ - public long srem(List<byte[]> membersToRemove, Region<RedisKey, RedisData> region, RedisKey key) { - membersToRemove.removeIf(memberToRemove -> !membersRemove(memberToRemove)); - int membersRemoved = membersToRemove.size(); - if (membersRemoved != 0) { - storeChanges(region, key, new RemoveByteArrays(membersToRemove)); - } - return membersRemoved; - } - - /** - * The returned set is NOT a copy and will be changed - * by future changes to this instance. - * - * @return a set containing all the members in this set - */ - public Set<byte[]> smembers() { - return Collections.unmodifiableSet(elements); - } - @Override public RedisDataType getType() { - return REDIS_SET; + return REDIS_LIST; } @Override @@ -247,8 +187,8 @@ public class RedisList extends AbstractRedisData { if (redisSet.elements.size() != elements.size()) { return false; } - for (byte[] member : elements) { - if (!redisSet.elements.contains(member)) { + for (byte[] element : elements) { + if (!redisSet.elements.contains(element)) { return false; } } @@ -262,7 +202,7 @@ public class RedisList extends AbstractRedisData { @Override public String toString() { - return "RedisSet{" + super.toString() + ", " + "size=" + elements.size() + '}'; + return "RedisList{" + super.toString() + ", " + "size=" + elements.size() + '}'; } @Override @@ -275,17 +215,13 @@ public class RedisList extends AbstractRedisData { return REDIS_LIST_OVERHEAD + elements.getSizeInBytes(); } - public static class MemberSet extends SizeableObjectOpenCustomHashSet<byte[]> { - public MemberSet() { - super(ByteArrays.HASH_STRATEGY); + public static class ElementList extends SizeableList<byte[]> { + public ElementList(Collection<byte[]> initialElements) { + super(initialElements); } - public MemberSet(int size) { - super(size, ByteArrays.HASH_STRATEGY); - } - - public MemberSet(Collection<byte[]> initialElements) { - super(initialElements, ByteArrays.HASH_STRATEGY); + public ElementList(int size) { + super(size); } @Override @@ -293,5 +229,4 @@ public class RedisList extends AbstractRedisData { return memoryOverhead(element); } } - } diff --git a/geode-for-redis/src/main/java/org/apache/geode/redis/internal/data/collections/SizeableList.java b/geode-for-redis/src/main/java/org/apache/geode/redis/internal/data/collections/SizeableList.java new file mode 100644 index 0000000..4f72243 --- /dev/null +++ b/geode-for-redis/src/main/java/org/apache/geode/redis/internal/data/collections/SizeableList.java @@ -0,0 +1,69 @@ +/* + * 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.data.collections; + + +import static org.apache.geode.internal.JvmSizeUtils.memoryOverhead; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.apache.geode.internal.size.Sizeable; + +public abstract class SizeableList<K> extends ArrayList<K> implements Sizeable { + private static final long serialVersionUID = 9174920505089089517L; + private static final int SIZEABLE_LIST_OVERHEAD = + memoryOverhead(SizeableList.class); + + private int memberOverhead; + private List<K> elements; + + public SizeableList(Collection<K> collection) { + elements = new ArrayList<>(collection); + } + + public SizeableList(int size) { + elements = new ArrayList<>(size); + } + + @Override + public boolean add(K k) { + boolean added = elements.add(k); + if (added) { + memberOverhead += sizeElement(k); + } + return added; + } + + @SuppressWarnings("unchecked") + @Override + public boolean remove(Object k) { + boolean removed = elements.remove(k); + if (removed) { + memberOverhead -= sizeElement((K) k); + } + return removed; + } + + @Override + public int getSizeInBytes() { + // The object referenced by the "strategy" field is not sized + // since it is usually a singleton instance. + return SIZEABLE_LIST_OVERHEAD + memberOverhead; + } + + protected abstract int sizeElement(K element); +}