You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2015/12/11 10:58:32 UTC
[3/3] ignite git commit: Merge branch 'ignite-2064-4' into ignite-1.5
Merge branch 'ignite-2064-4' into ignite-1.5
2
(cherry picked from commit 599d2edc6c4f3ce60654a53bb431d36db982bc87)
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/0ac39c97
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/0ac39c97
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/0ac39c97
Branch: refs/heads/ignite-1.5
Commit: 0ac39c976116b655304699d2477f207802cb5f8e
Parents: 1dbf20e 599d2ed
Author: Anton Vinogradov <av...@apache.org>
Authored: Fri Dec 11 12:54:50 2015 +0300
Committer: Anton Vinogradov <av...@apache.org>
Committed: Fri Dec 11 12:54:50 2015 +0300
----------------------------------------------------------------------
.../org/apache/ignite/internal/binary/BinaryObjectImpl.java | 1 -
.../ignite/internal/binary/BinaryObjectOffheapImpl.java | 6 ++++--
.../internal/binary/builder/BinaryObjectBuilderImpl.java | 3 +--
.../ignite/internal/binary/builder/PortableBuilderEnum.java | 3 +--
.../ignite/internal/binary/builder/PortableBuilderReader.java | 5 +++--
.../internal/binary/builder/PortableEnumArrayLazyValue.java | 3 +--
.../internal/binary/builder/PortableObjectArrayLazyValue.java | 3 +--
.../internal/processors/platform/PlatformContextImpl.java | 7 +++++--
.../context/IgniteCacheAbstractExecutionContextTest.java | 3 ---
9 files changed, 16 insertions(+), 18 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/0ac39c97/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
index a23330e,0000000..18adbc1
mode 100644,000000..100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
@@@ -1,570 -1,0 +1,569 @@@
+/*
+ * 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.binary;
+
+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.binary.BinaryObject;
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.binary.BinaryType;
+import org.apache.ignite.internal.GridDirectTransient;
+import org.apache.ignite.internal.IgniteCodeGeneratingFail;
+import org.apache.ignite.internal.binary.streams.PortableHeapInputStream;
+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.binary.CacheObjectBinaryProcessorImpl;
+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;
+import org.jetbrains.annotations.Nullable;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+/**
+ * Portable object implementation.
+ */
+@IgniteCodeGeneratingFail // Fields arr and start should not be generated by MessageCodeGenerator.
+public final class BinaryObjectImpl extends BinaryObjectExImpl implements Externalizable, KeyCacheObject {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** */
+ @GridDirectTransient
+ private PortableContext ctx;
+
+ /** */
+ private byte[] arr;
+
+ /** */
+ private int start;
+
+ /** */
+ @GridDirectTransient
+ private Object obj;
+
+ /** */
+ @GridDirectTransient
+ private boolean detachAllowed;
+
+ /**
+ * For {@link Externalizable}.
+ */
+ public BinaryObjectImpl() {
+ // No-op.
+ }
+
+ /**
+ * @param ctx Context.
+ * @param arr Array.
+ * @param start Start.
+ */
+ public BinaryObjectImpl(PortableContext ctx, byte[] arr, int start) {
+ assert ctx != null;
+ assert arr != null;
+
+ this.ctx = ctx;
+ this.arr = arr;
+ this.start = start;
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte cacheObjectType() {
+ return TYPE_BINARY;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean isPlatformType() {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean internal() {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Nullable @Override public <T> T value(CacheObjectContext ctx, boolean cpy) {
+ Object obj0 = obj;
+
+ if (obj0 == null || (cpy && needCopy(ctx)))
+ obj0 = deserializeValue(ctx);
+
+ return (T)obj0;
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte[] valueBytes(CacheObjectContext ctx) throws IgniteCheckedException {
+ if (detached())
+ return array();
+
+ int len = length();
+
+ byte[] arr0 = new byte[len];
+
+ U.arrayCopy(arr, start, arr0, 0, len);
+
+ return arr0;
+ }
+
+ /** {@inheritDoc} */
+ @Override public CacheObject prepareForCache(CacheObjectContext ctx) {
+ if (detached())
+ return this;
+
+ return (BinaryObjectImpl)detach();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void finishUnmarshal(CacheObjectContext ctx, ClassLoader ldr) throws IgniteCheckedException {
+ this.ctx = ((CacheObjectBinaryProcessorImpl)ctx.processor()).portableContext();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void prepareMarshal(CacheObjectContext ctx) throws IgniteCheckedException {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public int length() {
+ return PortablePrimitives.readInt(arr, start + GridPortableMarshaller.TOTAL_LEN_POS);
+ }
+
+ /**
+ * @return Detached portable object.
+ */
+ public BinaryObject detach() {
+ if (!detachAllowed || detached())
+ return this;
+
+ int len = length();
+
+ byte[] arr0 = new byte[len];
+
+ U.arrayCopy(arr, start, arr0, 0, len);
+
+ return new BinaryObjectImpl(ctx, arr0, 0);
+ }
+
+ /**
+ * @return Detached or not.
+ */
+ public boolean detached() {
+ return start == 0 && length() == arr.length;
+ }
+
+ /**
+ * @param detachAllowed Detach allowed flag.
+ */
+ public void detachAllowed(boolean detachAllowed) {
+ this.detachAllowed = detachAllowed;
+ }
+
+ /**
+ * @return Context.
+ */
+ public PortableContext context() {
+ return ctx;
+ }
+
+ /**
+ * @param ctx Context.
+ */
+ public void context(PortableContext ctx) {
+ this.ctx = ctx;
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte[] array() {
+ return arr;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int start() {
+ return start;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long offheapAddress() {
+ return 0;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected boolean hasArray() {
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int typeId() {
+ return PortablePrimitives.readInt(arr, start + GridPortableMarshaller.TYPE_ID_POS);
+ }
+
+ /** {@inheritDoc} */
+ @Nullable @Override public BinaryType type() throws BinaryObjectException {
+ if (ctx == null)
+ throw new BinaryObjectException("PortableContext is not set for the object.");
+
+ return ctx.metadata(typeId());
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Nullable @Override public <F> F field(String fieldName) throws BinaryObjectException {
+ return (F) reader(null).unmarshalField(fieldName);
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Nullable @Override public <F> F field(int fieldId) throws BinaryObjectException {
+ return (F) reader(null).unmarshalField(fieldId);
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @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);
+
+ short flags = PortablePrimitives.readShort(arr, start + GridPortableMarshaller.FLAGS_POS);
+
+ int fieldIdLen = PortableUtils.isCompactFooter(flags) ? 0 : PortableUtils.FIELD_ID_LEN;
+ int fieldOffsetLen = PortableUtils.fieldOffsetLength(flags);
+
+ int fieldOffsetPos = start + schemaOffset + order * (fieldIdLen + fieldOffsetLen) + fieldIdLen;
+
+ int fieldPos;
+
+ if (fieldOffsetLen == PortableUtils.OFFSET_1)
+ fieldPos = start + ((int)PortablePrimitives.readByte(arr, fieldOffsetPos) & 0xFF);
+ else if (fieldOffsetLen == 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);
+
+ switch (hdr) {
+ case GridPortableMarshaller.INT:
+ val = PortablePrimitives.readInt(arr, fieldPos + 1);
+
+ break;
+
+ case GridPortableMarshaller.LONG:
+ val = PortablePrimitives.readLong(arr, fieldPos + 1);
+
+ break;
+
+ case GridPortableMarshaller.BOOLEAN:
+ val = PortablePrimitives.readBoolean(arr, fieldPos + 1);
+
+ break;
+
+ case GridPortableMarshaller.SHORT:
+ val = PortablePrimitives.readShort(arr, fieldPos + 1);
+
+ break;
+
+ case GridPortableMarshaller.BYTE:
+ val = PortablePrimitives.readByte(arr, fieldPos + 1);
+
+ break;
+
+ case GridPortableMarshaller.CHAR:
+ val = PortablePrimitives.readChar(arr, fieldPos + 1);
+
+ break;
+
+ case GridPortableMarshaller.FLOAT:
+ val = PortablePrimitives.readFloat(arr, fieldPos + 1);
+
+ break;
+
+ case GridPortableMarshaller.DOUBLE:
+ val = PortablePrimitives.readDouble(arr, fieldPos + 1);
+
+ break;
+
+ case GridPortableMarshaller.STRING: {
+ int dataLen = PortablePrimitives.readInt(arr, fieldPos + 1);
+
+ val = new String(arr, fieldPos + 5, dataLen, UTF_8);
+
+ break;
+ }
+
+ case GridPortableMarshaller.DATE: {
+ long time = PortablePrimitives.readLong(arr, fieldPos + 1);
+
+ val = new Date(time);
+
+ break;
+ }
+
+ case GridPortableMarshaller.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 GridPortableMarshaller.UUID: {
+ long most = PortablePrimitives.readLong(arr, fieldPos + 1);
+ long least = PortablePrimitives.readLong(arr, fieldPos + 1 + 8);
+
+ val = new UUID(most, least);
+
+ break;
+ }
+
+ case GridPortableMarshaller.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 GridPortableMarshaller.NULL:
+ val = null;
+
+ break;
+
+ default:
+ val = PortableUtils.unmarshal(PortableHeapInputStream.create(arr, fieldPos), ctx, null);
+
+ break;
+ }
+
+ return (F)val;
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Nullable @Override protected <F> F field(BinaryReaderHandles rCtx, String fieldName) {
+ return (F)reader(rCtx).unmarshalField(fieldName);
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean hasField(String fieldName) {
+ return reader(null).findFieldByName(fieldName);
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Nullable @Override public <T> T deserialize() throws BinaryObjectException {
+ Object obj0 = obj;
+
+ if (obj0 == null)
+ obj0 = deserializeValue(null);
+
+ return (T)obj0;
+ }
+
+ /** {@inheritDoc} */
+ @Override public BinaryObject clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ return PortablePrimitives.readInt(arr, start + GridPortableMarshaller.HASH_CODE_POS);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected int schemaId() {
+ return PortablePrimitives.readInt(arr, start + GridPortableMarshaller.SCHEMA_ID_POS);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected PortableSchema createSchema() {
+ return reader(null).getOrCreateSchema();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeObject(ctx);
+
+ if (detachAllowed) {
+ int len = length();
+
+ out.writeInt(len);
+ out.write(arr, start, len);
+ out.writeInt(0);
+ }
+ else {
+ out.writeInt(arr.length);
+ out.write(arr);
+ out.writeInt(start);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ ctx = (PortableContext)in.readObject();
+
+ arr = new byte[in.readInt()];
+
+ in.readFully(arr);
+
+ start = in.readInt();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) {
+ writer.setBuffer(buf);
+
+ if (!writer.isHeaderWritten()) {
+ if (!writer.writeHeader(directType(), fieldsCount()))
+ return false;
+
+ writer.onHeaderWritten();
+ }
+
+ switch (writer.state()) {
+ case 0:
+ if (!writer.writeByteArray("arr",
+ arr,
+ detachAllowed ? start : 0,
+ detachAllowed ? length() : arr.length))
+ return false;
+
+ writer.incrementState();
+
+ case 1:
+ if (!writer.writeInt("start", detachAllowed ? 0 : start))
+ return false;
+
+ writer.incrementState();
+
+ }
+
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
+ reader.setBuffer(buf);
+
+ if (!reader.beforeMessageRead())
+ return false;
+
+ switch (reader.state()) {
+ case 0:
+ arr = reader.readByteArray("arr");
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ case 1:
+ start = reader.readInt("start");
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ }
+
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte directType() {
+ return 113;
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte fieldsCount() {
+ return 3;
+ }
+
+ /**
+ * Runs value deserialization regardless of whether obj already has the deserialized value.
+ * Will set obj if descriptor is configured to keep deserialized values.
+ * @param coCtx CacheObjectContext.
+ * @return Object.
+ */
+ private Object deserializeValue(@Nullable CacheObjectContext coCtx) {
- // TODO: IGNITE-1272 - Deserialize with proper class loader.
+ BinaryReaderExImpl reader = reader(null);
+
+ Object obj0 = reader.deserialize();
+
+ PortableClassDescriptor desc = reader.descriptor();
+
+ assert desc != null;
+
+ if (coCtx != null && coCtx.storeValue())
+ obj = obj0;
+
+ return obj0;
+ }
+
+ /**
+ * @param ctx Context.
+ * @return {@code True} need to copy value returned to user.
+ */
+ private boolean needCopy(CacheObjectContext ctx) {
+ return ctx.copyOnGet() && obj != null && !ctx.processor().immutable(obj);
+ }
+
+ /**
+ * Create new reader for this object.
+ *
+ * @param rCtx Reader context.
+ * @return Reader.
+ */
+ private BinaryReaderExImpl reader(@Nullable BinaryReaderHandles rCtx) {
+ return new BinaryReaderExImpl(ctx,
+ PortableHeapInputStream.create(arr, start),
+ ctx.configuration().getClassLoader(),
+ rCtx);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/0ac39c97/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectOffheapImpl.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectOffheapImpl.java
index 27b46c1,0000000..2944099
mode 100644,000000..100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectOffheapImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectOffheapImpl.java
@@@ -1,430 -1,0 +1,432 @@@
+/*
+ * 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.binary;
+
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.binary.BinaryObject;
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.binary.BinaryType;
+import org.apache.ignite.internal.binary.streams.PortableOffheapInputStream;
+import org.apache.ignite.internal.binary.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.U;
+import org.apache.ignite.plugin.extensions.communication.MessageReader;
+import org.apache.ignite.plugin.extensions.communication.MessageWriter;
+import org.jetbrains.annotations.Nullable;
+import sun.misc.Unsafe;
+
+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.binary.GridPortableMarshaller.BOOLEAN;
+import static org.apache.ignite.internal.binary.GridPortableMarshaller.BYTE;
+import static org.apache.ignite.internal.binary.GridPortableMarshaller.CHAR;
+import static org.apache.ignite.internal.binary.GridPortableMarshaller.DATE;
+import static org.apache.ignite.internal.binary.GridPortableMarshaller.DECIMAL;
+import static org.apache.ignite.internal.binary.GridPortableMarshaller.DOUBLE;
+import static org.apache.ignite.internal.binary.GridPortableMarshaller.FLOAT;
+import static org.apache.ignite.internal.binary.GridPortableMarshaller.INT;
+import static org.apache.ignite.internal.binary.GridPortableMarshaller.LONG;
+import static org.apache.ignite.internal.binary.GridPortableMarshaller.NULL;
+import static org.apache.ignite.internal.binary.GridPortableMarshaller.SHORT;
+import static org.apache.ignite.internal.binary.GridPortableMarshaller.STRING;
+import static org.apache.ignite.internal.binary.GridPortableMarshaller.TIMESTAMP;
+import static org.apache.ignite.internal.binary.GridPortableMarshaller.UUID;
+
+/**
+ * Portable object implementation over offheap memory
+ */
+public class BinaryObjectOffheapImpl extends BinaryObjectExImpl implements Externalizable, CacheObject {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** */
+ private static final Unsafe UNSAFE = GridUnsafe.unsafe();
+
+ /** */
+ private final PortableContext ctx;
+
+ /** */
+ private final long ptr;
+
+ /** */
+ private final int start;
+
+ /** */
+ private final int size;
+
+ /**
+ * For {@link Externalizable} (not supported).
+ */
+ public BinaryObjectOffheapImpl() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @param ctx Context.
+ * @param ptr Memory address.
+ * @param start Object start.
+ * @param size Memory size.
+ */
+ public BinaryObjectOffheapImpl(PortableContext ctx, long ptr, int start, int size) {
+ this.ctx = ctx;
+ this.ptr = ptr;
+ this.start = start;
+ this.size = size;
+ }
+
+ /**
+ * @return Heap-based copy.
+ */
+ public BinaryObject heapCopy() {
+ return new BinaryObjectImpl(ctx, U.copyMemory(ptr, size), start);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int typeId() {
+ return UNSAFE.getInt(ptr + start + GridPortableMarshaller.TYPE_ID_POS);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int length() {
+ return UNSAFE.getInt(ptr + start + GridPortableMarshaller.TOTAL_LEN_POS);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ return UNSAFE.getInt(ptr + start + GridPortableMarshaller.HASH_CODE_POS);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected int schemaId() {
+ return UNSAFE.getInt(ptr + start + GridPortableMarshaller.SCHEMA_ID_POS);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected PortableSchema createSchema() {
+ return reader(null).getOrCreateSchema();
+ }
+
+ /** {@inheritDoc} */
+ @Override public int start() {
+ return start;
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte[] array() {
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long offheapAddress() {
+ return ptr;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected boolean hasArray() {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Nullable @Override public BinaryType type() throws BinaryObjectException {
+ if (ctx == null)
+ throw new BinaryObjectException("PortableContext is not set for the object.");
+
+ return ctx.metadata(typeId());
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Nullable @Override public <F> F field(String fieldName) throws BinaryObjectException {
+ return (F) reader(null).unmarshalField(fieldName);
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Nullable @Override public <F> F field(int fieldId) throws BinaryObjectException {
+ return (F) reader(null).unmarshalField(fieldId);
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @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 fieldIdLen = PortableUtils.isCompactFooter(flags) ? 0 : PortableUtils.FIELD_ID_LEN;
+ int fieldOffsetLen = PortableUtils.fieldOffsetLength(flags);
+
+ int fieldOffsetPos = start + schemaOffset + order * (fieldIdLen + fieldOffsetLen) + fieldIdLen;
+
+ int fieldPos;
+
+ if (fieldOffsetLen == PortableUtils.OFFSET_1)
+ fieldPos = start + ((int)PortablePrimitives.readByte(ptr, fieldOffsetPos) & 0xFF);
+ else if (fieldOffsetLen == 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 GridPortableMarshaller.INT:
+ val = PortablePrimitives.readInt(ptr, fieldPos + 1);
+
+ break;
+
+ case GridPortableMarshaller.LONG:
+ val = PortablePrimitives.readLong(ptr, fieldPos + 1);
+
+ break;
+
+ case GridPortableMarshaller.BOOLEAN:
+ val = PortablePrimitives.readBoolean(ptr, fieldPos + 1);
+
+ break;
+
+ case GridPortableMarshaller.SHORT:
+ val = PortablePrimitives.readShort(ptr, fieldPos + 1);
+
+ break;
+
+ case GridPortableMarshaller.BYTE:
+ val = PortablePrimitives.readByte(ptr, fieldPos + 1);
+
+ break;
+
+ case GridPortableMarshaller.CHAR:
+ val = PortablePrimitives.readChar(ptr, fieldPos + 1);
+
+ break;
+
+ case GridPortableMarshaller.FLOAT:
+ val = PortablePrimitives.readFloat(ptr, fieldPos + 1);
+
+ break;
+
+ case GridPortableMarshaller.DOUBLE:
+ val = PortablePrimitives.readDouble(ptr, fieldPos + 1);
+
+ break;
+
+ case GridPortableMarshaller.STRING: {
+ int dataLen = PortablePrimitives.readInt(ptr, fieldPos + 1);
+ byte[] data = PortablePrimitives.readByteArray(ptr, fieldPos + 5, dataLen);
+
+ val = new String(data, UTF_8);
+
+ break;
+ }
+
+ case GridPortableMarshaller.DATE: {
+ long time = PortablePrimitives.readLong(ptr, fieldPos + 1);
+
+ val = new Date(time);
+
+ break;
+ }
+
+ case GridPortableMarshaller.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 GridPortableMarshaller.UUID: {
+ long most = PortablePrimitives.readLong(ptr, fieldPos + 1);
+ long least = PortablePrimitives.readLong(ptr, fieldPos + 1 + 8);
+
+ val = new UUID(most, least);
+
+ break;
+ }
+
+ case GridPortableMarshaller.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 GridPortableMarshaller.NULL:
+ val = null;
+
+ break;
+
+ default:
+ PortableOffheapInputStream stream = new PortableOffheapInputStream(ptr, size, false);
+
+ stream.position(fieldPos);
+
+ val = PortableUtils.unmarshal(stream, ctx, null);
+
+ break;
+ }
+
+ return (F)val;
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Nullable @Override protected <F> F field(BinaryReaderHandles rCtx, String fieldName) {
+ return (F)reader(rCtx).unmarshalField(fieldName);
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean hasField(String fieldName) {
+ return reader(null).findFieldByName(fieldName);
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Nullable @Override public <T> T deserialize() throws BinaryObjectException {
+ return (T)deserializeValue();
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("CloneDoesntCallSuperClone")
+ @Override public BinaryObject clone() throws CloneNotSupportedException {
+ return heapCopy();
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte cacheObjectType() {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean isPlatformType() {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Nullable @Override public <T> T value(CacheObjectContext ctx, boolean cpy) {
+ return (T)deserializeValue();
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte[] valueBytes(CacheObjectContext ctx) throws IgniteCheckedException {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public CacheObject prepareForCache(CacheObjectContext ctx) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void finishUnmarshal(CacheObjectContext ctx, ClassLoader ldr) throws IgniteCheckedException {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void prepareMarshal(CacheObjectContext ctx) throws IgniteCheckedException {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte directType() {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte fieldsCount() {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeExternal(ObjectOutput out) throws IOException {
+ throw new UnsupportedOperationException(); // To make sure it is not marshalled.
+ }
+
+ /** {@inheritDoc} */
+ @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ throw new UnsupportedOperationException(); // To make sure it is not marshalled.
+ }
+
+ /**
+ * @return Deserialized value.
+ */
+ private Object deserializeValue() {
- // TODO: IGNITE-1272 - Deserialize with proper class loader.
+ return reader(null).deserialize();
+ }
+
+ /**
+ * Create new reader for this object.
+ *
+ * @param rCtx Reader context.
+ * @return Reader.
+ */
+ private BinaryReaderExImpl reader(@Nullable BinaryReaderHandles rCtx) {
+ PortableOffheapInputStream stream = new PortableOffheapInputStream(ptr, size, false);
+
+ stream.position(start);
+
- return new BinaryReaderExImpl(ctx, stream, null, rCtx);
++ return new BinaryReaderExImpl(ctx,
++ stream,
++ ctx.configuration().getClassLoader(),
++ rCtx);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/0ac39c97/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
index f5e4e06,0000000..f1d4185
mode 100644,000000..100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
@@@ -1,587 -1,0 +1,586 @@@
+/*
+ * 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.binary.builder;
+
+import org.apache.ignite.binary.BinaryInvalidTypeException;
+import org.apache.ignite.binary.BinaryObject;
+import org.apache.ignite.binary.BinaryObjectBuilder;
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.binary.BinaryType;
+import org.apache.ignite.internal.binary.BinaryMetadata;
+import org.apache.ignite.internal.binary.BinaryObjectImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.binary.GridPortableMarshaller;
+import org.apache.ignite.internal.binary.PortableContext;
+import org.apache.ignite.internal.binary.PortableSchema;
+import org.apache.ignite.internal.binary.PortableSchemaRegistry;
+import org.apache.ignite.internal.binary.BinaryMetadata;
+import org.apache.ignite.internal.binary.BinaryObjectImpl;
+import org.apache.ignite.internal.binary.BinaryObjectOffheapImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.binary.GridPortableMarshaller;
+import org.apache.ignite.internal.binary.PortableContext;
+import org.apache.ignite.internal.binary.PortableSchema;
+import org.apache.ignite.internal.binary.PortableSchemaRegistry;
+import org.apache.ignite.internal.binary.PortableUtils;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteBiTuple;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import static org.apache.ignite.internal.binary.GridPortableMarshaller.DFLT_HDR_LEN;
+import static org.apache.ignite.internal.binary.GridPortableMarshaller.FLAGS_POS;
+import static org.apache.ignite.internal.binary.GridPortableMarshaller.HASH_CODE_POS;
+import static org.apache.ignite.internal.binary.GridPortableMarshaller.PROTO_VER_POS;
+import static org.apache.ignite.internal.binary.GridPortableMarshaller.TYPE_ID_POS;
+import static org.apache.ignite.internal.binary.GridPortableMarshaller.UNREGISTERED_TYPE_ID;
+
+/**
+ *
+ */
+public class BinaryObjectBuilderImpl implements BinaryObjectBuilder {
+ /** */
+ private static final Object REMOVED_FIELD_MARKER = new Object();
+
+ /** */
+ private final PortableContext ctx;
+
+ /** */
+ private final int typeId;
+
+ /** May be null. */
+ private String typeName;
+
+ /** May be null. */
+ private String clsNameToWrite;
+
+ /** */
+ private boolean registeredType = true;
+
+ /** */
+ private Map<String, Object> assignedVals;
+
+ /** */
+ private Map<Integer, Object> readCache;
+
+ /** 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. */
+ private final PortableBuilderReader reader;
+
+ /** */
+ private int hashCode;
+
+ /**
+ * @param clsName Class name.
+ * @param ctx Portable context.
+ */
+ public BinaryObjectBuilderImpl(PortableContext ctx, String clsName) {
+ this(ctx, ctx.typeId(clsName), PortableContext.typeName(clsName));
+ }
+
+ /**
+ * @param typeName Type name.
+ * @param ctx Context.
+ * @param typeId Type id.
+ */
+ public BinaryObjectBuilderImpl(PortableContext ctx, int typeId, String typeName) {
+ this.typeId = typeId;
+ this.typeName = typeName;
+ this.ctx = ctx;
+
+ start = -1;
+ flags = -1;
+ reader = null;
+ hdrLen = GridPortableMarshaller.DFLT_HDR_LEN;
+
+ readCache = Collections.emptyMap();
+ }
+
+ /**
+ * @param obj Object to wrap.
+ */
+ public BinaryObjectBuilderImpl(BinaryObjectImpl obj) {
+ this(new PortableBuilderReader(obj), obj.start());
+
+ reader.registerObject(this);
+ }
+
+ /**
+ * @param reader ctx
+ * @param start Start.
+ */
+ BinaryObjectBuilderImpl(PortableBuilderReader reader, int start) {
+ this.reader = reader;
+ this.start = start;
+ this.flags = reader.readShortPositioned(start + GridPortableMarshaller.FLAGS_POS);
+
+ byte ver = reader.readBytePositioned(start + GridPortableMarshaller.PROTO_VER_POS);
+
+ PortableUtils.checkProtocolVersion(ver);
+
+ int typeId = reader.readIntPositioned(start + GridPortableMarshaller.TYPE_ID_POS);
+ ctx = reader.portableContext();
+ hashCode = reader.readIntPositioned(start + GridPortableMarshaller.HASH_CODE_POS);
+
+ if (typeId == GridPortableMarshaller.UNREGISTERED_TYPE_ID) {
+ int mark = reader.position();
+
+ reader.position(start + GridPortableMarshaller.DFLT_HDR_LEN);
+
+ clsNameToWrite = reader.readString();
+
+ Class cls;
+
+ try {
- // TODO: IGNITE-1272 - Is class loader needed here?
- cls = U.forName(clsNameToWrite, null);
++ cls = U.forName(clsNameToWrite, ctx.configuration().getClassLoader());
+ }
+ catch (ClassNotFoundException e) {
+ throw new BinaryInvalidTypeException("Failed to load the class: " + clsNameToWrite, e);
+ }
+
+ this.typeId = ctx.descriptorForClass(cls, false).typeId();
+
+ registeredType = false;
+
+ hdrLen = reader.position() - mark;
+
+ reader.position(mark);
+ }
+ else {
+ this.typeId = typeId;
+ hdrLen = GridPortableMarshaller.DFLT_HDR_LEN;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public BinaryObject build() {
+ try (BinaryWriterExImpl writer = new BinaryWriterExImpl(ctx)) {
+ writer.typeId(typeId);
+
+ PortableBuilderSerializer serializationCtx = new PortableBuilderSerializer();
+
+ serializationCtx.registerObjectWriting(this, 0);
+
+ serializeTo(writer, serializationCtx);
+
+ byte[] arr = writer.array();
+
+ return new BinaryObjectImpl(ctx, arr, 0);
+ }
+ }
+
+ /**
+ * @param writer Writer.
+ * @param serializer Serializer.
+ */
+ void serializeTo(BinaryWriterExImpl writer, PortableBuilderSerializer serializer) {
+ try {
+ writer.preWrite(registeredType ? null : clsNameToWrite);
+
+ Set<Integer> remainsFlds = null;
+
+ if (reader != null) {
+ PortableSchema schema = reader.schema();
+
+ Map<Integer, Object> assignedFldsById;
+
+ if (assignedVals != null) {
+ assignedFldsById = U.newHashMap(assignedVals.size());
+
+ for (Map.Entry<String, Object> entry : assignedVals.entrySet()) {
+ int fieldId = ctx.fieldId(typeId, entry.getKey());
+
+ assignedFldsById.put(fieldId, entry.getValue());
+ }
+
+ remainsFlds = assignedFldsById.keySet();
+ }
+ else
+ assignedFldsById = Collections.emptyMap();
+
+ // Get footer details.
+ int fieldIdLen = PortableUtils.fieldIdLength(flags);
+ int fieldOffsetLen = PortableUtils.fieldOffsetLength(flags);
+
+ IgniteBiTuple<Integer, Integer> footer = PortableUtils.footerAbsolute(reader, start);
+
+ int footerPos = footer.get1();
+ int footerEnd = footer.get2();
+
+ // Get raw position.
+ int rawPos = PortableUtils.rawOffsetAbsolute(reader, start);
+
+ // Position reader on data.
+ reader.position(start + hdrLen);
+
+ int idx = 0;
+
+ while (reader.position() < rawPos) {
+ int fieldId = schema.fieldId(idx++);
+ int fieldLen =
+ fieldPositionAndLength(footerPos, footerEnd, rawPos, fieldIdLen, fieldOffsetLen).get2();
+
+ int postPos = reader.position() + fieldLen; // Position where reader will be placed afterwards.
+
+ footerPos += fieldIdLen + fieldOffsetLen;
+
+ if (assignedFldsById.containsKey(fieldId)) {
+ Object assignedVal = assignedFldsById.remove(fieldId);
+
+ if (assignedVal != REMOVED_FIELD_MARKER) {
+ writer.writeFieldId(fieldId);
+
+ serializer.writeValue(writer, assignedVal);
+ }
+ }
+ else {
+ int type = fieldLen != 0 ? reader.readByte(0) : 0;
+
+ if (fieldLen != 0 && !PortableUtils.isPlainArrayType(type) && PortableUtils.isPlainType(type)) {
+ writer.writeFieldId(fieldId);
+
+ writer.write(reader.array(), reader.position(), fieldLen);
+ }
+ else {
+ writer.writeFieldId(fieldId);
+
+ Object val;
+
+ if (fieldLen == 0)
+ val = null;
+ else if (readCache == null) {
+ val = reader.parseValue();
+
+ assert reader.position() == postPos;
+ }
+ else
+ val = readCache.get(fieldId);
+
+ serializer.writeValue(writer, val);
+ }
+ }
+
+ reader.position(postPos);
+ }
+ }
+
+ BinaryType meta = ctx.metadata(typeId);
+
+ Map<String, Integer> fieldsMeta = null;
+
+ if (assignedVals != null && (remainsFlds == null || !remainsFlds.isEmpty())) {
+ for (Map.Entry<String, Object> entry : assignedVals.entrySet()) {
+ Object val = entry.getValue();
+
+ if (val == REMOVED_FIELD_MARKER)
+ continue;
+
+ String name = entry.getKey();
+
+ int fieldId = ctx.fieldId(typeId, name);
+
+ if (remainsFlds != null && !remainsFlds.contains(fieldId))
+ continue;
+
+ writer.writeFieldId(fieldId);
+
+ serializer.writeValue(writer, val);
+
+ String oldFldTypeName = meta == null ? null : meta.fieldTypeName(name);
+
+ boolean nullObjField = false;
+
+ int newFldTypeId;
+
+ if (val instanceof PortableValueWithType) {
+ newFldTypeId = ((PortableValueWithType)val).typeId();
+
+ if (newFldTypeId == GridPortableMarshaller.OBJ && ((PortableValueWithType)val).value() == null)
+ nullObjField = true;
+ }
+ else
+ newFldTypeId = PortableUtils.typeByClass(val.getClass());
+
+ String newFldTypeName = PortableUtils.fieldTypeName(newFldTypeId);
+
+ if (oldFldTypeName == null) {
+ // It's a new field, we have to add it to metadata.
+ if (fieldsMeta == null)
+ fieldsMeta = new HashMap<>();
+
+ fieldsMeta.put(name, PortableUtils.fieldTypeId(newFldTypeName));
+ }
+ else if (!nullObjField) {
+ String objTypeName = PortableUtils.fieldTypeName(GridPortableMarshaller.OBJ);
+
+ if (!objTypeName.equals(oldFldTypeName) && !oldFldTypeName.equals(newFldTypeName)) {
+ throw new BinaryObjectException(
+ "Wrong value has been set [" +
+ "typeName=" + (typeName == null ? meta.typeName() : typeName) +
+ ", fieldName=" + name +
+ ", fieldType=" + oldFldTypeName +
+ ", assignedValueType=" + newFldTypeName + ']'
+ );
+ }
+ }
+ }
+ }
+
+ if (reader != null) {
+ // Write raw data if any.
+ int rawOff = PortableUtils.rawOffsetAbsolute(reader, start);
+ int footerStart = PortableUtils.footerStartAbsolute(reader, start);
+
+ if (rawOff < footerStart) {
+ writer.rawWriter();
+
+ writer.write(reader.array(), rawOff, footerStart - rawOff);
+ }
+
+ // Shift reader to the end of the object.
+ reader.position(start + PortableUtils.length(reader, start));
+ }
+
+ writer.postWrite(true, registeredType, hashCode);
+
+ // Update metadata if needed.
+ int schemaId = writer.schemaId();
+
+ PortableSchemaRegistry schemaReg = ctx.schemaRegistry(typeId);
+
+ if (schemaReg.schema(schemaId) == null) {
+ String typeName = this.typeName;
+
+ if (typeName == null) {
+ assert meta != null;
+
+ typeName = meta.typeName();
+ }
+
+ PortableSchema curSchema = writer.currentSchema();
+
+ ctx.updateMetadata(typeId, new BinaryMetadata(typeId, typeName, fieldsMeta,
+ ctx.affinityKeyFieldName(typeId), Collections.singleton(curSchema), false));
+
+ schemaReg.addSchema(curSchema.schemaId(), curSchema);
+ }
+ }
+ finally {
+ writer.popSchema();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public BinaryObjectBuilderImpl hashCode(int hashCode) {
+ this.hashCode = hashCode;
+
+ return this;
+ }
+
+ /**
+ * Get field position and length.
+ *
+ * @param footerPos Field position inside the footer (absolute).
+ * @param footerEnd Footer end (absolute).
+ * @param rawPos Raw data position (absolute).
+ * @param fieldIdLen Field ID length.
+ * @param fieldOffsetLen Field offset length.
+ * @return Tuple with field position and length.
+ */
+ private IgniteBiTuple<Integer, Integer> fieldPositionAndLength(int footerPos, int footerEnd, int rawPos,
+ int fieldIdLen, int fieldOffsetLen) {
+ // Get field offset first.
+ int fieldOffset = PortableUtils.fieldOffsetRelative(reader, footerPos + fieldIdLen, fieldOffsetLen);
+ int fieldPos = start + fieldOffset;
+
+ // Get field length.
+ int fieldLen;
+
+ if (footerPos + fieldIdLen + fieldOffsetLen == 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 = PortableUtils.fieldOffsetRelative(reader,
+ footerPos + fieldIdLen + fieldOffsetLen + fieldIdLen, fieldOffsetLen);
+
+ fieldLen = nextFieldOffset - fieldOffset;
+ }
+
+ return F.t(fieldPos, fieldLen);
+ }
+
+ /**
+ * Initialize read cache if needed.
+ */
+ private void ensureReadCacheInit() {
+ assert reader != null;
+
+ if (readCache == null) {
+ int fieldIdLen = PortableUtils.fieldIdLength(flags);
+ int fieldOffsetLen = PortableUtils.fieldOffsetLength(flags);
+
+ PortableSchema schema = reader.schema();
+
+ Map<Integer, Object> readCache = new HashMap<>();
+
+ IgniteBiTuple<Integer, Integer> footer = PortableUtils.footerAbsolute(reader, start);
+
+ int footerPos = footer.get1();
+ int footerEnd = footer.get2();
+
+ int rawPos = PortableUtils.rawOffsetAbsolute(reader, start);
+
+ int idx = 0;
+
+ while (footerPos + fieldIdLen < footerEnd) {
+ int fieldId = schema.fieldId(idx++);
+
+ IgniteBiTuple<Integer, Integer> posAndLen =
+ fieldPositionAndLength(footerPos, footerEnd, rawPos, fieldIdLen, fieldOffsetLen);
+
+ Object val = reader.getValueQuickly(posAndLen.get1(), posAndLen.get2());
+
+ readCache.put(fieldId, val);
+
+ // Shift current footer position.
+ footerPos += fieldIdLen + fieldOffsetLen;
+ }
+
+ this.readCache = readCache;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Override public <T> T getField(String name) {
+ Object val;
+
+ if (assignedVals != null && assignedVals.containsKey(name)) {
+ val = assignedVals.get(name);
+
+ if (val == REMOVED_FIELD_MARKER)
+ return null;
+ }
+ else {
+ ensureReadCacheInit();
+
+ int fldId = ctx.fieldId(typeId, name);
+
+ val = readCache.get(fldId);
+ }
+
+ return (T)PortableUtils.unwrapLazy(val);
+ }
+
+ /** {@inheritDoc} */
+ @Override public BinaryObjectBuilder setField(String name, Object val0) {
+ Object val = val0 == null ? new PortableValueWithType(PortableUtils.typeByClass(Object.class), null) : val0;
+
+ if (assignedVals == null)
+ assignedVals = new LinkedHashMap<>();
+
+ Object oldVal = assignedVals.put(name, val);
+
+ if (oldVal instanceof PortableValueWithType && val0 != null) {
+ ((PortableValueWithType)oldVal).value(val);
+
+ assignedVals.put(name, oldVal);
+ }
+
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override public <T> BinaryObjectBuilder setField(String name, @Nullable T val, Class<? super T> type) {
+ if (assignedVals == null)
+ assignedVals = new LinkedHashMap<>();
+
+ assignedVals.put(name, new PortableValueWithType(PortableUtils.typeByClass(type), val));
+
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override public BinaryObjectBuilder setField(String name, @Nullable BinaryObjectBuilder builder) {
+ if (builder == null)
+ return setField(name, null, Object.class);
+ else
+ return setField(name, (Object)builder);
+ }
+
+ /**
+ * Removes field from portable object.
+ *
+ * @param name Field name.
+ * @return {@code this} instance for chaining.
+ */
+ @Override public BinaryObjectBuilderImpl removeField(String name) {
+ if (assignedVals == null)
+ assignedVals = new LinkedHashMap<>();
+
+ assignedVals.put(name, REMOVED_FIELD_MARKER);
+
+ return this;
+ }
+
+ /**
+ * Creates builder initialized by specified portable object.
+ *
+ * @param obj Portable object to initialize builder.
+ * @return New builder.
+ */
+ public static BinaryObjectBuilderImpl wrap(BinaryObject obj) {
+ BinaryObjectImpl heapObj;
+
+ if (obj instanceof BinaryObjectOffheapImpl)
+ heapObj = (BinaryObjectImpl)((BinaryObjectOffheapImpl)obj).heapCopy();
+ else
+ heapObj = (BinaryObjectImpl)obj;
+
+ return new BinaryObjectBuilderImpl(heapObj);
+ }
+
+ /**
+ * @return Object start position in source array.
+ */
+ int start() {
+ return start;
+ }
+
+ /**
+ * @return Object type id.
+ */
+ public int typeId() {
+ return typeId;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/0ac39c97/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/PortableBuilderEnum.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/binary/builder/PortableBuilderEnum.java
index 3bb8194,0000000..779c514
mode 100644,000000..100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/PortableBuilderEnum.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/PortableBuilderEnum.java
@@@ -1,116 -1,0 +1,115 @@@
+/*
+ * 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.binary.builder;
+
+import org.apache.ignite.internal.binary.GridPortableMarshaller;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.binary.BinaryInvalidTypeException;
+
+/**
+ *
+ */
+public class PortableBuilderEnum implements PortableBuilderSerializationAware {
+ /** */
+ private final int ordinal;
+
+ /** */
+ private final int typeId;
+
+ /** */
+ private final String clsName;
+
+ /**
+ * @param typeId Type ID.
+ * @param anEnum Enum instance.
+ */
+ public PortableBuilderEnum(int typeId, Enum anEnum) {
+ ordinal = anEnum.ordinal();
+ this.typeId = typeId;
+ clsName = null;
+ }
+
+ /**
+ * @param reader PortableBuilderReader.
+ */
+ public PortableBuilderEnum(PortableBuilderReader reader) {
+ int typeId = reader.readInt();
+
+ if (typeId == GridPortableMarshaller.UNREGISTERED_TYPE_ID) {
+ clsName = reader.readString();
+
+ Class cls;
+
+ try {
- // TODO: IGNITE-1272 - Is class loader needed here?
- cls = U.forName(reader.readString(), null);
++ cls = U.forName(reader.readString(), reader.portableContext().configuration().getClassLoader());
+ }
+ catch (ClassNotFoundException e) {
+ throw new BinaryInvalidTypeException("Failed to load the class: " + clsName, e);
+ }
+
+ this.typeId = reader.portableContext().descriptorForClass(cls, false).typeId();
+ }
+ else {
+ this.typeId = typeId;
+ this.clsName = null;
+ }
+
+ ordinal = reader.readInt();
+ }
+
+ /**
+ * @return Ordinal.
+ */
+ public int getOrdinal() {
+ return ordinal;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeTo(BinaryWriterExImpl writer, PortableBuilderSerializer ctx) {
+ writer.writeByte(GridPortableMarshaller.ENUM);
+
+ if (typeId == GridPortableMarshaller.UNREGISTERED_TYPE_ID) {
+ writer.writeInt(GridPortableMarshaller.UNREGISTERED_TYPE_ID);
+ writer.writeString(clsName);
+ }
+ else
+ writer.writeInt(typeId);
+
+ writer.writeInt(ordinal);
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ PortableBuilderEnum that = (PortableBuilderEnum)o;
+
+ return ordinal == that.ordinal && typeId == that.typeId;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ int result = ordinal;
+
+ result = 31 * result + typeId;
+
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/0ac39c97/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/PortableBuilderReader.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/binary/builder/PortableBuilderReader.java
index 2b28e3d,0000000..c86fb95
mode 100644,000000..100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/PortableBuilderReader.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/PortableBuilderReader.java
@@@ -1,856 -1,0 +1,857 @@@
+/*
+ * 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.binary.builder;
+
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.internal.binary.BinaryObjectImpl;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.binary.GridPortableMarshaller;
+import org.apache.ignite.internal.binary.PortableContext;
+import org.apache.ignite.internal.binary.PortablePositionReadable;
+import org.apache.ignite.internal.binary.PortablePrimitives;
+import org.apache.ignite.internal.binary.PortableSchema;
+import org.apache.ignite.internal.binary.streams.PortableHeapInputStream;
+import org.apache.ignite.internal.binary.BinaryObjectImpl;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.binary.GridPortableMarshaller;
+import org.apache.ignite.internal.binary.PortableContext;
+import org.apache.ignite.internal.binary.PortablePositionReadable;
+import org.apache.ignite.internal.binary.PortablePrimitives;
+import org.apache.ignite.internal.binary.PortableSchema;
+import org.apache.ignite.internal.binary.PortableUtils;
+import org.apache.ignite.internal.binary.streams.PortableHeapInputStream;
+
+import java.sql.Timestamp;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.ignite.internal.binary.GridPortableMarshaller.NULL;
+import static org.apache.ignite.internal.binary.GridPortableMarshaller.STRING;
+
+/**
+ *
+ */
+public class PortableBuilderReader implements PortablePositionReadable {
+ /** */
+ private final PortableContext ctx;
+
+ /** */
+ private final byte[] arr;
+
+ /** */
+ private final BinaryReaderExImpl reader;
+
+ /** */
+ private final Map<Integer, BinaryObjectBuilderImpl> objMap;
+
+ /** */
+ private int pos;
+
+ /*
+ * Constructor.
+ *
+ * @param objImpl Portable object
+ */
+ PortableBuilderReader(BinaryObjectImpl objImpl) {
+ ctx = objImpl.context();
+ arr = objImpl.array();
+ pos = objImpl.start();
+
- // TODO: IGNITE-1272 - Is class loader needed here?
- reader = new BinaryReaderExImpl(ctx, PortableHeapInputStream.create(arr, pos), null);
++ reader = new BinaryReaderExImpl(ctx,
++ PortableHeapInputStream.create(arr, pos),
++ ctx.configuration().getClassLoader());
+
+ objMap = new HashMap<>();
+ }
+
+ /**
+ * Copying constructor.
+ *
+ * @param other Other reader.
+ * @param start Start position.
+ */
+ PortableBuilderReader(PortableBuilderReader other, int start) {
+ this.ctx = other.ctx;
+ this.arr = other.arr;
+ this.pos = start;
+
+ reader = new BinaryReaderExImpl(ctx, PortableHeapInputStream.create(arr, start), null, other.reader.handles());
+
+ this.objMap = other.objMap;
+ }
+
+ /**
+ * @return Portable context.
+ */
+ public PortableContext portableContext() {
+ return ctx;
+ }
+
+ /**
+ * @param obj Mutable portable object.
+ */
+ public void registerObject(BinaryObjectBuilderImpl obj) {
+ objMap.put(obj.start(), obj);
+ }
+
+ /**
+ * Get schema of the object, starting at the given position.
+ *
+ * @return Object's schema.
+ */
+ public PortableSchema schema() {
+ return reader.getOrCreateSchema();
+ }
+
+ /**
+ * @return Read int value.
+ */
+ public int readInt() {
+ int res = readInt(0);
+
+ pos += 4;
+
+ return res;
+ }
+
+ /**
+ * @return Read int value.
+ */
+ public byte readByte() {
+ return arr[pos++];
+ }
+
+ /**
+ * @return Read boolean value.
+ */
+ public boolean readBoolean() {
+ return readByte() == 1;
+ }
+
+ /**
+ * @return Read int value.
+ */
+ public byte readByte(int off) {
+ return arr[pos + off];
+ }
+
+ /**
+ * @param off Offset related to {@link #pos}
+ * @return Read int value.
+ */
+ public int readInt(int off) {
+ return PortablePrimitives.readInt(arr, pos + off);
+ }
+
+ /**
+ * @param pos Position in the source array.
+ * @return Read byte value.
+ */
+ public byte readBytePositioned(int pos) {
+ return PortablePrimitives.readByte(arr, pos);
+ }
+
+ /** {@inheritDoc} */
+ @Override public short readShortPositioned(int pos) {
+ return PortablePrimitives.readShort(arr, pos);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int readIntPositioned(int pos) {
+ return PortablePrimitives.readInt(arr, pos);
+ }
+
+ /**
+ * @return Read length of array.
+ */
+ public int readLength() {
+ return PortablePrimitives.readInt(arr, pos);
+ }
+
+ /**
+ * Read string length.
+ *
+ * @return String length.
+ */
+ public int readStringLength() {
+ return PortablePrimitives.readInt(arr, pos);
+ }
+
+ /**
+ * Reads string.
+ *
+ * @return String.
+ */
+ public String readString() {
+ byte flag = readByte();
+
+ if (flag == GridPortableMarshaller.NULL)
+ return null;
+
+ if (flag != GridPortableMarshaller.STRING)
+ throw new BinaryObjectException("Failed to deserialize String.");
+
+ int len = readInt();
+
+ String str = new String(arr, pos, len, UTF_8);
+
+ pos += len;
+
+ return str;
+ }
+
+ /**
+ *
+ */
+ public void skipValue() {
+ byte type = arr[pos++];
+
+ int len;
+
+ switch (type) {
+ case GridPortableMarshaller.NULL:
+ return;
+
+ case GridPortableMarshaller.OBJ:
+ pos += readInt(GridPortableMarshaller.TOTAL_LEN_POS - 1) - 1;
+
+ return;
+
+ case GridPortableMarshaller.BOOLEAN:
+ case GridPortableMarshaller.BYTE:
+ len = 1;
+ break;
+
+ case GridPortableMarshaller.CHAR:
+ case GridPortableMarshaller.SHORT:
+ len = 2;
+
+ break;
+
+ case GridPortableMarshaller.HANDLE:
+ case GridPortableMarshaller.FLOAT:
+ case GridPortableMarshaller.INT:
+ len = 4;
+
+ break;
+
+ case GridPortableMarshaller.ENUM:
+ //skipping type id and ordinal value
+ len = 8;
+
+ break;
+
+ case GridPortableMarshaller.LONG:
+ case GridPortableMarshaller.DOUBLE:
+ len = 8;
+
+ break;
+
+ case GridPortableMarshaller.BYTE_ARR:
+ case GridPortableMarshaller.BOOLEAN_ARR:
+ len = 4 + readLength();
+
+ break;
+
+ case GridPortableMarshaller.STRING:
+ len = 4 + readStringLength();
+
+ break;
+
+ case GridPortableMarshaller.DECIMAL:
+ len = /** scale */ 4 + /** mag len */ 4 + /** mag bytes count */ readInt(4);
+
+ break;
+
+ case GridPortableMarshaller.UUID:
+ len = 8 + 8;
+
+ break;
+
+ case GridPortableMarshaller.DATE:
+ len = 8;
+
+ break;
+
+ case GridPortableMarshaller.TIMESTAMP:
+ len = 8 + 4;
+
+ break;
+
+ case GridPortableMarshaller.CHAR_ARR:
+ case GridPortableMarshaller.SHORT_ARR:
+ len = 4 + readLength() * 2;
+
+ break;
+
+ case GridPortableMarshaller.INT_ARR:
+ case GridPortableMarshaller.FLOAT_ARR:
+ len = 4 + readLength() * 4;
+
+ break;
+
+ case GridPortableMarshaller.LONG_ARR:
+ case GridPortableMarshaller.DOUBLE_ARR:
+ len = 4 + readLength() * 8;
+
+ break;
+
+ case GridPortableMarshaller.DECIMAL_ARR:
+ case GridPortableMarshaller.DATE_ARR:
+ case GridPortableMarshaller.TIMESTAMP_ARR:
+ case GridPortableMarshaller.OBJ_ARR:
+ case GridPortableMarshaller.ENUM_ARR:
+ case GridPortableMarshaller.UUID_ARR:
+ case GridPortableMarshaller.STRING_ARR: {
+ int size = readInt();
+
+ for (int i = 0; i < size; i++)
+ skipValue();
+
+ return;
+ }
+
+ case GridPortableMarshaller.COL: {
+ int size = readInt();
+
+ pos++; // skip collection type
+
+ for (int i = 0; i < size; i++)
+ skipValue();
+
+ return;
+ }
+
+ case GridPortableMarshaller.MAP: {
+ int size = readInt();
+
+ pos++; // skip collection type
+
+ for (int i = 0; i < size; i++) {
+ skipValue(); // skip key.
+ skipValue(); // skip value.
+ }
+
+ return;
+ }
+
+ case GridPortableMarshaller.PORTABLE_OBJ:
+ len = readInt() + 4;
+
+ break;
+
+ default:
+ throw new BinaryObjectException("Invalid flag value: " + type);
+ }
+
+ pos += len;
+ }
+
+ /**
+ * @param pos Position.
+ * @param len Length.
+ * @return Object.
+ */
+ public Object getValueQuickly(int pos, int len) {
+ byte type = arr[pos];
+
+ switch (type) {
+ case GridPortableMarshaller.NULL:
+ return null;
+
+ case GridPortableMarshaller.HANDLE: {
+ int objStart = pos - readIntPositioned(pos + 1);
+
+ BinaryObjectBuilderImpl res = objMap.get(objStart);
+
+ if (res == null) {
+ res = new BinaryObjectBuilderImpl(new PortableBuilderReader(this, objStart), objStart);
+
+ objMap.put(objStart, res);
+ }
+
+ return res;
+ }
+
+ case GridPortableMarshaller.OBJ: {
+ BinaryObjectBuilderImpl res = objMap.get(pos);
+
+ if (res == null) {
+ res = new BinaryObjectBuilderImpl(new PortableBuilderReader(this, pos), pos);
+
+ objMap.put(pos, res);
+ }
+
+ return res;
+ }
+
+ case GridPortableMarshaller.BYTE:
+ return arr[pos + 1];
+
+ case GridPortableMarshaller.SHORT:
+ return PortablePrimitives.readShort(arr, pos + 1);
+
+ case GridPortableMarshaller.INT:
+ return PortablePrimitives.readInt(arr, pos + 1);
+
+ case GridPortableMarshaller.LONG:
+ return PortablePrimitives.readLong(arr, pos + 1);
+
+ case GridPortableMarshaller.FLOAT:
+ return PortablePrimitives.readFloat(arr, pos + 1);
+
+ case GridPortableMarshaller.DOUBLE:
+ return PortablePrimitives.readDouble(arr, pos + 1);
+
+ case GridPortableMarshaller.CHAR:
+ return PortablePrimitives.readChar(arr, pos + 1);
+
+ case GridPortableMarshaller.BOOLEAN:
+ return arr[pos + 1] != 0;
+
+ case GridPortableMarshaller.DECIMAL:
+ case GridPortableMarshaller.STRING:
+ case GridPortableMarshaller.UUID:
+ case GridPortableMarshaller.DATE:
+ case GridPortableMarshaller.TIMESTAMP:
+ return new PortablePlainLazyValue(this, pos, len);
+
+ case GridPortableMarshaller.BYTE_ARR:
+ case GridPortableMarshaller.SHORT_ARR:
+ case GridPortableMarshaller.INT_ARR:
+ case GridPortableMarshaller.LONG_ARR:
+ case GridPortableMarshaller.FLOAT_ARR:
+ case GridPortableMarshaller.DOUBLE_ARR:
+ case GridPortableMarshaller.CHAR_ARR:
+ case GridPortableMarshaller.BOOLEAN_ARR:
+ case GridPortableMarshaller.DECIMAL_ARR:
+ case GridPortableMarshaller.DATE_ARR:
+ case GridPortableMarshaller.TIMESTAMP_ARR:
+ case GridPortableMarshaller.UUID_ARR:
+ case GridPortableMarshaller.STRING_ARR:
+ case GridPortableMarshaller.ENUM_ARR:
+ case GridPortableMarshaller.OBJ_ARR:
+ case GridPortableMarshaller.COL:
+ case GridPortableMarshaller.MAP:
+ return new LazyCollection(pos);
+
+ case GridPortableMarshaller.ENUM: {
+ if (len == 1) {
+ assert readByte(pos) == GridPortableMarshaller.NULL;
+
+ return null;
+ }
+
+ int mark = position();
+ position(pos + 1);
+
+ PortableBuilderEnum builderEnum = new PortableBuilderEnum(this);
+
+ position(mark);
+
+ return builderEnum;
+ }
+
+ case GridPortableMarshaller.PORTABLE_OBJ: {
+ int size = readIntPositioned(pos + 1);
+
+ int start = readIntPositioned(pos + 4 + size);
+
+ BinaryObjectImpl portableObj = new BinaryObjectImpl(ctx, arr, pos + 4 + start);
+
+ return new PortablePlainPortableObject(portableObj);
+ }
+
+ default:
+ throw new BinaryObjectException("Invalid flag value: " + type);
+ }
+ }
+
+ /**
+ * @return Parsed value.
+ */
+ public Object parseValue() {
+ int valPos = pos;
+
+ byte type = arr[pos++];
+
+ int plainLazyValLen;
+
+ boolean modifiableLazyVal = false;
+
+ switch (type) {
+ case GridPortableMarshaller.NULL:
+ return null;
+
+ case GridPortableMarshaller.HANDLE: {
+ int objStart = pos - 1 - readInt();
+
+ BinaryObjectBuilderImpl res = objMap.get(objStart);
+
+ if (res == null) {
+ res = new BinaryObjectBuilderImpl(new PortableBuilderReader(this, objStart), objStart);
+
+ objMap.put(objStart, res);
+ }
+
+ return res;
+ }
+
+ case GridPortableMarshaller.OBJ: {
+ pos--;
+
+ BinaryObjectBuilderImpl res = objMap.get(pos);
+
+ if (res == null) {
+ res = new BinaryObjectBuilderImpl(new PortableBuilderReader(this, pos), pos);
+
+ objMap.put(pos, res);
+ }
+
+ pos += readInt(GridPortableMarshaller.TOTAL_LEN_POS);
+
+ return res;
+ }
+
+ case GridPortableMarshaller.BYTE:
+ return arr[pos++];
+
+ case GridPortableMarshaller.SHORT: {
+ Object res = PortablePrimitives.readShort(arr, pos);
+ pos += 2;
+ return res;
+ }
+
+ case GridPortableMarshaller.INT:
+ return readInt();
+
+ case GridPortableMarshaller.LONG:
+ plainLazyValLen = 8;
+
+ break;
+
+ case GridPortableMarshaller.FLOAT:
+ plainLazyValLen = 4;
+
+ break;
+
+ case GridPortableMarshaller.DOUBLE:
+ plainLazyValLen = 8;
+
+ break;
+
+ case GridPortableMarshaller.CHAR:
+ plainLazyValLen = 2;
+
+ break;
+
+ case GridPortableMarshaller.BOOLEAN:
+ return arr[pos++] != 0;
+
+ case GridPortableMarshaller.DECIMAL:
+ plainLazyValLen = /** scale */ 4 + /** mag len */ 4 + /** mag bytes count */ readInt(4);
+
+ break;
+
+ case GridPortableMarshaller.STRING:
+ plainLazyValLen = 4 + readStringLength();
+
+ break;
+
+ case GridPortableMarshaller.UUID:
+ plainLazyValLen = 8 + 8;
+
+ break;
+
+ case GridPortableMarshaller.DATE:
+ plainLazyValLen = 8;
+
+ break;
+
+ case GridPortableMarshaller.TIMESTAMP:
+ plainLazyValLen = 8 + 4;
+
+ break;
+
+ case GridPortableMarshaller.BYTE_ARR:
+ plainLazyValLen = 4 + readLength();
+ modifiableLazyVal = true;
+
+ break;
+
+ case GridPortableMarshaller.SHORT_ARR:
+ plainLazyValLen = 4 + readLength() * 2;
+ modifiableLazyVal = true;
+
+ break;
+
+ case GridPortableMarshaller.INT_ARR:
+ plainLazyValLen = 4 + readLength() * 4;
+ modifiableLazyVal = true;
+
+ break;
+
+ case GridPortableMarshaller.LONG_ARR:
+ plainLazyValLen = 4 + readLength() * 8;
+ modifiableLazyVal = true;
+
+ break;
+
+ case GridPortableMarshaller.FLOAT_ARR:
+ plainLazyValLen = 4 + readLength() * 4;
+ modifiableLazyVal = true;
+
+ break;
+
+ case GridPortableMarshaller.DOUBLE_ARR:
+ plainLazyValLen = 4 + readLength() * 8;
+ modifiableLazyVal = true;
+
+ break;
+
+ case GridPortableMarshaller.CHAR_ARR:
+ plainLazyValLen = 4 + readLength() * 2;
+ modifiableLazyVal = true;
+
+ break;
+
+ case GridPortableMarshaller.BOOLEAN_ARR:
+ plainLazyValLen = 4 + readLength();
+ modifiableLazyVal = true;
+
+ break;
+
+ case GridPortableMarshaller.OBJ_ARR:
+ return new PortableObjectArrayLazyValue(this);
+
+ case GridPortableMarshaller.DATE_ARR: {
+ int size = readInt();
+
+ Date[] res = new Date[size];
+
+ for (int i = 0; i < res.length; i++) {
+ byte flag = arr[pos++];
+
+ if (flag == GridPortableMarshaller.NULL) continue;
+
+ if (flag != GridPortableMarshaller.DATE)
+ throw new BinaryObjectException("Invalid flag value: " + flag);
+
+ long time = PortablePrimitives.readLong(arr, pos);
+
+ pos += 8;
+
+ res[i] = new Date(time);
+ }
+
+ return res;
+ }
+
+ case GridPortableMarshaller.TIMESTAMP_ARR: {
+ int size = readInt();
+
+ Timestamp[] res = new Timestamp[size];
+
+ for (int i = 0; i < res.length; i++) {
+ byte flag = arr[pos++];
+
+ if (flag == GridPortableMarshaller.NULL)
+ continue;
+
+ if (flag != GridPortableMarshaller.TIMESTAMP)
+ throw new BinaryObjectException("Invalid flag value: " + flag);
+
+ long time = PortablePrimitives.readLong(arr, pos);
+
+ pos += 8;
+
+ int nano = PortablePrimitives.readInt(arr, pos);
+
+ pos += 4;
+
+ Timestamp ts = new Timestamp(time);
+
+ ts.setNanos(ts.getNanos() + nano);
+
+ res[i] = ts;
+ }
+
+ return res;
+ }
+
+ case GridPortableMarshaller.UUID_ARR:
+ case GridPortableMarshaller.STRING_ARR:
+ case GridPortableMarshaller.DECIMAL_ARR: {
+ int size = readInt();
+
+ for (int i = 0; i < size; i++) {
+ byte flag = arr[pos++];
+
+ if (flag == GridPortableMarshaller.UUID)
+ pos += 8 + 8;
+ else if (flag == GridPortableMarshaller.STRING)
+ pos += 4 + readStringLength();
+ else if (flag == GridPortableMarshaller.DECIMAL) {
+ pos += 4; // scale value
+ pos += 4 + readLength();
+ }
+ else
+ assert flag == GridPortableMarshaller.NULL;
+ }
+
+ return new PortableModifiableLazyValue(this, valPos, pos - valPos);
+ }
+
+ case GridPortableMarshaller.COL: {
+ int size = readInt();
+ byte colType = arr[pos++];
+
+ switch (colType) {
+ case GridPortableMarshaller.USER_COL:
+ case GridPortableMarshaller.ARR_LIST:
+ return new PortableLazyArrayList(this, size);
+
+ case GridPortableMarshaller.LINKED_LIST:
+ return new PortableLazyLinkedList(this, size);
+
+ case GridPortableMarshaller.HASH_SET:
+ case GridPortableMarshaller.LINKED_HASH_SET:
+ return new PortableLazySet(this, size);
+ }
+
+ throw new BinaryObjectException("Unknown collection type: " + colType);
+ }
+
+ case GridPortableMarshaller.MAP:
+ return PortableLazyMap.parseMap(this);
+
+ case GridPortableMarshaller.ENUM:
+ return new PortableBuilderEnum(this);
+
+ case GridPortableMarshaller.ENUM_ARR:
+ return new PortableEnumArrayLazyValue(this);
+
+ case GridPortableMarshaller.PORTABLE_OBJ: {
+ int size = readInt();
+
+ pos += size;
+
+ int start = readInt();
+
+ BinaryObjectImpl portableObj = new BinaryObjectImpl(ctx, arr,
+ pos - 4 - size + start);
+
+ return new PortablePlainPortableObject(portableObj);
+ }
+
+ default:
+ throw new BinaryObjectException("Invalid flag value: " + type);
+ }
+
+ PortableAbstractLazyValue res;
+
+ if (modifiableLazyVal)
+ res = new PortableModifiableLazyValue(this, valPos, 1 + plainLazyValLen);
+ else
+ res = new PortablePlainLazyValue(this, valPos, 1 + plainLazyValLen);
+
+ pos += plainLazyValLen;
+
+ return res;
+ }
+
+ /**
+ * @return Array.
+ */
+ public byte[] array() {
+ return arr;
+ }
+
+ /**
+ * @return Position of reader.
+ */
+ public int position() {
+ return pos;
+ }
+
+ /**
+ * @param pos New pos.
+ */
+ public void position(int pos) {
+ this.pos = pos;
+ }
+
+ /**
+ * @param n Number of bytes to skip.
+ */
+ public void skip(int n) {
+ pos += n;
+ }
+
+ /**
+ * @return Reader.
+ */
+ BinaryReaderExImpl reader() {
+ return reader;
+ }
+
+ /**
+ *
+ */
+ private class LazyCollection implements PortableLazyValue {
+ /** */
+ private final int valOff;
+
+ /** */
+ private Object col;
+
+ /**
+ * @param valOff Value.
+ */
+ protected LazyCollection(int valOff) {
+ this.valOff = valOff;
+ }
+
+ /**
+ * @return Object.
+ */
+ private Object wrappedCollection() {
+ if (col == null) {
+ position(valOff);
+
+ col = parseValue();
+ }
+
+ return col;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeTo(BinaryWriterExImpl writer, PortableBuilderSerializer ctx) {
+ ctx.writeValue(writer, wrappedCollection());
+ }
+
+ /** {@inheritDoc} */
+ @Override public Object value() {
+ return PortableUtils.unwrapLazy(wrappedCollection());
+ }
+ }
+}