From cd0401b9c12ea9f029090a23d264f0eaf6ff874e Mon Sep 17 00:00:00 2001 From: Nikita Koksharov Date: Tue, 6 Dec 2022 09:04:26 +0300 Subject: [PATCH] Feature - added FencedLock implementation. #4684 --- .../java/org/redisson/RedissonFencedLock.java | 49 ++++++++++++++++--- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/redisson/src/main/java/org/redisson/RedissonFencedLock.java b/redisson/src/main/java/org/redisson/RedissonFencedLock.java index f5a4d88aa..a9d2ae043 100644 --- a/redisson/src/main/java/org/redisson/RedissonFencedLock.java +++ b/redisson/src/main/java/org/redisson/RedissonFencedLock.java @@ -35,14 +35,23 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; +/** + * Redis based implementation of Fenced Lock with reentrancy support. + *

+ * Each lock acquisition increases fencing token. It should be + * checked if it's greater or equal with the previous one by + * the service guarded by this lock and reject operation if condition is false. + * + * @author Nikita Koksharov + * + */ public class RedissonFencedLock extends RedissonLock implements RFencedLock { + private final String tokenName; + public RedissonFencedLock(CommandAsyncExecutor commandExecutor, String name) { super(commandExecutor, name); - } - - String getTokenName() { - return prefixName("redisson_lock_token", getRawName()); + tokenName = prefixName("redisson_lock_token", getRawName()); } @Override @@ -52,7 +61,7 @@ public class RedissonFencedLock extends RedissonLock implements RFencedLock { @Override public RFuture getTokenAsync() { - return commandExecutor.writeAsync(getTokenName(), StringCodec.INSTANCE, RedisCommands.GET_LONG, getTokenName()); + return commandExecutor.writeAsync(tokenName, StringCodec.INSTANCE, RedisCommands.GET_LONG, tokenName); } @Override @@ -105,7 +114,7 @@ public class RedissonFencedLock extends RedissonLock implements RFencedLock { "return {-1, token}; " + "end; " + "return {redis.call('pttl', KEYS[1]), -1};", - Arrays.asList(getRawName(), getTokenName()), + Arrays.asList(getRawName(), tokenName), unit.toMillis(leaseTime), getLockName(threadId)); } @@ -298,8 +307,34 @@ public class RedissonFencedLock extends RedissonLock implements RFencedLock { "return nil; " + "end; " + "return redis.call('pttl', KEYS[1]);", - Arrays.asList(getRawName(), getTokenName()), + Arrays.asList(getRawName(), tokenName), unit.toMillis(leaseTime), getLockName(threadId)); } + @Override + public RFuture deleteAsync() { + return deleteAsync(getRawName(), tokenName); + } + + @Override + public RFuture sizeInMemoryAsync() { + List keys = Arrays.asList(getRawName(), tokenName); + return super.sizeInMemoryAsync(keys); + } + + @Override + public RFuture expireAsync(long timeToLive, TimeUnit timeUnit, String param, String... keys) { + return super.expireAsync(timeToLive, timeUnit, param, getRawName(), tokenName); + } + + @Override + protected RFuture expireAtAsync(long timestamp, String param, String... keys) { + return super.expireAtAsync(timestamp, param, getRawName(), tokenName); + } + + @Override + public RFuture clearExpireAsync() { + return clearExpireAsync(getRawName(), tokenName); + } + }