Return-Path: X-Original-To: apmail-ignite-commits-archive@minotaur.apache.org Delivered-To: apmail-ignite-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 9A06D18A66 for ; Tue, 25 Aug 2015 09:08:32 +0000 (UTC) Received: (qmail 54407 invoked by uid 500); 25 Aug 2015 09:08:32 -0000 Delivered-To: apmail-ignite-commits-archive@ignite.apache.org Received: (qmail 54351 invoked by uid 500); 25 Aug 2015 09:08:32 -0000 Mailing-List: contact commits-help@ignite.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@ignite.apache.org Delivered-To: mailing list commits@ignite.apache.org Received: (qmail 54202 invoked by uid 99); 25 Aug 2015 09:08:32 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 25 Aug 2015 09:08:32 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id B7F52E713A; Tue, 25 Aug 2015 09:08:31 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: sboikov@apache.org To: commits@ignite.apache.org Date: Tue, 25 Aug 2015 09:08:42 -0000 Message-Id: <40fae44f00744402a76ac053be1d6833@git.apache.org> In-Reply-To: <01ae7429b82644bd8e8f218a32dde56a@git.apache.org> References: <01ae7429b82644bd8e8f218a32dde56a@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [12/19] ignite git commit: ignite-1258: portable objects API support in Ignite http://git-wip-us.apache.org/repos/asf/ignite/blob/878dcd92/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableReaderExImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableReaderExImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableReaderExImpl.java new file mode 100644 index 0000000..2a6c2e3 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableReaderExImpl.java @@ -0,0 +1,2949 @@ +/* + * 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.*; +import org.apache.ignite.internal.portable.streams.*; +import org.apache.ignite.internal.util.*; +import org.apache.ignite.internal.util.lang.*; +import org.apache.ignite.internal.util.typedef.internal.*; +import org.apache.ignite.portable.*; + +import org.jetbrains.annotations.*; + +import java.io.*; +import java.lang.reflect.Array; +import java.lang.reflect.*; +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.Date; +import java.util.concurrent.*; + +import static java.nio.charset.StandardCharsets.*; +import static org.apache.ignite.internal.portable.GridPortableMarshaller.*; + +/** + * Portable reader implementation. + */ +@SuppressWarnings("unchecked") +public class PortableReaderExImpl implements PortableReader, PortableRawReaderEx, ObjectInput { + /** */ + private final PortableContext ctx; + + /** */ + private final PortableInputStream in; + + /** */ + private final int start; + + /** */ + private final PortableReaderContext rCtx; + + /** */ + private final ClassLoader ldr; + + /** */ + private int off; + + /** */ + private int rawOff; + + /** */ + private int len; + + /** */ + private PortableClassDescriptor desc; + + /** */ + private int hdrLen; + + /** */ + private int clsNameLen; + + /** */ + private Integer typeId; + + /** + * @param ctx Context. + * @param arr Array. + * @param start Start. + * @param ldr Class loader. + */ + PortableReaderExImpl(PortableContext ctx, byte[] arr, int start, ClassLoader ldr) { + this(ctx, new PortableHeapInputStream(arr), start, ldr, new PortableReaderContext()); + } + + /** + * @param ctx Context. + * @param in Input stream. + * @param start Start. + */ + PortableReaderExImpl(PortableContext ctx, PortableInputStream in, int start, ClassLoader ldr) { + this(ctx, in, start, ldr, new PortableReaderContext()); + } + + /** + * @param ctx Context. + * @param in Input stream. + * @param start Start. + * @param rCtx Context. + */ + PortableReaderExImpl(PortableContext ctx, PortableInputStream in, int start, ClassLoader ldr, + PortableReaderContext rCtx) { + this.ctx = ctx; + this.in = in; + this.start = start; + this.ldr = ldr; + this.rCtx = rCtx; + + off = start; + rawOff = start; + } + + /** + * Preloads typeId from the input array. + */ + private void readObjectTypeId(boolean skipObjByte) { + int pos = rawOff; + + if (!skipObjByte) + // skip obj type byte + rawOff++; + + // skip user flag + rawOff += 1; + + typeId = doReadInt(true); + + if (typeId == UNREGISTERED_TYPE_ID) { + // skip hash code, length and raw offset + rawOff += 12; + + int off = rawOff; + + Class cls = doReadClass(true, typeId); + + // registers class by typeId, at least locally if the cache is not ready yet. + PortableClassDescriptor desc = ctx.descriptorForClass(cls); + + typeId = desc.typeId(); + + clsNameLen = rawOff - off; + + hdrLen = CLS_NAME_POS + clsNameLen; + } + else + hdrLen = DFLT_HDR_LEN; + + in.position(rawOff = pos); + } + + /** + * @return Descriptor. + */ + PortableClassDescriptor descriptor() { + return desc; + } + + /** + * @return Unmarshalled value. + * @throws PortableException In case of error. + */ + @Nullable Object unmarshal() throws PortableException { + return unmarshal(true); + } + + /** + * @param fieldName Field name. + * @return Unmarshalled value. + * @throws PortableException In case of error. + */ + @Nullable Object unmarshal(String fieldName) throws PortableException { + off = fieldOffset(fieldId(fieldName)); + + return off >= 0 ? unmarshal(false) : null; + } + + /** + * @param offset Offset in the array. + * @return Unmarshalled value. + * @throws PortableException In case of error. + */ + Object unmarshal(int offset) throws PortableException { + off = offset; + + return off >= 0 ? unmarshal(false) : null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable Byte readByte(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != BYTE) + throw new PortableException("Invalid flag value: " + flag); + + return doReadByte(false); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable Short readShort(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != SHORT) + throw new PortableException("Invalid flag value: " + flag); + + return doReadShort(false); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable Integer readInt(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != INT) + throw new PortableException("Invalid flag value: " + flag); + + return doReadInt(false); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable Long readLong(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != LONG) + throw new PortableException("Invalid flag value: " + flag); + + return doReadLong(false); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable Float readFloat(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != FLOAT) + throw new PortableException("Invalid flag value: " + flag); + + return doReadFloat(false); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable Double readDouble(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != DOUBLE) + throw new PortableException("Invalid flag value: " + flag); + + return doReadDouble(false); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable Character readChar(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != CHAR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadChar(false); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable Boolean readBoolean(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != BOOLEAN) + throw new PortableException("Invalid flag value: " + flag); + + return doReadBoolean(false); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable BigDecimal readDecimal(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != DECIMAL) + throw new PortableException("Invalid flag value: " + flag); + + return doReadDecimal(false); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable String readString(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != STRING) + throw new PortableException("Invalid flag value: " + flag); + + return doReadString(false); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable UUID readUuid(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != UUID) + throw new PortableException("Invalid flag value: " + flag); + + return doReadUuid(false); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable Date readDate(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != DATE) + throw new PortableException("Invalid flag value: " + flag); + + return doReadDate(false); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable Timestamp readTimestamp(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != DATE) + throw new PortableException("Invalid flag value: " + flag); + + return doReadTimestamp(false); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable Object readObject(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + return off >= 0 ? doReadObject(false) : null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable byte[] readByteArray(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != BYTE_ARR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadByteArray(false); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable short[] readShortArray(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != SHORT_ARR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadShortArray(false); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable int[] readIntArray(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != INT_ARR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadIntArray(false); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable long[] readLongArray(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != LONG_ARR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadLongArray(false); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable float[] readFloatArray(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != FLOAT_ARR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadFloatArray(false); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable double[] readDoubleArray(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != DOUBLE_ARR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadDoubleArray(false); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable char[] readCharArray(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != CHAR_ARR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadCharArray(false); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable boolean[] readBooleanArray(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != BOOLEAN_ARR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadBooleanArray(false); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable BigDecimal[] readDecimalArray(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != DECIMAL_ARR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadDecimalArray(false); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable String[] readStringArray(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != STRING_ARR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadStringArray(false); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable UUID[] readUuidArray(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != UUID_ARR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadUuidArray(false); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable Date[] readDateArray(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != DATE_ARR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadDateArray(false); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable Object[] readObjectArray(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != OBJ_ARR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadObjectArray(false, true); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @param cls Collection class. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable Collection readCollection(int fieldId, @Nullable Class cls) + throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != COL) + throw new PortableException("Invalid flag value: " + flag); + + return (Collection)doReadCollection(false, true, cls); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @param cls Map class. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable Map readMap(int fieldId, @Nullable Class cls) + throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != MAP) + throw new PortableException("Invalid flag value: " + flag); + + return doReadMap(false, true, cls); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Value. + * @throws PortableException On case of error. + */ + @Nullable Map.Entry readMapEntry(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != MAP_ENTRY) + throw new PortableException("Invalid flag value: " + flag); + + return new GridMapEntry<>(doReadObject(false), doReadObject(false)); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Portable object. + * @throws PortableException In case of error. + */ + @Nullable PortableObject readPortableObject(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != PORTABLE_OBJ) + throw new PortableException("Invalid flag value: " + flag); + + return new PortableObjectImpl(ctx, doReadByteArray(false), doReadInt(false)); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @param cls Class. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable Enum readEnum(int fieldId, @Nullable Class cls) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != ENUM) + throw new PortableException("Invalid flag value: " + flag); + + // Revisit: why have we started writing Class for enums in their serialized form? + if (cls == null) + cls = doReadClass(false); + else + doReadClass(false); + + Object[] vals = GridEnumCache.get(cls); + + return (Enum)vals[doReadInt(false)]; + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @param cls Class. + * @return Value. + * @throws PortableException In case of error. + */ + @Nullable Object[] readEnumArray(int fieldId, @Nullable Class cls) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != ENUM_ARR) + throw new PortableException("Invalid flag value: " + flag); + + // Revisit: why have we started writing Class for enums in their serialized form? + if (cls == null) + cls = doReadClass(false); + else + doReadClass(false); + + return doReadEnumArray(false, cls); + } + else + return null; + } + + /** + * @param fieldId Field ID. + * @return Field class. + * @throws PortableException In case of error. + */ + @Nullable Class readClass(int fieldId) throws PortableException { + off = fieldOffset(fieldId); + + if (off >= 0) { + byte flag = doReadByte(false); + + if (flag == NULL) + return null; + + if (flag != CLASS) + throw new PortableException("Invalid flag type: [flag=" + flag + ']'); + + return doReadClass(false); + } + + return null; + } + + /** + * @param obj Object. + */ + void setHandler(Object obj) { + rCtx.setObjectHandler(start, obj); + } + + /** {@inheritDoc} */ + @Override public byte readByte(String fieldName) throws PortableException { + Byte val = readByte(fieldId(fieldName)); + + return val != null ? val : 0; + } + + /** {@inheritDoc} */ + @Override public byte readByte() throws PortableException { + return doReadByte(true); + } + + /** {@inheritDoc} */ + @Override public short readShort(String fieldName) throws PortableException { + Short val = readShort(fieldId(fieldName)); + + return val != null ? val : 0; + } + + /** {@inheritDoc} */ + @Override public short readShort() throws PortableException { + return doReadShort(true); + } + + /** {@inheritDoc} */ + @Override public int readInt(String fieldName) throws PortableException { + Integer val = readInt(fieldId(fieldName)); + + return val != null ? val : 0; + } + + /** {@inheritDoc} */ + @Override public int readInt() throws PortableException { + return doReadInt(true); + } + + /** {@inheritDoc} */ + @Override public long readLong(String fieldName) throws PortableException { + Long val = readLong(fieldId(fieldName)); + + return val != null ? val : 0; + } + + /** {@inheritDoc} */ + @Override public long readLong() throws PortableException { + return doReadLong(true); + } + + /** {@inheritDoc} */ + @Override public float readFloat(String fieldName) throws PortableException { + Float val = readFloat(fieldId(fieldName)); + + return val != null ? val : 0; + } + + /** {@inheritDoc} */ + @Override public float readFloat() throws PortableException { + return doReadFloat(true); + } + + /** {@inheritDoc} */ + @Override public double readDouble(String fieldName) throws PortableException { + Double val = readDouble(fieldId(fieldName)); + + return val != null ? val : 0; + } + + /** {@inheritDoc} */ + @Override public double readDouble() throws PortableException { + return doReadDouble(true); + } + + /** {@inheritDoc} */ + @Override public char readChar(String fieldName) throws PortableException { + Character val = readChar(fieldId(fieldName)); + + return val != null ? val : 0; + } + + /** {@inheritDoc} */ + @Override public char readChar() throws PortableException { + return doReadChar(true); + } + + /** {@inheritDoc} */ + @Override public boolean readBoolean(String fieldName) throws PortableException { + Boolean val = readBoolean(fieldId(fieldName)); + + return val != null ? val : false; + } + + /** {@inheritDoc} */ + @Override public boolean readBoolean() throws PortableException { + return doReadBoolean(true); + } + + /** {@inheritDoc} */ + @Override @Nullable public BigDecimal readDecimal(String fieldName) throws PortableException { + return readDecimal(fieldId(fieldName)); + } + + /** {@inheritDoc} */ + @Override @Nullable public BigDecimal readDecimal() throws PortableException { + byte flag = doReadByte(true); + + if (flag == NULL) + return null; + + if (flag != DECIMAL) + throw new PortableException("Invalid flag value: " + flag); + + return doReadDecimal(true); + } + + /** {@inheritDoc} */ + @Nullable @Override public String readString(String fieldName) throws PortableException { + return readString(fieldId(fieldName)); + } + + /** {@inheritDoc} */ + @Nullable @Override public String readString() throws PortableException { + byte flag = doReadByte(true); + + if (flag == NULL) + return null; + + if (flag != STRING) + throw new PortableException("Invalid flag value: " + flag); + + return doReadString(true); + } + + /** {@inheritDoc} */ + @Nullable @Override public UUID readUuid(String fieldName) throws PortableException { + return readUuid(fieldId(fieldName)); + } + + /** {@inheritDoc} */ + @Nullable @Override public UUID readUuid() throws PortableException { + byte flag = doReadByte(true); + + if (flag == NULL) + return null; + + if (flag != UUID) + throw new PortableException("Invalid flag value: " + flag); + + return doReadUuid(true); + } + + /** {@inheritDoc} */ + @Nullable @Override public Date readDate(String fieldName) throws PortableException { + return readDate(fieldId(fieldName)); + } + + /** {@inheritDoc} */ + @Nullable @Override public Date readDate() throws PortableException { + byte flag = doReadByte(true); + + if (flag == NULL) + return null; + + if (flag != DATE) + throw new PortableException("Invalid flag value: " + flag); + + return doReadDate(true); + } + + /** {@inheritDoc} */ + @Nullable @Override public Timestamp readTimestamp(String fieldName) throws PortableException { + return readTimestamp(fieldId(fieldName)); + } + + /** {@inheritDoc} */ + @Nullable @Override public Timestamp readTimestamp() throws PortableException { + byte flag = doReadByte(true); + + if (flag == NULL) + return null; + + if (flag != DATE) + throw new PortableException("Invalid flag value: " + flag); + + return doReadTimestamp(true); + } + + /** {@inheritDoc} */ + @SuppressWarnings("unchecked") + @Nullable @Override public T readObject(String fieldName) throws PortableException { + return (T)readObject(fieldId(fieldName)); + } + + /** {@inheritDoc} */ + @Override public Object readObject() throws PortableException { + return doReadObject(true); + } + + /** {@inheritDoc} */ + @Nullable @Override public Object readObjectDetached() throws PortableException { + return unmarshal(true, true); + } + + /** {@inheritDoc} */ + @Nullable @Override public byte[] readByteArray(String fieldName) throws PortableException { + return readByteArray(fieldId(fieldName)); + } + + /** {@inheritDoc} */ + @Nullable @Override public byte[] readByteArray() throws PortableException { + byte flag = doReadByte(true); + + if (flag == NULL) + return null; + + if (flag != BYTE_ARR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadByteArray(true); + } + + /** {@inheritDoc} */ + @Nullable @Override public short[] readShortArray(String fieldName) throws PortableException { + return readShortArray(fieldId(fieldName)); + } + + /** {@inheritDoc} */ + @Nullable @Override public short[] readShortArray() throws PortableException { + byte flag = doReadByte(true); + + if (flag == NULL) + return null; + + if (flag != SHORT_ARR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadShortArray(true); + } + + /** {@inheritDoc} */ + @Nullable @Override public int[] readIntArray(String fieldName) throws PortableException { + return readIntArray(fieldId(fieldName)); + } + + /** {@inheritDoc} */ + @Nullable @Override public int[] readIntArray() throws PortableException { + byte flag = doReadByte(true); + + if (flag == NULL) + return null; + + if (flag != INT_ARR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadIntArray(true); + } + + /** {@inheritDoc} */ + @Nullable @Override public long[] readLongArray(String fieldName) throws PortableException { + return readLongArray(fieldId(fieldName)); + } + + /** {@inheritDoc} */ + @Nullable @Override public long[] readLongArray() throws PortableException { + byte flag = doReadByte(true); + + if (flag == NULL) + return null; + + if (flag != LONG_ARR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadLongArray(true); + } + + /** {@inheritDoc} */ + @Nullable @Override public float[] readFloatArray(String fieldName) throws PortableException { + return readFloatArray(fieldId(fieldName)); + } + + /** {@inheritDoc} */ + @Nullable @Override public float[] readFloatArray() throws PortableException { + byte flag = doReadByte(true); + + if (flag == NULL) + return null; + + if (flag != FLOAT_ARR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadFloatArray(true); + } + + /** {@inheritDoc} */ + @Nullable @Override public double[] readDoubleArray(String fieldName) throws PortableException { + return readDoubleArray(fieldId(fieldName)); + } + + /** {@inheritDoc} */ + @Nullable @Override public double[] readDoubleArray() throws PortableException { + byte flag = doReadByte(true); + + if (flag == NULL) + return null; + + if (flag != DOUBLE_ARR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadDoubleArray(true); + } + + /** {@inheritDoc} */ + @Nullable @Override public char[] readCharArray(String fieldName) throws PortableException { + return readCharArray(fieldId(fieldName)); + } + + /** {@inheritDoc} */ + @Nullable @Override public char[] readCharArray() throws PortableException { + byte flag = doReadByte(true); + + if (flag == NULL) + return null; + + if (flag != CHAR_ARR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadCharArray(true); + } + + /** {@inheritDoc} */ + @Nullable @Override public boolean[] readBooleanArray(String fieldName) throws PortableException { + return readBooleanArray(fieldId(fieldName)); + } + + /** {@inheritDoc} */ + @Nullable @Override public boolean[] readBooleanArray() throws PortableException { + byte flag = doReadByte(true); + + if (flag == NULL) + return null; + + if (flag != BOOLEAN_ARR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadBooleanArray(true); + } + + /** {@inheritDoc} */ + @Override @Nullable public BigDecimal[] readDecimalArray(String fieldName) throws PortableException { + return readDecimalArray(fieldId(fieldName)); + } + + /** {@inheritDoc} */ + @Override @Nullable public BigDecimal[] readDecimalArray() throws PortableException { + byte flag = doReadByte(true); + + if (flag == NULL) + return null; + + if (flag != DECIMAL_ARR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadDecimalArray(true); + } + + /** {@inheritDoc} */ + @Nullable @Override public String[] readStringArray(String fieldName) throws PortableException { + return readStringArray(fieldId(fieldName)); + } + + /** {@inheritDoc} */ + @Nullable @Override public String[] readStringArray() throws PortableException { + byte flag = doReadByte(true); + + if (flag == NULL) + return null; + + if (flag != STRING_ARR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadStringArray(true); + } + + /** {@inheritDoc} */ + @Nullable @Override public UUID[] readUuidArray(String fieldName) throws PortableException { + return readUuidArray(fieldId(fieldName)); + } + + /** {@inheritDoc} */ + @Nullable @Override public UUID[] readUuidArray() throws PortableException { + byte flag = doReadByte(true); + + if (flag == NULL) + return null; + + if (flag != UUID_ARR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadUuidArray(true); + } + + /** {@inheritDoc} */ + @Nullable @Override public Date[] readDateArray(String fieldName) throws PortableException { + return readDateArray(fieldId(fieldName)); + } + + /** {@inheritDoc} */ + @Nullable @Override public Date[] readDateArray() throws PortableException { + byte flag = doReadByte(true); + + if (flag == NULL) + return null; + + if (flag != DATE_ARR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadDateArray(true); + } + + /** {@inheritDoc} */ + @Nullable @Override public Object[] readObjectArray(String fieldName) throws PortableException { + return readObjectArray(fieldId(fieldName)); + } + + /** {@inheritDoc} */ + @Nullable @Override public Object[] readObjectArray() throws PortableException { + byte flag = doReadByte(true); + + if (flag == NULL) + return null; + + if (flag != OBJ_ARR) + throw new PortableException("Invalid flag value: " + flag); + + return doReadObjectArray(true, true); + } + + /** {@inheritDoc} */ + @Nullable @Override public Collection readCollection(String fieldName) throws PortableException { + return readCollection(fieldId(fieldName), null); + } + + /** {@inheritDoc} */ + @Nullable @Override public Collection readCollection() throws PortableException { + byte flag = doReadByte(true); + + if (flag == NULL) + return null; + + if (flag != COL) + throw new PortableException("Invalid flag value: " + flag); + + return (Collection)doReadCollection(true, true, null); + } + + /** {@inheritDoc} */ + @Nullable @Override public Collection readCollection(String fieldName, + Class> colCls) throws PortableException { + return readCollection(fieldId(fieldName), colCls); + } + + /** {@inheritDoc} */ + @Nullable @Override public Collection readCollection(Class> colCls) + throws PortableException { + byte flag = doReadByte(true); + + if (flag == NULL) + return null; + + if (flag != COL) + throw new PortableException("Invalid flag value: " + flag); + + return (Collection)doReadCollection(true, true, colCls); + } + + /** {@inheritDoc} */ + @Nullable @Override public Map readMap(String fieldName) throws PortableException { + return (Map)readMap(fieldId(fieldName), null); + } + + /** {@inheritDoc} */ + @Nullable @Override public Map readMap() throws PortableException { + byte flag = doReadByte(true); + + if (flag == NULL) + return null; + + if (flag != MAP) + throw new PortableException("Invalid flag value: " + flag); + + return (Map)doReadMap(true, true, null); + } + + /** {@inheritDoc} */ + @Nullable @Override public Map readMap(String fieldName, Class> mapCls) + throws PortableException { + return (Map)readMap(fieldId(fieldName), mapCls); + } + + /** {@inheritDoc} */ + @Nullable @Override public Map readMap(Class> mapCls) + throws PortableException { + byte flag = doReadByte(true); + + if (flag == NULL) + return null; + + if (flag != MAP) + throw new PortableException("Invalid flag value: " + flag); + + return (Map)doReadMap(true, true, mapCls); + } + + /** {@inheritDoc} */ + @Nullable @Override public > T readEnum(String fieldName) + throws PortableException { + return (T)readEnum(fieldId(fieldName), null); + } + + /** {@inheritDoc} */ + @Nullable @Override public > T readEnum() throws PortableException { + byte flag = doReadByte(true); + + if (flag == NULL) + return null; + + if (flag != ENUM) + throw new PortableException("Invalid flag value: " + flag); + + Class cls = doReadClass(true); + + return (T)doReadEnum(true, cls); + } + + /** {@inheritDoc} */ + @Nullable @Override public > T[] readEnumArray(String fieldName) + throws PortableException { + return (T[])readEnumArray(fieldId(fieldName), null); + } + + /** {@inheritDoc} */ + @Nullable @Override public > T[] readEnumArray() throws PortableException { + byte flag = doReadByte(true); + + if (flag == NULL) + return null; + + if (flag != ENUM_ARR) + throw new PortableException("Invalid flag value: " + flag); + + Class cls = doReadClass(true); + + return (T[])doReadEnumArray(true, cls); + } + + /** + * @param fieldName Field name. + * @return {@code true} if field is set. + */ + public boolean hasField(String fieldName) { + return fieldOffset(fieldId(fieldName)) != -1; + } + + /** {@inheritDoc} */ + @Override public PortableRawReader rawReader() { + return this; + } + + /** + * @param raw Raw flag. + * @return Unmarshalled value. + * @throws PortableException In case of error. + */ + @Nullable private Object unmarshal(boolean raw) throws PortableException { + return unmarshal(raw, false); + } + + /** + * @param raw Raw flag. + * @return Unmarshalled value. + * @throws PortableException In case of error. + */ + @Nullable private Object unmarshal(boolean raw, boolean detach) throws PortableException { + int start = raw ? rawOff : off; + + byte flag = doReadByte(raw); + + switch (flag) { + case NULL: + return null; + + case HANDLE: + int handle = start - doReadInt(raw); + + PortableObject handledPo = rCtx.getPortableByHandle(handle); + + if (handledPo != null) + return handledPo; + + off = handle; + + return unmarshal(false); + + case OBJ: + PortableObjectEx po; + + if (detach) { + in.position(start + GridPortableMarshaller.TOTAL_LEN_POS); + + int len = in.readInt(); + + in.position(start); + + po = new PortableObjectImpl(ctx, in.readByteArray(len), 0); + } + else + po = in.offheapPointer() > 0 + ? new PortableObjectOffheapImpl(ctx, in.offheapPointer(), start, + in.remaining() + in.position()) + : new PortableObjectImpl(ctx, in.array(), start); + + rCtx.setPortableHandler(start, po); + + if (raw) + rawOff = start + po.length(); + else + off = start + po.length(); + + return po; + + case BYTE: + return doReadByte(raw); + + case SHORT: + return doReadShort(raw); + + case INT: + return doReadInt(raw); + + case LONG: + return doReadLong(raw); + + case FLOAT: + return doReadFloat(raw); + + case DOUBLE: + return doReadDouble(raw); + + case CHAR: + return doReadChar(raw); + + case BOOLEAN: + return doReadBoolean(raw); + + case DECIMAL: + return doReadDecimal(raw); + + case STRING: + return doReadString(raw); + + case UUID: + return doReadUuid(raw); + + case DATE: + return isUseTimestamp() ? doReadTimestamp(raw) : doReadDate(raw); + + case BYTE_ARR: + return doReadByteArray(raw); + + case SHORT_ARR: + return doReadShortArray(raw); + + case INT_ARR: + return doReadIntArray(raw); + + case LONG_ARR: + return doReadLongArray(raw); + + case FLOAT_ARR: + return doReadFloatArray(raw); + + case DOUBLE_ARR: + return doReadDoubleArray(raw); + + case CHAR_ARR: + return doReadCharArray(raw); + + case BOOLEAN_ARR: + return doReadBooleanArray(raw); + + case DECIMAL_ARR: + return doReadDecimalArray(raw); + + case STRING_ARR: + return doReadStringArray(raw); + + case UUID_ARR: + return doReadUuidArray(raw); + + case DATE_ARR: + return doReadDateArray(raw); + + case OBJ_ARR: + return doReadObjectArray(raw, false); + + case COL: + return doReadCollection(raw, false, null); + + case MAP: + return doReadMap(raw, false, null); + + case MAP_ENTRY: + return doReadMapEntry(raw, false); + + case PORTABLE_OBJ: + return doReadPortableObject(raw); + + case ENUM: + return doReadEnum(raw, doReadClass(raw)); + + case ENUM_ARR: + return doReadEnumArray(raw, doReadClass(raw)); + + case CLASS: + return doReadInt(raw); + + case OPTM_MARSH: + int len = doReadInt(true); + + ByteArrayInputStream input = new ByteArrayInputStream(in.array(), in.position(), len); + + Object obj; + + try { + obj = ctx.optimizedMarsh().unmarshal(input, null); + } + catch (IgniteCheckedException e) { + throw new PortableException("Failed to unmarshal object with optmMarsh marshaller", e); + } + + if (raw) + rawOff += len; + else + off += len; + + return obj; + + + default: + throw new PortableException("Invalid flag value: " + flag); + } + } + + /** + * @param raw Raw flag. + * @return Value. + */ + private byte doReadByte(boolean raw) { + in.position(raw ? rawOff++ : off++); + + return in.readByte(); + } + + /** + * @param raw Raw flag. + * @return Value. + */ + private short doReadShort(boolean raw) { + in.position(raw ? rawOff : off); + + short val = in.readShort(); + + if (raw) + rawOff += 2; + else + off += 2; + + return val; + } + + /** + * @param raw Raw flag. + * @return Value. + */ + private int doReadInt(boolean raw) { + in.position(raw ? rawOff : off); + + int val = in.readInt(); + + if (raw) + rawOff += 4; + else + off += 4; + + return val; + } + + /** + * @param raw Raw flag. + * @return Value. + */ + private long doReadLong(boolean raw) { + in.position(raw ? rawOff : off); + + long val = in.readLong(); + + if (raw) + rawOff += 8; + else + off += 8; + + return val; + } + + /** + * @param raw Raw flag. + * @return Value. + */ + private float doReadFloat(boolean raw) { + in.position(raw ? rawOff : off); + + float val = in.readFloat(); + + if (raw) + rawOff += 4; + else + off += 4; + + return val; + } + + /** + * @param raw Raw flag. + * @return Value. + */ + private double doReadDouble(boolean raw) { + in.position(raw ? rawOff : off); + + double val = in.readDouble(); + + if (raw) + rawOff += 8; + else + off += 8; + + return val; + } + + /** + * @param raw Raw flag. + * @return Value. + */ + private char doReadChar(boolean raw) { + in.position(raw ? rawOff : off); + + char val = in.readChar(); + + if (raw) + rawOff += 2; + else + off += 2; + + return val; + } + + /** + * @param raw Raw flag. + * @return Value. + */ + private boolean doReadBoolean(boolean raw) { + in.position(raw ? rawOff++ : off++); + + return in.readBoolean(); + } + + /** + * @param raw Raw flag. + * @return Value. + */ + private BigDecimal doReadDecimal(boolean raw) { + int scale = doReadInt(raw); + byte[] mag = doReadByteArray(raw); + + BigInteger intVal = new BigInteger(mag); + + if (scale < 0) { + scale &= 0x7FFFFFFF; + + intVal = intVal.negate(); + } + + return new BigDecimal(intVal, scale); + } + + /** + * @param raw Raw flag. + * @return Value. + */ + private String doReadString(boolean raw) { + if (doReadBoolean(raw)) { + if (!in.hasArray()) + return new String(doReadByteArray(raw), UTF_8); + + int strLen = doReadInt(raw); + int strOff = raw ? rawOff : off; + + String res = new String(in.array(), strOff, strLen, UTF_8); + + if (raw) + rawOff += strLen; + else + off += strLen; + + return res; + } + else + return String.valueOf(doReadCharArray(raw)); + } + + /** + * @param raw Raw flag. + * @return Value. + */ + private UUID doReadUuid(boolean raw) { + return new UUID(doReadLong(raw), doReadLong(raw)); + } + + /** + * @param raw Raw flag. + * @return Value. + */ + private Date doReadDate(boolean raw) { + long time = doReadLong(raw); + + // Skip remainder. + if (raw) + rawOff += 4; + else + off += 4; + + return new Date(time); + } + + /** + * @param raw Raw flag. + * @return Value. + */ + private Timestamp doReadTimestamp(boolean raw) { + long time = doReadLong(raw); + + int nanos = doReadInt(raw); + + Timestamp ts = new Timestamp(time); + + ts.setNanos(ts.getNanos() + nanos); + + return ts; + } + + /** + * @param raw Raw flag. + * @return Object. + * @throws PortableException In case of error. + */ + @Nullable private Object doReadObject(boolean raw) throws PortableException { + PortableReaderExImpl reader = new PortableReaderExImpl(ctx, in, raw ? rawOff : off, ldr, rCtx); + + Object obj = reader.deserialize(); + + if (raw) + rawOff += reader.len; + else + off += reader.len; + + return obj; + } + + /** + * @return Deserialized object. + * @throws PortableException If failed. + */ + @Nullable Object deserialize() throws PortableException { + Object obj; + + byte flag = doReadByte(true); + + switch (flag) { + case NULL: + obj = null; + + break; + + case HANDLE: + int handle = start - doReadInt(true); + + obj = rCtx.getObjectByHandle(handle); + + if (obj == null) { + off = handle; + + obj = doReadObject(false); + } + + break; + + case OBJ: + if (typeId == null) + readObjectTypeId(true); + + assert typeId != UNREGISTERED_TYPE_ID; + + boolean userType = doReadBoolean(true); + + // Skip typeId and hash code. + rawOff += 8; + + desc = ctx.descriptorForTypeId(userType, typeId, ldr); + + len = doReadInt(true); + + rawOff = start + doReadInt(true); + + if (desc == null) + throw new PortableInvalidClassException("Unknown type ID: " + typeId); + + // Skip clsName field if any. + rawOff += clsNameLen; + + obj = desc.read(this); + + break; + + case BYTE: + obj = doReadByte(true); + + break; + + case SHORT: + obj = doReadShort(true); + + break; + + case INT: + obj = doReadInt(true); + + break; + + case LONG: + obj = doReadLong(true); + + break; + + case FLOAT: + obj = doReadFloat(true); + + break; + + case DOUBLE: + obj = doReadDouble(true); + + break; + + case CHAR: + obj = doReadChar(true); + + break; + + case BOOLEAN: + obj = doReadBoolean(true); + + break; + + case DECIMAL: + obj = doReadDecimal(true); + + break; + + case STRING: + obj = doReadString(true); + + break; + + case UUID: + obj = doReadUuid(true); + + break; + + case DATE: + obj = isUseTimestamp() ? doReadTimestamp(true) : doReadDate(true); + + break; + + case BYTE_ARR: + obj = doReadByteArray(true); + + break; + + case SHORT_ARR: + obj = doReadShortArray(true); + + break; + + case INT_ARR: + obj = doReadIntArray(true); + + break; + + case LONG_ARR: + obj = doReadLongArray(true); + + break; + + case FLOAT_ARR: + obj = doReadFloatArray(true); + + break; + + case DOUBLE_ARR: + obj = doReadDoubleArray(true); + + break; + + case CHAR_ARR: + obj = doReadCharArray(true); + + break; + + case BOOLEAN_ARR: + obj = doReadBooleanArray(true); + + break; + + case DECIMAL_ARR: + obj = doReadDecimalArray(true); + + break; + + case STRING_ARR: + obj = doReadStringArray(true); + + break; + + case UUID_ARR: + obj = doReadUuidArray(true); + + break; + + case DATE_ARR: + obj = doReadDateArray(true); + + break; + + case OBJ_ARR: + obj = doReadObjectArray(true, true); + + break; + + case COL: + obj = doReadCollection(true, true, null); + + break; + + case MAP: + obj = doReadMap(true, true, null); + + break; + + case MAP_ENTRY: + obj = doReadMapEntry(true, true); + + break; + + case PORTABLE_OBJ: + obj = doReadPortableObject(true); + + ((PortableObjectImpl)obj).context(ctx); + + if (!GridPortableMarshaller.KEEP_PORTABLES.get()) + obj = ((PortableObject)obj).deserialize(); + + break; + + case ENUM: + obj = doReadEnum(true, doReadClass(true)); + + break; + + case ENUM_ARR: + obj = doReadEnumArray(true, doReadClass(true)); + + break; + + case CLASS: + obj = doReadClass(true); + + break; + + case OPTM_MARSH: + int len = doReadInt(true); + + ByteArrayInputStream input = new ByteArrayInputStream(in.array(), in.position(), len); + + try { + obj = ctx.optimizedMarsh().unmarshal(input, null); + } + catch (IgniteCheckedException e) { + throw new PortableException("Failed to unmarshal object with optimized marshaller", e); + } + + rawOff += len; + + break; + + default: + throw new PortableException("Invalid flag value: " + flag); + } + + if (len == 0) + len = rawOff - start; + + return obj; + } + + /** + * @return Use timestamp flag. + * @throws PortableInvalidClassException If fails to find object type descriptor. + */ + private boolean isUseTimestamp() throws PortableInvalidClassException { + in.position(start); + + boolean dateObj = in.readByte() == DATE; + + if (!dateObj) { + in.position(start + 2); + + int typeId = in.readInt(start + 2); + + return ctx.isUseTimestamp(typeId); + } + + return ctx.isUseTimestamp(); + } + + /** + * @param raw Raw flag. + * @return Value. + */ + private byte[] doReadByteArray(boolean raw) { + int len = doReadInt(raw); + + in.position(raw ? rawOff : off); + + byte[] arr = in.readByteArray(len); + + if (raw) + rawOff += len; + else + off += len; + + return arr; + } + + /** + * @param raw Raw flag. + * @return Value. + */ + private short[] doReadShortArray(boolean raw) { + int len = doReadInt(raw); + + in.position(raw ? rawOff : off); + + short[] arr = in.readShortArray(len); + + int bytes = len << 1; + + if (raw) + rawOff += bytes; + else + off += bytes; + + return arr; + } + + /** + * @param raw Raw flag. + * @return Value. + */ + private int[] doReadIntArray(boolean raw) { + int len = doReadInt(raw); + + in.position(raw ? rawOff : off); + + int[] arr = in.readIntArray(len); + + int bytes = len << 2; + + if (raw) + rawOff += bytes; + else + off += bytes; + + return arr; + } + + /** + * @param raw Raw flag. + * @return Value. + */ + private long[] doReadLongArray(boolean raw) { + int len = doReadInt(raw); + + in.position(raw ? rawOff : off); + + long[] arr = in.readLongArray(len); + + int bytes = len << 3; + + if (raw) + rawOff += bytes; + else + off += bytes; + + return arr; + } + + /** + * @param raw Raw flag. + * @return Value. + */ + private float[] doReadFloatArray(boolean raw) { + int len = doReadInt(raw); + + in.position(raw ? rawOff : off); + + float[] arr = in.readFloatArray(len); + + int bytes = len << 2; + + if (raw) + rawOff += bytes; + else + off += bytes; + + return arr; + } + + /** + * @param raw Raw flag. + * @return Value. + */ + private double[] doReadDoubleArray(boolean raw) { + int len = doReadInt(raw); + + in.position(raw ? rawOff : off); + + double[] arr = in.readDoubleArray(len); + + int bytes = len << 3; + + if (raw) + rawOff += bytes; + else + off += bytes; + + return arr; + } + + /** + * @param raw Raw flag. + * @return Value. + */ + private char[] doReadCharArray(boolean raw) { + int len = doReadInt(raw); + + in.position(raw ? rawOff : off); + + char[] arr = in.readCharArray(len); + + int bytes = len << 1; + + if (raw) + rawOff += bytes; + else + off += bytes; + + return arr; + } + + /** + * @param raw Raw flag. + * @return Value. + */ + private boolean[] doReadBooleanArray(boolean raw) { + int len = doReadInt(raw); + + in.position(raw ? rawOff : off); + + boolean[] arr = in.readBooleanArray(len); + + if (raw) + rawOff += len; + else + off += len; + + return arr; + } + + /** + * @param raw Raw flag. + * @return Value. + * @throws PortableException In case of error. + */ + private BigDecimal[] doReadDecimalArray(boolean raw) throws PortableException { + int len = doReadInt(raw); + + BigDecimal[] arr = new BigDecimal[len]; + + for (int i = 0; i < len; i++) { + byte flag = doReadByte(raw); + + if (flag == NULL) + arr[i] = null; + else { + if (flag != DECIMAL) + throw new PortableException("Invalid flag value: " + flag); + + arr[i] = doReadDecimal(raw); + } + } + + return arr; + } + + /** + * @param raw Raw flag. + * @return Value. + * @throws PortableException In case of error. + */ + private String[] doReadStringArray(boolean raw) throws PortableException { + int len = doReadInt(raw); + + String[] arr = new String[len]; + + for (int i = 0; i < len; i++) { + byte flag = doReadByte(raw); + + if (flag == NULL) + arr[i] = null; + else { + if (flag != STRING) + throw new PortableException("Invalid flag value: " + flag); + + arr[i] = doReadString(raw); + } + } + + return arr; + } + + /** + * @param raw Raw flag. + * @return Value. + * @throws PortableException In case of error. + */ + private UUID[] doReadUuidArray(boolean raw) throws PortableException { + int len = doReadInt(raw); + + UUID[] arr = new UUID[len]; + + for (int i = 0; i < len; i++) { + byte flag = doReadByte(raw); + + if (flag == NULL) + arr[i] = null; + else { + if (flag != UUID) + throw new PortableException("Invalid flag value: " + flag); + + arr[i] = doReadUuid(raw); + } + } + + return arr; + } + + /** + * @param raw Raw flag. + * @return Value. + * @throws PortableException In case of error. + */ + private Date[] doReadDateArray(boolean raw) throws PortableException { + int len = doReadInt(raw); + + Date[] arr = new Date[len]; + + for (int i = 0; i < len; i++) { + byte flag = doReadByte(raw); + + if (flag == NULL) + arr[i] = null; + else { + if (flag != DATE) + throw new PortableException("Invalid flag value: " + flag); + + arr[i] = doReadDate(raw); + } + } + + return arr; + } + + /** + * @param raw Raw flag. + * @param deep Deep flag. + * @return Value. + * @throws PortableException In case of error. + */ + private Object[] doReadObjectArray(boolean raw, boolean deep) throws PortableException { + Class compType = doReadClass(raw); + + int len = doReadInt(raw); + + Object[] arr = deep ? (Object[])Array.newInstance(compType, len) : new Object[len]; + + for (int i = 0; i < len; i++) + arr[i] = deep ? doReadObject(raw) : unmarshal(raw); + + return arr; + } + + /** + * @param raw Raw flag. + * @param deep Deep flag. + * @param cls Collection class. + * @return Value. + * @throws PortableException In case of error. + */ + @SuppressWarnings("unchecked") + private Collection doReadCollection(boolean raw, boolean deep, @Nullable Class cls) + throws PortableException { + int size = doReadInt(raw); + + assert size >= 0; + + byte colType = doReadByte(raw); + + Collection col; + + if (cls != null) { + try { + Constructor cons = cls.getConstructor(); + + col = cons.newInstance(); + } + catch (NoSuchMethodException ignored) { + throw new PortableException("Collection class doesn't have public default constructor: " + + cls.getName()); + } + catch (InvocationTargetException | InstantiationException | IllegalAccessException e) { + throw new PortableException("Failed to instantiate collection: " + cls.getName(), e); + } + } + else { + switch (colType) { + case ARR_LIST: + col = new ArrayList<>(size); + + break; + + case LINKED_LIST: + col = new LinkedList<>(); + + break; + + case HASH_SET: + col = U.newHashSet(size); + + break; + + case LINKED_HASH_SET: + col = U.newLinkedHashSet(size); + + break; + + case TREE_SET: + col = new TreeSet<>(); + + break; + + case CONC_SKIP_LIST_SET: + col = new ConcurrentSkipListSet<>(); + + break; + + case USER_SET: + col = U.newHashSet(size); + + break; + + case USER_COL: + col = new ArrayList<>(size); + + break; + + default: + throw new PortableException("Invalid collection type: " + colType); + } + } + + for (int i = 0; i < size; i++) + col.add(deep ? doReadObject(raw) : unmarshal(raw)); + + return col; + } + + /** + * @param raw Raw flag. + * @param deep Deep flag. + * @param cls Map class. + * @return Value. + * @throws PortableException In case of error. + */ + @SuppressWarnings("unchecked") + private Map doReadMap(boolean raw, boolean deep, @Nullable Class cls) + throws PortableException { + int size = doReadInt(raw); + + assert size >= 0; + + byte mapType = doReadByte(raw); + + Map map; + + if (cls != null) { + try { + Constructor cons = cls.getConstructor(); + + map = cons.newInstance(); + } + catch (NoSuchMethodException ignored) { + throw new PortableException("Map class doesn't have public default constructor: " + + cls.getName()); + } + catch (InvocationTargetException | InstantiationException | IllegalAccessException e) { + throw new PortableException("Failed to instantiate map: " + cls.getName(), e); + } + } + else { + switch (mapType) { + case HASH_MAP: + map = U.newHashMap(size); + + break; + + case LINKED_HASH_MAP: + map = U.newLinkedHashMap(size); + + break; + + case TREE_MAP: + map = new TreeMap<>(); + + break; + + case CONC_HASH_MAP: + map = new ConcurrentHashMap<>(size); + + break; + + case USER_COL: + map = U.newHashMap(size); + + break; + + case PROPERTIES_MAP: + map = new Properties(); + + break; + + default: + throw new PortableException("Invalid map type: " + mapType); + } + } + + for (int i = 0; i < size; i++) + map.put(deep ? doReadObject(raw) : unmarshal(raw), deep ? doReadObject(raw) : unmarshal(raw)); + + return map; + } + + /** + * @param raw Raw flag. + * @param deep Deep flag. + * @return Value. + * @throws PortableException In case of error. + */ + private Map.Entry doReadMapEntry(boolean raw, boolean deep) throws PortableException { + Object val1 = deep ? doReadObject(raw) : unmarshal(raw); + Object val2 = deep ? doReadObject(raw) : unmarshal(raw); + + return new GridMapEntry<>(val1, val2); + } + + /** + * @param raw Raw flag. + * @return Value. + */ + private PortableObject doReadPortableObject(boolean raw) { + if (in.offheapPointer() > 0) { + int len = doReadInt(raw); + + int pos = raw ? rawOff : off; + + if (raw) + rawOff += len; + else + off += len; + + int start = doReadInt(raw); + + return new PortableObjectOffheapImpl(ctx, in.offheapPointer() + pos, start, len); + } + else { + byte[] arr = doReadByteArray(raw); + int start = doReadInt(raw); + + return new PortableObjectImpl(ctx, arr, start); + } + } + + /** + * @param raw Raw flag. + * @param cls Enum class. + * @return Value. + */ + private Enum doReadEnum(boolean raw, Class cls) throws PortableException { + if (!cls.isEnum()) + throw new PortableException("Class does not represent enum type: " + cls.getName()); + + int ord = doReadInt(raw); + + return ord >= 0 ? (Enum)GridEnumCache.get(cls)[ord] : null; + } + + /** + * @param raw Raw flag. + * @param cls Enum class. + * @return Value. + */ + private Object[] doReadEnumArray(boolean raw, Class cls) throws PortableException { + int len = doReadInt(raw); + + Object[] arr = (Object[])Array.newInstance(cls, len); + + for (int i = 0; i < len; i++) { + byte flag = doReadByte(raw); + + if (flag == NULL) + arr[i] = null; + else + arr[i] = doReadEnum(raw, doReadClass(raw)); + } + + return arr; + } + + /** + * @param raw Raw flag. + * @return Value. + */ + private Class doReadClass(boolean raw) throws PortableException { + return doReadClass(raw, doReadInt(raw)); + } + + /** + * @param raw Raw flag. + * @param typeId Type id. + * @return Value. + */ + private Class doReadClass(boolean raw, int typeId) throws PortableException { + Class cls; + + if (typeId == OBJECT_TYPE_ID) + return Object.class; + + if (typeId != UNREGISTERED_TYPE_ID) + cls = ctx.descriptorForTypeId(true, typeId, ldr).describedClass(); + else { + byte flag = doReadByte(raw); + + if (flag != STRING) + throw new PortableException("No class definition for typeId: " + typeId); + + String clsName = doReadString(raw); + + try { + cls = U.forName(clsName, ldr); + } + catch (ClassNotFoundException e) { + throw new PortableInvalidClassException("Failed to load the class: " + clsName, e); + } + + // forces registering of class by type id, at least locally + ctx.descriptorForClass(cls); + } + + return cls; + } + + /** + * @param name Field name. + * @return Field offset. + */ + private int fieldId(String name) { + assert name != null; + + if (typeId == null) + readObjectTypeId(false); + + assert typeId != UNREGISTERED_TYPE_ID; + + return ctx.fieldId(typeId, name); + } + + /** + * @param id Field ID. + * @return Field offset. + */ + private int fieldOffset(int id) { + assert hdrLen != 0; + + int off = start + hdrLen; + + int end = start + in.readInt(start + RAW_DATA_OFF_POS); + + while (true) { + if (off >= end) + return -1; + + int id0 = in.readInt(off); + + if (id0 == id) + return off + 8; + + int len = in.readInt(off + 4); + + off += (8 + len); + } + } + + /** {@inheritDoc} */ + @Override public int readUnsignedByte() throws IOException { + return readByte() & 0xff; + } + + /** {@inheritDoc} */ + @Override public int readUnsignedShort() throws IOException { + return readShort() & 0xffff; + } + + /** {@inheritDoc} */ + @Override public String readLine() throws IOException { + SB sb = new SB(); + + int b; + + while ((b = read()) >= 0) { + char c = (char)b; + + switch (c) { + case '\n': + return sb.toString(); + + case '\r': + b = read(); + + if (b < 0 || b == '\n') + return sb.toString(); + else + sb.a((char)b); + + break; + + default: + sb.a(c); + } + } + + return sb.toString(); + } + + /** {@inheritDoc} */ + @NotNull @Override public String readUTF() throws IOException { + return readString(); + } + + /** {@inheritDoc} */ + @Override public void readFully(byte[] b) throws IOException { + readFully(b, 0, b.length); + } + + /** {@inheritDoc} */ + @Override public void readFully(byte[] b, int off, int len) throws IOException { + in.position(rawOff); + + int cnt = in.read(b, off, len); + + if (cnt < len) + throw new EOFException(); + + rawOff += len; + } + + /** {@inheritDoc} */ + @Override public int skipBytes(int n) throws IOException { + int toSkip = Math.min(in.remaining(), n); + + in.position(in.position() + toSkip); + + rawOff += toSkip; + + return toSkip; + } + + /** {@inheritDoc} */ + @Override public int read() throws IOException { + return readByte(); + } + + /** {@inheritDoc} */ + @Override public int read(byte[] b) throws IOException { + return read(b, 0, b.length); + } + + /** {@inheritDoc} */ + @Override public int read(byte[] b, int off, int len) throws IOException { + in.position(rawOff); + + int cnt = in.read(b, off, len); + + rawOff += len; + + return cnt; + } + + /** {@inheritDoc} */ + @Override public long skip(long n) throws IOException { + return skipBytes((int)n); + } + + /** {@inheritDoc} */ + @Override public int available() throws IOException { + return in.remaining(); + } + + /** {@inheritDoc} */ + @Override public void close() throws IOException { + // No-op. + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/878dcd92/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableThreadLocalMemoryAllocator.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableThreadLocalMemoryAllocator.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableThreadLocalMemoryAllocator.java new file mode 100644 index 0000000..f3b3739 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableThreadLocalMemoryAllocator.java @@ -0,0 +1,163 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.portable; + +import org.apache.ignite.internal.portable.streams.*; +import org.apache.ignite.internal.util.*; +import org.apache.ignite.internal.util.typedef.internal.*; + +import sun.misc.*; + +import static org.apache.ignite.IgniteSystemProperties.*; + +/** + * Thread-local memory allocator. + */ +public class PortableThreadLocalMemoryAllocator implements PortableMemoryAllocator { + /** Memory allocator instance. */ + public static final PortableThreadLocalMemoryAllocator THREAD_LOCAL_ALLOC = + new PortableThreadLocalMemoryAllocator(); + + /** Holders. */ + private static final ThreadLocal holders = new ThreadLocal<>(); + + /** Unsafe instance. */ + protected static final Unsafe UNSAFE = GridUnsafe.unsafe(); + + /** Array offset: byte. */ + protected static final long BYTE_ARR_OFF = UNSAFE.arrayBaseOffset(byte[].class); + + /** + * Ensures singleton. + */ + private PortableThreadLocalMemoryAllocator() { + // No-op. + } + + /** {@inheritDoc} */ + @Override public byte[] allocate(int size) { + ByteArrayHolder holder = holders.get(); + + if (holder == null) + holders.set(holder = new ByteArrayHolder()); + + if (holder.acquired) + return new byte[size]; + + holder.acquired = true; + + if (holder.data == null || size > holder.data.length) + holder.data = new byte[size]; + + return holder.data; + } + + /** {@inheritDoc} */ + @Override public byte[] reallocate(byte[] data, int size) { + ByteArrayHolder holder = holders.get(); + + assert holder != null; + + byte[] newData = new byte[size]; + + if (holder.data == data) + holder.data = newData; + + UNSAFE.copyMemory(data, BYTE_ARR_OFF, newData, BYTE_ARR_OFF, data.length); + + return newData; + } + + /** {@inheritDoc} */ + @Override public void release(byte[] data, int maxMsgSize) { + ByteArrayHolder holder = holders.get(); + + assert holder != null; + + if (holder.data != data) + return; + + holder.maxMsgSize = maxMsgSize; + holder.acquired = false; + + holder.shrink(); + } + + /** {@inheritDoc} */ + @Override public long allocateDirect(int size) { + return 0; + } + + /** {@inheritDoc} */ + @Override public long reallocateDirect(long addr, int size) { + return 0; + } + + /** {@inheritDoc} */ + @Override public void releaseDirect(long addr) { + // No-op + } + + /** + * Checks whether a thread-local array is acquired or not. + * The function is used by Unit tests. + * + * @return {@code true} if acquired {@code false} otherwise. + */ + public boolean isThreadLocalArrayAcquired() { + ByteArrayHolder holder = holders.get(); + + return holder != null && holder.acquired; + } + + /** + * Thread-local byte array holder. + */ + private static class ByteArrayHolder { + /** */ + private static final Long CHECK_FREQ = Long.getLong(IGNITE_MARSHAL_BUFFERS_RECHECK, 10000); + + /** Data array */ + private byte[] data; + + /** Max message size detected between checks. */ + private int maxMsgSize; + + /** Last time array size is checked. */ + private long lastCheck = U.currentTimeMillis(); + + /** Whether the holder is acquired or not. */ + private boolean acquired; + + /** + * Shrinks array size if needed. + */ + private void shrink() { + long now = U.currentTimeMillis(); + + if (now - lastCheck >= CHECK_FREQ) { + int halfSize = data.length >> 1; + + if (maxMsgSize < halfSize) + data = new byte[halfSize]; + + lastCheck = now; + } + } + } +} \ No newline at end of file