From b807ac8cdc3475b3d6dd6fbaf9f4c3f1f8263d10 Mon Sep 17 00:00:00 2001 From: "Brian S. O'Neill" Date: Wed, 31 Dec 2008 20:55:22 +0000 Subject: Revert automatic initial version number if insert fails. --- .../com/amazon/carbonado/gen/CodeBuilderUtil.java | 36 +++++++++++++++++ .../carbonado/gen/MasterStorableGenerator.java | 47 ++++++++++++++++++++++ .../amazon/carbonado/layout/LayoutProperty.java | 8 ++++ 3 files changed, 91 insertions(+) (limited to 'src/main') diff --git a/src/main/java/com/amazon/carbonado/gen/CodeBuilderUtil.java b/src/main/java/com/amazon/carbonado/gen/CodeBuilderUtil.java index 82be9f2..f25d6f1 100644 --- a/src/main/java/com/amazon/carbonado/gen/CodeBuilderUtil.java +++ b/src/main/java/com/amazon/carbonado/gen/CodeBuilderUtil.java @@ -578,6 +578,42 @@ public class CodeBuilderUtil { b.convert(primitiveType, type); } + /** + * Generates code to push a blank value to the stack. For objects, it is + * null, and for primitive types it is zero or false. + */ + public static void blankValue(CodeBuilder b, TypeDesc type) { + switch (type.getTypeCode()) { + default: + b.loadNull(); + break; + + case TypeDesc.BYTE_CODE: + case TypeDesc.CHAR_CODE: + case TypeDesc.SHORT_CODE: + case TypeDesc.INT_CODE: + b.loadConstant(0); + break; + + case TypeDesc.BOOLEAN_CODE: + b.loadConstant(false); + break; + + case TypeDesc.LONG_CODE: + b.loadConstant(0L); + break; + + case TypeDesc.FLOAT_CODE: + b.loadConstant(0.0f); + break; + + case TypeDesc.DOUBLE_CODE: + + b.loadConstant(0.0); + break; + } + } + /** * Determines which overloaded "with" method on Query should be bound to. */ diff --git a/src/main/java/com/amazon/carbonado/gen/MasterStorableGenerator.java b/src/main/java/com/amazon/carbonado/gen/MasterStorableGenerator.java index 82d8c7a..21af6cf 100644 --- a/src/main/java/com/amazon/carbonado/gen/MasterStorableGenerator.java +++ b/src/main/java/com/amazon/carbonado/gen/MasterStorableGenerator.java @@ -403,12 +403,16 @@ public final class MasterStorableGenerator { Label tryStart = addEnterTransaction(b, INSERT_OP, txnVar); + LocalVariable wasVersionInitVar = null; if (mFeatures.contains(MasterFeature.VERSIONING)) { if (!mInfo.getVersionProperty().isDerived()) { // Only set if uninitialized. b.loadThis(); b.invokeVirtual(StorableGenerator.IS_VERSION_INITIALIZED_METHOD_NAME, TypeDesc.BOOLEAN, null); + wasVersionInitVar = b.createLocalVariable(null, TypeDesc.BOOLEAN); + b.storeLocal(wasVersionInitVar); + b.loadLocal(wasVersionInitVar); Label isInitialized = b.createLabel(); b.ifZeroComparisonBranch(isInitialized, "!="); addAdjustVersionProperty(b, null, 1); @@ -535,6 +539,23 @@ public final class MasterStorableGenerator { b.loadThis(); b.invokeVirtual(DO_TRY_INSERT_MASTER_METHOD_NAME, TypeDesc.BOOLEAN, null); + + if (wasVersionInitVar != null) { + // Decide if version property needs to rollback to uninitialized. + + b.dup(); + Label noRollback = b.createLabel(); + // Don't rollback if insert succeeded. + b.ifZeroComparisonBranch(noRollback, "!="); + + b.loadLocal(wasVersionInitVar); + // Rollback only if version was automatically set. + b.ifZeroComparisonBranch(noRollback, "!="); + unsetVersionProperty(b); + + noRollback.setLocation(); + } + addNormalizationRollback(b, doTryStart, unnormalized); if (tryStart == null) { @@ -1080,6 +1101,32 @@ public final class MasterStorableGenerator { b.invoke(versionProperty.getWriteMethod()); } + /** + * Sets the version property to its initial uninitialized state. + */ + private void unsetVersionProperty(CodeBuilder b) throws SupportException { + StorableProperty property = mInfo.getVersionProperty(); + + // Set the property state to uninitialized. + { + String stateFieldName = + StorableGenerator.PROPERTY_STATE_FIELD_NAME + (property.getNumber() >> 4); + b.loadThis(); + b.loadThis(); + b.loadField(stateFieldName, TypeDesc.INT); + int shift = (property.getNumber() & 0xf) * 2; + b.loadConstant(~(StorableGenerator.PROPERTY_STATE_MASK << shift)); + b.math(Opcode.IAND); + b.storeField(stateFieldName, TypeDesc.INT); + } + + // Zero the property value. + TypeDesc type = TypeDesc.forClass(property.getType()); + b.loadThis(); + CodeBuilderUtil.blankValue(b, type); + b.storeField(property.getName(), type); + } + private List addNormalization(CodeBuilder b, boolean forUpdate) { List unnormalized = null; diff --git a/src/main/java/com/amazon/carbonado/layout/LayoutProperty.java b/src/main/java/com/amazon/carbonado/layout/LayoutProperty.java index a0ce48f..bf35073 100644 --- a/src/main/java/com/amazon/carbonado/layout/LayoutProperty.java +++ b/src/main/java/com/amazon/carbonado/layout/LayoutProperty.java @@ -20,6 +20,7 @@ package com.amazon.carbonado.layout; import org.cojen.classfile.TypeDesc; +import com.amazon.carbonado.FetchException; import com.amazon.carbonado.PersistException; import com.amazon.carbonado.SupportException; @@ -187,6 +188,13 @@ public class LayoutProperty { void store() throws PersistException { if (!mStoredLayoutProperty.tryInsert()) { + StoredLayoutProperty existing = mStoredLayoutProperty.copy(); + try { + existing.load(); + existing.copyVersionProperty(mStoredLayoutProperty); + } catch (FetchException e) { + throw e.toPersistException(); + } mStoredLayoutProperty.update(); } } -- cgit v1.2.3