IGNITE-8752 Deadlock when registering binary metadata while holding topology read lock - Fixes #4237.
Signed-off-by: Ivan Rakov <ira...@apache.org> Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/929a12d4 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/929a12d4 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/929a12d4 Branch: refs/heads/ignite-8446 Commit: 929a12d4a9ad156cd6253204112e742cc0fb9c41 Parents: 67a2aac Author: Ilya Lantukh <ilant...@gridgain.com> Authored: Wed Jun 27 14:53:05 2018 +0300 Committer: Ivan Rakov <ira...@apache.org> Committed: Wed Jun 27 14:53:05 2018 +0300 ---------------------------------------------------------------------- .../internal/UnregisteredClassException.java | 74 ++++++++++++++++++++ .../ignite/internal/binary/BinaryContext.java | 20 ++++-- .../internal/binary/BinaryEnumObjectImpl.java | 2 +- .../internal/binary/BinaryMarshaller.java | 2 +- .../internal/binary/BinaryReaderExImpl.java | 2 +- .../ignite/internal/binary/BinaryUtils.java | 4 +- .../internal/binary/BinaryWriterExImpl.java | 28 ++++++-- .../internal/binary/GridBinaryMarshaller.java | 5 +- .../binary/builder/BinaryBuilderEnum.java | 2 +- .../binary/builder/BinaryBuilderSerializer.java | 2 +- .../builder/BinaryEnumArrayLazyValue.java | 2 +- .../builder/BinaryObjectArrayLazyValue.java | 2 +- .../binary/builder/BinaryObjectBuilderImpl.java | 2 +- .../client/thin/ClientBinaryMarshaller.java | 2 +- .../CacheDefaultBinaryAffinityKeyMapper.java | 2 +- .../processors/cache/CacheGroupContext.java | 10 +++ .../processors/cache/GridCacheContext.java | 2 +- .../processors/cache/GridCacheReturn.java | 5 ++ .../binary/CacheObjectBinaryProcessor.java | 3 +- .../binary/CacheObjectBinaryProcessorImpl.java | 43 +++++++----- .../cache/binary/IgniteBinaryImpl.java | 2 +- .../dht/GridClientPartitionTopology.java | 5 ++ .../dht/GridDhtPartitionTopology.java | 4 ++ .../dht/GridDhtPartitionTopologyImpl.java | 5 ++ .../dht/atomic/GridDhtAtomicCache.java | 70 +++++++++++------- .../cacheobject/IgniteCacheObjectProcessor.java | 11 +++ .../IgniteCacheObjectProcessorImpl.java | 6 ++ .../util/StripedCompositeReadWriteLock.java | 25 ++++++- .../IgniteCacheEntryProcessorCallTest.java | 5 ++ 29 files changed, 273 insertions(+), 74 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/UnregisteredClassException.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/UnregisteredClassException.java b/modules/core/src/main/java/org/apache/ignite/internal/UnregisteredClassException.java new file mode 100644 index 0000000..6da7daa --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/UnregisteredClassException.java @@ -0,0 +1,74 @@ +/* + * 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; + +import org.apache.ignite.IgniteException; +import org.jetbrains.annotations.Nullable; + +/** + * Exception thrown during serialization if class isn't registered and it's registration isn't allowed. + */ +public class UnregisteredClassException extends IgniteException { + /** */ + private static final long serialVersionUID = 0L; + + /** */ + private final Class cls; + + /** + * @param cls Class that isn't registered. + */ + public UnregisteredClassException(Class cls) { + this.cls = cls; + } + + /** + * @param msg Error message. + * @param cls Class that isn't registered. + */ + public UnregisteredClassException(String msg, Class cls) { + super(msg); + this.cls = cls; + } + + /** + * @param cause Exception cause. + * @param cls Class that isn't registered. + */ + public UnregisteredClassException(Throwable cause, Class cls) { + super(cause); + this.cls = cls; + } + + /** + * @param msg Error message. + * @param cause Exception cause. + * @param cls Class that isn't registered. + */ + public UnregisteredClassException(String msg, @Nullable Throwable cause, Class cls) { + super(msg, cause); + this.cls = cls; + } + + /** + * @return Class that isn't registered. + */ + public Class cls() { + return cls; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java index 2337696..0121570 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java @@ -48,6 +48,7 @@ import java.util.jar.JarFile; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteException; import org.apache.ignite.IgniteLogger; +import org.apache.ignite.internal.UnregisteredClassException; import org.apache.ignite.internal.util.IgniteUtils; import org.apache.ignite.binary.BinaryBasicIdMapper; import org.apache.ignite.binary.BinaryBasicNameMapper; @@ -610,17 +611,22 @@ public class BinaryContext { /** * @param cls Class. + * @param failIfUnregistered Throw exception if class isn't registered. * @return Class descriptor. * @throws BinaryObjectException In case of error. */ - public BinaryClassDescriptor descriptorForClass(Class<?> cls, boolean deserialize) + public BinaryClassDescriptor descriptorForClass(Class<?> cls, boolean deserialize, boolean failIfUnregistered) throws BinaryObjectException { assert cls != null; BinaryClassDescriptor desc = descByCls.get(cls); - if (desc == null) + if (desc == null) { + if (failIfUnregistered) + throw new UnregisteredClassException(cls); + desc = registerClassDescriptor(cls, deserialize); + } else if (!desc.registered()) { if (!desc.userType()) { BinaryClassDescriptor desc0 = new BinaryClassDescriptor( @@ -652,8 +658,12 @@ public class BinaryContext { return desc0; } } - else + else { + if (failIfUnregistered) + throw new UnregisteredClassException(cls); + desc = registerUserClassDescriptor(desc); + } } return desc; @@ -1176,8 +1186,8 @@ public class BinaryContext { /** * Register "type ID to class name" mapping on all nodes to allow for mapping requests resolution form client. * Other {@link BinaryContext}'s "register" methods and method - * {@link BinaryContext#descriptorForClass(Class, boolean)} already call this functionality so use this method - * only when registering class names whose {@link Class} is unknown. + * {@link BinaryContext#descriptorForClass(Class, boolean, boolean)} already call this functionality + * so use this method only when registering class names whose {@link Class} is unknown. * * @param typeId Type ID. * @param clsName Class Name. http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryEnumObjectImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryEnumObjectImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryEnumObjectImpl.java index 12a0fc3..2751695 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryEnumObjectImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryEnumObjectImpl.java @@ -437,6 +437,6 @@ public class BinaryEnumObjectImpl implements BinaryObjectEx, Externalizable, Cac * binary enum. */ public boolean isTypeEquals(final Class<?> cls) { - return ctx.descriptorForClass(cls, false).typeId() == typeId(); + return ctx.descriptorForClass(cls, false, false).typeId() == typeId(); } } http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryMarshaller.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryMarshaller.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryMarshaller.java index dfc726e..bfb0e10 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryMarshaller.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryMarshaller.java @@ -79,7 +79,7 @@ public class BinaryMarshaller extends AbstractNodeNameAwareMarshaller { /** {@inheritDoc} */ @Override protected byte[] marshal0(@Nullable Object obj) throws IgniteCheckedException { - return impl.marshal(obj); + return impl.marshal(obj, false); } /** {@inheritDoc} */ http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryReaderExImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryReaderExImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryReaderExImpl.java index f88e3c3..ab1f874 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryReaderExImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryReaderExImpl.java @@ -265,7 +265,7 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina if (forUnmarshal) { // Registers class by type ID, at least locally if the cache is not ready yet. - desc = ctx.descriptorForClass(BinaryUtils.doReadClass(in, ctx, ldr, typeId0), false); + desc = ctx.descriptorForClass(BinaryUtils.doReadClass(in, ctx, ldr, typeId0), false, false); typeId = desc.typeId(); } http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java index 082cc20..553d8e5 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java @@ -1625,7 +1625,7 @@ public class BinaryUtils { } // forces registering of class by type id, at least locally - ctx.descriptorForClass(cls, true); + ctx.descriptorForClass(cls, true, false); } return cls; @@ -1655,7 +1655,7 @@ public class BinaryUtils { } // forces registering of class by type id, at least locally - ctx.descriptorForClass(cls, true); + ctx.descriptorForClass(cls, true, false); } return cls; http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryWriterExImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryWriterExImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryWriterExImpl.java index a7f645c..3d93e70 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryWriterExImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryWriterExImpl.java @@ -82,6 +82,9 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje /** */ private BinaryInternalMapper mapper; + /** */ + private boolean failIfUnregistered; + /** * @param ctx Context. */ @@ -113,6 +116,13 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje } /** + * @param failIfUnregistered Fail if unregistered. + */ + public void failIfUnregistered(boolean failIfUnregistered) { + this.failIfUnregistered = failIfUnregistered; + } + + /** * @param typeId Type ID. */ public void typeId(int typeId) { @@ -161,7 +171,7 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje Class<?> cls = obj.getClass(); - BinaryClassDescriptor desc = ctx.descriptorForClass(cls, false); + BinaryClassDescriptor desc = ctx.descriptorForClass(cls, false, failIfUnregistered); if (desc == null) throw new BinaryObjectException("Object is not binary: [class=" + cls + ']'); @@ -724,7 +734,10 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje if (tryWriteAsHandle(val)) return; - BinaryClassDescriptor desc = ctx.descriptorForClass(val.getClass().getComponentType(), false); + BinaryClassDescriptor desc = ctx.descriptorForClass( + val.getClass().getComponentType(), + false, + failIfUnregistered); out.unsafeEnsure(1 + 4); out.unsafeWriteByte(GridBinaryMarshaller.OBJ_ARR); @@ -795,7 +808,7 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje if (val == null) out.writeByte(GridBinaryMarshaller.NULL); else { - BinaryClassDescriptor desc = ctx.descriptorForClass(val.getDeclaringClass(), false); + BinaryClassDescriptor desc = ctx.descriptorForClass(val.getDeclaringClass(), false, failIfUnregistered); out.unsafeEnsure(1 + 4); @@ -848,7 +861,10 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje if (val == null) out.writeByte(GridBinaryMarshaller.NULL); else { - BinaryClassDescriptor desc = ctx.descriptorForClass(val.getClass().getComponentType(), false); + BinaryClassDescriptor desc = ctx.descriptorForClass( + val.getClass().getComponentType(), + false, + failIfUnregistered); out.unsafeEnsure(1 + 4); @@ -877,7 +893,7 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje if (val == null) out.writeByte(GridBinaryMarshaller.NULL); else { - BinaryClassDescriptor desc = ctx.descriptorForClass(val, false); + BinaryClassDescriptor desc = ctx.descriptorForClass(val, false, failIfUnregistered); out.unsafeEnsure(1 + 4); @@ -906,7 +922,7 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje out.unsafeWriteInt(intfs.length); for (Class<?> intf : intfs) { - BinaryClassDescriptor desc = ctx.descriptorForClass(intf, false); + BinaryClassDescriptor desc = ctx.descriptorForClass(intf, false, failIfUnregistered); if (desc.registered()) out.writeInt(desc.typeId()); http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/binary/GridBinaryMarshaller.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/GridBinaryMarshaller.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/GridBinaryMarshaller.java index d6c8abd..7439589 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/GridBinaryMarshaller.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/GridBinaryMarshaller.java @@ -240,14 +240,17 @@ public class GridBinaryMarshaller { /** * @param obj Object to marshal. + * @param failIfUnregistered Throw exception if class isn't registered. * @return Byte array. * @throws org.apache.ignite.binary.BinaryObjectException In case of error. */ - public byte[] marshal(@Nullable Object obj) throws BinaryObjectException { + public byte[] marshal(@Nullable Object obj, boolean failIfUnregistered) throws BinaryObjectException { if (obj == null) return new byte[] { NULL }; try (BinaryWriterExImpl writer = new BinaryWriterExImpl(ctx)) { + writer.failIfUnregistered(failIfUnregistered); + writer.marshal(obj); return writer.array(); http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderEnum.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderEnum.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderEnum.java index bc5eb9e..3930c46 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderEnum.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderEnum.java @@ -63,7 +63,7 @@ public class BinaryBuilderEnum implements BinaryBuilderSerializationAware { throw new BinaryInvalidTypeException("Failed to load the class: " + clsName, e); } - this.typeId = reader.binaryContext().descriptorForClass(cls, false).typeId(); + this.typeId = reader.binaryContext().descriptorForClass(cls, false, false).typeId(); } else { this.typeId = typeId; http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderSerializer.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderSerializer.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderSerializer.java index 42f6873..5333cc4 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderSerializer.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderSerializer.java @@ -129,7 +129,7 @@ class BinaryBuilderSerializer { writer.context().updateMetadata(typeId, meta); // Need register class for marshaller to be able to deserialize enum value. - writer.context().descriptorForClass(((Enum)val).getDeclaringClass(), false); + writer.context().descriptorForClass(((Enum)val).getDeclaringClass(), false, false); writer.writeByte(GridBinaryMarshaller.ENUM); writer.writeInt(typeId); http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryEnumArrayLazyValue.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryEnumArrayLazyValue.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryEnumArrayLazyValue.java index 787ff63..c0e79ec 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryEnumArrayLazyValue.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryEnumArrayLazyValue.java @@ -56,7 +56,7 @@ class BinaryEnumArrayLazyValue extends BinaryAbstractLazyValue { throw new BinaryInvalidTypeException("Failed to load the class: " + clsName, e); } - compTypeId = reader.binaryContext().descriptorForClass(cls, true).typeId(); + compTypeId = reader.binaryContext().descriptorForClass(cls, true, false).typeId(); } else { compTypeId = typeId; http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectArrayLazyValue.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectArrayLazyValue.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectArrayLazyValue.java index 8962107..d4882dc 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectArrayLazyValue.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectArrayLazyValue.java @@ -55,7 +55,7 @@ class BinaryObjectArrayLazyValue extends BinaryAbstractLazyValue { throw new BinaryInvalidTypeException("Failed to load the class: " + clsName, e); } - compTypeId = reader.binaryContext().descriptorForClass(cls, true).typeId(); + compTypeId = reader.binaryContext().descriptorForClass(cls, true, false).typeId(); } else { compTypeId = typeId; http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java index b9eb3e5..3fc5dc4 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java @@ -157,7 +157,7 @@ public class BinaryObjectBuilderImpl implements BinaryObjectBuilder { throw new BinaryInvalidTypeException("Failed to load the class: " + clsNameToWrite, e); } - this.typeId = ctx.descriptorForClass(cls, false).typeId(); + this.typeId = ctx.descriptorForClass(cls, false, false).typeId(); registeredType = false; http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientBinaryMarshaller.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientBinaryMarshaller.java b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientBinaryMarshaller.java index c68b8f9..aac6873 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientBinaryMarshaller.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientBinaryMarshaller.java @@ -66,7 +66,7 @@ class ClientBinaryMarshaller { * Serializes Java object into a byte array. */ public byte[] marshal(Object obj) { - return impl.marshal(obj); + return impl.marshal(obj, false); } /** http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheDefaultBinaryAffinityKeyMapper.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheDefaultBinaryAffinityKeyMapper.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheDefaultBinaryAffinityKeyMapper.java index 4350687..385ed59 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheDefaultBinaryAffinityKeyMapper.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheDefaultBinaryAffinityKeyMapper.java @@ -63,7 +63,7 @@ public class CacheDefaultBinaryAffinityKeyMapper extends GridCacheDefaultAffinit /** {@inheritDoc} */ @Override public Object affinityKey(Object key) { try { - key = proc.toBinary(key); + key = proc.toBinary(key, false); } catch (IgniteException e) { U.error(log, "Failed to marshal key to binary: " + key, e); http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheGroupContext.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheGroupContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheGroupContext.java index 99f9f97..d2b98f2 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheGroupContext.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheGroupContext.java @@ -581,6 +581,16 @@ public class CacheGroupContext { } /** + * @return {@code True} if current thread holds lock on topology. + */ + public boolean isTopologyLocked() { + if (top == null) + return false; + + return top.holdsLock(); + } + + /** * @return Offheap manager. */ public IgniteCacheOffheapManager offheap() { http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java index c5f4d3c..191734b 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java @@ -1799,7 +1799,7 @@ public class GridCacheContext<K, V> implements Externalizable { @Nullable public CacheObject toCacheObject(@Nullable Object obj) { assert validObjectForCache(obj) : obj; - return cacheObjects().toCacheObject(cacheObjCtx, obj, true); + return cacheObjects().toCacheObject(cacheObjCtx, obj, true, grp.isTopologyLocked()); } /** http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheReturn.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheReturn.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheReturn.java index 551d70d..bc85931 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheReturn.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheReturn.java @@ -31,6 +31,7 @@ import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.binary.BinaryObject; import org.apache.ignite.internal.GridDirectCollection; import org.apache.ignite.internal.GridDirectTransient; +import org.apache.ignite.internal.UnregisteredClassException; import org.apache.ignite.internal.util.tostring.GridToStringInclude; import org.apache.ignite.internal.util.typedef.internal.CU; import org.apache.ignite.internal.util.typedef.internal.S; @@ -242,6 +243,10 @@ public class GridCacheReturn implements Externalizable, Message { v = resMap; } + // This exception means that we should register class and call EntryProcessor again. + if (err != null && err instanceof UnregisteredClassException) + throw (UnregisteredClassException) err; + CacheInvokeResult res0 = err == null ? CacheInvokeResult.fromResult(res) : CacheInvokeResult.fromError(err); Object resKey = key0 != null ? key0 : http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessor.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessor.java index 14dd5cb..c7e2e68 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessor.java @@ -140,8 +140,9 @@ public interface CacheObjectBinaryProcessor extends IgniteCacheObjectProcessor { /** * @param obj Original object. + * @param failIfUnregistered Throw exception if class isn't registered. * @return Binary object (in case binary marshaller is used). * @throws IgniteException If failed. */ - public Object marshalToBinary(Object obj) throws IgniteException; + public Object marshalToBinary(Object obj, boolean failIfUnregistered) throws IgniteException; } http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java index 8e5ec5c..69d1f91 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java @@ -295,7 +295,7 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm * @throws BinaryObjectException If failed. */ public byte[] marshal(@Nullable Object obj) throws BinaryObjectException { - byte[] arr = binaryMarsh.marshal(obj); + byte[] arr = binaryMarsh.marshal(obj, false); assert arr.length > 0; @@ -330,7 +330,10 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm /** {@inheritDoc} */ @SuppressWarnings("unchecked") - @Override public Object marshalToBinary(@Nullable Object obj) throws BinaryObjectException { + @Override public Object marshalToBinary( + @Nullable Object obj, + boolean failIfUnregistered + ) throws BinaryObjectException { if (obj == null) return null; @@ -343,7 +346,7 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm Object[] pArr = new Object[arr.length]; for (int i = 0; i < arr.length; i++) - pArr[i] = marshalToBinary(arr[i]); + pArr[i] = marshalToBinary(arr[i], failIfUnregistered); return pArr; } @@ -352,9 +355,11 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm IgniteBiTuple tup = (IgniteBiTuple)obj; if (obj instanceof T2) - return new T2<>(marshalToBinary(tup.get1()), marshalToBinary(tup.get2())); + return new T2<>(marshalToBinary(tup.get1(), failIfUnregistered), + marshalToBinary(tup.get2(), failIfUnregistered)); - return new IgniteBiTuple<>(marshalToBinary(tup.get1()), marshalToBinary(tup.get2())); + return new IgniteBiTuple<>(marshalToBinary(tup.get1(), failIfUnregistered), + marshalToBinary(tup.get2(), failIfUnregistered)); } { @@ -364,7 +369,7 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm Collection<?> col = (Collection<?>)obj; for (Object item : col) - pCol.add(marshalToBinary(item)); + pCol.add(marshalToBinary(item, failIfUnregistered)); return (pCol instanceof MutableSingletonList) ? U.convertToSingletonList(pCol) : pCol; } @@ -377,7 +382,8 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm Map<?, ?> map = (Map<?, ?>)obj; for (Map.Entry<?, ?> e : map.entrySet()) - pMap.put(marshalToBinary(e.getKey()), marshalToBinary(e.getValue())); + pMap.put(marshalToBinary(e.getKey(), failIfUnregistered), + marshalToBinary(e.getValue(), failIfUnregistered)); return pMap; } @@ -386,13 +392,14 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm if (obj instanceof Map.Entry) { Map.Entry<?, ?> e = (Map.Entry<?, ?>)obj; - return new GridMapEntry<>(marshalToBinary(e.getKey()), marshalToBinary(e.getValue())); + return new GridMapEntry<>(marshalToBinary(e.getKey(), failIfUnregistered), + marshalToBinary(e.getValue(), failIfUnregistered)); } if (binaryMarsh.mustDeserialize(obj)) return obj; // No need to go through marshal-unmarshal because result will be the same as initial object. - byte[] arr = binaryMarsh.marshal(obj); + byte[] arr = binaryMarsh.marshal(obj, failIfUnregistered); assert arr.length > 0; @@ -765,7 +772,7 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm if (!ctx.binaryEnabled() || binaryMarsh == null) return super.marshal(ctx, val); - byte[] arr = binaryMarsh.marshal(val); + byte[] arr = binaryMarsh.marshal(val, false); assert arr.length > 0; @@ -801,7 +808,7 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm return key; } - obj = toBinary(obj); + obj = toBinary(obj, false); if (obj instanceof BinaryObjectImpl) { ((BinaryObjectImpl)obj).partition(partition(ctx, cctx, obj)); @@ -814,14 +821,14 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm /** {@inheritDoc} */ @Nullable @Override public CacheObject toCacheObject(CacheObjectContext ctx, @Nullable Object obj, - boolean userObj) { + boolean userObj, boolean failIfUnregistered) { if (!ctx.binaryEnabled()) - return super.toCacheObject(ctx, obj, userObj); + return super.toCacheObject(ctx, obj, userObj, failIfUnregistered); if (obj == null || obj instanceof CacheObject) return (CacheObject)obj; - obj = toBinary(obj); + obj = toBinary(obj, failIfUnregistered); if (obj instanceof CacheObject) return (CacheObject)obj; @@ -864,18 +871,20 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm * @return Binary object. * @throws IgniteException In case of error. */ - @Nullable public Object toBinary(@Nullable Object obj) throws IgniteException { + @Nullable public Object toBinary(@Nullable Object obj, boolean failIfUnregistered) throws IgniteException { if (obj == null) return null; if (isBinaryObject(obj)) return obj; - return marshalToBinary(obj); + return marshalToBinary(obj, failIfUnregistered); } /** {@inheritDoc} */ - @Nullable @Override public IgniteNodeValidationResult validateNode(ClusterNode rmtNode, DiscoveryDataBag.JoiningNodeDiscoveryData discoData) { + @Nullable @Override public IgniteNodeValidationResult validateNode(ClusterNode rmtNode, + DiscoveryDataBag.JoiningNodeDiscoveryData discoData + ) { IgniteNodeValidationResult res; if (getBoolean(IGNITE_SKIP_CONFIGURATION_CONSISTENCY_CHECK) || !(marsh instanceof BinaryMarshaller)) http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/IgniteBinaryImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/IgniteBinaryImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/IgniteBinaryImpl.java index e88819b..71475be 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/IgniteBinaryImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/IgniteBinaryImpl.java @@ -66,7 +66,7 @@ public class IgniteBinaryImpl implements IgniteBinary { guard(); try { - return (T)proc.marshalToBinary(obj); + return (T)proc.marshalToBinary(obj, false); } finally { unguard(); http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridClientPartitionTopology.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridClientPartitionTopology.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridClientPartitionTopology.java index fc80bbc..54a850c 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridClientPartitionTopology.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridClientPartitionTopology.java @@ -199,6 +199,11 @@ public class GridClientPartitionTopology implements GridDhtPartitionTopology { } /** {@inheritDoc} */ + @Override public boolean holdsLock() { + return lock.isWriteLockedByCurrentThread() || lock.getReadHoldCount() > 0; + } + + /** {@inheritDoc} */ @Override public void updateTopologyVersion( GridDhtTopologyFuture exchFut, DiscoCache discoCache, http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopology.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopology.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopology.java index b77dbd6..42ef309 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopology.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopology.java @@ -59,6 +59,10 @@ public interface GridDhtPartitionTopology { public void readUnlock(); /** + * @return {@code True} if locked by current thread. + */ + public boolean holdsLock(); + /** * Updates topology version. * * @param exchFut Exchange future. http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java index cabb0b8..ac338ae 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java @@ -235,6 +235,11 @@ public class GridDhtPartitionTopologyImpl implements GridDhtPartitionTopology { } /** {@inheritDoc} */ + @Override public boolean holdsLock() { + return lock.isWriteLockedByCurrentThread() || lock.getReadHoldCount() > 0; + } + + /** {@inheritDoc} */ @Override public void updateTopologyVersion( GridDhtTopologyFuture exchFut, @NotNull DiscoCache discoCache, http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java index 187f1b0..8408b32 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java @@ -37,6 +37,7 @@ import org.apache.ignite.IgniteLogger; import org.apache.ignite.cluster.ClusterNode; import org.apache.ignite.internal.IgniteInternalFuture; import org.apache.ignite.internal.NodeStoppingException; +import org.apache.ignite.internal.UnregisteredClassException; import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException; import org.apache.ignite.internal.mem.IgniteOutOfMemoryException; import org.apache.ignite.internal.pagemem.wal.StorageException; @@ -62,6 +63,7 @@ import org.apache.ignite.internal.processors.cache.GridCacheReturn; import org.apache.ignite.internal.processors.cache.GridCacheUpdateAtomicResult; import org.apache.ignite.internal.processors.cache.IgniteCacheExpiryPolicy; import org.apache.ignite.internal.processors.cache.KeyCacheObject; +import org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl; import org.apache.ignite.internal.processors.cache.persistence.CacheDataRow; import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtCacheAdapter; import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtCacheEntry; @@ -84,6 +86,7 @@ import org.apache.ignite.internal.processors.cache.transactions.IgniteTxLocalEx; import org.apache.ignite.internal.processors.cache.version.GridCacheVersion; import org.apache.ignite.internal.processors.cache.version.GridCacheVersionConflictContext; import org.apache.ignite.internal.processors.cache.version.GridCacheVersionEx; +import org.apache.ignite.internal.processors.cacheobject.IgniteCacheObjectProcessor; import org.apache.ignite.internal.processors.timeout.GridTimeoutObject; import org.apache.ignite.internal.util.GridLongList; import org.apache.ignite.internal.util.future.GridFinishedFuture; @@ -1707,43 +1710,56 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> { Collection<IgniteBiTuple<GridDhtCacheEntry, GridCacheVersion>> deleted = null; try { - GridDhtPartitionTopology top = topology(); + while (true) { + try { + GridDhtPartitionTopology top = topology(); - top.readLock(); + top.readLock(); - try { - if (top.stopping()) { - res.addFailedKeys(req.keys(), new CacheStoppedException(name())); + try { + if (top.stopping()) { + res.addFailedKeys(req.keys(), new CacheStoppedException(name())); - completionCb.apply(req, res); + completionCb.apply(req, res); - return; - } + return; + } + + boolean remap = false; + + // Do not check topology version if topology was locked on near node by + // external transaction or explicit lock. + if (!req.topologyLocked()) { + // Can not wait for topology future since it will break + // GridNearAtomicCheckUpdateRequest processing. + remap = !top.topologyVersionFuture().exchangeDone() || + needRemap(req.topologyVersion(), top.readyTopologyVersion()); + } - boolean remap = false; + if (!remap) { + DhtAtomicUpdateResult updRes = update(node, locked, req, res); - // Do not check topology version if topology was locked on near node by - // external transaction or explicit lock. - if (!req.topologyLocked()) { - // Can not wait for topology future since it will break - // GridNearAtomicCheckUpdateRequest processing. - remap = !top.topologyVersionFuture().exchangeDone() || - needRemap(req.topologyVersion(), top.readyTopologyVersion()); + dhtFut = updRes.dhtFuture(); + deleted = updRes.deleted(); + expiry = updRes.expiryPolicy(); + } + else + // Should remap all keys. + res.remapTopologyVersion(top.lastTopologyChangeVersion()); + } + finally { + top.readUnlock(); + } + + break; } + catch (UnregisteredClassException ex) { + IgniteCacheObjectProcessor cacheObjProc = ctx.cacheObjects(); - if (!remap) { - DhtAtomicUpdateResult updRes = update(node, locked, req, res); + assert cacheObjProc instanceof CacheObjectBinaryProcessorImpl; - dhtFut = updRes.dhtFuture(); - deleted = updRes.deleted(); - expiry = updRes.expiryPolicy(); + ((CacheObjectBinaryProcessorImpl)cacheObjProc).binaryContext().descriptorForClass(ex.cls(), false, false); } - else - // Should remap all keys. - res.remapTopologyVersion(top.lastTopologyChangeVersion()); - } - finally { - top.readUnlock(); } } catch (GridCacheEntryRemovedException e) { http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java index dad6728..defb3cc 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java @@ -154,6 +154,17 @@ public interface IgniteCacheObjectProcessor extends GridProcessor { /** * @param ctx Cache context. + * @param obj Object. + * @param userObj If {@code true} then given object is object provided by user and should be copied + * before stored in cache. + * @param failIfUnregistered Throw exception if class isn't registered. + * @return Cache object. + */ + @Nullable public CacheObject toCacheObject(CacheObjectContext ctx, @Nullable Object obj, boolean userObj, + boolean failIfUnregistered); + + /** + * @param ctx Cache context. * @param type Object type. * @param bytes Object bytes. * @return Cache object. http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java index 17be90f..7f55614 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java @@ -225,6 +225,12 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme @Nullable @Override public CacheObject toCacheObject(CacheObjectContext ctx, @Nullable Object obj, boolean userObj) { + return toCacheObject(ctx, obj, userObj, false); + } + + /** {@inheritDoc} */ + @Nullable @Override public CacheObject toCacheObject(CacheObjectContext ctx, @Nullable Object obj, boolean userObj, + boolean failIfUnregistered) { if (obj == null || obj instanceof CacheObject) return (CacheObject)obj; http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/main/java/org/apache/ignite/internal/util/StripedCompositeReadWriteLock.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/StripedCompositeReadWriteLock.java b/modules/core/src/main/java/org/apache/ignite/internal/util/StripedCompositeReadWriteLock.java index 18ef06c..42ec397 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/util/StripedCompositeReadWriteLock.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/util/StripedCompositeReadWriteLock.java @@ -63,8 +63,10 @@ public class StripedCompositeReadWriteLock implements ReadWriteLock { writeLock = new WriteLock(); } - /** {@inheritDoc} */ - @NotNull @Override public Lock readLock() { + /** + * @return Index of current thread stripe. + */ + private int curIdx() { int idx; Thread curThread = Thread.currentThread(); @@ -83,7 +85,12 @@ public class StripedCompositeReadWriteLock implements ReadWriteLock { else idx = IDX.get(); - return locks[idx % locks.length].readLock(); + return idx % locks.length; + } + + /** {@inheritDoc} */ + @NotNull @Override public Lock readLock() { + return locks[curIdx()].readLock(); } /** {@inheritDoc} */ @@ -102,6 +109,18 @@ public class StripedCompositeReadWriteLock implements ReadWriteLock { } /** + * Queries the number of reentrant read holds on this lock by the + * current thread. A reader thread has a hold on a lock for + * each lock action that is not matched by an unlock action. + * + * @return the number of holds on the read lock by the current thread, + * or zero if the read lock is not held by the current thread + */ + public int getReadHoldCount() { + return locks[curIdx()].getReadHoldCount(); + } + + /** * Read lock. */ @SuppressWarnings("unused") http://git-wip-us.apache.org/repos/asf/ignite/blob/929a12d4/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheEntryProcessorCallTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheEntryProcessorCallTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheEntryProcessorCallTest.java index 2f80462..4efe513 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheEntryProcessorCallTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheEntryProcessorCallTest.java @@ -154,6 +154,11 @@ public class IgniteCacheEntryProcessorCallTest extends GridCommonAbstractTest { int key = 0; + // Call EntryProcessor on every node to ensure that binary metadata has been registered everywhere. + for (int i = 0; i < 1_000; i++) + ignite(i % SRV_CNT).<Integer, TestValue>cache(ccfg.getName()) + .invoke(key++, new TestEntryProcessor(OP_UPDATE), new TestValue(Integer.MIN_VALUE)); + checkEntryProcessCall(key++, clientCache1, null, null, expCallCnt); if (ccfg.getAtomicityMode() == TRANSACTIONAL) {