Index: modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryReaderExImpl.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryReaderExImpl.java (revision b52296077c731ef08186fd80fd5a949d3c3fff72) +++ modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryReaderExImpl.java (date 1608311360735) @@ -1336,6 +1336,11 @@ return BinaryUtils.unmarshal(in, ctx, ldr, this, true); } + /** {@inheritDoc} */ + @Nullable @Override public Object readObjectDetached(boolean deserialize) throws BinaryObjectException { + return BinaryUtils.unmarshal(in, ctx, ldr, this, true, deserialize); + } + /** {@inheritDoc} */ @Nullable @Override public Object[] readObjectArray(String fieldName) throws BinaryObjectException { try { @@ -1359,7 +1364,7 @@ @Nullable @Override public Object[] readObjectArray() throws BinaryObjectException { switch (checkFlag(OBJ_ARR)) { case NORMAL: - return BinaryUtils.doReadObjectArray(in, ctx, ldr, this, false, true); + return (Object[])BinaryUtils.doReadObjectArray(in, ctx, ldr, this, false, true); case HANDLE: return readHandleField(); Index: modules/core/src/main/java/org/apache/ignite/internal/processors/platform/services/PlatformServices.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- modules/core/src/main/java/org/apache/ignite/internal/processors/platform/services/PlatformServices.java (revision b52296077c731ef08186fd80fd5a949d3c3fff72) +++ modules/core/src/main/java/org/apache/ignite/internal/processors/platform/services/PlatformServices.java (date 1608727864414) @@ -17,7 +17,6 @@ package org.apache.ignite.internal.processors.platform.services; -import java.lang.reflect.Array; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; @@ -30,6 +29,7 @@ import org.apache.ignite.IgniteServices; import org.apache.ignite.internal.binary.BinaryRawReaderEx; import org.apache.ignite.internal.binary.BinaryRawWriterEx; +import org.apache.ignite.internal.binary.GridBinaryMarshaller; import org.apache.ignite.internal.processors.platform.PlatformAbstractTarget; import org.apache.ignite.internal.processors.platform.PlatformContext; import org.apache.ignite.internal.processors.platform.PlatformTarget; @@ -274,18 +274,23 @@ String mthdName = reader.readString(); Object[] args; + ServiceProxyHolder svcProxy = (ServiceProxyHolder)arg; + + GridBinaryMarshaller.FULL_KEEP_BINARY.set(svcProxy.isPlatformService()); + + boolean keepBinary = srvKeepBinary || svcProxy.isPlatformService(); if (reader.readBoolean()) { args = new Object[reader.readInt()]; for (int i = 0; i < args.length; i++) - args[i] = reader.readObjectDetached(); + args[i] = reader.readObjectDetached(!keepBinary); } else args = null; try { - Object result = ((ServiceProxyHolder)arg).invoke(mthdName, srvKeepBinary, args); + Object result = svcProxy.invoke(mthdName, srvKeepBinary, args); PlatformUtils.writeInvocationResult(writer, result, null); } @@ -571,6 +576,14 @@ serviceClass = clazz; } + /** + * @return {@code true} if the target service is a {@link PlatformService} and {@code false} if the target + * service is a native Java service. + */ + public boolean isPlatformService() { + return PlatformService.class.isAssignableFrom(serviceClass); + } + /** * Invokes the proxy. * @@ -588,32 +601,8 @@ else { assert proxy instanceof GridServiceProxy; - // Deserialize arguments for Java service when not in binary mode - if (!srvKeepBinary) - args = PlatformUtils.unwrapBinariesInArray(args); - Method mtd = getMethod(serviceClass, mthdName, args); - // Convert Object[] to T[] when required: - // Ignite loses array item types when passing arguments through GridServiceProxy. - for (int i = 0; i < args.length; i++) { - Object arg = args[i]; - - if (arg instanceof Object[]) { - Class parameterType = mtd.getParameterTypes()[i]; - - if (parameterType.isArray() && parameterType != Object[].class) { - Object[] arr = (Object[])arg; - Object newArg = Array.newInstance(parameterType.getComponentType(), arr.length); - - for (int j = 0; j < arr.length; j++) - Array.set(newArg, j, arr[j]); - - args[i] = newArg; - } - } - } - try { return ((GridServiceProxy)proxy).invokeMethod(mtd, args); } Index: modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryRawReaderEx.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryRawReaderEx.java (revision b52296077c731ef08186fd80fd5a949d3c3fff72) +++ modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryRawReaderEx.java (date 1608311359437) @@ -30,4 +30,11 @@ * @throws org.apache.ignite.binary.BinaryObjectException In case of error. */ @Nullable public Object readObjectDetached() throws BinaryObjectException; + + /** + * @param deserialize {@code true} if object should be unmarshelled and then deserialized. + * @return Object. + * @throws org.apache.ignite.binary.BinaryObjectException In case of error. + */ + @Nullable public Object readObjectDetached(boolean deserialize) throws BinaryObjectException; } Index: modules/core/src/main/java/org/apache/ignite/internal/processors/task/GridTaskProcessor.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- modules/core/src/main/java/org/apache/ignite/internal/processors/task/GridTaskProcessor.java (revision b52296077c731ef08186fd80fd5a949d3c3fff72) +++ modules/core/src/main/java/org/apache/ignite/internal/processors/task/GridTaskProcessor.java (date 1608311365286) @@ -489,6 +489,21 @@ */ public ComputeTaskInternalFuture execute(ComputeTask task, @Nullable T arg, boolean sys, @Nullable String execName) { + return execute(task, arg, sys, execName, false); + } + + /** + * @param task Actual task. + * @param arg Optional task argument. + * @param sys If {@code true}, then system pool will be used. + * @param execName Name of the custom executor. + * @param keepBinary Keep binary return value. + * @return Task future. + * @param Task argument type. + * @param Task return value type. + */ + public ComputeTaskInternalFuture execute(ComputeTask task, @Nullable T arg, boolean sys, + @Nullable String execName, boolean keepBinary) { lock.readLock(); try { @@ -496,7 +511,7 @@ throw new IllegalStateException("Failed to execute task due to grid shutdown: " + task); return startTask(null, null, task, IgniteUuid.fromUuid(ctx.localNodeId()), arg, - sys, execName); + sys, execName, keepBinary); } finally { lock.readUnlock(); @@ -570,6 +585,22 @@ * @param execName Name of the custom executor. * @return Task future. */ + private ComputeTaskInternalFuture startTask(@Nullable String taskName, @Nullable Class taskCls, + @Nullable ComputeTask task, IgniteUuid sesId, @Nullable T arg, boolean sys, @Nullable String execName) { + return startTask(taskName, taskCls, task, sesId, arg, sys, execName, false); + } + + /** + * @param taskName Task name. + * @param taskCls Task class. + * @param task Task. + * @param sesId Task session ID. + * @param arg Optional task argument. + * @param sys If {@code true}, then system pool will be used. + * @param execName Name of the custom executor. + * @param keepBinary Keep binary return value. + * @return Task future. + */ private ComputeTaskInternalFuture startTask( @Nullable String taskName, @Nullable Class taskCls, @@ -577,7 +608,8 @@ IgniteUuid sesId, @Nullable T arg, boolean sys, - @Nullable String execName) { + @Nullable String execName, + boolean keepBinary) { assert sesId != null; String taskClsName; @@ -784,7 +816,8 @@ dep, new TaskEventListener(), map, - subjId); + subjId, + keepBinary); GridTaskWorker taskWorker0 = tasks.putIfAbsent(sesId, taskWorker); Index: modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectArray.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectArray.java (date 1608311359367) +++ modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectArray.java (date 1608311359367) @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.binary; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Objects; + +final class BinaryObjectArray implements Serializable { + private static final long serialVersionUID = 0L; + + private final int itemTypeId; + private final Object[] items; + + BinaryObjectArray(int itemTypeId, Object[] items) { + this.itemTypeId = itemTypeId; + this.items = items; + } + + public int itemTypeId() { + return itemTypeId; + } + + public Object[] items() { + return items; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof BinaryObjectArray)) + return false; + BinaryObjectArray array = (BinaryObjectArray)o; + return itemTypeId == array.itemTypeId && Arrays.equals(items, array.items); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int result = Objects.hash(itemTypeId); + result = 31 * result + Arrays.hashCode(items); + return result; + } + + /** {@inheritDoc} */ + @Override public String toString() { + return Arrays.toString(items); + } +} Index: modules/core/src/main/java/org/apache/ignite/marshaller/Marshaller.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- modules/core/src/main/java/org/apache/ignite/marshaller/Marshaller.java (revision b52296077c731ef08186fd80fd5a949d3c3fff72) +++ modules/core/src/main/java/org/apache/ignite/marshaller/Marshaller.java (date 1608311366439) @@ -115,4 +115,16 @@ * @throws IgniteCheckedException If unmarshalling failed. */ public T unmarshal(byte[] arr, @Nullable ClassLoader clsLdr) throws IgniteCheckedException; + + /** + * Unmarshals object from byte array using given class loader. + * + * @param Type of unmarshalled object. + * @param arr Byte array. + * @param clsLdr If not {@code null} then given class loader will be used for unmarshal object. + * @param deserialize {@code true} if object should be unmarshelled and then deserialized. + * @return Unmarshalled object. + * @throws IgniteCheckedException If unmarshalling failed. + */ + public T unmarshal(byte[] arr, ClassLoader clsLdr, boolean deserialize) throws IgniteCheckedException; } Index: modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProxy.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProxy.java (revision b52296077c731ef08186fd80fd5a949d3c3fff72) +++ modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProxy.java (date 1608311363956) @@ -42,6 +42,7 @@ import org.apache.ignite.internal.GridClosureCallMode; import org.apache.ignite.internal.GridKernalContext; import org.apache.ignite.internal.IgniteEx; +import org.apache.ignite.internal.binary.GridBinaryMarshaller; import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException; import org.apache.ignite.internal.managers.communication.GridIoPolicy; import org.apache.ignite.internal.processors.platform.PlatformNativeException; @@ -204,14 +205,17 @@ else { ctx.task().setThreadContext(TC_IO_POLICY, GridIoPolicy.SERVICE_POOL); + boolean keepBinary = GridBinaryMarshaller.FULL_KEEP_BINARY.get(); + // Execute service remotely. return ctx.closure().callAsyncNoFailover( GridClosureCallMode.BROADCAST, - new ServiceProxyCallable(methodName(mtd), name, mtd.getParameterTypes(), args), + new ServiceProxyCallable(mtd.getName(), name, mtd.getParameterTypes(), args, keepBinary), Collections.singleton(node), false, waitTimeout, - true).get(); + true, + keepBinary).get(); } } catch (RuntimeException | Error e) { @@ -416,6 +420,9 @@ /** Serial version UID. */ private static final long serialVersionUID = 0L; + /** Keep binary return value. */ + private boolean keepBinary; + /** Method name. */ private String mtdName; @@ -444,12 +451,15 @@ * @param svcName Service name. * @param argTypes Argument types. * @param args Arguments for invocation. + * @param keepBinary Keep binary return value. */ - private ServiceProxyCallable(String mtdName, String svcName, Class[] argTypes, Object[] args) { + private ServiceProxyCallable(String mtdName, String svcName, Class[] argTypes, Object[] args, + boolean keepBinary) { this.mtdName = mtdName; this.svcName = svcName; this.argTypes = argTypes; this.args = args; + this.keepBinary = keepBinary; } /** {@inheritDoc} */ @@ -463,6 +473,8 @@ Method mtd = ctx.method(key); + GridBinaryMarshaller.FULL_KEEP_BINARY.set(keepBinary); + if (ctx.service() instanceof PlatformService && mtd == null) return callPlatformService((PlatformService)ctx.service()); else @@ -501,6 +513,7 @@ U.writeString(out, mtdName); U.writeArray(out, argTypes); U.writeArray(out, args); + out.writeBoolean(keepBinary); } /** {@inheritDoc} */ @@ -509,6 +522,7 @@ mtdName = U.readString(in); argTypes = U.readClassArray(in); args = U.readArray(in); + keepBinary = in.readBoolean(); } /** {@inheritDoc} */ Index: modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/DelegateConverter.cs IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/DelegateConverter.cs (revision b52296077c731ef08186fd80fd5a949d3c3fff72) +++ modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/DelegateConverter.cs (date 1608728359777) @@ -38,10 +38,6 @@ /** */ private static readonly MethodInfo ReadObjectMethod = typeof (IBinaryRawReader).GetMethod("ReadObject"); - /** */ - private static readonly MethodInfo ConvertArrayMethod = typeof(DelegateConverter).GetMethod("ConvertArray", - BindingFlags.Static | BindingFlags.NonPublic); - /// /// Compiles a function without arguments. /// @@ -182,7 +178,7 @@ for (var i = 0; i < methodParams.Length; i++) { var arrElem = Expression.ArrayIndex(arrParam, Expression.Constant(i)); - argParams[i] = Convert(arrElem, methodParams[i].ParameterType); + argParams[i] = Expression.Convert(arrElem, methodParams[i].ParameterType); } Expression callExpr = Expression.Call(targetParamConverted, method, argParams); @@ -526,40 +522,5 @@ return null; } - - /// - /// Converts expression to a given type. - /// - private static Expression Convert(Expression value, Type targetType) - { - if (targetType.IsArray && targetType.GetElementType() != typeof(object)) - { - var convertMethod = ConvertArrayMethod.MakeGenericMethod(targetType.GetElementType()); - - var objArray = Expression.Convert(value, typeof(object[])); - - return Expression.Call(null, convertMethod, objArray); - } - - return Expression.Convert(value, targetType); - } - - /// - /// Converts object array to typed array. - /// - // ReSharper disable once UnusedMember.Local (used by reflection). - private static T[] ConvertArray(object[] arr) - { - if (arr == null) - { - return null; - } - - var res = new T[arr.Length]; - - Array.Copy(arr, res, arr.Length); - - return res; - } } } Index: modules/core/src/main/java/org/apache/ignite/marshaller/AbstractNodeNameAwareMarshaller.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- modules/core/src/main/java/org/apache/ignite/marshaller/AbstractNodeNameAwareMarshaller.java (revision b52296077c731ef08186fd80fd5a949d3c3fff72) +++ modules/core/src/main/java/org/apache/ignite/marshaller/AbstractNodeNameAwareMarshaller.java (date 1608311366413) @@ -74,10 +74,15 @@ /** {@inheritDoc} */ @Override public T unmarshal(byte[] arr, @Nullable ClassLoader clsLdr) throws IgniteCheckedException { + return unmarshal(arr, clsLdr, true); + } + + /** {@inheritDoc} */ + @Override public T unmarshal(byte[] arr, @Nullable ClassLoader clsLdr, boolean deserialize) throws IgniteCheckedException { String oldNodeName = IgniteUtils.setCurrentIgniteName(nodeName); try { - return unmarshal0(arr, clsLdr); + return unmarshal0(arr, clsLdr, deserialize); } finally { IgniteUtils.restoreOldIgniteName(oldNodeName, nodeName); @@ -137,4 +142,18 @@ * @throws IgniteCheckedException If unmarshalling failed. */ protected abstract T unmarshal0(byte[] arr, @Nullable ClassLoader clsLdr) throws IgniteCheckedException; + + /** + * Unmarshals object from byte array using given class loader. + * + * @param Type of unmarshalled object. + * @param arr Byte array. + * @param clsLdr If not {@code null} then given class loader will be used for unmarshal object. + * @param deserialize Deserialize. + * @return Unmarshalled object. + * @throws IgniteCheckedException If unmarshalling failed. + */ + protected T unmarshal0(byte[] arr, @Nullable ClassLoader clsLdr, boolean deserialize) throws IgniteCheckedException { + return unmarshal0(arr, clsLdr); + } } Index: modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java (revision b52296077c731ef08186fd80fd5a949d3c3fff72) +++ modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java (date 1608311361411) @@ -1555,6 +1555,21 @@ return doReadClass(in, ctx, ldr, true); } + /** + * @param in Binary input stream. + * @return Type ID specified at the input stream + * @throws BinaryObjectException If failed. + */ + public static int doReadTypeId(BinaryInputStream in) + throws BinaryObjectException { + int typeId = in.readInt(); + + if (typeId == GridBinaryMarshaller.UNREGISTERED_TYPE_ID) + doReadClassName(in); + + return typeId; + } + /** * @param in Binary input stream. * @param ctx Binary context. @@ -1819,12 +1834,25 @@ return unmarshal(in, ctx, ldr, handles, false); } + /** + * @return Unmarshalled value. + * @throws BinaryObjectException In case of error. + */ + @Nullable public static Object unmarshal( + BinaryInputStream in, + BinaryContext ctx, + ClassLoader ldr, + BinaryReaderHandlesHolder handles, + boolean detach) throws BinaryObjectException { + return unmarshal(in, ctx, ldr, handles, detach, false); + } + /** * @return Unmarshalled value. * @throws BinaryObjectException In case of error. */ @Nullable public static Object unmarshal(BinaryInputStream in, BinaryContext ctx, ClassLoader ldr, - BinaryReaderHandlesHolder handles, boolean detach) throws BinaryObjectException { + BinaryReaderHandlesHolder handles, boolean detach, boolean deserialize) throws BinaryObjectException { int start = in.position(); byte flag = in.readByte(); @@ -1876,7 +1904,7 @@ handles.setHandle(po, start); - return po; + return deserialize ? po.deserialize() : po; } case GridBinaryMarshaller.BYTE: @@ -1964,13 +1992,13 @@ return doReadTimeArray(in); case GridBinaryMarshaller.OBJ_ARR: - return doReadObjectArray(in, ctx, ldr, handles, detach, false); + return doReadObjectArray(in, ctx, ldr, handles, detach, deserialize); case GridBinaryMarshaller.COL: - return doReadCollection(in, ctx, ldr, handles, detach, false, null); + return doReadCollection(in, ctx, ldr, handles, detach, deserialize, null); case GridBinaryMarshaller.MAP: - return doReadMap(in, ctx, ldr, handles, detach, false, null); + return doReadMap(in, ctx, ldr, handles, detach, deserialize, null); case GridBinaryMarshaller.BINARY_OBJ: return doReadBinaryObject(in, ctx, detach); @@ -2008,11 +2036,17 @@ * @return Value. * @throws BinaryObjectException In case of error. */ - public static Object[] doReadObjectArray(BinaryInputStream in, BinaryContext ctx, ClassLoader ldr, + public static Object doReadObjectArray(BinaryInputStream in, BinaryContext ctx, ClassLoader ldr, BinaryReaderHandlesHolder handles, boolean detach, boolean deserialize) throws BinaryObjectException { int hPos = positionForHandle(in); - Class compType = doReadClass(in, ctx, ldr, deserialize); + Class compType = null; + int compTypeId = 0; + + if (deserialize) + compType = doReadClass(in, ctx, ldr); + else + compTypeId = doReadTypeId(in); int len = in.readInt(); @@ -2023,7 +2057,11 @@ for (int i = 0; i < len; i++) arr[i] = deserializeOrUnmarshal(in, ctx, ldr, handles, detach, deserialize); - return arr; + boolean keepCompTypeId = GridBinaryMarshaller.FULL_KEEP_BINARY.get() + && compTypeId != GridBinaryMarshaller.OBJECT + && compTypeId != GridBinaryMarshaller.UNREGISTERED_TYPE_ID; + + return keepCompTypeId ? new BinaryObjectArray(compTypeId, arr) : arr; } /** Index: modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java (revision b52296077c731ef08186fd80fd5a949d3c3fff72) +++ modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java (date 1608311358607) @@ -185,6 +185,8 @@ else { if (cls == BinaryEnumObjectImpl.class) mode = BinaryWriteMode.BINARY_ENUM; + else if (cls == BinaryObjectArray.class) + mode = BinaryWriteMode.OBJECT_ARR; else mode = serializer != null ? BinaryWriteMode.BINARY : BinaryUtils.mode(cls); } @@ -714,7 +716,7 @@ break; case OBJECT_ARR: - writer.doWriteObjectArray((Object[])obj); + writer.doWriteObjectArray(obj); break; Index: modules/core/src/main/java/org/apache/ignite/internal/processors/closure/GridClosureProcessor.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- modules/core/src/main/java/org/apache/ignite/internal/processors/closure/GridClosureProcessor.java (revision b52296077c731ef08186fd80fd5a949d3c3fff72) +++ modules/core/src/main/java/org/apache/ignite/internal/processors/closure/GridClosureProcessor.java (date 1608311362476) @@ -576,6 +576,28 @@ boolean sys, long timeout, boolean skipAuth) { + return callAsyncNoFailover(mode, job, nodes, sys, timeout, skipAuth, false); + } + + /** + * @param Type. + * @param mode Distribution mode. + * @param job Closure to execute. + * @param nodes Grid nodes. + * @param sys If {@code true}, then system pool will be used. + * @param timeout Timeout. + * @param skipAuth Skip authorization check. + * @param keepBinary Keep binary return value. + * @return Grid future for collection of closure results. + */ + public IgniteInternalFuture callAsyncNoFailover( + GridClosureCallMode mode, + @Nullable Callable job, + @Nullable Collection nodes, + boolean sys, + long timeout, + boolean skipAuth, + boolean keepBinary) { assert mode != null; assert timeout >= 0 : timeout; @@ -597,7 +619,7 @@ if (timeout > 0) ctx.task().setThreadContext(TC_TIMEOUT, timeout); - return ctx.task().execute(new T7<>(mode, job), null, sys); + return ctx.task().execute(new T7<>(mode, job), null, sys, null, keepBinary); } finally { busyLock.readUnlock(); Index: modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryWriterExImpl.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryWriterExImpl.java (revision b52296077c731ef08186fd80fd5a949d3c3fff72) +++ modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryWriterExImpl.java (date 1608311362059) @@ -745,32 +745,38 @@ * @param val Array of objects. * @throws org.apache.ignite.binary.BinaryObjectException In case of error. */ - void doWriteObjectArray(@Nullable Object[] val) throws BinaryObjectException { + void doWriteObjectArray(@Nullable Object val) throws BinaryObjectException { if (val == null) out.writeByte(GridBinaryMarshaller.NULL); else { - if (tryWriteAsHandle(val)) + boolean isBinary = val instanceof BinaryObjectArray; + + Object[] arr = isBinary ? ((BinaryObjectArray)val).items() : (Object[])val; + + if (tryWriteAsHandle(arr)) return; BinaryClassDescriptor desc = ctx.registerClass( - val.getClass().getComponentType(), + arr.getClass().getComponentType(), true, failIfUnregistered); out.unsafeEnsure(1 + 4); out.unsafeWriteByte(GridBinaryMarshaller.OBJ_ARR); - if (desc.registered()) + if (isBinary) + out.unsafeWriteInt(((BinaryObjectArray)val).itemTypeId()); + else if (desc.registered()) out.unsafeWriteInt(desc.typeId()); else { out.unsafeWriteInt(GridBinaryMarshaller.UNREGISTERED_TYPE_ID); - doWriteString(val.getClass().getComponentType().getName()); + doWriteString(arr.getClass().getComponentType().getName()); } - out.writeInt(val.length); + out.writeInt(arr.length); - for (Object obj : val) + for (Object obj : arr) doWriteObject(obj); } } @@ -1296,7 +1302,7 @@ * @param val Value. * @throws org.apache.ignite.binary.BinaryObjectException In case of error. */ - void writeObjectArrayField(@Nullable Object[] val) throws BinaryObjectException { + void writeObjectArrayField(@Nullable Object val) throws BinaryObjectException { doWriteObjectArray(val); } Index: modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryMarshaller.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryMarshaller.java (revision b52296077c731ef08186fd80fd5a949d3c3fff72) +++ modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryMarshaller.java (date 1608311359341) @@ -98,7 +98,12 @@ /** {@inheritDoc} */ @Override protected T unmarshal0(byte[] bytes, @Nullable ClassLoader clsLdr) throws IgniteCheckedException { - return impl.deserialize(bytes, clsLdr); + return unmarshal0(bytes, clsLdr, true); + } + + /** {@inheritDoc} */ + @Override protected T unmarshal0(byte[] bytes, @Nullable ClassLoader clsLdr, boolean deserialize) throws IgniteCheckedException { + return deserialize ? impl.deserialize(bytes, clsLdr) : impl.unmarshal(bytes, clsLdr); } /** {@inheritDoc} */ Index: modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryFieldAccessor.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryFieldAccessor.java (revision b52296077c731ef08186fd80fd5a949d3c3fff72) +++ modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryFieldAccessor.java (date 1608311359315) @@ -647,7 +647,7 @@ break; case OBJECT_ARR: - writer.writeObjectArrayField((Object[])val); + writer.writeObjectArrayField(val); break; Index: modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java (revision b52296077c731ef08186fd80fd5a949d3c3fff72) +++ modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java (date 1608311366390) @@ -10380,16 +10380,17 @@ * @param marsh Marshaller. * @param arr Byte array. * @param clsLdr Class loader to use. + * @param deserialize {@code true} if object should be unmarshelled and then deserialized. * @return Unmarshalled object. * @throws IgniteCheckedException If unmarshalling failed. */ - public static T unmarshal(Marshaller marsh, byte[] arr, @Nullable ClassLoader clsLdr) + public static T unmarshal(Marshaller marsh, byte[] arr, @Nullable ClassLoader clsLdr, boolean deserialize) throws IgniteCheckedException { assert marsh != null; assert arr != null; try { - return marsh.unmarshal(arr, clsLdr); + return marsh.unmarshal(arr, clsLdr, deserialize); } catch (IgniteCheckedException e) { throw e; @@ -10399,6 +10400,24 @@ } } + /** + * Unmarshals object from the input stream using given class loader. + * This method should not close given input stream. + *

+ * This method wraps marshaller invocations and guaranty throws {@link IgniteCheckedException} in fail case. + * + * @param Type of unmarshalled object. + * @param marsh Marshaller. + * @param arr Byte array. + * @param clsLdr Class loader to use. + * @return Unmarshalled object. + * @throws IgniteCheckedException If unmarshalling failed. + */ + public static T unmarshal(Marshaller marsh, byte[] arr, @Nullable ClassLoader clsLdr) + throws IgniteCheckedException { + return unmarshal(marsh, arr, clsLdr, true); + } + /** * Unmarshals object from the input stream using given class loader. * This method should not close given input stream. Index: modules/core/src/main/java/org/apache/ignite/internal/binary/GridBinaryMarshaller.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- modules/core/src/main/java/org/apache/ignite/internal/binary/GridBinaryMarshaller.java (revision b52296077c731ef08186fd80fd5a949d3c3fff72) +++ modules/core/src/main/java/org/apache/ignite/internal/binary/GridBinaryMarshaller.java (date 1608311362244) @@ -32,6 +32,9 @@ * Binary objects marshaller. */ public class GridBinaryMarshaller { + /** Do not deserialize anything. */ + public static final ThreadLocal FULL_KEEP_BINARY = ThreadLocal.withInitial(() -> false); + /** Binary context in TLS store. */ private static final ThreadLocal BINARY_CTX = ThreadLocal.withInitial(BinaryContextHolder::new); Index: modules/core/src/main/java/org/apache/ignite/internal/processors/task/GridTaskWorker.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- modules/core/src/main/java/org/apache/ignite/internal/processors/task/GridTaskWorker.java (revision b52296077c731ef08186fd80fd5a949d3c3fff72) +++ modules/core/src/main/java/org/apache/ignite/internal/processors/task/GridTaskWorker.java (date 1608311366336) @@ -62,6 +62,7 @@ import org.apache.ignite.internal.GridTaskSessionImpl; import org.apache.ignite.internal.IgniteClientDisconnectedCheckedException; import org.apache.ignite.internal.IgniteInternalFuture; +import org.apache.ignite.internal.binary.GridBinaryMarshaller; import org.apache.ignite.internal.cluster.ClusterGroupEmptyCheckedException; import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException; import org.apache.ignite.internal.compute.ComputeTaskTimeoutCheckedException; @@ -117,6 +118,9 @@ /** Retry delay factor (ms). Retry delay = retryAttempt * RETRY_DELAY_MS */ private static final long RETRY_DELAY_MS = 10; + /** Keep binary return value. */ + private final boolean keepBinary; + /** {@code True} for internal tasks. */ private boolean internal; @@ -281,6 +285,7 @@ * @param evtLsnr Event listener. * @param thCtx Thread-local context from task processor. * @param subjId Subject ID. + * @param keepBinary Keep binary return value. */ GridTaskWorker( GridKernalContext ctx, @@ -292,7 +297,8 @@ GridDeployment dep, GridTaskEventListener evtLsnr, @Nullable Map thCtx, - UUID subjId) { + UUID subjId, + boolean keepBinary) { super(ctx.config().getIgniteInstanceName(), "grid-task-worker", ctx.log(GridTaskWorker.class)); assert ses != null; @@ -310,6 +316,7 @@ this.evtLsnr = evtLsnr; this.thCtx = thCtx; this.subjId = subjId; + this.keepBinary = keepBinary; log = U.logger(ctx, logRef, this); @@ -825,8 +832,10 @@ try { boolean loc = ctx.localNodeId().equals(res.getNodeId()) && !ctx.config().isMarshalLocalJobs(); + GridBinaryMarshaller.FULL_KEEP_BINARY.set(keepBinary); + Object res0 = loc ? res.getJobResult() : U.unmarshal(marsh, res.getJobResultBytes(), - U.resolveClassLoader(clsLdr, ctx.config())); + U.resolveClassLoader(clsLdr, ctx.config()), !keepBinary); IgniteException ex = loc ? res.getException() : U.unmarshal(marsh, res.getExceptionBytes(), Index: modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java (revision b52296077c731ef08186fd80fd5a949d3c3fff72) +++ modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java (date 1608311359281) @@ -240,6 +240,7 @@ registerPredefinedType(Timestamp[].class, GridBinaryMarshaller.TIMESTAMP_ARR); registerPredefinedType(Time[].class, GridBinaryMarshaller.TIME_ARR); registerPredefinedType(Object[].class, GridBinaryMarshaller.OBJ_ARR); + registerPredefinedType(BinaryObjectArray.class, GridBinaryMarshaller.OBJ_ARR); // Special collections. registerPredefinedType(ArrayList.class, 0);