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 C3DEB17F98 for ; Thu, 5 Nov 2015 13:16:02 +0000 (UTC) Received: (qmail 2532 invoked by uid 500); 5 Nov 2015 13:15:58 -0000 Delivered-To: apmail-ignite-commits-archive@ignite.apache.org Received: (qmail 2450 invoked by uid 500); 5 Nov 2015 13:15:57 -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 875 invoked by uid 99); 5 Nov 2015 13:15:53 -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; Thu, 05 Nov 2015 13:15:53 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 804E2E393A; Thu, 5 Nov 2015 13:15:53 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: agoncharuk@apache.org To: commits@ignite.apache.org Date: Thu, 05 Nov 2015 13:16:09 -0000 Message-Id: <2ec5f8d71cc342f9891f2617fadcb53d@git.apache.org> In-Reply-To: <1fde8345cf7b41f58211e2c5b798ae8c@git.apache.org> References: <1fde8345cf7b41f58211e2c5b798ae8c@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [17/26] ignite git commit: Merged IGNITE-950-new into IGNITE-1282 http://git-wip-us.apache.org/repos/asf/ignite/blob/b783d2b7/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableWriterExImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableWriterExImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableWriterExImpl.java deleted file mode 100644 index 542c897..0000000 --- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableWriterExImpl.java +++ /dev/null @@ -1,1915 +0,0 @@ -/* - * 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.portable.streams.PortableHeapOutputStream; -import org.apache.ignite.internal.portable.streams.PortableOutputStream; -import org.apache.ignite.internal.util.typedef.internal.A; -import org.apache.ignite.portable.PortableException; -import org.apache.ignite.portable.PortableIdMapper; -import org.apache.ignite.portable.PortableRawWriter; -import org.apache.ignite.portable.PortableWriter; -import org.jetbrains.annotations.Nullable; - -import java.io.IOException; -import java.io.ObjectOutput; -import java.lang.reflect.InvocationTargetException; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.sql.Timestamp; -import java.util.Collection; -import java.util.Date; -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.UUID; - -import static java.nio.charset.StandardCharsets.UTF_8; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.BOOLEAN; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.BOOLEAN_ARR; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.BYTE; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.BYTE_ARR; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.CHAR; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.CHAR_ARR; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.CLASS; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.COL; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.DATE; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.DATE_ARR; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.DECIMAL; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.DECIMAL_ARR; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.DOUBLE; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.DOUBLE_ARR; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.ENUM; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.ENUM_ARR; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.FLAGS_POS; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.FLOAT; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.FLOAT_ARR; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.INT; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.INT_ARR; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.LONG; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.LONG_ARR; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.MAP; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.MAP_ENTRY; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.NULL; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.OBJ; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.OBJ_ARR; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.OPTM_MARSH; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.PORTABLE_OBJ; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.SCHEMA_ID_POS; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.SCHEMA_OR_RAW_OFF_POS; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.SHORT; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.SHORT_ARR; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.STRING; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.STRING_ARR; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.TIMESTAMP; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.TIMESTAMP_ARR; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.TOTAL_LEN_POS; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.UNREGISTERED_TYPE_ID; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.UUID; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.UUID_ARR; - -/** - * Portable writer implementation. - */ -public class PortableWriterExImpl implements PortableWriter, PortableRawWriterEx, ObjectOutput { - /** Length: integer. */ - private static final int LEN_INT = 4; - - /** */ - private static final int INIT_CAP = 1024; - - /** FNV1 hash offset basis. */ - private static final int FNV1_OFFSET_BASIS = 0x811C9DC5; - - /** FNV1 hash prime. */ - private static final int FNV1_PRIME = 0x01000193; - - /** Maximum offset which fits in 1 byte. */ - private static final int MAX_OFFSET_1 = 1 << 8; - - /** Maximum offset which fits in 2 bytes. */ - private static final int MAX_OFFSET_2 = 1 << 16; - - /** Thread-local schema. */ - private static final ThreadLocal SCHEMA = new ThreadLocal<>(); - - /** */ - private final PortableContext ctx; - - /** */ - private final int start; - - /** */ - private Class cls; - - /** */ - private int typeId; - - /** Raw offset position. */ - private int rawOffPos; - - /** */ - private boolean metaEnabled; - - /** */ - private int metaHashSum; - - /** Handles. */ - private Map handles; - - /** Output stream. */ - private PortableOutputStream out; - - /** Schema. */ - private SchemaHolder schema; - - /** Schema ID. */ - private int schemaId; - - /** Amount of written fields. */ - private int fieldCnt; - - /** ID mapper. */ - private PortableIdMapper idMapper; - - /** - * @param ctx Context. - */ - PortableWriterExImpl(PortableContext ctx) { - this(ctx, new PortableHeapOutputStream(INIT_CAP)); - } - - /** - * @param ctx Context. - * @param out Output stream. - */ - PortableWriterExImpl(PortableContext ctx, PortableOutputStream out) { - this(ctx, out, new IdentityHashMap()); - } - - /** - * @param ctx Context. - * @param out Output stream. - * @param handles Handles. - */ - private PortableWriterExImpl(PortableContext ctx, PortableOutputStream out, Map handles) { - this.ctx = ctx; - this.out = out; - this.handles = handles; - - start = out.position(); - } - - /** - * @param ctx Context. - * @param typeId Type ID. - */ - public PortableWriterExImpl(PortableContext ctx, int typeId, boolean metaEnabled) { - this(ctx); - - this.typeId = typeId; - this.metaEnabled = metaEnabled; - } - - /** - * Close the writer releasing resources if necessary. - */ - @Override public void close() { - out.close(); - } - - /** - * @return Meta data hash sum or {@code null} if meta data is disabled. - */ - @Nullable Integer metaDataHashSum() { - return metaEnabled ? metaHashSum : null; - } - - /** - * @param obj Object. - * @throws PortableException In case of error. - */ - void marshal(Object obj) throws PortableException { - marshal(obj, true); - } - - /** - * @param obj Object. - * @param enableReplace Object replacing enabled flag. - * @throws PortableException In case of error. - */ - void marshal(Object obj, boolean enableReplace) throws PortableException { - assert obj != null; - - cls = obj.getClass(); - - PortableClassDescriptor desc = ctx.descriptorForClass(cls); - - if (desc == null) - throw new PortableException("Object is not portable: [class=" + cls + ']'); - - if (desc.excluded()) { - doWriteByte(NULL); - return; - } - - if (desc.useOptimizedMarshaller()) { - writeByte(OPTM_MARSH); - - try { - byte[] arr = ctx.optimizedMarsh().marshal(obj); - - writeInt(arr.length); - - write(arr); - } - catch (IgniteCheckedException e) { - throw new PortableException("Failed to marshal object with optimized marshaller: " + obj, e); - } - - return; - } - - if (enableReplace && desc.getWriteReplaceMethod() != null) { - Object replacedObj; - - try { - replacedObj = desc.getWriteReplaceMethod().invoke(obj); - } - catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - catch (InvocationTargetException e) { - if (e.getTargetException() instanceof PortableException) - throw (PortableException)e.getTargetException(); - - throw new PortableException("Failed to execute writeReplace() method on " + obj, e); - } - - if (replacedObj == null) { - doWriteByte(NULL); - return; - } - - marshal(replacedObj, false); - - return; - } - - typeId = desc.typeId(); - - metaEnabled = ctx.isMetaDataEnabled(typeId); - - desc.write(obj, this); - } - - /** - * @param obj Object. - * @return Handle. - */ - int handle(Object obj) { - assert obj != null; - - Integer h = handles.get(obj); - - if (h != null) - return out.position() - h; - else { - handles.put(obj, out.position()); - - return -1; - } - } - - /** - * @return Array. - */ - public byte[] array() { - return out.arrayCopy(); - } - - /** - * @return Stream current position. - */ - int position() { - return out.position(); - } - - /** - * Sets new position. - * - * @param pos Position. - */ - void position(int pos) { - out.position(pos); - } - - /** - * @param bytes Number of bytes to reserve. - * @return Offset. - */ - public int reserve(int bytes) { - int pos = out.position(); - - out.position(pos + bytes); - - return pos; - } - - /** - * Perform post-write activity. This includes: - * - writing object length; - * - writing schema offset; - * - writing schema to the tail. - * - * @param userType User type flag. - */ - public void postWrite(boolean userType) { - if (schema != null) { - // Write schema ID. - out.writeInt(start + SCHEMA_ID_POS, schemaId); - - // Write schema offset. - out.writeInt(start + SCHEMA_OR_RAW_OFF_POS, out.position() - start); - - // Write the schema. - int offsetByteCnt = schema.write(this, fieldCnt); - - // Write raw offset if needed. - if (rawOffPos != 0) - out.writeInt(rawOffPos - start); - - if (offsetByteCnt == PortableUtils.OFFSET_1) { - int flags = (userType ? PortableUtils.FLAG_USR_TYP : 0) | PortableUtils.FLAG_OFFSET_ONE_BYTE; - - out.writeShort(start + FLAGS_POS, (short)flags); - } - else if (offsetByteCnt == PortableUtils.OFFSET_2) { - int flags = (userType ? PortableUtils.FLAG_USR_TYP : 0) | PortableUtils.FLAG_OFFSET_TWO_BYTES; - - out.writeShort(start + FLAGS_POS, (short)flags); - } - } - else { - // Write raw-only flag is needed. - int flags = (userType ? PortableUtils.FLAG_USR_TYP : 0) | PortableUtils.FLAG_RAW_ONLY; - - out.writeShort(start + FLAGS_POS, (short)flags); - - // If there are no schema, we are free to write raw offset to schema offset. - out.writeInt(start + SCHEMA_OR_RAW_OFF_POS, (rawOffPos == 0 ? out.position() : rawOffPos) - start); - } - - // 5. Write length. - out.writeInt(start + TOTAL_LEN_POS, out.position() - start); - } - - /** - * Pop schema. - */ - public void popSchema() { - if (schema != null) { - assert fieldCnt > 0; - - schema.pop(fieldCnt); - } - } - - /** - * @param val Byte array. - */ - public void write(byte[] val) { - assert val != null; - - out.writeByteArray(val); - } - - /** - * @param val Byte array. - * @param off Offset. - * @param len Length. - */ - public void write(byte[] val, int off, int len) { - assert val != null; - - out.write(val, off, len); - } - - /** - * @param val Value. - */ - public void doWriteByte(byte val) { - out.writeByte(val); - } - - /** - * @param val Value. - */ - public void doWriteShort(short val) { - out.writeShort(val); - } - - /** - * @param val Value. - */ - public void doWriteInt(int val) { - out.writeInt(val); - } - - /** - * @param val Value. - */ - public void doWriteLong(long val) { - out.writeLong(val); - } - - /** - * @param val Value. - */ - public void doWriteFloat(float val) { - out.writeFloat(val); - } - - /** - * @param val Value. - */ - public void doWriteDouble(double val) { - out.writeDouble(val); - } - - /** - * @param val Value. - */ - public void doWriteChar(char val) { - out.writeChar(val); - } - - /** - * @param val Value. - */ - public void doWriteBoolean(boolean val) { - out.writeBoolean(val); - } - - /** - * @param val String value. - */ - public void doWriteDecimal(@Nullable BigDecimal val) { - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(DECIMAL); - - BigInteger intVal = val.unscaledValue(); - - if (intVal.signum() == -1) { - intVal = intVal.negate(); - - out.writeInt(val.scale() | 0x80000000); - } - else - out.writeInt(val.scale()); - - byte[] vals = intVal.toByteArray(); - - out.writeInt(vals.length); - out.writeByteArray(vals); - } - } - - /** - * @param val String value. - */ - public void doWriteString(@Nullable String val) { - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(STRING); - - if (ctx.isConvertString()) { - doWriteBoolean(true); - - byte[] strArr = val.getBytes(UTF_8); - - doWriteInt(strArr.length); - - out.writeByteArray(strArr); - } - else { - doWriteBoolean(false); - - char[] strArr = val.toCharArray(); - - doWriteInt(strArr.length); - - out.writeCharArray(strArr); - } - } - } - - /** - * @param uuid UUID. - */ - public void doWriteUuid(@Nullable UUID uuid) { - if (uuid == null) - doWriteByte(NULL); - else { - doWriteByte(UUID); - doWriteLong(uuid.getMostSignificantBits()); - doWriteLong(uuid.getLeastSignificantBits()); - } - } - - /** - * @param date Date. - */ - public void doWriteDate(@Nullable Date date) { - if (date == null) - doWriteByte(NULL); - else { - doWriteByte(DATE); - doWriteLong(date.getTime()); - } - } - - /** - * @param ts Timestamp. - */ - public void doWriteTimestamp(@Nullable Timestamp ts) { - if (ts== null) - doWriteByte(NULL); - else { - doWriteByte(TIMESTAMP); - doWriteLong(ts.getTime()); - doWriteInt(ts.getNanos() % 1000000); - } - } - - /** - * Write object. - * - * @param obj Object. - * @throws PortableException In case of error. - */ - public void doWriteObject(@Nullable Object obj) throws PortableException { - if (obj == null) - doWriteByte(NULL); - else { - PortableWriterExImpl writer = new PortableWriterExImpl(ctx, out, handles); - - writer.marshal(obj); - } - } - - /** - * @param val Byte array. - */ - void doWriteByteArray(@Nullable byte[] val) { - if (val == null) - doWriteByte(NULL); - else { - if (tryWriteAsHandle(val)) - return; - - doWriteByte(BYTE_ARR); - doWriteInt(val.length); - - out.writeByteArray(val); - } - } - - /** - * @param val Short array. - */ - void doWriteShortArray(@Nullable short[] val) { - if (val == null) - doWriteByte(NULL); - else { - if (tryWriteAsHandle(val)) - return; - - doWriteByte(SHORT_ARR); - doWriteInt(val.length); - - out.writeShortArray(val); - } - } - - /** - * @param val Integer array. - */ - void doWriteIntArray(@Nullable int[] val) { - if (val == null) - doWriteByte(NULL); - else { - if (tryWriteAsHandle(val)) - return; - - doWriteByte(INT_ARR); - doWriteInt(val.length); - - out.writeIntArray(val); - } - } - - /** - * @param val Long array. - */ - void doWriteLongArray(@Nullable long[] val) { - if (val == null) - doWriteByte(NULL); - else { - if (tryWriteAsHandle(val)) - return; - - doWriteByte(LONG_ARR); - doWriteInt(val.length); - - out.writeLongArray(val); - } - } - - /** - * @param val Float array. - */ - void doWriteFloatArray(@Nullable float[] val) { - if (val == null) - doWriteByte(NULL); - else { - if (tryWriteAsHandle(val)) - return; - - doWriteByte(FLOAT_ARR); - doWriteInt(val.length); - - out.writeFloatArray(val); - } - } - - /** - * @param val Double array. - */ - void doWriteDoubleArray(@Nullable double[] val) { - if (val == null) - doWriteByte(NULL); - else { - if (tryWriteAsHandle(val)) - return; - - doWriteByte(DOUBLE_ARR); - doWriteInt(val.length); - - out.writeDoubleArray(val); - } - } - - /** - * @param val Char array. - */ - void doWriteCharArray(@Nullable char[] val) { - if (val == null) - doWriteByte(NULL); - else { - if (tryWriteAsHandle(val)) - return; - - doWriteByte(CHAR_ARR); - doWriteInt(val.length); - - out.writeCharArray(val); - } - } - - /** - * @param val Boolean array. - */ - void doWriteBooleanArray(@Nullable boolean[] val) { - if (val == null) - doWriteByte(NULL); - else { - if (tryWriteAsHandle(val)) - return; - - doWriteByte(BOOLEAN_ARR); - doWriteInt(val.length); - - out.writeBooleanArray(val); - } - } - - /** - * @param val Array of strings. - */ - void doWriteDecimalArray(@Nullable BigDecimal[] val) { - if (val == null) - doWriteByte(NULL); - else { - if (tryWriteAsHandle(val)) - return; - - doWriteByte(DECIMAL_ARR); - doWriteInt(val.length); - - for (BigDecimal str : val) - doWriteDecimal(str); - } - } - - /** - * @param val Array of strings. - */ - void doWriteStringArray(@Nullable String[] val) { - if (val == null) - doWriteByte(NULL); - else { - if (tryWriteAsHandle(val)) - return; - - doWriteByte(STRING_ARR); - doWriteInt(val.length); - - for (String str : val) - doWriteString(str); - } - } - - /** - * @param val Array of UUIDs. - */ - void doWriteUuidArray(@Nullable UUID[] val) { - if (val == null) - doWriteByte(NULL); - else { - if (tryWriteAsHandle(val)) - return; - - doWriteByte(UUID_ARR); - doWriteInt(val.length); - - for (UUID uuid : val) - doWriteUuid(uuid); - } - } - - /** - * @param val Array of dates. - */ - void doWriteDateArray(@Nullable Date[] val) { - if (val == null) - doWriteByte(NULL); - else { - if (tryWriteAsHandle(val)) - return; - - doWriteByte(DATE_ARR); - doWriteInt(val.length); - - for (Date date : val) - doWriteDate(date); - } - } - - /** - * @param val Array of timestamps. - */ - void doWriteTimestampArray(@Nullable Timestamp[] val) { - if (val == null) - doWriteByte(NULL); - else { - if (tryWriteAsHandle(val)) - return; - - doWriteByte(TIMESTAMP_ARR); - doWriteInt(val.length); - - for (Timestamp ts : val) - doWriteTimestamp(ts); - } - } - - /** - * @param val Array of objects. - * @throws PortableException In case of error. - */ - void doWriteObjectArray(@Nullable Object[] val) throws PortableException { - if (val == null) - doWriteByte(NULL); - else { - if (tryWriteAsHandle(val)) - return; - - PortableClassDescriptor desc = ctx.descriptorForClass(val.getClass().getComponentType()); - - doWriteByte(OBJ_ARR); - - if (desc.registered()) - doWriteInt(desc.typeId()); - else { - doWriteInt(UNREGISTERED_TYPE_ID); - doWriteString(val.getClass().getComponentType().getName()); - } - - doWriteInt(val.length); - - for (Object obj : val) - doWriteObject(obj); - } - } - - /** - * @param col Collection. - * @throws PortableException In case of error. - */ - void doWriteCollection(@Nullable Collection col) throws PortableException { - if (col == null) - doWriteByte(NULL); - else { - if (tryWriteAsHandle(col)) - return; - - doWriteByte(COL); - doWriteInt(col.size()); - doWriteByte(ctx.collectionType(col.getClass())); - - for (Object obj : col) - doWriteObject(obj); - } - } - - /** - * @param map Map. - * @throws PortableException In case of error. - */ - void doWriteMap(@Nullable Map map) throws PortableException { - if (map == null) - doWriteByte(NULL); - else { - if (tryWriteAsHandle(map)) - return; - - doWriteByte(MAP); - doWriteInt(map.size()); - doWriteByte(ctx.mapType(map.getClass())); - - for (Map.Entry e : map.entrySet()) { - doWriteObject(e.getKey()); - doWriteObject(e.getValue()); - } - } - } - - /** - * @param e Map entry. - * @throws PortableException In case of error. - */ - void doWriteMapEntry(@Nullable Map.Entry e) throws PortableException { - if (e == null) - doWriteByte(NULL); - else { - if (tryWriteAsHandle(e)) - return; - - doWriteByte(MAP_ENTRY); - doWriteObject(e.getKey()); - doWriteObject(e.getValue()); - } - } - - /** - * @param val Value. - */ - void doWriteEnum(@Nullable Enum val) { - if (val == null) - doWriteByte(NULL); - else { - PortableClassDescriptor desc = ctx.descriptorForClass(val.getClass()); - - doWriteByte(ENUM); - - if (desc.registered()) - doWriteInt(desc.typeId()); - else { - doWriteInt(UNREGISTERED_TYPE_ID); - doWriteString(val.getClass().getName()); - } - - doWriteInt(val.ordinal()); - } - } - - /** - * @param val Array. - */ - void doWriteEnumArray(@Nullable Object[] val) { - assert val == null || val.getClass().getComponentType().isEnum(); - - if (val == null) - doWriteByte(NULL); - else { - PortableClassDescriptor desc = ctx.descriptorForClass(val.getClass().getComponentType()); - doWriteByte(ENUM_ARR); - - if (desc.registered()) - doWriteInt(desc.typeId()); - else { - doWriteInt(UNREGISTERED_TYPE_ID); - doWriteString(val.getClass().getComponentType().getName()); - } - - doWriteInt(val.length); - - // TODO: Denis: Redundant data for each element of the array. - for (Object o : val) - doWriteEnum((Enum)o); - } - } - - /** - * @param val Class. - */ - void doWriteClass(@Nullable Class val) { - if (val == null) - doWriteByte(NULL); - else { - PortableClassDescriptor desc = ctx.descriptorForClass(val); - - doWriteByte(CLASS); - - if (desc.registered()) - doWriteInt(desc.typeId()); - else { - doWriteInt(UNREGISTERED_TYPE_ID); - doWriteString(val.getClass().getName()); - } - } - } - - /** - * @param po Portable object. - */ - public void doWritePortableObject(@Nullable PortableObjectImpl po) { - if (po == null) - doWriteByte(NULL); - else { - doWriteByte(PORTABLE_OBJ); - - byte[] poArr = po.array(); - - doWriteInt(poArr.length); - - out.writeByteArray(poArr); - - doWriteInt(po.start()); - } - } - - /** - * @param val Value. - */ - void writeByteField(@Nullable Byte val) { - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(BYTE); - doWriteByte(val); - } - } - - /** - * @param val Class. - */ - void writeClassField(@Nullable Class val) { - doWriteClass(val); - } - - /** - * @param val Value. - */ - void writeShortField(@Nullable Short val) { - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(SHORT); - doWriteShort(val); - } - } - - /** - * @param val Value. - */ - void writeIntField(@Nullable Integer val) { - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(INT); - doWriteInt(val); - } - } - - /** - * @param val Value. - */ - void writeLongField(@Nullable Long val) { - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(LONG); - doWriteLong(val); - } - } - - /** - * @param val Value. - */ - void writeFloatField(@Nullable Float val) { - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(FLOAT); - doWriteFloat(val); - } - } - - /** - * @param val Value. - */ - void writeDoubleField(@Nullable Double val) { - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(DOUBLE); - doWriteDouble(val); - } - } - - /** - * @param val Value. - */ - void writeCharField(@Nullable Character val) { - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(CHAR); - doWriteChar(val); - } - } - - /** - * @param val Value. - */ - void writeBooleanField(@Nullable Boolean val) { - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(BOOLEAN); - doWriteBoolean(val); - } - } - - /** - * @param val Value. - */ - void writeDecimalField(@Nullable BigDecimal val) { - doWriteDecimal(val); - } - - /** - * @param val Value. - */ - void writeStringField(@Nullable String val) { - doWriteString(val); - } - - /** - * @param val Value. - */ - void writeUuidField(@Nullable UUID val) { - doWriteUuid(val); - } - - /** - * @param val Value. - */ - void writeDateField(@Nullable Date val) { - doWriteDate(val); - } - - /** - * @param val Value. - */ - void writeTimestampField(@Nullable Timestamp val) { - doWriteTimestamp(val); - } - - /** - * @param obj Object. - * @throws PortableException In case of error. - */ - void writeObjectField(@Nullable Object obj) throws PortableException { - doWriteObject(obj); - } - - /** - * @param val Value. - */ - void writeByteArrayField(@Nullable byte[] val) { - doWriteByteArray(val); - } - - /** - * @param val Value. - */ - void writeShortArrayField(@Nullable short[] val) { - doWriteShortArray(val); - } - - /** - * @param val Value. - */ - void writeIntArrayField(@Nullable int[] val) { - doWriteIntArray(val); - } - - /** - * @param val Value. - */ - void writeLongArrayField(@Nullable long[] val) { - doWriteLongArray(val); - } - - /** - * @param val Value. - */ - void writeFloatArrayField(@Nullable float[] val) { - doWriteFloatArray(val); - } - - /** - * @param val Value. - */ - void writeDoubleArrayField(@Nullable double[] val) { - doWriteDoubleArray(val); - } - - /** - * @param val Value. - */ - void writeCharArrayField(@Nullable char[] val) { - doWriteCharArray(val); - } - - /** - * @param val Value. - */ - void writeBooleanArrayField(@Nullable boolean[] val) { - doWriteBooleanArray(val); - } - - /** - * @param val Value. - */ - void writeDecimalArrayField(@Nullable BigDecimal[] val) { - doWriteDecimalArray(val); - } - - /** - * @param val Value. - */ - void writeStringArrayField(@Nullable String[] val) { - doWriteStringArray(val); - } - - /** - * @param val Value. - */ - void writeUuidArrayField(@Nullable UUID[] val) { - doWriteUuidArray(val); - } - - /** - * @param val Value. - */ - void writeDateArrayField(@Nullable Date[] val) { - doWriteDateArray(val); - } - - /** - * @param val Value. - */ - void writeTimestampArrayField(@Nullable Timestamp[] val) { - doWriteTimestampArray(val); - } - - /** - * @param val Value. - * @throws PortableException In case of error. - */ - void writeObjectArrayField(@Nullable Object[] val) throws PortableException { - doWriteObjectArray(val); - } - - /** - * @param col Collection. - * @throws PortableException In case of error. - */ - void writeCollectionField(@Nullable Collection col) throws PortableException { - doWriteCollection(col); - } - - /** - * @param map Map. - * @throws PortableException In case of error. - */ - void writeMapField(@Nullable Map map) throws PortableException { - doWriteMap(map); - } - - /** - * @param e Map entry. - * @throws PortableException In case of error. - */ - void writeMapEntryField(@Nullable Map.Entry e) throws PortableException { - doWriteMapEntry(e); - } - - /** - * @param val Value. - */ - void writeEnumField(@Nullable Enum val) { - doWriteEnum(val); - } - - /** - * @param val Value. - */ - void writeEnumArrayField(@Nullable Object[] val) { - doWriteEnumArray(val); - } - - /** - * @param po Portable object. - * @throws PortableException In case of error. - */ - void writePortableObjectField(@Nullable PortableObjectImpl po) throws PortableException { - doWritePortableObject(po); - } - - /** {@inheritDoc} */ - @Override public void writeByte(String fieldName, byte val) throws PortableException { - writeFieldId(fieldName, BYTE); - writeByteField(val); - } - - /** {@inheritDoc} */ - @Override public void writeByte(byte val) throws PortableException { - doWriteByte(val); - } - - /** {@inheritDoc} */ - @Override public void writeShort(String fieldName, short val) throws PortableException { - writeFieldId(fieldName, SHORT); - writeShortField(val); - } - - /** {@inheritDoc} */ - @Override public void writeShort(short val) throws PortableException { - doWriteShort(val); - } - - /** {@inheritDoc} */ - @Override public void writeInt(String fieldName, int val) throws PortableException { - writeFieldId(fieldName, INT); - writeIntField(val); - } - - /** {@inheritDoc} */ - @Override public void writeInt(int val) throws PortableException { - doWriteInt(val); - } - - /** {@inheritDoc} */ - @Override public void writeLong(String fieldName, long val) throws PortableException { - writeFieldId(fieldName, LONG); - writeLongField(val); - } - - /** {@inheritDoc} */ - @Override public void writeLong(long val) throws PortableException { - doWriteLong(val); - } - - /** {@inheritDoc} */ - @Override public void writeFloat(String fieldName, float val) throws PortableException { - writeFieldId(fieldName, FLOAT); - writeFloatField(val); - } - - /** {@inheritDoc} */ - @Override public void writeFloat(float val) throws PortableException { - doWriteFloat(val); - } - - /** {@inheritDoc} */ - @Override public void writeDouble(String fieldName, double val) throws PortableException { - writeFieldId(fieldName, DOUBLE); - writeDoubleField(val); - } - - /** {@inheritDoc} */ - @Override public void writeDouble(double val) throws PortableException { - doWriteDouble(val); - } - - /** {@inheritDoc} */ - @Override public void writeChar(String fieldName, char val) throws PortableException { - writeFieldId(fieldName, CHAR); - writeCharField(val); - } - - /** {@inheritDoc} */ - @Override public void writeChar(char val) throws PortableException { - doWriteChar(val); - } - - /** {@inheritDoc} */ - @Override public void writeBoolean(String fieldName, boolean val) throws PortableException { - writeFieldId(fieldName, BOOLEAN); - writeBooleanField(val); - } - - /** {@inheritDoc} */ - @Override public void writeBoolean(boolean val) throws PortableException { - doWriteBoolean(val); - } - - /** {@inheritDoc} */ - @Override public void writeDecimal(String fieldName, @Nullable BigDecimal val) throws PortableException { - writeFieldId(fieldName, DECIMAL); - writeDecimalField(val); - } - - /** {@inheritDoc} */ - @Override public void writeDecimal(@Nullable BigDecimal val) throws PortableException { - doWriteDecimal(val); - } - - /** {@inheritDoc} */ - @Override public void writeString(String fieldName, @Nullable String val) throws PortableException { - writeFieldId(fieldName, STRING); - writeStringField(val); - } - - /** {@inheritDoc} */ - @Override public void writeString(@Nullable String val) throws PortableException { - doWriteString(val); - } - - /** {@inheritDoc} */ - @Override public void writeUuid(String fieldName, @Nullable UUID val) throws PortableException { - writeFieldId(fieldName, UUID); - writeUuidField(val); - } - - /** {@inheritDoc} */ - @Override public void writeUuid(@Nullable UUID val) throws PortableException { - doWriteUuid(val); - } - - /** {@inheritDoc} */ - @Override public void writeDate(String fieldName, @Nullable Date val) throws PortableException { - writeFieldId(fieldName, DATE); - writeDateField(val); - } - - /** {@inheritDoc} */ - @Override public void writeDate(@Nullable Date val) throws PortableException { - doWriteDate(val); - } - - /** {@inheritDoc} */ - @Override public void writeTimestamp(String fieldName, @Nullable Timestamp val) throws PortableException { - writeFieldId(fieldName, TIMESTAMP); - writeTimestampField(val); - } - - /** {@inheritDoc} */ - @Override public void writeTimestamp(@Nullable Timestamp val) throws PortableException { - doWriteTimestamp(val); - } - - /** {@inheritDoc} */ - @Override public void writeObject(String fieldName, @Nullable Object obj) throws PortableException { - writeFieldId(fieldName, OBJ); - writeObjectField(obj); - } - - /** {@inheritDoc} */ - @Override public void writeObject(@Nullable Object obj) throws PortableException { - doWriteObject(obj); - } - - /** {@inheritDoc} */ - @Override public void writeObjectDetached(@Nullable Object obj) throws PortableException { - if (obj == null) - doWriteByte(NULL); - else { - PortableWriterExImpl writer = new PortableWriterExImpl(ctx, out, new IdentityHashMap()); - - writer.marshal(obj); - } - } - - /** {@inheritDoc} */ - @Override public void writeByteArray(String fieldName, @Nullable byte[] val) throws PortableException { - writeFieldId(fieldName, BYTE_ARR); - writeByteArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeByteArray(@Nullable byte[] val) throws PortableException { - doWriteByteArray(val); - } - - /** {@inheritDoc} */ - @Override public void writeShortArray(String fieldName, @Nullable short[] val) throws PortableException { - writeFieldId(fieldName, SHORT_ARR); - writeShortArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeShortArray(@Nullable short[] val) throws PortableException { - doWriteShortArray(val); - } - - /** {@inheritDoc} */ - @Override public void writeIntArray(String fieldName, @Nullable int[] val) throws PortableException { - writeFieldId(fieldName, INT_ARR); - writeIntArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeIntArray(@Nullable int[] val) throws PortableException { - doWriteIntArray(val); - } - - /** {@inheritDoc} */ - @Override public void writeLongArray(String fieldName, @Nullable long[] val) throws PortableException { - writeFieldId(fieldName, LONG_ARR); - writeLongArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeLongArray(@Nullable long[] val) throws PortableException { - doWriteLongArray(val); - } - - /** {@inheritDoc} */ - @Override public void writeFloatArray(String fieldName, @Nullable float[] val) throws PortableException { - writeFieldId(fieldName, FLOAT_ARR); - writeFloatArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeFloatArray(@Nullable float[] val) throws PortableException { - doWriteFloatArray(val); - } - - /** {@inheritDoc} */ - @Override public void writeDoubleArray(String fieldName, @Nullable double[] val) - throws PortableException { - writeFieldId(fieldName, DOUBLE_ARR); - writeDoubleArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeDoubleArray(@Nullable double[] val) throws PortableException { - doWriteDoubleArray(val); - } - - /** {@inheritDoc} */ - @Override public void writeCharArray(String fieldName, @Nullable char[] val) throws PortableException { - writeFieldId(fieldName, CHAR_ARR); - writeCharArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeCharArray(@Nullable char[] val) throws PortableException { - doWriteCharArray(val); - } - - /** {@inheritDoc} */ - @Override public void writeBooleanArray(String fieldName, @Nullable boolean[] val) - throws PortableException { - writeFieldId(fieldName, BOOLEAN_ARR); - writeBooleanArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeBooleanArray(@Nullable boolean[] val) throws PortableException { - doWriteBooleanArray(val); - } - - /** {@inheritDoc} */ - @Override public void writeDecimalArray(String fieldName, @Nullable BigDecimal[] val) - throws PortableException { - writeFieldId(fieldName, DECIMAL_ARR); - writeDecimalArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeDecimalArray(@Nullable BigDecimal[] val) throws PortableException { - doWriteDecimalArray(val); - } - - /** {@inheritDoc} */ - @Override public void writeStringArray(String fieldName, @Nullable String[] val) - throws PortableException { - writeFieldId(fieldName, STRING_ARR); - writeStringArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeStringArray(@Nullable String[] val) throws PortableException { - doWriteStringArray(val); - } - - /** {@inheritDoc} */ - @Override public void writeUuidArray(String fieldName, @Nullable UUID[] val) throws PortableException { - writeFieldId(fieldName, UUID_ARR); - writeUuidArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeUuidArray(@Nullable UUID[] val) throws PortableException { - doWriteUuidArray(val); - } - - /** {@inheritDoc} */ - @Override public void writeDateArray(String fieldName, @Nullable Date[] val) throws PortableException { - writeFieldId(fieldName, DATE_ARR); - writeDateArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeDateArray(@Nullable Date[] val) throws PortableException { - doWriteDateArray(val); - } - - /** {@inheritDoc} */ - @Override public void writeTimestampArray(String fieldName, @Nullable Timestamp[] val) throws PortableException { - writeFieldId(fieldName, TIMESTAMP_ARR); - writeTimestampArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeTimestampArray(@Nullable Timestamp[] val) throws PortableException { - doWriteTimestampArray(val); - } - - /** {@inheritDoc} */ - @Override public void writeObjectArray(String fieldName, @Nullable Object[] val) throws PortableException { - writeFieldId(fieldName, OBJ_ARR); - writeObjectArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeObjectArray(@Nullable Object[] val) throws PortableException { - doWriteObjectArray(val); - } - - /** {@inheritDoc} */ - @Override public void writeCollection(String fieldName, @Nullable Collection col) - throws PortableException { - writeFieldId(fieldName, COL); - writeCollectionField(col); - } - - /** {@inheritDoc} */ - @Override public void writeCollection(@Nullable Collection col) throws PortableException { - doWriteCollection(col); - } - - /** {@inheritDoc} */ - @Override public void writeMap(String fieldName, @Nullable Map map) - throws PortableException { - writeFieldId(fieldName, MAP); - writeMapField(map); - } - - /** {@inheritDoc} */ - @Override public void writeMap(@Nullable Map map) throws PortableException { - doWriteMap(map); - } - - /** {@inheritDoc} */ - @Override public > void writeEnum(String fieldName, T val) throws PortableException { - writeFieldId(fieldName, ENUM); - writeEnumField(val); - } - - /** {@inheritDoc} */ - @Override public > void writeEnum(T val) throws PortableException { - doWriteEnum(val); - } - - /** {@inheritDoc} */ - @Override public > void writeEnumArray(String fieldName, T[] val) throws PortableException { - writeFieldId(fieldName, ENUM_ARR); - writeEnumArrayField(val); - } - - /** {@inheritDoc} */ - @Override public > void writeEnumArray(T[] val) throws PortableException { - doWriteEnumArray(val); - } - - /** {@inheritDoc} */ - @Override public PortableRawWriter rawWriter() { - if (rawOffPos == 0) - rawOffPos = out.position(); - - return this; - } - - /** {@inheritDoc} */ - @Override public PortableOutputStream out() { - return out; - } - - /** {@inheritDoc} */ - @SuppressWarnings("NullableProblems") - @Override public void writeBytes(String s) throws IOException { - int len = s.length(); - - writeInt(len); - - for (int i = 0; i < len; i++) - writeByte(s.charAt(i)); - } - - /** {@inheritDoc} */ - @SuppressWarnings("NullableProblems") - @Override public void writeChars(String s) throws IOException { - int len = s.length(); - - writeInt(len); - - for (int i = 0; i < len; i++) - writeChar(s.charAt(i)); - } - - /** {@inheritDoc} */ - @SuppressWarnings("NullableProblems") - @Override public void writeUTF(String s) throws IOException { - writeString(s); - } - - /** {@inheritDoc} */ - @Override public void writeByte(int v) throws IOException { - doWriteByte((byte) v); - } - - /** {@inheritDoc} */ - @Override public void writeShort(int v) throws IOException { - doWriteShort((short) v); - } - - /** {@inheritDoc} */ - @Override public void writeChar(int v) throws IOException { - doWriteChar((char) v); - } - - /** {@inheritDoc} */ - @Override public void write(int b) throws IOException { - doWriteByte((byte) b); - } - - /** {@inheritDoc} */ - @Override public void flush() throws IOException { - // No-op. - } - - /** {@inheritDoc} */ - @Override public int reserveInt() { - return reserve(LEN_INT); - } - - /** {@inheritDoc} */ - @Override public void writeInt(int pos, int val) throws PortableException { - out.writeInt(pos, val); - } - - /** - * @param fieldName Field name. - * @throws PortableException If fields are not allowed. - */ - private void writeFieldId(String fieldName, byte fieldType) throws PortableException { - A.notNull(fieldName, "fieldName"); - - if (rawOffPos != 0) - throw new PortableException("Individual field can't be written after raw writer is acquired " + - "via rawWriter() method. Consider fixing serialization logic for class: " + cls.getName()); - - if (idMapper == null) - idMapper = ctx.userTypeIdMapper(typeId); - - int id = idMapper.fieldId(typeId, fieldName); - - writeFieldId(id); - - if (metaEnabled) - metaHashSum = 31 * metaHashSum + (id + fieldType); - } - - /** - * Write field ID. - * @param fieldId Field ID. - */ - public void writeFieldId(int fieldId) { - int fieldOff = out.position() - start; - - if (schema == null) { - schema = SCHEMA.get(); - - if (schema == null) { - schema = new SchemaHolder(); - - SCHEMA.set(schema); - } - - // Initialize offset when the first field is written. - schemaId = FNV1_OFFSET_BASIS; - } - - // Advance schema hash. - int schemaId0 = schemaId ^ (fieldId & 0xFF); - schemaId0 = schemaId0 * FNV1_PRIME; - schemaId0 = schemaId0 ^ ((fieldId >> 8) & 0xFF); - schemaId0 = schemaId0 * FNV1_PRIME; - schemaId0 = schemaId0 ^ ((fieldId >> 16) & 0xFF); - schemaId0 = schemaId0 * FNV1_PRIME; - schemaId0 = schemaId0 ^ ((fieldId >> 24) & 0xFF); - schemaId0 = schemaId0 * FNV1_PRIME; - - schemaId = schemaId0; - - schema.push(fieldId, fieldOff); - - fieldCnt++; - } - - /** - * Attempts to write the object as a handle. - * - * @param obj Object to write. - * @return {@code true} if the object has been written as a handle. - */ - boolean tryWriteAsHandle(Object obj) { - int handle = handle(obj); - - if (handle >= 0) { - doWriteByte(GridPortableMarshaller.HANDLE); - doWriteInt(handle); - - return true; - } - - return false; - } - - /** - * Create new writer with same context. - * - * @param typeId type - * @return New writer. - */ - public PortableWriterExImpl newWriter(int typeId) { - PortableWriterExImpl res = new PortableWriterExImpl(ctx, out, handles); - - res.typeId = typeId; - - return res; - } - - /** - * @return Portable context. - */ - public PortableContext context() { - return ctx; - } - - /** - * Schema holder. - */ - private static class SchemaHolder { - /** Grow step. */ - private static final int GROW_STEP = 64; - - /** Maximum stable size. */ - private static final int MAX_SIZE = 1024; - - /** Data. */ - private int[] data; - - /** Index. */ - private int idx; - - /** - * Constructor. - */ - public SchemaHolder() { - data = new int[GROW_STEP]; - } - - /** - * Push another frame. - * - * @param id Field ID. - * @param off Field offset. - */ - public void push(int id, int off) { - if (idx == data.length) { - int[] data0 = new int[data.length + GROW_STEP]; - - System.arraycopy(data, 0, data0, 0, data.length); - - data = data0; - } - - data[idx] = id; - data[idx + 1] = off; - - idx += 2; - } - - /** - * Write collected frames and pop them. - * - * @param writer Writer. - * @param fieldCnt Count. - * @return Amount of bytes dedicated to - */ - public int write(PortableWriterExImpl writer, int fieldCnt) { - int startIdx = idx - fieldCnt * 2; - - assert startIdx >= 0; - - int lastOffset = data[idx - 1]; - - int res; - - if (lastOffset < MAX_OFFSET_1) { - for (int idx0 = startIdx; idx0 < idx; ) { - writer.writeInt(data[idx0++]); - writer.writeByte((byte) data[idx0++]); - } - - res = PortableUtils.OFFSET_1; - } - else if (lastOffset < MAX_OFFSET_2) { - for (int idx0 = startIdx; idx0 < idx; ) { - writer.writeInt(data[idx0++]); - writer.writeShort((short)data[idx0++]); - } - - res = PortableUtils.OFFSET_2; - } - else { - for (int idx0 = startIdx; idx0 < idx; ) { - writer.writeInt(data[idx0++]); - writer.writeInt(data[idx0++]); - } - - res = PortableUtils.OFFSET_4; - } - - return res; - } - - /** - * Pop current object's frame. - */ - public void pop(int fieldCnt) { - idx = idx - fieldCnt * 2; - - // Shrink data array if needed. - if (idx == 0 && data.length > MAX_SIZE) - data = new int[MAX_SIZE]; - } - } -} http://git-wip-us.apache.org/repos/asf/ignite/blob/b783d2b7/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/BinaryObjectBuilderImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/BinaryObjectBuilderImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/BinaryObjectBuilderImpl.java new file mode 100644 index 0000000..8844660 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/BinaryObjectBuilderImpl.java @@ -0,0 +1,569 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.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.binary.BinaryObject; +import org.apache.ignite.binary.BinaryObjectBuilder; +import org.apache.ignite.binary.BinaryObjectException; +import org.apache.ignite.binary.BinaryInvalidTypeException; +import org.apache.ignite.binary.BinaryType; +import org.apache.ignite.internal.portable.BinaryObjectImpl; +import org.apache.ignite.internal.portable.BinaryObjectOffheapImpl; +import org.apache.ignite.internal.portable.BinaryWriterExImpl; +import org.apache.ignite.internal.portable.GridPortableMarshaller; +import org.apache.ignite.internal.portable.PortableContext; +import org.apache.ignite.internal.portable.PortableUtils; +import org.apache.ignite.internal.processors.cache.portable.CacheObjectBinaryProcessorImpl; +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.FLAGS_POS; +import static org.apache.ignite.internal.portable.GridPortableMarshaller.HASH_CODE_POS; +import static org.apache.ignite.internal.portable.GridPortableMarshaller.PROTO_VER_POS; +import static org.apache.ignite.internal.portable.GridPortableMarshaller.TYPE_ID_POS; +import static org.apache.ignite.internal.portable.GridPortableMarshaller.UNREGISTERED_TYPE_ID; + +/** + * + */ +public class BinaryObjectBuilderImpl implements BinaryObjectBuilder { + /** */ + private static final Object REMOVED_FIELD_MARKER = new Object(); + + /** */ + private final PortableContext ctx; + + /** */ + private final int typeId; + + /** May be null. */ + private String typeName; + + /** May be null. */ + private String clsNameToWrite; + + /** */ + private boolean registeredType = true; + + /** */ + private Map assignedVals; + + /** */ + private Map readCache; + + /** Position of object in source array, or -1 if object is not created from PortableObject. */ + private final int start; + + /** Flags. */ + private final short flags; + + /** Total header length */ + private final int hdrLen; + + /** Context of PortableObject reading process. Or {@code null} if object is not created from PortableObject. */ + private final PortableBuilderReader reader; + + /** */ + private int hashCode; + + /** + * @param clsName Class name. + * @param ctx Portable context. + */ + public BinaryObjectBuilderImpl(PortableContext ctx, String clsName) { + this(ctx, ctx.typeId(clsName), PortableContext.typeName(clsName)); + } + + /** + * @param typeId Type ID. + * @param ctx Portable context. + */ + public BinaryObjectBuilderImpl(PortableContext ctx, int typeId) { + this(ctx, typeId, null); + } + + /** + * @param typeName Type name. + * @param ctx Context. + * @param typeId Type id. + */ + public BinaryObjectBuilderImpl(PortableContext ctx, int typeId, String typeName) { + this.typeId = typeId; + this.typeName = typeName; + this.ctx = ctx; + + start = -1; + flags = -1; + reader = null; + hdrLen = DFLT_HDR_LEN; + + readCache = Collections.emptyMap(); + } + + /** + * @param obj Object to wrap. + */ + public BinaryObjectBuilderImpl(BinaryObjectImpl obj) { + this(new PortableBuilderReader(obj), obj.start()); + + reader.registerObject(this); + } + + /** + * @param reader ctx + * @param start Start. + */ + BinaryObjectBuilderImpl(PortableBuilderReader reader, int start) { + this.reader = reader; + this.start = start; + this.flags = reader.readShortPositioned(start + FLAGS_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 BinaryInvalidTypeException("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 BinaryObject build() { + try (BinaryWriterExImpl writer = new BinaryWriterExImpl(ctx, typeId, false)) { + + PortableBuilderSerializer serializationCtx = new PortableBuilderSerializer(); + + serializationCtx.registerObjectWriting(this, 0); + + serializeTo(writer, serializationCtx); + + byte[] arr = writer.array(); + + return new BinaryObjectImpl(ctx, arr, 0); + } + } + + /** + * @param writer Writer. + * @param serializer Serializer. + */ + void serializeTo(BinaryWriterExImpl writer, PortableBuilderSerializer serializer) { + try { + PortableUtils.writeHeader(writer, + true, + registeredType ? typeId : UNREGISTERED_TYPE_ID, + hashCode, + registeredType ? null : clsNameToWrite); + + Set remainsFlds = null; + + if (reader != null) { + Map assignedFldsById; + + if (assignedVals != null) { + assignedFldsById = U.newHashMap(assignedVals.size()); + + for (Map.Entry 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. + int fieldOffsetSize = PortableUtils.fieldOffsetSize(flags); + + IgniteBiTuple footer = PortableUtils.footerAbsolute(reader, start, fieldOffsetSize); + + int footerPos = footer.get1(); + int footerEnd = footer.get2(); + + // Get raw position. + int rawPos = PortableUtils.rawOffsetAbsolute(reader, start, fieldOffsetSize); + + // Position reader on data. + reader.position(start + hdrLen); + + while (reader.position() + 4 < rawPos) { + int fieldId = reader.readIntPositioned(footerPos); + int fieldLen = fieldPositionAndLength(footerPos, footerEnd, rawPos, fieldOffsetSize).get2(); + + int postPos = reader.position() + fieldLen; // Position where reader will be placed afterwards. + + footerPos += 4 + fieldOffsetSize; + + if (assignedFldsById.containsKey(fieldId)) { + Object assignedVal = assignedFldsById.remove(fieldId); + + if (assignedVal != REMOVED_FIELD_MARKER) { + writer.writeFieldId(fieldId); + + serializer.writeValue(writer, assignedVal); + } + } + else { + int type = fieldLen != 0 ? reader.readByte(0) : 0; + + if (fieldLen != 0 && !PortableUtils.isPlainArrayType(type) && PortableUtils.isPlainType(type)) { + writer.writeFieldId(fieldId); + + writer.write(reader.array(), reader.position(), fieldLen); + } + else { + writer.writeFieldId(fieldId); + + Object val; + + if (fieldLen == 0) + val = null; + else if (readCache == null) { + val = reader.parseValue(); + + assert reader.position() == postPos; + } + else + val = readCache.get(fieldId); + + serializer.writeValue(writer, val); + } + } + + reader.position(postPos); + } + } + + if (assignedVals != null && (remainsFlds == null || !remainsFlds.isEmpty())) { + boolean metadataEnabled = ctx.isMetaDataEnabled(typeId); + + BinaryType metadata = null; + + if (metadataEnabled) + metadata = ctx.metaData(typeId); + + Map newFldsMetadata = null; + + for (Map.Entry 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 = CacheObjectBinaryProcessorImpl.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 { + String objTypeName = + CacheObjectBinaryProcessorImpl.FIELD_TYPE_NAMES[GridPortableMarshaller.OBJ]; + + if (!objTypeName.equals(oldFldTypeName) && !oldFldTypeName.equals(newFldTypeName)) { + throw new BinaryObjectException( + "Wrong value has been set [" + + "typeName=" + (typeName == null ? metadata.typeName() : typeName) + + ", fieldName=" + name + + ", fieldType=" + oldFldTypeName + + ", assignedValueType=" + newFldTypeName + ']' + ); + } + } + } + } + + 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 fieldOffsetSize = PortableUtils.fieldOffsetSize(flags); + + int rawOff = PortableUtils.rawOffsetAbsolute(reader, start, fieldOffsetSize); + 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); + } + finally { + writer.popSchema(); + } + } + + /** {@inheritDoc} */ + @Override public BinaryObjectBuilderImpl hashCode(int hashCode) { + this.hashCode = hashCode; + + return this; + } + + /** + * Get field position and length. + * + * @param footerPos Field position inside the footer (absolute). + * @param footerEnd Footer end (absolute). + * @param rawPos Raw data position (absolute). + * @param fieldOffsetSize Size of field's offset. + * @return Tuple with field position and length. + */ + private IgniteBiTuple fieldPositionAndLength(int footerPos, int footerEnd, int rawPos, + int fieldOffsetSize) { + // Get field offset first. + int fieldOffset = PortableUtils.fieldOffsetRelative(reader, footerPos + 4, fieldOffsetSize); + int fieldPos = start + fieldOffset; + + // Get field length. + int fieldLen; + + if (footerPos + 4 + fieldOffsetSize == footerEnd) + // This is the last field, compare to raw offset. + fieldLen = rawPos - fieldPos; + else { + // Field is somewhere in the middle, get difference with the next offset. + int nextFieldOffset = PortableUtils.fieldOffsetRelative(reader, footerPos + 4 + fieldOffsetSize + 4, + fieldOffsetSize); + + fieldLen = nextFieldOffset - fieldOffset; + } + + return F.t(fieldPos, fieldLen); + } + + /** + * Initialize read cache if needed. + */ + private void ensureReadCacheInit() { + if (readCache == null) { + int fieldOffsetSize = PortableUtils.fieldOffsetSize(flags); + + Map readCache = new HashMap<>(); + + IgniteBiTuple footer = PortableUtils.footerAbsolute(reader, start, fieldOffsetSize); + + int footerPos = footer.get1(); + int footerEnd = footer.get2(); + + int rawPos = PortableUtils.rawOffsetAbsolute(reader, start, fieldOffsetSize); + + while (footerPos + 4 < footerEnd) { + int fieldId = reader.readIntPositioned(footerPos); + + IgniteBiTuple posAndLen = + fieldPositionAndLength(footerPos, footerEnd, rawPos, fieldOffsetSize); + + Object val = reader.getValueQuickly(posAndLen.get1(), posAndLen.get2()); + + readCache.put(fieldId, val); + + // Shift current footer position. + footerPos += 4 + fieldOffsetSize; + } + + this.readCache = readCache; + } + } + + /** {@inheritDoc} */ + @SuppressWarnings("unchecked") + @Override public T getField(String name) { + Object val; + + if (assignedVals != null && assignedVals.containsKey(name)) { + val = assignedVals.get(name); + + if (val == REMOVED_FIELD_MARKER) + return null; + } + else { + ensureReadCacheInit(); + + int fldId = ctx.fieldId(typeId, name); + + val = readCache.get(fldId); + } + + return (T)PortableUtils.unwrapLazy(val); + } + + /** {@inheritDoc} */ + @Override public BinaryObjectBuilder setField(String name, Object 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 BinaryObjectBuilder setField(String name, @Nullable T val, Class 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 BinaryObjectBuilder setField(String name, @Nullable BinaryObjectBuilder builder) { + if (builder == null) + return setField(name, null, Object.class); + else + return setField(name, (Object)builder); + } + + /** + * Removes field from portable object. + * + * @param name Field name. + * @return {@code this} instance for chaining. + */ + @Override public BinaryObjectBuilderImpl removeField(String name) { + if (assignedVals == null) + assignedVals = new LinkedHashMap<>(); + + assignedVals.put(name, REMOVED_FIELD_MARKER); + + return this; + } + + /** + * Creates builder initialized by specified portable object. + * + * @param obj Portable object to initialize builder. + * @return New builder. + */ + public static BinaryObjectBuilderImpl wrap(BinaryObject obj) { + BinaryObjectImpl heapObj; + + if (obj instanceof BinaryObjectOffheapImpl) + heapObj = (BinaryObjectImpl)((BinaryObjectOffheapImpl)obj).heapCopy(); + else + heapObj = (BinaryObjectImpl)obj; + + return new BinaryObjectBuilderImpl(heapObj); + } + + /** + * @return Object start position in source array. + */ + int start() { + return start; + } + + /** + * @return Object type id. + */ + public int typeId() { + return typeId; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/b783d2b7/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderEnum.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderEnum.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderEnum.java index 1472d56..9eb77b4 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderEnum.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/PortableBuilderEnum.java @@ -18,9 +18,9 @@ package org.apache.ignite.internal.portable.builder; import org.apache.ignite.internal.portable.GridPortableMarshaller; -import org.apache.ignite.internal.portable.PortableWriterExImpl; +import org.apache.ignite.internal.portable.BinaryWriterExImpl; import org.apache.ignite.internal.util.typedef.internal.U; -import org.apache.ignite.portable.PortableInvalidClassException; +import org.apache.ignite.binary.BinaryInvalidTypeException; /** * @@ -61,7 +61,7 @@ public class PortableBuilderEnum implements PortableBuilderSerializationAware { cls = U.forName(reader.readString(), null); } catch (ClassNotFoundException e) { - throw new PortableInvalidClassException("Failed to load the class: " + clsName, e); + throw new BinaryInvalidTypeException("Failed to load the class: " + clsName, e); } this.typeId = reader.portableContext().descriptorForClass(cls).typeId(); @@ -82,7 +82,7 @@ public class PortableBuilderEnum implements PortableBuilderSerializationAware { } /** {@inheritDoc} */ - @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) { + @Override public void writeTo(BinaryWriterExImpl writer, PortableBuilderSerializer ctx) { writer.writeByte(GridPortableMarshaller.ENUM); if (typeId == GridPortableMarshaller.UNREGISTERED_TYPE_ID) {