mirror of
https://github.com/usatiuk/dhfs.git
synced 2025-10-28 12:37:48 +01:00
Compare commits
1 Commits
2434b0464f
...
cursed-ite
| Author | SHA1 | Date | |
|---|---|---|---|
| 5cd0e5f045 |
@@ -1,6 +1,12 @@
|
||||
package com.usatiuk.objects.iterators;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface IterProdFn<K extends Comparable<K>, V> {
|
||||
CloseableKvIterator<K, V> get(IteratorStart start, K key);
|
||||
|
||||
default Stream<CloseableKvIterator<K, MaybeTombstone<V>>> getFlat(IteratorStart start, K key) {
|
||||
return Stream.of(new MappingKvIterator<>(get(start, key), Data::new));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
package com.usatiuk.objects.iterators;
|
||||
|
||||
import io.quarkus.logging.Log;
|
||||
import org.apache.commons.lang3.mutable.MutableInt;
|
||||
import org.apache.commons.lang3.mutable.MutableObject;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.NavigableMap;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.TreeMap;
|
||||
import java.util.*;
|
||||
|
||||
public class MergingKvIterator<K extends Comparable<K>, V> extends ReversibleKvIterator<K, V> {
|
||||
private record IteratorEntry<K extends Comparable<K>, V>(int priority, CloseableKvIterator<K, V> iterator) {
|
||||
public class MergingKvIterator<K extends Comparable<K>, V> extends ReversibleKvIterator<K, MaybeTombstone<V>> {
|
||||
private record IteratorEntry<K extends Comparable<K>, V>(int priority,
|
||||
CloseableKvIterator<K, MaybeTombstone<V>> iterator) {
|
||||
public IteratorEntry<K, V> reversed() {
|
||||
return new IteratorEntry<>(priority, iterator.reversed());
|
||||
}
|
||||
@@ -26,11 +25,13 @@ public class MergingKvIterator<K extends Comparable<K>, V> extends ReversibleKvI
|
||||
|
||||
// Why streams are so slow?
|
||||
{
|
||||
IteratorEntry<K, V>[] iteratorEntries = new IteratorEntry[iterators.size()];
|
||||
for (int i = 0; i < iterators.size(); i++) {
|
||||
iteratorEntries[i] = new IteratorEntry<>(i, iterators.get(i).get(startType, startKey));
|
||||
}
|
||||
_iterators = List.of(iteratorEntries);
|
||||
var iteratorsTmp = iterators.stream().flatMap(i -> i.getFlat(startType, startKey));
|
||||
MutableInt i = new MutableInt(0);
|
||||
ArrayList<IteratorEntry<K, V>> tmp = new ArrayList<>(16);
|
||||
iteratorsTmp.forEach(i2 -> {
|
||||
tmp.add(new IteratorEntry<>(i.getAndIncrement(), i2));
|
||||
});
|
||||
_iterators = List.copyOf(tmp);
|
||||
}
|
||||
|
||||
if (startType == IteratorStart.LT || startType == IteratorStart.LE) {
|
||||
@@ -185,7 +186,7 @@ public class MergingKvIterator<K extends Comparable<K>, V> extends ReversibleKvI
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Pair<K, V> nextImpl() {
|
||||
protected Pair<K, MaybeTombstone<V>> nextImpl() {
|
||||
var cur = _goingForward ? _sortedIterators.pollFirstEntry() : _sortedIterators.pollLastEntry();
|
||||
if (cur == null) {
|
||||
throw new NoSuchElementException();
|
||||
|
||||
@@ -9,7 +9,7 @@ public class TombstoneMergingKvIterator<K extends Comparable<K>, V> implements C
|
||||
private final CloseableKvIterator<K, V> _backing;
|
||||
private final String _name;
|
||||
|
||||
public TombstoneMergingKvIterator(String name, IteratorStart startType, K startKey, List<IterProdFn<K, MaybeTombstone<V>>> iterators) {
|
||||
public TombstoneMergingKvIterator(String name, IteratorStart startType, K startKey, List<IterProdFn<K, V>> iterators) {
|
||||
_name = name;
|
||||
_backing = new PredicateKvIterator<>(
|
||||
new MergingKvIterator<>(name + "-merging", startType, startKey, iterators),
|
||||
@@ -24,7 +24,7 @@ public class TombstoneMergingKvIterator<K extends Comparable<K>, V> implements C
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public TombstoneMergingKvIterator(String name, IteratorStart startType, K startKey, IterProdFn<K, MaybeTombstone<V>>... iterators) {
|
||||
public TombstoneMergingKvIterator(String name, IteratorStart startType, K startKey, IterProdFn<K, V>... iterators) {
|
||||
this(name, startType, startKey, List.of(iterators));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
package com.usatiuk.objects.snapshot;
|
||||
|
||||
import com.usatiuk.objects.JObjectKey;
|
||||
import com.usatiuk.objects.iterators.CloseableKvIterator;
|
||||
import com.usatiuk.objects.iterators.IteratorStart;
|
||||
import com.usatiuk.dhfs.utils.AutoCloseableNoThrow;
|
||||
import com.usatiuk.objects.iterators.CloseableKvIterator;
|
||||
import com.usatiuk.objects.iterators.IterProdFn;
|
||||
import com.usatiuk.objects.iterators.IteratorStart;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface Snapshot<K extends Comparable<K>, V> extends AutoCloseableNoThrow {
|
||||
CloseableKvIterator<K, V> getIterator(IteratorStart start, K key);
|
||||
IterProdFn<K, V> getIterator();
|
||||
|
||||
default CloseableKvIterator<K, V> getIterator(IteratorStart start, K key) {
|
||||
return getIterator().get(start, key);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
Optional<V> readObject(K name);
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@ApplicationScoped
|
||||
public class CachingObjectPersistentStore {
|
||||
@@ -186,17 +187,43 @@ public class CachingObjectPersistentStore {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CloseableKvIterator<JObjectKey, JDataVersionedWrapper> getIterator(IteratorStart start, JObjectKey key) {
|
||||
return new TombstoneMergingKvIterator<>("cache", start, key,
|
||||
(mS, mK)
|
||||
-> new MappingKvIterator<>(
|
||||
new NavigableMapKvIterator<>(_curCache.map(), mS, mK),
|
||||
e -> {
|
||||
public IterProdFn<JObjectKey, JDataVersionedWrapper> getIterator() {
|
||||
IterProdFn<JObjectKey, JDataVersionedWrapper> cacheItProdFn = new IterProdFn<JObjectKey, JDataVersionedWrapper>() {
|
||||
@Override
|
||||
public CloseableKvIterator<JObjectKey, JDataVersionedWrapper> get(IteratorStart start, JObjectKey key) {
|
||||
throw new UnsupportedOperationException("Not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<CloseableKvIterator<JObjectKey, MaybeTombstone<JDataVersionedWrapper>>> getFlat(IteratorStart start, JObjectKey key) {
|
||||
return Stream.of(
|
||||
new MappingKvIterator<>(
|
||||
new NavigableMapKvIterator<>(_curCache.map(), start, key),
|
||||
e -> {
|
||||
// Log.tracev("Taken from cache: {0}", e);
|
||||
return e.object();
|
||||
}
|
||||
),
|
||||
(mS, mK) -> new MappingKvIterator<>(new CachingKvIterator(_backing.getIterator(start, key)), Data::new));
|
||||
return e.object();
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
IterProdFn<JObjectKey, JDataVersionedWrapper> backingItProdFn = (mS, mK) -> new CachingKvIterator(_backing.getIterator(mS, mK));
|
||||
|
||||
return new IterProdFn<JObjectKey, JDataVersionedWrapper>() {
|
||||
@Override
|
||||
public CloseableKvIterator<JObjectKey, JDataVersionedWrapper> get(IteratorStart start, JObjectKey key) {
|
||||
return new TombstoneMergingKvIterator<>("cache", start, key, cacheItProdFn, backingItProdFn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<CloseableKvIterator<JObjectKey, MaybeTombstone<JDataVersionedWrapper>>> getFlat(IteratorStart start, JObjectKey key) {
|
||||
return Stream.concat(
|
||||
cacheItProdFn.getFlat(start, key),
|
||||
backingItProdFn.getFlat(start, key)
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
||||
@@ -6,7 +6,7 @@ import com.usatiuk.dhfs.utils.RefcountedCloseable;
|
||||
import com.usatiuk.objects.JObjectKey;
|
||||
import com.usatiuk.objects.JObjectKeyMax;
|
||||
import com.usatiuk.objects.JObjectKeyMin;
|
||||
import com.usatiuk.objects.iterators.CloseableKvIterator;
|
||||
import com.usatiuk.objects.iterators.IterProdFn;
|
||||
import com.usatiuk.objects.iterators.IteratorStart;
|
||||
import com.usatiuk.objects.iterators.KeyPredicateKvIterator;
|
||||
import com.usatiuk.objects.iterators.ReversibleKvIterator;
|
||||
@@ -121,9 +121,9 @@ public class LmdbObjectPersistentStore implements ObjectPersistentStore {
|
||||
private boolean _closed = false;
|
||||
|
||||
@Override
|
||||
public CloseableKvIterator<JObjectKey, ByteString> getIterator(IteratorStart start, JObjectKey key) {
|
||||
public IterProdFn<JObjectKey, ByteString> getIterator() {
|
||||
assert !_closed;
|
||||
return new KeyPredicateKvIterator<>(new LmdbKvIterator(_txn.ref(), start, key), start, key, (k) -> !k.value().equals(DB_VER_OBJ_NAME_STR));
|
||||
return (start, key) -> new KeyPredicateKvIterator<>(new LmdbKvIterator(_txn.ref(), start, key), start, key, (k) -> !k.value().equals(DB_VER_OBJ_NAME_STR));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
||||
@@ -2,9 +2,7 @@ package com.usatiuk.objects.stores;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.usatiuk.objects.JObjectKey;
|
||||
import com.usatiuk.objects.JObjectKeyImpl;
|
||||
import com.usatiuk.objects.iterators.CloseableKvIterator;
|
||||
import com.usatiuk.objects.iterators.IteratorStart;
|
||||
import com.usatiuk.objects.iterators.IterProdFn;
|
||||
import com.usatiuk.objects.iterators.NavigableMapKvIterator;
|
||||
import com.usatiuk.objects.snapshot.Snapshot;
|
||||
import io.quarkus.arc.properties.IfBuildProperty;
|
||||
@@ -38,8 +36,8 @@ public class MemoryObjectPersistentStore implements ObjectPersistentStore {
|
||||
private final long _lastCommitId = MemoryObjectPersistentStore.this._lastCommitId;
|
||||
|
||||
@Override
|
||||
public CloseableKvIterator<JObjectKey, ByteString> getIterator(IteratorStart start, JObjectKey key) {
|
||||
return new NavigableMapKvIterator<>(_objects, start, key);
|
||||
public IterProdFn<JObjectKey, ByteString> getIterator() {
|
||||
return (start, key) -> new NavigableMapKvIterator<>(_objects, start, key);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
||||
@@ -4,8 +4,7 @@ import com.google.protobuf.ByteString;
|
||||
import com.usatiuk.objects.JDataVersionedWrapper;
|
||||
import com.usatiuk.objects.JObjectKey;
|
||||
import com.usatiuk.objects.ObjectSerializer;
|
||||
import com.usatiuk.objects.iterators.CloseableKvIterator;
|
||||
import com.usatiuk.objects.iterators.IteratorStart;
|
||||
import com.usatiuk.objects.iterators.IterProdFn;
|
||||
import com.usatiuk.objects.iterators.MappingKvIterator;
|
||||
import com.usatiuk.objects.snapshot.Snapshot;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
@@ -33,8 +32,8 @@ public class SerializingObjectPersistentStore {
|
||||
private final Snapshot<JObjectKey, ByteString> _backing = delegateStore.getSnapshot();
|
||||
|
||||
@Override
|
||||
public CloseableKvIterator<JObjectKey, JDataVersionedWrapper> getIterator(IteratorStart start, JObjectKey key) {
|
||||
return new MappingKvIterator<>(_backing.getIterator(start, key), d -> serializer.deserialize(d));
|
||||
public IterProdFn<JObjectKey, JDataVersionedWrapper> getIterator() {
|
||||
return (start, key) -> new MappingKvIterator<>(_backing.getIterator(start, key), d -> serializer.deserialize(d));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
||||
@@ -27,6 +27,7 @@ import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@ApplicationScoped
|
||||
public class WritebackObjectPersistentStore {
|
||||
@@ -349,16 +350,37 @@ public class WritebackObjectPersistentStore {
|
||||
private final long txId = finalPw.lastCommittedId();
|
||||
|
||||
@Override
|
||||
public CloseableKvIterator<JObjectKey, JDataVersionedWrapper> getIterator(IteratorStart start, JObjectKey key) {
|
||||
return new TombstoneMergingKvIterator<>("writeback-ps", start, key,
|
||||
(tS, tK) -> new MappingKvIterator<>(
|
||||
new NavigableMapKvIterator<>(_pendingWrites, tS, tK),
|
||||
public IterProdFn<JObjectKey, JDataVersionedWrapper> getIterator() {
|
||||
IterProdFn<JObjectKey, JDataVersionedWrapper> cacheItProdFn = new IterProdFn<JObjectKey, JDataVersionedWrapper>() {
|
||||
@Override
|
||||
public CloseableKvIterator<JObjectKey, JDataVersionedWrapper> get(IteratorStart start, JObjectKey key) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<CloseableKvIterator<JObjectKey, MaybeTombstone<JDataVersionedWrapper>>> getFlat(IteratorStart start, JObjectKey key) {
|
||||
return Stream.of(new MappingKvIterator<>(
|
||||
new NavigableMapKvIterator<>(_pendingWrites, start, key),
|
||||
e -> switch (e) {
|
||||
case PendingWrite pw -> new Data<>(pw.data());
|
||||
case PendingDelete d -> new Tombstone<>();
|
||||
default -> throw new IllegalStateException("Unexpected value: " + e);
|
||||
}),
|
||||
(tS, tK) -> new MappingKvIterator<>(_cache.getIterator(tS, tK), Data::new));
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
return new IterProdFn<JObjectKey, JDataVersionedWrapper>() {
|
||||
@Override
|
||||
public CloseableKvIterator<JObjectKey, JDataVersionedWrapper> get(IteratorStart start, JObjectKey key) {
|
||||
return new TombstoneMergingKvIterator<>("writeback-ps", start, key,
|
||||
cacheItProdFn, _cache.getIterator());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<CloseableKvIterator<JObjectKey, MaybeTombstone<JDataVersionedWrapper>>> getFlat(IteratorStart start, JObjectKey key) {
|
||||
return Stream.concat(cacheItProdFn.getFlat(start, key), _cache.getIterator().getFlat(start, key));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
||||
@@ -7,13 +7,13 @@ import com.usatiuk.objects.iterators.*;
|
||||
import com.usatiuk.objects.snapshot.Snapshot;
|
||||
import com.usatiuk.objects.snapshot.SnapshotManager;
|
||||
import io.quarkus.logging.Log;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Singleton
|
||||
public class TransactionFactoryImpl implements TransactionFactory {
|
||||
@@ -161,17 +161,48 @@ public class TransactionFactoryImpl implements TransactionFactory {
|
||||
|
||||
@Override
|
||||
public CloseableKvIterator<JObjectKey, JData> getIterator(IteratorStart start, JObjectKey key) {
|
||||
|
||||
Log.tracev("Getting tx iterator with start={0}, key={1}", start, key);
|
||||
return new ReadTrackingIterator(new TombstoneMergingKvIterator<>("tx", start, key,
|
||||
(tS, tK) -> new MappingKvIterator<>(new NavigableMapKvIterator<>(_writes, tS, tK),
|
||||
t -> switch (t) {
|
||||
case TxRecord.TxObjectRecordWrite<?> write ->
|
||||
new Data<>(new ReadTrackingInternalCrapTx(write.data()));
|
||||
case TxRecord.TxObjectRecordDeleted deleted -> new Tombstone<>();
|
||||
case null, default -> null;
|
||||
}),
|
||||
(tS, tK) -> new MappingKvIterator<>(_snapshot.getIterator(tS, tK),
|
||||
d -> new Data<ReadTrackingInternalCrap>(new ReadTrackingInternalCrapSource(d)))));
|
||||
new IterProdFn<JObjectKey, ReadTrackingInternalCrap>() {
|
||||
@Override
|
||||
public CloseableKvIterator<JObjectKey, ReadTrackingInternalCrap> get(IteratorStart start, JObjectKey key) {
|
||||
throw new UnsupportedOperationException("Not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<CloseableKvIterator<JObjectKey, MaybeTombstone<ReadTrackingInternalCrap>>> getFlat(IteratorStart start, JObjectKey key) {
|
||||
return Stream.of(new MappingKvIterator<>(new NavigableMapKvIterator<>(_writes, start, key),
|
||||
t -> switch (t) {
|
||||
case TxRecord.TxObjectRecordWrite<?> write ->
|
||||
new Data<>(new ReadTrackingInternalCrapTx(write.data()));
|
||||
case TxRecord.TxObjectRecordDeleted deleted -> new Tombstone<>();
|
||||
case null, default -> null;
|
||||
}));
|
||||
}
|
||||
},
|
||||
new IterProdFn<JObjectKey, ReadTrackingInternalCrap>() {
|
||||
@Override
|
||||
public CloseableKvIterator<JObjectKey, ReadTrackingInternalCrap> get(IteratorStart start, JObjectKey key) {
|
||||
throw new UnsupportedOperationException("Not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<CloseableKvIterator<JObjectKey, MaybeTombstone<ReadTrackingInternalCrap>>> getFlat(IteratorStart start, JObjectKey key) {
|
||||
return _snapshot.getIterator().getFlat(start, key).<CloseableKvIterator<JObjectKey, MaybeTombstone<ReadTrackingInternalCrap>>>map(
|
||||
i -> new MappingKvIterator<JObjectKey, MaybeTombstone<JDataVersionedWrapper>, MaybeTombstone<ReadTrackingInternalCrap>>(i,
|
||||
d ->
|
||||
switch (d) {
|
||||
case Data<JDataVersionedWrapper> data ->
|
||||
new Data<ReadTrackingInternalCrap>(new ReadTrackingInternalCrapSource(data.value()));
|
||||
case Tombstone<JDataVersionedWrapper> tombstone ->
|
||||
new Tombstone<ReadTrackingInternalCrap>();
|
||||
default ->
|
||||
throw new IllegalStateException("Unexpected value: " + d);
|
||||
})
|
||||
);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,262 +1,262 @@
|
||||
package com.usatiuk.objects.iterators;
|
||||
|
||||
import net.jqwik.api.*;
|
||||
import net.jqwik.api.state.Action;
|
||||
import net.jqwik.api.state.ActionChain;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class MergingKvIteratorPbtTest {
|
||||
static class MergingIteratorModel implements CloseableKvIterator<Integer, Integer> {
|
||||
private final CloseableKvIterator<Integer, Integer> mergedIterator;
|
||||
private final CloseableKvIterator<Integer, Integer> mergingIterator;
|
||||
|
||||
private MergingIteratorModel(List<List<Map.Entry<Integer, Integer>>> pairs, IteratorStart startType, Integer startKey) {
|
||||
TreeMap<Integer, Integer> perfectMerged = new TreeMap<>();
|
||||
for (List<Map.Entry<Integer, Integer>> list : pairs) {
|
||||
for (Map.Entry<Integer, Integer> pair : list) {
|
||||
perfectMerged.putIfAbsent(pair.getKey(), pair.getValue());
|
||||
}
|
||||
}
|
||||
mergedIterator = new NavigableMapKvIterator<>(perfectMerged, startType, startKey);
|
||||
mergingIterator = new MergingKvIterator<>("test", startType, startKey, pairs.stream().<IterProdFn<Integer, Integer>>map(
|
||||
list -> (IteratorStart start, Integer key) -> new NavigableMapKvIterator<>(new TreeMap<Integer, Integer>(Map.ofEntries(list.toArray(Map.Entry[]::new))), start, key)
|
||||
).toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer peekNextKey() {
|
||||
var mergedKey = mergedIterator.peekNextKey();
|
||||
var mergingKey = mergingIterator.peekNextKey();
|
||||
Assertions.assertEquals(mergedKey, mergingKey);
|
||||
return mergedKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void skip() {
|
||||
mergedIterator.skip();
|
||||
mergingIterator.skip();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer peekPrevKey() {
|
||||
var mergedKey = mergedIterator.peekPrevKey();
|
||||
var mergingKey = mergingIterator.peekPrevKey();
|
||||
Assertions.assertEquals(mergedKey, mergingKey);
|
||||
return mergedKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<Integer, Integer> prev() {
|
||||
var mergedKey = mergedIterator.prev();
|
||||
var mergingKey = mergingIterator.prev();
|
||||
Assertions.assertEquals(mergedKey, mergingKey);
|
||||
return mergedKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPrev() {
|
||||
var mergedKey = mergedIterator.hasPrev();
|
||||
var mergingKey = mergingIterator.hasPrev();
|
||||
Assertions.assertEquals(mergedKey, mergingKey);
|
||||
return mergedKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void skipPrev() {
|
||||
mergedIterator.skipPrev();
|
||||
mergingIterator.skipPrev();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
mergedIterator.close();
|
||||
mergingIterator.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
var mergedKey = mergedIterator.hasNext();
|
||||
var mergingKey = mergingIterator.hasNext();
|
||||
Assertions.assertEquals(mergedKey, mergingKey);
|
||||
return mergedKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<Integer, Integer> next() {
|
||||
var mergedKey = mergedIterator.next();
|
||||
var mergingKey = mergingIterator.next();
|
||||
Assertions.assertEquals(mergedKey, mergingKey);
|
||||
return mergedKey;
|
||||
}
|
||||
}
|
||||
|
||||
static class PeekNextKeyAction extends Action.JustMutate<MergingIteratorModel> {
|
||||
@Override
|
||||
public void mutate(MergingIteratorModel state) {
|
||||
state.peekNextKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean precondition(MergingIteratorModel state) {
|
||||
return state.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return "Peek next key";
|
||||
}
|
||||
}
|
||||
|
||||
static class SkipAction extends Action.JustMutate<MergingIteratorModel> {
|
||||
@Override
|
||||
public void mutate(MergingIteratorModel state) {
|
||||
state.skip();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean precondition(MergingIteratorModel state) {
|
||||
return state.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return "Skip next key";
|
||||
}
|
||||
}
|
||||
|
||||
static class PeekPrevKeyAction extends Action.JustMutate<MergingIteratorModel> {
|
||||
@Override
|
||||
public void mutate(MergingIteratorModel state) {
|
||||
state.peekPrevKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean precondition(MergingIteratorModel state) {
|
||||
return state.hasPrev();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return "Peek prev key";
|
||||
}
|
||||
}
|
||||
|
||||
static class SkipPrevAction extends Action.JustMutate<MergingIteratorModel> {
|
||||
@Override
|
||||
public void mutate(MergingIteratorModel state) {
|
||||
state.skipPrev();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean precondition(MergingIteratorModel state) {
|
||||
return state.hasPrev();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return "Skip prev key";
|
||||
}
|
||||
}
|
||||
|
||||
static class PrevAction extends Action.JustMutate<MergingIteratorModel> {
|
||||
@Override
|
||||
public void mutate(MergingIteratorModel state) {
|
||||
state.prev();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean precondition(MergingIteratorModel state) {
|
||||
return state.hasPrev();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return "Prev key";
|
||||
}
|
||||
}
|
||||
|
||||
static class NextAction extends Action.JustMutate<MergingIteratorModel> {
|
||||
@Override
|
||||
public void mutate(MergingIteratorModel state) {
|
||||
state.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean precondition(MergingIteratorModel state) {
|
||||
return state.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return "Next key";
|
||||
}
|
||||
}
|
||||
|
||||
static class HasNextAction extends Action.JustMutate<MergingIteratorModel> {
|
||||
@Override
|
||||
public void mutate(MergingIteratorModel state) {
|
||||
state.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean precondition(MergingIteratorModel state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return "Has next key";
|
||||
}
|
||||
}
|
||||
|
||||
static class HasPrevAction extends Action.JustMutate<MergingIteratorModel> {
|
||||
@Override
|
||||
public void mutate(MergingIteratorModel state) {
|
||||
state.hasPrev();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean precondition(MergingIteratorModel state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return "Has prev key";
|
||||
}
|
||||
}
|
||||
|
||||
@Property
|
||||
public void checkMergingIterator(@ForAll("actions") ActionChain<MergingIteratorModel> actions) {
|
||||
actions.run();
|
||||
}
|
||||
|
||||
@Provide
|
||||
Arbitrary<ActionChain<MergingIteratorModel>> actions(@ForAll("lists") List<List<Map.Entry<Integer, Integer>>> list,
|
||||
@ForAll IteratorStart iteratorStart, @ForAll("startKey") Integer startKey) {
|
||||
return ActionChain.startWith(() -> new MergingIteratorModel(list, iteratorStart, startKey))
|
||||
.withAction(new NextAction())
|
||||
.withAction(new PeekNextKeyAction())
|
||||
.withAction(new SkipAction())
|
||||
.withAction(new PeekPrevKeyAction())
|
||||
.withAction(new SkipPrevAction())
|
||||
.withAction(new PrevAction())
|
||||
.withAction(new HasNextAction())
|
||||
.withAction(new HasPrevAction());
|
||||
}
|
||||
|
||||
@Provide
|
||||
Arbitrary<List<List<Map.Entry<Integer, Integer>>>> lists() {
|
||||
return Arbitraries.entries(Arbitraries.integers().between(-50, 50), Arbitraries.integers().between(-50, 50))
|
||||
.list().uniqueElements(Map.Entry::getKey).ofMinSize(0).ofMaxSize(20)
|
||||
.list().ofMinSize(1).ofMaxSize(5);
|
||||
}
|
||||
|
||||
@Provide
|
||||
Arbitrary<Integer> startKey() {
|
||||
return Arbitraries.integers().between(-51, 51);
|
||||
}
|
||||
}
|
||||
//package com.usatiuk.objects.iterators;
|
||||
//
|
||||
//import net.jqwik.api.*;
|
||||
//import net.jqwik.api.state.Action;
|
||||
//import net.jqwik.api.state.ActionChain;
|
||||
//import org.apache.commons.lang3.tuple.Pair;
|
||||
//import org.junit.jupiter.api.Assertions;
|
||||
//
|
||||
//import java.util.*;
|
||||
//
|
||||
//public class MergingKvIteratorPbtTest {
|
||||
// static class MergingIteratorModel implements CloseableKvIterator<Integer, Integer> {
|
||||
// private final CloseableKvIterator<Integer, Integer> mergedIterator;
|
||||
// private final CloseableKvIterator<Integer, Integer> mergingIterator;
|
||||
//
|
||||
// private MergingIteratorModel(List<List<Map.Entry<Integer, Integer>>> pairs, IteratorStart startType, Integer startKey) {
|
||||
// TreeMap<Integer, Integer> perfectMerged = new TreeMap<>();
|
||||
// for (List<Map.Entry<Integer, Integer>> list : pairs) {
|
||||
// for (Map.Entry<Integer, Integer> pair : list) {
|
||||
// perfectMerged.putIfAbsent(pair.getKey(), pair.getValue());
|
||||
// }
|
||||
// }
|
||||
// mergedIterator = new NavigableMapKvIterator<>(perfectMerged, startType, startKey);
|
||||
// mergingIterator = new MergingKvIterator<>("test", startType, startKey, pairs.stream().<IterProdFn<Integer, Integer>>map(
|
||||
// list -> (IteratorStart start, Integer key) -> new NavigableMapKvIterator<>(new TreeMap<Integer, Integer>(Map.ofEntries(list.toArray(Map.Entry[]::new))), start, key)
|
||||
// ).toList());
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Integer peekNextKey() {
|
||||
// var mergedKey = mergedIterator.peekNextKey();
|
||||
// var mergingKey = mergingIterator.peekNextKey();
|
||||
// Assertions.assertEquals(mergedKey, mergingKey);
|
||||
// return mergedKey;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void skip() {
|
||||
// mergedIterator.skip();
|
||||
// mergingIterator.skip();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Integer peekPrevKey() {
|
||||
// var mergedKey = mergedIterator.peekPrevKey();
|
||||
// var mergingKey = mergingIterator.peekPrevKey();
|
||||
// Assertions.assertEquals(mergedKey, mergingKey);
|
||||
// return mergedKey;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Pair<Integer, Integer> prev() {
|
||||
// var mergedKey = mergedIterator.prev();
|
||||
// var mergingKey = mergingIterator.prev();
|
||||
// Assertions.assertEquals(mergedKey, mergingKey);
|
||||
// return mergedKey;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean hasPrev() {
|
||||
// var mergedKey = mergedIterator.hasPrev();
|
||||
// var mergingKey = mergingIterator.hasPrev();
|
||||
// Assertions.assertEquals(mergedKey, mergingKey);
|
||||
// return mergedKey;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void skipPrev() {
|
||||
// mergedIterator.skipPrev();
|
||||
// mergingIterator.skipPrev();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void close() {
|
||||
// mergedIterator.close();
|
||||
// mergingIterator.close();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean hasNext() {
|
||||
// var mergedKey = mergedIterator.hasNext();
|
||||
// var mergingKey = mergingIterator.hasNext();
|
||||
// Assertions.assertEquals(mergedKey, mergingKey);
|
||||
// return mergedKey;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Pair<Integer, Integer> next() {
|
||||
// var mergedKey = mergedIterator.next();
|
||||
// var mergingKey = mergingIterator.next();
|
||||
// Assertions.assertEquals(mergedKey, mergingKey);
|
||||
// return mergedKey;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// static class PeekNextKeyAction extends Action.JustMutate<MergingIteratorModel> {
|
||||
// @Override
|
||||
// public void mutate(MergingIteratorModel state) {
|
||||
// state.peekNextKey();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean precondition(MergingIteratorModel state) {
|
||||
// return state.hasNext();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String description() {
|
||||
// return "Peek next key";
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// static class SkipAction extends Action.JustMutate<MergingIteratorModel> {
|
||||
// @Override
|
||||
// public void mutate(MergingIteratorModel state) {
|
||||
// state.skip();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean precondition(MergingIteratorModel state) {
|
||||
// return state.hasNext();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String description() {
|
||||
// return "Skip next key";
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// static class PeekPrevKeyAction extends Action.JustMutate<MergingIteratorModel> {
|
||||
// @Override
|
||||
// public void mutate(MergingIteratorModel state) {
|
||||
// state.peekPrevKey();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean precondition(MergingIteratorModel state) {
|
||||
// return state.hasPrev();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String description() {
|
||||
// return "Peek prev key";
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// static class SkipPrevAction extends Action.JustMutate<MergingIteratorModel> {
|
||||
// @Override
|
||||
// public void mutate(MergingIteratorModel state) {
|
||||
// state.skipPrev();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean precondition(MergingIteratorModel state) {
|
||||
// return state.hasPrev();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String description() {
|
||||
// return "Skip prev key";
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// static class PrevAction extends Action.JustMutate<MergingIteratorModel> {
|
||||
// @Override
|
||||
// public void mutate(MergingIteratorModel state) {
|
||||
// state.prev();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean precondition(MergingIteratorModel state) {
|
||||
// return state.hasPrev();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String description() {
|
||||
// return "Prev key";
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// static class NextAction extends Action.JustMutate<MergingIteratorModel> {
|
||||
// @Override
|
||||
// public void mutate(MergingIteratorModel state) {
|
||||
// state.next();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean precondition(MergingIteratorModel state) {
|
||||
// return state.hasNext();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String description() {
|
||||
// return "Next key";
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// static class HasNextAction extends Action.JustMutate<MergingIteratorModel> {
|
||||
// @Override
|
||||
// public void mutate(MergingIteratorModel state) {
|
||||
// state.hasNext();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean precondition(MergingIteratorModel state) {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String description() {
|
||||
// return "Has next key";
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// static class HasPrevAction extends Action.JustMutate<MergingIteratorModel> {
|
||||
// @Override
|
||||
// public void mutate(MergingIteratorModel state) {
|
||||
// state.hasPrev();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean precondition(MergingIteratorModel state) {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String description() {
|
||||
// return "Has prev key";
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Property
|
||||
// public void checkMergingIterator(@ForAll("actions") ActionChain<MergingIteratorModel> actions) {
|
||||
// actions.run();
|
||||
// }
|
||||
//
|
||||
// @Provide
|
||||
// Arbitrary<ActionChain<MergingIteratorModel>> actions(@ForAll("lists") List<List<Map.Entry<Integer, Integer>>> list,
|
||||
// @ForAll IteratorStart iteratorStart, @ForAll("startKey") Integer startKey) {
|
||||
// return ActionChain.startWith(() -> new MergingIteratorModel(list, iteratorStart, startKey))
|
||||
// .withAction(new NextAction())
|
||||
// .withAction(new PeekNextKeyAction())
|
||||
// .withAction(new SkipAction())
|
||||
// .withAction(new PeekPrevKeyAction())
|
||||
// .withAction(new SkipPrevAction())
|
||||
// .withAction(new PrevAction())
|
||||
// .withAction(new HasNextAction())
|
||||
// .withAction(new HasPrevAction());
|
||||
// }
|
||||
//
|
||||
// @Provide
|
||||
// Arbitrary<List<List<Map.Entry<Integer, Integer>>>> lists() {
|
||||
// return Arbitraries.entries(Arbitraries.integers().between(-50, 50), Arbitraries.integers().between(-50, 50))
|
||||
// .list().uniqueElements(Map.Entry::getKey).ofMinSize(0).ofMaxSize(20)
|
||||
// .list().ofMinSize(1).ofMaxSize(5);
|
||||
// }
|
||||
//
|
||||
// @Provide
|
||||
// Arbitrary<Integer> startKey() {
|
||||
// return Arbitraries.integers().between(-51, 51);
|
||||
// }
|
||||
//}
|
||||
Reference in New Issue
Block a user