diff --git a/activemq-core/src/main/java/org/apache/activemq/util/BitArrayBin.java b/activemq-core/src/main/java/org/apache/activemq/util/BitArrayBin.java index 846abdeadd..7ab7339534 100755 --- a/activemq-core/src/main/java/org/apache/activemq/util/BitArrayBin.java +++ b/activemq-core/src/main/java/org/apache/activemq/util/BitArrayBin.java @@ -28,7 +28,6 @@ public class BitArrayBin { private LinkedList list; private int maxNumberOfArrays; private int firstIndex = -1; - private int firstBin = -1; private long lastInOrderBit=-1; /** @@ -54,16 +53,13 @@ public class BitArrayBin { * @return true if set */ public boolean setBit(long index, boolean value) { - boolean answer = true; + boolean answer = false; BitArray ba = getBitArray(index); if (ba != null) { int offset = getOffset(index); if (offset >= 0) { answer = ba.set(offset, value); } - if (value) { - }else { - } } return answer; } @@ -117,14 +113,16 @@ public class BitArrayBin { int bin = getBin(index); BitArray answer = null; if (bin >= 0) { - if (firstIndex < 0) { - firstIndex = 0; - } - if (bin >= list.size()) { - list.removeFirst(); - firstIndex += BitArray.LONG_SIZE; - list.add(new BitArray()); - bin = list.size() - 1; + if (bin >= maxNumberOfArrays) { + int overShoot = bin - maxNumberOfArrays + 1; + while (overShoot > 0) { + list.removeFirst(); + firstIndex += BitArray.LONG_SIZE; + list.add(new BitArray()); + overShoot--; + } + + bin = maxNumberOfArrays - 1; } answer = list.get(bin); if (answer == null) { @@ -143,8 +141,8 @@ public class BitArrayBin { */ private int getBin(long index) { int answer = 0; - if (firstBin < 0) { - firstBin = 0; + if (firstIndex < 0) { + firstIndex = (int) (index - (index % BitArray.LONG_SIZE)); } else if (firstIndex >= 0) { answer = (int)((index - firstIndex) / BitArray.LONG_SIZE); } diff --git a/activemq-core/src/test/java/org/apache/activemq/ActiveMQMessageAuditTest.java b/activemq-core/src/test/java/org/apache/activemq/ActiveMQMessageAuditTest.java index 5ac7d0ce3f..6676a3689a 100755 --- a/activemq-core/src/test/java/org/apache/activemq/ActiveMQMessageAuditTest.java +++ b/activemq-core/src/test/java/org/apache/activemq/ActiveMQMessageAuditTest.java @@ -67,8 +67,9 @@ public class ActiveMQMessageAuditTest extends TestCase { list.add(id); assertFalse(audit.isDuplicate(id)); } - for (String id : list) { - assertTrue(audit.isDuplicate(id)); + List windowList = list.subList(list.size() -1 -audit.getAuditDepth(), list.size() -1); + for (String id : windowList) { + assertTrue("duplicate, id:" + id, audit.isDuplicate(id)); } } @@ -90,8 +91,9 @@ public class ActiveMQMessageAuditTest extends TestCase { list.add(msg); assertFalse(audit.isDuplicate(msg.getMessageId())); } - for (MessageReference msg : list) { - assertTrue(audit.isDuplicate(msg)); + List windowList = list.subList(list.size() -1 -audit.getAuditDepth(), list.size() -1); + for (MessageReference msg : windowList) { + assertTrue("duplicate msg:" + msg, audit.isDuplicate(msg)); } } diff --git a/activemq-core/src/test/java/org/apache/activemq/util/BitArrayBinTest.java b/activemq-core/src/test/java/org/apache/activemq/util/BitArrayBinTest.java new file mode 100644 index 0000000000..01ed11e126 --- /dev/null +++ b/activemq-core/src/test/java/org/apache/activemq/util/BitArrayBinTest.java @@ -0,0 +1,108 @@ +package org.apache.activemq.util; + +import junit.framework.TestCase; + +public class BitArrayBinTest extends TestCase { + + public void testSetAroundWindow() throws Exception { + doTestSetAroundWindow(500, 2000); + doTestSetAroundWindow(512, 2000); + doTestSetAroundWindow(128, 512); + } + + private void doTestSetAroundWindow(int window, int dataSize) throws Exception { + + BitArrayBin toTest = new BitArrayBin(window); + + for (int i=0; i <= dataSize; i++) { + assertTrue("not already set", !toTest.setBit(i, Boolean.TRUE)); + } + + int windowOfValidData = roundWindow(dataSize, window); + int i=dataSize; + for (; i >= dataSize -windowOfValidData; i--) { + assertTrue("was already set, id=" + i, toTest.setBit(i, Boolean.TRUE)); + } + + for (; i >= 0; i--) { + assertTrue("was not already set, id=" + i, !toTest.setBit(i, Boolean.TRUE)); + } + + for (int j= dataSize +1; j<(2*dataSize); j++) { + assertTrue("not already set: id=" + j, !toTest.setBit(j, Boolean.TRUE)); + } + } + + public void testSetUnsetAroundWindow() throws Exception { + doTestSetUnSetAroundWindow(500, 2000); + doTestSetUnSetAroundWindow(512, 2000); + doTestSetUnSetAroundWindow(128, 512); + } + + private void doTestSetUnSetAroundWindow(int dataSize, int window) throws Exception { + + BitArrayBin toTest = new BitArrayBin(window); + + for (int i=0; i <=dataSize; i++) { + assertTrue("not already set", !toTest.setBit(i, Boolean.TRUE)); + } + + int windowOfValidData = roundWindow(dataSize, window); + for (int i=dataSize; i >= 0 && i >=dataSize -windowOfValidData; i--) { + assertTrue("was already set, id=" + i, toTest.setBit(i, Boolean.FALSE)); + } + + for (int i=0; i <=dataSize; i++) { + assertTrue("not already set, id:" + i, !toTest.setBit(i, Boolean.TRUE)); + } + + for (int j= 2*dataSize; j< 4*dataSize; j++) { + assertTrue("not already set: id=" + j, !toTest.setBit(j, Boolean.TRUE)); + } + } + + public void testSetAroundLongSizeMultiplier() throws Exception { + int window = 512; + int dataSize = 1000; + for (int muliplier=1; muliplier <8; muliplier++) { + for (int value=0; value