From ebb5951693129a9757af86ff0ff4382cb0d19331 Mon Sep 17 00:00:00 2001 From: yuluo-yx Date: Sat, 8 Aug 2026 14:34:29 +0800 Subject: [PATCH] [ISSUE #10831] fix(store): handle minimum hash index in compaction offset map --- .../rocketmq/store/kv/CompactionLog.java | 2 +- .../rocketmq/store/kv/OffsetMapTest.java | 49 ++++++++++++++++++- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/store/src/main/java/org/apache/rocketmq/store/kv/CompactionLog.java b/store/src/main/java/org/apache/rocketmq/store/kv/CompactionLog.java index be2bb551ad7..7e772144c02 100644 --- a/store/src/main/java/org/apache/rocketmq/store/kv/CompactionLog.java +++ b/store/src/main/java/org/apache/rocketmq/store/kv/CompactionLog.java @@ -965,7 +965,7 @@ private boolean isEmpty(int pos) { private int indexOf(byte[] hash, int tryNum) { int index = readInt(hash, Math.min(tryNum, hashSize - 4)) + Math.max(0, tryNum - hashSize + 4); - int entry = Math.abs(index) % capacity; + int entry = Math.floorMod(index, capacity); return entry * entrySize; } diff --git a/store/src/test/java/org/apache/rocketmq/store/kv/OffsetMapTest.java b/store/src/test/java/org/apache/rocketmq/store/kv/OffsetMapTest.java index e520c6a3bb4..38fcecc5ffc 100644 --- a/store/src/test/java/org/apache/rocketmq/store/kv/OffsetMapTest.java +++ b/store/src/test/java/org/apache/rocketmq/store/kv/OffsetMapTest.java @@ -16,6 +16,7 @@ */ package org.apache.rocketmq.store.kv; +import java.security.MessageDigest; import org.apache.rocketmq.store.kv.CompactionLog.OffsetMap; import org.junit.Test; @@ -50,4 +51,50 @@ public void testFull() throws Exception { assertEquals(offsetMap.getLastOffset(), 99); assertThrows(IllegalArgumentException.class, () -> offsetMap.put(String.valueOf(100), 100)); } -} \ No newline at end of file + + @Test + public void testMinimumHashValue() throws Exception { + OffsetMap offsetMap = new OffsetMap(0, new MinimumHashDigest()); + + offsetMap.put("key", 7); + + assertEquals(7, offsetMap.get("key")); + } + + private static class MinimumHashDigest extends MessageDigest { + private MinimumHashDigest() { + super("minimum-hash"); + } + + @Override + protected int engineGetDigestLength() { + return 16; + } + + @Override + protected void engineUpdate(byte input) { + } + + @Override + protected void engineUpdate(byte[] input, int offset, int len) { + } + + @Override + protected byte[] engineDigest() { + byte[] digest = new byte[16]; + digest[0] = Byte.MIN_VALUE; + return digest; + } + + @Override + protected int engineDigest(byte[] buf, int offset, int len) { + byte[] digest = engineDigest(); + System.arraycopy(digest, 0, buf, offset, digest.length); + return digest.length; + } + + @Override + protected void engineReset() { + } + } +}