mirror of
https://github.com/usatiuk/dhfs.git
synced 2025-10-28 12:37:48 +01:00
type iterators?
This commit is contained in:
@@ -8,10 +8,14 @@ import java.util.Iterator;
|
|||||||
public interface CloseableKvIterator<K extends Comparable<K>, V> extends Iterator<Pair<K, V>>, AutoCloseableNoThrow {
|
public interface CloseableKvIterator<K extends Comparable<K>, V> extends Iterator<Pair<K, V>>, AutoCloseableNoThrow {
|
||||||
K peekNextKey();
|
K peekNextKey();
|
||||||
|
|
||||||
|
Class<?> peekNextType();
|
||||||
|
|
||||||
void skip();
|
void skip();
|
||||||
|
|
||||||
K peekPrevKey();
|
K peekPrevKey();
|
||||||
|
|
||||||
|
Class<?> peekPrevType();
|
||||||
|
|
||||||
Pair<K, V> prev();
|
Pair<K, V> prev();
|
||||||
|
|
||||||
boolean hasPrev();
|
boolean hasPrev();
|
||||||
|
|||||||
@@ -114,6 +114,11 @@ public class KeyPredicateKvIterator<K extends Comparable<K>, V> extends Reversib
|
|||||||
return got;
|
return got;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<? > peekTypeImpl() {
|
||||||
|
return _goingForward ? _backing.peekNextType() : _backing.peekPrevType();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
_backing.close();
|
_backing.close();
|
||||||
|
|||||||
@@ -2,15 +2,18 @@ package com.usatiuk.dhfs.objects;
|
|||||||
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class MappingKvIterator<K extends Comparable<K>, V, V_T> implements CloseableKvIterator<K, V_T> {
|
public class MappingKvIterator<K extends Comparable<K>, V, V_T> implements CloseableKvIterator<K, V_T> {
|
||||||
private final CloseableKvIterator<K, V> _backing;
|
private final CloseableKvIterator<K, V> _backing;
|
||||||
private final Function<V, V_T> _transformer;
|
private final Function<V, V_T> _transformer;
|
||||||
|
private final Function<Class<?>, Class<?>> _classMapper;
|
||||||
|
|
||||||
public MappingKvIterator(CloseableKvIterator<K, V> backing, Function<V, V_T> transformer) {
|
public MappingKvIterator(CloseableKvIterator<K, V> backing, Function<V, V_T> transformer, Function<Class<?>, Class<?>> classMapper) {
|
||||||
_backing = backing;
|
_backing = backing;
|
||||||
_transformer = transformer;
|
_transformer = transformer;
|
||||||
|
_classMapper = classMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -18,6 +21,13 @@ public class MappingKvIterator<K extends Comparable<K>, V, V_T> implements Close
|
|||||||
return _backing.peekNextKey();
|
return _backing.peekNextKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> peekNextType() {
|
||||||
|
if (!hasNext())
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
return _classMapper.apply(_backing.peekNextType());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void skip() {
|
public void skip() {
|
||||||
_backing.skip();
|
_backing.skip();
|
||||||
@@ -38,6 +48,13 @@ public class MappingKvIterator<K extends Comparable<K>, V, V_T> implements Close
|
|||||||
return _backing.peekPrevKey();
|
return _backing.peekPrevKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> peekPrevType() {
|
||||||
|
if (!hasPrev())
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
return _classMapper.apply(_backing.peekPrevType());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Pair<K, V_T> prev() {
|
public Pair<K, V_T> prev() {
|
||||||
var got = _backing.prev();
|
var got = _backing.prev();
|
||||||
|
|||||||
@@ -289,6 +289,28 @@ public class MergingKvIterator<K extends Comparable<K>, V> extends ReversibleKvI
|
|||||||
return curVal;
|
return curVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<? > peekTypeImpl() {
|
||||||
|
switch (_firstMatchState) {
|
||||||
|
case FirstMatchFound<K, V> firstMatchFound -> {
|
||||||
|
return firstMatchFound.iterator().peekNextType();
|
||||||
|
}
|
||||||
|
case FirstMatchConsumed<K, V> firstMatchConsumed -> {
|
||||||
|
doHydrate();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default -> {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_sortedIterators.isEmpty())
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
|
||||||
|
return _goingForward
|
||||||
|
? _sortedIterators.firstEntry().getValue().peekNextType()
|
||||||
|
: _sortedIterators.lastEntry().getValue().peekNextType();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
|
|||||||
@@ -91,6 +91,13 @@ public class NavigableMapKvIterator<K extends Comparable<K>, V> extends Reversib
|
|||||||
return Pair.of(ret);
|
return Pair.of(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<? extends V> peekTypeImpl() {
|
||||||
|
if (_next == null)
|
||||||
|
throw new NoSuchElementException("No more elements");
|
||||||
|
return (Class<? extends V>) _next.getValue().getClass();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,6 +131,17 @@ public class PredicateKvIterator<K extends Comparable<K>, V, V_T> extends Revers
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?> peekTypeImpl() {
|
||||||
|
if (!_checkedNext)
|
||||||
|
fillNext();
|
||||||
|
|
||||||
|
if (_next == null)
|
||||||
|
throw new NoSuchElementException("No more elements");
|
||||||
|
|
||||||
|
return _next.getValue().getClass();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
_backing.close();
|
_backing.close();
|
||||||
|
|||||||
@@ -29,6 +29,11 @@ public class ReversedKvIterator<K extends Comparable<K>, V> implements Closeable
|
|||||||
return _backing.peekPrevKey();
|
return _backing.peekPrevKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> peekNextType() {
|
||||||
|
return _backing.peekPrevType();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void skip() {
|
public void skip() {
|
||||||
_backing.skipPrev();
|
_backing.skipPrev();
|
||||||
@@ -39,6 +44,11 @@ public class ReversedKvIterator<K extends Comparable<K>, V> implements Closeable
|
|||||||
return _backing.peekNextKey();
|
return _backing.peekNextKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> peekPrevType() {
|
||||||
|
return _backing.peekNextType();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Pair<K, V> prev() {
|
public Pair<K, V> prev() {
|
||||||
return _backing.next();
|
return _backing.next();
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ public abstract class ReversibleKvIterator<K extends Comparable<K>, V> implement
|
|||||||
|
|
||||||
abstract protected Pair<K, V> nextImpl();
|
abstract protected Pair<K, V> nextImpl();
|
||||||
|
|
||||||
|
abstract protected Class<?> peekTypeImpl();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public K peekNextKey() {
|
public K peekNextKey() {
|
||||||
ensureForward();
|
ensureForward();
|
||||||
@@ -76,4 +78,15 @@ public abstract class ReversibleKvIterator<K extends Comparable<K>, V> implement
|
|||||||
skipImpl();
|
skipImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> peekNextType() {
|
||||||
|
ensureForward();
|
||||||
|
return peekTypeImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> peekPrevType() {
|
||||||
|
ensureBackward();
|
||||||
|
return peekTypeImpl();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,24 +9,25 @@ import java.util.List;
|
|||||||
public class TombstoneMergingKvIterator<K extends Comparable<K>, V> implements CloseableKvIterator<K, V> {
|
public class TombstoneMergingKvIterator<K extends Comparable<K>, V> implements CloseableKvIterator<K, V> {
|
||||||
private final CloseableKvIterator<K, V> _backing;
|
private final CloseableKvIterator<K, V> _backing;
|
||||||
private final String _name;
|
private final String _name;
|
||||||
|
private final Class<?> _returnType;
|
||||||
|
|
||||||
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, MaybeTombstone<V>>> iterators,
|
||||||
|
Class<?> returnType) {
|
||||||
_name = name;
|
_name = name;
|
||||||
_backing = new PredicateKvIterator<>(
|
_returnType = returnType;
|
||||||
|
_backing = new MappingKvIterator<>(new TypePredicateKvIterator<>(
|
||||||
new MergingKvIterator<>(name + "-merging", startType, startKey, iterators),
|
new MergingKvIterator<>(name + "-merging", startType, startKey, iterators),
|
||||||
startType, startKey,
|
startType, startKey,
|
||||||
pair -> {
|
k -> {
|
||||||
Log.tracev("{0} - Processing pair {1}", _name, pair);
|
assert !k.equals(MaybeTombstone.class);
|
||||||
if (pair instanceof Tombstone) {
|
assert Tombstone.class.isAssignableFrom(k) || Data.class.isAssignableFrom(k);
|
||||||
return null;
|
return Data.class.isAssignableFrom(k);
|
||||||
}
|
}), t -> (V) returnType.cast(Data.class.cast(t).value()), (t) -> returnType);
|
||||||
return ((Data<V>) pair).value();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SafeVarargs
|
@SafeVarargs
|
||||||
public TombstoneMergingKvIterator(String name, IteratorStart startType, K startKey, IterProdFn<K, MaybeTombstone<V>>... iterators) {
|
public TombstoneMergingKvIterator(String name, IteratorStart startType, K startKey, Class<?> returnType, IterProdFn<K, MaybeTombstone<V>>... iterators) {
|
||||||
this(name, startType, startKey, List.of(iterators));
|
this(name, startType, startKey, List.of(iterators), returnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -34,6 +35,11 @@ public class TombstoneMergingKvIterator<K extends Comparable<K>, V> implements C
|
|||||||
return _backing.peekNextKey();
|
return _backing.peekNextKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> peekNextType() {
|
||||||
|
return _returnType;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void skip() {
|
public void skip() {
|
||||||
_backing.skip();
|
_backing.skip();
|
||||||
@@ -44,6 +50,11 @@ public class TombstoneMergingKvIterator<K extends Comparable<K>, V> implements C
|
|||||||
return _backing.peekPrevKey();
|
return _backing.peekPrevKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> peekPrevType() {
|
||||||
|
return _returnType;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Pair<K, V> prev() {
|
public Pair<K, V> prev() {
|
||||||
return _backing.prev();
|
return _backing.prev();
|
||||||
|
|||||||
@@ -0,0 +1,141 @@
|
|||||||
|
package com.usatiuk.dhfs.objects;
|
||||||
|
|
||||||
|
import com.usatiuk.dhfs.objects.persistence.IteratorStart;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class TypePredicateKvIterator<K extends Comparable<K>, V> extends ReversibleKvIterator<K, V> {
|
||||||
|
private final CloseableKvIterator<K, V> _backing;
|
||||||
|
private final Function<Class<?>, Boolean> _filter;
|
||||||
|
private K _next;
|
||||||
|
|
||||||
|
public TypePredicateKvIterator(CloseableKvIterator<K, V> backing, IteratorStart start, K startKey, Function<Class<?>, Boolean> filter) {
|
||||||
|
_goingForward = true;
|
||||||
|
_backing = backing;
|
||||||
|
_filter = filter;
|
||||||
|
fillNext();
|
||||||
|
|
||||||
|
boolean shouldGoBack = false;
|
||||||
|
if (start == IteratorStart.LE) {
|
||||||
|
if (_next == null || _next.compareTo(startKey) > 0) {
|
||||||
|
shouldGoBack = true;
|
||||||
|
}
|
||||||
|
} else if (start == IteratorStart.LT) {
|
||||||
|
if (_next == null || _next.compareTo(startKey) >= 0) {
|
||||||
|
shouldGoBack = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldGoBack && _backing.hasPrev()) {
|
||||||
|
_goingForward = false;
|
||||||
|
_next = null;
|
||||||
|
fillNext();
|
||||||
|
if (_next != null)
|
||||||
|
_backing.skipPrev();
|
||||||
|
_goingForward = true;
|
||||||
|
// _backing.skip();
|
||||||
|
fillNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
switch (start) {
|
||||||
|
case LT -> {
|
||||||
|
// assert _next == null || _next.getKey().compareTo(startKey) < 0;
|
||||||
|
}
|
||||||
|
case LE -> {
|
||||||
|
// assert _next == null || _next.getKey().compareTo(startKey) <= 0;
|
||||||
|
}
|
||||||
|
case GT -> {
|
||||||
|
assert _next == null || _next.compareTo(startKey) > 0;
|
||||||
|
}
|
||||||
|
case GE -> {
|
||||||
|
assert _next == null || _next.compareTo(startKey) >= 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillNext() {
|
||||||
|
while ((_goingForward ? _backing.hasNext() : _backing.hasPrev()) && _next == null) {
|
||||||
|
var next = _goingForward ? _backing.peekNextType() : _backing.peekPrevType();
|
||||||
|
if (!_filter.apply(next)) {
|
||||||
|
if (_goingForward)
|
||||||
|
_backing.skip();
|
||||||
|
else
|
||||||
|
_backing.skipPrev();
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
_next = _goingForward ? _backing.peekNextKey() : _backing.peekPrevKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void reverse() {
|
||||||
|
_goingForward = !_goingForward;
|
||||||
|
_next = null;
|
||||||
|
|
||||||
|
fillNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected K peekImpl() {
|
||||||
|
if (_next == null)
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
return _next;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void skipImpl() {
|
||||||
|
if (_next == null)
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
_next = null;
|
||||||
|
if (_goingForward)
|
||||||
|
_backing.skip();
|
||||||
|
else
|
||||||
|
_backing.skipPrev();
|
||||||
|
fillNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean hasImpl() {
|
||||||
|
return _next != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Pair<K, V> nextImpl() {
|
||||||
|
if (_next == null)
|
||||||
|
throw new NoSuchElementException("No more elements");
|
||||||
|
var retKey = _next;
|
||||||
|
_next = null;
|
||||||
|
var nextType = _goingForward ? _backing.peekNextType() : _backing.peekPrevType();
|
||||||
|
var got = _goingForward ? _backing.next() : _backing.prev();
|
||||||
|
assert got.getKey().equals(retKey);
|
||||||
|
assert nextType.equals(got.getValue().getClass());
|
||||||
|
assert _filter.apply(got.getValue().getClass());
|
||||||
|
fillNext();
|
||||||
|
return got;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?> peekTypeImpl() {
|
||||||
|
if (_next == null)
|
||||||
|
throw new NoSuchElementException("No more elements");
|
||||||
|
|
||||||
|
return _goingForward ? _backing.peekNextType() : _backing.peekPrevType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
_backing.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "KeyPredicateKvIterator{" +
|
||||||
|
"_backing=" + _backing +
|
||||||
|
", _next=" + _next +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -465,13 +465,22 @@ public class WritebackObjectPersistentStore {
|
|||||||
_pendingWritesVersionLock.readLock().lock();
|
_pendingWritesVersionLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
var curPending = _pendingWrites.get();
|
var curPending = _pendingWrites.get();
|
||||||
return new TombstoneMergingKvIterator<>("writeback-ps", start, key,
|
return new TombstoneMergingKvIterator<>("writeback-ps", start, key, JDataVersionedWrapper.class,
|
||||||
(tS, tK) -> new MappingKvIterator<>(
|
(tS, tK) -> new MappingKvIterator<>(
|
||||||
new NavigableMapKvIterator<>(curPending, tS, tK),
|
new NavigableMapKvIterator<>(curPending, tS, tK),
|
||||||
e -> switch (e) {
|
e -> switch (e) {
|
||||||
case PendingWrite pw -> new Data<>(pw.data());
|
case PendingWrite pw -> new Data<>(pw.data());
|
||||||
case PendingDelete d -> new Tombstone<>();
|
case PendingDelete d -> new Tombstone<>();
|
||||||
default -> throw new IllegalStateException("Unexpected value: " + e);
|
default -> throw new IllegalStateException("Unexpected value: " + e);
|
||||||
|
},
|
||||||
|
e -> {
|
||||||
|
if (PendingWrite.class.isAssignableFrom(e)) {
|
||||||
|
return Data.class;
|
||||||
|
} else if (PendingDelete.class.isAssignableFrom(e)) {
|
||||||
|
return Tombstone.class;
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("Unexpected type: " + e);
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
(tS, tK) -> cachedStore.getIterator(tS, tK));
|
(tS, tK) -> cachedStore.getIterator(tS, tK));
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public class CachingObjectPersistentStore {
|
|||||||
int size = obj.map(JDataVersionedWrapper::estimateSize).orElse(16);
|
int size = obj.map(JDataVersionedWrapper::estimateSize).orElse(16);
|
||||||
|
|
||||||
_curSize += size;
|
_curSize += size;
|
||||||
var entry = new CacheEntry(obj.<MaybeTombstone<JDataVersionedWrapper>>map(Data::new).orElse(new Tombstone<>()), size);
|
CacheEntry entry = obj.<CacheEntry>map(v -> new CacheEntryYes(v, size)).orElse(new CacheEntryDeleted());
|
||||||
var old = _cache.putLast(key, entry);
|
var old = _cache.putLast(key, entry);
|
||||||
|
|
||||||
_sortedCache = _sortedCache.plus(key, entry);
|
_sortedCache = _sortedCache.plus(key, entry);
|
||||||
@@ -87,7 +87,11 @@ public class CachingObjectPersistentStore {
|
|||||||
try {
|
try {
|
||||||
var got = _cache.get(name);
|
var got = _cache.get(name);
|
||||||
if (got != null) {
|
if (got != null) {
|
||||||
return got.object().opt();
|
return switch (got) {
|
||||||
|
case CacheEntryYes yes -> Optional.of(yes.object());
|
||||||
|
case CacheEntryDeleted del -> Optional.empty();
|
||||||
|
default -> throw new IllegalStateException("Unexpected value: " + got);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
_lock.readLock().unlock();
|
_lock.readLock().unlock();
|
||||||
@@ -137,6 +141,11 @@ public class CachingObjectPersistentStore {
|
|||||||
return _delegate.peekNextKey();
|
return _delegate.peekNextKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> peekNextType() {
|
||||||
|
return _delegate.peekNextType();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void skip() {
|
public void skip() {
|
||||||
_delegate.skip();
|
_delegate.skip();
|
||||||
@@ -157,6 +166,11 @@ public class CachingObjectPersistentStore {
|
|||||||
return _delegate.peekPrevKey();
|
return _delegate.peekPrevKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> peekPrevType() {
|
||||||
|
return _delegate.peekPrevType();
|
||||||
|
}
|
||||||
|
|
||||||
private void maybeCache(Pair<JObjectKey, JDataVersionedWrapper> prev) {
|
private void maybeCache(Pair<JObjectKey, JDataVersionedWrapper> prev) {
|
||||||
_lock.writeLock().lock();
|
_lock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
@@ -209,19 +223,39 @@ public class CachingObjectPersistentStore {
|
|||||||
(mS, mK)
|
(mS, mK)
|
||||||
-> new MappingKvIterator<>(
|
-> new MappingKvIterator<>(
|
||||||
new NavigableMapKvIterator<>(curSortedCache, mS, mK),
|
new NavigableMapKvIterator<>(curSortedCache, mS, mK),
|
||||||
|
e -> switch (e) {
|
||||||
|
case CacheEntryYes pw -> new Data<>(pw.object());
|
||||||
|
case CacheEntryDeleted d -> new Tombstone<>();
|
||||||
|
default -> throw new IllegalStateException("Unexpected value: " + e);
|
||||||
|
},
|
||||||
e -> {
|
e -> {
|
||||||
Log.tracev("Taken from cache: {0}", e);
|
if (CacheEntryYes.class.isAssignableFrom(e)) {
|
||||||
return e.object();
|
return Data.class;
|
||||||
}
|
} else if (CacheEntryDeleted.class.isAssignableFrom(e)) {
|
||||||
),
|
return Tombstone.class;
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("Unexpected type: " + e);
|
||||||
|
}
|
||||||
|
}),
|
||||||
(mS, mK)
|
(mS, mK)
|
||||||
-> new MappingKvIterator<>(new CachingKvIterator(delegate.getIterator(mS, mK)), Data::new));
|
-> new MappingKvIterator<>(new CachingKvIterator(delegate.getIterator(mS, mK)), Data::new, (d) -> Data.class));
|
||||||
} finally {
|
} finally {
|
||||||
_lock.readLock().unlock();
|
_lock.readLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private record CacheEntry(MaybeTombstone<JDataVersionedWrapper> object, long size) {
|
private interface CacheEntry {
|
||||||
|
long size();
|
||||||
|
}
|
||||||
|
|
||||||
|
private record CacheEntryYes(JDataVersionedWrapper object, long size) implements CacheEntry {
|
||||||
|
}
|
||||||
|
|
||||||
|
private record CacheEntryDeleted() implements CacheEntry {
|
||||||
|
@Override
|
||||||
|
public long size() {
|
||||||
|
return 16;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getLastTxId() {
|
public long getLastTxId() {
|
||||||
|
|||||||
@@ -285,6 +285,14 @@ public class LmdbObjectPersistentStore implements ObjectPersistentStore {
|
|||||||
Log.tracev("Read: {0}, hasNext: {1}", ret, _hasNext);
|
Log.tracev("Read: {0}, hasNext: {1}", ret, _hasNext);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<? extends ByteString> peekTypeImpl() {
|
||||||
|
if (!_hasNext)
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
|
||||||
|
return ByteString.class;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public class SerializingObjectPersistentStore {
|
|||||||
// Returns an iterator with a view of all commited objects
|
// Returns an iterator with a view of all commited objects
|
||||||
// Does not have to guarantee consistent view, snapshots are handled by upper layers
|
// Does not have to guarantee consistent view, snapshots are handled by upper layers
|
||||||
public CloseableKvIterator<JObjectKey, JDataVersionedWrapper> getIterator(IteratorStart start, JObjectKey key) {
|
public CloseableKvIterator<JObjectKey, JDataVersionedWrapper> getIterator(IteratorStart start, JObjectKey key) {
|
||||||
return new MappingKvIterator<>(delegateStore.getIterator(start, key), d -> serializer.deserialize(d));
|
return new MappingKvIterator<>(delegateStore.getIterator(start, key), d -> serializer.deserialize(d), (d) -> JDataVersionedWrapper.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TxManifestRaw prepareManifest(TxManifestObj<? extends JDataVersionedWrapper> names) {
|
public TxManifestRaw prepareManifest(TxManifestObj<? extends JDataVersionedWrapper> names) {
|
||||||
|
|||||||
@@ -187,4 +187,12 @@ public class SnapshotKvIterator extends ReversibleKvIterator<JObjectKey, MaybeTo
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<? extends MaybeTombstone<JDataVersionedWrapper>> peekTypeImpl() {
|
||||||
|
if (_next == null)
|
||||||
|
throw new NoSuchElementException("No more elements");
|
||||||
|
|
||||||
|
return (Class<? extends MaybeTombstone<JDataVersionedWrapper>>) _next.getValue().getClass();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -243,6 +243,11 @@ public class SnapshotManager {
|
|||||||
return _backing.peekNextKey();
|
return _backing.peekNextKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> peekNextType() {
|
||||||
|
return _backing.peekNextType();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void skip() {
|
public void skip() {
|
||||||
_backing.skip();
|
_backing.skip();
|
||||||
@@ -253,6 +258,11 @@ public class SnapshotManager {
|
|||||||
return _backing.peekPrevKey();
|
return _backing.peekPrevKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> peekPrevType() {
|
||||||
|
return _backing.peekPrevType();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Pair<JObjectKey, JDataVersionedWrapper> prev() {
|
public Pair<JObjectKey, JDataVersionedWrapper> prev() {
|
||||||
var ret = _backing.prev();
|
var ret = _backing.prev();
|
||||||
@@ -293,10 +303,10 @@ public class SnapshotManager {
|
|||||||
try {
|
try {
|
||||||
Log.tracev("Getting snapshot {0} iterator for {1} {2}\n" +
|
Log.tracev("Getting snapshot {0} iterator for {1} {2}\n" +
|
||||||
"objects in snapshots: {3}", _id, start, key, _objects);
|
"objects in snapshots: {3}", _id, start, key, _objects);
|
||||||
return new CheckingSnapshotKvIterator(new TombstoneMergingKvIterator<>("snapshot", start, key,
|
return new CheckingSnapshotKvIterator(new TombstoneMergingKvIterator<>("snapshot", start, key, JDataVersionedWrapper.class,
|
||||||
(tS, tK) -> new SnapshotKvIterator(_objects, _id, tS, tK),
|
(tS, tK) -> new SnapshotKvIterator(_objects, _id, tS, tK),
|
||||||
(tS, tK) -> new MappingKvIterator<>(
|
(tS, tK) -> new PredicateKvIterator<>(
|
||||||
writebackStore.getIterator(tS, tK), d -> d.version() <= _id ? new Data<>(d) : new Tombstone<>())
|
writebackStore.getIterator(tS, tK), tS, tK, d -> d.version() <= _id ? new Data<>(d) : null)
|
||||||
));
|
));
|
||||||
} finally {
|
} finally {
|
||||||
_lock.readLock().unlock();
|
_lock.readLock().unlock();
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import com.usatiuk.dhfs.objects.snapshot.SnapshotManager;
|
|||||||
import io.quarkus.logging.Log;
|
import io.quarkus.logging.Log;
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
|
import org.apache.commons.lang3.NotImplementedException;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
@@ -74,6 +75,11 @@ public class TransactionFactoryImpl implements TransactionFactory {
|
|||||||
return _backing.peekNextKey();
|
return _backing.peekNextKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends JData> peekNextType() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void skip() {
|
public void skip() {
|
||||||
_backing.skip();
|
_backing.skip();
|
||||||
@@ -84,6 +90,11 @@ public class TransactionFactoryImpl implements TransactionFactory {
|
|||||||
return _backing.peekPrevKey();
|
return _backing.peekPrevKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends JData> peekPrevType() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Pair<JObjectKey, JData> prev() {
|
public Pair<JObjectKey, JData> prev() {
|
||||||
var got = _backing.prev();
|
var got = _backing.prev();
|
||||||
@@ -221,16 +232,26 @@ public class TransactionFactoryImpl implements TransactionFactory {
|
|||||||
@Override
|
@Override
|
||||||
public CloseableKvIterator<JObjectKey, JData> getIterator(IteratorStart start, JObjectKey key) {
|
public CloseableKvIterator<JObjectKey, JData> getIterator(IteratorStart start, JObjectKey key) {
|
||||||
Log.tracev("Getting tx iterator with start={0}, key={1}", start, key);
|
Log.tracev("Getting tx iterator with start={0}, key={1}", start, key);
|
||||||
return new ReadTrackingIterator(new TombstoneMergingKvIterator<>("tx", start, key,
|
return new ReadTrackingIterator(new TombstoneMergingKvIterator<>("tx", start, key, ReadTrackingInternalCrap.class,
|
||||||
(tS, tK) -> new MappingKvIterator<>(new NavigableMapKvIterator<>(_writes, tS, tK),
|
(tS, tK) -> new MappingKvIterator<>(
|
||||||
|
new NavigableMapKvIterator<>(_writes, tS, tK),
|
||||||
t -> switch (t) {
|
t -> switch (t) {
|
||||||
case TxRecord.TxObjectRecordWrite<?> write ->
|
case TxRecord.TxObjectRecordWrite<?> write ->
|
||||||
new Data<>(new ReadTrackingInternalCrapTx(write.data()));
|
new Data<>(new ReadTrackingInternalCrapTx(write.data()));
|
||||||
case TxRecord.TxObjectRecordDeleted deleted -> new Tombstone<>();
|
case TxRecord.TxObjectRecordDeleted deleted -> new Tombstone<>();
|
||||||
case null, default -> null;
|
case null, default -> null;
|
||||||
|
},
|
||||||
|
e -> {
|
||||||
|
if (TxRecord.TxObjectRecordWrite.class.isAssignableFrom(e)) {
|
||||||
|
return Data.class;
|
||||||
|
} else if (TxRecord.TxObjectRecordDeleted.class.isAssignableFrom(e)) {
|
||||||
|
return Tombstone.class;
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("Unexpected type: " + e);
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
(tS, tK) -> new MappingKvIterator<>(_snapshot.getIterator(tS, tK),
|
(tS, tK) -> new MappingKvIterator<>(_snapshot.getIterator(tS, tK),
|
||||||
d -> new Data<ReadTrackingInternalCrap>(new ReadTrackingInternalCrapSource(d)))));
|
d -> new Data<>(new ReadTrackingInternalCrapSource(d)), (t) -> Data.class)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.usatiuk.dhfs.objects;
|
package com.usatiuk.dhfs.objects;
|
||||||
|
|
||||||
import com.usatiuk.dhfs.objects.persistence.IteratorStart;
|
import com.usatiuk.dhfs.objects.persistence.IteratorStart;
|
||||||
|
import org.apache.commons.lang3.NotImplementedException;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@@ -35,6 +36,11 @@ public class MergingKvIteratorTest {
|
|||||||
return _next.getKey();
|
return _next.getKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends V> peekNextType() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void skip() {
|
public void skip() {
|
||||||
if (_next == null) {
|
if (_next == null) {
|
||||||
@@ -49,6 +55,11 @@ public class MergingKvIteratorTest {
|
|||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends V> peekPrevType() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Pair<K, V> prev() {
|
public Pair<K, V> prev() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
|
|||||||
@@ -1,161 +0,0 @@
|
|||||||
package com.usatiuk.dhfs.objects;
|
|
||||||
|
|
||||||
import com.usatiuk.dhfs.objects.persistence.IteratorStart;
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
|
||||||
import org.junit.jupiter.api.Assertions;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.pcollections.TreePMap;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class PredicateKvIteratorTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void simpleTest() {
|
|
||||||
var source1 = TreePMap.<Integer, Integer>empty().plus(1, 3).plus(3, 5).plus(4, 6);
|
|
||||||
var pit = new PredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.GT, 1),
|
|
||||||
IteratorStart.GE, 1, v -> (v % 2 == 0) ? v : null);
|
|
||||||
var expected = List.of(Pair.of(4, 6));
|
|
||||||
for (var pair : expected) {
|
|
||||||
Assertions.assertTrue(pit.hasNext());
|
|
||||||
Assertions.assertEquals(pair, pit.next());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void ltTest() {
|
|
||||||
var source1 = TreePMap.<Integer, Integer>empty().plus(1, 3).plus(3, 5).plus(4, 6);
|
|
||||||
var pit = new PredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 4),
|
|
||||||
IteratorStart.LT, 4, v -> (v % 2 == 0) ? v : null);
|
|
||||||
var expected = List.of(Pair.of(4, 6));
|
|
||||||
for (var pair : expected) {
|
|
||||||
Assertions.assertTrue(pit.hasNext());
|
|
||||||
Assertions.assertEquals(pair, pit.next());
|
|
||||||
}
|
|
||||||
Assertions.assertFalse(pit.hasNext());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void ltTest2() {
|
|
||||||
var source1 = TreePMap.<Integer, Integer>empty().plus(1, 3).plus(3, 5).plus(4, 6);
|
|
||||||
var pit = new PredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 1),
|
|
||||||
IteratorStart.LT, 1, v -> (v % 2 == 0) ? v : null);
|
|
||||||
Just.checkIterator(pit, Pair.of(4, 6));
|
|
||||||
Assertions.assertFalse(pit.hasNext());
|
|
||||||
|
|
||||||
pit = new PredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 2),
|
|
||||||
IteratorStart.LT, 2, v -> (v % 2 == 0) ? v : null);
|
|
||||||
Just.checkIterator(pit, Pair.of(4, 6));
|
|
||||||
Assertions.assertFalse(pit.hasNext());
|
|
||||||
|
|
||||||
pit = new PredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 4),
|
|
||||||
IteratorStart.LT, 4, v -> (v % 2 == 0) ? v : null);
|
|
||||||
Just.checkIterator(pit, Pair.of(4, 6));
|
|
||||||
Assertions.assertFalse(pit.hasNext());
|
|
||||||
|
|
||||||
pit = new PredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LE, 4),
|
|
||||||
IteratorStart.LE, 4, v -> (v % 2 == 0) ? v : null);
|
|
||||||
Just.checkIterator(pit, Pair.of(4, 6));
|
|
||||||
Assertions.assertFalse(pit.hasNext());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void ltTest3() {
|
|
||||||
var source1 = TreePMap.<Integer, Integer>empty().plus(1, 3).plus(3, 5).plus(4, 6).plus(5, 7).plus(6, 8);
|
|
||||||
var pit = new PredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 4),
|
|
||||||
IteratorStart.LT, 4, v -> (v % 2 == 0) ? v : null);
|
|
||||||
Just.checkIterator(pit, Pair.of(4, 6), Pair.of(6, 8));
|
|
||||||
Assertions.assertFalse(pit.hasNext());
|
|
||||||
|
|
||||||
pit = new PredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 5),
|
|
||||||
IteratorStart.LT, 5, v -> (v % 2 == 0) ? v : null);
|
|
||||||
Just.checkIterator(pit, Pair.of(4, 6), Pair.of(6, 8));
|
|
||||||
Assertions.assertFalse(pit.hasNext());
|
|
||||||
|
|
||||||
pit = new PredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 6),
|
|
||||||
IteratorStart.LT, 6, v -> (v % 2 == 0) ? v : null);
|
|
||||||
Just.checkIterator(pit, Pair.of(4, 6), Pair.of(6, 8));
|
|
||||||
Assertions.assertFalse(pit.hasNext());
|
|
||||||
|
|
||||||
pit = new PredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 7),
|
|
||||||
IteratorStart.LT, 7, v -> (v % 2 == 0) ? v : null);
|
|
||||||
Just.checkIterator(pit, Pair.of(6, 8));
|
|
||||||
Assertions.assertFalse(pit.hasNext());
|
|
||||||
|
|
||||||
pit = new PredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 8),
|
|
||||||
IteratorStart.LT, 8, v -> (v % 2 == 0) ? v : null);
|
|
||||||
Just.checkIterator(pit, Pair.of(6, 8));
|
|
||||||
Assertions.assertFalse(pit.hasNext());
|
|
||||||
|
|
||||||
pit = new PredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LE, 6),
|
|
||||||
IteratorStart.LE, 6, v -> (v % 2 == 0) ? v : null);
|
|
||||||
Just.checkIterator(pit, Pair.of(6, 8));
|
|
||||||
Assertions.assertFalse(pit.hasNext());
|
|
||||||
|
|
||||||
pit = new PredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 6),
|
|
||||||
IteratorStart.LT, 6, v -> (v % 2 == 0) ? v : null);
|
|
||||||
Assertions.assertTrue(pit.hasNext());
|
|
||||||
Assertions.assertEquals(4, pit.peekNextKey());
|
|
||||||
Assertions.assertFalse(pit.hasPrev());
|
|
||||||
Assertions.assertEquals(4, pit.peekNextKey());
|
|
||||||
Assertions.assertFalse(pit.hasPrev());
|
|
||||||
Assertions.assertEquals(Pair.of(4, 6), pit.next());
|
|
||||||
Assertions.assertTrue(pit.hasNext());
|
|
||||||
Assertions.assertEquals(6, pit.peekNextKey());
|
|
||||||
Assertions.assertEquals(4, pit.peekPrevKey());
|
|
||||||
Assertions.assertEquals(6, pit.peekNextKey());
|
|
||||||
Assertions.assertEquals(4, pit.peekPrevKey());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void itTest4() {
|
|
||||||
var source1 = TreePMap.<Integer, Integer>empty().plus(1, 3).plus(3, 5).plus(4, 6).plus(5, 8).plus(6, 10);
|
|
||||||
var pit = new PredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 4),
|
|
||||||
IteratorStart.LT, 4, v -> (v % 2 == 0) ? v : null);
|
|
||||||
Just.checkIterator(pit, Pair.of(4, 6), Pair.of(5, 8), Pair.of(6, 10));
|
|
||||||
Assertions.assertFalse(pit.hasNext());
|
|
||||||
|
|
||||||
pit = new PredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 5),
|
|
||||||
IteratorStart.LT, 5, v -> (v % 2 == 0) ? v : null);
|
|
||||||
Just.checkIterator(pit, Pair.of(4, 6), Pair.of(5, 8), Pair.of(6, 10));
|
|
||||||
Assertions.assertFalse(pit.hasNext());
|
|
||||||
|
|
||||||
pit = new PredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 6),
|
|
||||||
IteratorStart.LT, 6, v -> (v % 2 == 0) ? v : null);
|
|
||||||
Just.checkIterator(pit, Pair.of(5, 8), Pair.of(6, 10));
|
|
||||||
Assertions.assertFalse(pit.hasNext());
|
|
||||||
|
|
||||||
pit = new PredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 7),
|
|
||||||
IteratorStart.LT, 7, v -> (v % 2 == 0) ? v : null);
|
|
||||||
Just.checkIterator(pit, Pair.of(6, 10));
|
|
||||||
Assertions.assertFalse(pit.hasNext());
|
|
||||||
Assertions.assertTrue(pit.hasPrev());
|
|
||||||
Assertions.assertEquals(6, pit.peekPrevKey());
|
|
||||||
Assertions.assertEquals(Pair.of(6, 10), pit.prev());
|
|
||||||
Assertions.assertTrue(pit.hasNext());
|
|
||||||
Assertions.assertEquals(6, pit.peekNextKey());
|
|
||||||
|
|
||||||
pit = new PredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 6),
|
|
||||||
IteratorStart.LT, 6, v -> (v % 2 == 0) ? v : null);
|
|
||||||
Assertions.assertTrue(pit.hasNext());
|
|
||||||
Assertions.assertEquals(5, pit.peekNextKey());
|
|
||||||
Assertions.assertTrue(pit.hasPrev());
|
|
||||||
Assertions.assertEquals(4, pit.peekPrevKey());
|
|
||||||
Assertions.assertEquals(5, pit.peekNextKey());
|
|
||||||
Assertions.assertEquals(4, pit.peekPrevKey());
|
|
||||||
Assertions.assertEquals(Pair.of(5, 8), pit.next());
|
|
||||||
Assertions.assertTrue(pit.hasNext());
|
|
||||||
Assertions.assertEquals(6, pit.peekNextKey());
|
|
||||||
Assertions.assertEquals(5, pit.peekPrevKey());
|
|
||||||
Assertions.assertEquals(6, pit.peekNextKey());
|
|
||||||
Assertions.assertEquals(5, pit.peekPrevKey());
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Test
|
|
||||||
// public void reverseTest() {
|
|
||||||
// var source1 = TreePMap.<Integer, Integer>empty().plus(1, 3).plus(3, 5).plus(4, 6);
|
|
||||||
// var pit = new PredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 4),
|
|
||||||
// IteratorStart.LT, 4, v -> (v % 2 == 0) ? v : null);
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,161 @@
|
|||||||
|
package com.usatiuk.dhfs.objects;
|
||||||
|
|
||||||
|
import com.usatiuk.dhfs.objects.persistence.IteratorStart;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.pcollections.TreePMap;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class TypePredicateKvIteratorTest {
|
||||||
|
|
||||||
|
// @Test
|
||||||
|
// public void simpleTest() {
|
||||||
|
// var source1 = TreePMap.<Integer, Integer>empty().plus(1, 3).plus(3, 5).plus(4, 6);
|
||||||
|
// var pit = new TypePredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.GT, 1),
|
||||||
|
// IteratorStart.GE, 1, v -> (v % 2 == 0) ? v : null);
|
||||||
|
// var expected = List.of(Pair.of(4, 6));
|
||||||
|
// for (var pair : expected) {
|
||||||
|
// Assertions.assertTrue(pit.hasNext());
|
||||||
|
// Assertions.assertEquals(pair, pit.next());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Test
|
||||||
|
// public void ltTest() {
|
||||||
|
// var source1 = TreePMap.<Integer, Integer>empty().plus(1, 3).plus(3, 5).plus(4, 6);
|
||||||
|
// var pit = new TypePredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 4),
|
||||||
|
// IteratorStart.LT, 4, v -> (v % 2 == 0) ? v : null);
|
||||||
|
// var expected = List.of(Pair.of(4, 6));
|
||||||
|
// for (var pair : expected) {
|
||||||
|
// Assertions.assertTrue(pit.hasNext());
|
||||||
|
// Assertions.assertEquals(pair, pit.next());
|
||||||
|
// }
|
||||||
|
// Assertions.assertFalse(pit.hasNext());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Test
|
||||||
|
// public void ltTest2() {
|
||||||
|
// var source1 = TreePMap.<Integer, Integer>empty().plus(1, 3).plus(3, 5).plus(4, 6);
|
||||||
|
// var pit = new TypePredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 1),
|
||||||
|
// IteratorStart.LT, 1, v -> (v % 2 == 0) ? v : null);
|
||||||
|
// Just.checkIterator(pit, Pair.of(4, 6));
|
||||||
|
// Assertions.assertFalse(pit.hasNext());
|
||||||
|
//
|
||||||
|
// pit = new TypePredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 2),
|
||||||
|
// IteratorStart.LT, 2, v -> (v % 2 == 0) ? v : null);
|
||||||
|
// Just.checkIterator(pit, Pair.of(4, 6));
|
||||||
|
// Assertions.assertFalse(pit.hasNext());
|
||||||
|
//
|
||||||
|
// pit = new TypePredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 4),
|
||||||
|
// IteratorStart.LT, 4, v -> (v % 2 == 0) ? v : null);
|
||||||
|
// Just.checkIterator(pit, Pair.of(4, 6));
|
||||||
|
// Assertions.assertFalse(pit.hasNext());
|
||||||
|
//
|
||||||
|
// pit = new TypePredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LE, 4),
|
||||||
|
// IteratorStart.LE, 4, v -> (v % 2 == 0) ? v : null);
|
||||||
|
// Just.checkIterator(pit, Pair.of(4, 6));
|
||||||
|
// Assertions.assertFalse(pit.hasNext());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Test
|
||||||
|
// public void ltTest3() {
|
||||||
|
// var source1 = TreePMap.<Integer, Integer>empty().plus(1, 3).plus(3, 5).plus(4, 6).plus(5, 7).plus(6, 8);
|
||||||
|
// var pit = new TypePredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 4),
|
||||||
|
// IteratorStart.LT, 4, v -> (v % 2 == 0) ? v : null);
|
||||||
|
// Just.checkIterator(pit, Pair.of(4, 6), Pair.of(6, 8));
|
||||||
|
// Assertions.assertFalse(pit.hasNext());
|
||||||
|
//
|
||||||
|
// pit = new TypePredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 5),
|
||||||
|
// IteratorStart.LT, 5, v -> (v % 2 == 0) ? v : null);
|
||||||
|
// Just.checkIterator(pit, Pair.of(4, 6), Pair.of(6, 8));
|
||||||
|
// Assertions.assertFalse(pit.hasNext());
|
||||||
|
//
|
||||||
|
// pit = new TypePredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 6),
|
||||||
|
// IteratorStart.LT, 6, v -> (v % 2 == 0) ? v : null);
|
||||||
|
// Just.checkIterator(pit, Pair.of(4, 6), Pair.of(6, 8));
|
||||||
|
// Assertions.assertFalse(pit.hasNext());
|
||||||
|
//
|
||||||
|
// pit = new TypePredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 7),
|
||||||
|
// IteratorStart.LT, 7, v -> (v % 2 == 0) ? v : null);
|
||||||
|
// Just.checkIterator(pit, Pair.of(6, 8));
|
||||||
|
// Assertions.assertFalse(pit.hasNext());
|
||||||
|
//
|
||||||
|
// pit = new TypePredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 8),
|
||||||
|
// IteratorStart.LT, 8, v -> (v % 2 == 0) ? v : null);
|
||||||
|
// Just.checkIterator(pit, Pair.of(6, 8));
|
||||||
|
// Assertions.assertFalse(pit.hasNext());
|
||||||
|
//
|
||||||
|
// pit = new TypePredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LE, 6),
|
||||||
|
// IteratorStart.LE, 6, v -> (v % 2 == 0) ? v : null);
|
||||||
|
// Just.checkIterator(pit, Pair.of(6, 8));
|
||||||
|
// Assertions.assertFalse(pit.hasNext());
|
||||||
|
//
|
||||||
|
// pit = new TypePredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 6),
|
||||||
|
// IteratorStart.LT, 6, v -> (v % 2 == 0) ? v : null);
|
||||||
|
// Assertions.assertTrue(pit.hasNext());
|
||||||
|
// Assertions.assertEquals(4, pit.peekNextKey());
|
||||||
|
// Assertions.assertFalse(pit.hasPrev());
|
||||||
|
// Assertions.assertEquals(4, pit.peekNextKey());
|
||||||
|
// Assertions.assertFalse(pit.hasPrev());
|
||||||
|
// Assertions.assertEquals(Pair.of(4, 6), pit.next());
|
||||||
|
// Assertions.assertTrue(pit.hasNext());
|
||||||
|
// Assertions.assertEquals(6, pit.peekNextKey());
|
||||||
|
// Assertions.assertEquals(4, pit.peekPrevKey());
|
||||||
|
// Assertions.assertEquals(6, pit.peekNextKey());
|
||||||
|
// Assertions.assertEquals(4, pit.peekPrevKey());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Test
|
||||||
|
// public void itTest4() {
|
||||||
|
// var source1 = TreePMap.<Integer, Integer>empty().plus(1, 3).plus(3, 5).plus(4, 6).plus(5, 8).plus(6, 10);
|
||||||
|
// var pit = new TypePredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 4),
|
||||||
|
// IteratorStart.LT, 4, v -> (v % 2 == 0) ? v : null);
|
||||||
|
// Just.checkIterator(pit, Pair.of(4, 6), Pair.of(5, 8), Pair.of(6, 10));
|
||||||
|
// Assertions.assertFalse(pit.hasNext());
|
||||||
|
//
|
||||||
|
// pit = new TypePredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 5),
|
||||||
|
// IteratorStart.LT, 5, v -> (v % 2 == 0) ? v : null);
|
||||||
|
// Just.checkIterator(pit, Pair.of(4, 6), Pair.of(5, 8), Pair.of(6, 10));
|
||||||
|
// Assertions.assertFalse(pit.hasNext());
|
||||||
|
//
|
||||||
|
// pit = new TypePredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 6),
|
||||||
|
// IteratorStart.LT, 6, v -> (v % 2 == 0) ? v : null);
|
||||||
|
// Just.checkIterator(pit, Pair.of(5, 8), Pair.of(6, 10));
|
||||||
|
// Assertions.assertFalse(pit.hasNext());
|
||||||
|
//
|
||||||
|
// pit = new TypePredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 7),
|
||||||
|
// IteratorStart.LT, 7, v -> (v % 2 == 0) ? v : null);
|
||||||
|
// Just.checkIterator(pit, Pair.of(6, 10));
|
||||||
|
// Assertions.assertFalse(pit.hasNext());
|
||||||
|
// Assertions.assertTrue(pit.hasPrev());
|
||||||
|
// Assertions.assertEquals(6, pit.peekPrevKey());
|
||||||
|
// Assertions.assertEquals(Pair.of(6, 10), pit.prev());
|
||||||
|
// Assertions.assertTrue(pit.hasNext());
|
||||||
|
// Assertions.assertEquals(6, pit.peekNextKey());
|
||||||
|
//
|
||||||
|
// pit = new TypePredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 6),
|
||||||
|
// IteratorStart.LT, 6, v -> (v % 2 == 0) ? v : null);
|
||||||
|
// Assertions.assertTrue(pit.hasNext());
|
||||||
|
// Assertions.assertEquals(5, pit.peekNextKey());
|
||||||
|
// Assertions.assertTrue(pit.hasPrev());
|
||||||
|
// Assertions.assertEquals(4, pit.peekPrevKey());
|
||||||
|
// Assertions.assertEquals(5, pit.peekNextKey());
|
||||||
|
// Assertions.assertEquals(4, pit.peekPrevKey());
|
||||||
|
// Assertions.assertEquals(Pair.of(5, 8), pit.next());
|
||||||
|
// Assertions.assertTrue(pit.hasNext());
|
||||||
|
// Assertions.assertEquals(6, pit.peekNextKey());
|
||||||
|
// Assertions.assertEquals(5, pit.peekPrevKey());
|
||||||
|
// Assertions.assertEquals(6, pit.peekNextKey());
|
||||||
|
// Assertions.assertEquals(5, pit.peekPrevKey());
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @Test
|
||||||
|
// public void reverseTest() {
|
||||||
|
// var source1 = TreePMap.<Integer, Integer>empty().plus(1, 3).plus(3, 5).plus(4, 6);
|
||||||
|
// var pit = new PredicateKvIterator<>(new NavigableMapKvIterator<>(source1, IteratorStart.LT, 4),
|
||||||
|
// IteratorStart.LT, 4, v -> (v % 2 == 0) ? v : null);
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -45,6 +45,11 @@ public class JMapIterator<K extends JMapKey & Comparable<K>> implements Closeabl
|
|||||||
return keyToKey(_backing.peekNextKey());
|
return keyToKey(_backing.peekNextKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends JMapEntry<K>> peekNextType() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void skip() {
|
public void skip() {
|
||||||
if (!_hasNext) {
|
if (!_hasNext) {
|
||||||
@@ -58,6 +63,11 @@ public class JMapIterator<K extends JMapKey & Comparable<K>> implements Closeabl
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends JMapEntry<K>> peekPrevType() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Pair<K, JMapEntry<K>> prev() {
|
public Pair<K, JMapEntry<K>> prev() {
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
|
|||||||
Reference in New Issue
Block a user