diff --git a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/JDataVersionedWrapper.java b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/JDataVersionedWrapper.java index 949f12f5..04328ef9 100644 --- a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/JDataVersionedWrapper.java +++ b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/JDataVersionedWrapper.java @@ -1,6 +1,13 @@ package com.usatiuk.objects; -public sealed interface JDataVersionedWrapper permits JDataVersionedWrapperLazy, JDataVersionedWrapperImpl { +import com.usatiuk.objects.iterators.Data; + +public sealed interface JDataVersionedWrapper extends Data permits JDataVersionedWrapperLazy, JDataVersionedWrapperImpl { + @Override + default JDataVersionedWrapper value() { + return this; + } + JData data(); long version(); diff --git a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/iterators/Data.java b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/iterators/Data.java index 145a6769..98c487ad 100644 --- a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/iterators/Data.java +++ b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/iterators/Data.java @@ -2,9 +2,6 @@ package com.usatiuk.objects.iterators; import java.util.Optional; -public record Data(V value) implements MaybeTombstone { - @Override - public Optional opt() { - return Optional.of(value); - } +public interface Data extends MaybeTombstone { + V value(); } diff --git a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/iterators/DataWrapper.java b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/iterators/DataWrapper.java new file mode 100644 index 00000000..585bd654 --- /dev/null +++ b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/iterators/DataWrapper.java @@ -0,0 +1,6 @@ +package com.usatiuk.objects.iterators; + +import java.util.Optional; + +public record DataWrapper(V value) implements Data { +} diff --git a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/iterators/MaybeTombstone.java b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/iterators/MaybeTombstone.java index 34122def..7e04e01f 100644 --- a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/iterators/MaybeTombstone.java +++ b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/iterators/MaybeTombstone.java @@ -3,5 +3,4 @@ package com.usatiuk.objects.iterators; import java.util.Optional; public interface MaybeTombstone { - Optional opt(); } diff --git a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/iterators/NavigableMapKvIterator.java b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/iterators/NavigableMapKvIterator.java index 358cc94c..7aaa904d 100644 --- a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/iterators/NavigableMapKvIterator.java +++ b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/iterators/NavigableMapKvIterator.java @@ -9,22 +9,22 @@ public class NavigableMapKvIterator, V> extends Reversib private Iterator> _iterator; private Map.Entry _next; - public NavigableMapKvIterator(NavigableMap map, IteratorStart start, K key) { - _map = map; + public NavigableMapKvIterator(NavigableMap map, IteratorStart start, K key) { + _map = (NavigableMap) map; SortedMap _view; _goingForward = true; switch (start) { - case GE -> _view = map.tailMap(key, true); - case GT -> _view = map.tailMap(key, false); + case GE -> _view = _map.tailMap(key, true); + case GT -> _view = _map.tailMap(key, false); case LE -> { - var floorKey = map.floorKey(key); + var floorKey = _map.floorKey(key); if (floorKey == null) _view = _map; - else _view = map.tailMap(floorKey, true); + else _view = _map.tailMap(floorKey, true); } case LT -> { var lowerKey = map.lowerKey(key); if (lowerKey == null) _view = _map; - else _view = map.tailMap(lowerKey, true); + else _view = _map.tailMap(lowerKey, true); } default -> throw new IllegalArgumentException("Unknown start type"); } diff --git a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/iterators/Tombstone.java b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/iterators/Tombstone.java index 34e0adf0..425c8c65 100644 --- a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/iterators/Tombstone.java +++ b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/iterators/Tombstone.java @@ -2,9 +2,5 @@ package com.usatiuk.objects.iterators; import java.util.Optional; -public record Tombstone() implements MaybeTombstone { - @Override - public Optional opt() { - return Optional.empty(); - } +public interface Tombstone extends MaybeTombstone { } diff --git a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/iterators/TombstoneImpl.java b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/iterators/TombstoneImpl.java new file mode 100644 index 00000000..33886d40 --- /dev/null +++ b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/iterators/TombstoneImpl.java @@ -0,0 +1,4 @@ +package com.usatiuk.objects.iterators; + +public record TombstoneImpl() implements Tombstone { +} diff --git a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/iterators/TombstoneMergingKvIterator.java b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/iterators/TombstoneMergingKvIterator.java index 27566d11..8f354a48 100644 --- a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/iterators/TombstoneMergingKvIterator.java +++ b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/iterators/TombstoneMergingKvIterator.java @@ -16,7 +16,7 @@ public class TombstoneMergingKvIterator, V> implements C startType, startKey, pair -> { Log.tracev("{0} - Processing pair {1}", _name, pair); - if (pair instanceof Tombstone) { + if (pair instanceof Tombstone) { return null; } return ((Data) pair).value(); diff --git a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/stores/CachingObjectPersistentStore.java b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/stores/CachingObjectPersistentStore.java index cd9a404f..79385fd8 100644 --- a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/stores/CachingObjectPersistentStore.java +++ b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/stores/CachingObjectPersistentStore.java @@ -34,10 +34,9 @@ public class CachingObjectPersistentStore { long version, int sizeLimit) { public Cache withPut(JObjectKey key, Optional obj) { - int objSize = obj.map(JDataVersionedWrapper::estimateSize).orElse(16); + var entry = obj.map(o -> new CacheEntryPresent(o, o.estimateSize())).orElse(new CacheEntryMiss()); - int newSize = size() + objSize; - var entry = new CacheEntry(obj.>map(Data::new).orElse(new Tombstone<>()), objSize); + int newSize = size() + entry.size(); var old = map.get(key); if (old != null) @@ -188,15 +187,8 @@ public class CachingObjectPersistentStore { @Override public CloseableKvIterator getIterator(IteratorStart start, JObjectKey key) { return new TombstoneMergingKvIterator<>("cache", start, key, - (mS, mK) - -> new MappingKvIterator<>( - new NavigableMapKvIterator<>(_curCache.map(), mS, mK), - e -> { -// Log.tracev("Taken from cache: {0}", e); - return e.object(); - } - ), - (mS, mK) -> new MappingKvIterator<>(new CachingKvIterator(_backing.getIterator(start, key)), Data::new)); + (mS, mK) -> new NavigableMapKvIterator>(_curCache.map(), mS, mK), + (mS, mK) -> new CachingKvIterator(_backing.getIterator(start, key))); } @Nonnull @@ -204,12 +196,12 @@ public class CachingObjectPersistentStore { public Optional readObject(JObjectKey name) { var cached = _curCache.map().get(name); if (cached != null) { - return switch (cached.object()) { - case Data data -> Optional.of(data.value()); - case Tombstone tombstone -> { + return switch (cached) { + case CacheEntryPresent data -> Optional.of(data.value()); + case CacheEntryMiss tombstone -> { yield Optional.empty(); } - default -> throw new IllegalStateException("Unexpected value: " + cached.object()); + default -> throw new IllegalStateException("Unexpected value: " + cached); }; } var read = _backing.readObject(name); @@ -228,7 +220,7 @@ public class CachingObjectPersistentStore { _backing.close(); } - private class CachingKvIterator implements CloseableKvIterator { + private class CachingKvIterator implements CloseableKvIterator> { private final CloseableKvIterator _delegate; private CachingKvIterator(CloseableKvIterator delegate) { @@ -261,10 +253,10 @@ public class CachingObjectPersistentStore { } @Override - public Pair prev() { + public Pair> prev() { var prev = _delegate.prev(); maybeCache(prev.getKey(), Optional.of(prev.getValue())); - return prev; + return (Pair>) (Pair) prev; } @Override @@ -278,10 +270,10 @@ public class CachingObjectPersistentStore { } @Override - public Pair next() { + public Pair> next() { var next = _delegate.next(); maybeCache(next.getKey(), Optional.of(next.getValue())); - return next; + return (Pair>) (Pair) next; } } }; @@ -294,6 +286,18 @@ public class CachingObjectPersistentStore { } } - private record CacheEntry(MaybeTombstone object, int size) { + private interface CacheEntry extends MaybeTombstone { + int size(); + } + + private record CacheEntryPresent(JDataVersionedWrapper value, + int size) implements CacheEntry, Data { + } + + private record CacheEntryMiss() implements CacheEntry, Tombstone { + @Override + public int size() { + return 64; + } } } diff --git a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/stores/PendingDelete.java b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/stores/PendingDelete.java index 34709575..d0d01db3 100644 --- a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/stores/PendingDelete.java +++ b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/stores/PendingDelete.java @@ -1,6 +1,9 @@ package com.usatiuk.objects.stores; +import com.usatiuk.objects.JDataVersionedWrapper; import com.usatiuk.objects.JObjectKey; +import com.usatiuk.objects.iterators.Tombstone; -public record PendingDelete(JObjectKey key, long bundleId) implements PendingWriteEntry { +public record PendingDelete(JObjectKey key, + long bundleId) implements PendingWriteEntry, Tombstone { } diff --git a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/stores/PendingWrite.java b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/stores/PendingWrite.java index f8bfc7a5..42dd0cee 100644 --- a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/stores/PendingWrite.java +++ b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/stores/PendingWrite.java @@ -1,6 +1,7 @@ package com.usatiuk.objects.stores; import com.usatiuk.objects.JDataVersionedWrapper; +import com.usatiuk.objects.iterators.Data; -public record PendingWrite(JDataVersionedWrapper data, long bundleId) implements PendingWriteEntry { +public record PendingWrite(JDataVersionedWrapper value, long bundleId) implements PendingWriteEntry, Data { } diff --git a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/stores/PendingWriteEntry.java b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/stores/PendingWriteEntry.java index 52d4edd0..bb6239ad 100644 --- a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/stores/PendingWriteEntry.java +++ b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/stores/PendingWriteEntry.java @@ -1,5 +1,8 @@ package com.usatiuk.objects.stores; -public interface PendingWriteEntry { +import com.usatiuk.objects.JDataVersionedWrapper; +import com.usatiuk.objects.iterators.MaybeTombstone; + +public interface PendingWriteEntry extends MaybeTombstone { long bundleId(); } diff --git a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/stores/WritebackObjectPersistentStore.java b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/stores/WritebackObjectPersistentStore.java index 4ab48c12..3b53b2d0 100644 --- a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/stores/WritebackObjectPersistentStore.java +++ b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/stores/WritebackObjectPersistentStore.java @@ -350,15 +350,9 @@ public class WritebackObjectPersistentStore { @Override public CloseableKvIterator getIterator(IteratorStart start, JObjectKey key) { - return new TombstoneMergingKvIterator<>("writeback-ps", start, key, - (tS, tK) -> new MappingKvIterator<>( - new NavigableMapKvIterator<>(_pendingWrites, tS, tK), - e -> switch (e) { - case PendingWrite pw -> new Data<>(pw.data()); - case PendingDelete d -> new Tombstone<>(); - default -> throw new IllegalStateException("Unexpected value: " + e); - }), - (tS, tK) -> new MappingKvIterator<>(_cache.getIterator(tS, tK), Data::new)); + return new TombstoneMergingKvIterator("writeback-ps", start, key, + (tS, tK) -> new NavigableMapKvIterator<>(_pendingWrites, tS, tK), + (tS, tK) -> (CloseableKvIterator>) (CloseableKvIterator) _cache.getIterator(tS, tK)); } @Nonnull @@ -367,7 +361,7 @@ public class WritebackObjectPersistentStore { var cached = _pendingWrites.get(name); if (cached != null) { return switch (cached) { - case PendingWrite c -> Optional.of(c.data()); + case PendingWrite c -> Optional.of(c.value()); case PendingDelete d -> { yield Optional.empty(); } diff --git a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/transaction/JObjectManager.java b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/transaction/JObjectManager.java index 4f468d5f..585f7b57 100644 --- a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/transaction/JObjectManager.java +++ b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/transaction/JObjectManager.java @@ -21,10 +21,6 @@ import java.util.*; import java.util.function.Function; import java.util.stream.Stream; -// Manages all access to com.usatiuk.objects.JData objects. -// In particular, it serves as a source of truth for what is committed to the backing storage. -// All data goes through it, it is responsible for transaction atomicity -// TODO: persistent tx id @ApplicationScoped public class JObjectManager { private final List _preCommitTxHooks; @@ -219,7 +215,7 @@ public class JObjectManager { // TODO: Every write gets a dependency due to hooks continue; // assert false; -// throw new TxCommitException("Serialization hazard: " + dep.isEmpty() + " vs " + read.getValue().data().isEmpty()); +// throw new TxCommitException("Serialization hazard: " + dep.isEmpty() + " vs " + read.getValue().value().isEmpty()); } if (current.get().version() > snapshotId) { @@ -270,31 +266,4 @@ public class JObjectManager { }); tx.close(); } - - // private class TransactionObjectSourceImpl implements TransactionObjectSource { -// private final long _txId; -// -// private TransactionObjectSourceImpl(long txId) { -// _txId = txId; -// } -// -// @Override -// public TransactionObject get(Class type, JObjectKey key) { -// var got = getObj(type, key); -// if (got.data().isPresent() && got.data().get().version() > _txId) { -// throw new TxCommitException("Serialization race for " + key + ": " + got.data().get().version() + " vs " + _txId); -// } -// return got; -// } -// -// @Override -// public TransactionObject getWriteLocked(Class type, JObjectKey key) { -// var got = getObjLock(type, key); -// if (got.data().isPresent() && got.data().get().version() > _txId) { -// got.lock().close(); -// throw new TxCommitException("Serialization race for " + key + ": " + got.data().get().version() + " vs " + _txId); -// } -// return got; -// } -// } } \ No newline at end of file diff --git a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/transaction/TransactionFactoryImpl.java b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/transaction/TransactionFactoryImpl.java index 72ee7482..771865e8 100644 --- a/dhfs-parent/objects/src/main/java/com/usatiuk/objects/transaction/TransactionFactoryImpl.java +++ b/dhfs-parent/objects/src/main/java/com/usatiuk/objects/transaction/TransactionFactoryImpl.java @@ -7,7 +7,6 @@ import com.usatiuk.objects.iterators.*; import com.usatiuk.objects.snapshot.Snapshot; import com.usatiuk.objects.snapshot.SnapshotManager; import io.quarkus.logging.Log; -import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.apache.commons.lang3.tuple.Pair; @@ -166,12 +165,12 @@ public class TransactionFactoryImpl implements TransactionFactory { (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<>(); + new DataWrapper<>(new ReadTrackingInternalCrapTx(write.data())); + case TxRecord.TxObjectRecordDeleted deleted -> new TombstoneImpl<>(); case null, default -> null; }), (tS, tK) -> new MappingKvIterator<>(_snapshot.getIterator(tS, tK), - d -> new Data(new ReadTrackingInternalCrapSource(d))))); + d -> new DataWrapper(new ReadTrackingInternalCrapSource(d))))); } @Override