From 41ee17d2e1d7700d7b6684519f1bccf44fef40ed Mon Sep 17 00:00:00 2001 From: Nikita Date: Wed, 16 Dec 2015 16:27:05 +0300 Subject: [PATCH] ReadWriteLock forceUnlock fixed --- .../java/org/redisson/RedissonReadLock.java | 33 ++++++++++++------- .../java/org/redisson/RedissonWriteLock.java | 15 +++++++-- .../redisson/RedissonReadWriteLockTest.java | 21 +++++++++--- 3 files changed, 51 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/redisson/RedissonReadLock.java b/src/main/java/org/redisson/RedissonReadLock.java index 0f203779f..0db7c3a2b 100644 --- a/src/main/java/org/redisson/RedissonReadLock.java +++ b/src/main/java/org/redisson/RedissonReadLock.java @@ -27,6 +27,7 @@ import org.redisson.command.CommandExecutor; import org.redisson.core.RLock; import io.netty.util.concurrent.Future; +import io.netty.util.concurrent.FutureListener; /** * Lock will be removed automatically if client disconnects. @@ -111,18 +112,26 @@ public class RedissonReadLock extends RedissonLock implements RLock { } Future forceUnlockAsync() { - cancelExpirationRenewal(); - return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN, - "if (redis.call('hdel', KEYS[1], ARGV[2]) == 1) then " + - "if (redis.call('hlen', KEYS[1]) == 1) then " + - "redis.call('del', KEYS[1]); " + - "redis.call('publish', KEYS[2], ARGV[1]); " + - "end; " + - "return 1; " + - "else " + - "return 0; " + - "end;", - Arrays.asList(getName(), getChannelName()), unlockMessage, getLockName()); + Future result = commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN, + "if (redis.call('hget', KEYS[1], 'mode') == 'read') then " + + "redis.call('del', KEYS[1]); " + + "redis.call('publish', KEYS[2], ARGV[1]); " + + "return 1; " + + "else " + + "return 0; " + + "end;", + Arrays.asList(getName(), getChannelName()), unlockMessage); + + result.addListener(new FutureListener() { + @Override + public void operationComplete(Future future) throws Exception { + if (future.isSuccess() && future.getNow()) { + cancelExpirationRenewal(); + } + } + }); + + return result; } @Override diff --git a/src/main/java/org/redisson/RedissonWriteLock.java b/src/main/java/org/redisson/RedissonWriteLock.java index 13a718fb5..38443f7bc 100644 --- a/src/main/java/org/redisson/RedissonWriteLock.java +++ b/src/main/java/org/redisson/RedissonWriteLock.java @@ -27,6 +27,7 @@ import org.redisson.command.CommandExecutor; import org.redisson.core.RLock; import io.netty.util.concurrent.Future; +import io.netty.util.concurrent.FutureListener; /** * Lock will be removed automatically if client disconnects. @@ -113,8 +114,7 @@ public class RedissonWriteLock extends RedissonLock implements RLock { } Future forceUnlockAsync() { - cancelExpirationRenewal(); - return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN, + Future result = commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN, "if (redis.call('hget', KEYS[1], 'mode') == 'write') then " + "redis.call('del', KEYS[1]); " + "redis.call('publish', KEYS[2], ARGV[1]); " + @@ -123,6 +123,17 @@ public class RedissonWriteLock extends RedissonLock implements RLock { "return 0; " + "end;", Arrays.asList(getName(), getChannelName()), unlockMessage); + + result.addListener(new FutureListener() { + @Override + public void operationComplete(Future future) throws Exception { + if (future.isSuccess() && future.getNow()) { + cancelExpirationRenewal(); + } + } + }); + + return result; } @Override diff --git a/src/test/java/org/redisson/RedissonReadWriteLockTest.java b/src/test/java/org/redisson/RedissonReadWriteLockTest.java index 8683708a1..a3be3e6ee 100644 --- a/src/test/java/org/redisson/RedissonReadWriteLockTest.java +++ b/src/test/java/org/redisson/RedissonReadWriteLockTest.java @@ -11,6 +11,7 @@ import org.junit.Assert; import org.junit.Test; import org.redisson.core.RLock; import org.redisson.core.RReadWriteLock; +import static org.assertj.core.api.Assertions.*; public class RedissonReadWriteLockTest extends BaseConcurrentTest { @@ -119,14 +120,26 @@ public class RedissonReadWriteLockTest extends BaseConcurrentTest { @Test public void testForceUnlock() { RReadWriteLock lock = redisson.getReadWriteLock("lock"); + RLock readLock = lock.readLock(); readLock.lock(); - Assert.assertTrue(readLock.isLocked()); - readLock.forceUnlock(); - Assert.assertFalse(readLock.isLocked()); + assertThat(readLock.isLocked()).isTrue(); + lock.writeLock().forceUnlock(); + assertThat(readLock.isLocked()).isTrue(); + lock.readLock().forceUnlock(); + assertThat(readLock.isLocked()).isFalse(); + + RLock writeLock = lock.writeLock(); + writeLock.lock(); + assertThat(writeLock.isLocked()).isTrue(); + lock.readLock().forceUnlock(); + assertThat(writeLock.isLocked()).isTrue(); + lock.writeLock().forceUnlock(); + assertThat(writeLock.isLocked()).isFalse(); lock = redisson.getReadWriteLock("lock"); - Assert.assertFalse(lock.readLock().isLocked()); + assertThat(lock.readLock().isLocked()).isFalse(); + assertThat(lock.writeLock().isLocked()).isFalse(); } @Test