From be2a482880156bb93cd45194e2121c874b400832 Mon Sep 17 00:00:00 2001 From: Costin Leau Date: Fri, 3 Dec 2010 20:47:17 +0200 Subject: [PATCH] DATAKV-9 + add capped support for redis list + integration test --- .../keyvalue/redis/util/DefaultRedisList.java | 51 +++++++++++++++++-- .../data/keyvalue/redis/util/RedisList.java | 2 +- .../redis/util/AbstractRedisListTests.java | 14 +++++ 3 files changed, 62 insertions(+), 5 deletions(-) diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/util/DefaultRedisList.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/util/DefaultRedisList.java index 238435bf9..cd5a7a1af 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/util/DefaultRedisList.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/util/DefaultRedisList.java @@ -25,7 +25,8 @@ import org.springframework.data.keyvalue.redis.core.BoundListOperations; import org.springframework.data.keyvalue.redis.core.RedisOperations; /** - * Default implementation for {@link RedisList}. + * Default implementation for {@link RedisList}. Allows the maximum size (or the cap) to + * be specified to prevent the list from overgrowing. * * @author Costin Leau */ @@ -33,6 +34,10 @@ public class DefaultRedisList extends AbstractRedisCollection implements R private final BoundListOperations listOps; + private volatile long maxSize = 0; + + private volatile boolean capped = false; + private class DefaultRedisListIterator extends RedisIterator { public DefaultRedisListIterator(Iterator delegate) { @@ -46,19 +51,44 @@ public class DefaultRedisList extends AbstractRedisCollection implements R } /** - * Constructs a new DefaultRedisList instance. + * Constructs a new, uncapped DefaultRedisList instance. * * @param key * @param operations */ public DefaultRedisList(String key, RedisOperations operations) { - super(key, operations); - listOps = operations.forList(key); + this(operations.forList(key)); } + /** + * Constructs a new, uncapped DefaultRedisList instance. + * + * @param boundOps + */ public DefaultRedisList(BoundListOperations boundOps) { + this(boundOps, 0); + } + + /** + * Constructs a new DefaultRedisList instance. + * + * @param boundOps + * @param maxSize + */ + public DefaultRedisList(BoundListOperations boundOps, long maxSize) { super(boundOps.getKey(), boundOps.getOperations()); listOps = boundOps; + setMaxSize(maxSize); + } + + /** + * Sets the maximum size of the (capped) list. A value of 0 means unlimited. + * + * @param maxSize list maximum size + */ + public void setMaxSize(long maxSize) { + this.maxSize = maxSize; + capped = (maxSize > 0); } @Override @@ -76,6 +106,13 @@ public class DefaultRedisList extends AbstractRedisCollection implements R return listOps.range(0, -1); } + private void cap() { + if (capped) { + listOps.trim(0, maxSize - 1); + } + } + + @Override public Iterator iterator() { return content().iterator(); @@ -90,6 +127,7 @@ public class DefaultRedisList extends AbstractRedisCollection implements R @Override public boolean add(E value) { listOps.rightPush(value); + cap(); return true; } @@ -108,6 +146,7 @@ public class DefaultRedisList extends AbstractRedisCollection implements R public void add(int index, E element) { if (index == 0) { listOps.leftPush(element); + cap(); return; } @@ -115,6 +154,7 @@ public class DefaultRedisList extends AbstractRedisCollection implements R if (index == size()) { listOps.rightPush(element); + cap(); return; } @@ -133,6 +173,7 @@ public class DefaultRedisList extends AbstractRedisCollection implements R for (E e : reverseC) { listOps.leftPush(e); + cap(); } return true; } @@ -142,6 +183,7 @@ public class DefaultRedisList extends AbstractRedisCollection implements R if (index == size()) { for (E e : c) { listOps.rightPush(e); + cap(); } return true; } @@ -213,6 +255,7 @@ public class DefaultRedisList extends AbstractRedisCollection implements R @Override public boolean offer(E e) { listOps.leftPush(e); + cap(); return true; } diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/util/RedisList.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/util/RedisList.java index 1ec480930..cd0c54222 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/util/RedisList.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/util/RedisList.java @@ -19,7 +19,7 @@ import java.util.List; import java.util.Queue; /** - * Redis extension for the {@link List} contract. Supports {@link List} specific + * Redis extension for the {@link List} contract. Supports {@link List} and {@link Queue} specific * operations backed by Redis operations. * * @author Costin Leau diff --git a/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/util/AbstractRedisListTests.java b/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/util/AbstractRedisListTests.java index 6d82d1912..c8df2b3e9 100644 --- a/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/util/AbstractRedisListTests.java +++ b/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/util/AbstractRedisListTests.java @@ -268,4 +268,18 @@ public abstract class AbstractRedisListTests extends AbstractRedisCollectionT assertEquals(1, list.size()); assertEquals(t1, list.get(0)); } + + @Test + public void testCappedCollection() throws Exception { + RedisList cappedList = new DefaultRedisList(template.forList(collection.key + ":capped"), 1); + T first = getT(); + cappedList.offer(first); + assertEquals(1, cappedList.size()); + cappedList.add(getT()); + assertEquals(1, cappedList.size()); + T last = getT(); + cappedList.add(last); + assertEquals(1, cappedList.size()); + assertEquals(first, cappedList.get(0)); + } } \ No newline at end of file