From b66fb3db6951b2b6d3ace72ca3e197c7c2048e86 Mon Sep 17 00:00:00 2001 From: "Brian S. O'Neill" Date: Thu, 18 Dec 2008 20:58:00 +0000 Subject: Fixes for excessive class generation and memory usage when opening multiple repositories. --- .../amazon/carbonado/raw/GenericStorableCodec.java | 122 ++++++++++----------- .../java/com/amazon/carbonado/raw/RawSupport.java | 14 +++ .../com/amazon/carbonado/raw/StorableCodec.java | 14 +++ 3 files changed, 87 insertions(+), 63 deletions(-) (limited to 'src/main/java/com/amazon/carbonado/raw') diff --git a/src/main/java/com/amazon/carbonado/raw/GenericStorableCodec.java b/src/main/java/com/amazon/carbonado/raw/GenericStorableCodec.java index dd43515..4506bc1 100644 --- a/src/main/java/com/amazon/carbonado/raw/GenericStorableCodec.java +++ b/src/main/java/com/amazon/carbonado/raw/GenericStorableCodec.java @@ -18,7 +18,6 @@ package com.amazon.carbonado.raw; -import java.lang.ref.WeakReference; import java.lang.reflect.Method; import java.lang.reflect.UndeclaredThrowableException; import java.util.Map; @@ -51,6 +50,8 @@ import com.amazon.carbonado.info.StorableProperty; import com.amazon.carbonado.layout.Layout; import com.amazon.carbonado.gen.CodeBuilderUtil; +import com.amazon.carbonado.gen.StorableGenerator; +import com.amazon.carbonado.gen.TriggerSupport; import com.amazon.carbonado.util.ThrowUnchecked; import com.amazon.carbonado.util.QuickConstructorGenerator; @@ -64,10 +65,8 @@ import com.amazon.carbonado.util.QuickConstructorGenerator; */ public class GenericStorableCodec implements StorableCodec { private static final String BLANK_KEY_FIELD_NAME = "blankKey$"; - private static final String CODEC_FIELD_NAME = "codec$"; - private static final String ASSIGN_CODEC_METHOD_NAME = "assignCodec$"; - // Maps GenericEncodingStrategy instances to GenericStorableCodec instances. + // Maps GenericEncodingStrategy instances to Storable classes. private static final Map cCache = new SoftValuedHashMap(); /** @@ -100,7 +99,8 @@ public class GenericStorableCodec implements StorableCodec - (factory, + (key, + factory, encodingStrategy.getType(), storableImpl, encodingStrategy, @@ -128,30 +128,10 @@ public class GenericStorableCodec implements StorableCodec implements StorableCodec implements StorableCodec mType; private final Class mStorableClass; @@ -330,9 +306,6 @@ public class GenericStorableCodec implements StorableCodec mPrimaryKeyFactory; - // Maps OrderedProperty[] keys to SearchKeyFactory instances. - private final Map mSearchKeyFactories = new SoftValuedHashMap(); - private final Layout mLayout; private final RawSupport mSupport; @@ -340,11 +313,16 @@ public class GenericStorableCodec implements StorableCodec type, Class storableClass, GenericEncodingStrategy encodingStrategy, Layout layout, RawSupport support) { + mCodecKey = codecKey; mFactory = factory; mType = type; mStorableClass = storableClass; @@ -354,16 +332,6 @@ public class GenericStorableCodec implements StorableCodec implements StorableCodec getSearchKeyFactory(OrderedProperty[] properties) { // This KeyFactory makes arrays work as hashtable keys. - Object key = org.cojen.util.KeyFactory.createKey(properties); + Object key = KeyFactory.createKey(new Object[] {mCodecKey, properties}); - synchronized (mSearchKeyFactories) { - SearchKeyFactory factory = (SearchKeyFactory) mSearchKeyFactories.get(key); + synchronized (cCodecSearchKeyFactories) { + SearchKeyFactory factory = (SearchKeyFactory) cCodecSearchKeyFactories.get(key); if (factory == null) { factory = generateSearchKeyFactory(properties); - mSearchKeyFactories.put(key, factory); + cCodecSearchKeyFactories.put(key, factory); } return factory; } } + @Override + public void decode(S dest, int generation, byte[] data) throws CorruptEncodingException { + try { + getDecoder(generation).decode(dest, data); + } catch (CorruptEncodingException e) { + throw e; + } catch (RepositoryException e) { + throw new CorruptEncodingException(e); + } + } + /** * Returns a data decoder for the given generation. * * @throws FetchNoneException if generation is unknown + * @deprecated use direct decode method */ + @Deprecated public Decoder getDecoder(int generation) throws FetchNoneException, FetchException { try { synchronized (mLayout) { @@ -524,7 +505,22 @@ public class GenericStorableCodec implements StorableCodec decoder = (Decoder) decoders.get(generation); if (decoder == null) { - decoder = generateDecoder(generation); + synchronized (cCodecDecoders) { + Object key = KeyFactory.createKey(new Object[] {mCodecKey, generation}); + decoder = (Decoder) cCodecDecoders.get(key); + if (decoder == null) { + decoder = generateDecoder(generation); + cCodecDecoders.put(key, decoder); + } else { + // Confirm that layout still exists. + try { + mLayout.getGeneration(generation); + } catch (FetchNoneException e) { + cCodecDecoders.remove(key); + throw e; + } + } + } mDecoders.put(generation, decoder); } return decoder; @@ -915,6 +911,6 @@ public class GenericStorableCodec implements StorableCodec extends MasterSupport { * @throws PersistException if blob is unrecognized */ long getLocator(Clob clob) throws PersistException; + + /** + * Used for decoding different generations of Storable. If layout + * generations are not supported, simply throw a CorruptEncodingException. + * + * @param dest storable to receive decoded properties + * @param int storable layout generation number + * @param data decoded into properties, some of which may be dropped if + * destination storable doesn't have it + * @throws CorruptEncodingException if generation is unknown or if data cannot be decoded + * @since 1.2.1 + */ + void decode(S dest, int generation, byte[] data) throws CorruptEncodingException; } diff --git a/src/main/java/com/amazon/carbonado/raw/StorableCodec.java b/src/main/java/com/amazon/carbonado/raw/StorableCodec.java index fefb0fe..6874305 100644 --- a/src/main/java/com/amazon/carbonado/raw/StorableCodec.java +++ b/src/main/java/com/amazon/carbonado/raw/StorableCodec.java @@ -18,6 +18,7 @@ package com.amazon.carbonado.raw; +import com.amazon.carbonado.CorruptEncodingException; import com.amazon.carbonado.FetchException; import com.amazon.carbonado.Storable; import com.amazon.carbonado.info.StorableIndex; @@ -133,6 +134,19 @@ public interface StorableCodec { */ byte[] encodePrimaryKeyPrefix(); + /** + * Used for decoding different generations of Storable. If layout + * generations are not supported, simply throw a CorruptEncodingException. + * + * @param dest storable to receive decoded properties + * @param int storable layout generation number + * @param data decoded into properties, some of which may be dropped if + * destination storable doesn't have it + * @throws CorruptEncodingException if generation is unknown or if data cannot be decoded + * @since 1.2.1 + */ + void decode(S dest, int generation, byte[] data) throws CorruptEncodingException; + /** * Returns the default {@link RawSupport} object that is supplied to * Storable instances produced by this codec. -- cgit v1.2.3