You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ag...@apache.org on 2015/11/02 18:21:59 UTC
[11/29] ignite git commit: Merge branch ignite-1282 into
ignite-950-new
Merge branch ignite-1282 into ignite-950-new
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/71d18bb4
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/71d18bb4
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/71d18bb4
Branch: refs/heads/ignite-950-new
Commit: 71d18bb4d33032b140227be35aea99543621af0b
Parents: f957ed4 fd640d7
Author: Alexey Goncharuk <al...@gmail.com>
Authored: Mon Nov 2 19:39:51 2015 +0300
Committer: Alexey Goncharuk <al...@gmail.com>
Committed: Mon Nov 2 19:39:51 2015 +0300
----------------------------------------------------------------------
.../internal/portable/IgniteObjectImpl.java | 33 +-
.../portable/PortablePositionReadable.java | 8 +
.../internal/portable/PortablePrimitives.java | 755 ++++---------------
.../ignite/internal/portable/PortableUtils.java | 15 +
.../builder/IgniteObjectBuilderImpl.java | 2 +-
.../portable/builder/PortableBuilderReader.java | 41 +-
.../streams/PortableAbstractInputStream.java | 18 +
.../streams/PortableHeapInputStream.java | 5 +
.../streams/PortableOffheapInputStream.java | 5 +
.../PlatformBigEndianInputStreamImpl.java | 5 +
.../memory/PlatformInputStreamImpl.java | 10 +
.../src/impl/portable/portable_reader_impl.cpp | 44 --
12 files changed, 261 insertions(+), 680 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/71d18bb4/modules/core/src/main/java/org/apache/ignite/internal/portable/IgniteObjectImpl.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/portable/IgniteObjectImpl.java
index 7b16b66,0000000..639435b
mode 100644,000000..100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/IgniteObjectImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/IgniteObjectImpl.java
@@@ -1,541 -1,0 +1,538 @@@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.portable;
+
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.GridDirectTransient;
+import org.apache.ignite.internal.IgniteCodeGeneratingFail;
+import org.apache.ignite.internal.portable.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.portable.CacheObjectPortableProcessorImpl;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.plugin.extensions.communication.Message;
+import org.apache.ignite.plugin.extensions.communication.MessageReader;
+import org.apache.ignite.plugin.extensions.communication.MessageWriter;
+import org.apache.ignite.igniteobject.IgniteObjectException;
+import org.apache.ignite.igniteobject.IgniteObjectMetadata;
+import org.apache.ignite.igniteobject.IgniteObject;
+import org.apache.ignite.portable.PortableField;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.nio.ByteBuffer;
+
+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.
+ */
+@IgniteCodeGeneratingFail // Fields arr and start should not be generated by MessageCodeGenerator.
+public final class IgniteObjectImpl extends IgniteObjectEx implements Externalizable,
+ Message, CacheObject, KeyCacheObject {
+ /** */
+ public static final byte TYPE_PORTABLE = 100;
+
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** */
- private static final PortablePrimitives PRIM = PortablePrimitives.get();
-
- /** */
+ @GridDirectTransient
+ private PortableContext ctx;
+
+ /** */
+ private byte[] arr;
+
+ /** */
+ private int start;
+
+ /** */
+ @GridDirectTransient
+ private Object obj;
+
+ /** */
+ @GridDirectTransient
+ private boolean detachAllowed;
+
+ /**
+ * For {@link Externalizable}.
+ */
+ public IgniteObjectImpl() {
+ // No-op.
+ }
+
+ /**
+ * @param ctx Context.
+ * @param arr Array.
+ * @param start Start.
+ */
+ public IgniteObjectImpl(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 type() {
+ return TYPE_PORTABLE;
+ }
+
+ /** {@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)
+ obj0 = deserializeValue();
+
+ 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 (IgniteObjectImpl)detach();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void finishUnmarshal(CacheObjectContext ctx, ClassLoader ldr) throws IgniteCheckedException {
+ this.ctx = ((CacheObjectPortableProcessorImpl)ctx.processor()).portableContext();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void prepareMarshal(CacheObjectContext ctx) throws IgniteCheckedException {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public int length() {
- return PRIM.readInt(arr, start + GridPortableMarshaller.TOTAL_LEN_POS);
++ return PortablePrimitives.readInt(arr, start + GridPortableMarshaller.TOTAL_LEN_POS);
+ }
+
+ /**
+ * @return Detached portable object.
+ */
+ public IgniteObject detach() {
+ if (!detachAllowed || detached())
+ return this;
+
+ int len = length();
+
+ byte[] arr0 = new byte[len];
+
+ U.arrayCopy(arr, start, arr0, 0, len);
+
+ return new IgniteObjectImpl(ctx, arr0, 0);
+ }
+
+ /**
+ * @return Detached or not.
+ */
+ public boolean detached() {
+ return start == 0 && length() == arr.length;
+ }
+
+ /**
+ * @return {@code True} if detach is allowed.
+ */
+ public boolean detachAllowed() {
+ return true;
+ }
+
+ /**
+ * @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 PRIM.readInt(arr, start + GridPortableMarshaller.TYPE_ID_POS);
++ return PortablePrimitives.readInt(arr, start + GridPortableMarshaller.TYPE_ID_POS);
+ }
+
+ /** {@inheritDoc} */
+ @Nullable @Override public IgniteObjectMetadata metaData() throws IgniteObjectException {
+ if (ctx == null)
+ throw new IgniteObjectException("PortableContext is not set for the object.");
+
+ return ctx.metaData(typeId());
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Nullable @Override public <F> F field(String fieldName) throws IgniteObjectException {
+ IgniteObjectReaderExImpl reader = new IgniteObjectReaderExImpl(ctx, arr, start, null);
+
+ return (F)reader.unmarshalField(fieldName);
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Nullable @Override public <F> F field(int fieldId) throws IgniteObjectException {
+ IgniteObjectReaderExImpl reader = new IgniteObjectReaderExImpl(ctx, arr, start, null);
+
+ return (F)reader.unmarshalField(fieldId);
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Nullable @Override protected <F> F fieldByOffset(int fieldOffset) {
+ Object val;
+
- int schemaOffset = PRIM.readInt(arr, start + GridPortableMarshaller.SCHEMA_OR_RAW_OFF_POS);
- int fieldPos = PRIM.readInt(arr, start + schemaOffset + fieldOffset);
++ int schemaOffset = PortablePrimitives.readInt(arr, start + GridPortableMarshaller.SCHEMA_OR_RAW_OFF_POS);
++ int fieldPos = PortablePrimitives.readInt(arr, start + schemaOffset + fieldOffset);
+
+ // Read header and try performing fast lookup for well-known types (the most common types go first).
- byte hdr = PRIM.readByte(arr, fieldPos);
++ byte hdr = PortablePrimitives.readByte(arr, fieldPos);
+
+ switch (hdr) {
+ case INT:
- val = PRIM.readInt(arr, fieldPos + 1);
++ val = PortablePrimitives.readInt(arr, fieldPos + 1);
+
+ break;
+
+ case LONG:
- val = PRIM.readLong(arr, fieldPos + 1);
++ val = PortablePrimitives.readLong(arr, fieldPos + 1);
+
+ break;
+
+ case BOOLEAN:
- val = PRIM.readBoolean(arr, fieldPos + 1);
++ val = PortablePrimitives.readBoolean(arr, fieldPos + 1);
+
+ break;
+
+ case SHORT:
- val = PRIM.readShort(arr, fieldPos + 1);
++ val = PortablePrimitives.readShort(arr, fieldPos + 1);
+
+ break;
+
+ case BYTE:
- val = PRIM.readByte(arr, fieldPos + 1);
++ val = PortablePrimitives.readByte(arr, fieldPos + 1);
+
+ break;
+
+ case CHAR:
- val = PRIM.readChar(arr, fieldPos + 1);
++ val = PortablePrimitives.readChar(arr, fieldPos + 1);
+
+ break;
+
+ case FLOAT:
- val = PRIM.readFloat(arr, fieldPos + 1);
++ val = PortablePrimitives.readFloat(arr, fieldPos + 1);
+
+ break;
+
+ case DOUBLE:
- val = PRIM.readDouble(arr, fieldPos + 1);
++ val = PortablePrimitives.readDouble(arr, fieldPos + 1);
+
+ 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.
+ IgniteObjectReaderExImpl reader = new IgniteObjectReaderExImpl(ctx, arr, start, null);
+
+ val = reader.unmarshalFieldByOffset(fieldOffset);
+ }
+ }
+
+ return (F)val;
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Nullable @Override protected <F> F field(PortableReaderContext rCtx, String fieldName) {
+ IgniteObjectReaderExImpl reader = new IgniteObjectReaderExImpl(ctx,
+ new PortableHeapInputStream(arr),
+ start,
+ null,
+ rCtx);
+
+ return (F)reader.unmarshalField(fieldName);
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean hasField(String fieldName) {
+ IgniteObjectReaderExImpl reader = new IgniteObjectReaderExImpl(ctx, arr, start, null);
+
+ return reader.hasField(fieldName);
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Nullable @Override public <T> T deserialize() throws IgniteObjectException {
+ Object obj0 = obj;
+
+ if (obj0 == null)
+ obj0 = deserializeValue();
+
+ return (T)obj0;
+
+ }
+
+ /** {@inheritDoc} */
+ @Override public IgniteObject clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
- return PRIM.readInt(arr, start + GridPortableMarshaller.HASH_CODE_POS);
++ return PortablePrimitives.readInt(arr, start + GridPortableMarshaller.HASH_CODE_POS);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected int schemaId() {
- return PRIM.readInt(arr, start + GridPortableMarshaller.SCHEMA_ID_POS);
++ return PortablePrimitives.readInt(arr, start + GridPortableMarshaller.SCHEMA_ID_POS);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected PortableSchema createSchema() {
+ IgniteObjectReaderExImpl reader = new IgniteObjectReaderExImpl(ctx, arr, start, null);
+
+ return reader.createSchema();
+ }
+
+ /** {@inheritDoc} */
+ @Override public PortableField fieldDescriptor(String fieldName) throws IgniteObjectException {
+ int typeId = typeId();
+
+ PortableSchemaRegistry schemaReg = ctx.schemaRegistry(typeId);
+
+ int fieldId = ctx.userTypeIdMapper(typeId).fieldId(typeId, fieldName);
+
+ return new PortableFieldImpl(schemaReg, fieldId);
+ }
+
+ /** {@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.
+ */
+ private Object deserializeValue() {
+ // TODO: IGNITE-1272 - Deserialize with proper class loader.
+ IgniteObjectReaderExImpl reader = new IgniteObjectReaderExImpl(ctx, arr, start, null);
+
+ Object obj0 = reader.deserialize();
+
+ PortableClassDescriptor desc = reader.descriptor();
+
+ assert desc != null;
+
+ if (desc.keepDeserialized())
+ obj = obj0;
+
+ return obj0;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/71d18bb4/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableUtils.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/71d18bb4/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/IgniteObjectBuilderImpl.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/portable/builder/IgniteObjectBuilderImpl.java
index 7c167f3,0000000..2783f8a
mode 100644,000000..100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/IgniteObjectBuilderImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/IgniteObjectBuilderImpl.java
@@@ -1,551 -1,0 +1,551 @@@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.portable.builder;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+import org.apache.ignite.igniteobject.IgniteObject;
+import org.apache.ignite.igniteobject.IgniteObjectBuilder;
+import org.apache.ignite.igniteobject.IgniteObjectException;
+import org.apache.ignite.igniteobject.IgniteObjectInvalidClassException;
+import org.apache.ignite.igniteobject.IgniteObjectMetadata;
+import org.apache.ignite.internal.portable.IgniteObjectImpl;
+import org.apache.ignite.internal.portable.IgniteObjectOffheapImpl;
+import org.apache.ignite.internal.portable.IgniteObjectWriterExImpl;
+import org.apache.ignite.internal.portable.PortableContext;
+import org.apache.ignite.internal.portable.PortableUtils;
+import org.apache.ignite.internal.processors.cache.portable.CacheObjectPortableProcessorImpl;
+import org.apache.ignite.internal.util.GridArgumentCheck;
+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 static org.apache.ignite.internal.portable.GridPortableMarshaller.DFLT_HDR_LEN;
+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;
+import static org.apache.ignite.internal.portable.GridPortableMarshaller.UNREGISTERED_TYPE_ID;
+
+/**
+ *
+ */
+public class IgniteObjectBuilderImpl implements IgniteObjectBuilder {
+ /** */
+ 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;
+
+ /** 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 IgniteObjectBuilderImpl(PortableContext ctx, String clsName) {
+ this(ctx, ctx.typeId(clsName), PortableContext.typeName(clsName));
+ }
+
+ /**
+ * @param typeId Type ID.
+ * @param ctx Portable context.
+ */
+ public IgniteObjectBuilderImpl(PortableContext ctx, int typeId) {
+ this(ctx, typeId, null);
+ }
+
+ /**
+ * @param typeName Type name.
+ * @param ctx Context.
+ * @param typeId Type id.
+ */
+ public IgniteObjectBuilderImpl(PortableContext ctx, int typeId, String typeName) {
+ this.typeId = typeId;
+ this.typeName = typeName;
+ this.ctx = ctx;
+
+ start = -1;
+ reader = null;
+ hdrLen = DFLT_HDR_LEN;
+
+ readCache = Collections.emptyMap();
+ }
+
+ /**
+ * @param obj Object to wrap.
+ */
+ public IgniteObjectBuilderImpl(IgniteObjectImpl obj) {
+ this(new PortableBuilderReader(obj), obj.start());
+
+ reader.registerObject(this);
+ }
+
+ /**
+ * @param reader ctx
+ * @param start Start.
+ */
+ IgniteObjectBuilderImpl(PortableBuilderReader reader, int start) {
+ this.reader = reader;
+ this.start = start;
+
- byte ver = reader.readByteAbsolute(start + PROTO_VER_POS);
++ byte ver = reader.readBytePositioned(start + PROTO_VER_POS);
+
+ PortableUtils.checkProtocolVersion(ver);
+
+ int typeId = reader.readIntPositioned(start + TYPE_ID_POS);
+ ctx = reader.portableContext();
+ hashCode = reader.readIntPositioned(start + HASH_CODE_POS);
+
+ if (typeId == UNREGISTERED_TYPE_ID) {
+ int mark = reader.position();
+
+ reader.position(start + DFLT_HDR_LEN);
+
+ clsNameToWrite = reader.readString();
+
+ Class cls;
+
+ try {
+ // TODO: IGNITE-1272 - Is class loader needed here?
+ cls = U.forName(clsNameToWrite, null);
+ }
+ catch (ClassNotFoundException e) {
+ throw new IgniteObjectInvalidClassException("Failed to load the class: " + clsNameToWrite, e);
+ }
+
+ this.typeId = ctx.descriptorForClass(cls).typeId();
+
+ registeredType = false;
+
+ hdrLen = reader.position() - mark;
+
+ reader.position(mark);
+ }
+ else {
+ this.typeId = typeId;
+ hdrLen = DFLT_HDR_LEN;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public IgniteObject build() {
+ try (IgniteObjectWriterExImpl writer = new IgniteObjectWriterExImpl(ctx, typeId, false)) {
+
+ PortableBuilderSerializer serializationCtx = new PortableBuilderSerializer();
+
+ serializationCtx.registerObjectWriting(this, 0);
+
+ serializeTo(writer, serializationCtx);
+
+ byte[] arr = writer.array();
+
+ return new IgniteObjectImpl(ctx, arr, 0);
+ }
+ }
+
+ /**
+ * @param writer Writer.
+ * @param serializer Serializer.
+ */
+ void serializeTo(IgniteObjectWriterExImpl writer, PortableBuilderSerializer serializer) {
+ PortableUtils.writeHeader(writer,
+ true,
+ registeredType ? typeId : UNREGISTERED_TYPE_ID,
+ hashCode,
+ registeredType ? null : clsNameToWrite);
+
+ Set<Integer> remainsFlds = null;
+
+ if (reader != null) {
+ Map<Integer, Object> assignedFldsById;
+
+ if (assignedVals != null) {
+ assignedFldsById = U.newHashMap(assignedVals.size());
+
+ for (Map.Entry<String, Object> entry : assignedVals.entrySet()) {
+ int fldId = ctx.fieldId(typeId, entry.getKey());
+
+ assignedFldsById.put(fldId, entry.getValue());
+ }
+
+ remainsFlds = assignedFldsById.keySet();
+ }
+ else
+ assignedFldsById = Collections.emptyMap();
+
+ // Get footer details.
+ 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);
+
+ while (reader.position() < rawPos) {
+ int fieldId = reader.readIntPositioned(footerPos);
+ int fieldLen = fieldPositionAndLength(footerPos, footerEnd, rawPos).get2();
+
+ footerPos += 8;
+
+ if (assignedFldsById.containsKey(fieldId)) {
+ Object assignedVal = assignedFldsById.remove(fieldId);
+
+ reader.skip(fieldLen);
+
+ 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);
+
+ reader.skip(fieldLen);
+ }
+ else {
+ writer.writeFieldId(fieldId);
+
+ Object val;
+
+ if (fieldLen == 0)
+ val = null;
+ else if (readCache == null) {
+ int savedPos = reader.position();
+
+ val = reader.parseValue();
+
+ assert reader.position() == savedPos + fieldLen;
+ }
+ else {
+ val = readCache.get(fieldId);
+
+ reader.skip(fieldLen);
+ }
+
+ serializer.writeValue(writer, val);
+ }
+ }
+ }
+ }
+
+ if (assignedVals != null && (remainsFlds == null || !remainsFlds.isEmpty())) {
+ boolean metadataEnabled = ctx.isMetaDataEnabled(typeId);
+
+ IgniteObjectMetadata metadata = null;
+
+ if (metadataEnabled)
+ metadata = ctx.metaData(typeId);
+
+ Map<String, String> newFldsMetadata = null;
+
+ for (Map.Entry<String, Object> entry : assignedVals.entrySet()) {
+ Object val = entry.getValue();
+
+ if (val == REMOVED_FIELD_MARKER)
+ continue;
+
+ String name = entry.getKey();
+
+ int fldId = ctx.fieldId(typeId, name);
+
+ if (remainsFlds != null && !remainsFlds.contains(fldId))
+ continue;
+
+ writer.writeFieldId(fldId);
+
+ serializer.writeValue(writer, val);
+
+ if (metadataEnabled) {
+ String oldFldTypeName = metadata == null ? null : metadata.fieldTypeName(name);
+
+ String newFldTypeName;
+
+ if (val instanceof PortableValueWithType)
+ newFldTypeName = ((PortableValueWithType)val).typeName();
+ else {
+ byte type = PortableUtils.typeByClass(val.getClass());
+
+ newFldTypeName = CacheObjectPortableProcessorImpl.fieldTypeName(type);
+ }
+
+ 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 IgniteObjectException(
+ "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 (typeName == null)
+ typeName = metadata.typeName();
+
+ 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 (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);
+ }
+
+ /** {@inheritDoc} */
+ @Override public IgniteObjectBuilderImpl 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).
+ * @return Tuple with field position and length.
+ */
+ private IgniteBiTuple<Integer, Integer> fieldPositionAndLength(int footerPos, int footerEnd, int rawPos) {
+ int fieldOffset = reader.readIntPositioned(footerPos + 4);
+ int fieldPos = start + fieldOffset;
+
+ // Get field length.
+ int fieldLen;
+
+ if (footerPos + 8 == 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);
+
+ fieldLen = nextFieldOffset - fieldOffset;
+ }
+
+ return F.t(fieldPos, fieldLen);
+ }
+
+ /**
+ * Initialize read cache if needed.
+ */
+ private void ensureReadCacheInit() {
+ if (readCache == null) {
+ 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);
+
+ while (footerPos < footerEnd) {
+ int fieldId = reader.readIntPositioned(footerPos);
+
+ IgniteBiTuple<Integer, Integer> posAndLen = fieldPositionAndLength(footerPos, footerEnd, rawPos);
+
+ Object val = reader.getValueQuickly(posAndLen.get1(), posAndLen.get2());
+
+ readCache.put(fieldId, val);
+
+ // Shift current footer position.
+ footerPos += 8;
+ }
+
+ 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 IgniteObjectBuilder setField(String name, Object val) {
+ GridArgumentCheck.notNull(val, name);
+
+ if (assignedVals == null)
+ assignedVals = new LinkedHashMap<>();
+
+ Object oldVal = assignedVals.put(name, val);
+
+ if (oldVal instanceof PortableValueWithType) {
+ ((PortableValueWithType)oldVal).value(val);
+
+ assignedVals.put(name, oldVal);
+ }
+
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override public <T> IgniteObjectBuilder setField(String name, @Nullable T val, Class<? super T> type) {
+ if (assignedVals == null)
+ assignedVals = new LinkedHashMap<>();
+
+ //int fldId = ctx.fieldId(typeId, fldName);
+
+ assignedVals.put(name, new PortableValueWithType(PortableUtils.typeByClass(type), val));
+
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override public IgniteObjectBuilder setField(String name, @Nullable IgniteObjectBuilder 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 IgniteObjectBuilderImpl 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 IgniteObjectBuilderImpl wrap(IgniteObject obj) {
+ IgniteObjectImpl heapObj;
+
+ if (obj instanceof IgniteObjectOffheapImpl)
+ heapObj = (IgniteObjectImpl)((IgniteObjectOffheapImpl)obj).heapCopy();
+ else
+ heapObj = (IgniteObjectImpl)obj;
+
+ return new IgniteObjectBuilderImpl(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/71d18bb4/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderReader.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderReader.java
index cf8ad20,9645ced..abea3c0
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderReader.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderReader.java
@@@ -40,10 -40,7 +40,7 @@@ import static org.apache.ignite.interna
*/
public class PortableBuilderReader implements PortablePositionReadable {
/** */
- private static final PortablePrimitives PRIM = PortablePrimitives.get();
-
- /** */
- private final Map<Integer, PortableBuilderImpl> objMap = new HashMap<>();
+ private final Map<Integer, IgniteObjectBuilderImpl> objMap = new HashMap<>();
/** */
private final PortableContext ctx;
@@@ -636,9 -633,9 +633,9 @@@
if (flag == GridPortableMarshaller.NULL) continue;
if (flag != GridPortableMarshaller.DATE)
- throw new PortableException("Invalid flag value: " + flag);
+ throw new IgniteObjectException("Invalid flag value: " + flag);
- long time = PRIM.readLong(arr, pos);
+ long time = PortablePrimitives.readLong(arr, pos);
pos += 8;
@@@ -660,9 -657,9 +657,9 @@@
continue;
if (flag != GridPortableMarshaller.TIMESTAMP)
- throw new PortableException("Invalid flag value: " + flag);
+ throw new IgniteObjectException("Invalid flag value: " + flag);
- long time = PRIM.readLong(arr, pos);
+ long time = PortablePrimitives.readLong(arr, pos);
pos += 8;
http://git-wip-us.apache.org/repos/asf/ignite/blob/71d18bb4/modules/core/src/main/java/org/apache/ignite/internal/portable/streams/PortableAbstractInputStream.java
----------------------------------------------------------------------