From 6bcd474c6558e91ef8c8d47c09fd3a5a0de9c9d9 Mon Sep 17 00:00:00 2001 From: Nikita Date: Thu, 18 Jan 2018 13:25:57 +0300 Subject: [PATCH] RAtomicLong.getAndDelete and RAtomicDouble.getAndDelete methods added. #1248 --- .../org/redisson/RedissonAtomicDouble.java | 21 ++++++++++++++++--- .../java/org/redisson/RedissonAtomicLong.java | 18 ++++++++++++++-- .../java/org/redisson/api/RAtomicDouble.java | 7 +++++++ .../org/redisson/api/RAtomicDoubleAsync.java | 12 +++++++++++ .../java/org/redisson/api/RAtomicLong.java | 7 +++++++ .../org/redisson/api/RAtomicLongAsync.java | 12 +++++++++++ .../client/protocol/RedisCommands.java | 8 +++++-- .../DoubleNullSafeReplayConvertor.java | 19 +++++++++++++++++ .../redisson/RedissonAtomicDoubleTest.java | 17 +++++++++++++++ .../org/redisson/RedissonAtomicLongTest.java | 19 +++++++++++++++++ 10 files changed, 133 insertions(+), 7 deletions(-) create mode 100644 redisson/src/main/java/org/redisson/client/protocol/convertor/DoubleNullSafeReplayConvertor.java diff --git a/redisson/src/main/java/org/redisson/RedissonAtomicDouble.java b/redisson/src/main/java/org/redisson/RedissonAtomicDouble.java index 61ceba620..e23d67c23 100644 --- a/redisson/src/main/java/org/redisson/RedissonAtomicDouble.java +++ b/redisson/src/main/java/org/redisson/RedissonAtomicDouble.java @@ -60,7 +60,8 @@ public class RedissonAtomicDouble extends RedissonExpirable implements RAtomicDo @Override public RFuture compareAndSetAsync(double expect, double update) { return commandExecutor.evalWriteAsync(getName(), StringCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN, - "if tonumber(redis.call('get', KEYS[1])) == tonumber(ARGV[1]) then " + "local value = redis.call('get', KEYS[1]);" + + "if (value == false and tonumber(ARGV[1]) == 0) or (tonumber(value) == tonumber(ARGV[1])) then " + "redis.call('set', KEYS[1], ARGV[2]); " + "return 1 " + "else " @@ -80,12 +81,26 @@ public class RedissonAtomicDouble extends RedissonExpirable implements RAtomicDo @Override public double get() { - return addAndGet(0); + return get(getAsync()); } + @Override + public double getAndDelete() { + return get(getAndDeleteAsync()); + } + + @Override + public RFuture getAndDeleteAsync() { + return commandExecutor.evalWriteAsync(getName(), StringCodec.INSTANCE, RedisCommands.EVAL_DOUBLE, + "local currValue = redis.call('get', KEYS[1]); " + + "redis.call('del', KEYS[1]); " + + "return currValue; ", + Collections.singletonList(getName())); + } + @Override public RFuture getAsync() { - return addAndGetAsync(0); + return commandExecutor.writeAsync(getName(), StringCodec.INSTANCE, RedisCommands.GET_DOUBLE, getName()); } @Override diff --git a/redisson/src/main/java/org/redisson/RedissonAtomicLong.java b/redisson/src/main/java/org/redisson/RedissonAtomicLong.java index 69b8bb647..22d65d1f2 100644 --- a/redisson/src/main/java/org/redisson/RedissonAtomicLong.java +++ b/redisson/src/main/java/org/redisson/RedissonAtomicLong.java @@ -66,6 +66,20 @@ public class RedissonAtomicLong extends RedissonExpirable implements RAtomicLong + "end", Collections.singletonList(getName()), expect, update); } + + @Override + public long getAndDelete() { + return get(getAndDeleteAsync()); + } + + @Override + public RFuture getAndDeleteAsync() { + return commandExecutor.evalWriteAsync(getName(), StringCodec.INSTANCE, RedisCommands.EVAL_LONG_SAFE, + "local currValue = redis.call('get', KEYS[1]); " + + "redis.call('del', KEYS[1]); " + + "return currValue; ", + Collections.singletonList(getName())); + } @Override public long decrementAndGet() { @@ -79,12 +93,12 @@ public class RedissonAtomicLong extends RedissonExpirable implements RAtomicLong @Override public long get() { - return addAndGet(0); + return get(getAsync()); } @Override public RFuture getAsync() { - return addAndGetAsync(0); + return commandExecutor.writeAsync(getName(), StringCodec.INSTANCE, RedisCommands.GET_LONG, getName()); } @Override diff --git a/redisson/src/main/java/org/redisson/api/RAtomicDouble.java b/redisson/src/main/java/org/redisson/api/RAtomicDouble.java index e52b395dc..7ec2abcb5 100644 --- a/redisson/src/main/java/org/redisson/api/RAtomicDouble.java +++ b/redisson/src/main/java/org/redisson/api/RAtomicDouble.java @@ -62,6 +62,13 @@ public interface RAtomicDouble extends RExpirable, RAtomicDoubleAsync { * @return the current value */ double get(); + + /** + * Gets and deletes object + * + * @return the current value + */ + double getAndDelete(); /** * Atomically adds the given value to the current value. diff --git a/redisson/src/main/java/org/redisson/api/RAtomicDoubleAsync.java b/redisson/src/main/java/org/redisson/api/RAtomicDoubleAsync.java index d83dbf883..9889655ab 100644 --- a/redisson/src/main/java/org/redisson/api/RAtomicDoubleAsync.java +++ b/redisson/src/main/java/org/redisson/api/RAtomicDoubleAsync.java @@ -15,6 +15,11 @@ */ package org.redisson.api; +/** + * + * @author Nikita Koksharov + * + */ public interface RAtomicDoubleAsync extends RExpirableAsync { RFuture compareAndSetAsync(double expect, double update); @@ -25,6 +30,13 @@ public interface RAtomicDoubleAsync extends RExpirableAsync { RFuture getAsync(); + /** + * Gets and deletes object + * + * @return the current value + */ + RFuture getAndDeleteAsync(); + RFuture getAndAddAsync(double delta); RFuture getAndSetAsync(double newValue); diff --git a/redisson/src/main/java/org/redisson/api/RAtomicLong.java b/redisson/src/main/java/org/redisson/api/RAtomicLong.java index 714f56fcb..c2d8da378 100644 --- a/redisson/src/main/java/org/redisson/api/RAtomicLong.java +++ b/redisson/src/main/java/org/redisson/api/RAtomicLong.java @@ -63,6 +63,13 @@ public interface RAtomicLong extends RExpirable, RAtomicLongAsync { */ long get(); + /** + * Gets and deletes object + * + * @return the current value + */ + long getAndDelete(); + /** * Atomically adds the given value to the current value. * diff --git a/redisson/src/main/java/org/redisson/api/RAtomicLongAsync.java b/redisson/src/main/java/org/redisson/api/RAtomicLongAsync.java index 02bffedbd..c4cf387d1 100644 --- a/redisson/src/main/java/org/redisson/api/RAtomicLongAsync.java +++ b/redisson/src/main/java/org/redisson/api/RAtomicLongAsync.java @@ -15,6 +15,11 @@ */ package org.redisson.api; +/** + * + * @author Nikita Koksharov + * + */ public interface RAtomicLongAsync extends RExpirableAsync { RFuture compareAndSetAsync(long expect, long update); @@ -24,6 +29,13 @@ public interface RAtomicLongAsync extends RExpirableAsync { RFuture decrementAndGetAsync(); RFuture getAsync(); + + /** + * Gets and deletes object + * + * @return the current value + */ + RFuture getAndDeleteAsync(); RFuture getAndAddAsync(long delta); 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 48299979a..c3eac37eb 100644 --- a/redisson/src/main/java/org/redisson/client/protocol/RedisCommands.java +++ b/redisson/src/main/java/org/redisson/client/protocol/RedisCommands.java @@ -32,6 +32,7 @@ import org.redisson.client.protocol.convertor.BooleanNullReplayConvertor; import org.redisson.client.protocol.convertor.BooleanNullSafeReplayConvertor; import org.redisson.client.protocol.convertor.BooleanNumberReplayConvertor; import org.redisson.client.protocol.convertor.BooleanReplayConvertor; +import org.redisson.client.protocol.convertor.DoubleNullSafeReplayConvertor; import org.redisson.client.protocol.convertor.DoubleReplayConvertor; import org.redisson.client.protocol.convertor.IntegerReplayConvertor; import org.redisson.client.protocol.convertor.KeyValueConvertor; @@ -133,7 +134,7 @@ public interface RedisCommands { RedisCommand>> ZRANGE_ENTRY = new RedisCommand>>("ZRANGE", new ScoredSortedSetReplayDecoder()); RedisCommand>> ZRANGEBYSCORE_ENTRY = new RedisCommand>>("ZRANGEBYSCORE", new ScoredSortedSetReplayDecoder()); RedisCommand> ZSCAN = new RedisCommand>("ZSCAN", new ListMultiDecoder(new LongMultiDecoder(), new ScoredSortedSetScanDecoder(), new ScoredSortedSetScanReplayDecoder())); - RedisStrictCommand ZINCRBY = new RedisStrictCommand("ZINCRBY", new DoubleReplayConvertor()); + RedisStrictCommand ZINCRBY = new RedisStrictCommand("ZINCRBY", new DoubleNullSafeReplayConvertor()); RedisCommand> SCAN = new RedisCommand>("SCAN", new ListMultiDecoder(new LongMultiDecoder(), new ObjectListReplayDecoder(), new ListScanResultReplayDecoder())); RedisStrictCommand RANDOM_KEY = new RedisStrictCommand("RANDOMKEY", new StringDataDecoder()); @@ -221,7 +222,9 @@ public interface RedisCommands { RedisStrictCommand EVAL_STRING = new RedisStrictCommand("EVAL", new StringReplayDecoder()); RedisStrictCommand EVAL_STRING_DATA = new RedisStrictCommand("EVAL", new StringDataDecoder()); RedisStrictCommand EVAL_INTEGER = new RedisStrictCommand("EVAL", new IntegerReplayConvertor()); + RedisStrictCommand EVAL_DOUBLE = new RedisStrictCommand("EVAL", new DoubleNullSafeReplayConvertor()); RedisStrictCommand EVAL_LONG = new RedisStrictCommand("EVAL"); + RedisStrictCommand EVAL_LONG_SAFE = new RedisStrictCommand("EVAL", new LongReplayConvertor()); RedisStrictCommand EVAL_VOID = new RedisStrictCommand("EVAL", new VoidReplayConvertor()); RedisCommand> EVAL_LIST = new RedisCommand>("EVAL", new ObjectListReplayDecoder()); RedisCommand> EVAL_SET = new RedisCommand>("EVAL", new ObjectSetReplayDecoder()); @@ -235,7 +238,7 @@ public interface RedisCommands { RedisStrictCommand INCR = new RedisStrictCommand("INCR"); RedisStrictCommand INCRBY = new RedisStrictCommand("INCRBY"); - RedisStrictCommand INCRBYFLOAT = new RedisStrictCommand("INCRBYFLOAT", new DoubleReplayConvertor()); + RedisStrictCommand INCRBYFLOAT = new RedisStrictCommand("INCRBYFLOAT", new DoubleNullSafeReplayConvertor()); RedisStrictCommand DECR = new RedisStrictCommand("DECR"); RedisStrictCommand AUTH = new RedisStrictCommand("AUTH", new VoidReplayConvertor()); @@ -281,6 +284,7 @@ public interface RedisCommands { RedisCommand GET = new RedisCommand("GET"); RedisStrictCommand GET_LONG = new RedisStrictCommand("GET", new LongReplayConvertor()); RedisStrictCommand GET_INTEGER = new RedisStrictCommand("GET", new IntegerReplayConvertor()); + RedisStrictCommand GET_DOUBLE = new RedisStrictCommand("GET", new DoubleNullSafeReplayConvertor()); RedisCommand GETSET = new RedisCommand("GETSET"); RedisCommand GETRANGE = new RedisCommand("GETRANGE"); RedisCommand APPEND = new RedisCommand("APPEND"); diff --git a/redisson/src/main/java/org/redisson/client/protocol/convertor/DoubleNullSafeReplayConvertor.java b/redisson/src/main/java/org/redisson/client/protocol/convertor/DoubleNullSafeReplayConvertor.java new file mode 100644 index 000000000..c1c0b1c5c --- /dev/null +++ b/redisson/src/main/java/org/redisson/client/protocol/convertor/DoubleNullSafeReplayConvertor.java @@ -0,0 +1,19 @@ +package org.redisson.client.protocol.convertor; + +/** + * + * @author Nikita Koksharov + * + */ +public class DoubleNullSafeReplayConvertor extends DoubleReplayConvertor { + + @Override + public Double convert(Object obj) { + Double r = super.convert(obj); + if (r == null) { + return 0.0; + } + return r; + } + +} diff --git a/redisson/src/test/java/org/redisson/RedissonAtomicDoubleTest.java b/redisson/src/test/java/org/redisson/RedissonAtomicDoubleTest.java index 3a4850ca0..0d69e2186 100644 --- a/redisson/src/test/java/org/redisson/RedissonAtomicDoubleTest.java +++ b/redisson/src/test/java/org/redisson/RedissonAtomicDoubleTest.java @@ -9,6 +9,23 @@ import org.redisson.api.RAtomicDouble; public class RedissonAtomicDoubleTest extends BaseTest { + @Test + public void testGetZero() { + RAtomicDouble ad2 = redisson.getAtomicDouble("test"); + assertThat(ad2.get()).isZero(); + } + + @Test + public void testGetAndDelete() { + RAtomicDouble al = redisson.getAtomicDouble("test"); + al.set(10.34); + assertThat(al.getAndDelete()).isEqualTo(10.34); + assertThat(al.isExists()).isFalse(); + + RAtomicDouble ad2 = redisson.getAtomicDouble("test2"); + assertThat(ad2.getAndDelete()).isZero(); + } + @Test public void testCompareAndSet() { RAtomicDouble al = redisson.getAtomicDouble("test"); diff --git a/redisson/src/test/java/org/redisson/RedissonAtomicLongTest.java b/redisson/src/test/java/org/redisson/RedissonAtomicLongTest.java index a35ff024f..170368e51 100644 --- a/redisson/src/test/java/org/redisson/RedissonAtomicLongTest.java +++ b/redisson/src/test/java/org/redisson/RedissonAtomicLongTest.java @@ -1,11 +1,30 @@ package org.redisson; +import static org.assertj.core.api.Assertions.assertThat; + import org.junit.Assert; import org.junit.Test; import org.redisson.api.RAtomicLong; public class RedissonAtomicLongTest extends BaseTest { + @Test + public void testGetZero() { + RAtomicLong ad2 = redisson.getAtomicLong("test"); + assertThat(ad2.get()).isZero(); + } + + @Test + public void testGetAndDelete() { + RAtomicLong al = redisson.getAtomicLong("test"); + al.set(10); + assertThat(al.getAndDelete()).isEqualTo(10); + assertThat(al.isExists()).isFalse(); + + RAtomicLong ad2 = redisson.getAtomicLong("test2"); + assertThat(ad2.getAndDelete()).isZero(); + } + @Test public void testCompareAndSetZero() { RAtomicLong al = redisson.getAtomicLong("test");