From 2f14a36ed762b2287bab1c97fdb4cbee118e2921 Mon Sep 17 00:00:00 2001 From: "Brian S. O'Neill" Date: Tue, 7 Nov 2006 02:29:16 +0000 Subject: Allow resync to delete or skip over corrupt replica entries. --- .../carbonado/raw/GenericInstanceFactory.java | 3 + .../amazon/carbonado/raw/GenericStorableCodec.java | 48 ++++++---- .../amazon/carbonado/raw/RawStorableGenerator.java | 105 +++++++++++++++------ 3 files changed, 110 insertions(+), 46 deletions(-) (limited to 'src/main/java/com/amazon/carbonado/raw') diff --git a/src/main/java/com/amazon/carbonado/raw/GenericInstanceFactory.java b/src/main/java/com/amazon/carbonado/raw/GenericInstanceFactory.java index e436760..339bdbd 100644 --- a/src/main/java/com/amazon/carbonado/raw/GenericInstanceFactory.java +++ b/src/main/java/com/amazon/carbonado/raw/GenericInstanceFactory.java @@ -30,6 +30,9 @@ import com.amazon.carbonado.Storable; public interface GenericInstanceFactory { Storable instantiate(RawSupport support); + Storable instantiate(RawSupport support, byte[] key) + throws FetchException; + Storable instantiate(RawSupport support, byte[] key, byte[] value) throws FetchException; } diff --git a/src/main/java/com/amazon/carbonado/raw/GenericStorableCodec.java b/src/main/java/com/amazon/carbonado/raw/GenericStorableCodec.java index df3245b..cac1283 100644 --- a/src/main/java/com/amazon/carbonado/raw/GenericStorableCodec.java +++ b/src/main/java/com/amazon/carbonado/raw/GenericStorableCodec.java @@ -149,27 +149,31 @@ public class GenericStorableCodec implements StorableCodec= 2) { + params[1] = byteArrayType; + if (i == 3) { + params[2] = byteArrayType; + } + } - // Add constructor that accepts a RawSupport, an encoded key, and an - // encoded data. - { - TypeDesc[] params = {rawSupportType, byteArrayType, byteArrayType}; MethodInfo mi = cf.addConstructor(Modifiers.PUBLIC, params); CodeBuilder b = new CodeBuilder(mi); + b.loadThis(); b.loadLocal(b.getParameter(0)); - b.loadLocal(b.getParameter(1)); - b.loadLocal(b.getParameter(2)); + if (i >= 2) { + b.loadLocal(b.getParameter(1)); + if (i == 3) { + b.loadLocal(b.getParameter(2)); + } + } b.invokeSuperConstructor(params); b.returnVoid(); } @@ -367,7 +371,17 @@ public class GenericStorableCodec implements StorableCodec support, byte[] key, byte[] value) throws FetchException { - return (S) mInstanceFactory.instantiate(support, key, value); + try { + return (S) mInstanceFactory.instantiate(support, key, value); + } catch (CorruptEncodingException e) { + // Try to instantiate just the key and pass what we can to the exception. + try { + e.setStorableWithPrimaryKey(mInstanceFactory.instantiate(support, key)); + } catch (FetchException e2) { + // Oh well, can't even decode the key. + } + throw e; + } } public StorableIndex getPrimaryKeyIndex() { diff --git a/src/main/java/com/amazon/carbonado/raw/RawStorableGenerator.java b/src/main/java/com/amazon/carbonado/raw/RawStorableGenerator.java index 93c38be..e48aef8 100644 --- a/src/main/java/com/amazon/carbonado/raw/RawStorableGenerator.java +++ b/src/main/java/com/amazon/carbonado/raw/RawStorableGenerator.java @@ -20,6 +20,7 @@ package com.amazon.carbonado.raw; import java.lang.ref.Reference; import java.lang.ref.SoftReference; +import java.util.Collection; import java.util.EnumSet; import java.util.Map; @@ -29,6 +30,7 @@ import org.cojen.classfile.Label; import org.cojen.classfile.LocalVariable; import org.cojen.classfile.MethodInfo; import org.cojen.classfile.Modifiers; +import org.cojen.classfile.Opcode; import org.cojen.classfile.TypeDesc; import org.cojen.util.ClassInjector; import org.cojen.util.WeakIdentityMap; @@ -38,6 +40,9 @@ import com.amazon.carbonado.PersistException; import com.amazon.carbonado.Storable; import com.amazon.carbonado.SupportException; +import com.amazon.carbonado.info.StorableIntrospector; +import com.amazon.carbonado.info.StorableProperty; + import com.amazon.carbonado.spi.MasterFeature; import com.amazon.carbonado.spi.MasterStorableGenerator; import com.amazon.carbonado.spi.MasterSupport; @@ -112,12 +117,14 @@ public class RawStorableGenerator { * Returns an abstract implementation of the given Storable type, which is * fully thread-safe. The Storable type itself may be an interface or a * class. If it is a class, then it must not be final, and it must have a - * public, no-arg constructor. Two constructors are defined for the + * public, no-arg constructor. Three constructors are defined for the * abstract implementation: * *
      * public <init>(RawSupport);
-
+     *
+     * public <init>(RawSupport, byte[] key);
+     *
      * public <init>(RawSupport, byte[] key, byte[] value);
      * 
* @@ -201,40 +208,80 @@ public class RawStorableGenerator { final TypeDesc rawSupportType = TypeDesc.forClass(RawSupport.class); final TypeDesc byteArrayType = TypeDesc.forClass(byte[].class); - // Add constructor that accepts a RawSupport. - { - TypeDesc[] params = {rawSupportType}; - MethodInfo mi = cf.addConstructor(Modifiers.PUBLIC, params); - CodeBuilder b = new CodeBuilder(mi); - b.loadThis(); - b.loadLocal(b.getParameter(0)); - b.invokeSuperConstructor(new TypeDesc[] {masterSupportType}); - b.returnVoid(); - } + // Add constructors. + // 1: Accepts a RawSupport. + // 2: Accepts a RawSupport and an encoded key. + // 3: Accepts a RawSupport, an encoded key and an encoded data. + for (int i=1; i<=3; i++) { + TypeDesc[] params = new TypeDesc[i]; + params[0] = rawSupportType; + if (i >= 2) { + params[1] = byteArrayType; + if (i == 3) { + params[2] = byteArrayType; + } + } - // Add constructor that accepts a RawSupport, an encoded key, and an - // encoded data. - { - TypeDesc[] params = {rawSupportType, byteArrayType, byteArrayType}; MethodInfo mi = cf.addConstructor(Modifiers.PUBLIC, params); CodeBuilder b = new CodeBuilder(mi); + b.loadThis(); b.loadLocal(b.getParameter(0)); b.invokeSuperConstructor(new TypeDesc[] {masterSupportType}); - params = new TypeDesc[] {byteArrayType}; - - b.loadThis(); - b.loadLocal(b.getParameter(1)); - b.invokeVirtual(DECODE_KEY_METHOD_NAME, null, params); - - b.loadThis(); - b.loadLocal(b.getParameter(2)); - b.invokeVirtual(DECODE_DATA_METHOD_NAME, null, params); - - // Indicate that object is clean by calling markAllPropertiesClean. - b.loadThis(); - b.invokeVirtual(MARK_ALL_PROPERTIES_CLEAN, null, null); + if (i >= 2) { + params = new TypeDesc[] {byteArrayType}; + + b.loadThis(); + b.loadLocal(b.getParameter(1)); + b.invokeVirtual(DECODE_KEY_METHOD_NAME, null, params); + + if (i == 3) { + b.loadThis(); + b.loadLocal(b.getParameter(2)); + b.invokeVirtual(DECODE_DATA_METHOD_NAME, null, params); + + // Indicate that object is clean by calling markAllPropertiesClean. + b.loadThis(); + b.invokeVirtual(MARK_ALL_PROPERTIES_CLEAN, null, null); + } else { + // Only the primary key is clean. Calling + // markPropertiesClean might have no effect since subclass + // may set fields directly. Instead, set state bits directly. + + Collection> properties = StorableIntrospector + .examine(storableClass).getPrimaryKeyProperties().values(); + final int count = properties.size(); + int ordinal = 0; + int andMask = ~0; + int orMask = 0; + + for (StorableProperty property : properties) { + orMask |= StorableGenerator.PROPERTY_STATE_CLEAN << ((ordinal & 0xf) * 2); + andMask &= StorableGenerator.PROPERTY_STATE_MASK << ((ordinal & 0xf) * 2); + + ordinal++; + if ((ordinal & 0xf) == 0 || ordinal >= count) { + String stateFieldName = + StorableGenerator.PROPERTY_STATE_FIELD_NAME + ((ordinal - 1) >> 4); + b.loadThis(); + if (andMask == 0) { + b.loadConstant(orMask); + } else { + b.loadThis(); + b.loadField(stateFieldName, TypeDesc.INT); + b.loadConstant(andMask); + b.math(Opcode.IAND); + b.loadConstant(orMask); + b.math(Opcode.IOR); + } + b.storeField(stateFieldName, TypeDesc.INT); + andMask = ~0; + orMask = 0; + } + } + } + } b.returnVoid(); } -- cgit v1.2.3