diff --git a/dhfs-parent/objects/src/main/java/com/usatiuk/dhfs/objects/JObjectManager.java b/dhfs-parent/objects/src/main/java/com/usatiuk/dhfs/objects/JObjectManager.java index ec9eece8..440f606e 100644 --- a/dhfs-parent/objects/src/main/java/com/usatiuk/dhfs/objects/JObjectManager.java +++ b/dhfs-parent/objects/src/main/java/com/usatiuk/dhfs/objects/JObjectManager.java @@ -8,9 +8,9 @@ import com.usatiuk.dhfs.objects.transaction.TransactionPrivate; import com.usatiuk.dhfs.objects.transaction.TxRecord; import com.usatiuk.dhfs.utils.DataLocker; import com.usatiuk.dhfs.utils.VoidFn; +import com.usatiuk.objects.alloc.runtime.ObjectAllocator; import com.usatiuk.objects.common.runtime.JData; import com.usatiuk.objects.common.runtime.JObjectKey; -import com.usatiuk.objects.alloc.runtime.ObjectAllocator; import io.quarkus.logging.Log; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @@ -106,6 +106,43 @@ public class JObjectManager { if (got == null) return Optional.empty(); return Optional.of(new TransactionObjectImpl<>(got.getLeft(), got.getRight().lock)); } + + private Optional> getLocked(Class type, JObjectKey key, boolean write) { + var read = get(type, key).orElse(null); + if (read == null) return Optional.empty(); + var lock = write ? read.lock().writeLock() : read.lock().readLock(); + lock.lock(); + while (true) { + try { + var readAgain = get(type, key).orElse(null); + if (readAgain == null) { + lock.unlock(); + return Optional.empty(); + } + if (!Objects.equals(read, readAgain)) { + lock.unlock(); + read = readAgain; + lock = write ? read.lock().writeLock() : read.lock().readLock(); + lock.lock(); + continue; + } + return Optional.of(new TransactionObjectImpl<>(read.data(), read.lock())); + } catch (Throwable e) { + lock.unlock(); + throw e; + } + } + } + + @Override + public Optional> getReadLocked(Class type, JObjectKey key) { + return getLocked(type, key, false); + } + + @Override + public Optional> getWriteLocked(Class type, JObjectKey key) { + return getLocked(type, key, true); + } }; public TransactionPrivate createTransaction() { @@ -114,7 +151,6 @@ public class JObjectManager { return transactionFactory.createTransaction(counter, _objSource); } - public void commit(TransactionPrivate tx) { var toUnlock = new LinkedList(); var toFlush = new LinkedList>(); diff --git a/dhfs-parent/objects/src/main/java/com/usatiuk/dhfs/objects/transaction/TransactionFactoryImpl.java b/dhfs-parent/objects/src/main/java/com/usatiuk/dhfs/objects/transaction/TransactionFactoryImpl.java index 7ab3a41c..a84741a4 100644 --- a/dhfs-parent/objects/src/main/java/com/usatiuk/dhfs/objects/transaction/TransactionFactoryImpl.java +++ b/dhfs-parent/objects/src/main/java/com/usatiuk/dhfs/objects/transaction/TransactionFactoryImpl.java @@ -1,8 +1,8 @@ package com.usatiuk.dhfs.objects.transaction; +import com.usatiuk.objects.alloc.runtime.ObjectAllocator; import com.usatiuk.objects.common.runtime.JData; import com.usatiuk.objects.common.runtime.JObjectKey; -import com.usatiuk.objects.alloc.runtime.ObjectAllocator; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import lombok.AccessLevel; @@ -49,9 +49,12 @@ public class TransactionFactoryImpl implements TransactionFactory { switch (strategy) { case READ_ONLY: { - read.lock().readLock().lock(); - var view = objectAllocator.unmodifiable(read.data()); - _objects.put(key, new TxRecord.TxObjectRecordRead<>(read, view)); + var locked = _source.getReadLocked(type, key).orElse(null); + if (locked == null) { + return Optional.empty(); + } + var view = objectAllocator.unmodifiable(locked.data()); + _objects.put(key, new TxRecord.TxObjectRecordRead<>(locked, view)); return Optional.of(view); } case OPTIMISTIC: { @@ -60,28 +63,13 @@ public class TransactionFactoryImpl implements TransactionFactory { return Optional.of(copy.wrapped()); } case WRITE: { - read.lock().writeLock().lock(); - while (true) { - try { - var readAgain = _source.get(type, key).orElse(null); - if (readAgain == null) { - read.lock().writeLock().unlock(); - return Optional.empty(); - } - if (!Objects.equals(read, readAgain)) { - read.lock().writeLock().unlock(); - read = readAgain; - read.lock().writeLock().lock(); - continue; - } - var copy = objectAllocator.copy(read.data()); - _objects.put(key, new TxRecord.TxObjectRecordCopyLock<>(read, copy)); - return Optional.of(copy.wrapped()); - } catch (Throwable e) { - read.lock().writeLock().unlock(); - throw e; - } + var locked = _source.getWriteLocked(type, key).orElse(null); + if (locked == null) { + return Optional.empty(); } + var copy = objectAllocator.copy(locked.data()); + _objects.put(key, new TxRecord.TxObjectRecordCopyLock<>(locked, copy)); + return Optional.of(copy.wrapped()); } default: throw new IllegalArgumentException("Unknown locking strategy"); diff --git a/dhfs-parent/objects/src/main/java/com/usatiuk/dhfs/objects/transaction/TransactionObjectSource.java b/dhfs-parent/objects/src/main/java/com/usatiuk/dhfs/objects/transaction/TransactionObjectSource.java index 7a4dcd22..b6cd156e 100644 --- a/dhfs-parent/objects/src/main/java/com/usatiuk/dhfs/objects/transaction/TransactionObjectSource.java +++ b/dhfs-parent/objects/src/main/java/com/usatiuk/dhfs/objects/transaction/TransactionObjectSource.java @@ -14,4 +14,8 @@ public interface TransactionObjectSource { } Optional> get(Class type, JObjectKey key); + + Optional> getReadLocked(Class type, JObjectKey key); + + Optional> getWriteLocked(Class type, JObjectKey key); }