Repository: ignite
Updated Branches:
  refs/heads/master 45698810a -> 83b5c0e0a


IGNITE-8347 Test of Memory leaks on restart Ignite node with enabled 
persistence at ThreadLocal. - Fixes #3889.

Signed-off-by: dpavlov <[email protected]>


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

Branch: refs/heads/master
Commit: 83b5c0e0ae493247dc9ba0db0e1014f6c38821aa
Parents: 4569881
Author: tledkov-gridgain <[email protected]>
Authored: Thu May 3 16:23:40 2018 +0300
Committer: dpavlov <[email protected]>
Committed: Thu May 3 16:23:40 2018 +0300

----------------------------------------------------------------------
 .../apache/ignite/internal/util/GridDebug.java  |  69 ++++++++++-
 .../internal/MemoryLeaksOnRestartNodeTest.java  | 118 +++++++++++++++++++
 2 files changed, 186 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/83b5c0e0/modules/core/src/main/java/org/apache/ignite/internal/util/GridDebug.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/util/GridDebug.java 
b/modules/core/src/main/java/org/apache/ignite/internal/util/GridDebug.java
index a8af0fb..2fa148e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/GridDebug.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/GridDebug.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.util;
 
+import com.sun.management.HotSpotDiagnosticMXBean;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
@@ -32,6 +33,7 @@ import java.util.Collection;
 import java.util.Date;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.atomic.AtomicReference;
+import javax.management.MBeanServer;
 import org.apache.ignite.internal.util.typedef.X;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgnitePredicate;
@@ -67,7 +69,13 @@ public class GridDebug {
     /** */
     private static boolean allowLog;
 
-    /** */
+    /** This is the name of the HotSpot Diagnostic MBean */
+    private static final String HOTSPOT_BEAN_NAME = 
"com.sun.management:type=HotSpotDiagnostic";
+
+    /** field to store the hotspot diagnostic MBean */
+    private static volatile HotSpotDiagnosticMXBean hotspotMBean;
+
+    /* */
     static {
         if (LOGS_PATH != null) {
             File log = new File(new File(LOGS_PATH), new 
SimpleDateFormat("yyyy-MM-dd_HH-mm-ss-").format(new Date()) +
@@ -303,6 +311,65 @@ public class GridDebug {
     }
 
     /**
+     * Call this method from your application whenever you
+     * want to dump the heap snapshot into a file.
+     *
+     * @param fileName name of the heap dump file
+     * @param live flag that tells whether to dump
+     * only the live objects
+     */
+    public static void dumpHeap(String fileName, boolean live) {
+        // initialize hotspot diagnostic MBean
+        initHotspotMBean();
+
+        File f = new File(fileName);
+
+        if (f.exists())
+            f.delete();
+
+        try {
+            hotspotMBean.dumpHeap(fileName, live);
+        }
+        catch (RuntimeException re) {
+            throw re;
+        }
+        catch (Exception exp) {
+            throw new RuntimeException(exp);
+        }
+    }
+
+    /**
+     * Initialize the hotspot diagnostic MBean field
+     */
+    private static void initHotspotMBean() {
+        if (hotspotMBean == null) {
+            synchronized (GridDebug.class) {
+                if (hotspotMBean == null)
+                    hotspotMBean = getHotspotMBean();
+            }
+        }
+    }
+
+    /**
+     * Gets the hotspot diagnostic MBean from the platform MBean server
+     * @return Diagnostic bean.
+     */
+    private static HotSpotDiagnosticMXBean getHotspotMBean() {
+        try {
+            MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+
+            HotSpotDiagnosticMXBean bean = 
ManagementFactory.newPlatformMXBeanProxy(server,
+                HOTSPOT_BEAN_NAME, HotSpotDiagnosticMXBean.class);
+
+            return bean;
+        } catch (RuntimeException re) {
+            throw re;
+        } catch (Exception exp) {
+            throw new RuntimeException(exp);
+        }
+    }
+
+    /**
      * Debug info queue item.
      */
     @SuppressWarnings({"PublicInnerClass", "PublicField"})

http://git-wip-us.apache.org/repos/asf/ignite/blob/83b5c0e0/modules/core/src/test/java/org/apache/ignite/internal/MemoryLeaksOnRestartNodeTest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/MemoryLeaksOnRestartNodeTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/MemoryLeaksOnRestartNodeTest.java
new file mode 100644
index 0000000..56ab091
--- /dev/null
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/MemoryLeaksOnRestartNodeTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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 java.io.File;
+import org.apache.ignite.IgniteSystemProperties;
+import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.DataStorageConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.util.GridDebug;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+/**
+ * Tests leaks on node restart with enabled persistence.
+ */
+public class MemoryLeaksOnRestartNodeTest extends GridCommonAbstractTest {
+    /** Heap dump file name. */
+    private static final String HEAP_DUMP_FILE_NAME = "test.hprof";
+
+    /** Restarts count. */
+    private static final int RESTARTS = 10;
+
+    /** Nodes count. */
+    private static final int NODES = 3;
+
+    /** Allow 5Mb leaks on node restart. */
+    private static final int ALLOW_LEAK_ON_RESTART_IN_MB = 1;
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String 
igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        cfg.setDataStorageConfiguration(new DataStorageConfiguration()
+            .setDefaultDataRegionConfiguration(
+                new 
DataRegionConfiguration().setName("mem0").setPersistenceEnabled(false))
+            .setDataRegionConfigurations(
+                new 
DataRegionConfiguration().setName("disk").setPersistenceEnabled(true),
+                new 
DataRegionConfiguration().setName("mem2").setPersistenceEnabled(false)));
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        cleanPersistenceDir();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+
+        cleanPersistenceDir();
+
+        super.afterTestsStopped();
+    }
+
+    /**
+     * @throws Exception On failed.
+     */
+    public void test() throws Exception {
+        
System.setProperty(IgniteSystemProperties.IGNITE_DELAYED_REPLACED_PAGE_WRITE, 
"false");
+
+        // Warmup
+        for (int i = 0; i < RESTARTS / 2; ++i) {
+            startGrids(NODES);
+
+            U.sleep(500);
+
+            stopAllGrids();
+        }
+
+        GridDebug.dumpHeap(HEAP_DUMP_FILE_NAME, true);
+
+        File dumpFile = new File(HEAP_DUMP_FILE_NAME);
+
+        final long size0 = dumpFile.length();
+
+        // Restarts
+        for (int i = 0; i < RESTARTS; ++i) {
+            startGrids(NODES);
+
+            U.sleep(500);
+
+            stopAllGrids();
+
+            GridDebug.dumpHeap(HEAP_DUMP_FILE_NAME, true);
+        }
+
+        GridDebug.dumpHeap(HEAP_DUMP_FILE_NAME, true);
+
+        final float leakSize = (float)(dumpFile.length() - size0) / 1024 / 
1024 / NODES / RESTARTS;
+
+        assertTrue("Possible leaks detected. The " + leakSize + "M leaks per 
node restart after " + RESTARTS
+                + " restarts. See the '" + dumpFile.getAbsolutePath() + "'",
+            leakSize < ALLOW_LEAK_ON_RESTART_IN_MB);
+
+        // Remove dump if successful.
+        dumpFile.delete();
+   }
+}
\ No newline at end of file

Reply via email to