Sort members

This commit is contained in:
Gary Gregory 2024-05-12 08:38:43 -04:00
parent 1a9ff2f6ba
commit 5051dbf0b5
5 changed files with 165 additions and 165 deletions

View File

@ -299,6 +299,18 @@ public class LayerManager<T extends BloomFilter> implements BloomFilterProducer
filters.add(bf); filters.add(bf);
} }
/**
* 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();
}
}
/** /**
* Removes all the filters from the layer manager, and sets up a new one as the * Removes all the filters from the layer manager, and sets up a new one as the
* target. * target.
@ -325,6 +337,16 @@ public class LayerManager<T extends BloomFilter> implements BloomFilterProducer
return newMgr; return newMgr;
} }
/**
* Gets the Bloom filter from the first layer.
* No extension check is performed during this call.
* @return The Bloom filter from the first layer.
* @see #getTarget()
*/
public final T first() {
return filters.getFirst();
}
/** /**
* Executes a Bloom filter Predicate on each Bloom filter in the manager in * Executes a Bloom filter Predicate on each Bloom filter in the manager in
* depth order. Oldest filter first. * depth order. Oldest filter first.
@ -369,26 +391,6 @@ public class LayerManager<T extends BloomFilter> implements BloomFilterProducer
return filters.size(); return filters.size();
} }
/**
* Gets the Bloom filter from the first layer.
* No extension check is performed during this call.
* @return The Bloom filter from the first layer.
* @see #getTarget()
*/
public final T first() {
return filters.getFirst();
}
/**
* Gets the Bloom filter from the last layer.
* No extension check is performed during this call.
* @return The Bloom filter from the last layer.
* @see #getTarget()
*/
public final T last() {
return filters.getLast();
}
/** /**
* Returns the current target filter. If a new filter should be created based on * Returns the current target filter. If a new filter should be created based on
* {@code extendCheck} it will be created before this method returns. * {@code extendCheck} it will be created before this method returns.
@ -402,6 +404,16 @@ public class LayerManager<T extends BloomFilter> implements BloomFilterProducer
return last(); return last();
} }
/**
* Gets the Bloom filter from the last layer.
* No extension check is performed during this call.
* @return The Bloom filter from the last layer.
* @see #getTarget()
*/
public final T last() {
return filters.getLast();
}
/** /**
* Forces an advance to the next depth. This method will clean-up the current * Forces an advance to the next depth. This method will clean-up the current
* layers and generate a new filter layer. In most cases is it unnecessary to * layers and generate a new filter layer. In most cases is it unnecessary to
@ -417,16 +429,4 @@ public class LayerManager<T extends BloomFilter> implements BloomFilterProducer
this.filterCleanup.accept(filters); this.filterCleanup.accept(filters);
addFilter(); 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();
}
}
} }

View File

@ -115,6 +115,16 @@ public class LayeredBloomFilter<T extends BloomFilter> implements BloomFilter, B
return 0; return 0;
} }
/**
* 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();
}
@Override @Override
public final void clear() { public final void clear() {
layerManager.clear(); layerManager.clear();
@ -366,14 +376,4 @@ public class LayeredBloomFilter<T extends BloomFilter> implements BloomFilter, B
public void next() { public void next() {
layerManager.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();
}
} }

View File

@ -36,10 +36,6 @@ public abstract class WrappedBloomFilter implements BloomFilter {
this.wrapped = bf; this.wrapped = bf;
} }
protected BloomFilter getWrapped() {
return wrapped;
}
@Override @Override
public long[] asBitMapArray() { public long[] asBitMapArray() {
return wrapped.asBitMapArray(); return wrapped.asBitMapArray();
@ -120,6 +116,10 @@ public abstract class WrappedBloomFilter implements BloomFilter {
return wrapped.getShape(); return wrapped.getShape();
} }
protected BloomFilter getWrapped() {
return wrapped;
}
@Override @Override
public boolean isFull() { public boolean isFull() {
return wrapped.isFull(); return wrapped.isFull();

View File

@ -36,36 +36,6 @@ import org.junit.jupiter.api.Test;
public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloomFilter<?>> { public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloomFilter<?>> {
/**
* Creates a fixed size layered bloom filter that adds new filters to the list,
* but never merges them. List will never exceed maxDepth. As additional filters
* are added earlier filters are removed. Uses SimpleBloomFilters.
*
* @param shape The shape for the enclosed Bloom filters.
* @param maxDepth The maximum depth of layers.
* @return An empty layered Bloom filter of the specified shape and depth.
*/
public static LayeredBloomFilter<BloomFilter> fixed(final Shape shape, int maxDepth) {
return fixed(shape, maxDepth, () -> new SimpleBloomFilter(shape));
}
/**
* Creates a fixed size layered bloom filter that adds new filters to the list,
* but never merges them. List will never exceed maxDepth. As additional filters
* are added earlier filters are removed.
*
* @param shape The shape for the enclosed Bloom filters.
* @param maxDepth The maximum depth of layers.
* @param supplier A supplier of the Bloom filters to create layers with.
* @return An empty layered Bloom filter of the specified shape and depth.
*/
public static <T extends BloomFilter> LayeredBloomFilter<T> fixed(final Shape shape, int maxDepth, Supplier<T> supplier) {
LayerManager.Builder<T> builder = LayerManager.builder();
builder.setExtendCheck(LayerManager.ExtendCheck.advanceOnPopulated())
.setCleanup(LayerManager.Cleanup.onMaxSize(maxDepth)).setSupplier(supplier);
return new LayeredBloomFilter<>(shape, builder.build());
}
/** /**
* A Predicate that advances after a quantum of time. * A Predicate that advances after a quantum of time.
*/ */
@ -111,6 +81,21 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom
} }
} }
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;
}
@Override
public BloomFilter copy() {
return new NumberedBloomFilter(getShape(), value, sequence);
}
}
/** /**
* A Bloomfilter implementation that tracks the creation time. * A Bloomfilter implementation that tracks the creation time.
*/ */
@ -127,14 +112,14 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom
this.timestamp = timestamp; this.timestamp = timestamp;
} }
public long getTimestamp() {
return timestamp;
}
@Override @Override
public TimestampedBloomFilter copy() { public TimestampedBloomFilter copy() {
return new TimestampedBloomFilter(this.getWrapped().copy(), timestamp); return new TimestampedBloomFilter(this.getWrapped().copy(), timestamp);
} }
public long getTimestamp() {
return timestamp;
}
} }
// ***example of instrumentation *** // ***example of instrumentation ***
@ -166,6 +151,36 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom
return new LayeredBloomFilter<>(shape, layerManager); return new LayeredBloomFilter<>(shape, layerManager);
} }
/**
* Creates a fixed size layered bloom filter that adds new filters to the list,
* but never merges them. List will never exceed maxDepth. As additional filters
* are added earlier filters are removed. Uses SimpleBloomFilters.
*
* @param shape The shape for the enclosed Bloom filters.
* @param maxDepth The maximum depth of layers.
* @return An empty layered Bloom filter of the specified shape and depth.
*/
public static LayeredBloomFilter<BloomFilter> fixed(final Shape shape, int maxDepth) {
return fixed(shape, maxDepth, () -> new SimpleBloomFilter(shape));
}
/**
* Creates a fixed size layered bloom filter that adds new filters to the list,
* but never merges them. List will never exceed maxDepth. As additional filters
* are added earlier filters are removed.
*
* @param shape The shape for the enclosed Bloom filters.
* @param maxDepth The maximum depth of layers.
* @param supplier A supplier of the Bloom filters to create layers with.
* @return An empty layered Bloom filter of the specified shape and depth.
*/
public static <T extends BloomFilter> LayeredBloomFilter<T> fixed(final Shape shape, int maxDepth, Supplier<T> supplier) {
LayerManager.Builder<T> builder = LayerManager.builder();
builder.setExtendCheck(LayerManager.ExtendCheck.advanceOnPopulated())
.setCleanup(LayerManager.Cleanup.onMaxSize(maxDepth)).setSupplier(supplier);
return new LayeredBloomFilter<>(shape, builder.build());
}
// instrumentation to record timestamps in dbgInstrument list // instrumentation to record timestamps in dbgInstrument list
private final Predicate<BloomFilter> dbg = (bf) -> { private final Predicate<BloomFilter> dbg = (bf) -> {
TimestampedBloomFilter tbf = (TimestampedBloomFilter) bf; TimestampedBloomFilter tbf = (TimestampedBloomFilter) bf;
@ -214,6 +229,39 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom
testCardinalityAndIsEmpty(new LayeredBloomFilter<>(getTestShape(), layerManager)); testCardinalityAndIsEmpty(new LayeredBloomFilter<>(getTestShape(), layerManager));
} }
// ***** TESTS THAT CHECK LAYERED PROCESSING ******
@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.
}
/** /**
* Tests that the estimated union calculations are correct. * Tests that the estimated union calculations are correct.
*/ */
@ -227,8 +275,6 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom
assertEquals(2, bf2.estimateUnion(bf)); assertEquals(2, bf2.estimateUnion(bf));
} }
// ***** TESTS THAT CHECK LAYERED PROCESSING ******
@Test @Test
public void testExpiration() throws InterruptedException { public void testExpiration() throws InterruptedException {
// this test uses the instrumentation noted above to track changes for debugging // this test uses the instrumentation noted above to track changes for debugging
@ -270,6 +316,7 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom
assertTrue(underTest.forEachBloomFilter(dbg.and(x -> !lst.contains(((TimestampedBloomFilter) x).timestamp))), assertTrue(underTest.forEachBloomFilter(dbg.and(x -> !lst.contains(((TimestampedBloomFilter) x).timestamp))),
"Found filter that should have been deleted: " + dbgInstrument.get(dbgInstrument.size() - 1)); "Found filter that should have been deleted: " + dbgInstrument.get(dbgInstrument.size() - 1));
} }
@Test @Test
public void testFindBitMapProducer() { public void testFindBitMapProducer() {
LayeredBloomFilter<BloomFilter> filter = setupFindTest(); LayeredBloomFilter<BloomFilter> filter = setupFindTest();
@ -359,51 +406,4 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom
assertFalse(filter.get(1).contains(TestingHashers.FROM11)); assertFalse(filter.get(1).contains(TestingHashers.FROM11));
assertTrue(filter.get(1).contains(new IncrementingHasher(11, 2))); 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.
}
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;
}
@Override
public BloomFilter copy() {
return new NumberedBloomFilter(getShape(), value, sequence);
}
}
} }

View File

@ -32,6 +32,22 @@ import org.junit.jupiter.api.Test;
*/ */
public class DefaultAbstractLinkedListForJava21Test<E> extends AbstractListTest<E> { public class DefaultAbstractLinkedListForJava21Test<E> extends AbstractListTest<E> {
private static class DefaultAbstractLinkedListForJava21<E> extends AbstractLinkedListForJava21<E> {
DefaultAbstractLinkedListForJava21() {
init();
}
private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
doReadObject(in);
}
private void writeObject(final ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
doWriteObject(out);
}
}
public DefaultAbstractLinkedListForJava21Test() { public DefaultAbstractLinkedListForJava21Test() {
super(DefaultAbstractLinkedListForJava21Test.class.getSimpleName()); super(DefaultAbstractLinkedListForJava21Test.class.getSimpleName());
} }
@ -47,6 +63,26 @@ public class DefaultAbstractLinkedListForJava21Test<E> extends AbstractListTest<
} }
} }
@Override
public AbstractLinkedListForJava21<E> getCollection() {
return (AbstractLinkedListForJava21<E>) super.getCollection();
}
@Override
public String getCompatibilityVersion() {
return null;
}
@Override
public List<E> makeObject() {
return new DefaultAbstractLinkedListForJava21<>();
}
@Override
protected boolean skipSerializedCanonicalTests() {
return true;
}
@Test @Test
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void testAddNodeAfter() { public void testAddNodeAfter() {
@ -178,26 +214,6 @@ public class DefaultAbstractLinkedListForJava21Test<E> extends AbstractListTest<
checkNodes(); checkNodes();
} }
@Override
public String getCompatibilityVersion() {
return null;
}
@Override
protected boolean skipSerializedCanonicalTests() {
return true;
}
@Override
public AbstractLinkedListForJava21<E> getCollection() {
return (AbstractLinkedListForJava21<E>) super.getCollection();
}
@Override
public List<E> makeObject() {
return new DefaultAbstractLinkedListForJava21<>();
}
@Test @Test
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void testSubList() { public void testSubList() {
@ -297,20 +313,4 @@ public class DefaultAbstractLinkedListForJava21Test<E> extends AbstractListTest<
assertEquals("[]", sublist.toString()); assertEquals("[]", sublist.toString());
assertEquals("[A, E]", list.toString()); assertEquals("[A, E]", list.toString());
} }
private static class DefaultAbstractLinkedListForJava21<E> extends AbstractLinkedListForJava21<E> {
DefaultAbstractLinkedListForJava21() {
init();
}
private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
doReadObject(in);
}
private void writeObject(final ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
doWriteObject(out);
}
}
} }