basic object deletion

This commit is contained in:
2024-12-29 11:46:29 +01:00
parent 6da2e43cee
commit 9273dc818e
8 changed files with 72 additions and 14 deletions

View File

@@ -3,11 +3,13 @@ package com.usatiuk.objects.alloc.test;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import io.quarkus.test.QuarkusDevModeTest;
@Disabled
public class ObjectsAllocDevModeTest {
// Start hot reload (DevMode) test with your extension loaded

View File

@@ -6,9 +6,11 @@ import jakarta.inject.Inject;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
@Disabled
public class ObjectsAllocTest {
// Start unit test with your extension loaded

View File

@@ -24,6 +24,11 @@ public class CurrentTransaction implements Transaction {
return transactionManager.current().getObject(type, key, strategy);
}
@Override
public void deleteObject(JObjectKey key) {
transactionManager.current().deleteObject(key);
}
@Override
public <T extends JData> void putObject(JData obj) {
transactionManager.current().putObject(obj);

View File

@@ -196,7 +196,8 @@ public class JObjectManager {
var toFlush = new LinkedList<TxRecord.TxObjectRecordWrite<?>>();
var toPut = new LinkedList<TxRecord.TxObjectRecordNew<?>>();
var toLock = new ArrayList<TransactionObject<?>>();
var toDelete = new LinkedList<JObjectKey>();
var toLock = new ArrayList<JObjectKey>();
var dependencies = new LinkedList<TransactionObject<?>>();
Log.trace("Committing transaction " + tx.getId());
@@ -214,12 +215,16 @@ public class JObjectManager {
toFlush.add(copy);
}
case TxRecord.TxObjectRecordOptimistic<?> copy -> {
toLock.add(copy.original());
toLock.add(copy.original().data().getKey());
toFlush.add(copy);
}
case TxRecord.TxObjectRecordNew<?> created -> {
toPut.add(created);
}
case TxRecord.TxObjectRecordDeleted deleted -> {
toLock.add(deleted.key());
toDelete.add(deleted.key());
}
default -> throw new IllegalStateException("Unexpected value: " + entry);
}
}
@@ -231,7 +236,7 @@ public class JObjectManager {
// TODO: Check this
}
case ReadTrackingObjectSource.TxReadObjectSome<?>(var obj) -> {
toLock.add(obj);
toLock.add(obj.data().getKey());
dependencies.add(obj);
}
default -> throw new IllegalStateException("Unexpected value: " + entry);
@@ -240,28 +245,23 @@ public class JObjectManager {
toLock.sort(Comparator.comparingInt(System::identityHashCode));
for (var record : toLock) {
Log.trace("Locking " + record.toString());
for (var key : toLock) {
Log.trace("Locking " + key.toString());
var got = getLocked(record.data().getClass(), record.data().getKey(), true);
var got = getLocked(JData.class, key, true);
if (got == null) {
throw new IllegalStateException("Object " + record.data().getKey() + " not found");
throw new IllegalStateException("Object " + key + " not found");
}
toUnlock.add(got.wrapper().lock.writeLock()::unlock);
if (got.obj() != record.data()) {
throw new IllegalStateException("Object changed during transaction: " + got.obj() + " vs " + record.data());
}
}
for (var dep : dependencies) {
Log.trace("Checking dependency " + dep.toString());
var current = _objects.get(dep.data().getKey()).get();
// Checked above
assert current == dep.data();
if (current == null) continue; // FIXME? Does this matter much for deletion
if (current.getVersion() >= tx.getId()) {
throw new IllegalStateException("Serialization hazard: " + current.getVersion() + " vs " + tx.getId());
@@ -312,7 +312,11 @@ public class JObjectManager {
Log.tracef("Committing transaction %d to storage", tx.getId());
objectStorage.commitTx(new SimpleTxManifest(written.stream().map(JData::getKey).toList(), Collections.emptyList()));
objectStorage.commitTx(new SimpleTxManifest(written.stream().map(JData::getKey).toList(), toDelete));
for (var del : toDelete) {
_objects.remove(del);
}
} catch (Throwable t) {
Log.error("Error when committing transaction", t);
throw t;

View File

@@ -13,6 +13,8 @@ public interface Transaction {
<T extends JData> void putObject(JData obj);
void deleteObject(JObjectKey key);
default <T extends JData> Optional<T> getObject(Class<T> type, JObjectKey key) {
return getObject(type, key, LockingStrategy.OPTIMISTIC);
}

View File

@@ -65,6 +65,11 @@ public class TransactionFactoryImpl implements TransactionFactory {
}
}
@Override
public void deleteObject(JObjectKey key) {
_objects.put(key, new TxRecord.TxObjectRecordDeleted(key));
}
@Override
public void putObject(JData obj) {
if (_objects.containsKey(obj.getKey())) {

View File

@@ -31,6 +31,13 @@ public class TxRecord {
}
}
public record TxObjectRecordDeleted(JObjectKey key) implements TxObjectRecord<JData> {
@Override
public JData getIfStrategyCompatible(JObjectKey key, LockingStrategy strategy) {
return null;
}
}
public record TxObjectRecordCopyLock<T extends JData>(TransactionObject<T> original,
ChangeTrackingJData<T> copy)
implements TxObjectRecordWrite<T> {

View File

@@ -46,6 +46,37 @@ public class ObjectsTest {
}
}
@Test
void createDeleteObject() {
{
txm.begin();
var newParent = alloc.create(Parent.class, new JObjectKey("Parent"));
newParent.setLastName("John");
curTx.putObject(newParent);
txm.commit();
}
{
txm.begin();
var parent = curTx.getObject(Parent.class, new JObjectKey("Parent")).orElse(null);
Assertions.assertEquals("John", parent.getLastName());
txm.commit();
}
{
txm.begin();
curTx.deleteObject(new JObjectKey("Parent"));
txm.commit();
}
{
txm.begin();
var parent = curTx.getObject(Parent.class, new JObjectKey("Parent")).orElse(null);
Assertions.assertNull(parent);
txm.commit();
}
}
@Test
void createCreateObject() {
{