IGNITE-2100: Fixed serilaization of Externalizable. Now queries work in all modes.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/057ad5bb Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/057ad5bb Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/057ad5bb Branch: refs/heads/ignite-gg-10889 Commit: 057ad5bb4d054cba90932ff5614a928b623d44cc Parents: 1f484ea Author: vozerov-gridgain <voze...@gridgain.com> Authored: Thu Dec 17 17:00:29 2015 +0300 Committer: vozerov-gridgain <voze...@gridgain.com> Committed: Thu Dec 17 17:00:29 2015 +0300 ---------------------------------------------------------------------- .../binary/BinaryReflectiveSerializer.java | 33 ++ .../ignite/binary/BinaryTypeConfiguration.java | 20 +- .../ignite/cache/affinity/AffinityKey.java | 2 +- .../internal/binary/BinaryClassDescriptor.java | 124 ++---- .../ignite/internal/binary/BinaryContext.java | 109 ++++- .../internal/binary/BinaryFieldAccessor.java | 3 - .../ignite/internal/binary/BinaryUtils.java | 49 ++- .../ignite/internal/binary/BinaryWriteMode.java | 3 - .../cache/binary/BinaryMetadataKey.java | 2 +- .../binary/CacheObjectBinaryProcessorImpl.java | 2 +- .../PlatformDotNetConfigurationClosure.java | 4 +- .../processors/query/GridQueryProcessor.java | 204 ++++++--- .../binary/BinaryFieldsAbstractSelfTest.java | 4 +- .../BinaryFooterOffsetsAbstractSelfTest.java | 3 +- .../binary/BinaryMarshallerSelfTest.java | 34 +- ...GridBinaryMarshallerCtxDisabledSelfTest.java | 3 +- .../binary/GridBinaryWildcardsSelfTest.java | 3 +- .../GridCacheOnCopyFlagAbstractSelfTest.java | 33 +- .../GridBinaryCacheEntryMemorySizeSelfTest.java | 3 +- .../session/GridSessionCheckpointSelfTest.java | 3 +- .../ignite/testframework/junits/IgniteMock.java | 3 +- .../junits/IgniteTestResources.java | 4 +- .../cache/BinarySerializationQuerySelfTest.java | 416 +++++++++++++++++++ ...onQueryWithReflectiveSerializerSelfTest.java | 28 ++ ...niteCacheP2pUnmarshallingQueryErrorTest.java | 4 +- .../IgniteBinaryCacheQueryTestSuite.java | 119 +++++- 26 files changed, 995 insertions(+), 220 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/057ad5bb/modules/core/src/main/java/org/apache/ignite/binary/BinaryReflectiveSerializer.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/binary/BinaryReflectiveSerializer.java b/modules/core/src/main/java/org/apache/ignite/binary/BinaryReflectiveSerializer.java new file mode 100644 index 0000000..fd0f841 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/binary/BinaryReflectiveSerializer.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.binary; + +/** + * Binary serializer which writes object fields using reflection. Transient fields are not written. + */ +public class BinaryReflectiveSerializer implements BinarySerializer { + /** {@inheritDoc} */ + @Override public void writeBinary(Object obj, BinaryWriter writer) throws BinaryObjectException { + assert false : "Method should not be called directly."; + } + + /** {@inheritDoc} */ + @Override public void readBinary(Object obj, BinaryReader reader) throws BinaryObjectException { + assert false : "Method should not be called directly."; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/057ad5bb/modules/core/src/main/java/org/apache/ignite/binary/BinaryTypeConfiguration.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/binary/BinaryTypeConfiguration.java b/modules/core/src/main/java/org/apache/ignite/binary/BinaryTypeConfiguration.java index a694eaf..a00c061 100644 --- a/modules/core/src/main/java/org/apache/ignite/binary/BinaryTypeConfiguration.java +++ b/modules/core/src/main/java/org/apache/ignite/binary/BinaryTypeConfiguration.java @@ -17,9 +17,10 @@ package org.apache.ignite.binary; -import org.apache.ignite.internal.util.typedef.internal.S; -import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.configuration.BinaryConfiguration; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.internal.util.typedef.internal.A; +import org.apache.ignite.internal.util.typedef.internal.S; /** * Defines configuration properties for a specific binary type. Providing per-type @@ -42,12 +43,27 @@ public class BinaryTypeConfiguration { private boolean isEnum; /** + * Constructor. */ public BinaryTypeConfiguration() { // No-op. } /** + * Copying constructor. + * + * @param other Other instance. + */ + public BinaryTypeConfiguration(BinaryTypeConfiguration other) { + A.notNull(other, "other"); + + typeName = other.typeName; + idMapper = other.idMapper; + serializer = other.serializer; + isEnum = other.isEnum; + } + + /** * @param typeName Class name. */ public BinaryTypeConfiguration(String typeName) { http://git-wip-us.apache.org/repos/asf/ignite/blob/057ad5bb/modules/core/src/main/java/org/apache/ignite/cache/affinity/AffinityKey.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/cache/affinity/AffinityKey.java b/modules/core/src/main/java/org/apache/ignite/cache/affinity/AffinityKey.java index ee6321c..c745ed8 100644 --- a/modules/core/src/main/java/org/apache/ignite/cache/affinity/AffinityKey.java +++ b/modules/core/src/main/java/org/apache/ignite/cache/affinity/AffinityKey.java @@ -64,6 +64,7 @@ public class AffinityKey<K> implements Externalizable { private K key; /** Affinity key. */ + @AffinityKeyMapped @GridToStringInclude private Object affKey; @@ -126,7 +127,6 @@ public class AffinityKey<K> implements Externalizable { * * @return Affinity key to use for affinity mapping. */ - @AffinityKeyMapped @SuppressWarnings({"unchecked"}) public <T> T affinityKey() { A.notNull(key, "key"); http://git-wip-us.apache.org/repos/asf/ignite/blob/057ad5bb/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java index 4a93bf6..eac1874 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java @@ -17,15 +17,24 @@ package org.apache.ignite.internal.binary; -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.binary.BinaryIdMapper; +import org.apache.ignite.binary.BinaryObjectException; +import org.apache.ignite.binary.BinaryReflectiveSerializer; +import org.apache.ignite.binary.BinarySerializer; +import org.apache.ignite.binary.Binarylizable; +import org.apache.ignite.internal.processors.cache.CacheObjectImpl; +import org.apache.ignite.internal.util.GridUnsafe; +import org.apache.ignite.internal.util.typedef.internal.U; +import org.apache.ignite.marshaller.MarshallerExclusions; +import org.apache.ignite.marshaller.optimized.OptimizedMarshaller; +import org.jetbrains.annotations.Nullable; +import sun.misc.Unsafe; + import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.lang.reflect.Modifier; import java.math.BigDecimal; import java.sql.Timestamp; import java.util.ArrayList; @@ -36,18 +45,6 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.UUID; -import org.apache.ignite.IgniteCheckedException; -import org.apache.ignite.binary.BinaryIdMapper; -import org.apache.ignite.binary.BinaryObjectException; -import org.apache.ignite.binary.BinarySerializer; -import org.apache.ignite.binary.Binarylizable; -import org.apache.ignite.internal.processors.cache.CacheObjectImpl; -import org.apache.ignite.internal.util.GridUnsafe; -import org.apache.ignite.internal.util.typedef.internal.U; -import org.apache.ignite.marshaller.MarshallerExclusions; -import org.apache.ignite.marshaller.optimized.OptimizedMarshaller; -import org.jetbrains.annotations.Nullable; -import sun.misc.Unsafe; import static java.lang.reflect.Modifier.isStatic; import static java.lang.reflect.Modifier.isTransient; @@ -65,7 +62,7 @@ public class BinaryClassDescriptor { /** */ private final Class<?> cls; - /** */ + /** Configured serializer. */ private final BinarySerializer serializer; /** ID mapper. */ @@ -127,7 +124,6 @@ public class BinaryClassDescriptor { * @param serializer Serializer. * @param metaDataEnabled Metadata enabled flag. * @param registered Whether typeId has been successfully registered by MarshallerContext or not. - * @param predefined Whether the class is predefined or not. * @throws BinaryObjectException In case of error. */ BinaryClassDescriptor( @@ -140,13 +136,19 @@ public class BinaryClassDescriptor { @Nullable BinaryIdMapper idMapper, @Nullable BinarySerializer serializer, boolean metaDataEnabled, - boolean registered, - boolean predefined + boolean registered ) throws BinaryObjectException { assert ctx != null; assert cls != null; assert idMapper != null; + // If serializer is not defined at this point, then we have to user OptimizedMarshaller. + useOptMarshaller = serializer == null; + + // Reset reflective serializer so that we rely on existing reflection-based serialization. + if (serializer instanceof BinaryReflectiveSerializer) + serializer = null; + this.ctx = ctx; this.cls = cls; this.typeId = typeId; @@ -161,10 +163,10 @@ public class BinaryClassDescriptor { excluded = MarshallerExclusions.isExcluded(cls); - useOptMarshaller = !predefined && initUseOptimizedMarshallerFlag(); - if (excluded) mode = BinaryWriteMode.EXCLUSION; + else if (useOptMarshaller) + mode = BinaryWriteMode.OBJECT; // Will not be used anywhere. else { if (cls == BinaryEnumObjectImpl.class) mode = BinaryWriteMode.BINARY_ENUM; @@ -172,6 +174,14 @@ public class BinaryClassDescriptor { mode = serializer != null ? BinaryWriteMode.BINARY : BinaryUtils.mode(cls); } + if (useOptMarshaller && userType) { + U.quietAndWarn(ctx.log(), "Class \"" + cls.getName() + "\" cannot be written in binary format because " + + "it either implements Externalizable interface or have writeObject/readObject methods. Please " + + "ensure that all nodes have this class in classpath. To enable binary serialization either " + + "implement " + Binarylizable.class.getSimpleName() + " interface or set explicit serializer using " + + "BinaryTypeConfiguration.setSerializer() method."); + } + switch (mode) { case P_BYTE: case P_BOOLEAN: @@ -224,7 +234,6 @@ public class BinaryClassDescriptor { break; case BINARY: - case EXTERNALIZABLE: ctor = constructor(cls); fields = null; stableFieldsMeta = null; @@ -267,8 +276,11 @@ public class BinaryClassDescriptor { schemaBuilder.addField(fieldId); - if (metaDataEnabled) + if (metaDataEnabled) { + assert stableFieldsMeta != null; + stableFieldsMeta.put(name, fieldInfo.mode().typeId()); + } } } } @@ -284,8 +296,7 @@ public class BinaryClassDescriptor { throw new BinaryObjectException("Invalid mode: " + mode); } - if (mode == BinaryWriteMode.BINARY || mode == BinaryWriteMode.EXTERNALIZABLE || - mode == BinaryWriteMode.OBJECT) { + if (mode == BinaryWriteMode.BINARY || mode == BinaryWriteMode.OBJECT) { readResolveMtd = U.findNonPublicMethod(cls, "readResolve"); writeReplaceMtd = U.findNonPublicMethod(cls, "writeReplace"); } @@ -608,25 +619,6 @@ public class BinaryClassDescriptor { break; - case EXTERNALIZABLE: - if (preWrite(writer, obj)) { - writer.rawWriter(); - - try { - ((Externalizable)obj).writeExternal(writer); - - postWrite(writer, obj); - } - catch (IOException e) { - throw new BinaryObjectException("Failed to write Externalizable object: " + obj, e); - } - finally { - writer.popSchema(); - } - } - - break; - case OBJECT: if (preWrite(writer, obj)) { try { @@ -672,21 +664,6 @@ public class BinaryClassDescriptor { break; - case EXTERNALIZABLE: - res = newInstance(); - - reader.setHandle(res); - - try { - ((Externalizable)res).readExternal(reader); - } - catch (IOException | ClassNotFoundException e) { - throw new BinaryObjectException("Failed to read Externalizable object: " + - res.getClass().getName(), e); - } - - break; - case OBJECT: res = newInstance(); @@ -785,29 +762,4 @@ public class BinaryClassDescriptor { throw new BinaryObjectException("Failed to get constructor for class: " + cls.getName(), e); } } - - /** - * Determines whether to use {@link OptimizedMarshaller} for serialization or - * not. - * - * @return {@code true} if to use, {@code false} otherwise. - */ - @SuppressWarnings("unchecked") - private boolean initUseOptimizedMarshallerFlag() { - for (Class c = cls; c != null && !c.equals(Object.class); c = c.getSuperclass()) { - try { - Method writeObj = c.getDeclaredMethod("writeObject", ObjectOutputStream.class); - Method readObj = c.getDeclaredMethod("readObject", ObjectInputStream.class); - - if (!Modifier.isStatic(writeObj.getModifiers()) && !Modifier.isStatic(readObj.getModifiers()) && - writeObj.getReturnType() == void.class && readObj.getReturnType() == void.class) - return true; - } - catch (NoSuchMethodException ignored) { - // No-op. - } - } - - return false; - } } http://git-wip-us.apache.org/repos/asf/ignite/blob/057ad5bb/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java index 7f9bacf..abe283e 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java @@ -18,18 +18,22 @@ package org.apache.ignite.internal.binary; import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.IgniteLogger; import org.apache.ignite.binary.BinaryIdMapper; import org.apache.ignite.binary.BinaryInvalidTypeException; import org.apache.ignite.binary.BinaryObjectException; +import org.apache.ignite.binary.BinaryReflectiveSerializer; import org.apache.ignite.binary.BinarySerializer; import org.apache.ignite.binary.BinaryType; import org.apache.ignite.binary.BinaryTypeConfiguration; import org.apache.ignite.cache.CacheKeyConfiguration; +import org.apache.ignite.cache.affinity.AffinityKey; import org.apache.ignite.cache.affinity.AffinityKeyMapped; import org.apache.ignite.configuration.BinaryConfiguration; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.internal.IgniteKernal; import org.apache.ignite.internal.IgnitionEx; +import org.apache.ignite.internal.processors.cache.binary.BinaryMetadataKey; import org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl; import org.apache.ignite.internal.processors.datastructures.CollocatedQueueItemKey; import org.apache.ignite.internal.processors.datastructures.CollocatedSetItemKey; @@ -126,8 +130,11 @@ public class BinaryContext implements Externalizable { /** */ private IgniteConfiguration igniteCfg; + /** Logger. */ + private IgniteLogger log; + /** */ - private final OptimizedMarshaller optmMarsh = new OptimizedMarshaller(); + private final OptimizedMarshaller optmMarsh = new OptimizedMarshaller(false); /** Compact footer flag. */ private boolean compactFooter; @@ -145,13 +152,15 @@ public class BinaryContext implements Externalizable { /** * @param metaHnd Meta data handler. * @param igniteCfg Ignite configuration. + * @param log Logger. */ - public BinaryContext(BinaryMetadataHandler metaHnd, IgniteConfiguration igniteCfg) { + public BinaryContext(BinaryMetadataHandler metaHnd, IgniteConfiguration igniteCfg, IgniteLogger log) { assert metaHnd != null; assert igniteCfg != null; this.metaHnd = metaHnd; this.igniteCfg = igniteCfg; + this.log = log; gridName = igniteCfg.getGridName(); @@ -194,22 +203,37 @@ public class BinaryContext implements Externalizable { registerPredefinedType(Timestamp[].class, GridBinaryMarshaller.TIMESTAMP_ARR); registerPredefinedType(Object[].class, GridBinaryMarshaller.OBJ_ARR); + // Special collections. registerPredefinedType(ArrayList.class, 0); registerPredefinedType(LinkedList.class, 0); registerPredefinedType(HashSet.class, 0); registerPredefinedType(LinkedHashSet.class, 0); - registerPredefinedType(HashMap.class, 0); registerPredefinedType(LinkedHashMap.class, 0); + // Classes with overriden default serialization flag. + registerPredefinedType(AffinityKey.class, 0); + registerPredefinedType(GridMapEntry.class, 60); registerPredefinedType(IgniteBiTuple.class, 61); registerPredefinedType(T2.class, 62); + registerPredefinedType(BinaryObjectImpl.class, 0); + registerPredefinedType(BinaryObjectOffheapImpl.class, 0); + registerPredefinedType(BinaryMetadataKey.class, 0); + registerPredefinedType(BinaryMetadata.class, 0); + // IDs range [200..1000] is used by Ignite internal APIs. } /** + * @return Logger. + */ + public IgniteLogger log() { + return log; + } + + /** * @return Marshaller. */ public BinaryMarshaller marshaller() { @@ -217,6 +241,21 @@ public class BinaryContext implements Externalizable { } /** + * Check whether class must be deserialized anyway. + * + * @param cls Class. + * @return {@code True} if must be deserialized. + */ + public boolean mustDeserialize(Class cls) { + BinaryClassDescriptor desc = descByCls.get(cls); + + if (desc == null) + return marshCtx.isSystemType(cls.getName()) || serializerForClass(cls) == null; + else + return desc.useOptimizedMarshaller(); + } + + /** * @return Ignite configuration. */ public IgniteConfiguration configuration(){ @@ -504,8 +543,7 @@ public class BinaryContext implements Externalizable { BinaryInternalIdMapper.defaultInstance(), null, false, - true, /* registered */ - false /* predefined */ + true /* registered */ ); BinaryClassDescriptor old = descByCls.putIfAbsent(cls, desc); @@ -541,6 +579,8 @@ public class BinaryContext implements Externalizable { throw new BinaryObjectException("Failed to register class.", e); } + BinarySerializer serializer = serializerForClass(cls); + String affFieldName = affinityFieldName(cls); BinaryClassDescriptor desc = new BinaryClassDescriptor(this, @@ -550,10 +590,9 @@ public class BinaryContext implements Externalizable { typeName, affFieldName, idMapper, - null, + serializer, true, - registered, - false /* predefined */ + registered ); if (!deserialize) { @@ -576,6 +615,30 @@ public class BinaryContext implements Externalizable { } /** + * Get serializer for class taking in count default one. + * + * @param cls Class. + * @return Serializer for class or {@code null} if none exists. + */ + private @Nullable BinarySerializer serializerForClass(Class cls) { + BinarySerializer serializer = defaultSerializer(); + + if (serializer == null && canUseReflectiveSerializer(cls)) + serializer = new BinaryReflectiveSerializer(); + + return serializer; + } + + /** + * @return Default serializer. + */ + private BinarySerializer defaultSerializer() { + BinaryConfiguration binCfg = igniteCfg.getBinaryConfiguration(); + + return binCfg != null ? binCfg.getSerializer() : null; + } + + /** * @param cls Collection class. * @return Collection type ID. */ @@ -700,6 +763,9 @@ public class BinaryContext implements Externalizable { public BinaryClassDescriptor registerPredefinedType(Class<?> cls, int id) { String typeName = typeName(cls.getName()); + if (id == 0) + id = BinaryInternalIdMapper.defaultInstance().typeId(typeName); + BinaryClassDescriptor desc = new BinaryClassDescriptor( this, cls, @@ -708,10 +774,9 @@ public class BinaryContext implements Externalizable { typeName, null, BinaryInternalIdMapper.defaultInstance(), - null, + new BinaryReflectiveSerializer(), false, - true, /* registered */ - true /* predefined */ + true /* registered */ ); predefinedTypeNames.put(typeName, id); @@ -770,6 +835,14 @@ public class BinaryContext implements Externalizable { Collection<BinarySchema> schemas = null; if (cls != null) { + if (serializer == null) { + // At this point we must decide whether to rely on Java serialization mechanics or not. + // If no serializer is provided, we examine the class and if it doesn't contain non-trivial + // serialization logic we are safe to fallback to reflective binary serialization. + if (canUseReflectiveSerializer(cls)) + serializer = new BinaryReflectiveSerializer(); + } + BinaryClassDescriptor desc = new BinaryClassDescriptor( this, cls, @@ -780,8 +853,7 @@ public class BinaryContext implements Externalizable { idMapper, serializer, true, - true, /* registered */ - false /* predefined */ + true /* registered */ ); fieldsMeta = desc.fieldsMeta(); @@ -797,6 +869,16 @@ public class BinaryContext implements Externalizable { } /** + * Check whether reflective serializer can be used for class. + * + * @param cls Class. + * @return {@code True} if reflective serializer can be used. + */ + private static boolean canUseReflectiveSerializer(Class cls) { + return BinaryUtils.isBinarylizable(cls) || !BinaryUtils.isCustomJavaSerialization(cls); + } + + /** * Create binary field. * * @param typeId Type ID. @@ -1059,6 +1141,7 @@ public class BinaryContext implements Externalizable { idMapper = other.idMapper; serializer = other.serializer; affKeyFieldName = other.affKeyFieldName; + isEnum = other.isEnum; canOverride = other.canOverride; } else if (!other.canOverride) http://git-wip-us.apache.org/repos/asf/ignite/blob/057ad5bb/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryFieldAccessor.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryFieldAccessor.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryFieldAccessor.java index 8050edd..2d69cbd 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryFieldAccessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryFieldAccessor.java @@ -105,7 +105,6 @@ public abstract class BinaryFieldAccessor { case OBJECT_ARR: case BINARY_OBJ: case BINARY: - case EXTERNALIZABLE: return new DefaultFinalClassAccessor(field, id, mode, false); default: @@ -624,7 +623,6 @@ public abstract class BinaryFieldAccessor { break; case BINARY: - case EXTERNALIZABLE: case OBJECT: writer.writeObjectField(val); @@ -825,7 +823,6 @@ public abstract class BinaryFieldAccessor { break; case BINARY: - case EXTERNALIZABLE: case OBJECT: val = reader.readObject(id); http://git-wip-us.apache.org/repos/asf/ignite/blob/057ad5bb/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java index 9e5260b..8cb4b38 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java @@ -34,7 +34,11 @@ import org.jsr166.ConcurrentHashMap8; import java.io.ByteArrayInputStream; import java.io.Externalizable; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.lang.reflect.Array; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.math.BigDecimal; import java.math.BigInteger; import java.sql.Timestamp; @@ -952,8 +956,6 @@ public class BinaryUtils { return BinaryWriteMode.BINARY_OBJ; else if (Binarylizable.class.isAssignableFrom(cls)) return BinaryWriteMode.BINARY; - else if (Externalizable.class.isAssignableFrom(cls)) - return BinaryWriteMode.EXTERNALIZABLE; else if (isSpecialCollection(cls)) return BinaryWriteMode.COL; else if (isSpecialMap(cls)) @@ -1838,6 +1840,49 @@ public class BinaryUtils { } /** + * Check if class is binarylizable. + * + * @param cls Class. + * @return {@code True} if binarylizable. + */ + public static boolean isBinarylizable(Class cls) { + for (Class c = cls; c != null && !c.equals(Object.class); c = c.getSuperclass()) { + if (Binarylizable.class.isAssignableFrom(c)) + return true; + } + + return false; + } + + /** + * Determines whether class contains custom Java serialization logic. + * + * @param cls Class. + * @return {@code true} if custom Java serialization logic exists, {@code false} otherwise. + */ + @SuppressWarnings("unchecked") + public static boolean isCustomJavaSerialization(Class cls) { + for (Class c = cls; c != null && !c.equals(Object.class); c = c.getSuperclass()) { + if (Externalizable.class.isAssignableFrom(c)) + return true; + + try { + Method writeObj = c.getDeclaredMethod("writeObject", ObjectOutputStream.class); + Method readObj = c.getDeclaredMethod("readObject", ObjectInputStream.class); + + if (!Modifier.isStatic(writeObj.getModifiers()) && !Modifier.isStatic(readObj.getModifiers()) && + writeObj.getReturnType() == void.class && readObj.getReturnType() == void.class) + return true; + } + catch (NoSuchMethodException ignored) { + // No-op. + } + } + + return false; + } + + /** * Enum type. */ private static class EnumType { http://git-wip-us.apache.org/repos/asf/ignite/blob/057ad5bb/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryWriteMode.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryWriteMode.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryWriteMode.java index 90127f4..30e0458 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryWriteMode.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryWriteMode.java @@ -151,9 +151,6 @@ public enum BinaryWriteMode { BINARY(GridBinaryMarshaller.BINARY_OBJ), /** */ - EXTERNALIZABLE(GridBinaryMarshaller.OBJ), - - /** */ OBJECT(GridBinaryMarshaller.OBJ), /** */ http://git-wip-us.apache.org/repos/asf/ignite/blob/057ad5bb/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/BinaryMetadataKey.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/BinaryMetadataKey.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/BinaryMetadataKey.java index 1f2678b..32ab2a0 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/BinaryMetadataKey.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/BinaryMetadataKey.java @@ -27,7 +27,7 @@ import org.apache.ignite.internal.util.typedef.internal.S; /** * Key for binary meta data. */ -class BinaryMetadataKey extends GridCacheUtilityKey<BinaryMetadataKey> implements Externalizable { +public class BinaryMetadataKey extends GridCacheUtilityKey<BinaryMetadataKey> implements Externalizable { /** */ private static final long serialVersionUID = 0L; http://git-wip-us.apache.org/repos/asf/ignite/blob/057ad5bb/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java index e77b85a..6aee7a9 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java @@ -206,7 +206,7 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm BinaryMarshaller pMarh0 = (BinaryMarshaller)marsh; - binaryCtx = new BinaryContext(metaHnd, ctx.config()); + binaryCtx = new BinaryContext(metaHnd, ctx.config(), ctx.log(BinaryContext.class)); IgniteUtils.invoke(BinaryMarshaller.class, pMarh0, "setBinaryContext", binaryCtx, ctx.config()); http://git-wip-us.apache.org/repos/asf/ignite/blob/057ad5bb/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetConfigurationClosure.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetConfigurationClosure.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetConfigurationClosure.java index 4ac3536..c068d59 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetConfigurationClosure.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetConfigurationClosure.java @@ -36,6 +36,7 @@ import org.apache.ignite.internal.processors.platform.memory.PlatformOutputStrea import org.apache.ignite.internal.processors.platform.utils.PlatformUtils; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.lifecycle.LifecycleBean; +import org.apache.ignite.logger.NullLogger; import org.apache.ignite.marshaller.Marshaller; import org.apache.ignite.platform.dotnet.PlatformDotNetConfiguration; import org.apache.ignite.internal.binary.BinaryMarshaller; @@ -241,7 +242,8 @@ public class PlatformDotNetConfigurationClosure extends PlatformAbstractConfigur @SuppressWarnings("deprecation") private static GridBinaryMarshaller marshaller() { try { - BinaryContext ctx = new BinaryContext(BinaryNoopMetadataHandler.instance(), new IgniteConfiguration()); + BinaryContext ctx = + new BinaryContext(BinaryNoopMetadataHandler.instance(), new IgniteConfiguration(), new NullLogger()); BinaryMarshaller marsh = new BinaryMarshaller(); http://git-wip-us.apache.org/repos/asf/ignite/blob/057ad5bb/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java index 0412b4c..28b854c 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java @@ -17,35 +17,13 @@ package org.apache.ignite.internal.processors.query; -import java.lang.reflect.AccessibleObject; -import java.lang.reflect.Field; -import java.lang.reflect.Member; -import java.lang.reflect.Method; -import java.math.BigDecimal; -import java.sql.Time; -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; -import java.util.UUID; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ExecutorService; -import javax.cache.Cache; -import javax.cache.CacheException; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteException; import org.apache.ignite.IgniteLogger; import org.apache.ignite.binary.BinaryField; +import org.apache.ignite.binary.BinaryObject; import org.apache.ignite.binary.BinaryType; +import org.apache.ignite.binary.Binarylizable; import org.apache.ignite.cache.CacheTypeMetadata; import org.apache.ignite.cache.QueryEntity; import org.apache.ignite.cache.QueryIndex; @@ -55,15 +33,16 @@ import org.apache.ignite.cache.query.SqlFieldsQuery; import org.apache.ignite.cache.query.SqlQuery; import org.apache.ignite.configuration.CacheConfiguration; import org.apache.ignite.events.CacheQueryExecutedEvent; -import org.apache.ignite.binary.BinaryObject; import org.apache.ignite.internal.GridKernalContext; import org.apache.ignite.internal.IgniteInternalFuture; +import org.apache.ignite.internal.binary.BinaryMarshaller; import org.apache.ignite.internal.processors.GridProcessorAdapter; import org.apache.ignite.internal.processors.cache.CacheEntryImpl; import org.apache.ignite.internal.processors.cache.CacheObject; import org.apache.ignite.internal.processors.cache.CacheObjectContext; import org.apache.ignite.internal.processors.cache.GridCacheContext; import org.apache.ignite.internal.processors.cache.QueryCursorImpl; +import org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl; import org.apache.ignite.internal.processors.cache.query.CacheQueryFuture; import org.apache.ignite.internal.processors.cache.query.CacheQueryType; import org.apache.ignite.internal.processors.cache.query.GridCacheTwoStepQuery; @@ -87,6 +66,31 @@ import org.apache.ignite.spi.indexing.IndexingQueryFilter; import org.jetbrains.annotations.Nullable; import org.jsr166.ConcurrentHashMap8; +import javax.cache.Cache; +import javax.cache.CacheException; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.math.BigDecimal; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; +import java.util.UUID; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; + import static org.apache.ignite.events.EventType.EVT_CACHE_QUERY_EXECUTED; import static org.apache.ignite.internal.IgniteComponentType.INDEXING; import static org.apache.ignite.internal.processors.query.GridQueryIndexType.FULLTEXT; @@ -193,6 +197,12 @@ public class GridQueryProcessor extends GridProcessorAdapter { idx.registerCache(ccfg); try { + List<Class<?>> mustDeserializeClss = null; + + boolean binaryEnabled = ctx.cacheObjects().isBinaryEnabled(ccfg); + + CacheObjectContext coCtx = binaryEnabled ? ctx.cacheObjects().contextForCache(ccfg) : null; + if (!F.isEmpty(ccfg.getQueryEntities())) { for (QueryEntity qryEntity : ccfg.getQueryEntities()) { if (F.isEmpty(qryEntity.getValueType())) @@ -202,14 +212,23 @@ public class GridQueryProcessor extends GridProcessorAdapter { // Key and value classes still can be available if they are primitive or JDK part. // We need that to set correct types for _key and _val columns. - Class<?> keyCls = U.classForName(qryEntity.getKeyType(), Object.class); + Class<?> keyCls = U.classForName(qryEntity.getKeyType(), null); Class<?> valCls = U.classForName(qryEntity.getValueType(), null); + // If local node has the classes and they are externalizable, we must use reflection properties. + boolean keyMustDeserialize = mustDeserializeBinary(keyCls); + boolean valMustDeserialize = mustDeserializeBinary(valCls); + + boolean keyOrValMustDeserialize = keyMustDeserialize || valMustDeserialize; + + if (keyCls == null) + keyCls = Object.class; + String simpleValType = valCls == null ? typeName(qryEntity.getValueType()) : typeName(valCls); desc.name(simpleValType); - if (ctx.cacheObjects().isBinaryEnabled(ccfg)) { + if (binaryEnabled && !keyOrValMustDeserialize) { // Safe to check null. if (SQL_TYPES.contains(valCls)) desc.valueClass(valCls); @@ -234,10 +253,21 @@ public class GridQueryProcessor extends GridProcessorAdapter { desc.keyClass(keyCls); } + if (binaryEnabled && keyOrValMustDeserialize) { + if (mustDeserializeClss == null) + mustDeserializeClss = new ArrayList<>(); + + if (keyMustDeserialize) + mustDeserializeClss.add(keyCls); + + if (valMustDeserialize) + mustDeserializeClss.add(valCls); + } + TypeId typeId; TypeId altTypeId = null; - if (valCls == null || ctx.cacheObjects().isBinaryEnabled(ccfg)) { + if (valCls == null || (binaryEnabled && !keyOrValMustDeserialize)) { processBinaryMeta(qryEntity, desc); typeId = new TypeId(ccfg.getName(), ctx.cacheObjects().typeId(qryEntity.getValueType())); @@ -246,7 +276,7 @@ public class GridQueryProcessor extends GridProcessorAdapter { altTypeId = new TypeId(ccfg.getName(), valCls); } else { - processClassMeta(qryEntity, desc); + processClassMeta(qryEntity, desc, coCtx); typeId = new TypeId(ccfg.getName(), valCls); altTypeId = new TypeId(ccfg.getName(), ctx.cacheObjects().typeId(qryEntity.getValueType())); @@ -276,12 +306,21 @@ public class GridQueryProcessor extends GridProcessorAdapter { // Key and value classes still can be available if they are primitive or JDK part. // We need that to set correct types for _key and _val columns. - Class<?> keyCls = U.classForName(meta.getKeyType(), Object.class); + Class<?> keyCls = U.classForName(meta.getKeyType(), null); Class<?> valCls = U.classForName(meta.getValueType(), null); + // If local node has the classes and they are externalizable, we must use reflection properties. + boolean keyMustDeserialize = mustDeserializeBinary(keyCls); + boolean valMustDeserialize = mustDeserializeBinary(valCls); + + boolean keyOrValMustDeserialize = keyMustDeserialize || valMustDeserialize; + + if (keyCls == null) + keyCls = Object.class; + desc.name(meta.getSimpleValueType()); - if (ctx.cacheObjects().isBinaryEnabled(ccfg)) { + if (binaryEnabled && !keyOrValMustDeserialize) { // Safe to check null. if (SQL_TYPES.contains(valCls)) desc.valueClass(valCls); @@ -298,10 +337,21 @@ public class GridQueryProcessor extends GridProcessorAdapter { desc.keyClass(keyCls); } + if (binaryEnabled && keyOrValMustDeserialize) { + if (mustDeserializeClss == null) + mustDeserializeClss = new ArrayList<>(); + + if (keyMustDeserialize) + mustDeserializeClss.add(keyCls); + + if (valMustDeserialize) + mustDeserializeClss.add(valCls); + } + TypeId typeId; TypeId altTypeId = null; - if (valCls == null || ctx.cacheObjects().isBinaryEnabled(ccfg)) { + if (valCls == null || (binaryEnabled && !keyOrValMustDeserialize)) { processBinaryMeta(meta, desc); typeId = new TypeId(ccfg.getName(), ctx.cacheObjects().typeId(meta.getValueType())); @@ -310,7 +360,7 @@ public class GridQueryProcessor extends GridProcessorAdapter { altTypeId = new TypeId(ccfg.getName(), valCls); } else { - processClassMeta(meta, desc); + processClassMeta(meta, desc, coCtx); typeId = new TypeId(ccfg.getName(), valCls); altTypeId = new TypeId(ccfg.getName(), ctx.cacheObjects().typeId(meta.getValueType())); @@ -327,6 +377,15 @@ public class GridQueryProcessor extends GridProcessorAdapter { } // Indexed types must be translated to CacheTypeMetadata in CacheConfiguration. + + if (mustDeserializeClss != null) { + U.quietAndWarn(log, "Some classes in query configuration cannot be written in binary format " + + "because they either implement Externalizable interface or have writeObject/readObject methods. " + + "Instances of these classes will be deserialized in order to build indexes. Please ensure that " + + "all nodes have these classes in classpath. To enable binary serialization either implement " + + Binarylizable.class.getSimpleName() + " interface or set explicit serializer using " + + "BinaryTypeConfiguration.setSerializer() method: " + mustDeserializeClss); + } } catch (IgniteCheckedException | RuntimeException e) { idx.unregisterCache(ccfg); @@ -336,6 +395,22 @@ public class GridQueryProcessor extends GridProcessorAdapter { } /** + * Check whether type still must be deserialized when binary marshaller is set. + * + * @param cls Class. + * @return {@code True} if will be deserialized. + */ + private boolean mustDeserializeBinary(Class cls) { + if (cls != null && ctx.config().getMarshaller() instanceof BinaryMarshaller) { + CacheObjectBinaryProcessorImpl proc0 = (CacheObjectBinaryProcessorImpl)ctx.cacheObjects(); + + return proc0.binaryContext().mustDeserialize(cls); + } + else + return false; + } + + /** * @param ccfg Cache configuration. * @param desc Type descriptor. * @throws IgniteCheckedException If failed. @@ -1185,9 +1260,10 @@ public class GridQueryProcessor extends GridProcessorAdapter { * * @param meta Type metadata. * @param d Type descriptor. + * @param coCtx Cache object context. * @throws IgniteCheckedException If failed. */ - private void processClassMeta(CacheTypeMetadata meta, TypeDescriptor d) + private void processClassMeta(CacheTypeMetadata meta, TypeDescriptor d, CacheObjectContext coCtx) throws IgniteCheckedException { Map<String,String> aliases = meta.getAliases(); @@ -1201,13 +1277,13 @@ public class GridQueryProcessor extends GridProcessorAdapter { assert valCls != null; for (Map.Entry<String, Class<?>> entry : meta.getAscendingFields().entrySet()) - addToIndex(d, keyCls, valCls, entry.getKey(), entry.getValue(), 0, IndexType.ASC, null, aliases); + addToIndex(d, keyCls, valCls, entry.getKey(), entry.getValue(), 0, IndexType.ASC, null, aliases, coCtx); for (Map.Entry<String, Class<?>> entry : meta.getDescendingFields().entrySet()) - addToIndex(d, keyCls, valCls, entry.getKey(), entry.getValue(), 0, IndexType.DESC, null, aliases); + addToIndex(d, keyCls, valCls, entry.getKey(), entry.getValue(), 0, IndexType.DESC, null, aliases, coCtx); for (String txtField : meta.getTextFields()) - addToIndex(d, keyCls, valCls, txtField, String.class, 0, IndexType.TEXT, null, aliases); + addToIndex(d, keyCls, valCls, txtField, String.class, 0, IndexType.TEXT, null, aliases, coCtx); Map<String, LinkedHashMap<String, IgniteBiTuple<Class<?>, Boolean>>> grps = meta.getGroups(); @@ -1226,7 +1302,7 @@ public class GridQueryProcessor extends GridProcessorAdapter { descending = false; addToIndex(d, keyCls, valCls, idxField.getKey(), idxField.getValue().get1(), order, - descending ? IndexType.DESC : IndexType.ASC, idxName, aliases); + descending ? IndexType.DESC : IndexType.ASC, idxName, aliases, coCtx); order++; } @@ -1239,7 +1315,8 @@ public class GridQueryProcessor extends GridProcessorAdapter { valCls, entry.getKey(), entry.getValue(), - aliases); + aliases, + coCtx); d.addProperty(prop, false); } @@ -1266,7 +1343,8 @@ public class GridQueryProcessor extends GridProcessorAdapter { int idxOrder, IndexType idxType, String idxName, - Map<String,String> aliases + Map<String,String> aliases, + CacheObjectContext coCtx ) throws IgniteCheckedException { String propName; Class<?> propCls; @@ -1281,7 +1359,8 @@ public class GridQueryProcessor extends GridProcessorAdapter { valCls, pathStr, resType, - aliases); + aliases, + coCtx); d.addProperty(prop, false); @@ -1410,7 +1489,11 @@ public class GridQueryProcessor extends GridProcessorAdapter { * @param d Type descriptor. * @throws IgniteCheckedException If failed. */ - private void processClassMeta(QueryEntity qryEntity, TypeDescriptor d) throws IgniteCheckedException { + private void processClassMeta( + QueryEntity qryEntity, + TypeDescriptor d, + CacheObjectContext coCtx + ) throws IgniteCheckedException { Map<String,String> aliases = qryEntity.getAliases(); if (aliases == null) @@ -1422,7 +1505,8 @@ public class GridQueryProcessor extends GridProcessorAdapter { d.valueClass(), entry.getKey(), U.classForName(entry.getValue(), Object.class), - aliases); + aliases, + coCtx); d.addProperty(prop, false); @@ -1524,16 +1608,17 @@ public class GridQueryProcessor extends GridProcessorAdapter { * @throws IgniteCheckedException If failed. */ private static ClassProperty buildClassProperty(Class<?> keyCls, Class<?> valCls, String pathStr, Class<?> resType, - Map<String,String> aliases) throws IgniteCheckedException { + Map<String,String> aliases, CacheObjectContext coCtx) throws IgniteCheckedException { ClassProperty res = buildClassProperty( true, keyCls, pathStr, resType, - aliases); + aliases, + coCtx); if (res == null) // We check key before value consistently with BinaryProperty. - res = buildClassProperty(false, valCls, pathStr, resType, aliases); + res = buildClassProperty(false, valCls, pathStr, resType, aliases, coCtx); if (res == null) throw new IgniteCheckedException("Failed to initialize property '" + pathStr + "' for " + @@ -1552,7 +1637,7 @@ public class GridQueryProcessor extends GridProcessorAdapter { * @return Property instance corresponding to the given path. */ static ClassProperty buildClassProperty(boolean key, Class<?> cls, String pathStr, Class<?> resType, - Map<String,String> aliases) { + Map<String,String> aliases, CacheObjectContext coCtx) { String[] path = pathStr.split("\\."); ClassProperty res = null; @@ -1576,7 +1661,7 @@ public class GridQueryProcessor extends GridProcessorAdapter { ClassProperty tmp = null; try { - tmp = new ClassProperty(cls.getMethod(bld.toString()), key, alias); + tmp = new ClassProperty(cls.getMethod(bld.toString()), key, alias, coCtx); } catch (NoSuchMethodException ignore) { // No-op. @@ -1584,7 +1669,7 @@ public class GridQueryProcessor extends GridProcessorAdapter { if (tmp == null) { try { - tmp = new ClassProperty(cls.getDeclaredField(prop), key, alias); + tmp = new ClassProperty(cls.getDeclaredField(prop), key, alias, coCtx); } catch (NoSuchFieldException ignored) { // No-op. @@ -1593,7 +1678,7 @@ public class GridQueryProcessor extends GridProcessorAdapter { if (tmp == null) { try { - tmp = new ClassProperty(cls.getMethod(prop), key, alias); + tmp = new ClassProperty(cls.getMethod(prop), key, alias, coCtx); } catch (NoSuchMethodException ignored) { // No-op. @@ -1733,12 +1818,15 @@ public class GridQueryProcessor extends GridProcessorAdapter { /** */ private boolean key; + /** */ + private CacheObjectContext coCtx; + /** * Constructor. * * @param member Element. */ - ClassProperty(Member member, boolean key, String name) { + ClassProperty(Member member, boolean key, String name, @Nullable CacheObjectContext coCtx) { this.member = member; this.key = key; @@ -1749,11 +1837,13 @@ public class GridQueryProcessor extends GridProcessorAdapter { ((AccessibleObject) member).setAccessible(true); field = member instanceof Field; + + this.coCtx = coCtx; } /** {@inheritDoc} */ @Override public Object value(Object key, Object val) throws IgniteCheckedException { - Object x = this.key ? key : val; + Object x = unwrap(this.key ? key : val); if (parent != null) x = parent.value(key, val); @@ -1778,6 +1868,16 @@ public class GridQueryProcessor extends GridProcessorAdapter { } } + /** + * Unwraps cache object, if needed. + * + * @param o Object to unwrap. + * @return Unwrapped object. + */ + private Object unwrap(Object o) { + return coCtx == null ? o : o instanceof CacheObject ? ((CacheObject)o).value(coCtx, false) : o; + } + /** {@inheritDoc} */ @Override public String name() { return name; http://git-wip-us.apache.org/repos/asf/ignite/blob/057ad5bb/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryFieldsAbstractSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryFieldsAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryFieldsAbstractSelfTest.java index 943c5aa..fd095e9 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryFieldsAbstractSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryFieldsAbstractSelfTest.java @@ -24,6 +24,7 @@ import org.apache.ignite.configuration.BinaryConfiguration; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.internal.util.IgniteUtils; import org.apache.ignite.internal.util.typedef.internal.U; +import org.apache.ignite.logger.NullLogger; import org.apache.ignite.marshaller.MarshallerContextTestImpl; import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; @@ -47,7 +48,8 @@ public abstract class BinaryFieldsAbstractSelfTest extends GridCommonAbstractTes * @throws Exception If failed. */ protected BinaryMarshaller createMarshaller() throws Exception { - BinaryContext ctx = new BinaryContext(BinaryCachingMetadataHandler.create(), new IgniteConfiguration()); + BinaryContext ctx = new BinaryContext(BinaryCachingMetadataHandler.create(), new IgniteConfiguration(), + new NullLogger()); BinaryMarshaller marsh = new BinaryMarshaller(); http://git-wip-us.apache.org/repos/asf/ignite/blob/057ad5bb/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryFooterOffsetsAbstractSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryFooterOffsetsAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryFooterOffsetsAbstractSelfTest.java index 0e3749c..265d283 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryFooterOffsetsAbstractSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryFooterOffsetsAbstractSelfTest.java @@ -23,6 +23,7 @@ import org.apache.ignite.binary.BinaryTypeConfiguration; import org.apache.ignite.configuration.BinaryConfiguration; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.internal.util.IgniteUtils; +import org.apache.ignite.logger.NullLogger; import org.apache.ignite.marshaller.MarshallerContextTestImpl; import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; @@ -46,7 +47,7 @@ public abstract class BinaryFooterOffsetsAbstractSelfTest extends GridCommonAbst @Override protected void beforeTest() throws Exception { super.beforeTest(); - ctx = new BinaryContext(BinaryCachingMetadataHandler.create(), new IgniteConfiguration()); + ctx = new BinaryContext(BinaryCachingMetadataHandler.create(), new IgniteConfiguration(), new NullLogger()); marsh = new BinaryMarshaller(); http://git-wip-us.apache.org/repos/asf/ignite/blob/057ad5bb/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java index b83bbad..fcd511b 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java @@ -76,6 +76,7 @@ import org.apache.ignite.internal.util.lang.GridMapEntry; import org.apache.ignite.internal.util.typedef.F; import org.apache.ignite.internal.util.typedef.internal.S; import org.apache.ignite.internal.util.typedef.internal.U; +import org.apache.ignite.logger.NullLogger; import org.apache.ignite.marshaller.MarshallerContextTestImpl; import org.apache.ignite.testframework.GridTestUtils; import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; @@ -435,23 +436,6 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest { /** * @throws Exception If failed. */ - public void testExternalizableHashCode() throws Exception { - SimpleExternalizable sim1 = new SimpleExternalizable("Simple"); - SimpleExternalizable sim2 = new SimpleExternalizable("Simple"); - - BinaryMarshaller marsh = binaryMarshaller(); - - BinaryObjectImpl sim1Binary = marshal(sim1, marsh); - BinaryObjectImpl sim2Binary = marshal(sim2, marsh); - - assertEquals(sim1.hashCode(), sim2.hashCode()); - assertEquals(sim1.hashCode(), sim1Binary.hashCode()); - assertEquals(sim2.hashCode(), sim2Binary.hashCode()); - } - - /** - * @throws Exception If failed. - */ public void testExternalizableInEnclosing() throws Exception { SimpleEnclosingObject obj = new SimpleEnclosingObject(); obj.simpl = new SimpleExternalizable("field"); @@ -797,6 +781,13 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest { private String name; /** + * {@link Externalizable} support. + */ + public TestQueue() { + // No-op. + } + + /** * @param name Name. */ public TestQueue(String name) { @@ -2690,7 +2681,7 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest { iCfg.setBinaryConfiguration(bCfg); - BinaryContext ctx = new BinaryContext(BinaryCachingMetadataHandler.create(), iCfg); + BinaryContext ctx = new BinaryContext(BinaryCachingMetadataHandler.create(), iCfg, new NullLogger()); BinaryMarshaller marsh = new BinaryMarshaller(); @@ -4067,6 +4058,13 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest { private String field; /** + * {@link Externalizable} support. + */ + public SimpleExternalizable() { + // No-op. + } + + /** * @param field Field. */ public SimpleExternalizable(String field) { http://git-wip-us.apache.org/repos/asf/ignite/blob/057ad5bb/modules/core/src/test/java/org/apache/ignite/internal/binary/GridBinaryMarshallerCtxDisabledSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/binary/GridBinaryMarshallerCtxDisabledSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/binary/GridBinaryMarshallerCtxDisabledSelfTest.java index e433ec0..2b0051e 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/binary/GridBinaryMarshallerCtxDisabledSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/binary/GridBinaryMarshallerCtxDisabledSelfTest.java @@ -25,6 +25,7 @@ import org.apache.ignite.binary.Binarylizable; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.internal.MarshallerContextAdapter; import org.apache.ignite.internal.util.IgniteUtils; +import org.apache.ignite.logger.NullLogger; import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; import java.io.Externalizable; @@ -46,7 +47,7 @@ public class GridBinaryMarshallerCtxDisabledSelfTest extends GridCommonAbstractT IgniteConfiguration cfg = new IgniteConfiguration(); - BinaryContext context = new BinaryContext(BinaryCachingMetadataHandler.create(), cfg); + BinaryContext context = new BinaryContext(BinaryCachingMetadataHandler.create(), cfg, new NullLogger()); IgniteUtils.invoke(BinaryMarshaller.class, marsh, "setBinaryContext", context, cfg); http://git-wip-us.apache.org/repos/asf/ignite/blob/057ad5bb/modules/core/src/test/java/org/apache/ignite/internal/binary/GridBinaryWildcardsSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/binary/GridBinaryWildcardsSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/binary/GridBinaryWildcardsSelfTest.java index 2887afa..ae0cfa0 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/binary/GridBinaryWildcardsSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/binary/GridBinaryWildcardsSelfTest.java @@ -26,6 +26,7 @@ import org.apache.ignite.configuration.BinaryConfiguration; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.internal.util.IgniteUtils; import org.apache.ignite.internal.util.typedef.internal.U; +import org.apache.ignite.logger.NullLogger; import org.apache.ignite.marshaller.MarshallerContextTestImpl; import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; @@ -451,7 +452,7 @@ public class GridBinaryWildcardsSelfTest extends GridCommonAbstractTest { iCfg.setBinaryConfiguration(bCfg); - BinaryContext ctx = new BinaryContext(BinaryNoopMetadataHandler.instance(), iCfg); + BinaryContext ctx = new BinaryContext(BinaryNoopMetadataHandler.instance(), iCfg, new NullLogger()); BinaryMarshaller marsh = new BinaryMarshaller(); http://git-wip-us.apache.org/repos/asf/ignite/blob/057ad5bb/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheOnCopyFlagAbstractSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheOnCopyFlagAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheOnCopyFlagAbstractSelfTest.java index d29440e..6f73e0f 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheOnCopyFlagAbstractSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheOnCopyFlagAbstractSelfTest.java @@ -21,6 +21,7 @@ import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; +import java.io.Serializable; import java.util.HashMap; import java.util.Map; import javax.cache.Cache; @@ -414,7 +415,10 @@ public abstract class GridCacheOnCopyFlagAbstractSelfTest extends GridCacheAbstr /** * */ - public static class TestKey implements Externalizable { + public static class TestKey implements Serializable { + /** */ + private static final long serialVersionUID = 0L; + /** */ private int key; @@ -471,18 +475,6 @@ public abstract class GridCacheOnCopyFlagAbstractSelfTest extends GridCacheAbstr } /** {@inheritDoc} */ - @Override public void writeExternal(ObjectOutput out) throws IOException { - out.writeInt(key); - out.writeInt(field); - } - - /** {@inheritDoc} */ - @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - key = in.readInt(); - field = in.readInt(); - } - - /** {@inheritDoc} */ @Override public String toString() { return "TestKey [field=" + field + ", key=" + key + ']'; } @@ -491,7 +483,10 @@ public abstract class GridCacheOnCopyFlagAbstractSelfTest extends GridCacheAbstr /** * */ - public static class TestValue implements Externalizable { + public static class TestValue implements Serializable { + /** */ + private static final long serialVersionUID = 0L; + /** */ private int val; @@ -541,16 +536,6 @@ public abstract class GridCacheOnCopyFlagAbstractSelfTest extends GridCacheAbstr @Override public int hashCode() { return val; } - - /** {@inheritDoc} */ - @Override public void writeExternal(ObjectOutput out) throws IOException { - out.writeInt(val); - } - - /** {@inheritDoc} */ - @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - val = in.readInt(); - } } /** http://git-wip-us.apache.org/repos/asf/ignite/blob/057ad5bb/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/binary/GridBinaryCacheEntryMemorySizeSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/binary/GridBinaryCacheEntryMemorySizeSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/binary/GridBinaryCacheEntryMemorySizeSelfTest.java index d1f7826..c7a6a55 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/binary/GridBinaryCacheEntryMemorySizeSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/binary/GridBinaryCacheEntryMemorySizeSelfTest.java @@ -23,6 +23,7 @@ import org.apache.ignite.internal.binary.BinaryNoopMetadataHandler; import org.apache.ignite.internal.binary.BinaryContext; import org.apache.ignite.internal.processors.cache.GridCacheEntryMemorySizeSelfTest; import org.apache.ignite.internal.util.IgniteUtils; +import org.apache.ignite.logger.NullLogger; import org.apache.ignite.marshaller.Marshaller; import org.apache.ignite.marshaller.MarshallerContextTestImpl; import org.apache.ignite.internal.binary.BinaryMarshaller; @@ -39,7 +40,7 @@ public class GridBinaryCacheEntryMemorySizeSelfTest extends GridCacheEntryMemory IgniteConfiguration iCfg = new IgniteConfiguration(); - BinaryContext pCtx = new BinaryContext(BinaryNoopMetadataHandler.instance(), iCfg); + BinaryContext pCtx = new BinaryContext(BinaryNoopMetadataHandler.instance(), iCfg, new NullLogger()); IgniteUtils.invoke(BinaryMarshaller.class, marsh, "setBinaryContext", pCtx, iCfg); http://git-wip-us.apache.org/repos/asf/ignite/blob/057ad5bb/modules/core/src/test/java/org/apache/ignite/session/GridSessionCheckpointSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/session/GridSessionCheckpointSelfTest.java b/modules/core/src/test/java/org/apache/ignite/session/GridSessionCheckpointSelfTest.java index 3038cba..a3df301 100644 --- a/modules/core/src/test/java/org/apache/ignite/session/GridSessionCheckpointSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/session/GridSessionCheckpointSelfTest.java @@ -23,6 +23,7 @@ import org.apache.ignite.internal.binary.BinaryCachingMetadataHandler; import org.apache.ignite.internal.binary.BinaryMarshaller; import org.apache.ignite.internal.binary.BinaryContext; import org.apache.ignite.internal.util.IgniteUtils; +import org.apache.ignite.logger.NullLogger; import org.apache.ignite.marshaller.Marshaller; import org.apache.ignite.marshaller.MarshallerContextTestImpl; import org.apache.ignite.spi.checkpoint.cache.CacheCheckpointSpi; @@ -96,7 +97,7 @@ public class GridSessionCheckpointSelfTest extends GridSessionCheckpointAbstract cfg.setCheckpointSpi(spi); if (cfg.getMarshaller() instanceof BinaryMarshaller) { - BinaryContext ctx = new BinaryContext(BinaryCachingMetadataHandler.create(), cfg); + BinaryContext ctx = new BinaryContext(BinaryCachingMetadataHandler.create(), cfg, new NullLogger()); Marshaller marsh = cfg.getMarshaller(); http://git-wip-us.apache.org/repos/asf/ignite/blob/057ad5bb/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteMock.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteMock.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteMock.java index 2367688..c49c730 100644 --- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteMock.java +++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteMock.java @@ -55,6 +55,7 @@ import org.apache.ignite.internal.binary.BinaryContext; import org.apache.ignite.internal.binary.builder.BinaryObjectBuilderImpl; import org.apache.ignite.internal.processors.cacheobject.NoOpBinary; import org.apache.ignite.lang.IgniteProductVersion; +import org.apache.ignite.logger.NullLogger; import org.apache.ignite.marshaller.Marshaller; import org.apache.ignite.plugin.IgnitePlugin; import org.apache.ignite.plugin.PluginNotFoundException; @@ -295,7 +296,7 @@ public class IgniteMock implements Ignite { if (ctx == null) { /** {@inheritDoc} */ - ctx = new BinaryContext(BinaryCachingMetadataHandler.create(), configuration()) { + ctx = new BinaryContext(BinaryCachingMetadataHandler.create(), configuration(), new NullLogger()) { @Override public int typeId(String typeName) { return typeName.hashCode(); } http://git-wip-us.apache.org/repos/asf/ignite/blob/057ad5bb/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteTestResources.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteTestResources.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteTestResources.java index 4e3f326..13d5fbd 100644 --- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteTestResources.java +++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteTestResources.java @@ -33,6 +33,7 @@ import org.apache.ignite.internal.binary.BinaryContext; import org.apache.ignite.internal.processors.resource.GridResourceProcessor; import org.apache.ignite.internal.util.IgniteUtils; import org.apache.ignite.internal.util.typedef.internal.U; +import org.apache.ignite.logger.NullLogger; import org.apache.ignite.marshaller.Marshaller; import org.apache.ignite.marshaller.MarshallerContextTestImpl; import org.apache.ignite.marshaller.optimized.OptimizedMarshaller; @@ -264,7 +265,8 @@ public class IgniteTestResources { marsh.setContext(new MarshallerContextTestImpl()); if (marsh instanceof BinaryMarshaller) { - BinaryContext ctx = new BinaryContext(BinaryCachingMetadataHandler.create(), new IgniteConfiguration()); + BinaryContext ctx = + new BinaryContext(BinaryCachingMetadataHandler.create(), new IgniteConfiguration(), new NullLogger()); IgniteUtils.invoke(BinaryMarshaller.class, marsh, "setBinaryContext", ctx, new IgniteConfiguration()); } http://git-wip-us.apache.org/repos/asf/ignite/blob/057ad5bb/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/BinarySerializationQuerySelfTest.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/BinarySerializationQuerySelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/BinarySerializationQuerySelfTest.java new file mode 100644 index 0000000..1eba7d1 --- /dev/null +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/BinarySerializationQuerySelfTest.java @@ -0,0 +1,416 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.cache; + +import org.apache.ignite.Ignite; +import org.apache.ignite.IgniteCache; +import org.apache.ignite.Ignition; +import org.apache.ignite.binary.BinaryObjectException; +import org.apache.ignite.binary.BinaryReader; +import org.apache.ignite.binary.BinaryReflectiveSerializer; +import org.apache.ignite.binary.BinaryTypeConfiguration; +import org.apache.ignite.binary.BinaryWriter; +import org.apache.ignite.binary.Binarylizable; +import org.apache.ignite.cache.CacheAtomicityMode; +import org.apache.ignite.cache.CacheMode; +import org.apache.ignite.cache.CacheRebalanceMode; +import org.apache.ignite.cache.CacheTypeMetadata; +import org.apache.ignite.cache.CacheWriteSynchronizationMode; +import org.apache.ignite.cache.query.QueryCursor; +import org.apache.ignite.cache.query.SqlFieldsQuery; +import org.apache.ignite.cache.query.SqlQuery; +import org.apache.ignite.configuration.BinaryConfiguration; +import org.apache.ignite.configuration.CacheConfiguration; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.internal.binary.BinaryMarshaller; +import org.apache.ignite.internal.util.typedef.G; +import org.apache.ignite.internal.util.typedef.internal.U; +import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi; +import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; + +import javax.cache.Cache; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectInputStream; +import java.io.ObjectOutput; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * Test for query with BinaryMarshaller and different serialization modes. + */ +public class BinarySerializationQuerySelfTest extends GridCommonAbstractTest { + /** Ignite instance. */ + private Ignite ignite; + + /** Cache. */ + private IgniteCache<Integer, Object> cache; + + /** {@inheritDoc} */ + @Override protected void beforeTest() throws Exception { + IgniteConfiguration cfg = new IgniteConfiguration(); + + cfg.setLocalHost("127.0.0.1"); + + TcpDiscoverySpi discoSpi = new TcpDiscoverySpi(); + discoSpi.setIpFinder(new TcpDiscoveryVmIpFinder(true)); + cfg.setDiscoverySpi(discoSpi); + + cfg.setMarshaller(new BinaryMarshaller()); + + if (useReflectiveSerializer()) { + BinaryTypeConfiguration binTypCfg1 = new BinaryTypeConfiguration(EntityPlain.class.getName()); + BinaryTypeConfiguration binTypCfg2 = new BinaryTypeConfiguration(EntitySerializable.class.getName()); + BinaryTypeConfiguration binTypCfg3 = new BinaryTypeConfiguration(EntityExternalizable.class.getName()); + BinaryTypeConfiguration binTypCfg4 = new BinaryTypeConfiguration(EntityBinarylizable.class.getName()); + BinaryTypeConfiguration binTypCfg5 = new BinaryTypeConfiguration(EntityWriteReadObject.class.getName()); + + binTypCfg1.setSerializer(new BinaryReflectiveSerializer()); + binTypCfg2.setSerializer(new BinaryReflectiveSerializer()); + binTypCfg3.setSerializer(new BinaryReflectiveSerializer()); + binTypCfg4.setSerializer(new BinaryReflectiveSerializer()); + binTypCfg5.setSerializer(new BinaryReflectiveSerializer()); + + List<BinaryTypeConfiguration> binTypCfgs = new ArrayList<>(); + + binTypCfgs.add(binTypCfg1); + binTypCfgs.add(binTypCfg2); + binTypCfgs.add(binTypCfg3); + binTypCfgs.add(binTypCfg4); + binTypCfgs.add(binTypCfg5); + + BinaryConfiguration binCfg = new BinaryConfiguration(); + + binCfg.setTypeConfigurations(binTypCfgs); + + cfg.setBinaryConfiguration(binCfg); + } + + CacheConfiguration cacheCfg = new CacheConfiguration(); + + cacheCfg.setName(null); + cacheCfg.setCacheMode(CacheMode.PARTITIONED); + cacheCfg.setAtomicityMode(CacheAtomicityMode.ATOMIC); + cacheCfg.setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC); + cacheCfg.setRebalanceMode(CacheRebalanceMode.SYNC); + + List<CacheTypeMetadata> metas = new ArrayList<>(); + + metas.add(metaForClass(EntityPlain.class)); + metas.add(metaForClass(EntitySerializable.class)); + metas.add(metaForClass(EntityExternalizable.class)); + metas.add(metaForClass(EntityBinarylizable.class)); + metas.add(metaForClass(EntityWriteReadObject.class)); + + cacheCfg.setTypeMetadata(metas); + + cfg.setCacheConfiguration(cacheCfg); + + ignite = Ignition.start(cfg); + + cache = ignite.cache(null); + } + + /** + * Create type metadata for class. + * + * @param cls Class. + * @return Type metadata. + */ + private static CacheTypeMetadata metaForClass(Class cls) { + CacheTypeMetadata meta = new CacheTypeMetadata(); + + meta.setKeyType(Integer.class); + meta.setValueType(cls); + meta.setAscendingFields(Collections.<String, Class<?>>singletonMap("val", Integer.class)); + + return meta; + } + + /** {@inheritDoc} */ + @Override protected void afterTest() throws Exception { + G.stopAll(true); + + ignite = null; + cache = null; + } + + /** + * Test plain type. + * + * @throws Exception If failed. + */ + public void testPlain() throws Exception { + check(EntityPlain.class); + } + + /** + * Test Serializable type. + * + * @throws Exception If failed. + */ + public void testSerializable() throws Exception { + check(EntitySerializable.class); + } + + /** + * Test Externalizable type. + * + * @throws Exception If failed. + */ + public void testExternalizable() throws Exception { + check(EntityExternalizable.class); + } + + /** + * Test Binarylizable type. + * + * @throws Exception If failed. + */ + public void testBinarylizable() throws Exception { + check(EntityBinarylizable.class); + } + + /** + * Test type with readObject/writeObject methods. + * + * @throws Exception If failed. + */ + public void testWriteReadObject() throws Exception { + check(EntityWriteReadObject.class); + } + + /** + * Internal check routine. + * + * @param cls Entity class. + * @throws Exception If failed. + */ + @SuppressWarnings("unchecked") + private void check(Class cls) throws Exception { + cache.put(1, createInstance(cls, 10)); + cache.put(2, createInstance(cls, 20)); + cache.put(3, createInstance(cls, 30)); + + Iterator iter = cache.query(new SqlQuery(cls, "val=20")).iterator(); + + assert iter.hasNext(); + + Cache.Entry res = (Cache.Entry)iter.next(); + + assertEquals(2, res.getKey()); + assertEquals(20, U.field(res.getValue(), "val")); + + assert !iter.hasNext(); + + iter = cache.query( + new SqlFieldsQuery("SELECT p.val FROM " + cls.getSimpleName() + " p WHERE p.val=20")).iterator(); + + assert iter.hasNext(); + + List<Object> fieldsRes = (List<Object>)iter.next(); + + assertEquals(20, fieldsRes.get(0)); + + assert !iter.hasNext(); + } + + /** + * Create object instance. + * + * @param cls Class. + * @param val Value. + * @return Instance. + */ + private static Object createInstance(Class cls, int val) { + if (cls.equals(EntityPlain.class)) + return new EntityPlain(val); + else if (cls.equals(EntitySerializable.class)) + return new EntitySerializable(val); + else if (cls.equals(EntityExternalizable.class)) + return new EntityExternalizable(val); + else if (cls.equals(EntityBinarylizable.class)) + return new EntityBinarylizable(val); + else + return new EntityWriteReadObject(val); + } + + /** + * @return Whether reflective serializer should be used. + */ + protected boolean useReflectiveSerializer() { + return false; + } + + /** + * Plain entry. + */ + private static class EntityPlain { + /** Value. */ + public int val; + + /** + * Default constructor. + */ + public EntityPlain() { + // No-op. + } + + /** + * Constructor. + * + * @param val Value. + */ + public EntityPlain(int val) { + this.val = val; + } + } + + /** + * Serializable entity. + */ + private static class EntitySerializable implements Serializable { + /** Value. */ + public int val; + + /** + * Default constructor. + */ + public EntitySerializable() { + // No-op. + } + + /** + * Constructor. + * + * @param val Value. + */ + public EntitySerializable(int val) { + this.val = val; + } + } + + /** + * Serializable entity. + */ + private static class EntityExternalizable implements Externalizable { + /** Value. */ + public int val; + + /** + * Default constructor. + */ + public EntityExternalizable() { + // No-op. + } + + /** + * Constructor. + * + * @param val Value. + */ + public EntityExternalizable(int val) { + this.val = val; + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeInt(val); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + val = in.readInt(); + } + } + + /** + * Serializable entity. + */ + private static class EntityBinarylizable implements Binarylizable { + /** Value. */ + public int val; + + /** + * Default constructor. + */ + public EntityBinarylizable() { + // No-op. + } + + /** + * Constructor. + * + * @param val Value. + */ + public EntityBinarylizable(int val) { + this.val = val; + } + + /** {@inheritDoc} */ + @Override public void writeBinary(BinaryWriter writer) throws BinaryObjectException { + writer.writeInt("val", val); + } + + /** {@inheritDoc} */ + @Override public void readBinary(BinaryReader reader) throws BinaryObjectException { + val = reader.readInt("val"); + } + } + + /** + * Serializable entity. + */ + private static class EntityWriteReadObject implements Serializable { + /** Value. */ + public int val; + + /** + * Default constructor. + */ + public EntityWriteReadObject() { + // No-op. + } + + /** + * Constructor. + * + * @param val Value. + */ + public EntityWriteReadObject(int val) { + this.val = val; + } + + /** {@inheritDoc} */ + private void writeObject(ObjectOutputStream s) throws IOException{ + s.writeInt(val); + } + + /** {@inheritDoc} */ + private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { + val = s.readInt(); + } + } +}