From 2c35b9c1c9bdad91c4ebba47eb506692faab3400 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sat, 13 Apr 2024 16:13:01 -0400 Subject: [PATCH 1/4] Remove useless call to String.format() --- .../org/apache/commons/collections4/bloomfilter/Shape.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/apache/commons/collections4/bloomfilter/Shape.java b/src/main/java/org/apache/commons/collections4/bloomfilter/Shape.java index 28667c309..86cd9cd07 100644 --- a/src/main/java/org/apache/commons/collections4/bloomfilter/Shape.java +++ b/src/main/java/org/apache/commons/collections4/bloomfilter/Shape.java @@ -137,8 +137,7 @@ public final class Shape { // exp(-1/Integer.MAX_INT) approx 0.9999999995343387 so Math.pow( x, y ) will // always be 00 if (probability >= 1.0) { - throw new IllegalArgumentException( - String.format("Calculated probability is greater than or equal to 1: " + probability)); + throw new IllegalArgumentException("Calculated probability is greater than or equal to 1: " + probability); } } From de05f5f126e39a0e907abbcec68ee2554eece779 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sat, 13 Apr 2024 16:14:55 -0400 Subject: [PATCH 2/4] Use long lines --- .../commons/collections4/bloomfilter/Shape.java | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/apache/commons/collections4/bloomfilter/Shape.java b/src/main/java/org/apache/commons/collections4/bloomfilter/Shape.java index 86cd9cd07..8a184e7da 100644 --- a/src/main/java/org/apache/commons/collections4/bloomfilter/Shape.java +++ b/src/main/java/org/apache/commons/collections4/bloomfilter/Shape.java @@ -111,8 +111,7 @@ public final class Shape { // than integer math. final long k = Math.round(LN_2 * numberOfBits / numberOfItems); if (k < 1) { - throw new IllegalArgumentException( - String.format("Filter too small: Calculated number of hash functions (%s) was less than 1", k)); + throw new IllegalArgumentException(String.format("Filter too small: Calculated number of hash functions (%s) was less than 1", k)); } // Normally we would check that numberOfHashFunctions <= Integer.MAX_VALUE but // since numberOfBits is at most Integer.MAX_VALUE the numerator of @@ -164,8 +163,7 @@ public final class Shape { */ private static int checkNumberOfHashFunctions(final int numberOfHashFunctions) { if (numberOfHashFunctions < 1) { - throw new IllegalArgumentException( - "Number of hash functions must be greater than 0: " + numberOfHashFunctions); + throw new IllegalArgumentException("Number of hash functions must be greater than 0: " + numberOfHashFunctions); } return numberOfHashFunctions; } @@ -329,8 +327,7 @@ public final class Shape { // Number of items (n): // n = ceil(m / (-k / ln(1 - exp(ln(p) / k)))) - final double n = Math.ceil(numberOfBits - / (-numberOfHashFunctions / Math.log(-Math.expm1(Math.log(probability) / numberOfHashFunctions)))); + final double n = Math.ceil(numberOfBits / (-numberOfHashFunctions / Math.log(-Math.expm1(Math.log(probability) / numberOfHashFunctions)))); // log of probability is always < 0 // number of hash functions is >= 1 @@ -377,8 +374,7 @@ public final class Shape { // Shape is final so no check for the same class as inheritance is not possible if (obj instanceof Shape) { final Shape other = (Shape) obj; - return numberOfBits == other.numberOfBits && - numberOfHashFunctions == other.numberOfHashFunctions; + return numberOfBits == other.numberOfBits && numberOfHashFunctions == other.numberOfHashFunctions; } return false; } @@ -462,8 +458,7 @@ public final class Shape { if (numberOfItems == 0) { return 0; } - return Math.pow(-Math.expm1(-1.0 * numberOfHashFunctions * numberOfItems / numberOfBits), - numberOfHashFunctions); + return Math.pow(-Math.expm1(-1.0 * numberOfHashFunctions * numberOfItems / numberOfBits), numberOfHashFunctions); } @Override From cc651b2db9eed97e9e02ee2bb521c3c47807f4a9 Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Wed, 17 Apr 2024 13:48:39 +0100 Subject: [PATCH 3/4] Collections-852: add layerd bloom filter clean method (#476) * Initial implementation and LayerManager test * updated LayeredBloomFilterTest - fixed checkstyle issues * changes as requested in review --- .../bloomfilter/LayerManager.java | 16 ++++++++- .../bloomfilter/LayeredBloomFilter.java | 18 ++++++++-- .../bloomfilter/LayerManagerTest.java | 9 +++++ .../bloomfilter/LayeredBloomFilterTest.java | 34 +++++++++++++++++++ 4 files changed, 73 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/apache/commons/collections4/bloomfilter/LayerManager.java b/src/main/java/org/apache/commons/collections4/bloomfilter/LayerManager.java index a80d3c4cc..b139d16ce 100644 --- a/src/main/java/org/apache/commons/collections4/bloomfilter/LayerManager.java +++ b/src/main/java/org/apache/commons/collections4/bloomfilter/LayerManager.java @@ -82,7 +82,7 @@ public class LayerManager implements BloomFilterProducer { * * @param cleanup the Consumer that will modify the list of filters removing out * dated or stale filters. - * @return this for chaining. + * @return this */ public Builder setCleanup(Consumer> cleanup) { this.cleanup = cleanup; @@ -375,9 +375,23 @@ public class LayerManager implements BloomFilterProducer { * Ths method is used within {@link #getTarget()} when the configured * {@code ExtendCheck} returns {@code true}. *

+ * @see LayerManager.Builder#setExtendCheck(Predicate) + * @see LayerManager.Builder#setCleanup(Consumer) */ void next() { this.filterCleanup.accept(filters); addFilter(); } + + /** + * Forces execution the configured cleanup without creating a new filter except in cases + * where the cleanup removes all the layers. + * @see LayerManager.Builder#setCleanup(Consumer) + */ + void cleanup() { + this.filterCleanup.accept(filters); + if (filters.isEmpty()) { + addFilter(); + } + } } diff --git a/src/main/java/org/apache/commons/collections4/bloomfilter/LayeredBloomFilter.java b/src/main/java/org/apache/commons/collections4/bloomfilter/LayeredBloomFilter.java index 01e32d8b6..9ed2688bb 100644 --- a/src/main/java/org/apache/commons/collections4/bloomfilter/LayeredBloomFilter.java +++ b/src/main/java/org/apache/commons/collections4/bloomfilter/LayeredBloomFilter.java @@ -369,12 +369,24 @@ public class LayeredBloomFilter implements BloomFilter, BloomFilterProducer { } /** - * Forces and advance to the next layer. Executes the same logic as when - * LayerManager.extendCheck returns {@code true} + * Forces and advance to the next layer. This method will clean-up the current + * layers and generate a new filter layer. In most cases is it unnecessary to + * call this method directly. * - * @see LayerManager + * @see LayerManager.Builder#setCleanup(java.util.function.Consumer) + * @see LayerManager.Builder#setExtendCheck(Predicate) */ public void next() { layerManager.next(); } + + /** + * Forces the execution of the cleanup Consumer that was provided when the associated LayerManager + * was built. + * + * @see LayerManager.Builder#setCleanup(java.util.function.Consumer) + */ + public void cleanup() { + layerManager.cleanup(); + } } diff --git a/src/test/java/org/apache/commons/collections4/bloomfilter/LayerManagerTest.java b/src/test/java/org/apache/commons/collections4/bloomfilter/LayerManagerTest.java index 679f263e3..4ee438b89 100644 --- a/src/test/java/org/apache/commons/collections4/bloomfilter/LayerManagerTest.java +++ b/src/test/java/org/apache/commons/collections4/bloomfilter/LayerManagerTest.java @@ -291,4 +291,13 @@ public class LayerManagerTest { assertEquals(2, supplierCount[0]); } + static class NumberedBloomFilter extends WrappedBloomFilter { + int value; + int sequence; + NumberedBloomFilter(Shape shape, int value, int sequence) { + super(new SimpleBloomFilter(shape)); + this.value = value; + this.sequence = sequence; + } + } } diff --git a/src/test/java/org/apache/commons/collections4/bloomfilter/LayeredBloomFilterTest.java b/src/test/java/org/apache/commons/collections4/bloomfilter/LayeredBloomFilterTest.java index bd4e59ca9..0859e58c6 100644 --- a/src/test/java/org/apache/commons/collections4/bloomfilter/LayeredBloomFilterTest.java +++ b/src/test/java/org/apache/commons/collections4/bloomfilter/LayeredBloomFilterTest.java @@ -16,6 +16,7 @@ */ package org.apache.commons.collections4.bloomfilter; +import static org.junit.Assert.assertEquals; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -30,6 +31,7 @@ import java.util.function.Predicate; import org.apache.commons.collections4.bloomfilter.LayerManager.Cleanup; import org.apache.commons.collections4.bloomfilter.LayerManager.ExtendCheck; +import org.apache.commons.collections4.bloomfilter.LayerManagerTest.NumberedBloomFilter; import org.junit.jupiter.api.Test; public class LayeredBloomFilterTest extends AbstractBloomFilterTest { @@ -311,4 +313,36 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest new NumberedBloomFilter(getTestShape(), 3, sequence[0]++)) + .setExtendCheck(ExtendCheck.neverAdvance()) + .setCleanup(ll -> ll.removeIf( f -> (((NumberedBloomFilter) f).value-- == 0))).build(); + LayeredBloomFilter underTest = new LayeredBloomFilter(getTestShape(), layerManager ); + assertEquals(1, underTest.getDepth()); + underTest.merge(TestingHashers.randomHasher()); + underTest.cleanup(); // first count == 2 + assertEquals(1, underTest.getDepth()); + underTest.next(); // first count == 1 + assertEquals(2, underTest.getDepth()); + underTest.merge(TestingHashers.randomHasher()); + underTest.cleanup(); // first count == 0 + NumberedBloomFilter f = (NumberedBloomFilter) underTest.get(0); + assertEquals(1, f.sequence); + + assertEquals(2, underTest.getDepth()); + underTest.cleanup(); // should be removed ; second is now 1st with value 1 + assertEquals(1, underTest.getDepth()); + f = (NumberedBloomFilter) underTest.get(0); + assertEquals(2, f.sequence); + + underTest.cleanup(); // first count == 0 + underTest.cleanup(); // should be removed. But there is always at least one + assertEquals(1, underTest.getDepth()); + f = (NumberedBloomFilter) underTest.get(0); + assertEquals(3, f.sequence); // it is a new one. + } } From cb47bc8c5a00c887b168befa3f499410deba5289 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 17 Apr 2024 08:50:51 -0400 Subject: [PATCH 4/4] [COLLECTIONS-852] Add layerd bloom filter clean method #476 --- src/changes/changes.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index bfd18c3aa..b49aeba4d 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -23,6 +23,8 @@ + + Add layerd bloom filter clean method #476 . Bump org.apache.commons:commons-parent from 67 to 69 #473.