alex-plekhanov commented on code in PR #11292: URL: https://github.com/apache/ignite/pull/11292#discussion_r1601847765
########## modules/core/src/main/java/org/apache/ignite/internal/binary/RawBytesObjectReader.java: ########## @@ -0,0 +1,309 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.binary; + +import org.apache.ignite.binary.BinaryObjectException; +import org.apache.ignite.internal.binary.streams.BinaryInputStream; +import org.apache.ignite.internal.binary.streams.BinaryOutputStream; + +/** */ +public class RawBytesObjectReader implements BinaryPositionReadable { Review Comment: Perhaps it's worth to add `Binary` word to class name. And we don't read objects in this class, so `object readed` is not very good name also. Perhaps `extractor` or something like this. ########## modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java: ########## @@ -282,16 +284,33 @@ private byte[] valueBytesFromArray(CacheObjectValueContext ctx) { * @return Detached binary object. */ public BinaryObjectImpl detach() { + return detach(true); + } + + /** */ + public BinaryObjectImpl detach(boolean resolveCrossObjectReferences) { Review Comment: Abbreviation should be used for `Object` ########## modules/core/src/main/java/org/apache/ignite/internal/binary/RawBytesObjectReader.java: ########## @@ -0,0 +1,309 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.binary; + +import org.apache.ignite.binary.BinaryObjectException; +import org.apache.ignite.internal.binary.streams.BinaryInputStream; +import org.apache.ignite.internal.binary.streams.BinaryOutputStream; + +/** */ +public class RawBytesObjectReader implements BinaryPositionReadable { + /** */ + private final BinaryInputStream in; + + /** */ + public RawBytesObjectReader(BinaryInputStream in) { + this.in = in; + } + + /** */ + public byte[] readObject() { + int startPos = in.position(); + + skipObject(); + + int endPos = in.position(); + + in.position(startPos); + + return in.readByteArray(endPos - startPos); + } + + /** */ + public void copyObject(BinaryOutputStream out) { + int startPos = in.position(); + + skipObject(); + + out.writeByteArray(in.array(), startPos, in.position() - startPos); + } + + /** */ + public int readInt() { + return in.readInt(); + } + + /** */ + public void skipObject() { + int objStartPos = in.position(); + + byte type = in.readByte(); + + switch (type) { + case GridBinaryMarshaller.NULL: + break; + + case GridBinaryMarshaller.OBJ: + skipBytes(BinaryUtils.length(in, objStartPos) - /** Object type. */ Byte.BYTES); + + break; + + case GridBinaryMarshaller.BINARY_OBJ: + skipBytes(in.readInt()); + + skipBytes(Integer.BYTES); // Offset. + + break; + + case GridBinaryMarshaller.BYTE: + case GridBinaryMarshaller.BOOLEAN: + skipBytes(Byte.BYTES); + + break; + + case GridBinaryMarshaller.CHAR: + skipBytes(Character.BYTES); + + break; + + case GridBinaryMarshaller.SHORT: + skipBytes(Short.BYTES); + + break; + + case GridBinaryMarshaller.FLOAT: + skipBytes(Float.BYTES); + + break; + + case GridBinaryMarshaller.HANDLE: + case GridBinaryMarshaller.INT: + skipBytes(Integer.BYTES); + + break; + + case GridBinaryMarshaller.ENUM: + case GridBinaryMarshaller.BINARY_ENUM: { + skipTypeId(); + + skipBytes(Integer.BYTES); // Ordinal. + + break; + } + + case GridBinaryMarshaller.LONG: + case GridBinaryMarshaller.DATE: + case GridBinaryMarshaller.TIME: + skipBytes(Long.BYTES); + + break; + + case GridBinaryMarshaller.DOUBLE: + skipBytes(Double.BYTES); + + break; + + case GridBinaryMarshaller.OPTM_MARSH: + case GridBinaryMarshaller.STRING: + skipBytes(in.readInt()); + + break; + + case GridBinaryMarshaller.DECIMAL: + skipBytes(Integer.BYTES); // Scale. + skipBytes(in.readInt()); + + break; + + case GridBinaryMarshaller.UUID: + skipBytes(Long.BYTES + Long.BYTES); + + break; + + case GridBinaryMarshaller.TIMESTAMP: + skipBytes(Long.BYTES + Integer.BYTES); + + break; + + case GridBinaryMarshaller.BYTE_ARR: + case GridBinaryMarshaller.BOOLEAN_ARR: + skipBytes(in.readInt() * Byte.BYTES); + + break; + + case GridBinaryMarshaller.CHAR_ARR: + skipBytes(in.readInt() * Character.BYTES); + + break; + + case GridBinaryMarshaller.SHORT_ARR: + skipBytes(in.readInt() * Short.BYTES); + + break; + + case GridBinaryMarshaller.INT_ARR: + skipBytes(in.readInt() * Integer.BYTES); + + break; + + case GridBinaryMarshaller.FLOAT_ARR: + skipBytes(in.readInt() * Float.BYTES); + + break; + + case GridBinaryMarshaller.LONG_ARR: + skipBytes(in.readInt() * Long.BYTES); + + break; + + case GridBinaryMarshaller.DOUBLE_ARR: + skipBytes(in.readInt() * Double.BYTES); + + break; + + case GridBinaryMarshaller.DECIMAL_ARR: + case GridBinaryMarshaller.DATE_ARR: + case GridBinaryMarshaller.TIMESTAMP_ARR: + case GridBinaryMarshaller.TIME_ARR: + case GridBinaryMarshaller.UUID_ARR: + case GridBinaryMarshaller.STRING_ARR: { + skipCortege(); + + break; + } + + case GridBinaryMarshaller.ENUM_ARR: + case GridBinaryMarshaller.OBJ_ARR: { + skipTypeId(); + + skipCortege(); + + break; + } + + case GridBinaryMarshaller.COL: { + int size = in.readInt(); + + skipBytes(Byte.BYTES); // Collection type. + + skipCortege(size); + + break; + } + + case GridBinaryMarshaller.MAP: { + int size = in.readInt() * 2; + + skipBytes(Byte.BYTES); // Map type. + + skipCortege(size); + + break; + } + + case GridBinaryMarshaller.CLASS: { + skipTypeId(); + + break; + } + + case GridBinaryMarshaller.PROXY: { + int size = in.readInt(); + + for (int i = 0; i < size; i++) + skipTypeId(); // Interface type. + + skipObject(); + + break; + } + + default: + throw new BinaryObjectException("Unsupported binary type [type=" + type + ']'); + } + } + + /** {@inheritDoc} */ + @Override public byte readBytePositioned(int pos) { + return in.readBytePositioned(pos); + } + + /** {@inheritDoc} */ + @Override public short readShortPositioned(int pos) { + return in.readShortPositioned(pos); + } + + /** {@inheritDoc} */ + @Override public int readIntPositioned(int pos) { + return in.readIntPositioned(pos); + } + + /** */ + public int position() { + return in.position(); + } + + /** */ + public void position(int position) { + in.position(position); + } + + /** */ + public void skipBytes(int count) { + int curPos = in.position(); + + in.position(curPos + count); + } + + /** */ + public void skipTypeId() { + int typeId = in.readInt(); + + if (typeId == GridBinaryMarshaller.UNREGISTERED_TYPE_ID) { + skipBytes(Byte.BYTES); // String type. + + skipBytes(in.readInt()); Review Comment: `skipObject()` ? ########## modules/core/src/main/java/org/apache/ignite/internal/binary/RawBytesObjectReader.java: ########## @@ -0,0 +1,309 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.binary; + +import org.apache.ignite.binary.BinaryObjectException; +import org.apache.ignite.internal.binary.streams.BinaryInputStream; +import org.apache.ignite.internal.binary.streams.BinaryOutputStream; + +/** */ +public class RawBytesObjectReader implements BinaryPositionReadable { + /** */ + private final BinaryInputStream in; + + /** */ + public RawBytesObjectReader(BinaryInputStream in) { + this.in = in; + } + + /** */ + public byte[] readObject() { Review Comment: Used only by test. Perhaps, can be replaced in test with `copyObject()` or, at least, can be package-private. ########## modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java: ########## @@ -282,16 +284,33 @@ private byte[] valueBytesFromArray(CacheObjectValueContext ctx) { * @return Detached binary object. */ public BinaryObjectImpl detach() { + return detach(true); Review Comment: Why `resolveCrossObjectReferences` is true by default? Looks like it can be false. ########## modules/core/src/main/java/org/apache/ignite/internal/binary/ObjectDetachHelper.java: ########## @@ -0,0 +1,288 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.binary; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; +import java.util.TreeSet; +import org.apache.ignite.internal.binary.streams.BinaryHeapInputStream; +import org.apache.ignite.internal.binary.streams.BinaryInputStream; +import org.apache.ignite.internal.binary.streams.BinaryOutputStream; +import org.jetbrains.annotations.NotNull; + +import static org.apache.ignite.internal.binary.BinaryArrayIdentityResolver.instance; +import static org.apache.ignite.internal.binary.BinaryUtils.dataStartRelative; +import static org.apache.ignite.internal.binary.BinaryUtils.footerStartAbsolute; +import static org.apache.ignite.internal.binary.BinaryUtils.length; +import static org.apache.ignite.internal.binary.BinaryUtils.rawOffsetAbsolute; +import static org.apache.ignite.internal.binary.GridBinaryMarshaller.HASH_CODE_POS; + +/** */ +public class ObjectDetachHelper { + /** */ + private final RawBytesObjectReader reader; + + /** */ + private final int rootObjStartPos; + + /** */ + private final Deque<ObjectDescriptor> objStack = new ArrayDeque<>(); + + /** */ + private final Map<Integer, Collection<Integer>> crossObjReferences = new HashMap<>(); + + /** */ + private final TreeSet<ObjectDescriptor> rehashRequireObjects = new TreeSet<>(); + + /** */ + private ObjectDetachHelper(BinaryInputStream in) { + reader = new RawBytesObjectReader(in); + + rootObjStartPos = in.position(); + } + + /** */ + static ObjectDetachHelper create(byte[] data, int offset) { + ObjectDetachHelper res = new ObjectDetachHelper(BinaryHeapInputStream.create(data, offset)); + + res.readNextObject(); + + return res; + } + + /** */ + public boolean isCrossObjectReferencesDetected() { + return !crossObjReferences.isEmpty(); + } + + /** */ + public int detach(BinaryOutputStream writer) { + reader.position(rootObjStartPos); + + int writerRootObjStartPos = writer.position(); + + reader.copyObject(writer); + + crossObjReferences.forEach((readerObjStartPos, handleOffsets) -> { + int writerObjStartPos = copyObject(readerObjStartPos, writer); + + for (int handleOffset : handleOffsets) { + int writerHandleStartPos = writerRootObjStartPos + handleOffset; + + writer.unsafeWriteInt(writerHandleStartPos + /* skip handle type */ 1, writerHandleStartPos - writerObjStartPos); + } + }); + + for (ObjectDescriptor objDesc : rehashRequireObjects.descendingSet()) + overrideHash(writer, writerRootObjStartPos, objDesc); + + return writerRootObjStartPos; + } + + /** */ + private void readNextObject() { + int objStartPos = reader.position(); + + byte objType = reader.readBytePositioned(objStartPos); + + switch (objType) { + case GridBinaryMarshaller.OBJ: { + int objDataStartPos = objStartPos + dataStartRelative(reader, objStartPos); + int objDataEndPos = rawOffsetAbsolute(reader, objStartPos); + int objFooterStartPos = footerStartAbsolute(reader, objStartPos); + int objEndPos = objStartPos + length(reader, objStartPos); + + reader.position(objDataStartPos); + + objStack.push(new ObjectDescriptor( + rootStartOffset(objStartPos), + rootStartOffset(objDataStartPos), + rootStartOffset(objFooterStartPos)) + ); + + while (reader.position() < objDataEndPos) + readNextObject(); + + objStack.pop(); + + reader.position(objEndPos); + + break; + } + + case GridBinaryMarshaller.HANDLE: { + reader.skipBytes(1); // Object type. + + int offset = reader.readInt(); + + int handleObjPos = objStartPos - offset; + + if (handleObjPos < rootObjStartPos) + saveCrossObjectReferenceData(handleObjPos, objStartPos); + + break; + } + + case GridBinaryMarshaller.OBJ_ARR: { + reader.skipBytes(1); // Object type. + + reader.skipTypeId(); + + int size = reader.readInt(); + + readCortege(size); + + break; + } + + case GridBinaryMarshaller.COL: { + reader.skipBytes(1); // Object type. + + int size = reader.readInt(); + + reader.skipBytes(1); // Collection type. + + readCortege(size); + + break; + } + + case GridBinaryMarshaller.MAP: { + reader.skipBytes(1); // Object type. + + int size = reader.readInt() * 2; + + reader.skipBytes(1); // Map type. + + readCortege(size); + + break; + } + + default: { + reader.skipObject(); + } + } + } + + /** */ + private void readCortege(int cortegeSize) { + for (int elemIdx = 0; elemIdx < cortegeSize; elemIdx++) + readNextObject(); + } + + /** */ + private void saveCrossObjectReferenceData(int objPos, int handlePos) { + crossObjReferences.computeIfAbsent(objPos, k -> new ArrayList<>()).add(rootStartOffset(handlePos)); + + rehashRequireObjects.addAll(objStack); + } + + /** */ + private int rootStartOffset(int pos) { + assert pos - rootObjStartPos >= 0; + + return pos - rootObjStartPos; + } + + /** */ + private void overrideHash(BinaryOutputStream writer, int writerRootObjStartPos, ObjectDescriptor objDesc) { + int hashCode = instance().hashCode( + writer.array(), + writerRootObjStartPos + objDesc.objectDataStartOffset(), + writerRootObjStartPos + objDesc.objectFooterStartOffset() + ); + + writer.unsafeWriteInt(writerRootObjStartPos + objDesc.objectStartOffset() + HASH_CODE_POS, hashCode); + } + + /** */ + private int copyObject(int readerObjStartPos, BinaryOutputStream writer) { + int readerRetPos = reader.position(); + int writerObjStartPos = writer.position(); + + reader.position(readerObjStartPos); + + ObjectDetachHelper detachHelper = create(reader.array(), readerObjStartPos); + + if (detachHelper.isCrossObjectReferencesDetected()) + detachHelper.detach(writer); + else + reader.copyObject(writer); + + reader.position(readerRetPos); + + return writerObjStartPos; + } + + /** */ + private static class ObjectDescriptor implements Comparable<ObjectDescriptor> { + /** */ + private final int objStartOffset; + + /** */ + private final int objDataStartOffset; + + /** */ + private final int objFooterStartOffset; + + /** */ + public ObjectDescriptor(int objStartOffset, int objDataStartOffset, int objFooterStartOffset) { + this.objStartOffset = objStartOffset; + this.objDataStartOffset = objDataStartOffset; + this.objFooterStartOffset = objFooterStartOffset; + } + + /** */ + public int objectFooterStartOffset() { + return objFooterStartOffset; + } + + /** */ + public int objectDataStartOffset() { + return objDataStartOffset; + } + + /** */ + public int objectStartOffset() { + return objStartOffset; + } + + /** {@inheritDoc} */ + @Override public int compareTo(@NotNull ObjectDetachHelper.ObjectDescriptor other) { + return Integer.compare(objStartOffset, other.objDataStartOffset); Review Comment: Why different fields are compared? ########## modules/core/src/main/java/org/apache/ignite/internal/binary/ObjectDetachHelper.java: ########## @@ -0,0 +1,288 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.binary; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; +import java.util.TreeSet; +import org.apache.ignite.internal.binary.streams.BinaryHeapInputStream; +import org.apache.ignite.internal.binary.streams.BinaryInputStream; +import org.apache.ignite.internal.binary.streams.BinaryOutputStream; +import org.jetbrains.annotations.NotNull; + +import static org.apache.ignite.internal.binary.BinaryArrayIdentityResolver.instance; +import static org.apache.ignite.internal.binary.BinaryUtils.dataStartRelative; +import static org.apache.ignite.internal.binary.BinaryUtils.footerStartAbsolute; +import static org.apache.ignite.internal.binary.BinaryUtils.length; +import static org.apache.ignite.internal.binary.BinaryUtils.rawOffsetAbsolute; +import static org.apache.ignite.internal.binary.GridBinaryMarshaller.HASH_CODE_POS; + +/** */ +public class ObjectDetachHelper { + /** */ + private final RawBytesObjectReader reader; + + /** */ + private final int rootObjStartPos; + + /** */ + private final Deque<ObjectDescriptor> objStack = new ArrayDeque<>(); + + /** */ + private final Map<Integer, Collection<Integer>> crossObjReferences = new HashMap<>(); + + /** */ + private final TreeSet<ObjectDescriptor> rehashRequireObjects = new TreeSet<>(); + + /** */ + private ObjectDetachHelper(BinaryInputStream in) { + reader = new RawBytesObjectReader(in); + + rootObjStartPos = in.position(); + } + + /** */ + static ObjectDetachHelper create(byte[] data, int offset) { + ObjectDetachHelper res = new ObjectDetachHelper(BinaryHeapInputStream.create(data, offset)); + + res.readNextObject(); + + return res; + } + + /** */ + public boolean isCrossObjectReferencesDetected() { + return !crossObjReferences.isEmpty(); + } + + /** */ + public int detach(BinaryOutputStream writer) { + reader.position(rootObjStartPos); + + int writerRootObjStartPos = writer.position(); + + reader.copyObject(writer); + + crossObjReferences.forEach((readerObjStartPos, handleOffsets) -> { + int writerObjStartPos = copyObject(readerObjStartPos, writer); + + for (int handleOffset : handleOffsets) { + int writerHandleStartPos = writerRootObjStartPos + handleOffset; + + writer.unsafeWriteInt(writerHandleStartPos + /* skip handle type */ 1, writerHandleStartPos - writerObjStartPos); + } + }); + + for (ObjectDescriptor objDesc : rehashRequireObjects.descendingSet()) + overrideHash(writer, writerRootObjStartPos, objDesc); + + return writerRootObjStartPos; + } + + /** */ + private void readNextObject() { + int objStartPos = reader.position(); + + byte objType = reader.readBytePositioned(objStartPos); + + switch (objType) { + case GridBinaryMarshaller.OBJ: { + int objDataStartPos = objStartPos + dataStartRelative(reader, objStartPos); + int objDataEndPos = rawOffsetAbsolute(reader, objStartPos); + int objFooterStartPos = footerStartAbsolute(reader, objStartPos); + int objEndPos = objStartPos + length(reader, objStartPos); + + reader.position(objDataStartPos); + + objStack.push(new ObjectDescriptor( + rootStartOffset(objStartPos), + rootStartOffset(objDataStartPos), + rootStartOffset(objFooterStartPos)) + ); + + while (reader.position() < objDataEndPos) + readNextObject(); + + objStack.pop(); + + reader.position(objEndPos); + + break; + } + + case GridBinaryMarshaller.HANDLE: { + reader.skipBytes(1); // Object type. + + int offset = reader.readInt(); + + int handleObjPos = objStartPos - offset; + + if (handleObjPos < rootObjStartPos) + saveCrossObjectReferenceData(handleObjPos, objStartPos); + + break; + } + + case GridBinaryMarshaller.OBJ_ARR: { + reader.skipBytes(1); // Object type. + + reader.skipTypeId(); + + int size = reader.readInt(); + + readCortege(size); + + break; + } + + case GridBinaryMarshaller.COL: { + reader.skipBytes(1); // Object type. + + int size = reader.readInt(); + + reader.skipBytes(1); // Collection type. + + readCortege(size); + + break; + } + + case GridBinaryMarshaller.MAP: { + reader.skipBytes(1); // Object type. + + int size = reader.readInt() * 2; + + reader.skipBytes(1); // Map type. + + readCortege(size); + + break; + } + + default: { + reader.skipObject(); + } + } + } + + /** */ + private void readCortege(int cortegeSize) { + for (int elemIdx = 0; elemIdx < cortegeSize; elemIdx++) + readNextObject(); + } + + /** */ + private void saveCrossObjectReferenceData(int objPos, int handlePos) { + crossObjReferences.computeIfAbsent(objPos, k -> new ArrayList<>()).add(rootStartOffset(handlePos)); + + rehashRequireObjects.addAll(objStack); + } + + /** */ + private int rootStartOffset(int pos) { + assert pos - rootObjStartPos >= 0; + + return pos - rootObjStartPos; + } + + /** */ + private void overrideHash(BinaryOutputStream writer, int writerRootObjStartPos, ObjectDescriptor objDesc) { + int hashCode = instance().hashCode( Review Comment: Let's use method name with class name for `instance()` (without static import), or `instance()` can be readed as local class method. ########## modules/core/src/test/java/org/apache/ignite/internal/binary/CrossObjetReferenceSerializationTest.java: ########## @@ -0,0 +1,594 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.binary; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import org.apache.ignite.Ignite; +import org.apache.ignite.IgniteCache; +import org.apache.ignite.Ignition; +import org.apache.ignite.binary.BinaryObjectException; +import org.apache.ignite.binary.BinaryRawReader; +import org.apache.ignite.binary.BinaryRawWriter; +import org.apache.ignite.binary.BinaryReader; +import org.apache.ignite.binary.BinaryWriter; +import org.apache.ignite.binary.Binarylizable; +import org.apache.ignite.client.ClientCache; +import org.apache.ignite.client.IgniteClient; +import org.apache.ignite.configuration.BinaryConfiguration; +import org.apache.ignite.configuration.CacheConfiguration; +import org.apache.ignite.configuration.ClientConfiguration; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.internal.binary.mutabletest.GridBinaryTestClasses.TestObjectAllTypes; +import org.apache.ignite.testframework.junits.WithSystemProperty; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import static org.apache.ignite.IgniteSystemProperties.IGNITE_BINARY_SORT_OBJECT_FIELDS; + +/** */ +@RunWith(Parameterized.class) +@WithSystemProperty(key = IGNITE_BINARY_SORT_OBJECT_FIELDS, value = "true") Review Comment: `BinaryUtils.FIELDS_SORTED_ORDER` is a static field and initiated when `BinaryUtils` class is initiated. If current JVM run some other tests before (on TC, for example) field is not reinitiated with this system property. ########## modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientUtils.java: ########## @@ -573,61 +573,59 @@ <T> T readObject(BinaryInputStream in, boolean keepBinary, Class<T> clazz) { if (keepBinary) return (T)marsh.unmarshal(in); else { - BinaryReaderHandles hnds = new BinaryReaderHandles(); - - return (T)unwrapBinary(marsh.deserialize(in, hnds), hnds, clazz); + return (T)unwrapBinary(marsh.deserialize(in, new BinaryReaderHandles()), clazz); Review Comment: One line statement with braces -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
