IGNITE-1838: Added fast-path deserialization for common field types (String, Date, Timestamp, UUID, BigDecimal, null).
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/7e399e84 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/7e399e84 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/7e399e84 Branch: refs/heads/ignite-1753-1282 Commit: 7e399e842322a3b6d2dad3974255a1629507e29b Parents: 433806d Author: vozerov-gridgain <[email protected]> Authored: Tue Nov 3 17:41:51 2015 +0300 Committer: vozerov-gridgain <[email protected]> Committed: Tue Nov 3 17:41:51 2015 +0300 ---------------------------------------------------------------------- .../internal/portable/PortableFieldImpl.java | 28 +- .../internal/portable/PortableObjectImpl.java | 100 ++- .../portable/PortableObjectOffheapImpl.java | 95 ++- .../internal/portable/PortablePrimitives.java | 44 ++ .../internal/portable/PortableReaderExImpl.java | 2 +- .../internal/portable/PortableSchema.java | 9 +- .../apache/ignite/portable/PortableField.java | 7 + .../PortableCompactOffsetsAbstractSelfTest.java | 201 ++++++ .../PortableCompactOffsetsHeapSelfTest.java | 32 + .../PortableCompactOffsetsOffheapSelfTest.java | 61 ++ .../PortableFieldsAbstractSelfTest.java | 688 +++++++++++++++++++ .../portable/PortableFieldsHeapSelfTest.java | 32 + .../portable/PortableFieldsOffheapSelfTest.java | 61 ++ .../IgnitePortableObjectsTestSuite.java | 9 + 14 files changed, 1349 insertions(+), 20 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/7e399e84/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableFieldImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableFieldImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableFieldImpl.java index 12be55c..80b0a6d 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableFieldImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableFieldImpl.java @@ -17,6 +17,8 @@ package org.apache.ignite.internal.portable; +import org.apache.ignite.internal.util.tostring.GridToStringExclude; +import org.apache.ignite.internal.util.typedef.internal.S; import org.apache.ignite.portable.PortableField; import org.apache.ignite.portable.PortableObject; @@ -25,8 +27,12 @@ import org.apache.ignite.portable.PortableObject; */ public class PortableFieldImpl implements PortableField { /** Well-known object schemas. */ + @GridToStringExclude private final PortableSchemaRegistry schemas; + /** Field name. */ + private final String fieldName; + /** Pre-calculated field ID. */ private final int fieldId; @@ -34,18 +40,29 @@ public class PortableFieldImpl implements PortableField { * Constructor. * * @param schemas Schemas. + * @param fieldName Field name. * @param fieldId Field ID. */ - public PortableFieldImpl(PortableSchemaRegistry schemas, int fieldId) { + public PortableFieldImpl(PortableSchemaRegistry schemas, String fieldName, int fieldId) { + assert schemas != null; + assert fieldName != null; + assert fieldId != 0; + this.schemas = schemas; + this.fieldName = fieldName; this.fieldId = fieldId; } /** {@inheritDoc} */ + @Override public String name() { + return fieldName; + } + + /** {@inheritDoc} */ @Override public boolean exists(PortableObject obj) { PortableObjectEx obj0 = (PortableObjectEx)obj; - return fieldOrder(obj0) != 0; + return fieldOrder(obj0) != PortableSchema.ORDER_NOT_FOUND; } /** {@inheritDoc} */ @@ -55,7 +72,7 @@ public class PortableFieldImpl implements PortableField { int order = fieldOrder(obj0); - return order != 0 ? (T)obj0.fieldByOrder(order) : null; + return order != PortableSchema.ORDER_NOT_FOUND ? (T)obj0.fieldByOrder(order) : null; } /** @@ -79,4 +96,9 @@ public class PortableFieldImpl implements PortableField { return schema.order(fieldId); } + + /** {@inheritDoc} */ + @Override public String toString() { + return S.toString(PortableFieldImpl.class, this); + } } http://git-wip-us.apache.org/repos/asf/ignite/blob/7e399e84/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableObjectImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableObjectImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableObjectImpl.java index c7e01d7..1d1be2b 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableObjectImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableObjectImpl.java @@ -25,6 +25,7 @@ import org.apache.ignite.internal.processors.cache.CacheObject; import org.apache.ignite.internal.processors.cache.CacheObjectContext; import org.apache.ignite.internal.processors.cache.KeyCacheObject; import org.apache.ignite.internal.processors.cache.portable.CacheObjectPortableProcessorImpl; +import org.apache.ignite.internal.util.typedef.internal.A; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.plugin.extensions.communication.Message; import org.apache.ignite.plugin.extensions.communication.MessageReader; @@ -39,16 +40,28 @@ import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; +import java.math.BigDecimal; +import java.math.BigInteger; import java.nio.ByteBuffer; +import java.sql.Timestamp; +import java.util.Date; +import java.util.UUID; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.apache.ignite.internal.portable.GridPortableMarshaller.BOOLEAN; import static org.apache.ignite.internal.portable.GridPortableMarshaller.BYTE; import static org.apache.ignite.internal.portable.GridPortableMarshaller.CHAR; +import static org.apache.ignite.internal.portable.GridPortableMarshaller.DATE; +import static org.apache.ignite.internal.portable.GridPortableMarshaller.DECIMAL; import static org.apache.ignite.internal.portable.GridPortableMarshaller.DOUBLE; import static org.apache.ignite.internal.portable.GridPortableMarshaller.FLOAT; import static org.apache.ignite.internal.portable.GridPortableMarshaller.INT; import static org.apache.ignite.internal.portable.GridPortableMarshaller.LONG; +import static org.apache.ignite.internal.portable.GridPortableMarshaller.NULL; import static org.apache.ignite.internal.portable.GridPortableMarshaller.SHORT; +import static org.apache.ignite.internal.portable.GridPortableMarshaller.STRING; +import static org.apache.ignite.internal.portable.GridPortableMarshaller.TIMESTAMP; +import static org.apache.ignite.internal.portable.GridPortableMarshaller.UUID; /** * Portable object implementation. @@ -178,13 +191,6 @@ public final class PortableObjectImpl extends PortableObjectEx implements Extern } /** - * @return {@code True} if detach is allowed. - */ - public boolean detachAllowed() { - return true; - } - - /** * @param detachAllowed Detach allowed flag. */ public void detachAllowed(boolean detachAllowed) { @@ -270,9 +276,9 @@ public final class PortableObjectImpl extends PortableObjectEx implements Extern int fieldPos; if (fieldOffsetSize == PortableUtils.OFFSET_1) - fieldPos = start + (int)PortablePrimitives.readByte(arr, fieldOffsetPos) & 0xFF; + fieldPos = start + ((int)PortablePrimitives.readByte(arr, fieldOffsetPos) & 0xFF); else if (fieldOffsetSize == PortableUtils.OFFSET_2) - fieldPos = start + (int)PortablePrimitives.readShort(arr, fieldOffsetPos) & 0xFFFF; + fieldPos = start + ((int)PortablePrimitives.readShort(arr, fieldOffsetPos) & 0xFFFF); else fieldPos = start + PortablePrimitives.readInt(arr, fieldOffsetPos); @@ -320,6 +326,78 @@ public final class PortableObjectImpl extends PortableObjectEx implements Extern break; + case STRING: { + boolean utf = PortablePrimitives.readBoolean(arr, fieldPos + 1); + + if (utf) { + int dataLen = PortablePrimitives.readInt(arr, fieldPos + 2); + + val = new String(arr, fieldPos + 6, dataLen, UTF_8); + } + else { + int dataLen = PortablePrimitives.readInt(arr, fieldPos + 2); + char[] data = PortablePrimitives.readCharArray(arr, fieldPos + 6, dataLen); + + val = String.valueOf(data); + } + + break; + } + + case DATE: { + long time = PortablePrimitives.readLong(arr, fieldPos + 1); + + val = new Date(time); + + break; + } + + case TIMESTAMP: { + long time = PortablePrimitives.readLong(arr, fieldPos + 1); + int nanos = PortablePrimitives.readInt(arr, fieldPos + 1 + 8); + + Timestamp ts = new Timestamp(time); + + ts.setNanos(ts.getNanos() + nanos); + + val = ts; + + break; + } + + case UUID: { + long most = PortablePrimitives.readLong(arr, fieldPos + 1); + long least = PortablePrimitives.readLong(arr, fieldPos + 1 + 8); + + val = new UUID(most, least); + + break; + } + + case DECIMAL: { + int scale = PortablePrimitives.readInt(arr, fieldPos + 1); + + int dataLen = PortablePrimitives.readInt(arr, fieldPos + 5); + byte[] data = PortablePrimitives.readByteArray(arr, fieldPos + 9, dataLen); + + BigInteger intVal = new BigInteger(data); + + if (scale < 0) { + scale &= 0x7FFFFFFF; + + intVal = intVal.negate(); + } + + val = new BigDecimal(intVal, scale); + + break; + } + + case NULL: + val = null; + + break; + default: { PortableReaderExImpl reader = new PortableReaderExImpl(ctx, arr, start, null); @@ -395,13 +473,15 @@ public final class PortableObjectImpl extends PortableObjectEx implements Extern /** {@inheritDoc} */ @Override public PortableField fieldDescriptor(String fieldName) throws PortableException { + A.notNull(fieldName, "fieldName"); + int typeId = typeId(); PortableSchemaRegistry schemaReg = ctx.schemaRegistry(typeId); int fieldId = ctx.userTypeIdMapper(typeId).fieldId(typeId, fieldName); - return new PortableFieldImpl(schemaReg, fieldId); + return new PortableFieldImpl(schemaReg, fieldName, fieldId); } /** {@inheritDoc} */ http://git-wip-us.apache.org/repos/asf/ignite/blob/7e399e84/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableObjectOffheapImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableObjectOffheapImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableObjectOffheapImpl.java index 7ba5553..3027f76 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableObjectOffheapImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableObjectOffheapImpl.java @@ -21,12 +21,19 @@ import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; +import java.math.BigDecimal; +import java.math.BigInteger; import java.nio.ByteBuffer; +import java.sql.Timestamp; +import java.util.Date; +import java.util.UUID; + import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.internal.portable.streams.PortableOffheapInputStream; import org.apache.ignite.internal.processors.cache.CacheObject; import org.apache.ignite.internal.processors.cache.CacheObjectContext; import org.apache.ignite.internal.util.GridUnsafe; +import org.apache.ignite.internal.util.typedef.internal.A; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.plugin.extensions.communication.MessageReader; import org.apache.ignite.plugin.extensions.communication.MessageWriter; @@ -37,14 +44,21 @@ import org.apache.ignite.portable.PortableObject; import org.jetbrains.annotations.Nullable; import sun.misc.Unsafe; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.apache.ignite.internal.portable.GridPortableMarshaller.BOOLEAN; import static org.apache.ignite.internal.portable.GridPortableMarshaller.BYTE; import static org.apache.ignite.internal.portable.GridPortableMarshaller.CHAR; +import static org.apache.ignite.internal.portable.GridPortableMarshaller.DATE; +import static org.apache.ignite.internal.portable.GridPortableMarshaller.DECIMAL; import static org.apache.ignite.internal.portable.GridPortableMarshaller.DOUBLE; import static org.apache.ignite.internal.portable.GridPortableMarshaller.FLOAT; import static org.apache.ignite.internal.portable.GridPortableMarshaller.INT; import static org.apache.ignite.internal.portable.GridPortableMarshaller.LONG; +import static org.apache.ignite.internal.portable.GridPortableMarshaller.NULL; import static org.apache.ignite.internal.portable.GridPortableMarshaller.SHORT; +import static org.apache.ignite.internal.portable.GridPortableMarshaller.STRING; +import static org.apache.ignite.internal.portable.GridPortableMarshaller.TIMESTAMP; +import static org.apache.ignite.internal.portable.GridPortableMarshaller.UUID; /** * Portable object implementation over offheap memory @@ -127,13 +141,15 @@ public class PortableObjectOffheapImpl extends PortableObjectEx implements Exter /** {@inheritDoc} */ @Override public PortableField fieldDescriptor(String fieldName) throws PortableException { + A.notNull(fieldName, "fieldName"); + int typeId = typeId(); PortableSchemaRegistry schemaReg = ctx.schemaRegistry(typeId); int fieldId = ctx.userTypeIdMapper(typeId).fieldId(typeId, fieldName); - return new PortableFieldImpl(schemaReg, fieldId); + return new PortableFieldImpl(schemaReg, fieldName, fieldId); } /** {@inheritDoc} */ @@ -202,9 +218,9 @@ public class PortableObjectOffheapImpl extends PortableObjectEx implements Exter int fieldPos; if (fieldOffsetSize == PortableUtils.OFFSET_1) - fieldPos = start + (int)PortablePrimitives.readByte(ptr, fieldOffsetPos) & 0xFF; + fieldPos = start + ((int)PortablePrimitives.readByte(ptr, fieldOffsetPos) & 0xFF); else if (fieldOffsetSize == PortableUtils.OFFSET_2) - fieldPos = start + (int)PortablePrimitives.readShort(ptr, fieldOffsetPos) & 0xFFFF; + fieldPos = start + ((int)PortablePrimitives.readShort(ptr, fieldOffsetPos) & 0xFFFF); else fieldPos = start + PortablePrimitives.readInt(ptr, fieldOffsetPos); @@ -252,6 +268,79 @@ public class PortableObjectOffheapImpl extends PortableObjectEx implements Exter break; + case STRING: { + boolean utf = PortablePrimitives.readBoolean(ptr, fieldPos + 1); + + if (utf) { + int dataLen = PortablePrimitives.readInt(ptr, fieldPos + 2); + byte[] data = PortablePrimitives.readByteArray(ptr, fieldPos + 6, dataLen); + + val = new String(data, UTF_8); + } + else { + int dataLen = PortablePrimitives.readInt(ptr, fieldPos + 2); + char[] data = PortablePrimitives.readCharArray(ptr, fieldPos + 6, dataLen); + + val = String.valueOf(data); + } + + break; + } + + case DATE: { + long time = PortablePrimitives.readLong(ptr, fieldPos + 1); + + val = new Date(time); + + break; + } + + case TIMESTAMP: { + long time = PortablePrimitives.readLong(ptr, fieldPos + 1); + int nanos = PortablePrimitives.readInt(ptr, fieldPos + 1 + 8); + + Timestamp ts = new Timestamp(time); + + ts.setNanos(ts.getNanos() + nanos); + + val = ts; + + break; + } + + case UUID: { + long most = PortablePrimitives.readLong(ptr, fieldPos + 1); + long least = PortablePrimitives.readLong(ptr, fieldPos + 1 + 8); + + val = new UUID(most, least); + + break; + } + + case DECIMAL: { + int scale = PortablePrimitives.readInt(ptr, fieldPos + 1); + + int dataLen = PortablePrimitives.readInt(ptr, fieldPos + 5); + byte[] data = PortablePrimitives.readByteArray(ptr, fieldPos + 9, dataLen); + + BigInteger intVal = new BigInteger(data); + + if (scale < 0) { + scale &= 0x7FFFFFFF; + + intVal = intVal.negate(); + } + + val = new BigDecimal(intVal, scale); + + break; + } + + case NULL: + val = null; + + break; + default: { PortableReaderExImpl reader = new PortableReaderExImpl(ctx, new PortableOffheapInputStream(ptr, size, false), http://git-wip-us.apache.org/repos/asf/ignite/blob/7e399e84/modules/core/src/main/java/org/apache/ignite/internal/portable/PortablePrimitives.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortablePrimitives.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortablePrimitives.java index d5a78bc..02f552a 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortablePrimitives.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortablePrimitives.java @@ -68,6 +68,32 @@ public abstract class PortablePrimitives { /** * @param arr Array. * @param off Offset. + * @return Value. + */ + public static byte[] readByteArray(byte[] arr, int off, int len) { + byte[] arr0 = new byte[len]; + + UNSAFE.copyMemory(arr, BYTE_ARR_OFF + off, arr0, BYTE_ARR_OFF, len); + + return arr0; + } + + /** + * @param ptr Pointer. + * @param off Offset. + * @return Value. + */ + public static byte[] readByteArray(long ptr, int off, int len) { + byte[] arr0 = new byte[len]; + + UNSAFE.copyMemory(null, ptr + off, arr0, BYTE_ARR_OFF, len); + + return arr0; + } + + /** + * @param arr Array. + * @param off Offset. * @param val Value. */ public static void writeBoolean(byte[] arr, int off, boolean val) { @@ -191,6 +217,24 @@ public abstract class PortablePrimitives { } /** + * @param ptr Pointer. + * @param off Offset. + * @return Value. + */ + public static char[] readCharArray(long ptr, int off, int len) { + char[] arr0 = new char[len]; + + UNSAFE.copyMemory(null, ptr + off, arr0, CHAR_ARR_OFF, len << 1); + + if (BIG_ENDIAN) { + for (int i = 0; i < len; i++) + arr0[i] = Character.reverseBytes(arr0[i]); + } + + return arr0; + } + + /** * @param arr Array. * @param off Offset. * @param val Value. http://git-wip-us.apache.org/repos/asf/ignite/blob/7e399e84/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableReaderExImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableReaderExImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableReaderExImpl.java index 9a088f4..b5decba 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableReaderExImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableReaderExImpl.java @@ -2633,7 +2633,7 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx int order = schema.order(id); - if (order != 0) { + if (order != PortableSchema.ORDER_NOT_FOUND) { int offsetPos = footerStart + order * (4 + offsetSize) + 4; int pos = start + PortableUtils.fieldOffsetRelative(in, offsetPos, offsetSize); http://git-wip-us.apache.org/repos/asf/ignite/blob/7e399e84/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableSchema.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableSchema.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableSchema.java index 03be319..96a93f4 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableSchema.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableSchema.java @@ -29,6 +29,9 @@ import java.util.Map; * - When there are more fields, we store them inside a hash map. */ public class PortableSchema { + /** Order returned if field is not found. */ + public static final int ORDER_NOT_FOUND = -1; + /** Inline flag. */ private final boolean inline; @@ -179,12 +182,12 @@ public class PortableSchema { if (id == id7) return 7; - return 0; + return ORDER_NOT_FOUND; } else { - Integer off = map.get(id); + Integer order = map.get(id); - return off != null ? off : 0; + return order != null ? order : ORDER_NOT_FOUND; } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/7e399e84/modules/core/src/main/java/org/apache/ignite/portable/PortableField.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/portable/PortableField.java b/modules/core/src/main/java/org/apache/ignite/portable/PortableField.java index f8851ee..81a7424 100644 --- a/modules/core/src/main/java/org/apache/ignite/portable/PortableField.java +++ b/modules/core/src/main/java/org/apache/ignite/portable/PortableField.java @@ -22,6 +22,13 @@ package org.apache.ignite.portable; */ public interface PortableField { /** + * Get field's name. + * + * @return Name. + */ + public String name(); + + /** * Check whether field exists in the object. * * @param obj Object. http://git-wip-us.apache.org/repos/asf/ignite/blob/7e399e84/modules/core/src/test/java/org/apache/ignite/internal/portable/PortableCompactOffsetsAbstractSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/portable/PortableCompactOffsetsAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/portable/PortableCompactOffsetsAbstractSelfTest.java new file mode 100644 index 0000000..28058de --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/portable/PortableCompactOffsetsAbstractSelfTest.java @@ -0,0 +1,201 @@ +/* + * 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.portable; + +import org.apache.ignite.internal.util.IgniteUtils; +import org.apache.ignite.marshaller.MarshallerContextTestImpl; +import org.apache.ignite.marshaller.portable.PortableMarshaller; +import org.apache.ignite.portable.PortableField; +import org.apache.ignite.portable.PortableMetadata; +import org.apache.ignite.portable.PortableTypeConfiguration; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; + +import java.util.Arrays; + +/** + * Contains tests for compact offsets. + */ +public abstract class PortableCompactOffsetsAbstractSelfTest extends GridCommonAbstractTest { + /** 2 pow 8. */ + private static int POW_8 = 1 << 8; + + /** 2 pow 16. */ + private static int POW_16 = 1 << 16; + + /** Dummy metadata handler. */ + protected static final PortableMetaDataHandler META_HND = new PortableMetaDataHandler() { + @Override public void addMeta(int typeId, PortableMetadata meta) { + // No-op. + } + + @Override public PortableMetadata metadata(int typeId) { + return null; + } + }; + + /** Marshaller. */ + protected PortableMarshaller marsh; + + /** Portable context. */ + protected PortableContext ctx; + + /** {@inheritDoc} */ + @Override protected void beforeTest() throws Exception { + super.beforeTest(); + + ctx = new PortableContext(META_HND, null); + + marsh = new PortableMarshaller(); + + marsh.setTypeConfigurations(Arrays.asList(new PortableTypeConfiguration(TestObject.class.getName()))); + marsh.setContext(new MarshallerContextTestImpl(null)); + + IgniteUtils.invoke(PortableMarshaller.class, marsh, "setPortableContext", ctx); + } + + /** + * Test 1 byte. + * + * @throws Exception If failed. + */ + public void test1Byte() throws Exception { + check(POW_8 >> 2); + } + + /** + * Test 1 byte with sign altering. + * + * @throws Exception If failed. + */ + public void test1ByteSign() throws Exception { + check(POW_8 >> 1); + } + + /** + * Test 2 bytes. + * + * @throws Exception If failed. + */ + public void test2Bytes() throws Exception { + check(POW_16 >> 2); + } + + /** + * Test 2 bytes with sign altering. + * + * @throws Exception If failed. + */ + public void test2BytesSign() throws Exception { + check(POW_16 >> 1); + } + + /** + * Test 4 bytes. + * + * @throws Exception If failed. + */ + public void test4Bytes() throws Exception { + check(POW_16 << 2); + } + + /** + * Main check routine. + * + * @param len Length of the first field. + * + * @throws Exception If failed. + */ + private void check(int len) throws Exception { + TestObject obj = new TestObject(len); + + PortableObjectEx portObj = toPortable(marsh, obj); + + // 1. Test portable object content. + assert portObj.hasField("field1"); + assert portObj.hasField("field2"); + + byte[] field1 = portObj.field("field1"); + Integer field2 = portObj.field("field2"); + + assert field1 != null; + assert field2 != null; + + assert Arrays.equals(obj.field1, field1); + assert obj.field2 == field2; + + // 2. Test fields API. + PortableField field1Desc = portObj.fieldDescriptor("field1"); + PortableField field2Desc = portObj.fieldDescriptor("field2"); + + assert field1Desc.exists(portObj); + assert field2Desc.exists(portObj); + + assert Arrays.equals(obj.field1, (byte[])field1Desc.value(portObj)); + assert obj.field2 == (Integer)field2Desc.value(portObj); + + // 3. Test deserialize. + TestObject objRestored = portObj.deserialize(); + + assert objRestored != null; + + assert Arrays.equals(obj.field1, objRestored.field1); + assert obj.field2 == objRestored.field2; + } + + /** + * Convert object to portable object. + * + * @param marsh Marshaller. + * @param obj Object. + * @return Portable object. + * @throws Exception If failed. + */ + protected abstract PortableObjectEx toPortable(PortableMarshaller marsh, Object obj) throws Exception; + + /** + * Test object. + */ + public static class TestObject { + /** First field with variable length. */ + public byte[] field1; + + /** Second field. */ + public int field2; + + /** + * Default constructor. + */ + public TestObject() { + // No-op. + } + + /** + * Constructor. + * + * @param len Array length. + */ + public TestObject(int len) { + field1 = new byte[len]; + + field1[0] = 1; + field1[len - 1] = 2; + + field2 = len; + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/7e399e84/modules/core/src/test/java/org/apache/ignite/internal/portable/PortableCompactOffsetsHeapSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/portable/PortableCompactOffsetsHeapSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/portable/PortableCompactOffsetsHeapSelfTest.java new file mode 100644 index 0000000..826f972 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/portable/PortableCompactOffsetsHeapSelfTest.java @@ -0,0 +1,32 @@ +/* + * 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.portable; + +import org.apache.ignite.marshaller.portable.PortableMarshaller; + +/** + * Compact offsets tests for heap portable objects. + */ +public class PortableCompactOffsetsHeapSelfTest extends PortableCompactOffsetsAbstractSelfTest { + /** {@inheritDoc} */ + @Override protected PortableObjectEx toPortable(PortableMarshaller marsh, Object obj) throws Exception { + byte[] bytes = marsh.marshal(obj); + + return new PortableObjectImpl(ctx, bytes, 0); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/7e399e84/modules/core/src/test/java/org/apache/ignite/internal/portable/PortableCompactOffsetsOffheapSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/portable/PortableCompactOffsetsOffheapSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/portable/PortableCompactOffsetsOffheapSelfTest.java new file mode 100644 index 0000000..9ad1c67 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/portable/PortableCompactOffsetsOffheapSelfTest.java @@ -0,0 +1,61 @@ +/* + * 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.portable; + +import org.apache.ignite.internal.util.GridUnsafe; +import org.apache.ignite.marshaller.portable.PortableMarshaller; +import org.eclipse.jetty.util.ConcurrentHashSet; +import sun.misc.Unsafe; + +/** + * Compact offsets tests for offheap portable objects. + */ +public class PortableCompactOffsetsOffheapSelfTest extends PortableCompactOffsetsAbstractSelfTest { + /** Unsafe instance. */ + private static final Unsafe UNSAFE = GridUnsafe.unsafe(); + + /** Byte array offset for unsafe mechanics. */ + protected static final long BYTE_ARR_OFF = UNSAFE.arrayBaseOffset(byte[].class); + + /** Allocated unsafe pointer. */ + private final ConcurrentHashSet<Long> ptrs = new ConcurrentHashSet<>(); + + /** {@inheritDoc} */ + @Override protected void afterTest() throws Exception { + super.afterTest(); + + // Cleanup allocated objects. + for (Long ptr : ptrs) + UNSAFE.freeMemory(ptr); + + ptrs.clear(); + } + + /** {@inheritDoc} */ + @Override protected PortableObjectEx toPortable(PortableMarshaller marsh, Object obj) throws Exception { + byte[] arr = marsh.marshal(obj); + + long ptr = UNSAFE.allocateMemory(arr.length); + + ptrs.add(ptr); + + UNSAFE.copyMemory(arr, BYTE_ARR_OFF, null, ptr, arr.length); + + return new PortableObjectOffheapImpl(ctx, ptr, 0, arr.length); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/7e399e84/modules/core/src/test/java/org/apache/ignite/internal/portable/PortableFieldsAbstractSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/portable/PortableFieldsAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/portable/PortableFieldsAbstractSelfTest.java new file mode 100644 index 0000000..2acc1f5 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/portable/PortableFieldsAbstractSelfTest.java @@ -0,0 +1,688 @@ +/* + * 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.portable; + +import org.apache.ignite.internal.util.IgniteUtils; +import org.apache.ignite.internal.util.typedef.internal.U; +import org.apache.ignite.marshaller.MarshallerContextTestImpl; +import org.apache.ignite.marshaller.portable.PortableMarshaller; +import org.apache.ignite.portable.PortableField; +import org.apache.ignite.portable.PortableMetadata; +import org.apache.ignite.portable.PortableObject; +import org.apache.ignite.portable.PortableTypeConfiguration; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; + +import java.math.BigDecimal; +import java.sql.Timestamp; +import java.util.Arrays; +import java.util.Date; +import java.util.UUID; + +/** + * Contains tests for portable object fields. + */ +public abstract class PortableFieldsAbstractSelfTest extends GridCommonAbstractTest { + /** Dummy metadata handler. */ + protected static final PortableMetaDataHandler META_HND = new PortableMetaDataHandler() { + @Override public void addMeta(int typeId, PortableMetadata meta) { + // No-op. + } + + @Override public PortableMetadata metadata(int typeId) { + return null; + } + }; + + /** Marshaller. */ + protected PortableMarshaller marsh; + + /** Portable context. */ + protected PortableContext ctx; + + /** {@inheritDoc} */ + @Override protected void beforeTest() throws Exception { + super.beforeTest(); + + ctx = new PortableContext(META_HND, null); + + marsh = new PortableMarshaller(); + + marsh.setTypeConfigurations(Arrays.asList( + new PortableTypeConfiguration(TestObject.class.getName()), + new PortableTypeConfiguration(TestOuterObject.class.getName()), + new PortableTypeConfiguration(TestInnerObject.class.getName()) + )); + + marsh.setContext(new MarshallerContextTestImpl(null)); + + IgniteUtils.invoke(PortableMarshaller.class, marsh, "setPortableContext", ctx); + } + + /** + * Test byte field. + * + * @throws Exception If failed. + */ + public void testByte() throws Exception { + check("fByte"); + } + + /** + * Test byte array field. + * + * @throws Exception If failed. + */ + public void testByteArray() throws Exception { + check("fByteArr"); + } + + /** + * Test boolean field. + * + * @throws Exception If failed. + */ + public void testBoolean() throws Exception { + check("fBool"); + } + + /** + * Test boolean array field. + * + * @throws Exception If failed. + */ + public void testBooleanArray() throws Exception { + check("fBoolArr"); + } + + /** + * Test short field. + * + * @throws Exception If failed. + */ + public void testShort() throws Exception { + check("fShort"); + } + + /** + * Test short array field. + * + * @throws Exception If failed. + */ + public void testShortArray() throws Exception { + check("fShortArr"); + } + + /** + * Test char field. + * + * @throws Exception If failed. + */ + public void testChar() throws Exception { + check("fChar"); + } + + /** + * Test char array field. + * + * @throws Exception If failed. + */ + public void testCharArray() throws Exception { + check("fCharArr"); + } + + /** + * Test int field. + * + * @throws Exception If failed. + */ + public void testInt() throws Exception { + check("fInt"); + } + + /** + * Test int array field. + * + * @throws Exception If failed. + */ + public void testIntArray() throws Exception { + check("fIntArr"); + } + + /** + * Test long field. + * + * @throws Exception If failed. + */ + public void testLong() throws Exception { + check("fLong"); + } + + /** + * Test long array field. + * + * @throws Exception If failed. + */ + public void testLongArray() throws Exception { + check("fLongArr"); + } + + /** + * Test float field. + * + * @throws Exception If failed. + */ + public void testFloat() throws Exception { + check("fFloat"); + } + + /** + * Test float array field. + * + * @throws Exception If failed. + */ + public void testFloatArray() throws Exception { + check("fFloatArr"); + } + + /** + * Test double field. + * + * @throws Exception If failed. + */ + public void testDouble() throws Exception { + check("fDouble"); + } + + /** + * Test double array field. + * + * @throws Exception If failed. + */ + public void testDoubleArray() throws Exception { + check("fDoubleArr"); + } + + /** + * Test string field. + * + * @throws Exception If failed. + */ + public void testString() throws Exception { + check("fString"); + } + + /** + * Test string array field. + * + * @throws Exception If failed. + */ + public void testStringArray() throws Exception { + check("fStringArr"); + } + + /** + * Test date field. + * + * @throws Exception If failed. + */ + public void testDate() throws Exception { + check("fDate"); + } + + /** + * Test date array field. + * + * @throws Exception If failed. + */ + public void testDateArray() throws Exception { + check("fDateArr"); + } + + /** + * Test timestamp field. + * + * @throws Exception If failed. + */ + public void testTimestamp() throws Exception { + check("fTimestamp"); + } + + /** + * Test timestamp array field. + * + * @throws Exception If failed. + */ + public void testTimestampArray() throws Exception { + check("fTimestampArr"); + } + + /** + * Test UUID field. + * + * @throws Exception If failed. + */ + public void testUuid() throws Exception { + check("fUuid"); + } + + /** + * Test UUID array field. + * + * @throws Exception If failed. + */ + public void testUuidArray() throws Exception { + check("fUuidArr"); + } + + /** + * Test decimal field. + * + * @throws Exception If failed. + */ + public void testDecimal() throws Exception { + check("fDecimal"); + } + + /** + * Test decimal array field. + * + * @throws Exception If failed. + */ + public void testDecimalArray() throws Exception { + check("fDecimalArr"); + } + + /** + * Test object field. + * + * @throws Exception If failed. + */ + public void testObject() throws Exception { + check("fObj"); + } + + /** + * Test object array field. + * + * @throws Exception If failed. + */ + public void testObjectArray() throws Exception { + check("fObjArr"); + } + + /** + * Test null field. + * + * @throws Exception If failed. + */ + public void testNull() throws Exception { + check("fNull"); + } + + /** + * Test missing field. + * + * @throws Exception If failed. + */ + public void testMissing() throws Exception { + String fieldName = "fMissing"; + + checkNormal(fieldName, false); + checkNested(fieldName, false); + } + + /** + * Check field resolution in both normal and nested modes. + * + * @param fieldName Field name. + * @throws Exception If failed. + */ + public void check(String fieldName) throws Exception { + checkNormal(fieldName, true); + checkNested(fieldName, true); + } + + /** + * Check field. + * + * @param fieldName Field name. + * @param exists Whether field should exist. + * @throws Exception If failed. + */ + private void checkNormal(String fieldName, boolean exists) throws Exception { + TestContext ctx = context(fieldName); + + check0(fieldName, ctx, exists); + } + + /** + * Check nested field. + * + * @param fieldName Field name. + * @param exists Whether field should exist. + * @throws Exception If failed. + */ + private void checkNested(String fieldName, boolean exists) throws Exception { + TestContext ctx = nestedContext(fieldName); + + check0(fieldName, ctx, exists); + } + + /** + * Internal check routine. + * + * @param fieldName Field name. + * @param ctx Context. + * @param exists Whether field should exist. + * @throws Exception If failed. + */ + private void check0(String fieldName, TestContext ctx, boolean exists) throws Exception { + Object val = ctx.field.value(ctx.portObj); + + if (exists) { + assertTrue(ctx.field.exists(ctx.portObj)); + + Object expVal = U.field(ctx.obj, fieldName); + + if (val instanceof PortableObject) + val = ((PortableObject) val).deserialize(); + + if (val != null && val.getClass().isArray()) { + assertNotNull(expVal); + + if (val instanceof byte[]) + assertTrue(Arrays.equals((byte[]) expVal, (byte[]) val)); + else if (val instanceof boolean[]) + assertTrue(Arrays.equals((boolean[]) expVal, (boolean[]) val)); + else if (val instanceof short[]) + assertTrue(Arrays.equals((short[]) expVal, (short[]) val)); + else if (val instanceof char[]) + assertTrue(Arrays.equals((char[]) expVal, (char[]) val)); + else if (val instanceof int[]) + assertTrue(Arrays.equals((int[]) expVal, (int[]) val)); + else if (val instanceof long[]) + assertTrue(Arrays.equals((long[]) expVal, (long[]) val)); + else if (val instanceof float[]) + assertTrue(Arrays.equals((float[]) expVal, (float[]) val)); + else if (val instanceof double[]) + assertTrue(Arrays.equals((double[]) expVal, (double[]) val)); + else { + Object[] expVal0 = (Object[])expVal; + Object[] val0 = (Object[])val; + + assertEquals(expVal0.length, val0.length); + + for (int i = 0; i < expVal0.length; i++) { + Object expItem = expVal0[i]; + Object item = val0[i]; + + if (item instanceof PortableObject) + item = ((PortableObject)item).deserialize(); + + assertEquals(expItem, item); + } + } + } + else + assertEquals(expVal, val); + } + else { + assertFalse(ctx.field.exists(ctx.portObj)); + + assert val == null; + } + } + + /** + * Get test context. + * + * @param fieldName Field name. + * @return Test context. + * @throws Exception If failed. + */ + private TestContext context(String fieldName) throws Exception { + TestObject obj = createObject(); + + PortableObjectEx portObj = toPortable(marsh, obj); + + PortableField field = portObj.fieldDescriptor(fieldName); + + return new TestContext(obj, portObj, field); + } + + /** + * Get test context with nested test object. + * + * @param fieldName Field name. + * @return Test context. + * @throws Exception If failed. + */ + private TestContext nestedContext(String fieldName) throws Exception { + TestObject obj = createObject(); + TestOuterObject outObj = new TestOuterObject(obj); + + PortableObjectEx portOutObj = toPortable(marsh, outObj); + PortableObjectEx portObj = portOutObj.field("fInner"); + + assert portObj != null; + + PortableField field = portObj.fieldDescriptor(fieldName); + + return new TestContext(obj, portObj, field); + } + + /** + * Create test object. + * + * @return Test object. + */ + private TestObject createObject() { + return new TestObject(0); + } + + /** + * Convert object to portable object. + * + * @param marsh Marshaller. + * @param obj Object. + * @return Portable object. + * @throws Exception If failed. + */ + protected abstract PortableObjectEx toPortable(PortableMarshaller marsh, Object obj) throws Exception; + + /** + * Outer test object. + */ + @SuppressWarnings("UnusedDeclaration") + public static class TestOuterObject { + /** Inner object. */ + public TestObject fInner; + + /** + * Default constructor. + */ + public TestOuterObject() { + // No-op. + } + + /** + * Constructor. + * + * @param fInner Inner object. + */ + public TestOuterObject(TestObject fInner) { + this.fInner = fInner; + } + } + + /** + * Test object class, c + */ + @SuppressWarnings("UnusedDeclaration") + public static class TestObject { + /** Primitive fields. */ + public byte fByte; + public boolean fBool; + public short fShort; + public char fChar; + public int fInt; + public long fLong; + public float fFloat; + public double fDouble; + + public byte[] fByteArr; + public boolean[] fBoolArr; + public short[] fShortArr; + public char[] fCharArr; + public int[] fIntArr; + public long[] fLongArr; + public float[] fFloatArr; + public double[] fDoubleArr; + + /** Special fields. */ + public String fString; + public Date fDate; + public Timestamp fTimestamp; + public UUID fUuid; + public BigDecimal fDecimal; + + public String[] fStringArr; + public Date[] fDateArr; + public Timestamp[] fTimestampArr; + public UUID[] fUuidArr; + public BigDecimal[] fDecimalArr; + + /** Nested object. */ + public TestInnerObject fObj; + + public TestInnerObject[] fObjArr; + + /** Field which is always set to null. */ + public Object fNull; + + /** + * Default constructor. + */ + public TestObject() { + // No-op. + } + + /** + * Non-default constructor. + * + * @param ignore Ignored. + */ + public TestObject(int ignore) { + fByte = 1; + fBool = true; + fShort = 2; + fChar = 3; + fInt = 4; + fLong = 5; + fFloat = 6.6f; + fDouble = 7.7; + + fByteArr = new byte[] { 1, 2 }; + fBoolArr = new boolean[] { true, false }; + fShortArr = new short[] { 2, 3 }; + fCharArr = new char[] { 3, 4 }; + fIntArr = new int[] { 4, 5 }; + fLongArr = new long[] { 5, 6 }; + fFloatArr = new float[] { 6.6f, 7.7f }; + fDoubleArr = new double[] { 7.7, 8.8 }; + + fString = "8"; + fDate = new Date(); + fTimestamp = new Timestamp(new Date().getTime() + 1); + fUuid = UUID.randomUUID(); + fDecimal = new BigDecimal(9); + + fStringArr = new String[] { "8", "9" }; + fDateArr = new Date[] { new Date(), new Date(new Date().getTime() + 1) }; + fTimestampArr = + new Timestamp[] { new Timestamp(new Date().getTime() + 1), new Timestamp(new Date().getTime() + 2) }; + fUuidArr = new UUID[] { UUID.randomUUID(), UUID.randomUUID() }; + fDecimalArr = new BigDecimal[] { new BigDecimal(9), new BigDecimal(10) }; + + fObj = new TestInnerObject(10); + fObjArr = new TestInnerObject[] { new TestInnerObject(10), new TestInnerObject(11) }; + } + } + + /** + * Inner test object. + */ + @SuppressWarnings("UnusedDeclaration") + public static class TestInnerObject { + /** Value. */ + private int val; + + /** + * Default constructor. + */ + public TestInnerObject() { + // No-op. + } + + /** + * Constructor. + * + * @param val Value. + */ + public TestInnerObject(int val) { + this.val = val; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + return val; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object other) { + return other != null && other instanceof TestInnerObject && val == ((TestInnerObject)(other)).val; + } + } + + /** + * Test context. + */ + public static class TestContext { + /** Object. */ + public final TestObject obj; + + /** Portable object. */ + public final PortableObjectEx portObj; + + /** Field. */ + public final PortableField field; + + /** + * Constructor. + * + * @param obj Object. + * @param portObj Portable object. + * @param field Field. + */ + public TestContext(TestObject obj, PortableObjectEx portObj, PortableField field) { + this.obj = obj; + this.portObj = portObj; + this.field = field; + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/7e399e84/modules/core/src/test/java/org/apache/ignite/internal/portable/PortableFieldsHeapSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/portable/PortableFieldsHeapSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/portable/PortableFieldsHeapSelfTest.java new file mode 100644 index 0000000..f7ccd1d --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/portable/PortableFieldsHeapSelfTest.java @@ -0,0 +1,32 @@ +/* + * 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.portable; + +import org.apache.ignite.marshaller.portable.PortableMarshaller; + +/** + * Field tests for heap-based portables. + */ +public class PortableFieldsHeapSelfTest extends PortableFieldsAbstractSelfTest { + /** {@inheritDoc} */ + @Override protected PortableObjectEx toPortable(PortableMarshaller marsh, Object obj) throws Exception { + byte[] bytes = marsh.marshal(obj); + + return new PortableObjectImpl(ctx, bytes, 0); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/7e399e84/modules/core/src/test/java/org/apache/ignite/internal/portable/PortableFieldsOffheapSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/portable/PortableFieldsOffheapSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/portable/PortableFieldsOffheapSelfTest.java new file mode 100644 index 0000000..e421375 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/portable/PortableFieldsOffheapSelfTest.java @@ -0,0 +1,61 @@ +/* + * 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.portable; + +import org.apache.ignite.internal.util.GridUnsafe; +import org.apache.ignite.marshaller.portable.PortableMarshaller; +import org.eclipse.jetty.util.ConcurrentHashSet; +import sun.misc.Unsafe; + +/** + * Field tests for heap-based portables. + */ +public class PortableFieldsOffheapSelfTest extends PortableFieldsAbstractSelfTest { + /** Unsafe instance. */ + private static final Unsafe UNSAFE = GridUnsafe.unsafe(); + + /** Byte array offset for unsafe mechanics. */ + protected static final long BYTE_ARR_OFF = UNSAFE.arrayBaseOffset(byte[].class); + + /** Allocated unsafe pointer. */ + private final ConcurrentHashSet<Long> ptrs = new ConcurrentHashSet<>(); + + /** {@inheritDoc} */ + @Override protected void afterTest() throws Exception { + super.afterTest(); + + // Cleanup allocated objects. + for (Long ptr : ptrs) + UNSAFE.freeMemory(ptr); + + ptrs.clear(); + } + + /** {@inheritDoc} */ + @Override protected PortableObjectEx toPortable(PortableMarshaller marsh, Object obj) throws Exception { + byte[] arr = marsh.marshal(obj); + + long ptr = UNSAFE.allocateMemory(arr.length); + + ptrs.add(ptr); + + UNSAFE.copyMemory(arr, BYTE_ARR_OFF, null, ptr, arr.length); + + return new PortableObjectOffheapImpl(ctx, ptr, 0, arr.length); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/7e399e84/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePortableObjectsTestSuite.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePortableObjectsTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePortableObjectsTestSuite.java index ecd25e1..3cfd530 100644 --- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePortableObjectsTestSuite.java +++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePortableObjectsTestSuite.java @@ -28,6 +28,11 @@ import org.apache.ignite.internal.portable.GridPortableMarshallerSelfTest; import org.apache.ignite.internal.portable.GridPortableMetaDataDisabledSelfTest; import org.apache.ignite.internal.portable.GridPortableMetaDataSelfTest; import org.apache.ignite.internal.portable.GridPortableWildcardsSelfTest; +import org.apache.ignite.internal.portable.PortableCompactOffsetsAbstractSelfTest; +import org.apache.ignite.internal.portable.PortableCompactOffsetsHeapSelfTest; +import org.apache.ignite.internal.portable.PortableCompactOffsetsOffheapSelfTest; +import org.apache.ignite.internal.portable.PortableFieldsHeapSelfTest; +import org.apache.ignite.internal.portable.PortableFieldsOffheapSelfTest; import org.apache.ignite.internal.processors.cache.portable.GridCacheClientNodePortableMetadataMultinodeTest; import org.apache.ignite.internal.processors.cache.portable.GridCacheClientNodePortableMetadataTest; import org.apache.ignite.internal.processors.cache.portable.GridCachePortableStoreObjectsSelfTest; @@ -60,6 +65,10 @@ public class IgnitePortableObjectsTestSuite extends TestSuite { suite.addTestSuite(GridPortableMarshallerCtxDisabledSelfTest.class); suite.addTestSuite(GridPortableBuilderSelfTest.class); suite.addTestSuite(GridPortableBuilderStringAsCharsSelfTest.class); + suite.addTestSuite(PortableFieldsHeapSelfTest.class); + suite.addTestSuite(PortableFieldsOffheapSelfTest.class); + suite.addTestSuite(PortableCompactOffsetsHeapSelfTest.class); + suite.addTestSuite(PortableCompactOffsetsOffheapSelfTest.class); suite.addTestSuite(GridPortableMetaDataSelfTest.class); suite.addTestSuite(GridPortableMetaDataDisabledSelfTest.class); suite.addTestSuite(GridPortableAffinityKeySelfTest.class);
