From 7143e8593c9fd9169a8107a8a1acd9ca56dac412 Mon Sep 17 00:00:00 2001 From: Nikita Koksharov <nkoksharov@redisson.pro> Date: Thu, 8 Nov 2018 19:04:31 +0300 Subject: [PATCH] Feature - RObject.getSizeInMemory method added #1726 --- .../org/redisson/RedissonBloomFilter.java | 6 +++++ .../RedissonBoundedBlockingQueue.java | 6 +++++ .../org/redisson/RedissonDelayedQueue.java | 6 +++++ .../java/org/redisson/RedissonFairLock.java | 7 ++++++ .../redisson/RedissonListMultimapCache.java | 5 ++++ .../redisson/RedissonListMultimapValues.java | 6 +++++ .../org/redisson/RedissonLocalCachedMap.java | 5 ++++ .../java/org/redisson/RedissonMapCache.java | 6 +++++ .../org/redisson/RedissonMultimapCache.java | 6 +++++ .../java/org/redisson/RedissonObject.java | 24 +++++++++++++++++++ .../RedissonPermitExpirableSemaphore.java | 7 ++++++ .../redisson/RedissonSetMultimapCache.java | 5 ++++ .../redisson/RedissonSetMultimapValues.java | 5 ++++ .../main/java/org/redisson/api/RObject.java | 7 ++++++ .../java/org/redisson/api/RObjectAsync.java | 7 ++++++ .../client/protocol/RedisCommands.java | 1 + .../java/org/redisson/RedissonBucketTest.java | 7 ++++++ .../org/redisson/RedissonMapCacheTest.java | 10 ++++++++ 18 files changed, 126 insertions(+) diff --git a/redisson/src/main/java/org/redisson/RedissonBloomFilter.java b/redisson/src/main/java/org/redisson/RedissonBloomFilter.java index 590a5bb7b..76dc5345c 100644 --- a/redisson/src/main/java/org/redisson/RedissonBloomFilter.java +++ b/redisson/src/main/java/org/redisson/RedissonBloomFilter.java @@ -220,6 +220,12 @@ public class RedissonBloomFilter<T> extends RedissonExpirable implements RBloomF return commandExecutor.writeAsync(getName(), RedisCommands.DEL_OBJECTS, getName(), configName); } + @Override + public RFuture<Long> sizeInMemoryAsync() { + List<Object> keys = Arrays.<Object>asList(getName(), configName); + return super.sizeInMemoryAsync(keys); + } + private void readConfig() { RFuture<Map<String, String>> future = commandExecutor.readAsync(configName, StringCodec.INSTANCE, new RedisCommand<Map<Object, Object>>("HGETALL", new ObjectMapReplayDecoder()), configName); diff --git a/redisson/src/main/java/org/redisson/RedissonBoundedBlockingQueue.java b/redisson/src/main/java/org/redisson/RedissonBoundedBlockingQueue.java index 9f8584393..01ed0700c 100644 --- a/redisson/src/main/java/org/redisson/RedissonBoundedBlockingQueue.java +++ b/redisson/src/main/java/org/redisson/RedissonBoundedBlockingQueue.java @@ -370,6 +370,12 @@ public class RedissonBoundedBlockingQueue<V> extends RedissonQueue<V> implements public RFuture<Boolean> deleteAsync() { return commandExecutor.writeAsync(getName(), RedisCommands.DEL_OBJECTS, getName(), getSemaphoreName()); } + + @Override + public RFuture<Long> sizeInMemoryAsync() { + List<Object> keys = Arrays.<Object>asList(getName(), getSemaphoreName()); + return super.sizeInMemoryAsync(keys); + } @Override public RFuture<Boolean> expireAsync(long timeToLive, TimeUnit timeUnit) { diff --git a/redisson/src/main/java/org/redisson/RedissonDelayedQueue.java b/redisson/src/main/java/org/redisson/RedissonDelayedQueue.java index 3f12023bf..73077d56a 100644 --- a/redisson/src/main/java/org/redisson/RedissonDelayedQueue.java +++ b/redisson/src/main/java/org/redisson/RedissonDelayedQueue.java @@ -401,6 +401,12 @@ public class RedissonDelayedQueue<V> extends RedissonExpirable implements RDelay return commandExecutor.writeAsync(getName(), RedisCommands.DEL_OBJECTS, queueName, timeoutSetName); } + @Override + public RFuture<Long> sizeInMemoryAsync() { + List<Object> keys = Arrays.<Object>asList(queueName, timeoutSetName); + return super.sizeInMemoryAsync(keys); + } + @Override public RFuture<Boolean> expireAsync(long timeToLive, TimeUnit timeUnit) { return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN, diff --git a/redisson/src/main/java/org/redisson/RedissonFairLock.java b/redisson/src/main/java/org/redisson/RedissonFairLock.java index 9c5a6b0a2..407a1fdd3 100644 --- a/redisson/src/main/java/org/redisson/RedissonFairLock.java +++ b/redisson/src/main/java/org/redisson/RedissonFairLock.java @@ -16,6 +16,7 @@ package org.redisson; import java.util.Arrays; +import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; @@ -230,6 +231,12 @@ public class RedissonFairLock extends RedissonLock implements RLock { return commandExecutor.writeAsync(getName(), RedisCommands.DEL_OBJECTS, getName(), threadsQueueName, timeoutSetName); } + @Override + public RFuture<Long> sizeInMemoryAsync() { + List<Object> keys = Arrays.<Object>asList(getName(), threadsQueueName, timeoutSetName); + return super.sizeInMemoryAsync(keys); + } + @Override public RFuture<Boolean> expireAsync(long timeToLive, TimeUnit timeUnit) { return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN, diff --git a/redisson/src/main/java/org/redisson/RedissonListMultimapCache.java b/redisson/src/main/java/org/redisson/RedissonListMultimapCache.java index eccdef969..6c1b96554 100644 --- a/redisson/src/main/java/org/redisson/RedissonListMultimapCache.java +++ b/redisson/src/main/java/org/redisson/RedissonListMultimapCache.java @@ -192,6 +192,11 @@ public class RedissonListMultimapCache<K, V> extends RedissonListMultimap<K, V> public RFuture<Boolean> expireKeyAsync(K key, long timeToLive, TimeUnit timeUnit) { return baseCache.expireKeyAsync(key, timeToLive, timeUnit); } + + @Override + public RFuture<Long> sizeInMemoryAsync() { + return baseCache.sizeInMemoryAsync(); + } @Override public RFuture<Boolean> deleteAsync() { diff --git a/redisson/src/main/java/org/redisson/RedissonListMultimapValues.java b/redisson/src/main/java/org/redisson/RedissonListMultimapValues.java index 4b0bbe617..bf961c1a8 100644 --- a/redisson/src/main/java/org/redisson/RedissonListMultimapValues.java +++ b/redisson/src/main/java/org/redisson/RedissonListMultimapValues.java @@ -92,6 +92,12 @@ public class RedissonListMultimapValues<V> extends RedissonExpirable implements throw new UnsupportedOperationException("This operation is not supported for SetMultimap values Set"); } + @Override + public RFuture<Long> sizeInMemoryAsync() { + List<Object> keys = Arrays.<Object>asList(getName(), timeoutSetName); + return super.sizeInMemoryAsync(keys); + } + public RFuture<Boolean> deleteAsync() { return commandExecutor.evalWriteAsync(getName(), codec, RedisCommands.EVAL_BOOLEAN, "local expireDate = 92233720368547758; " + diff --git a/redisson/src/main/java/org/redisson/RedissonLocalCachedMap.java b/redisson/src/main/java/org/redisson/RedissonLocalCachedMap.java index a4c18c7ec..00a985f8c 100644 --- a/redisson/src/main/java/org/redisson/RedissonLocalCachedMap.java +++ b/redisson/src/main/java/org/redisson/RedissonLocalCachedMap.java @@ -520,6 +520,11 @@ public class RedissonLocalCachedMap<K, V> extends RedissonMap<K, V> implements R return commandExecutor.writeAsync(getName(), codec, RedisCommands.HDEL, params.toArray()); } + @Override + public RFuture<Long> sizeInMemoryAsync() { + List<Object> keys = Arrays.<Object>asList(getName(), listener.getUpdatesLogName()); + return super.sizeInMemoryAsync(keys); + } @Override public RFuture<Boolean> deleteAsync() { diff --git a/redisson/src/main/java/org/redisson/RedissonMapCache.java b/redisson/src/main/java/org/redisson/RedissonMapCache.java index 4bab3fde2..ad31f1d0e 100644 --- a/redisson/src/main/java/org/redisson/RedissonMapCache.java +++ b/redisson/src/main/java/org/redisson/RedissonMapCache.java @@ -1975,6 +1975,12 @@ public class RedissonMapCache<K, V> extends RedissonMap<K, V> implements RMapCac expiredTopic.removeListener(listenerId); } + @Override + public RFuture<Long> sizeInMemoryAsync() { + List<Object> keys = Arrays.<Object>asList(getName(), getTimeoutSetName(), getIdleSetName(), getLastAccessTimeSetName(), getOptionsName()); + return super.sizeInMemoryAsync(keys); + } + @Override public RFuture<Boolean> deleteAsync() { return commandExecutor.writeAsync(getName(), RedisCommands.DEL_OBJECTS, diff --git a/redisson/src/main/java/org/redisson/RedissonMultimapCache.java b/redisson/src/main/java/org/redisson/RedissonMultimapCache.java index 9bdd3ef7e..43f7d9829 100644 --- a/redisson/src/main/java/org/redisson/RedissonMultimapCache.java +++ b/redisson/src/main/java/org/redisson/RedissonMultimapCache.java @@ -16,6 +16,7 @@ package org.redisson; import java.util.Arrays; +import java.util.List; import java.util.concurrent.TimeUnit; import org.redisson.api.RFuture; @@ -62,6 +63,11 @@ public class RedissonMultimapCache<K> { ttlTimeout, ((RedissonObject)object).encodeMapKey(key)); } + public RFuture<Long> sizeInMemoryAsync() { + List<Object> keys = Arrays.<Object>asList(object.getName(), timeoutSetName); + return ((RedissonObject)object).sizeInMemoryAsync(keys); + } + public RFuture<Boolean> deleteAsync() { return commandExecutor.evalWriteAsync(object.getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN_AMOUNT, "local entries = redis.call('hgetall', KEYS[1]); " + diff --git a/redisson/src/main/java/org/redisson/RedissonObject.java b/redisson/src/main/java/org/redisson/RedissonObject.java index 288f20410..b65a639e3 100644 --- a/redisson/src/main/java/org/redisson/RedissonObject.java +++ b/redisson/src/main/java/org/redisson/RedissonObject.java @@ -18,6 +18,7 @@ package org.redisson; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.concurrent.TimeUnit; @@ -97,6 +98,29 @@ public abstract class RedissonObject implements RObject { public void rename(String newName) { get(renameAsync(newName)); } + + @Override + public RFuture<Long> sizeInMemoryAsync() { + return commandExecutor.writeAsync(getName(), RedisCommands.MEMORY_USAGE, getName()); + } + + public final RFuture<Long> sizeInMemoryAsync(List<Object> keys) { + return commandExecutor.evalWriteAsync((String)keys.get(0), StringCodec.INSTANCE, RedisCommands.EVAL_LONG, + "local total = 0;" + + "for j = 1, #KEYS, 1 do " + + "local size = redis.call('memory', 'usage', KEYS[j]); " + + "if size ~= false then " + + "total = total + size;" + + "end; " + + "end; " + + "return total; ", keys); + + } + + @Override + public long sizeInMemory() { + return get(sizeInMemoryAsync()); + } @Override public RFuture<Void> renameAsync(String newName) { diff --git a/redisson/src/main/java/org/redisson/RedissonPermitExpirableSemaphore.java b/redisson/src/main/java/org/redisson/RedissonPermitExpirableSemaphore.java index 8658692d6..21c2d2fab 100644 --- a/redisson/src/main/java/org/redisson/RedissonPermitExpirableSemaphore.java +++ b/redisson/src/main/java/org/redisson/RedissonPermitExpirableSemaphore.java @@ -16,6 +16,7 @@ package org.redisson; import java.util.Arrays; +import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; @@ -624,6 +625,12 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen Arrays.<Object>asList(getName(), getChannelName(), timeoutName), permitId, 1); } + @Override + public RFuture<Long> sizeInMemoryAsync() { + List<Object> keys = Arrays.<Object>asList(getName(), timeoutName); + return super.sizeInMemoryAsync(keys); + } + @Override public RFuture<Boolean> deleteAsync() { return commandExecutor.writeAsync(getName(), RedisCommands.DEL_OBJECTS, getName(), timeoutName); diff --git a/redisson/src/main/java/org/redisson/RedissonSetMultimapCache.java b/redisson/src/main/java/org/redisson/RedissonSetMultimapCache.java index 40d5f8939..0fb86f548 100644 --- a/redisson/src/main/java/org/redisson/RedissonSetMultimapCache.java +++ b/redisson/src/main/java/org/redisson/RedissonSetMultimapCache.java @@ -186,6 +186,11 @@ public class RedissonSetMultimapCache<K, V> extends RedissonSetMultimap<K, V> im return baseCache.expireKeyAsync(key, timeToLive, timeUnit); } + @Override + public RFuture<Long> sizeInMemoryAsync() { + return baseCache.sizeInMemoryAsync(); + } + @Override public RFuture<Boolean> deleteAsync() { return baseCache.deleteAsync(); diff --git a/redisson/src/main/java/org/redisson/RedissonSetMultimapValues.java b/redisson/src/main/java/org/redisson/RedissonSetMultimapValues.java index 013739775..5ab429cc3 100644 --- a/redisson/src/main/java/org/redisson/RedissonSetMultimapValues.java +++ b/redisson/src/main/java/org/redisson/RedissonSetMultimapValues.java @@ -122,6 +122,11 @@ public class RedissonSetMultimapValues<V> extends RedissonExpirable implements R System.currentTimeMillis(), encodeMapKey(key)); } + @Override + public RFuture<Long> sizeInMemoryAsync() { + List<Object> keys = Arrays.<Object>asList(getName(), timeoutSetName); + return super.sizeInMemoryAsync(keys); + } @Override public RFuture<Integer> sizeAsync() { diff --git a/redisson/src/main/java/org/redisson/api/RObject.java b/redisson/src/main/java/org/redisson/api/RObject.java index 942da09ef..9a08b44e9 100644 --- a/redisson/src/main/java/org/redisson/api/RObject.java +++ b/redisson/src/main/java/org/redisson/api/RObject.java @@ -27,6 +27,13 @@ import org.redisson.client.codec.Codec; */ public interface RObject extends RObjectAsync { + /** + * Returns size of object in Redis memory + * + * @return size of object + */ + long sizeInMemory(); + /** * Restores object using its state returned by {@link #dump()} method. * diff --git a/redisson/src/main/java/org/redisson/api/RObjectAsync.java b/redisson/src/main/java/org/redisson/api/RObjectAsync.java index 63962f55f..93db42734 100644 --- a/redisson/src/main/java/org/redisson/api/RObjectAsync.java +++ b/redisson/src/main/java/org/redisson/api/RObjectAsync.java @@ -25,6 +25,13 @@ import java.util.concurrent.TimeUnit; */ public interface RObjectAsync { + /** + * Returns size of object in Redis memory + * + * @return size of object + */ + RFuture<Long> sizeInMemoryAsync(); + /** * Restores object using its state returned by {@link #dumpAsync()} method. * diff --git a/redisson/src/main/java/org/redisson/client/protocol/RedisCommands.java b/redisson/src/main/java/org/redisson/client/protocol/RedisCommands.java index c3bbbdefe..4d4d14eeb 100644 --- a/redisson/src/main/java/org/redisson/client/protocol/RedisCommands.java +++ b/redisson/src/main/java/org/redisson/client/protocol/RedisCommands.java @@ -382,6 +382,7 @@ public interface RedisCommands { RedisStrictCommand<Boolean> EXISTS = new RedisStrictCommand<Boolean>("EXISTS", new BooleanReplayConvertor()); RedisStrictCommand<Boolean> NOT_EXISTS = new RedisStrictCommand<Boolean>("EXISTS", new BooleanNumberReplayConvertor(1L)); + RedisStrictCommand<Long> MEMORY_USAGE = new RedisStrictCommand<Long>("MEMORY", "USAGE", new LongReplayConvertor()); RedisStrictCommand<Boolean> RENAMENX = new RedisStrictCommand<Boolean>("RENAMENX", new BooleanReplayConvertor()); RedisStrictCommand<Void> RENAME = new RedisStrictCommand<Void>("RENAME", new VoidReplayConvertor()); RedisStrictCommand<Boolean> MOVE = new RedisStrictCommand<Boolean>("MOVE", new BooleanReplayConvertor()); diff --git a/redisson/src/test/java/org/redisson/RedissonBucketTest.java b/redisson/src/test/java/org/redisson/RedissonBucketTest.java index edc24b1d5..e05bd296c 100755 --- a/redisson/src/test/java/org/redisson/RedissonBucketTest.java +++ b/redisson/src/test/java/org/redisson/RedissonBucketTest.java @@ -17,6 +17,13 @@ import org.redisson.config.Config; public class RedissonBucketTest extends BaseTest { + @Test + public void testSizeInMemory() { + RBucket<Integer> al = redisson.getBucket("test"); + al.set(1234); + assertThat(al.sizeInMemory()).isEqualTo(49); + } + @Test public void testDumpAndRestore() { RBucket<Integer> al = redisson.getBucket("test"); diff --git a/redisson/src/test/java/org/redisson/RedissonMapCacheTest.java b/redisson/src/test/java/org/redisson/RedissonMapCacheTest.java index 9b6a48fdc..6df47372b 100644 --- a/redisson/src/test/java/org/redisson/RedissonMapCacheTest.java +++ b/redisson/src/test/java/org/redisson/RedissonMapCacheTest.java @@ -70,6 +70,16 @@ public class RedissonMapCacheTest extends BaseMapTest { return redisson.getMapCache("test", options); } + @Test + public void testSizeInMemory() { + RMapCache<Integer, Integer> map = redisson.getMapCache("test"); + for (int i = 0; i < 10; i++) { + map.put(i, i, 5, TimeUnit.SECONDS); + } + + assertThat(map.sizeInMemory()).isGreaterThanOrEqualTo(466); + } + @Test public void testRemainTimeToLive() { RMapCache<String, String> map = redisson.getMapCache("test");