IGNITE-1418: Implemented compact field offsets.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/845c4f27 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/845c4f27 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/845c4f27 Branch: refs/heads/ignite-1753-1282 Commit: 845c4f2722e69aa1f7ccd8ff619c52a013eb775a Parents: fd640d7 Author: vozerov-gridgain <[email protected]> Authored: Tue Nov 3 13:16:10 2015 +0300 Committer: vozerov-gridgain <[email protected]> Committed: Tue Nov 3 13:16:10 2015 +0300 ---------------------------------------------------------------------- .gitignore | 7 + .../portable/PortableClassDescriptor.java | 33 ++- .../internal/portable/PortableFieldImpl.java | 10 +- .../internal/portable/PortableObjectEx.java | 2 +- .../internal/portable/PortableObjectImpl.java | 46 ++- .../portable/PortableObjectOffheapImpl.java | 89 +++++- .../internal/portable/PortableReaderExImpl.java | 41 +-- .../internal/portable/PortableSchema.java | 133 ++++----- .../ignite/internal/portable/PortableUtils.java | 46 ++- .../internal/portable/PortableWriterExImpl.java | 76 ++++- .../portable/builder/PortableBuilderImpl.java | 283 ++++++++++--------- .../src/portable_reader_writer_test.cpp | 251 +++++++++++++--- .../ignite/impl/interop/interop_input_stream.h | 16 ++ .../ignite/impl/interop/interop_output_stream.h | 8 + .../ignite/impl/portable/portable_common.h | 6 + .../ignite/impl/portable/portable_reader_impl.h | 29 +- .../ignite/impl/portable/portable_schema.h | 26 +- .../src/impl/interop/interop_input_stream.cpp | 20 ++ .../src/impl/interop/interop_output_stream.cpp | 7 + .../src/impl/portable/portable_reader_impl.cpp | 45 ++- .../core/src/impl/portable/portable_schema.cpp | 53 +++- .../src/impl/portable/portable_writer_impl.cpp | 21 +- .../Portable/PortableSelfTest.cs | 32 +++ .../Impl/Common/ResizeableArray.cs | 14 +- .../Apache.Ignite.Core/Impl/ExceptionUtils.cs | 2 - .../Impl/Portable/PortableBuilderImpl.cs | 8 +- .../Impl/Portable/PortableObjectHeader.cs | 196 ++++++++++--- .../Impl/Portable/PortableObjectSchema.cs | 6 +- .../Impl/Portable/PortableObjectSchemaField.cs | 69 +---- .../Impl/Portable/PortableReaderImpl.cs | 113 +++----- .../Impl/Portable/PortableUtils.cs | 4 +- .../Impl/Portable/PortableWriterImpl.cs | 7 +- .../Impl/Portable/PortablesImpl.cs | 2 +- .../Impl/Unmanaged/UnmanagedCallbackHandlers.cs | 2 +- 34 files changed, 1145 insertions(+), 558 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/845c4f27/.gitignore ---------------------------------------------------------------------- diff --git a/.gitignore b/.gitignore index 3da8e4d..22e3cc6 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,10 @@ target pom-installed.xml git-patch-prop-local.sh /slurp.sh +*.vcxproj.user +Apache.Ignite.sdf +ignite.sdf +ignite.opensdf +**/cpp/**/vs/x64/ +**/cpp/**/vs/Win32/ +**/dotnet/**/obj/ http://git-wip-us.apache.org/repos/asf/ignite/blob/845c4f27/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableClassDescriptor.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableClassDescriptor.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableClassDescriptor.java index 9f7f0c6..aa72017 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableClassDescriptor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableClassDescriptor.java @@ -524,12 +524,17 @@ public class PortableClassDescriptor { case PORTABLE: if (writeHeader(obj, writer)) { - if (serializer != null) - serializer.writePortable(obj, writer); - else - ((PortableMarshalAware)obj).writePortable(writer); + try { + if (serializer != null) + serializer.writePortable(obj, writer); + else + ((PortableMarshalAware) obj).writePortable(writer); - writer.postWrite(userType); + writer.postWrite(userType); + } + finally { + writer.popSchema(); + } if (obj.getClass() != PortableMetaDataImpl.class && ctx.isMetaDataChanged(typeId, writer.metaDataHashSum())) { @@ -552,22 +557,30 @@ public class PortableClassDescriptor { try { ((Externalizable)obj).writeExternal(writer); + + writer.postWrite(userType); } catch (IOException e) { throw new PortableException("Failed to write Externalizable object: " + obj, e); } - - writer.postWrite(userType); + finally { + writer.popSchema(); + } } break; case OBJECT: if (writeHeader(obj, writer)) { - for (FieldInfo info : fields) - info.write(obj, writer); + try { + for (FieldInfo info : fields) + info.write(obj, writer); - writer.postWrite(userType); + writer.postWrite(userType); + } + finally { + writer.popSchema(); + } } break; http://git-wip-us.apache.org/repos/asf/ignite/blob/845c4f27/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 5780b76..12be55c 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 @@ -45,7 +45,7 @@ public class PortableFieldImpl implements PortableField { @Override public boolean exists(PortableObject obj) { PortableObjectEx obj0 = (PortableObjectEx)obj; - return fieldOffset(obj0) != 0; + return fieldOrder(obj0) != 0; } /** {@inheritDoc} */ @@ -53,9 +53,9 @@ public class PortableFieldImpl implements PortableField { @Override public <T> T value(PortableObject obj) { PortableObjectEx obj0 = (PortableObjectEx)obj; - int offset = fieldOffset(obj0); + int order = fieldOrder(obj0); - return offset != 0 ? (T)obj0.fieldByOffset(offset) : null; + return order != 0 ? (T)obj0.fieldByOrder(order) : null; } /** @@ -64,7 +64,7 @@ public class PortableFieldImpl implements PortableField { * @param obj Object. * @return Field offset. */ - private int fieldOffset(PortableObjectEx obj) { + private int fieldOrder(PortableObjectEx obj) { int schemaId = obj.schemaId(); PortableSchema schema = schemas.schema(schemaId); @@ -77,6 +77,6 @@ public class PortableFieldImpl implements PortableField { assert schema != null; - return schema.offset(fieldId); + return schema.order(fieldId); } } http://git-wip-us.apache.org/repos/asf/ignite/blob/845c4f27/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableObjectEx.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableObjectEx.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableObjectEx.java index 42c973b..d6d7f50 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableObjectEx.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableObjectEx.java @@ -72,7 +72,7 @@ public abstract class PortableObjectEx implements PortableObject { * @param fieldOffset Field offset. * @return Field value. */ - @Nullable protected abstract <F> F fieldByOffset(int fieldOffset); + @Nullable protected abstract <F> F fieldByOrder(int fieldOffset); /** * @param ctx Reader context. http://git-wip-us.apache.org/repos/asf/ignite/blob/845c4f27/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 a1272d0..c7e01d7 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 @@ -256,11 +256,25 @@ public final class PortableObjectImpl extends PortableObjectEx implements Extern /** {@inheritDoc} */ @SuppressWarnings("unchecked") - @Nullable @Override protected <F> F fieldByOffset(int fieldOffset) { + @Nullable @Override protected <F> F fieldByOrder(int order) { Object val; + // Calculate field position. int schemaOffset = PortablePrimitives.readInt(arr, start + GridPortableMarshaller.SCHEMA_OR_RAW_OFF_POS); - int fieldPos = PortablePrimitives.readInt(arr, start + schemaOffset + fieldOffset); + + short flags = PortablePrimitives.readShort(arr, start + GridPortableMarshaller.FLAGS_POS); + int fieldOffsetSize = PortableUtils.fieldOffsetSize(flags); + + int fieldOffsetPos = start + schemaOffset + order * (4 + fieldOffsetSize) + 4; + + int fieldPos; + + if (fieldOffsetSize == PortableUtils.OFFSET_1) + fieldPos = start + (int)PortablePrimitives.readByte(arr, fieldOffsetPos) & 0xFF; + else if (fieldOffsetSize == PortableUtils.OFFSET_2) + fieldPos = start + (int)PortablePrimitives.readShort(arr, fieldOffsetPos) & 0xFFFF; + else + fieldPos = start + PortablePrimitives.readInt(arr, fieldOffsetPos); // Read header and try performing fast lookup for well-known types (the most common types go first). byte hdr = PortablePrimitives.readByte(arr, fieldPos); @@ -306,36 +320,10 @@ public final class PortableObjectImpl extends PortableObjectEx implements Extern break; -// case DECIMAL: -// val = doReadDecimal(); -// -// break; -// -// case STRING: -// val = doReadString(); -// -// break; -// -// case UUID: -// val = doReadUuid(); -// -// break; -// -// case DATE: -// val = doReadDate(); -// -// break; -// -// case TIMESTAMP: -// val = doReadTimestamp(); -// -// break; - default: { - // TODO: Pass absolute offset, not relative. PortableReaderExImpl reader = new PortableReaderExImpl(ctx, arr, start, null); - val = reader.unmarshalFieldByOffset(fieldOffset); + val = reader.unmarshalFieldByAbsolutePosition(fieldPos); } } http://git-wip-us.apache.org/repos/asf/ignite/blob/845c4f27/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 f023f2e..7ba5553 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 @@ -37,6 +37,15 @@ import org.apache.ignite.portable.PortableObject; import org.jetbrains.annotations.Nullable; import sun.misc.Unsafe; +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.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.SHORT; + /** * Portable object implementation over offheap memory */ @@ -179,13 +188,81 @@ public class PortableObjectOffheapImpl extends PortableObjectEx implements Exter /** {@inheritDoc} */ @SuppressWarnings("unchecked") - @Nullable @Override protected <F> F fieldByOffset(int fieldOffset) { - PortableReaderExImpl reader = new PortableReaderExImpl(ctx, - new PortableOffheapInputStream(ptr, size, false), - start, - null); + @Nullable @Override protected <F> F fieldByOrder(int order) { + Object val; + + // Calculate field position. + int schemaOffset = PortablePrimitives.readInt(ptr, start + GridPortableMarshaller.SCHEMA_OR_RAW_OFF_POS); + + short flags = PortablePrimitives.readShort(ptr, start + GridPortableMarshaller.FLAGS_POS); + int fieldOffsetSize = PortableUtils.fieldOffsetSize(flags); + + int fieldOffsetPos = start + schemaOffset + order * (4 + fieldOffsetSize) + 4; + + int fieldPos; + + if (fieldOffsetSize == PortableUtils.OFFSET_1) + fieldPos = start + (int)PortablePrimitives.readByte(ptr, fieldOffsetPos) & 0xFF; + else if (fieldOffsetSize == PortableUtils.OFFSET_2) + fieldPos = start + (int)PortablePrimitives.readShort(ptr, fieldOffsetPos) & 0xFFFF; + else + fieldPos = start + PortablePrimitives.readInt(ptr, fieldOffsetPos); + + // Read header and try performing fast lookup for well-known types (the most common types go first). + byte hdr = PortablePrimitives.readByte(ptr, fieldPos); + + switch (hdr) { + case INT: + val = PortablePrimitives.readInt(ptr, fieldPos + 1); + + break; + + case LONG: + val = PortablePrimitives.readLong(ptr, fieldPos + 1); + + break; + + case BOOLEAN: + val = PortablePrimitives.readBoolean(ptr, fieldPos + 1); + + break; + + case SHORT: + val = PortablePrimitives.readShort(ptr, fieldPos + 1); + + break; + + case BYTE: + val = PortablePrimitives.readByte(ptr, fieldPos + 1); + + break; + + case CHAR: + val = PortablePrimitives.readChar(ptr, fieldPos + 1); + + break; + + case FLOAT: + val = PortablePrimitives.readFloat(ptr, fieldPos + 1); + + break; + + case DOUBLE: + val = PortablePrimitives.readDouble(ptr, fieldPos + 1); + + break; + + default: { + PortableReaderExImpl reader = new PortableReaderExImpl(ctx, + new PortableOffheapInputStream(ptr, size, false), + start, + null); + + val = reader.unmarshalFieldByAbsolutePosition(fieldPos); + } + } - return (F)reader.unmarshalFieldByOffset(fieldOffset); + return (F)val; } /** {@inheritDoc} */ http://git-wip-us.apache.org/repos/asf/ignite/blob/845c4f27/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 aa1519d..061a9fd 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 @@ -163,6 +163,9 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx /** Schema Id. */ private int schemaId; + /** Offset size in bytes. */ + private int offsetSize; + /** Object schema. */ private PortableSchema schema; @@ -221,18 +224,20 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx PortableUtils.checkProtocolVersion(in.readByte()); - in.position(in.position() + 2); // Skip flags. + short flags = in.readShort(); + + offsetSize = PortableUtils.fieldOffsetSize(flags); typeId = in.readIntPositioned(start + GridPortableMarshaller.TYPE_ID_POS); - IgniteBiTuple<Integer, Integer> footer = PortableUtils.footerAbsolute(in, start); + IgniteBiTuple<Integer, Integer> footer = PortableUtils.footerAbsolute(in, start, offsetSize); footerStart = footer.get1(); footerLen = footer.get2() - footerStart; schemaId = in.readIntPositioned(start + GridPortableMarshaller.SCHEMA_ID_POS); - rawOff = PortableUtils.rawOffsetAbsolute(in, start); + rawOff = PortableUtils.rawOffsetAbsolute(in, start, offsetSize); if (typeId == UNREGISTERED_TYPE_ID) { // Skip to the class name position. @@ -307,16 +312,16 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx } /** - * @param fieldOffset Field offset. - * @return Unmarshalled value. + * Unmarshal field by absolute position. + * + * @param pos Absolute position. + * @return Field value. * @throws PortableException In case of error. */ - @Nullable Object unmarshalFieldByOffset(int fieldOffset) throws PortableException { - assert fieldOffset != 0; - + @Nullable Object unmarshalFieldByAbsolutePosition(int pos) throws PortableException { parseHeaderIfNeeded(); - in.position(start + in.readIntPositioned(footerStart + fieldOffset)); + in.position(pos); return unmarshal(); } @@ -2567,12 +2572,14 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx int searchPos = footerStart; int searchEnd = searchPos + footerLen; + int idx = 0; + while (searchPos < searchEnd) { int fieldId = in.readIntPositioned(searchPos); - fields.put(fieldId, searchPos + 4 - footerStart); + fields.put(fieldId, idx++); - searchPos += 8; + searchPos += 4 + offsetSize; } return new PortableSchema(fields); @@ -2599,14 +2606,14 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx int id0 = in.readIntPositioned(searchPos); if (id0 == id) { - int pos = start + in.readIntPositioned(searchPos + 4); + int pos = start + PortableUtils.fieldOffsetRelative(in, searchPos + 4, offsetSize); in.position(pos); return pos; } - searchPos += 8; + searchPos += 4 + offsetSize; } } else { @@ -2624,10 +2631,12 @@ public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx schema = schema0; } - int fieldOffsetPos = schema.offset(id); + int order = schema.order(id); + + if (order != 0) { + int offsetPos = footerStart + order * (4 + offsetSize) + 4; - if (fieldOffsetPos != 0) { - int pos = start + in.readIntPositioned(footerStart + fieldOffsetPos); + int pos = start + PortableUtils.fieldOffsetRelative(in, offsetPos, offsetSize); in.position(pos); http://git-wip-us.apache.org/repos/asf/ignite/blob/845c4f27/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 09bfe35..03be319 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 @@ -36,52 +36,28 @@ public class PortableSchema { private final HashMap<Integer, Integer> map; /** ID 1. */ - private final int id1; - - /** Offset 1. */ - private final int offset1; + private final int id0; /** ID 2. */ - private final int id2; - - /** Offset 2. */ - private final int offset2; + private final int id1; /** ID 3. */ - private final int id3; - - /** Offset 3. */ - private final int offset3; + private final int id2; /** ID 4. */ - private final int id4; - - /** Offset 4. */ - private final int offset4; + private final int id3; /** ID 1. */ - private final int id5; - - /** Offset 1. */ - private final int offset5; + private final int id4; /** ID 2. */ - private final int id6; - - /** Offset 2. */ - private final int offset6; + private final int id5; /** ID 3. */ - private final int id7; - - /** Offset 3. */ - private final int offset7; + private final int id6; /** ID 4. */ - private final int id8; - - /** Offset 4. */ - private final int offset8; + private final int id7; /** * Constructor. @@ -97,120 +73,111 @@ public class PortableSchema { Map.Entry<Integer, Integer> entry = iter.hasNext() ? iter.next() : null; if (entry != null) { + id0 = entry.getKey(); + + assert entry.getValue() == 0; + } + else + id0 = 0; + + if ((entry = iter.hasNext() ? iter.next() : null) != null) { id1 = entry.getKey(); - offset1 = entry.getValue(); + + assert entry.getValue() == 1; } - else{ + else id1 = 0; - offset1 = 0; - } if ((entry = iter.hasNext() ? iter.next() : null) != null) { id2 = entry.getKey(); - offset2 = entry.getValue(); + + assert entry.getValue() == 2; } - else{ + else id2 = 0; - offset2 = 0; - } if ((entry = iter.hasNext() ? iter.next() : null) != null) { id3 = entry.getKey(); - offset3 = entry.getValue(); + + assert entry.getValue() == 3; } - else{ + else id3 = 0; - offset3 = 0; - } if ((entry = iter.hasNext() ? iter.next() : null) != null) { id4 = entry.getKey(); - offset4 = entry.getValue(); + + assert entry.getValue() == 4; } - else{ + else id4 = 0; - offset4 = 0; - } if ((entry = iter.hasNext() ? iter.next() : null) != null) { id5 = entry.getKey(); - offset5 = entry.getValue(); + + assert entry.getValue() == 5; } - else{ + else id5 = 0; - offset5 = 0; - } if ((entry = iter.hasNext() ? iter.next() : null) != null) { id6 = entry.getKey(); - offset6 = entry.getValue(); + + assert entry.getValue() == 6; } - else{ + else id6 = 0; - offset6 = 0; - } if ((entry = iter.hasNext() ? iter.next() : null) != null) { id7 = entry.getKey(); - offset7 = entry.getValue(); - } - else{ - id7 = 0; - offset7 = 0; - } - if ((entry = iter.hasNext() ? iter.next() : null) != null) { - id8 = entry.getKey(); - offset8 = entry.getValue(); - } - else{ - id8 = 0; - offset8 = 0; + assert entry.getValue() == 7; } + else + id7 = 0; map = null; } else { inline = false; - id1 = id2 = id3 = id4 = id5 = id6 = id7 = id8 = 0; - offset1 = offset2 = offset3 = offset4 = offset5 = offset6 = offset7 = offset8 = 0; + id0 = id1 = id2 = id3 = id4 = id5 = id6 = id7 = 0; map = new HashMap<>(vals); } } /** - * Get offset for the given field ID. + * Get field position in footer by schema ID. * * @param id Field ID. * @return Offset or {@code 0} if there is no such field. */ - public int offset(int id) { + public int order(int id) { if (inline) { + if (id == id0) + return 0; + if (id == id1) - return offset1; + return 1; if (id == id2) - return offset2; + return 2; if (id == id3) - return offset3; + return 3; if (id == id4) - return offset4; + return 4; if (id == id5) - return offset5; + return 5; if (id == id6) - return offset6; + return 6; if (id == id7) - return offset7; - - if (id == id8) - return offset8; + return 7; return 0; } http://git-wip-us.apache.org/repos/asf/ignite/blob/845c4f27/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableUtils.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableUtils.java index f57a29b..4e3538c 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableUtils.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableUtils.java @@ -619,14 +619,16 @@ public class PortableUtils { * * @param in Input stream. * @param start Start position. + * @param fieldOffsetSize Field offset size. * @return Footer. */ - public static IgniteBiTuple<Integer, Integer> footerAbsolute(PortablePositionReadable in, int start) { + public static IgniteBiTuple<Integer, Integer> footerAbsolute(PortablePositionReadable in, int start, + int fieldOffsetSize) { int footerStart = footerStartRelative(in, start); int footerEnd = length(in, start); // Take in count possible raw offset. - if ((((footerEnd - footerStart) >> 2) & 0x1) == 0x1) + if ((footerEnd - footerStart) % (4 + fieldOffsetSize) != 0) footerEnd -= 4; return F.t(start + footerStart, start + footerEnd); @@ -637,9 +639,10 @@ public class PortableUtils { * * @param in Input stream. * @param start Object start position inside the stream. + * @param fieldOffsetSize Field offset size. * @return Raw offset. */ - public static int rawOffsetAbsolute(PortablePositionReadable in, int start) { + public static int rawOffsetAbsolute(PortablePositionReadable in, int start, int fieldOffsetSize) { int len = length(in, start); short flags = in.readShortPositioned(start + GridPortableMarshaller.FLAGS_POS); @@ -651,7 +654,7 @@ public class PortableUtils { // Schema exists. int schemaOff = in.readIntPositioned(start + GridPortableMarshaller.SCHEMA_OR_RAW_OFF_POS); - if ((((len - schemaOff) >> 2) & 0x1) == 0x0) + if (((len - schemaOff) % (4 + fieldOffsetSize)) == 0x0) // Even amount of records in schema => no raw offset. return start + schemaOff; else @@ -659,4 +662,39 @@ public class PortableUtils { return start + in.readIntPositioned(start + len - 4); } } + + /** + * Get offset size for the given flags. + * @param flags Flags. + * @return Offset size. + */ + public static int fieldOffsetSize(short flags) { + if ((flags & FLAG_OFFSET_ONE_BYTE) == FLAG_OFFSET_ONE_BYTE) + return OFFSET_1; + else if ((flags & FLAG_OFFSET_TWO_BYTES) == FLAG_OFFSET_TWO_BYTES) + return OFFSET_2; + else + return OFFSET_4; + } + + /** + * Get relative field offset. + * + * @param stream Stream. + * @param pos Position. + * @param fieldOffsetSize Field offset size. + * @return Relative field offset. + */ + public static int fieldOffsetRelative(PortablePositionReadable stream, int pos, int fieldOffsetSize) { + int res; + + if (fieldOffsetSize == PortableUtils.OFFSET_1) + res = (int)stream.readBytePositioned(pos) & 0xFF; + else if (fieldOffsetSize == PortableUtils.OFFSET_2) + res = (int)stream.readShortPositioned(pos) & 0xFFFF; + else + res = stream.readIntPositioned(pos); + + return res; + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/845c4f27/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableWriterExImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableWriterExImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableWriterExImpl.java index 227087b..ff85ecd 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableWriterExImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableWriterExImpl.java @@ -99,6 +99,12 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx /** FNV1 hash prime. */ private static final int FNV1_PRIME = 0x01000193; + /** Maximum offset which fits in 1 byte. */ + private static final int MAX_OFFSET_1 = 1 << 8; + + /** Maximum offset which fits in 2 bytes. */ + private static final int MAX_OFFSET_2 = 1 << 16; + /** Thread-local schema. */ private static final ThreadLocal<SchemaHolder> SCHEMA = new ThreadLocal<>(); @@ -342,11 +348,22 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx out.writeInt(start + SCHEMA_OR_RAW_OFF_POS, out.position() - start); // Write the schema. - schema.writeAndPop(this, fieldCnt); + int offsetByteCnt = schema.write(this, fieldCnt); // Write raw offset if needed. if (rawOffPos != 0) out.writeInt(rawOffPos - start); + + if (offsetByteCnt == PortableUtils.OFFSET_1) { + int flags = (userType ? PortableUtils.FLAG_USR_TYP : 0) | PortableUtils.FLAG_OFFSET_ONE_BYTE; + + out.writeShort(start + FLAGS_POS, (short)flags); + } + else if (offsetByteCnt == PortableUtils.OFFSET_2) { + int flags = (userType ? PortableUtils.FLAG_USR_TYP : 0) | PortableUtils.FLAG_OFFSET_TWO_BYTES; + + out.writeShort(start + FLAGS_POS, (short)flags); + } } else { // Write raw-only flag is needed. @@ -363,6 +380,17 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx } /** + * Pop schema. + */ + public void popSchema() { + if (schema != null) { + assert fieldCnt > 0; + + schema.pop(fieldCnt); + } + } + + /** * @param val Byte array. */ public void write(byte[] val) { @@ -1833,19 +1861,51 @@ public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx * Write collected frames and pop them. * * @param writer Writer. - * @param cnt Count. + * @param fieldCnt Count. + * @return Amount of bytes dedicated to */ - public void writeAndPop(PortableWriterExImpl writer, int cnt) { - int startIdx = idx - cnt * 2; + public int write(PortableWriterExImpl writer, int fieldCnt) { + int startIdx = idx - fieldCnt * 2; assert startIdx >= 0; - for (int idx0 = startIdx; idx0 < idx;) { - writer.writeInt(data[idx0++]); - writer.writeInt(data[idx0++]); + int lastOffset = data[idx - 1]; + + int res; + + if (lastOffset < MAX_OFFSET_1) { + for (int idx0 = startIdx; idx0 < idx; ) { + writer.writeInt(data[idx0++]); + writer.writeByte((byte) data[idx0++]); + } + + res = PortableUtils.OFFSET_1; } + else if (lastOffset < MAX_OFFSET_2) { + for (int idx0 = startIdx; idx0 < idx; ) { + writer.writeInt(data[idx0++]); + writer.writeShort((short)data[idx0++]); + } + + res = PortableUtils.OFFSET_2; + } + else { + for (int idx0 = startIdx; idx0 < idx; ) { + writer.writeInt(data[idx0++]); + writer.writeInt(data[idx0++]); + } - idx = startIdx; + res = PortableUtils.OFFSET_4; + } + + return res; + } + + /** + * Pop current object's frame. + */ + public void pop(int fieldCnt) { + idx = idx - fieldCnt * 2; // Shrink data array if needed. if (idx == 0 && data.length > MAX_SIZE) http://git-wip-us.apache.org/repos/asf/ignite/blob/845c4f27/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderImpl.java index 34e1d6d..608425d 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderImpl.java @@ -41,6 +41,7 @@ import java.util.Map; import java.util.Set; import static org.apache.ignite.internal.portable.GridPortableMarshaller.DFLT_HDR_LEN; +import static org.apache.ignite.internal.portable.GridPortableMarshaller.FLAGS_POS; import static org.apache.ignite.internal.portable.GridPortableMarshaller.HASH_CODE_POS; import static org.apache.ignite.internal.portable.GridPortableMarshaller.PROTO_VER_POS; import static org.apache.ignite.internal.portable.GridPortableMarshaller.TYPE_ID_POS; @@ -77,12 +78,13 @@ public class PortableBuilderImpl implements PortableBuilder { /** Position of object in source array, or -1 if object is not created from PortableObject. */ private final int start; + /** Flags. */ + private final short flags; + /** Total header length */ private final int hdrLen; - /** - * Context of PortableObject reading process. Or {@code null} if object is not created from PortableObject. - */ + /** Context of PortableObject reading process. Or {@code null} if object is not created from PortableObject. */ private final PortableBuilderReader reader; /** */ @@ -115,6 +117,7 @@ public class PortableBuilderImpl implements PortableBuilder { this.ctx = ctx; start = -1; + flags = -1; reader = null; hdrLen = DFLT_HDR_LEN; @@ -137,6 +140,7 @@ public class PortableBuilderImpl implements PortableBuilder { PortableBuilderImpl(PortableBuilderReader reader, int start) { this.reader = reader; this.start = start; + this.flags = reader.readShortPositioned(start + FLAGS_POS); byte ver = reader.readBytePositioned(start + PROTO_VER_POS); @@ -198,184 +202,188 @@ public class PortableBuilderImpl implements PortableBuilder { * @param serializer Serializer. */ void serializeTo(PortableWriterExImpl writer, PortableBuilderSerializer serializer) { - PortableUtils.writeHeader(writer, - true, - registeredType ? typeId : UNREGISTERED_TYPE_ID, - hashCode, - registeredType ? null : clsNameToWrite); + try { + PortableUtils.writeHeader(writer, + true, + registeredType ? typeId : UNREGISTERED_TYPE_ID, + hashCode, + registeredType ? null : clsNameToWrite); - Set<Integer> remainsFlds = null; + Set<Integer> remainsFlds = null; - if (reader != null) { - Map<Integer, Object> assignedFldsById; + if (reader != null) { + Map<Integer, Object> assignedFldsById; - if (assignedVals != null) { - assignedFldsById = U.newHashMap(assignedVals.size()); + if (assignedVals != null) { + assignedFldsById = U.newHashMap(assignedVals.size()); - for (Map.Entry<String, Object> entry : assignedVals.entrySet()) { - int fldId = ctx.fieldId(typeId, entry.getKey()); + for (Map.Entry<String, Object> entry : assignedVals.entrySet()) { + int fldId = ctx.fieldId(typeId, entry.getKey()); - assignedFldsById.put(fldId, entry.getValue()); - } + assignedFldsById.put(fldId, entry.getValue()); + } - remainsFlds = assignedFldsById.keySet(); - } - else - assignedFldsById = Collections.emptyMap(); + remainsFlds = assignedFldsById.keySet(); + } else + assignedFldsById = Collections.emptyMap(); - // Get footer details. - IgniteBiTuple<Integer, Integer> footer = PortableUtils.footerAbsolute(reader, start); + // Get footer details. + int fieldOffsetSize = PortableUtils.fieldOffsetSize(flags); - int footerPos = footer.get1(); - int footerEnd = footer.get2(); + IgniteBiTuple<Integer, Integer> footer = PortableUtils.footerAbsolute(reader, start, fieldOffsetSize); - // Get raw position. - int rawPos = PortableUtils.rawOffsetAbsolute(reader, start); + int footerPos = footer.get1(); + int footerEnd = footer.get2(); - // Position reader on data. - reader.position(start + hdrLen); + // Get raw position. + int rawPos = PortableUtils.rawOffsetAbsolute(reader, start, fieldOffsetSize); - while (reader.position() < rawPos) { - int fieldId = reader.readIntPositioned(footerPos); - int fieldLen = fieldPositionAndLength(footerPos, footerEnd, rawPos).get2(); + // Position reader on data. + reader.position(start + hdrLen); - footerPos += 8; + while (reader.position() + 4 < rawPos) { + int fieldId = reader.readIntPositioned(footerPos); + int fieldLen = fieldPositionAndLength(footerPos, footerEnd, rawPos, fieldOffsetSize).get2(); - if (assignedFldsById.containsKey(fieldId)) { - Object assignedVal = assignedFldsById.remove(fieldId); + footerPos += 4 + fieldOffsetSize; - reader.skip(fieldLen); + if (assignedFldsById.containsKey(fieldId)) { + Object assignedVal = assignedFldsById.remove(fieldId); - if (assignedVal != REMOVED_FIELD_MARKER) { - writer.writeFieldId(fieldId); + reader.skip(fieldLen); - serializer.writeValue(writer, assignedVal); - } - } - else { - int type = fieldLen != 0 ? reader.readByte(0) : 0; + if (assignedVal != REMOVED_FIELD_MARKER) { + writer.writeFieldId(fieldId); - if (fieldLen != 0 && !PortableUtils.isPlainArrayType(type) && PortableUtils.isPlainType(type)) { - writer.writeFieldId(fieldId); - writer.write(reader.array(), reader.position(), fieldLen); + serializer.writeValue(writer, assignedVal); + } + } else { + int type = fieldLen != 0 ? reader.readByte(0) : 0; - reader.skip(fieldLen); - } - else { - writer.writeFieldId(fieldId); + if (fieldLen != 0 && !PortableUtils.isPlainArrayType(type) && PortableUtils.isPlainType(type)) { + writer.writeFieldId(fieldId); + writer.write(reader.array(), reader.position(), fieldLen); - Object val; + reader.skip(fieldLen); + } else { + writer.writeFieldId(fieldId); - if (fieldLen == 0) - val = null; - else if (readCache == null) { - int savedPos = reader.position(); + Object val; - val = reader.parseValue(); + if (fieldLen == 0) + val = null; + else if (readCache == null) { + int savedPos = reader.position(); - assert reader.position() == savedPos + fieldLen; - } - else { - val = readCache.get(fieldId); + val = reader.parseValue(); - reader.skip(fieldLen); - } + assert reader.position() == savedPos + fieldLen; + } else { + val = readCache.get(fieldId); + + reader.skip(fieldLen); + } - serializer.writeValue(writer, val); + serializer.writeValue(writer, val); + } } } } - } - - if (assignedVals != null && (remainsFlds == null || !remainsFlds.isEmpty())) { - boolean metadataEnabled = ctx.isMetaDataEnabled(typeId); - PortableMetadata metadata = null; + if (assignedVals != null && (remainsFlds == null || !remainsFlds.isEmpty())) { + boolean metadataEnabled = ctx.isMetaDataEnabled(typeId); - if (metadataEnabled) - metadata = ctx.metaData(typeId); + PortableMetadata metadata = null; - Map<String, String> newFldsMetadata = null; + if (metadataEnabled) + metadata = ctx.metaData(typeId); - for (Map.Entry<String, Object> entry : assignedVals.entrySet()) { - Object val = entry.getValue(); + Map<String, String> newFldsMetadata = null; - if (val == REMOVED_FIELD_MARKER) - continue; - - String name = entry.getKey(); + for (Map.Entry<String, Object> entry : assignedVals.entrySet()) { + Object val = entry.getValue(); - int fldId = ctx.fieldId(typeId, name); + if (val == REMOVED_FIELD_MARKER) + continue; - if (remainsFlds != null && !remainsFlds.contains(fldId)) - continue; + String name = entry.getKey(); - writer.writeFieldId(fldId); + int fldId = ctx.fieldId(typeId, name); - serializer.writeValue(writer, val); + if (remainsFlds != null && !remainsFlds.contains(fldId)) + continue; - if (metadataEnabled) { - String oldFldTypeName = metadata == null ? null : metadata.fieldTypeName(name); + writer.writeFieldId(fldId); - String newFldTypeName; + serializer.writeValue(writer, val); - if (val instanceof PortableValueWithType) - newFldTypeName = ((PortableValueWithType)val).typeName(); - else { - byte type = PortableUtils.typeByClass(val.getClass()); + if (metadataEnabled) { + String oldFldTypeName = metadata == null ? null : metadata.fieldTypeName(name); - newFldTypeName = CacheObjectPortableProcessorImpl.fieldTypeName(type); - } + String newFldTypeName; - if (oldFldTypeName == null) { - // It's a new field, we have to add it to metadata. + if (val instanceof PortableValueWithType) + newFldTypeName = ((PortableValueWithType) val).typeName(); + else { + byte type = PortableUtils.typeByClass(val.getClass()); - if (newFldsMetadata == null) - newFldsMetadata = new HashMap<>(); + newFldTypeName = CacheObjectPortableProcessorImpl.fieldTypeName(type); + } - newFldsMetadata.put(name, newFldTypeName); - } - else { - if (!"Object".equals(oldFldTypeName) && !oldFldTypeName.equals(newFldTypeName)) { - throw new PortableException( - "Wrong value has been set [" + - "typeName=" + (typeName == null ? metadata.typeName() : typeName) + - ", fieldName=" + name + - ", fieldType=" + oldFldTypeName + - ", assignedValueType=" + newFldTypeName + - ", assignedValue=" + (((PortableValueWithType)val).value()) + ']' - ); + if (oldFldTypeName == null) { + // It's a new field, we have to add it to metadata. + + if (newFldsMetadata == null) + newFldsMetadata = new HashMap<>(); + + newFldsMetadata.put(name, newFldTypeName); + } else { + if (!"Object".equals(oldFldTypeName) && !oldFldTypeName.equals(newFldTypeName)) { + throw new PortableException( + "Wrong value has been set [" + + "typeName=" + (typeName == null ? metadata.typeName() : typeName) + + ", fieldName=" + name + + ", fieldType=" + oldFldTypeName + + ", assignedValueType=" + newFldTypeName + + ", assignedValue=" + (((PortableValueWithType) val).value()) + ']' + ); + } } } } - } - if (newFldsMetadata != null) { - String typeName = this.typeName; + if (newFldsMetadata != null) { + String typeName = this.typeName; - if (typeName == null) - typeName = metadata.typeName(); + if (typeName == null) + typeName = metadata.typeName(); - ctx.updateMetaData(typeId, typeName, newFldsMetadata); + ctx.updateMetaData(typeId, typeName, newFldsMetadata); + } } - } - if (reader != null) { - // Write raw data if any. - int rawOff = PortableUtils.rawOffsetAbsolute(reader, start); - int footerStart = PortableUtils.footerStartAbsolute(reader, start); + if (reader != null) { + // Write raw data if any. + int fieldOffsetSize = PortableUtils.fieldOffsetSize(flags); + + int rawOff = PortableUtils.rawOffsetAbsolute(reader, start, fieldOffsetSize); + int footerStart = PortableUtils.footerStartAbsolute(reader, start); - if (rawOff < footerStart) { - writer.rawWriter(); + if (rawOff < footerStart) { + writer.rawWriter(); - writer.write(reader.array(), rawOff, footerStart - rawOff); + writer.write(reader.array(), rawOff, footerStart - rawOff); + } + + // Shift reader to the end of the object. + reader.position(start + PortableUtils.length(reader, start)); } - // Shift reader to the end of the object. - reader.position(start + PortableUtils.length(reader, start)); + writer.postWrite(true); + } + finally { + writer.popSchema(); } - - writer.postWrite(true); } /** {@inheritDoc} */ @@ -391,21 +399,25 @@ public class PortableBuilderImpl implements PortableBuilder { * @param footerPos Field position inside the footer (absolute). * @param footerEnd Footer end (absolute). * @param rawPos Raw data position (absolute). + * @param fieldOffsetSize Size of field's offset. * @return Tuple with field position and length. */ - private IgniteBiTuple<Integer, Integer> fieldPositionAndLength(int footerPos, int footerEnd, int rawPos) { - int fieldOffset = reader.readIntPositioned(footerPos + 4); + private IgniteBiTuple<Integer, Integer> fieldPositionAndLength(int footerPos, int footerEnd, int rawPos, + int fieldOffsetSize) { + // Get field offset first. + int fieldOffset = PortableUtils.fieldOffsetRelative(reader, footerPos + 4, fieldOffsetSize); int fieldPos = start + fieldOffset; // Get field length. int fieldLen; - if (footerPos + 8 == footerEnd) + if (footerPos + 4 + fieldOffsetSize == footerEnd) // This is the last field, compare to raw offset. fieldLen = rawPos - fieldPos; else { // Field is somewhere in the middle, get difference with the next offset. - int nextFieldOffset = reader.readIntPositioned(footerPos + 8 + 4); + int nextFieldOffset = PortableUtils.fieldOffsetRelative(reader, footerPos + 4 + fieldOffsetSize + 4, + fieldOffsetSize); fieldLen = nextFieldOffset - fieldOffset; } @@ -418,26 +430,29 @@ public class PortableBuilderImpl implements PortableBuilder { */ private void ensureReadCacheInit() { if (readCache == null) { + int fieldOffsetSize = PortableUtils.fieldOffsetSize(flags); + Map<Integer, Object> readCache = new HashMap<>(); - IgniteBiTuple<Integer, Integer> footer = PortableUtils.footerAbsolute(reader, start); + IgniteBiTuple<Integer, Integer> footer = PortableUtils.footerAbsolute(reader, start, fieldOffsetSize); int footerPos = footer.get1(); int footerEnd = footer.get2(); - int rawPos = PortableUtils.rawOffsetAbsolute(reader, start); + int rawPos = PortableUtils.rawOffsetAbsolute(reader, start, fieldOffsetSize); - while (footerPos < footerEnd) { + while (footerPos + 4 < footerEnd) { int fieldId = reader.readIntPositioned(footerPos); - IgniteBiTuple<Integer, Integer> posAndLen = fieldPositionAndLength(footerPos, footerEnd, rawPos); + IgniteBiTuple<Integer, Integer> posAndLen = + fieldPositionAndLength(footerPos, footerEnd, rawPos, fieldOffsetSize); Object val = reader.getValueQuickly(posAndLen.get1(), posAndLen.get2()); readCache.put(fieldId, val); // Shift current footer position. - footerPos += 8; + footerPos += 4 + fieldOffsetSize; } this.readCache = readCache; http://git-wip-us.apache.org/repos/asf/ignite/blob/845c4f27/modules/platforms/cpp/core-test/src/portable_reader_writer_test.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core-test/src/portable_reader_writer_test.cpp b/modules/platforms/cpp/core-test/src/portable_reader_writer_test.cpp index baeb9e7..3ec5a15 100644 --- a/modules/platforms/cpp/core-test/src/portable_reader_writer_test.cpp +++ b/modules/platforms/cpp/core-test/src/portable_reader_writer_test.cpp @@ -68,9 +68,9 @@ void CheckPrimitive(T val) in.Synchronize(); int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); - int32_t footerEnd = footerBegin + 8; + int32_t footerEnd = footerBegin + 5; - PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd); + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd, OFFSET_TYPE_1_BYTE); PortableReader reader(&readerImpl); try @@ -148,9 +148,9 @@ void CheckPrimitiveArray(T dflt, T val1, T val2) in.Synchronize(); int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); - int32_t footerEnd = footerBegin + 8; + int32_t footerEnd = footerBegin + 5; - PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd); + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd, OFFSET_TYPE_1_BYTE); PortableReader reader(&readerImpl); in.Position(IGNITE_DFLT_HDR_LEN); @@ -181,9 +181,9 @@ void CheckPrimitiveArray(T dflt, T val1, T val2) in.Synchronize(); int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); - int32_t footerEnd = footerBegin + 8; + int32_t footerEnd = footerBegin + 5; - PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd); + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd, OFFSET_TYPE_1_BYTE); PortableReader reader(&readerImpl); in.Position(IGNITE_DFLT_HDR_LEN); @@ -218,9 +218,9 @@ void CheckPrimitiveArray(T dflt, T val1, T val2) in.Synchronize(); int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); - int32_t footerEnd = footerBegin + 8; + int32_t footerEnd = footerBegin + 5; - PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd); + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd, OFFSET_TYPE_1_BYTE); PortableReader reader(&readerImpl); in.Position(IGNITE_DFLT_HDR_LEN); @@ -258,9 +258,9 @@ void CheckPrimitiveArray(T dflt, T val1, T val2) in.Synchronize(); int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); - int32_t footerEnd = footerBegin + 8; + int32_t footerEnd = footerBegin + 5; - PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd); + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd, OFFSET_TYPE_1_BYTE); PortableReader reader(&readerImpl); in.Position(IGNITE_DFLT_HDR_LEN); @@ -510,9 +510,9 @@ void CheckCollectionEmpty(CollectionType* colType) InteropInputStream in(&mem); int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); - int32_t footerEnd = footerBegin + 8 * 2; + int32_t footerEnd = footerBegin + 5 * 2; - PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd); + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd, OFFSET_TYPE_1_BYTE); PortableReader reader(&readerImpl); in.Position(IGNITE_DFLT_HDR_LEN); @@ -600,9 +600,9 @@ void CheckCollection(CollectionType* colType) InteropInputStream in(&mem); int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); - int32_t footerEnd = footerBegin + 8 * 2; + int32_t footerEnd = footerBegin + 5 * 2; - PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd); + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd, OFFSET_TYPE_1_BYTE); PortableReader reader(&readerImpl); in.Position(IGNITE_DFLT_HDR_LEN); @@ -677,9 +677,9 @@ void CheckCollectionIterators(CollectionType* colType) InteropInputStream in(&mem); int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); - int32_t footerEnd = footerBegin + 8 * 2; + int32_t footerEnd = footerBegin + 5 * 2; - PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd); + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd, OFFSET_TYPE_1_BYTE); PortableReader reader(&readerImpl); in.Position(IGNITE_DFLT_HDR_LEN); @@ -753,9 +753,9 @@ void CheckMapEmpty(MapType* mapType) InteropInputStream in(&mem); int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); - int32_t footerEnd = footerBegin + 8 * 2; + int32_t footerEnd = footerBegin + 5 * 2; - PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd); + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd, OFFSET_TYPE_1_BYTE); PortableReader reader(&readerImpl); in.Position(IGNITE_DFLT_HDR_LEN); @@ -846,9 +846,9 @@ void CheckMap(MapType* mapType) InteropInputStream in(&mem); int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); - int32_t footerEnd = footerBegin + 8 * 2; + int32_t footerEnd = footerBegin + 5 * 2; - PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd); + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd, OFFSET_TYPE_1_BYTE); PortableReader reader(&readerImpl); in.Position(IGNITE_DFLT_HDR_LEN); @@ -1028,9 +1028,9 @@ BOOST_AUTO_TEST_CASE(TestGuidNull) InteropInputStream in(&mem); int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); - int32_t footerEnd = footerBegin + 8; + int32_t footerEnd = footerBegin + 5; - PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd); + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd, OFFSET_TYPE_1_BYTE); PortableReader reader(&readerImpl); in.Position(IGNITE_DFLT_HDR_LEN); @@ -1113,9 +1113,9 @@ BOOST_AUTO_TEST_CASE(TestString) { InteropInputStream in(&mem); int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); - int32_t footerEnd = footerBegin + 8 * 5; + int32_t footerEnd = footerBegin + 5 * 5; - PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd); + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd, OFFSET_TYPE_1_BYTE); PortableReader reader(&readerImpl); in.Position(IGNITE_DFLT_HDR_LEN); @@ -1191,9 +1191,9 @@ BOOST_AUTO_TEST_CASE(TestStringArrayNull) InteropInputStream in(&mem); int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); - int32_t footerEnd = footerBegin + 8 * 2; + int32_t footerEnd = footerBegin + 5 * 2; - PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd); + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd, OFFSET_TYPE_1_BYTE); PortableReader reader(&readerImpl); in.Position(IGNITE_DFLT_HDR_LEN); @@ -1308,9 +1308,9 @@ BOOST_AUTO_TEST_CASE(TestStringArrayEmpty) InteropInputStream in(&mem); int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); - int32_t footerEnd = footerBegin + 8 * 2; + int32_t footerEnd = footerBegin + 5 * 2; - PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd); + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd, OFFSET_TYPE_1_BYTE); PortableReader reader(&readerImpl); in.Position(IGNITE_DFLT_HDR_LEN); @@ -1435,9 +1435,9 @@ BOOST_AUTO_TEST_CASE(TestStringArray) InteropInputStream in(&mem); int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); - int32_t footerEnd = footerBegin + 8 * 2; + int32_t footerEnd = footerBegin + 5 * 2; - PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd); + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd, OFFSET_TYPE_1_BYTE); PortableReader reader(&readerImpl); in.Position(IGNITE_DFLT_HDR_LEN); @@ -1549,14 +1549,15 @@ BOOST_AUTO_TEST_CASE(TestObject) InteropInputStream in(&mem); int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); - int32_t footerEnd = footerBegin + 8 * 3; + int32_t footerEnd = footerBegin + 5 * 3; - PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd); + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd, OFFSET_TYPE_1_BYTE); PortableReader reader(&readerImpl); in.Position(IGNITE_DFLT_HDR_LEN); PortableInner readVal1 = reader.ReadObject<PortableInner>("field1"); + BOOST_REQUIRE(writeVal1.GetValue() == readVal1.GetValue()); PortableInner readVal2 = reader.ReadObject<PortableInner>("field2"); @@ -1592,9 +1593,9 @@ BOOST_AUTO_TEST_CASE(TestNestedObject) InteropInputStream in(&mem); int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); - int32_t footerEnd = footerBegin + 8 * 3; + int32_t footerEnd = footerBegin + 5 * 3; - PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd); + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd, OFFSET_TYPE_1_BYTE); PortableReader reader(&readerImpl); in.Position(IGNITE_DFLT_HDR_LEN); @@ -1634,9 +1635,9 @@ BOOST_AUTO_TEST_CASE(TestArrayNull) InteropInputStream in(&mem); int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); - int32_t footerEnd = footerBegin + 8 * 2; + int32_t footerEnd = footerBegin + 5 * 2; - PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd); + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd, OFFSET_TYPE_1_BYTE); PortableReader reader(&readerImpl); in.Position(IGNITE_DFLT_HDR_LEN); @@ -1710,9 +1711,9 @@ BOOST_AUTO_TEST_CASE(TestArrayEmpty) InteropInputStream in(&mem); int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); - int32_t footerEnd = footerBegin + 8 * 2; + int32_t footerEnd = footerBegin + 5 * 2; - PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd); + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd, OFFSET_TYPE_1_BYTE); PortableReader reader(&readerImpl); in.Position(IGNITE_DFLT_HDR_LEN); @@ -1794,9 +1795,9 @@ BOOST_AUTO_TEST_CASE(TestArray) InteropInputStream in(&mem); int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); - int32_t footerEnd = footerBegin + 8 * 2; + int32_t footerEnd = footerBegin + 5 * 2; - PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd); + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd, OFFSET_TYPE_1_BYTE); PortableReader reader(&readerImpl); in.Position(IGNITE_DFLT_HDR_LEN); @@ -1855,9 +1856,9 @@ BOOST_AUTO_TEST_CASE(TestCollectionNull) InteropInputStream in(&mem); int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); - int32_t footerEnd = footerBegin + 8 * 2; + int32_t footerEnd = footerBegin + 5 * 2; - PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd); + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd, OFFSET_TYPE_1_BYTE); PortableReader reader(&readerImpl); in.Position(IGNITE_DFLT_HDR_LEN); @@ -1941,9 +1942,9 @@ BOOST_AUTO_TEST_CASE(TestMapNull) InteropInputStream in(&mem); int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); - int32_t footerEnd = footerBegin + 8 * 2; + int32_t footerEnd = footerBegin + 5 * 2; - PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd); + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd, OFFSET_TYPE_1_BYTE); PortableReader reader(&readerImpl); in.Position(IGNITE_DFLT_HDR_LEN); @@ -2034,7 +2035,7 @@ BOOST_AUTO_TEST_CASE(TestRawMode) int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); int32_t footerEnd = footerBegin; - PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 1000, footerBegin, footerBegin, footerEnd); + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 1000, footerBegin, footerBegin, footerEnd, OFFSET_TYPE_1_BYTE); PortableReader reader(&readerImpl); in.Position(IGNITE_DFLT_HDR_LEN); @@ -2111,7 +2112,7 @@ BOOST_AUTO_TEST_CASE(TestFieldSeek) PortableReaderImpl readerImpl(&in, &idRslvr, pos, usrType, typeId, hashCode, len, rawOff, - footerBegin, footerEnd); + footerBegin, footerEnd, OFFSET_TYPE_1_BYTE); PortableReader reader(&readerImpl); @@ -2211,4 +2212,162 @@ BOOST_AUTO_TEST_CASE(TestFieldSeek) BOOST_REQUIRE(mapReader.IsNull()); } +BOOST_AUTO_TEST_CASE(TestSchemaOffset2ByteFields) +{ + const int fieldsNum = 64; + + TemplatedPortableIdResolver<PortableDummy> idRslvr; + + InteropUnpooledMemory mem(4096); + + InteropOutputStream out(&mem); + PortableWriterImpl writerImpl(&out, &idRslvr, NULL, NULL, 0); + PortableWriter writer(&writerImpl); + + out.Position(IGNITE_DFLT_HDR_LEN); + + for (int i = 0; i < fieldsNum; ++i) + { + std::stringstream tmp; + tmp << "field" << i; + + writer.WriteInt32(tmp.str().c_str(), i * 10); + } + + writerImpl.PostWrite(); + + out.Synchronize(); + + InteropInputStream in(&mem); + + int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); + int32_t footerEnd = footerBegin + 6 * fieldsNum; + + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd, OFFSET_TYPE_2_BYTE); + PortableReader reader(&readerImpl); + + in.Position(IGNITE_DFLT_HDR_LEN); + + for (int i = 0; i < fieldsNum; ++i) + { + std::stringstream tmp; + tmp << "field" << i; + + BOOST_REQUIRE(reader.ReadInt32(tmp.str().c_str()) == i * 10); + } +} + +BOOST_AUTO_TEST_CASE(TestSchemaOffset4ByteFields) +{ + const int fieldsNum = 0x10000 / 4; + + TemplatedPortableIdResolver<PortableDummy> idRslvr; + + InteropUnpooledMemory mem(1024 * 1024); + + InteropOutputStream out(&mem); + PortableWriterImpl writerImpl(&out, &idRslvr, NULL, NULL, 0); + PortableWriter writer(&writerImpl); + + out.Position(IGNITE_DFLT_HDR_LEN); + + for (int i = 0; i < fieldsNum; ++i) + { + std::stringstream tmp; + tmp << "field" << i; + + writer.WriteInt32(tmp.str().c_str(), i * 10); + } + + writerImpl.PostWrite(); + + out.Synchronize(); + + InteropInputStream in(&mem); + + int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); + int32_t footerEnd = footerBegin + 8 * fieldsNum; + + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd, OFFSET_TYPE_4_BYTE); + PortableReader reader(&readerImpl); + + in.Position(IGNITE_DFLT_HDR_LEN); + + for (int i = 0; i < fieldsNum; ++i) + { + std::stringstream tmp; + tmp << "field" << i; + + BOOST_REQUIRE(reader.ReadInt32(tmp.str().c_str()) == i * 10); + } +} + +BOOST_AUTO_TEST_CASE(TestSchemaOffset2ByteArray) +{ + TemplatedPortableIdResolver<PortableDummy> idRslvr; + + InteropUnpooledMemory mem(4096); + + InteropOutputStream out(&mem); + PortableWriterImpl writerImpl(&out, &idRslvr, NULL, NULL, 0); + PortableWriter writer(&writerImpl); + + out.Position(IGNITE_DFLT_HDR_LEN); + + int8_t dummyArray[256] = {}; + + writer.WriteInt8Array("field1", dummyArray, sizeof(dummyArray)); + writer.WriteInt32("field2", 42); + + writerImpl.PostWrite(); + + out.Synchronize(); + + InteropInputStream in(&mem); + + int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); + int32_t footerEnd = footerBegin + 6 * 2; + + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd, OFFSET_TYPE_2_BYTE); + PortableReader reader(&readerImpl); + + in.Position(IGNITE_DFLT_HDR_LEN); + + BOOST_REQUIRE(reader.ReadInt32("field2") == 42); +} + +BOOST_AUTO_TEST_CASE(TestSchemaOffset4ByteArray) +{ + TemplatedPortableIdResolver<PortableDummy> idRslvr; + + InteropUnpooledMemory mem(1024 * 1024); + + InteropOutputStream out(&mem); + PortableWriterImpl writerImpl(&out, &idRslvr, NULL, NULL, 0); + PortableWriter writer(&writerImpl); + + out.Position(IGNITE_DFLT_HDR_LEN); + + int8_t dummyArray[0x10000] = {}; + + writer.WriteInt8Array("field1", dummyArray, sizeof(dummyArray)); + writer.WriteInt32("field2", 42); + + writerImpl.PostWrite(); + + out.Synchronize(); + + InteropInputStream in(&mem); + + int32_t footerBegin = in.ReadInt32(IGNITE_OFFSET_SCHEMA_OR_RAW_OFF); + int32_t footerEnd = footerBegin + 8 * 2; + + PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100, footerBegin, footerEnd, OFFSET_TYPE_4_BYTE); + PortableReader reader(&readerImpl); + + in.Position(IGNITE_DFLT_HDR_LEN); + + BOOST_REQUIRE(reader.ReadInt32("field2") == 42); +} + BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/845c4f27/modules/platforms/cpp/core/include/ignite/impl/interop/interop_input_stream.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/impl/interop/interop_input_stream.h b/modules/platforms/cpp/core/include/ignite/impl/interop/interop_input_stream.h index f23cec6..6842990 100644 --- a/modules/platforms/cpp/core/include/ignite/impl/interop/interop_input_stream.h +++ b/modules/platforms/cpp/core/include/ignite/impl/interop/interop_input_stream.h @@ -44,6 +44,14 @@ namespace ignite * @return Value. */ int8_t ReadInt8(); + + /** + * Read signed 8-byte int at the given position. + * + * @param pos Position. + * @return Value. + */ + int32_t ReadInt8(int32_t pos); /** * Read signed 8-byte int array. @@ -76,6 +84,14 @@ namespace ignite int16_t ReadInt16(); /** + * Read signed 16-byte int at the given position. + * + * @param pos Position. + * @return Value. + */ + int32_t ReadInt16(int32_t pos); + + /** * Read signed 16-byte int array. * * @param res Allocated array. http://git-wip-us.apache.org/repos/asf/ignite/blob/845c4f27/modules/platforms/cpp/core/include/ignite/impl/interop/interop_output_stream.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/impl/interop/interop_output_stream.h b/modules/platforms/cpp/core/include/ignite/impl/interop/interop_output_stream.h index 211ac6d..0814c01 100644 --- a/modules/platforms/cpp/core/include/ignite/impl/interop/interop_output_stream.h +++ b/modules/platforms/cpp/core/include/ignite/impl/interop/interop_output_stream.h @@ -83,6 +83,14 @@ namespace ignite void WriteInt16(const int16_t val); /** + * Write signed 16-byte integer at the given position. + * + * @param pos Position. + * @param val Value. + */ + void WriteInt16(const int32_t pos, const int16_t val); + + /** * Write signed 16-byte integer array. * * @param val Value. http://git-wip-us.apache.org/repos/asf/ignite/blob/845c4f27/modules/platforms/cpp/core/include/ignite/impl/portable/portable_common.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/impl/portable/portable_common.h b/modules/platforms/cpp/core/include/ignite/impl/portable/portable_common.h index c6dad50..f08c49b 100644 --- a/modules/platforms/cpp/core/include/ignite/impl/portable/portable_common.h +++ b/modules/platforms/cpp/core/include/ignite/impl/portable/portable_common.h @@ -169,6 +169,12 @@ namespace ignite /** Raw only flag. */ const int16_t IGNITE_PORTABLE_FLAG_RAW_ONLY = 0x0002; + + /** Flag indicating that schema field offset is one byte long. */ + const int16_t IGNITE_PORTABLE_FLAG_OFFSET_1_BYTE = 0x0004; + + /** Flag indicating that schema field offset is two byte long. */ + const int16_t IGNITE_PORTABLE_FLAG_OFFSET_2_BYTE = 0x0008; } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/845c4f27/modules/platforms/cpp/core/include/ignite/impl/portable/portable_reader_impl.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/impl/portable/portable_reader_impl.h b/modules/platforms/cpp/core/include/ignite/impl/portable/portable_reader_impl.h index fe25c87..4762fff 100644 --- a/modules/platforms/cpp/core/include/ignite/impl/portable/portable_reader_impl.h +++ b/modules/platforms/cpp/core/include/ignite/impl/portable/portable_reader_impl.h @@ -59,7 +59,7 @@ namespace ignite */ PortableReaderImpl(interop::InteropInputStream* stream, PortableIdResolver* idRslvr, int32_t pos, bool usrType, int32_t typeId, int32_t hashCode, int32_t len, int32_t rawOff, - int32_t footerBegin, int32_t footerEnd); + int32_t footerBegin, int32_t footerEnd, PortableOffsetType schemaType); /** * Constructor used to construct light-weight reader allowing only raw operations @@ -788,7 +788,27 @@ namespace ignite else footerBegin = schemaOrRawOff; - int32_t trailingBytes = (len - footerBegin) % 8; + PortableOffsetType schemaType; + int32_t trailingBytes; + + if (flags & IGNITE_PORTABLE_FLAG_OFFSET_1_BYTE) + { + schemaType = OFFSET_TYPE_1_BYTE; + + trailingBytes = (len - footerBegin) % 5; + } + else if (flags & IGNITE_PORTABLE_FLAG_OFFSET_2_BYTE) + { + schemaType = OFFSET_TYPE_2_BYTE; + + trailingBytes = (len - footerBegin) % 6; + } + else + { + schemaType = OFFSET_TYPE_4_BYTE; + + trailingBytes = (len - footerBegin) % 8; + } int32_t footerEnd = len - trailingBytes; @@ -806,7 +826,7 @@ namespace ignite TemplatedPortableIdResolver<T> idRslvr(type); PortableReaderImpl readerImpl(stream, &idRslvr, pos, usrType, typeId, hashCode, len, rawOff, - footerBegin, footerEnd); + footerBegin, footerEnd, schemaType); ignite::portable::PortableReader reader(&readerImpl); T val = type.Read(reader); @@ -887,6 +907,9 @@ namespace ignite /** Footer ending position. */ int32_t footerEnd; + /** Object schema type. */ + PortableOffsetType schemaType; + IGNITE_NO_COPY_ASSIGNMENT(PortableReaderImpl) /** http://git-wip-us.apache.org/repos/asf/ignite/blob/845c4f27/modules/platforms/cpp/core/include/ignite/impl/portable/portable_schema.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/impl/portable/portable_schema.h b/modules/platforms/cpp/core/include/ignite/impl/portable/portable_schema.h index 1795fd1..4919e2a 100644 --- a/modules/platforms/cpp/core/include/ignite/impl/portable/portable_schema.h +++ b/modules/platforms/cpp/core/include/ignite/impl/portable/portable_schema.h @@ -34,6 +34,21 @@ namespace ignite class PortableWriterImpl; /** + * Schema size variants. + */ + enum PortableOffsetType + { + /** Means all field offsets can be fit in one byte. */ + OFFSET_TYPE_1_BYTE, + + /** Means all field offsets can be fit in two bytes. */ + OFFSET_TYPE_2_BYTE, + + /** Means field offsets should be stored in four bytes. */ + OFFSET_TYPE_4_BYTE + }; + + /** * Portable schema. */ class IGNITE_IMPORT_EXPORT PortableSchema @@ -86,10 +101,17 @@ namespace ignite */ void Clear(); + /** + * Get type of schema. + * + * @return Type of schema. + */ + PortableOffsetType GetType() const; + private: /** - * Single schema field info. - */ + * Single schema field info. + */ struct PortableSchemaFieldInfo { int32_t id; http://git-wip-us.apache.org/repos/asf/ignite/blob/845c4f27/modules/platforms/cpp/core/src/impl/interop/interop_input_stream.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/src/impl/interop/interop_input_stream.cpp b/modules/platforms/cpp/core/src/impl/interop/interop_input_stream.cpp index 02e894c..fed7871 100644 --- a/modules/platforms/cpp/core/src/impl/interop/interop_input_stream.cpp +++ b/modules/platforms/cpp/core/src/impl/interop/interop_input_stream.cpp @@ -69,6 +69,16 @@ namespace ignite IGNITE_INTEROP_IN_READ(int8_t, 1); } + int32_t InteropInputStream::ReadInt8(int32_t pos) + { + int delta = pos + 1 - this->pos; + + if (delta > 0) + EnsureEnoughData(delta); + + return *reinterpret_cast<int8_t*>(data + pos); + } + void InteropInputStream::ReadInt8Array(int8_t* const res, const int32_t len) { IGNITE_INTEROP_IN_READ_ARRAY(len, 0); @@ -90,6 +100,16 @@ namespace ignite IGNITE_INTEROP_IN_READ(int16_t, 2); } + int32_t InteropInputStream::ReadInt16(int32_t pos) + { + int delta = pos + 2 - this->pos; + + if (delta > 0) + EnsureEnoughData(delta); + + return *reinterpret_cast<int16_t*>(data + pos); + } + void InteropInputStream::ReadInt16Array(int16_t* const res, const int32_t len) { IGNITE_INTEROP_IN_READ_ARRAY(len, 1); http://git-wip-us.apache.org/repos/asf/ignite/blob/845c4f27/modules/platforms/cpp/core/src/impl/interop/interop_output_stream.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/src/impl/interop/interop_output_stream.cpp b/modules/platforms/cpp/core/src/impl/interop/interop_output_stream.cpp index 1fd400b..acfd3ec 100644 --- a/modules/platforms/cpp/core/src/impl/interop/interop_output_stream.cpp +++ b/modules/platforms/cpp/core/src/impl/interop/interop_output_stream.cpp @@ -96,6 +96,13 @@ namespace ignite IGNITE_INTEROP_OUT_WRITE(val, int16_t, 2); } + void InteropOutputStream::WriteInt16(const int32_t pos, const int16_t val) + { + EnsureCapacity(pos + 2); + + *reinterpret_cast<int16_t*>(data + pos) = val; + } + void InteropOutputStream::WriteInt16Array(const int16_t* val, const int32_t len) { IGNITE_INTEROP_OUT_WRITE_ARRAY(val, len << 1); http://git-wip-us.apache.org/repos/asf/ignite/blob/845c4f27/modules/platforms/cpp/core/src/impl/portable/portable_reader_impl.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/src/impl/portable/portable_reader_impl.cpp b/modules/platforms/cpp/core/src/impl/portable/portable_reader_impl.cpp index 96378e0..fd2cc18 100644 --- a/modules/platforms/cpp/core/src/impl/portable/portable_reader_impl.cpp +++ b/modules/platforms/cpp/core/src/impl/portable/portable_reader_impl.cpp @@ -36,10 +36,10 @@ namespace ignite { PortableReaderImpl::PortableReaderImpl(InteropInputStream* stream, PortableIdResolver* idRslvr, int32_t pos, bool usrType, int32_t typeId, int32_t hashCode, int32_t len, int32_t rawOff, - int32_t footerBegin, int32_t footerEnd) : + int32_t footerBegin, int32_t footerEnd, PortableOffsetType schemaType) : stream(stream), idRslvr(idRslvr), pos(pos), usrType(usrType), typeId(typeId), hashCode(hashCode), len(len), rawOff(rawOff), rawMode(false), elemIdGen(0), elemId(0), - elemCnt(-1), elemRead(0), footerBegin(footerBegin), footerEnd(footerEnd) + elemCnt(-1), elemRead(0), footerBegin(footerBegin), footerEnd(footerEnd), schemaType(schemaType) { // No-op. } @@ -47,7 +47,7 @@ namespace ignite PortableReaderImpl::PortableReaderImpl(InteropInputStream* stream) : stream(stream), idRslvr(NULL), pos(0), usrType(false), typeId(0), hashCode(0), len(0), rawOff(0), rawMode(true), elemIdGen(0), elemId(0), elemCnt(-1), elemRead(0), footerBegin(-1), - footerEnd(-1) + footerEnd(-1), schemaType(OFFSET_TYPE_4_BYTE) { // No-op. } @@ -648,12 +648,43 @@ namespace ignite stream->Position(footerBegin); - for (int32_t schemaPos = footerBegin; schemaPos < footerEnd; schemaPos += 8) + switch (schemaType) { - int32_t currentFieldId = stream->ReadInt32(schemaPos); + case OFFSET_TYPE_1_BYTE: + { + for (int32_t schemaPos = footerBegin; schemaPos < footerEnd; schemaPos += 5) + { + int32_t currentFieldId = stream->ReadInt32(schemaPos); + + if (fieldId == currentFieldId) + return static_cast<uint8_t>(stream->ReadInt8(schemaPos + 4)) + pos; + } + break; + } + + case OFFSET_TYPE_2_BYTE: + { + for (int32_t schemaPos = footerBegin; schemaPos < footerEnd; schemaPos += 6) + { + int32_t currentFieldId = stream->ReadInt32(schemaPos); - if (fieldId == currentFieldId) - return stream->ReadInt32(schemaPos + 4) + pos; + if (fieldId == currentFieldId) + return static_cast<uint16_t>(stream->ReadInt16(schemaPos + 4)) + pos; + } + break; + } + + case OFFSET_TYPE_4_BYTE: + { + for (int32_t schemaPos = footerBegin; schemaPos < footerEnd; schemaPos += 8) + { + int32_t currentFieldId = stream->ReadInt32(schemaPos); + + if (fieldId == currentFieldId) + return stream->ReadInt32(schemaPos + 4) + pos; + } + break; + } } return -1;
