From 10d9673e7b89fbf93bffc87056255b6c54c88ec8 Mon Sep 17 00:00:00 2001 From: seakider Date: Tue, 19 Nov 2024 23:34:08 +0800 Subject: [PATCH] Fixed - method length return unexpected value and caused RedisException in some case Signed-off-by: seakider --- .../java/org/redisson/RedissonBitSet.java | 24 ++++++++++++------- .../java/org/redisson/RedissonBitSetTest.java | 14 +++++++++++ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/redisson/src/main/java/org/redisson/RedissonBitSet.java b/redisson/src/main/java/org/redisson/RedissonBitSet.java index 790d79168..527130a57 100644 --- a/redisson/src/main/java/org/redisson/RedissonBitSet.java +++ b/redisson/src/main/java/org/redisson/RedissonBitSet.java @@ -427,14 +427,22 @@ public class RedissonBitSet extends RedissonExpirable implements RBitSet { @Override public RFuture lengthAsync() { return commandExecutor.evalReadAsync(getRawName(), LongCodec.INSTANCE, RedisCommands.EVAL_LONG, - "local fromBit = redis.call('bitpos', KEYS[1], 1, -1);" - + "local toBit = 8*(fromBit/8 + 1) - fromBit % 8;" - + "for i = toBit, fromBit, -1 do " - + "if redis.call('getbit', KEYS[1], i) == 1 then " - + "return i+1;" - + "end;" - + "end;" + - "return fromBit+1", + "local i = redis.call('bitpos', KEYS[1], 1, -1); " + + "local pos = i < 0 and redis.call('bitpos', KEYS[1], 0, -1) or math.floor(i / 8) * 8; " + + "while (pos >= 0) " + + "do " + + "i = redis.call('bitpos', KEYS[1], 1, math.floor(pos / 8), math.floor(pos / 8)); " + + "if i < 0 then " + + "pos = pos - 8; " + + "else " + + "for j = pos + 7, pos, -1 do " + + "if redis.call('getbit', KEYS[1], j) == 1 then " + + "return j + 1; " + + "end; " + + "end; " + + "end; " + + "end; " + + "return 0; ", Collections.singletonList(getRawName())); } diff --git a/redisson/src/test/java/org/redisson/RedissonBitSetTest.java b/redisson/src/test/java/org/redisson/RedissonBitSetTest.java index 5cede87ec..d1a550384 100644 --- a/redisson/src/test/java/org/redisson/RedissonBitSetTest.java +++ b/redisson/src/test/java/org/redisson/RedissonBitSetTest.java @@ -91,6 +91,20 @@ public class RedissonBitSetTest extends RedisDockerTest { bs.clear(); bs.set(0); assertThat(bs.length()).isEqualTo(1); + + // no exception happened, but return is unexpected. + bs.clear(); + bs.set(0, 2); + bs.set(9); + bs.clear(9, 10); + assertThat(bs.length()).isEqualTo(2); + + // cause exception + bs.clear(); + bs.set(7); + bs.set(9); + bs.clear(9, 10); + assertThat(bs.length()).isEqualTo(8); } @Test