You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2016/12/06 08:40:21 UTC

[24/50] ignite git commit: IGNITE-4026: Fixed BinaryObjectBuilder.build() can fail if one of the fields is Externalizable, enum from binary object. This closes #1281. This closes #1289.

IGNITE-4026: Fixed BinaryObjectBuilder.build() can fail if one of the fields is Externalizable, enum from binary object. This closes #1281. This closes #1289.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/0b7c62d2
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/0b7c62d2
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/0b7c62d2

Branch: refs/heads/ignite-comm-balance-master
Commit: 0b7c62d2939854223653d832a616ddb61211bf22
Parents: d1cc292
Author: dkarachentsev <dk...@gridgain.com>
Authored: Mon Nov 28 11:30:14 2016 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Mon Nov 28 11:30:14 2016 +0300

----------------------------------------------------------------------
 .../internal/binary/GridBinaryMarshaller.java   |   2 +-
 .../binary/builder/BinaryBuilderReader.java     |  11 ++
 .../binary/builder/BinaryBuilderSerializer.java |   4 +
 .../binary/builder/BinaryObjectBuilderImpl.java |  10 ++
 .../BinaryObjectBuilderAdditionalSelfTest.java  | 157 ++++++++++++++++++-
 5 files changed, 181 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/0b7c62d2/modules/core/src/main/java/org/apache/ignite/internal/binary/GridBinaryMarshaller.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/GridBinaryMarshaller.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/GridBinaryMarshaller.java
index ad63521..624fa33 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/GridBinaryMarshaller.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/GridBinaryMarshaller.java
@@ -43,7 +43,7 @@ public class GridBinaryMarshaller {
     private static final ThreadLocal<BinaryContext> BINARY_CTX = new ThreadLocal<>();
 
     /** */
-    static final byte OPTM_MARSH = -2;
+    public static final byte OPTM_MARSH = -2;
 
     /** */
     public static final byte BYTE = 1;

http://git-wip-us.apache.org/repos/asf/ignite/blob/0b7c62d2/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderReader.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderReader.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderReader.java
index 347fb2b..baaabd6 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderReader.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderReader.java
@@ -33,6 +33,7 @@ import java.sql.Timestamp;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
+import org.apache.ignite.internal.util.typedef.internal.U;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 
@@ -757,6 +758,16 @@ public class BinaryBuilderReader implements BinaryPositionReadable {
                 return new BinaryPlainBinaryObject(binaryObj);
             }
 
+            case GridBinaryMarshaller.OPTM_MARSH: {
+                final BinaryHeapInputStream bin = BinaryHeapInputStream.create(arr, pos);
+
+                final Object obj = BinaryUtils.doReadOptimized(bin, ctx, U.resolveClassLoader(ctx.configuration()));
+
+                pos = bin.position();
+
+                return obj;
+            }
+
             default:
                 throw new BinaryObjectException("Invalid flag value: " + type);
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/0b7c62d2/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderSerializer.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderSerializer.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderSerializer.java
index b296437..6974176 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderSerializer.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderSerializer.java
@@ -116,8 +116,12 @@ class BinaryBuilderSerializer {
             String typeName = writer.context().userTypeName(clsName);
 
             BinaryMetadata meta = new BinaryMetadata(typeId, typeName, null, null, null, true);
+
             writer.context().updateMetadata(typeId, meta);
 
+            // Need register class for marshaller to be able to deserialize enum value.
+            writer.context().descriptorForClass(val.getClass(), false);
+
             writer.writeByte(GridBinaryMarshaller.ENUM);
             writer.writeInt(typeId);
             writer.writeInt(((Enum)val).ordinal());

http://git-wip-us.apache.org/repos/asf/ignite/blob/0b7c62d2/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
index ddd2423..a847d04 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
@@ -22,6 +22,7 @@ import org.apache.ignite.binary.BinaryObject;
 import org.apache.ignite.binary.BinaryObjectBuilder;
 import org.apache.ignite.binary.BinaryObjectException;
 import org.apache.ignite.binary.BinaryType;
+import org.apache.ignite.internal.binary.BinaryEnumObjectImpl;
 import org.apache.ignite.internal.binary.BinaryMetadata;
 import org.apache.ignite.internal.binary.BinaryObjectImpl;
 import org.apache.ignite.internal.binary.BinaryWriterExImpl;
@@ -391,6 +392,15 @@ public class BinaryObjectBuilderImpl implements BinaryObjectBuilder {
             if (((BinaryValueWithType)newVal).value() == null)
                 nullFieldVal = true;
         }
+        // Detect Enum and Enum array type.
+        else if (newVal instanceof BinaryEnumObjectImpl)
+            newFldTypeId = GridBinaryMarshaller.ENUM;
+        else if (newVal.getClass().isArray() && newVal.getClass().getComponentType() == BinaryObject.class) {
+            BinaryObject[] arr = (BinaryObject[])newVal;
+
+            newFldTypeId = arr.length > 0 && arr[0] instanceof BinaryEnumObjectImpl ?
+                GridBinaryMarshaller.ENUM_ARR : GridBinaryMarshaller.OBJ_ARR;
+        }
         else
             newFldTypeId = BinaryUtils.typeByClass(newVal.getClass());
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/0b7c62d2/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectBuilderAdditionalSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectBuilderAdditionalSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectBuilderAdditionalSelfTest.java
index 24806cb..507aa6b 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectBuilderAdditionalSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectBuilderAdditionalSelfTest.java
@@ -21,6 +21,10 @@ import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
 import java.lang.reflect.Field;
 import java.math.BigDecimal;
 import java.math.BigInteger;
@@ -1423,11 +1427,19 @@ public class BinaryObjectBuilderAdditionalSelfTest extends GridCommonAbstractTes
      * @return Wrapper.
      */
     private BinaryObjectBuilderImpl newWrapper(Class<?> aCls) {
+        return newWrapper(aCls.getName());
+    }
+
+    /**
+     * @param typeName Type name.
+     * @return Wrapper.
+     */
+    private BinaryObjectBuilderImpl newWrapper(String typeName) {
         CacheObjectBinaryProcessorImpl processor = (CacheObjectBinaryProcessorImpl)(
             (IgniteBinaryImpl)binaries()).processor();
 
-        return new BinaryObjectBuilderImpl(processor.binaryContext(), processor.typeId(aCls.getName()),
-            processor.binaryContext().userTypeName(aCls.getName()));
+        return new BinaryObjectBuilderImpl(processor.binaryContext(), processor.typeId(typeName),
+            processor.binaryContext().userTypeName(typeName));
     }
 
     /**
@@ -1508,4 +1520,145 @@ public class BinaryObjectBuilderAdditionalSelfTest extends GridCommonAbstractTes
         assert OBJ.equals(binaryObj.type().fieldTypeName("asSetHint"));
         assert OBJ.equals(binaryObj.type().fieldTypeName("asMapHint"));
     }
+
+    /**
+     * Checks that externalizable value is correctly serialized/deserialized.
+     *
+     * @throws Exception If failed.
+     */
+    public void testBuilderExternalizable() throws Exception {
+        BinaryObjectBuilder builder = newWrapper("TestType");
+
+        final TestObjectExternalizable exp = new TestObjectExternalizable("test");
+        final TestObjectExternalizable[] expArr = new TestObjectExternalizable[]{
+            new TestObjectExternalizable("test1"), new TestObjectExternalizable("test2")};
+
+        BinaryObject extObj = builder.setField("extVal", exp).setField("extArr", expArr).build();
+
+        assertEquals(exp, extObj.field("extVal"));
+        Assert.assertArrayEquals(expArr, (Object[])extObj.field("extArr"));
+
+        builder = extObj.toBuilder();
+
+        extObj = builder.setField("intVal", 10).build();
+
+        assertEquals(exp, extObj.field("extVal"));
+        Assert.assertArrayEquals(expArr, (Object[])extObj.field("extArr"));
+        assertEquals(Integer.valueOf(10), extObj.field("intVal"));
+
+        builder = extObj.toBuilder();
+
+        extObj = builder.setField("strVal", "some string").build();
+
+        assertEquals(exp, extObj.field("extVal"));
+        Assert.assertArrayEquals(expArr, (Object[])extObj.field("extArr"));
+        assertEquals(Integer.valueOf(10), extObj.field("intVal"));
+        assertEquals("some string", extObj.field("strVal"));
+    }
+
+    /**
+     * Checks correct serialization/deserialization of enums in builder.
+     *
+     * @throws Exception If failed.
+     */
+    public void testEnum() throws Exception {
+        BinaryObjectBuilder builder = newWrapper("TestType");
+
+        final TestEnum exp = TestEnum.A;
+        final TestEnum[] expArr = {TestEnum.A, TestEnum.B};
+
+        BinaryObject enumObj = builder.setField("testEnum", exp).setField("testEnumArr", expArr).build();
+
+        assertEquals(exp, ((BinaryObject)enumObj.field("testEnum")).deserialize());
+        Assert.assertArrayEquals(expArr, (Object[])deserializeEnumBinaryArray(enumObj.field("testEnumArr")));
+
+        builder = newWrapper(enumObj.type().typeName());
+
+        enumObj = builder.setField("testEnum", (Object)enumObj.field("testEnum"))
+            .setField("testEnumArr", (Object)enumObj.field("testEnumArr")).build();
+
+        assertEquals(exp, ((BinaryObject)enumObj.field("testEnum")).deserialize());
+        Assert.assertArrayEquals(expArr, (Object[])deserializeEnumBinaryArray(enumObj.field("testEnumArr")));
+    }
+
+    /**
+     * @param obj BinaryObject array.
+     * @return Deserialized enums.
+     */
+    private TestEnum[] deserializeEnumBinaryArray(Object obj) {
+        Object[] arr = (Object[])obj;
+
+        final TestEnum[] res = new TestEnum[arr.length];
+
+        for (int i = 0; i < arr.length; i++)
+            res[i] = ((BinaryObject)arr[i]).deserialize();
+
+        return res;
+    }
+
+    /**
+     *
+     */
+    private static class TestObjectExternalizable implements Externalizable {
+        /** */
+        private String val;
+
+        /**
+         *
+         */
+        public TestObjectExternalizable() {
+        }
+
+        /**
+         * @param val Value.
+         */
+        public TestObjectExternalizable(final String val) {
+            this.val = val;
+        }
+
+        /** {@inheritDoc} */
+        @Override public void writeExternal(final ObjectOutput out) throws IOException {
+            out.writeUTF(val);
+        }
+
+        /** {@inheritDoc} */
+        @Override public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+            val = in.readUTF();
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean equals(final Object o) {
+            if (this == o)
+                return true;
+            if (o == null || getClass() != o.getClass())
+                return false;
+
+            final TestObjectExternalizable that = (TestObjectExternalizable)o;
+
+            return val != null ? val.equals(that.val) : that.val == null;
+        }
+
+        /** {@inheritDoc} */
+        @Override public int hashCode() {
+            return val != null ? val.hashCode() : 0;
+        }
+
+        /** {@inheritDoc} */
+        @Override public String toString() {
+            return "TestObjectExternalizable{" +
+                "val='" + val + '\'' +
+                '}';
+        }
+    }
+
+    /**
+     *
+     */
+    private enum TestEnum {
+        /** */
+        A,
+
+        /** */
+        B
+    }
 }