IGNITE-2649 - Ignition.localIgnite() unreliable under Gateways and cause wrong components deserialization.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/09a30f30 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/09a30f30 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/09a30f30 Branch: refs/heads/ignite-2649 Commit: 09a30f3077e6fa6034fa2d95803df2a19a70a278 Parents: 63210e6 Author: dkarachentsev <dkarachent...@gridgain.com> Authored: Wed Aug 3 18:34:00 2016 +0300 Committer: dkarachentsev <dkarachent...@gridgain.com> Committed: Wed Aug 3 18:34:00 2016 +0300 ---------------------------------------------------------------------- .../org/apache/ignite/internal/IgnitionEx.java | 54 ++++++++---- .../apache/ignite/internal/LocalGridName.java | 46 +++++++++++ .../internal/binary/BinaryReaderExImpl.java | 10 ++- .../internal/binary/BinaryWriterExImpl.java | 10 ++- .../ignite/marshaller/MarshallerUtils.java | 86 ++++++++++++-------- .../GridBinaryCacheSerializationTest.java | 63 +++++++------- 6 files changed, 183 insertions(+), 86 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/09a30f30/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java b/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java index fe9dab0..63d0aec 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java @@ -166,7 +166,11 @@ public class IgnitionEx { private static final Collection<IgnitionListener> lsnrs = new GridConcurrentHashSet<>(4); /** */ - private static final ThreadLocal<String> GRID_NAME_THREAD_LOC = new ThreadLocal<>(); + private static final ThreadLocal<LocalGridName> GRID_NAME_THREAD_LOC = new ThreadLocal<LocalGridName>() { + @Override protected LocalGridName initialValue() { + return new LocalGridNameImpl(); + } + }; /** */ private static ThreadLocal<Boolean> daemon = new ThreadLocal<Boolean>() { @@ -1289,12 +1293,10 @@ public class IgnitionEx { * @throws IllegalArgumentException Thrown to indicate, that current thread is not an {@link IgniteThread}. */ public static IgniteKernal localIgnite() throws IllegalArgumentException { - final String gridName = GRID_NAME_THREAD_LOC.get(); - - // TODO support null!! + final LocalGridName gridName = GRID_NAME_THREAD_LOC.get(); - if (gridName != null) - return gridx(gridName); + if (gridName.isSet()) + return gridx(gridName.getGridName()); else if (Thread.currentThread() instanceof IgniteThread) return gridx(((IgniteThread)Thread.currentThread()).getGridName()); else @@ -1365,20 +1367,11 @@ public class IgnitionEx { } /** - * Set ignite config to thread local. - * - * @param name Grid name. - */ - public static void setGridNameThreadLocal(final String name) { - GRID_NAME_THREAD_LOC.set(name); - } - - /** * Get ignite config from thread local. * - * @return Grid name. + * @return Local grid name. */ - public static String getGridNameThreadLocal() { + public static LocalGridName gridNameThreadLocal() { return GRID_NAME_THREAD_LOC.get(); } @@ -2549,4 +2542,31 @@ public class IgnitionEx { } } } + + /** + * + */ + private static class LocalGridNameImpl implements LocalGridName { + /** Indicates whether value is initial or not. */ + private boolean valSet; + + /** Grid name. */ + private String gridName; + + /** {@inheritDoc} */ + @Override public boolean isSet() { + return valSet; + } + + /** {@inheritDoc} */ + @Override public String getGridName() { + return gridName; + } + + /** {@inheritDoc} */ + @Override public void setGridName(final boolean set, final String gridName) { + this.valSet = set; + this.gridName = gridName; + } + } } http://git-wip-us.apache.org/repos/asf/ignite/blob/09a30f30/modules/core/src/main/java/org/apache/ignite/internal/LocalGridName.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/LocalGridName.java b/modules/core/src/main/java/org/apache/ignite/internal/LocalGridName.java new file mode 100644 index 0000000..276091b --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/LocalGridName.java @@ -0,0 +1,46 @@ +/* + * 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; + +/** + * Container holds local grid name and has indicator + * that shows if value was initialized. + */ +public interface LocalGridName { + /** + * Indicates whether value was set. + * + * @return {@code True} if value was set. + */ + public boolean isSet(); + + /** + * Get grid name. + * + * @return Grid name. + */ + public String getGridName(); + + /** + * Set grid name and set flag. + * + * @param set {@code True} if value is not initial. + * @param gridName Grid name. + */ + public void setGridName(boolean set, String gridName); +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/09a30f30/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 44cf85e..47df697 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 @@ -33,6 +33,7 @@ import org.apache.ignite.binary.BinaryObject; import org.apache.ignite.binary.BinaryObjectException; import org.apache.ignite.binary.BinaryRawReader; import org.apache.ignite.binary.BinaryReader; +import org.apache.ignite.internal.LocalGridName; import org.apache.ignite.internal.IgnitionEx; import org.apache.ignite.internal.binary.streams.BinaryInputStream; import org.apache.ignite.internal.util.typedef.internal.SB; @@ -1421,15 +1422,18 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina * @throws BinaryObjectException If failed. */ @Nullable Object deserialize() throws BinaryObjectException { - final String gridName = IgnitionEx.getGridNameThreadLocal(); + final LocalGridName gridName = IgnitionEx.gridNameThreadLocal(); + + final String gridNameStr = gridName.getGridName(); + final boolean init = gridName.isSet(); try { - IgnitionEx.setGridNameThreadLocal(ctx.configuration().getGridName()); + gridName.setGridName(true, ctx.configuration().getGridName()); return deserialize0(); } finally { - IgnitionEx.setGridNameThreadLocal(gridName); + gridName.setGridName(init, gridNameStr); } } http://git-wip-us.apache.org/repos/asf/ignite/blob/09a30f30/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 9bf7ecb..de89f76 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 @@ -33,6 +33,7 @@ import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.binary.BinaryObjectException; import org.apache.ignite.binary.BinaryRawWriter; import org.apache.ignite.binary.BinaryWriter; +import org.apache.ignite.internal.LocalGridName; import org.apache.ignite.internal.IgnitionEx; import org.apache.ignite.internal.binary.streams.BinaryHeapOutputStream; import org.apache.ignite.internal.binary.streams.BinaryOutputStream; @@ -140,15 +141,18 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje * @throws org.apache.ignite.binary.BinaryObjectException In case of error. */ void marshal(Object obj, boolean enableReplace) throws BinaryObjectException { - final String gridName = IgnitionEx.getGridNameThreadLocal(); + final LocalGridName gridName = IgnitionEx.gridNameThreadLocal(); + + final String gridNameStr = gridName.getGridName(); + final boolean init = gridName.isSet(); try { - IgnitionEx.setGridNameThreadLocal(ctx.configuration().getGridName()); + gridName.setGridName(true, ctx.configuration().getGridName()); marshal0(obj, enableReplace); } finally { - IgnitionEx.setGridNameThreadLocal(gridName); + gridName.setGridName(init, gridNameStr); } } http://git-wip-us.apache.org/repos/asf/ignite/blob/09a30f30/modules/core/src/main/java/org/apache/ignite/marshaller/MarshallerUtils.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/MarshallerUtils.java b/modules/core/src/main/java/org/apache/ignite/marshaller/MarshallerUtils.java index b678bd2..cfb45ad 100644 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/MarshallerUtils.java +++ b/modules/core/src/main/java/org/apache/ignite/marshaller/MarshallerUtils.java @@ -18,11 +18,9 @@ package org.apache.ignite.marshaller; import org.apache.ignite.IgniteCheckedException; -import org.apache.ignite.configuration.IgniteConfiguration; -import org.apache.ignite.internal.GridKernalContext; +import org.apache.ignite.internal.LocalGridName; import org.apache.ignite.internal.IgnitionEx; import org.apache.ignite.internal.client.marshaller.GridClientMarshaller; -import org.apache.ignite.internal.util.typedef.F; import org.jetbrains.annotations.Nullable; import java.io.IOException; @@ -51,12 +49,17 @@ public final class MarshallerUtils { */ public static void marshal(final Marshaller marshaller, final @Nullable Object obj, final OutputStream out, final String gridName) throws IgniteCheckedException { - final String name = setGridName(gridName); + final LocalGridName gridNameTl = gridName(); + + final String gridNameStr = gridNameTl.getGridName(); + final boolean init = gridNameTl.isSet(); try { + gridNameTl.setGridName(true, gridName); + marshaller.marshal(obj, out); } finally { - restoreGridName(name); + gridNameTl.setGridName(init, gridNameStr); } } @@ -70,12 +73,17 @@ public final class MarshallerUtils { */ public static byte[] marshal(final Marshaller marshaller, @Nullable Object obj, final String gridName) throws IgniteCheckedException { - final String name = setGridName(gridName); + final LocalGridName gridNameTl = gridName(); + + final String gridNameStr = gridNameTl.getGridName(); + final boolean init = gridNameTl.isSet(); try { + gridNameTl.setGridName(true, gridName); + return marshaller.marshal(obj); } finally { - restoreGridName(name); + gridNameTl.setGridName(init, gridNameStr); } } @@ -91,12 +99,17 @@ public final class MarshallerUtils { */ public static <T> T unmarshal(final Marshaller marshaller, InputStream in, @Nullable ClassLoader clsLdr, final String gridName) throws IgniteCheckedException { - final String name = setGridName(gridName); + final LocalGridName gridNameTl = gridName(); + + final String gridNameStr = gridNameTl.getGridName(); + final boolean init = gridNameTl.isSet(); try { + gridNameTl.setGridName(true, gridName); + return marshaller.unmarshal(in, clsLdr); } finally { - restoreGridName(name); + gridNameTl.setGridName(init, gridNameStr); } } @@ -112,12 +125,17 @@ public final class MarshallerUtils { */ public static <T> T unmarshal(final Marshaller marshaller, byte[] arr, @Nullable ClassLoader clsLdr, final String gridName) throws IgniteCheckedException { - final String name = setGridName(gridName); + final LocalGridName gridNameTl = gridName(); + + final String gridNameStr = gridNameTl.getGridName(); + final boolean init = gridNameTl.isSet(); try { + gridNameTl.setGridName(true, gridName); + return marshaller.unmarshal(arr, clsLdr); } finally { - restoreGridName(name); + gridNameTl.setGridName(init, gridNameStr); } } @@ -133,12 +151,17 @@ public final class MarshallerUtils { */ public static <T> T clone(final Marshaller marshaller, T obj, @Nullable ClassLoader clsLdr, final String gridName) throws IgniteCheckedException { - final String name = setGridName(gridName); + final LocalGridName gridNameTl = gridName(); + + final String gridNameStr = gridNameTl.getGridName(); + final boolean init = gridNameTl.isSet(); try { + gridNameTl.setGridName(true, gridName); + return marshaller.unmarshal(marshaller.marshal(obj), clsLdr); } finally { - restoreGridName(name); + gridNameTl.setGridName(init, gridNameStr); } } @@ -153,12 +176,17 @@ public final class MarshallerUtils { */ public static ByteBuffer marshal(GridClientMarshaller gridMarshaller, Object obj, int off, String gridName) throws IOException { - final String name = setGridName(gridName); + final LocalGridName gridNameTl = gridName(); + + final String gridNameStr = gridNameTl.getGridName(); + final boolean init = gridNameTl.isSet(); try { + gridNameTl.setGridName(true, gridName); + return gridMarshaller.marshal(obj, off); } finally { - restoreGridName(name); + gridNameTl.setGridName(init, gridNameStr); } } @@ -173,32 +201,24 @@ public final class MarshallerUtils { */ public static <T> T unmarshal(GridClientMarshaller gridMarshaller, byte[] bytes, String gridName) throws IOException { - final String name = setGridName(gridName); + final LocalGridName gridNameTl = gridName(); + + final String gridNameStr = gridNameTl.getGridName(); + final boolean init = gridNameTl.isSet(); try { + gridNameTl.setGridName(true, gridName); + return gridMarshaller.unmarshal(bytes); } finally { - restoreGridName(name); + gridNameTl.setGridName(init, gridNameStr); } } /** - * @param name Grid name. - * @return Old grid name. - */ - private static String setGridName(final String name) { - final String gridName = IgnitionEx.getGridNameThreadLocal(); - - if (!F.eq(name, gridName)) - IgnitionEx.setGridNameThreadLocal(name); - - return gridName; - } - - /** - * @param name Grid name. + * @return Grid name thread local. */ - private static void restoreGridName(final String name) { - IgnitionEx.setGridNameThreadLocal(name); + private static LocalGridName gridName() { + return IgnitionEx.gridNameThreadLocal(); } } http://git-wip-us.apache.org/repos/asf/ignite/blob/09a30f30/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/binary/GridBinaryCacheSerializationTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/binary/GridBinaryCacheSerializationTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/binary/GridBinaryCacheSerializationTest.java index d5de056..31a7258 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/binary/GridBinaryCacheSerializationTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/binary/GridBinaryCacheSerializationTest.java @@ -27,7 +27,7 @@ import org.apache.ignite.binary.Binarylizable; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.internal.binary.BinaryMarshaller; import org.apache.ignite.internal.util.typedef.internal.U; -import org.apache.ignite.testframework.junits.GridAbstractTest; +import org.apache.ignite.testframework.GridTestUtils; import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; import java.io.Externalizable; @@ -37,7 +37,7 @@ import java.io.ObjectInputStream; import java.io.ObjectOutput; import java.io.ObjectOutputStream; import java.io.Serializable; -import java.lang.reflect.Method; +import java.util.concurrent.Callable; /** * @@ -46,24 +46,6 @@ public class GridBinaryCacheSerializationTest extends GridCommonAbstractTest { /** */ private static final String CACHE_NAME = "cache_name"; - /** - * Emulate user thread. - * - * @throws Throwable - */ - @Override protected void runTest() throws Throwable { - Class<?> cls = getClass(); - - while (!cls.equals(GridAbstractTest.class)) - cls = cls.getSuperclass(); - - final Method runTest = cls.getDeclaredMethod("runTestInternal"); - - runTest.setAccessible(true); - - runTest.invoke(this); - } - /** {@inheritDoc} */ @Override protected IgniteConfiguration getConfiguration(final String gridName) throws Exception { final IgniteConfiguration cfg = super.getConfiguration(gridName); @@ -87,7 +69,7 @@ public class GridBinaryCacheSerializationTest extends GridCommonAbstractTest { /** * @throws Exception If failed. */ - public void testSerializable() throws Exception { + public void testPutGetSerializable() throws Exception { testPutGet(new SerializableTestObject("test"), null); } @@ -109,21 +91,28 @@ public class GridBinaryCacheSerializationTest extends GridCommonAbstractTest { * @throws Exception If failed. */ private void testPutGet(final TestObject obj, final String gridName) throws Exception { - try (final Ignite ignite = startGrid(gridName)) { - final IgniteCache<Integer, TestObject> cache = ignite.getOrCreateCache(CACHE_NAME); + // Run async to emulate user thread. + GridTestUtils.runAsync(new Callable<Object>() { + @Override public Object call() throws Exception { + try (final Ignite ignite = startGrid(gridName)) { + final IgniteCache<Integer, TestObject> cache = ignite.getOrCreateCache(CACHE_NAME); - assertNull(obj.ignite()); + assertNull(obj.ignite()); - cache.put(1, obj); + cache.put(1, obj); - assertNotNull(obj.ignite()); + assertNotNull(obj.ignite()); - final TestObject loadedObj = cache.get(1); + final TestObject loadedObj = cache.get(1); - assertNotNull(loadedObj.ignite()); + assertNotNull(loadedObj.ignite()); - assertEquals(obj, loadedObj); - } + assertEquals(obj, loadedObj); + } + + return null; + } + }).get(); } /** @@ -206,19 +195,33 @@ public class GridBinaryCacheSerializationTest extends GridCommonAbstractTest { /** */ private transient Ignite ignite; + /** + * + */ public SerializableTestObject() { } + /** + * @param val Value + */ public SerializableTestObject(final String val) { this.val = val; } + /** + * @param out Object output. + * @throws IOException If fail. + */ private void writeObject(ObjectOutputStream out) throws IOException { U.writeString(out, val); ignite = Ignition.localIgnite(); } + /** + * @param in Object input. + * @throws IOException If fail. + */ private void readObject(ObjectInputStream in) throws IOException { val = U.readString(in);