Skip to content

Commit

Permalink
Collections-852: add layerd bloom filter clean method (#476)
Browse files Browse the repository at this point in the history
* Initial implementation and LayerManager test

* updated LayeredBloomFilterTest - fixed checkstyle issues

* changes as requested in review
  • Loading branch information
Claudenw committed Apr 17, 2024
1 parent de05f5f commit cc651b2
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public LayerManager build() {
*
* @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<LinkedList<BloomFilter>> cleanup) {
this.cleanup = cleanup;
Expand Down Expand Up @@ -375,9 +375,23 @@ public final BloomFilter getTarget() {
* Ths method is used within {@link #getTarget()} when the configured
* {@code ExtendCheck} returns {@code true}.
* </p>
* @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();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -369,12 +369,24 @@ public boolean merge(IndexProducer indexProducer) {
}

/**
* 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();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -291,4 +291,13 @@ public void testTarget() {
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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -30,6 +31,7 @@

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<LayeredBloomFilter> {
Expand Down Expand Up @@ -311,4 +313,36 @@ public final void testNext() {
assertFalse(filter.get(1).contains(TestingHashers.FROM11));
assertTrue(filter.get(1).contains(new IncrementingHasher(11, 2)));
}

@Test
public void testCleanup() {
int[] sequence = {1};
LayerManager layerManager = LayerManager.builder()
.setSupplier(() -> 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.
}
}

0 comments on commit cc651b2

Please sign in to comment.