Use java.time

This commit is contained in:
Gary Gregory 2024-08-25 16:59:49 -04:00
parent d243ff4fde
commit a06dee1b39
1 changed files with 26 additions and 30 deletions

View File

@ -21,11 +21,12 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Deque; import java.util.Deque;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -40,16 +41,16 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom
* A Predicate that advances after a quantum of time. * A Predicate that advances after a quantum of time.
*/ */
static class AdvanceOnTimeQuanta implements Predicate<LayerManager<TimestampedBloomFilter>> { static class AdvanceOnTimeQuanta implements Predicate<LayerManager<TimestampedBloomFilter>> {
long quanta; Duration quanta;
AdvanceOnTimeQuanta(final long quanta, final TimeUnit unit) { AdvanceOnTimeQuanta(final Duration quanta) {
this.quanta = unit.toMillis(quanta); this.quanta = quanta;
} }
@Override @Override
public boolean test(final LayerManager<TimestampedBloomFilter> lm) { public boolean test(final LayerManager<TimestampedBloomFilter> layerManager) {
// can not use getTarget() as it causes recursion. // can not use getTarget() as it causes recursion.
return lm.last().timestamp + quanta < System.currentTimeMillis(); return layerManager.last().getTimestamp().plus(quanta).isBefore(Instant.now());
} }
} }
@ -58,23 +59,22 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom
* the list. * the list.
*/ */
static class CleanByTime<T extends TimestampedBloomFilter> implements Consumer<List<T>> { static class CleanByTime<T extends TimestampedBloomFilter> implements Consumer<List<T>> {
long elapsedTime; Duration elapsedTime;
CleanByTime(final long duration, final TimeUnit unit) { CleanByTime(final Duration elapsedTime) {
elapsedTime = unit.toMillis(duration); this.elapsedTime = elapsedTime;
} }
@Override @Override
public void accept(final List<T> t) { public void accept(final List<T> t) {
final long min = System.currentTimeMillis() - elapsedTime; final Instant min = Instant.now().minus(elapsedTime);
final Iterator<T> iter = t.iterator(); final Iterator<T> iter = t.iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
final TimestampedBloomFilter bf = iter.next(); final TimestampedBloomFilter bf = iter.next();
if (bf.getTimestamp() >= min) { if (bf.getTimestamp().isAfter(min) || bf.getTimestamp().equals(min)) {
return; return;
} }
dbgInstrument.add(String.format("Removing old entry: T:%s (Aged: %s) \n", bf.getTimestamp(), dbgInstrument.add(String.format("Removing old entry: T:%s (Aged: %s) \n", bf.getTimestamp(), Duration.between(bf.getTimestamp(), min)));
min - bf.getTimestamp()));
iter.remove(); iter.remove();
} }
} }
@ -96,17 +96,17 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom
} }
/** /**
* A Bloomfilter implementation that tracks the creation time. * A Bloom filter implementation that tracks the creation time.
*/ */
public static class TimestampedBloomFilter extends WrappedBloomFilter { public static class TimestampedBloomFilter extends WrappedBloomFilter {
final long timestamp;
private final Instant timestamp;
TimestampedBloomFilter(final BloomFilter bf) { TimestampedBloomFilter(final BloomFilter bf) {
super(bf); this(bf, Instant.now());
this.timestamp = System.currentTimeMillis();
} }
TimestampedBloomFilter(final BloomFilter bf, final long timestamp) { TimestampedBloomFilter(final BloomFilter bf, final Instant timestamp) {
super(bf); super(bf);
this.timestamp = timestamp; this.timestamp = timestamp;
} }
@ -116,7 +116,7 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom
return new TimestampedBloomFilter(getWrapped().copy(), timestamp); return new TimestampedBloomFilter(getWrapped().copy(), timestamp);
} }
public long getTimestamp() { public Instant getTimestamp() {
return timestamp; return timestamp;
} }
} }
@ -131,20 +131,17 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom
* *
* @param shape The shape of the Bloom filters. * @param shape The shape of the Bloom filters.
* @param duration The length of time to keep filters in the list. * @param duration The length of time to keep filters in the list.
* @param dUnit The unit of time to apply to duration.
* @param quanta The quantization factor for each filter. Individual filters * @param quanta The quantization factor for each filter. Individual filters
* will span at most this much time. * will span at most this much time.
* @param qUnit the unit of time to apply to quanta.
* @return LayeredBloomFilter with the above properties. * @return LayeredBloomFilter with the above properties.
*/ */
static LayeredBloomFilter<TimestampedBloomFilter> createTimedLayeredFilter(final Shape shape, final long duration, final TimeUnit dUnit, final long quanta, static LayeredBloomFilter<TimestampedBloomFilter> createTimedLayeredFilter(final Shape shape, final Duration duration, final Duration quanta) {
final TimeUnit qUnit) {
final LayerManager.Builder<TimestampedBloomFilter> builder = LayerManager.builder(); final LayerManager.Builder<TimestampedBloomFilter> builder = LayerManager.builder();
final Consumer<Deque<TimestampedBloomFilter>> cleanup = Cleanup.removeEmptyTarget().andThen(new CleanByTime(duration, dUnit)); final Consumer<Deque<TimestampedBloomFilter>> cleanup = Cleanup.removeEmptyTarget().andThen(new CleanByTime(duration));
final LayerManager<TimestampedBloomFilter> layerManager = builder final LayerManager<TimestampedBloomFilter> layerManager = builder
.setSupplier(() -> new TimestampedBloomFilter(new SimpleBloomFilter(shape))) .setSupplier(() -> new TimestampedBloomFilter(new SimpleBloomFilter(shape)))
.setCleanup(cleanup) .setCleanup(cleanup)
.setExtendCheck(new AdvanceOnTimeQuanta(quanta, qUnit) .setExtendCheck(new AdvanceOnTimeQuanta(quanta)
.or(LayerManager.ExtendCheck.advanceOnSaturation(shape.estimateMaxN()))) .or(LayerManager.ExtendCheck.advanceOnSaturation(shape.estimateMaxN())))
.build(); .build();
return new LayeredBloomFilter<>(shape, layerManager); return new LayeredBloomFilter<>(shape, layerManager);
@ -183,8 +180,8 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom
// 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 -> {
final TimestampedBloomFilter tbf = (TimestampedBloomFilter) bf; final TimestampedBloomFilter tbf = (TimestampedBloomFilter) bf;
final long ts = System.currentTimeMillis(); final Instant ts = Instant.now();
dbgInstrument.add(String.format("T:%s (Elapsed:%s)- EstN:%s (Card:%s)\n", tbf.timestamp, ts - tbf.timestamp, dbgInstrument.add(String.format("T:%s (Elapsed:%s)- EstN:%s (Card:%s)\n", tbf.timestamp, Duration.between(tbf.timestamp, ts),
tbf.estimateN(), tbf.cardinality())); tbf.estimateN(), tbf.cardinality()));
return true; return true;
}; };
@ -280,13 +277,12 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom
// purposes. // purposes.
// list of timestamps that are expected to be expired. // list of timestamps that are expected to be expired.
final List<Long> lst = new ArrayList<>(); final List<Instant> lst = new ArrayList<>();
final Shape shape = Shape.fromNM(4, 64); final Shape shape = Shape.fromNM(4, 64);
// create a filter that removes filters that are 4 seconds old // create a filter that removes filters that are 4 seconds old
// and quantises time to 1 second intervals. // and quantises time to 1 second intervals.
final LayeredBloomFilter<TimestampedBloomFilter> underTest = createTimedLayeredFilter(shape, 600, TimeUnit.MILLISECONDS, 150, final LayeredBloomFilter<TimestampedBloomFilter> underTest = createTimedLayeredFilter(shape, Duration.ofMillis(600), Duration.ofMillis(150));
TimeUnit.MILLISECONDS);
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
underTest.merge(TestingHashers.randomHasher()); underTest.merge(TestingHashers.randomHasher());