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

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/d83f1ec0
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/d83f1ec0
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/d83f1ec0

Branch: refs/heads/ignite-2.5
Commit: d83f1ec0a4d010e57fecc12ffd3d1f8346ded61c
Parents: 8401fe6
Author: dpavlov <[email protected]>
Authored: Thu May 3 18:26:49 2018 +0300
Committer: Andrey Gura <[email protected]>
Committed: Mon May 7 17:22:41 2018 +0300

----------------------------------------------------------------------
 .../persistence/pagemem/DelayedDirtyPageWrite.java  |  6 +++---
 .../pagemem/DelayedPageReplacementTracker.java      | 16 +++++++---------
 .../internal/MemoryLeaksOnRestartNodeTest.java      |  3 ---
 3 files changed, 10 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/d83f1ec0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/DelayedDirtyPageWrite.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/DelayedDirtyPageWrite.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/DelayedDirtyPageWrite.java
index 6eec609..b08ddc2 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/DelayedDirtyPageWrite.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/DelayedDirtyPageWrite.java
@@ -24,9 +24,9 @@ import org.apache.ignite.internal.util.GridUnsafe;
 import org.jetbrains.annotations.Nullable;
 
 /**
- * Not thread safe and stateful class for replacement of one page with write() 
delay. This allows to write page content
- * without holding segment lock. Page data is copied into temp buffer during 
{@link #writePage(FullPageId, ByteBuffer,
- * int)} and then sent to real implementation by {@link #finishReplacement()}.
+ * Not thread safe and stateful class for page replacement of one page with 
write() delay. This allows to write page
+ * content without holding segment lock. Page data is copied into temp buffer 
during {@link #writePage(FullPageId,
+ * ByteBuffer, int)} and then sent to real implementation by {@link 
#finishReplacement()}.
  */
 public class DelayedDirtyPageWrite implements ReplacedPageWriter {
     /** Real flush dirty page implementation. */

http://git-wip-us.apache.org/repos/asf/ignite/blob/d83f1ec0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/DelayedPageReplacementTracker.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/DelayedPageReplacementTracker.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/DelayedPageReplacementTracker.java
index 9cf5b77..aa1b061 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/DelayedPageReplacementTracker.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/DelayedPageReplacementTracker.java
@@ -21,6 +21,8 @@ import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.util.Collection;
 import java.util.HashSet;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 import org.apache.ignite.IgniteInterruptedException;
 import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.internal.pagemem.FullPageId;
@@ -56,15 +58,10 @@ public class DelayedPageReplacementTracker {
 
     /**
      * Dirty page write for replacement operations thread local. Because page 
write {@link DelayedDirtyPageWrite} is
-     * stateful and not thread safe, this thread local protects from GC 
pressure on pages replacement.
+     * stateful and not thread safe, this thread local protects from GC 
pressure on pages replacement. <br> Map is used
+     * instead of build-in thread local to allow GC to remove delayed writers 
for alive threads after node stop.
      */
-    private final ThreadLocal<DelayedDirtyPageWrite> delayedPageWriteThreadLoc
-        = new ThreadLocal<DelayedDirtyPageWrite>() {
-        @Override protected DelayedDirtyPageWrite initialValue() {
-            return new DelayedDirtyPageWrite(flushDirtyPage, byteBufThreadLoc, 
pageSize,
-                DelayedPageReplacementTracker.this);
-        }
-    };
+    private final Map<Long, DelayedDirtyPageWrite> 
delayedPageWriteThreadLocMap = new ConcurrentHashMap<>();
 
     /**
      * @param pageSize Page size.
@@ -87,7 +84,8 @@ public class DelayedPageReplacementTracker {
      * @return delayed page write implementation, finish method to be called 
to actually write page.
      */
     public DelayedDirtyPageWrite delayedPageWrite() {
-        return delayedPageWriteThreadLoc.get();
+        return 
delayedPageWriteThreadLocMap.computeIfAbsent(Thread.currentThread().getId(),
+            id -> new DelayedDirtyPageWrite(flushDirtyPage, byteBufThreadLoc, 
pageSize, this));
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/d83f1ec0/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
index 56ab091..df055fe 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/MemoryLeaksOnRestartNodeTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/MemoryLeaksOnRestartNodeTest.java
@@ -18,7 +18,6 @@
 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;
@@ -76,8 +75,6 @@ public class MemoryLeaksOnRestartNodeTest extends 
GridCommonAbstractTest {
      * @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);

Reply via email to