mirror of
				https://github.com/usatiuk/dhfs.git
				synced 2025-10-28 20:47:49 +01:00 
			
		
		
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			javadocs
			...
			type-itera
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 7ba219f35e | 
| @@ -8,10 +8,14 @@ import java.util.Iterator; | ||||
| public interface CloseableKvIterator<K extends Comparable<K>, V> extends Iterator<Pair<K, V>>, AutoCloseableNoThrow { | ||||
|     K peekNextKey(); | ||||
|  | ||||
|     Class<?> peekNextType(); | ||||
|  | ||||
|     void skip(); | ||||
|  | ||||
|     K peekPrevKey(); | ||||
|  | ||||
|     Class<?> peekPrevType(); | ||||
|  | ||||
|     Pair<K, V> prev(); | ||||
|  | ||||
|     boolean hasPrev(); | ||||
|   | ||||
| @@ -114,6 +114,11 @@ public class KeyPredicateKvIterator<K extends Comparable<K>, V> extends Reversib | ||||
|         return got; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected Class<? > peekTypeImpl() { | ||||
|         return _goingForward ? _backing.peekNextType() : _backing.peekPrevType(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void close() { | ||||
|         _backing.close(); | ||||
|   | ||||
| @@ -2,15 +2,18 @@ package com.usatiuk.dhfs.objects; | ||||
|  | ||||
| import org.apache.commons.lang3.tuple.Pair; | ||||
|  | ||||
| import java.util.NoSuchElementException; | ||||
| import java.util.function.Function; | ||||
|  | ||||
| public class MappingKvIterator<K extends Comparable<K>, V, V_T> implements CloseableKvIterator<K, V_T> { | ||||
|     private final CloseableKvIterator<K, V> _backing; | ||||
|     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; | ||||
|         _transformer = transformer; | ||||
|         _classMapper = classMapper; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
| @@ -18,6 +21,13 @@ public class MappingKvIterator<K extends Comparable<K>, V, V_T> implements Close | ||||
|         return _backing.peekNextKey(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Class<?> peekNextType() { | ||||
|         if (!hasNext()) | ||||
|             throw new NoSuchElementException(); | ||||
|         return _classMapper.apply(_backing.peekNextType()); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void skip() { | ||||
|         _backing.skip(); | ||||
| @@ -38,6 +48,13 @@ public class MappingKvIterator<K extends Comparable<K>, V, V_T> implements Close | ||||
|         return _backing.peekPrevKey(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Class<?> peekPrevType() { | ||||
|         if (!hasPrev()) | ||||
|             throw new NoSuchElementException(); | ||||
|         return _classMapper.apply(_backing.peekPrevType()); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Pair<K, V_T> prev() { | ||||
|         var got = _backing.prev(); | ||||
|   | ||||
| @@ -289,6 +289,28 @@ public class MergingKvIterator<K extends Comparable<K>, V> extends ReversibleKvI | ||||
|         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 | ||||
|     public void close() { | ||||
|   | ||||
| @@ -91,6 +91,13 @@ public class NavigableMapKvIterator<K extends Comparable<K>, V> extends Reversib | ||||
|         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 | ||||
|     public void close() { | ||||
|     } | ||||
|   | ||||
| @@ -131,6 +131,17 @@ public class PredicateKvIterator<K extends Comparable<K>, V, V_T> extends Revers | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected Class<?> peekTypeImpl() { | ||||
|         if (!_checkedNext) | ||||
|             fillNext(); | ||||
|  | ||||
|         if (_next == null) | ||||
|             throw new NoSuchElementException("No more elements"); | ||||
|  | ||||
|         return _next.getValue().getClass(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void close() { | ||||
|         _backing.close(); | ||||
|   | ||||
| @@ -29,6 +29,11 @@ public class ReversedKvIterator<K extends Comparable<K>, V> implements Closeable | ||||
|         return _backing.peekPrevKey(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Class<?> peekNextType() { | ||||
|         return _backing.peekPrevType(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void skip() { | ||||
|         _backing.skipPrev(); | ||||
| @@ -39,6 +44,11 @@ public class ReversedKvIterator<K extends Comparable<K>, V> implements Closeable | ||||
|         return _backing.peekNextKey(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Class<?> peekPrevType() { | ||||
|         return _backing.peekNextType(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Pair<K, V> prev() { | ||||
|         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 Class<?> peekTypeImpl(); | ||||
|  | ||||
|     @Override | ||||
|     public K peekNextKey() { | ||||
|         ensureForward(); | ||||
| @@ -76,4 +78,15 @@ public abstract class ReversibleKvIterator<K extends Comparable<K>, V> implement | ||||
|         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> { | ||||
|     private final CloseableKvIterator<K, V> _backing; | ||||
|     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; | ||||
|         _backing = new PredicateKvIterator<>( | ||||
|         _returnType = returnType; | ||||
|         _backing = new MappingKvIterator<>(new TypePredicateKvIterator<>( | ||||
|                 new MergingKvIterator<>(name + "-merging", startType, startKey, iterators), | ||||
|                 startType, startKey, | ||||
|                 pair -> { | ||||
|                     Log.tracev("{0} - Processing pair {1}", _name, pair); | ||||
|                     if (pair instanceof Tombstone) { | ||||
|                         return null; | ||||
|                     } | ||||
|                     return ((Data<V>) pair).value(); | ||||
|                 }); | ||||
|                 k -> { | ||||
|                     assert !k.equals(MaybeTombstone.class); | ||||
|                     assert Tombstone.class.isAssignableFrom(k) || Data.class.isAssignableFrom(k); | ||||
|                     return Data.class.isAssignableFrom(k); | ||||
|                 }), t -> (V) returnType.cast(Data.class.cast(t).value()), (t) -> returnType); | ||||
|     } | ||||
|  | ||||
|     @SafeVarargs | ||||
|     public TombstoneMergingKvIterator(String name, IteratorStart startType, K startKey, IterProdFn<K, MaybeTombstone<V>>... iterators) { | ||||
|         this(name, startType, startKey, List.of(iterators)); | ||||
|     public TombstoneMergingKvIterator(String name, IteratorStart startType, K startKey, Class<?> returnType, IterProdFn<K, MaybeTombstone<V>>... iterators) { | ||||
|         this(name, startType, startKey, List.of(iterators), returnType); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
| @@ -34,6 +35,11 @@ public class TombstoneMergingKvIterator<K extends Comparable<K>, V> implements C | ||||
|         return _backing.peekNextKey(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Class<?> peekNextType() { | ||||
|         return _returnType; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void skip() { | ||||
|         _backing.skip(); | ||||
| @@ -44,6 +50,11 @@ public class TombstoneMergingKvIterator<K extends Comparable<K>, V> implements C | ||||
|         return _backing.peekPrevKey(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Class<?> peekPrevType() { | ||||
|         return _returnType; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Pair<K, V> 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(); | ||||
|         try { | ||||
|             var curPending = _pendingWrites.get(); | ||||
|             return new TombstoneMergingKvIterator<>("writeback-ps", start, key, | ||||
|             return new TombstoneMergingKvIterator<>("writeback-ps", start, key, JDataVersionedWrapper.class, | ||||
|                     (tS, tK) -> new MappingKvIterator<>( | ||||
|                             new NavigableMapKvIterator<>(curPending, tS, tK), | ||||
|                             e -> switch (e) { | ||||
|                                 case PendingWrite pw -> new Data<>(pw.data()); | ||||
|                                 case PendingDelete d -> new Tombstone<>(); | ||||
|                                 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)); | ||||
|         } finally { | ||||
|   | ||||
| @@ -63,7 +63,7 @@ public class CachingObjectPersistentStore { | ||||
|             int size = obj.map(JDataVersionedWrapper::estimateSize).orElse(16); | ||||
|  | ||||
|             _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); | ||||
|  | ||||
|             _sortedCache = _sortedCache.plus(key, entry); | ||||
| @@ -87,7 +87,11 @@ public class CachingObjectPersistentStore { | ||||
|         try { | ||||
|             var got = _cache.get(name); | ||||
|             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 { | ||||
|             _lock.readLock().unlock(); | ||||
| @@ -137,6 +141,11 @@ public class CachingObjectPersistentStore { | ||||
|             return _delegate.peekNextKey(); | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public Class<?> peekNextType() { | ||||
|             return _delegate.peekNextType(); | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public void skip() { | ||||
|             _delegate.skip(); | ||||
| @@ -157,6 +166,11 @@ public class CachingObjectPersistentStore { | ||||
|             return _delegate.peekPrevKey(); | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public Class<?> peekPrevType() { | ||||
|             return _delegate.peekPrevType(); | ||||
|         } | ||||
|  | ||||
|         private void maybeCache(Pair<JObjectKey, JDataVersionedWrapper> prev) { | ||||
|             _lock.writeLock().lock(); | ||||
|             try { | ||||
| @@ -209,19 +223,39 @@ public class CachingObjectPersistentStore { | ||||
|                     (mS, mK) | ||||
|                             -> new MappingKvIterator<>( | ||||
|                             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 -> { | ||||
|                                 Log.tracev("Taken from cache: {0}", e); | ||||
|                                 return e.object(); | ||||
|                             } | ||||
|                     ), | ||||
|                                 if (CacheEntryYes.class.isAssignableFrom(e)) { | ||||
|                                     return Data.class; | ||||
|                                 } else if (CacheEntryDeleted.class.isAssignableFrom(e)) { | ||||
|                                     return Tombstone.class; | ||||
|                                 } else { | ||||
|                                     throw new IllegalStateException("Unexpected type: " + e); | ||||
|                                 } | ||||
|                             }), | ||||
|                     (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 { | ||||
|             _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() { | ||||
|   | ||||
| @@ -285,6 +285,14 @@ public class LmdbObjectPersistentStore implements ObjectPersistentStore { | ||||
|             Log.tracev("Read: {0}, hasNext: {1}", ret, _hasNext); | ||||
|             return ret; | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         protected Class<? extends ByteString> peekTypeImpl() { | ||||
|             if (!_hasNext) | ||||
|                 throw new NoSuchElementException(); | ||||
|  | ||||
|             return ByteString.class; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|   | ||||
| @@ -31,7 +31,7 @@ public class SerializingObjectPersistentStore { | ||||
|     // Returns an iterator with a view of all commited objects | ||||
|     // Does not have to guarantee consistent view, snapshots are handled by upper layers | ||||
|     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) { | ||||
|   | ||||
| @@ -187,4 +187,12 @@ public class SnapshotKvIterator extends ReversibleKvIterator<JObjectKey, MaybeTo | ||||
|         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(); | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public Class<?> peekNextType() { | ||||
|                 return _backing.peekNextType(); | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public void skip() { | ||||
|                 _backing.skip(); | ||||
| @@ -253,6 +258,11 @@ public class SnapshotManager { | ||||
|                 return _backing.peekPrevKey(); | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public Class<?> peekPrevType() { | ||||
|                 return _backing.peekPrevType(); | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public Pair<JObjectKey, JDataVersionedWrapper> prev() { | ||||
|                 var ret = _backing.prev(); | ||||
| @@ -293,10 +303,10 @@ public class SnapshotManager { | ||||
|             try { | ||||
|                 Log.tracev("Getting snapshot {0} iterator for {1} {2}\n" + | ||||
|                         "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 MappingKvIterator<>( | ||||
|                                 writebackStore.getIterator(tS, tK), d -> d.version() <= _id ? new Data<>(d) : new Tombstone<>()) | ||||
|                         (tS, tK) -> new PredicateKvIterator<>( | ||||
|                                 writebackStore.getIterator(tS, tK), tS, tK, d -> d.version() <= _id ? new Data<>(d) : null) | ||||
|                 )); | ||||
|             } finally { | ||||
|                 _lock.readLock().unlock(); | ||||
|   | ||||
| @@ -6,6 +6,7 @@ import com.usatiuk.dhfs.objects.snapshot.SnapshotManager; | ||||
| import io.quarkus.logging.Log; | ||||
| import jakarta.enterprise.context.ApplicationScoped; | ||||
| import jakarta.inject.Inject; | ||||
| import org.apache.commons.lang3.NotImplementedException; | ||||
| import org.apache.commons.lang3.tuple.Pair; | ||||
|  | ||||
| import javax.annotation.Nonnull; | ||||
| @@ -74,6 +75,11 @@ public class TransactionFactoryImpl implements TransactionFactory { | ||||
|                 return _backing.peekNextKey(); | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public Class<? extends JData> peekNextType() { | ||||
|                 throw new NotImplementedException(); | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public void skip() { | ||||
|                 _backing.skip(); | ||||
| @@ -84,6 +90,11 @@ public class TransactionFactoryImpl implements TransactionFactory { | ||||
|                 return _backing.peekPrevKey(); | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public Class<? extends JData> peekPrevType() { | ||||
|                 throw new NotImplementedException(); | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public Pair<JObjectKey, JData> prev() { | ||||
|                 var got = _backing.prev(); | ||||
| @@ -221,16 +232,26 @@ 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), | ||||
|             return new ReadTrackingIterator(new TombstoneMergingKvIterator<>("tx", start, key, ReadTrackingInternalCrap.class, | ||||
|                     (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; | ||||
|                             }, | ||||
|                             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), | ||||
|                             d -> new Data<ReadTrackingInternalCrap>(new ReadTrackingInternalCrapSource(d))))); | ||||
|                             d -> new Data<>(new ReadTrackingInternalCrapSource(d)), (t) -> Data.class))); | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| package com.usatiuk.dhfs.objects; | ||||
|  | ||||
| import com.usatiuk.dhfs.objects.persistence.IteratorStart; | ||||
| import org.apache.commons.lang3.NotImplementedException; | ||||
| import org.apache.commons.lang3.tuple.Pair; | ||||
| import org.junit.jupiter.api.Assertions; | ||||
| import org.junit.jupiter.api.Test; | ||||
| @@ -35,6 +36,11 @@ public class MergingKvIteratorTest { | ||||
|             return _next.getKey(); | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public Class<? extends V> peekNextType() { | ||||
|             throw new NotImplementedException(); | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public void skip() { | ||||
|             if (_next == null) { | ||||
| @@ -49,6 +55,11 @@ public class MergingKvIteratorTest { | ||||
|             throw new UnsupportedOperationException(); | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public Class<? extends V> peekPrevType() { | ||||
|             throw new NotImplementedException(); | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public Pair<K, V> prev() { | ||||
|             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()); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Class<? extends JMapEntry<K>> peekNextType() { | ||||
|         throw new NotImplementedException(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void skip() { | ||||
|         if (!_hasNext) { | ||||
| @@ -58,6 +63,11 @@ public class JMapIterator<K extends JMapKey & Comparable<K>> implements Closeabl | ||||
|         throw new NotImplementedException(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Class<? extends JMapEntry<K>> peekPrevType() { | ||||
|         throw new NotImplementedException(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Pair<K, JMapEntry<K>> prev() { | ||||
|         throw new NotImplementedException(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user