You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2017/03/10 07:23:53 UTC

[32/43] ignite git commit: [GG-11997] OutOfMemoryException when repeatedly updating the same entry larger than (page size / 2)

[GG-11997] OutOfMemoryException when repeatedly updating the same entry larger than (page size / 2)


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/869089db
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/869089db
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/869089db

Branch: refs/heads/ignite-4712
Commit: 869089db542894b7bdbf4f87b09131cfcd086dd8
Parents: b2f1ea9
Author: Igor Seliverstov <gv...@gmail.com>
Authored: Tue Feb 28 14:28:11 2017 +0300
Committer: Igor Seliverstov <gv...@gmail.com>
Committed: Wed Mar 1 10:44:55 2017 +0300

----------------------------------------------------------------------
 .../ignite/cache/LargeEntryUpdateTest.java      | 188 +++++++++++++++++++
 .../ignite/testsuites/IgniteCacheTestSuite.java |   3 +
 2 files changed, 191 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/869089db/modules/core/src/test/java/org/apache/ignite/cache/LargeEntryUpdateTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/cache/LargeEntryUpdateTest.java b/modules/core/src/test/java/org/apache/ignite/cache/LargeEntryUpdateTest.java
new file mode 100644
index 0000000..6b63296
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/cache/LargeEntryUpdateTest.java
@@ -0,0 +1,188 @@
+/*
+ * 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.cache;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import javax.cache.processor.EntryProcessorException;
+import javax.cache.processor.MutableEntry;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteCompute;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.MemoryConfiguration;
+import org.apache.ignite.internal.mem.OutOfMemoryException;
+import org.apache.ignite.lang.IgniteRunnable;
+import org.apache.ignite.resources.IgniteInstanceResource;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+/**
+ * LargeEntryUpdateTest
+ *
+ * @author Alexandr Kuramshin <ei...@gmail.com>
+ */
+public class LargeEntryUpdateTest extends GridCommonAbstractTest {
+
+    /**  */
+    private static final int THREAD_COUNT = 10;
+
+    /**  */
+    private static final int PAGE_SIZE = 1 << 10; // 1 kB
+
+    /**  */
+    private static final int PAGE_CACHE_SIZE = 30 << 20; // 30 MB
+
+    /**  */
+    private static final String CACHE_PREFIX = "testCache";
+
+    /**  */
+    private static final int CACHE_COUNT = 10;
+
+    /**  */
+    private static final long WAIT_TIMEOUT = 5 * 60_000L; // 5 min
+
+    /**  */
+    private static final long TEST_TIMEOUT = 10 * 60_000L; // 10 min
+
+    /**  */
+    private final AtomicBoolean cacheUpdate = new AtomicBoolean();
+
+    /**  */
+    private OutOfMemoryException outOfMemoryEx;
+
+    /** {@inheritDoc} */
+    @Override protected long getTestTimeout() {
+        return TEST_TIMEOUT;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(gridName);
+        cfg.setPublicThreadPoolSize(THREAD_COUNT);
+
+        MemoryConfiguration mem = new MemoryConfiguration();
+        mem.setPageSize(PAGE_SIZE);
+        mem.setPageCacheSize(PAGE_CACHE_SIZE);
+        cfg.setMemoryConfiguration(mem);
+
+        CacheConfiguration[] ccfgs = new CacheConfiguration[CACHE_COUNT];
+        for (int i = 0; i < CACHE_COUNT; ++i) {
+            CacheConfiguration ccfg = new CacheConfiguration();
+            ccfg.setName(CACHE_PREFIX + i);
+            ccfg.setAtomicityMode(CacheAtomicityMode.ATOMIC);
+            ccfg.setCacheMode(CacheMode.PARTITIONED);
+            ccfgs[i] = ccfg;
+        }
+        cfg.setCacheConfiguration(ccfgs);
+
+        return cfg;
+    }
+
+    /**  */
+    public void testEntryUpdate() throws Exception {
+        try (Ignite ignite = startGrid()) {
+            for (int i = 0; i < CACHE_COUNT; ++i) {
+                IgniteCache<Long, byte[]> cache = ignite.cache(CACHE_PREFIX + i);
+                cache.put(0L, new byte[PAGE_SIZE * 2]);
+            }
+            cacheUpdate.set(true);
+            IgniteCompute compute = ignite.compute().withAsync();
+            for (int i = 0; i < THREAD_COUNT; ++i)
+                compute.run(new CacheUpdater());
+            try {
+                long deadline = System.currentTimeMillis() + WAIT_TIMEOUT;
+                while (true)
+                    synchronized (this) {
+                        if (outOfMemoryEx != null)
+                            throw outOfMemoryEx;
+                        long timeout = deadline - System.currentTimeMillis();
+                        if (timeout <= 0)
+                            break;
+                        wait(timeout);
+                    }
+            }
+            finally {
+                cacheUpdate.set(false);
+            }
+        }
+    }
+
+    /**  */
+    private synchronized void setOutOfMemoryEx(OutOfMemoryException e) {
+        outOfMemoryEx = e;
+        notifyAll();
+    }
+
+    /**  */
+    public static class EntryUpdater implements CacheEntryProcessor<Long, byte[], Void> {
+
+        /**  */
+        public static final EntryUpdater INSTANCE = new EntryUpdater();
+
+        /** {@inheritDoc} */
+        @Override public Void process(MutableEntry<Long, byte[]> entry, Object... arguments)
+            throws EntryProcessorException {
+
+            entry.setValue(new byte[PAGE_SIZE]);
+            return null;
+        }
+    }
+
+    /**  */
+    public class CacheUpdater implements IgniteRunnable {
+
+        /**  */
+        @IgniteInstanceResource
+        public transient Ignite ignite;
+
+        /** {@inheritDoc} */
+        @Override public void run() {
+            try {
+                while (cacheUpdate.get())
+                    for (int i = 0; i < CACHE_COUNT; ++i) {
+                        IgniteCache<Long, byte[]> cache = ignite.cache(CACHE_PREFIX + i);
+                        cache.invoke(0L, EntryUpdater.INSTANCE);
+                    }
+            }
+            catch (Throwable ex) {
+                OutOfMemoryException e = findOutOfMemoryException(ex);
+                if (e != null)
+                    setOutOfMemoryEx(e);
+                else
+                    ignite.log().error("CacheUpdater failed", ex);
+            }
+        }
+
+        /**  */
+        private OutOfMemoryException findOutOfMemoryException(Throwable ex) {
+            if (ex instanceof OutOfMemoryException)
+                return (OutOfMemoryException)ex;
+            for (Throwable s : ex.getSuppressed()) {
+                OutOfMemoryException e = findOutOfMemoryException(s);
+                if (e != null)
+                    return e;
+            }
+            if (ex.getCause() != null) {
+                OutOfMemoryException e = findOutOfMemoryException(ex.getCause());
+                if (e != null)
+                    return e;
+            }
+            return null;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/869089db/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite.java
index 1cf2c14..efa3225 100755
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite.java
@@ -22,6 +22,7 @@ import junit.framework.TestSuite;
 import org.apache.ignite.GridCacheAffinityBackupsSelfTest;
 import org.apache.ignite.IgniteCacheAffinitySelfTest;
 import org.apache.ignite.cache.IgniteWarmupClosureSelfTest;
+import org.apache.ignite.cache.LargeEntryUpdateTest;
 import org.apache.ignite.cache.affinity.AffinityClientNodeSelfTest;
 import org.apache.ignite.cache.affinity.AffinityHistoryCleanupTest;
 import org.apache.ignite.cache.affinity.fair.FairAffinityDynamicCacheSelfTest;
@@ -229,6 +230,8 @@ public class IgniteCacheTestSuite extends TestSuite {
         // Warmup closure tests.
         suite.addTestSuite(IgniteWarmupClosureSelfTest.class);
 
+        suite.addTestSuite(LargeEntryUpdateTest.class);
+
         // Swap tests.
         suite.addTestSuite(GridCacheSwapPreloadSelfTest.class);