diff options
Diffstat (limited to 'src/main/java/com/amazon/carbonado/raw')
8 files changed, 221 insertions, 59 deletions
| diff --git a/src/main/java/com/amazon/carbonado/raw/CustomStorableCodec.java b/src/main/java/com/amazon/carbonado/raw/CustomStorableCodec.java index 60bde78..cfb0883 100644 --- a/src/main/java/com/amazon/carbonado/raw/CustomStorableCodec.java +++ b/src/main/java/com/amazon/carbonado/raw/CustomStorableCodec.java @@ -232,6 +232,10 @@ public abstract class CustomStorableCodec<S extends Storable> implements Storabl      private final int mPkPropertyCount;
      private final InstanceFactory mInstanceFactory;
 +    // Modified by CustomStorableCodecFactory after construction. This provides
 +    // backwards compatibility with implementations of CustomStorableCodecFactory.
 +    RawSupport<S> mSupport;
 +
      public interface InstanceFactory {
          Storable instantiate(RawSupport support, CustomStorableCodec codec);
 @@ -245,11 +249,22 @@ public abstract class CustomStorableCodec<S extends Storable> implements Storabl       * @throws SupportException if Storable is not supported
       */
      public CustomStorableCodec(Class<S> type, boolean isMaster) throws SupportException {
 +        this(type, isMaster, null);
 +    }
 +
 +    /**
 +     * @param isMaster when true, version properties and sequences are managed
 +     * @throws SupportException if Storable is not supported
 +     */
 +    public CustomStorableCodec(Class<S> type, boolean isMaster, RawSupport<S> support)
 +        throws SupportException
 +    {
          mType = type;
          mPkPropertyCount = getPrimaryKeyIndex().getPropertyCount();
          Class<? extends S> storableClass = getStorableClass(type, isMaster);
          mInstanceFactory = QuickConstructorGenerator
              .getInstance(storableClass, InstanceFactory.class);
 +        mSupport = support;
      }
      public Class<S> getStorableType() {
 @@ -257,6 +272,18 @@ public abstract class CustomStorableCodec<S extends Storable> implements Storabl      }
      @SuppressWarnings("unchecked")
 +    public S instantiate() {
 +        return (S) mInstanceFactory.instantiate(support(), this);
 +    }
 +
 +    @SuppressWarnings("unchecked")
 +    public S instantiate(byte[] key, byte[] value)
 +        throws FetchException
 +    {
 +        return (S) mInstanceFactory.instantiate(support(), key, value, this);
 +    }
 +
 +    @SuppressWarnings("unchecked")
      public S instantiate(RawSupport<S> support) {
          return (S) mInstanceFactory.instantiate(support, this);
      }
 @@ -276,6 +303,18 @@ public abstract class CustomStorableCodec<S extends Storable> implements Storabl          return encodePrimaryKey(values, 0, mPkPropertyCount);
      }
 +    public RawSupport<S> getSupport() {
 +        return mSupport;
 +    }
 +
 +    private RawSupport<S> support() {
 +        RawSupport<S> support = mSupport;
 +        if (support == null) {
 +            throw new IllegalStateException("No RawSupport");
 +        }
 +        return support;
 +    }
 +
      /**
       * Convenient access to all the storable properties.
       */
 diff --git a/src/main/java/com/amazon/carbonado/raw/CustomStorableCodecFactory.java b/src/main/java/com/amazon/carbonado/raw/CustomStorableCodecFactory.java index bfba733..a3af33f 100644 --- a/src/main/java/com/amazon/carbonado/raw/CustomStorableCodecFactory.java +++ b/src/main/java/com/amazon/carbonado/raw/CustomStorableCodecFactory.java @@ -59,6 +59,30 @@ public abstract class CustomStorableCodecFactory implements StorableCodecFactory      /**
       * @param type type of storable to create codec for
 +     * @param pkIndex ignored
 +     * @param isMaster when true, version properties and sequences are managed
 +     * @param layout when non-null, attempt to encode a storable layout
 +     * generation value in each storable
 +     * @param support binds generated storable with a storage layer
 +     * @throws SupportException if type is not supported
 +     */
 +    public <S extends Storable> CustomStorableCodec<S> createCodec(Class<S> type,
 +                                                                   StorableIndex pkIndex,
 +                                                                   boolean isMaster,
 +                                                                   Layout layout,
 +                                                                   RawSupport support)
 +        throws SupportException
 +    {
 +        CustomStorableCodec<S> codec = createCodec(type, isMaster, layout, support);
 +        // Possibly set support after construction, for backwards compatibility.
 +        if (codec.mSupport == null) {
 +            codec.mSupport = support;
 +        }
 +        return codec;
 +    }
 +
 +    /**
 +     * @param type type of storable to create codec for
       * @param isMaster when true, version properties and sequences are managed
       * @param layout when non-null, attempt to encode a storable layout
       * generation value in each storable
 @@ -67,4 +91,20 @@ public abstract class CustomStorableCodecFactory implements StorableCodecFactory      protected abstract <S extends Storable> CustomStorableCodec<S>
          createCodec(Class<S> type, boolean isMaster, Layout layout)
          throws SupportException;
 +
 +    /**
 +     * @param type type of storable to create codec for
 +     * @param isMaster when true, version properties and sequences are managed
 +     * @param layout when non-null, attempt to encode a storable layout
 +     * generation value in each storable
 +     * @param support binds generated storable with a storage layer
 +     * @throws SupportException if type is not supported
 +     */
 +    // Note: This factory method is not abstract for backwards compatibility.
 +    protected <S extends Storable> CustomStorableCodec<S>
 +        createCodec(Class<S> type, boolean isMaster, Layout layout, RawSupport support)
 +        throws SupportException
 +    {
 +        return createCodec(type, isMaster, layout);
 +    }
  }
 diff --git a/src/main/java/com/amazon/carbonado/raw/GenericEncodingStrategy.java b/src/main/java/com/amazon/carbonado/raw/GenericEncodingStrategy.java index 76622b7..c22881e 100644 --- a/src/main/java/com/amazon/carbonado/raw/GenericEncodingStrategy.java +++ b/src/main/java/com/amazon/carbonado/raw/GenericEncodingStrategy.java @@ -1318,8 +1318,11 @@ public class GenericEncodingStrategy<S extends Storable> {       * Generates code to push RawSupport instance to the stack.  RawSupport is
       * available only in Storable instances. If instanceVar is an Object[], a
       * SupportException is thrown.
 +     *
 +     * @param instanceVar Storable instance or array of property values. Null
 +     * is storable instance of "this".
       */
 -    private void pushRawSupport(CodeAssembler a, LocalVariable instanceVar)
 +    protected void pushRawSupport(CodeAssembler a, LocalVariable instanceVar)
          throws SupportException
      {
          boolean isObjectArrayInstanceVar = instanceVar != null
 diff --git a/src/main/java/com/amazon/carbonado/raw/GenericInstanceFactory.java b/src/main/java/com/amazon/carbonado/raw/GenericInstanceFactory.java index 339bdbd..fb2ef45 100644 --- a/src/main/java/com/amazon/carbonado/raw/GenericInstanceFactory.java +++ b/src/main/java/com/amazon/carbonado/raw/GenericInstanceFactory.java @@ -30,9 +30,7 @@ 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) throws FetchException;
 -    Storable instantiate(RawSupport support, byte[] key, byte[] value)
 -        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 741a50d..0ef4846 100644 --- a/src/main/java/com/amazon/carbonado/raw/GenericStorableCodec.java +++ b/src/main/java/com/amazon/carbonado/raw/GenericStorableCodec.java @@ -79,6 +79,7 @@ public class GenericStorableCodec<S extends Storable> implements StorableCodec<S       * @param layout when non-null, encode a storable layout generation
       * value in one or four bytes. Generation 0..127 is encoded in one byte, and
       * 128..max is encoded in four bytes, with the most significant bit set.
 +     * @param support binds generated storable with a storage layer
       * @throws SupportException if Storable is not supported
       * @throws amazon.carbonado.MalformedTypeException if Storable type is not well-formed
       * @throws IllegalArgumentException if type is null
 @@ -86,29 +87,25 @@ public class GenericStorableCodec<S extends Storable> implements StorableCodec<S      @SuppressWarnings("unchecked")
      static synchronized <S extends Storable> GenericStorableCodec<S> getInstance
          (GenericStorableCodecFactory factory,
 -         GenericEncodingStrategy<S> encodingStrategy, boolean isMaster, Layout layout)
 +         GenericEncodingStrategy<S> encodingStrategy, boolean isMaster,
 +         Layout layout, RawSupport support)
          throws SupportException
      {
 -        Object key;
 -        if (layout == null) {
 -            key = KeyFactory.createKey(new Object[] {encodingStrategy, isMaster});
 -        } else {
 -            key = KeyFactory.createKey
 -                (new Object[] {encodingStrategy, isMaster, factory, layout.getGeneration()});
 -        }
 +        Object key = KeyFactory.createKey(new Object[] {encodingStrategy, isMaster, layout});
 -        GenericStorableCodec<S> codec = (GenericStorableCodec<S>) cCache.get(key);
 -        if (codec == null) {
 -            codec = new GenericStorableCodec<S>
 -                (factory,
 -                 encodingStrategy.getType(),
 -                 generateStorable(encodingStrategy, isMaster, layout),
 -                 encodingStrategy,
 -                 layout);
 -            cCache.put(key, codec);
 +        Class<? extends S> storableImpl = (Class<? extends S>) cCache.get(key);
 +        if (storableImpl == null) {
 +            storableImpl = generateStorable(encodingStrategy, isMaster, layout);
 +            cCache.put(key, storableImpl);
          }
 -        return codec;
 +        return new GenericStorableCodec<S>
 +            (factory,
 +             encodingStrategy.getType(),
 +             storableImpl,
 +             encodingStrategy,
 +             layout,
 +             support);
      }
      @SuppressWarnings("unchecked")
 @@ -325,10 +322,7 @@ public class GenericStorableCodec<S extends Storable> implements StorableCodec<S      private final Class<? extends S> mStorableClass;
 -    // Weakly reference the encoding strategy because of the way
 -    // GenericStorableCodec instances are cached in a SoftValuedHashMap.
 -    // GenericStorableCodec can still be reclaimed by the garbage collector.
 -    private final WeakReference<GenericEncodingStrategy<S>> mEncodingStrategy;
 +    private final GenericEncodingStrategy<S> mEncodingStrategy;
      private final GenericInstanceFactory mInstanceFactory;
 @@ -339,27 +333,30 @@ public class GenericStorableCodec<S extends Storable> implements StorableCodec<S      private final Layout mLayout;
 +    private final RawSupport<S> mSupport;
 +
      // Maps layout generations to Decoders.
      private IntHashMap mDecoders;
      private GenericStorableCodec(GenericStorableCodecFactory factory,
                                   Class<S> type, Class<? extends S> storableClass,
                                   GenericEncodingStrategy<S> encodingStrategy,
 -                                 Layout layout) {
 +                                 Layout layout, RawSupport<S> support)
 +    {
          mFactory = factory;
          mType = type;
          mStorableClass = storableClass;
 -        mEncodingStrategy = new WeakReference<GenericEncodingStrategy<S>>(encodingStrategy);
 +        mEncodingStrategy = encodingStrategy;
          mInstanceFactory = QuickConstructorGenerator
              .getInstance(storableClass, GenericInstanceFactory.class);
          mPrimaryKeyFactory = getSearchKeyFactory(encodingStrategy.gatherAllKeyProperties());
          mLayout = layout;
 +        mSupport = support;
          if (layout != null) {
              try {
                  // Assign static reference back to this codec.
 -                Method m = storableClass.getMethod
 -                    (ASSIGN_CODEC_METHOD_NAME, WeakReference.class);
 +                Method m = storableClass.getMethod(ASSIGN_CODEC_METHOD_NAME, WeakReference.class);
                  m.invoke(null, new WeakReference(this));
              } catch (Exception e) {
                  ThrowUnchecked.fireFirstDeclaredCause(e);
 @@ -375,7 +372,30 @@ public class GenericStorableCodec<S extends Storable> implements StorableCodec<S      }
      /**
 -     * Instantiate a Storable with no key or value defined yet.
 +     * Instantiate a Storable with no key or value defined yet. The default
 +     * {@link RawSupport} is supplied to the instance.
 +     *
 +     * @throws IllegalStateException if no default support exists
 +     */
 +    @SuppressWarnings("unchecked")
 +    public S instantiate() {
 +        return (S) mInstanceFactory.instantiate(support());
 +    }
 +
 +    /**
 +     * Instantiate a Storable with a specific key and value. The default
 +     * {@link RawSupport} is supplied to the instance.
 +     *
 +     * @throws IllegalStateException if no default support exists
 +     */
 +    @SuppressWarnings("unchecked")
 +    public S instantiate(byte[] key, byte[] value) throws FetchException {
 +        return (S) mInstanceFactory.instantiate(support(), key, value);
 +    }
 +
 +    /**
 +     * Instantiate a Storable with no key or value defined yet. Any
 +     * {@link RawSupport} can be supplied to the instance.
       *
       * @param support binds generated storable with a storage layer
       */
 @@ -385,14 +405,13 @@ public class GenericStorableCodec<S extends Storable> implements StorableCodec<S      }
      /**
 -     * Instantiate a Storable with a specific key and value.
 +     * Instantiate a Storable with a specific key and value. Any
 +     * {@link RawSupport} can be supplied to the instance.
       *
       * @param support binds generated storable with a storage layer
       */
      @SuppressWarnings("unchecked")
 -    public S instantiate(RawSupport<S> support, byte[] key, byte[] value)
 -        throws FetchException
 -    {
 +    public S instantiate(RawSupport<S> support, byte[] key, byte[] value) throws FetchException {
          try {
              return (S) mInstanceFactory.instantiate(support, key, value);
          } catch (CorruptEncodingException e) {
 @@ -407,11 +426,11 @@ public class GenericStorableCodec<S extends Storable> implements StorableCodec<S      }
      public StorableIndex<S> getPrimaryKeyIndex() {
 -        return getEncodingStrategy().getPrimaryKeyIndex();
 +        return mEncodingStrategy.getPrimaryKeyIndex();
      }
      public int getPrimaryKeyPrefixLength() {
 -        return getEncodingStrategy().getConstantKeyPrefixLength();
 +        return mEncodingStrategy.getConstantKeyPrefixLength();
      }
      public byte[] encodePrimaryKey(S storable) {
 @@ -434,6 +453,18 @@ public class GenericStorableCodec<S extends Storable> implements StorableCodec<S          return mPrimaryKeyFactory.encodeSearchKeyPrefix();
      }
 +    public RawSupport<S> getSupport() {
 +        return mSupport;
 +    }
 +
 +    private RawSupport<S> support() {
 +        RawSupport<S> support = mSupport;
 +        if (support == null) {
 +            throw new IllegalStateException("No RawSupport");
 +        }
 +        return support;
 +    }
 +
      /**
       * Returns a concrete Storable implementation, which is fully
       * thread-safe. It has two constructors defined:
 @@ -499,17 +530,8 @@ public class GenericStorableCodec<S extends Storable> implements StorableCodec<S          }
      }
 -    private GenericEncodingStrategy<S> getEncodingStrategy() {
 -        // Should never be null, even though it is weakly referenced. As long
 -        // as this class can be reached by the cache, the encoding strategy
 -        // object exists since it is the cache key.
 -        return mEncodingStrategy.get();
 -    }
 -
      @SuppressWarnings("unchecked")
      private SearchKeyFactory<S> generateSearchKeyFactory(OrderedProperty<S>[] properties) {
 -        GenericEncodingStrategy encodingStrategy = getEncodingStrategy();
 -
          ClassInjector ci;
          {
              StringBuilder b = new StringBuilder();
 @@ -562,7 +584,7 @@ public class GenericStorableCodec<S extends Storable> implements StorableCodec<S              // useReadMethods       = false (will read fields directly)
              // partialStartVar      = null (only support encoding all properties)
              // partialEndVar        = null (only support encoding all properties)
 -            LocalVariable encodedVar = encodingStrategy.buildKeyEncoding
 +            LocalVariable encodedVar = mEncodingStrategy.buildKeyEncoding
                  (b, properties, instanceVar, null, false, null, null);
              b.loadLocal(encodedVar);
 @@ -591,7 +613,7 @@ public class GenericStorableCodec<S extends Storable> implements StorableCodec<S              // useReadMethods       = false (will read fields directly)
              // partialStartVar      = int parameter 1, references start property index
              // partialEndVar        = int parameter 2, references end property index
 -            LocalVariable encodedVar = encodingStrategy.buildKeyEncoding
 +            LocalVariable encodedVar = mEncodingStrategy.buildKeyEncoding
                  (b, properties, instanceVar, null, false, b.getParameter(1), b.getParameter(2));
              b.loadLocal(encodedVar);
 @@ -623,7 +645,7 @@ public class GenericStorableCodec<S extends Storable> implements StorableCodec<S              // useReadMethods       = false (will read fields directly)
              // partialStartVar      = null (only support encoding all properties)
              // partialEndVar        = null (only support encoding all properties)
 -            LocalVariable encodedVar = encodingStrategy.buildKeyEncoding
 +            LocalVariable encodedVar = mEncodingStrategy.buildKeyEncoding
                  (b, properties, b.getParameter(0), adapterInstanceClass, false, null, null);
              b.loadLocal(encodedVar);
 @@ -648,7 +670,7 @@ public class GenericStorableCodec<S extends Storable> implements StorableCodec<S              // useReadMethods       = false (will read fields directly)
              // partialStartVar      = int parameter 1, references start property index
              // partialEndVar        = int parameter 2, references end property index
 -            LocalVariable encodedVar = encodingStrategy.buildKeyEncoding
 +            LocalVariable encodedVar = mEncodingStrategy.buildKeyEncoding
                  (b, properties, b.getParameter(0), adapterInstanceClass,
                   false, b.getParameter(1), b.getParameter(2));
 @@ -666,8 +688,8 @@ public class GenericStorableCodec<S extends Storable> implements StorableCodec<S                  (Modifiers.PUBLIC, "encodeSearchKeyPrefix", byteArrayType, null);
              CodeBuilder b = new CodeBuilder(mi);
 -            if (encodingStrategy.getKeyPrefixPadding() == 0 &&
 -                encodingStrategy.getKeySuffixPadding() == 0) {
 +            if (mEncodingStrategy.getKeyPrefixPadding() == 0 &&
 +                mEncodingStrategy.getKeySuffixPadding() == 0) {
                  // Return null instead of a zero-length array.
                  b.loadNull();
                  b.returnValue(byteArrayType);
 @@ -689,7 +711,7 @@ public class GenericStorableCodec<S extends Storable> implements StorableCodec<S                  // useReadMethods       = false (no parameters means we don't need this)
                  // partialStartVar      = null (no parameters means we don't need this)
                  // partialEndVar        = null (no parameters means we don't need this)
 -                LocalVariable encodedVar = encodingStrategy.buildKeyEncoding
 +                LocalVariable encodedVar = mEncodingStrategy.buildKeyEncoding
                      (b, new OrderedProperty[0], null, null, false, null, null);
                  b.loadLocal(encodedVar);
 diff --git a/src/main/java/com/amazon/carbonado/raw/GenericStorableCodecFactory.java b/src/main/java/com/amazon/carbonado/raw/GenericStorableCodecFactory.java index ab640e6..3885505 100644 --- a/src/main/java/com/amazon/carbonado/raw/GenericStorableCodecFactory.java +++ b/src/main/java/com/amazon/carbonado/raw/GenericStorableCodecFactory.java @@ -57,8 +57,29 @@ public class GenericStorableCodecFactory implements StorableCodecFactory {                                                                      Layout layout)
          throws SupportException
      {
 +        return createCodec(type, pkIndex, isMaster, layout, null);
 +    }
 +
 +    /**
 +     * @param type type of storable to create codec for
 +     * @param pkIndex suggested index for primary key (optional)
 +     * @param isMaster when true, version properties and sequences are managed
 +     * @param layout when non-null, encode a storable layout generation
 +     * value in one or four bytes. Generation 0..127 is encoded in one byte, and
 +     * 128..max is encoded in four bytes, with the most significant bit set.
 +     * @param support binds generated storable with a storage layer
 +     * @throws SupportException if type is not supported
 +     */
 +    @SuppressWarnings("unchecked")
 +    public <S extends Storable> GenericStorableCodec<S> createCodec(Class<S> type,
 +                                                                    StorableIndex pkIndex,
 +                                                                    boolean isMaster,
 +                                                                    Layout layout,
 +                                                                    RawSupport support)
 +        throws SupportException
 +    {
          return GenericStorableCodec.getInstance
 -            (this, createStrategy(type, pkIndex), isMaster, layout);
 +            (this, createStrategy(type, pkIndex), isMaster, layout, support);
      }
      /**
 diff --git a/src/main/java/com/amazon/carbonado/raw/StorableCodec.java b/src/main/java/com/amazon/carbonado/raw/StorableCodec.java index 7965690..f9e347c 100644 --- a/src/main/java/com/amazon/carbonado/raw/StorableCodec.java +++ b/src/main/java/com/amazon/carbonado/raw/StorableCodec.java @@ -35,19 +35,36 @@ public interface StorableCodec<S extends Storable> {      Class<S> getStorableType();
      /**
 -     * Instantiate a Storable with no key or value defined yet.
 +     * Instantiate a Storable with no key or value defined yet. The default
 +     * {@link RawSupport} is supplied to the instance.
 +     *
 +     * @throws IllegalStateException if no default support exists
 +     */
 +    S instantiate();
 +
 +    /**
 +     * Instantiate a Storable with a specific key and value. The default
 +     * {@link RawSupport} is supplied to the instance.
 +     *
 +     * @throws IllegalStateException if no default support exists
 +     */
 +    S instantiate(byte[] key, byte[] value) throws FetchException;
 +
 +    /**
 +     * Instantiate a Storable with no key or value defined yet. Any
 +     * {@link RawSupport} can be supplied to the instance.
       *
       * @param support binds generated storable with a storage layer
       */
      S instantiate(RawSupport<S> support);
      /**
 -     * Instantiate a Storable with a specific key and value.
 +     * Instantiate a Storable with a specific key and value. Any
 +     * {@link RawSupport} can be supplied to the instance.
       *
       * @param support binds generated storable with a storage layer
       */
 -    S instantiate(RawSupport<S> support, byte[] key, byte[] value)
 -        throws FetchException;
 +    S instantiate(RawSupport<S> support, byte[] key, byte[] value) throws FetchException;
      /**
       * Returns the sequence and directions of properties that make up the
 @@ -113,4 +130,10 @@ public interface StorableCodec<S extends Storable> {       * prefix. Returned value may be null if no prefix is defined.
       */
      byte[] encodePrimaryKeyPrefix();
 +
 +    /**
 +     * Returns the default {@link RawSupport} object that is supplied to
 +     * Storable instances produced by this codec.
 +     */
 +    RawSupport<S> getSupport();
  }
 diff --git a/src/main/java/com/amazon/carbonado/raw/StorableCodecFactory.java b/src/main/java/com/amazon/carbonado/raw/StorableCodecFactory.java index 1b19490..db05a9e 100644 --- a/src/main/java/com/amazon/carbonado/raw/StorableCodecFactory.java +++ b/src/main/java/com/amazon/carbonado/raw/StorableCodecFactory.java @@ -51,4 +51,20 @@ public interface StorableCodecFactory {                                                        boolean isMaster,
                                                        Layout layout)
          throws SupportException;
 +
 +    /**
 +     * @param type type of storable to create codec for
 +     * @param pkIndex suggested index for primary key (optional)
 +     * @param isMaster when true, version properties and sequences are managed
 +     * @param layout when non-null, attempt to encode a storable layout
 +     * generation value in each storable
 +     * @param support binds generated storable with a storage layer
 +     * @throws SupportException if type is not supported
 +     */
 +    <S extends Storable> StorableCodec<S> createCodec(Class<S> type,
 +                                                      StorableIndex pkIndex,
 +                                                      boolean isMaster,
 +                                                      Layout layout,
 +                                                      RawSupport support)
 +        throws SupportException;
  }
 | 
