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:52 UTC

[31/43] ignite git commit: IGNITE-4712 Memory leaks in PageMemory

IGNITE-4712 Memory leaks in PageMemory


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

Branch: refs/heads/ignite-4712
Commit: b3d78b5c4ac8142d443b15af96c64c9fa20f5b43
Parents: 5e11f5d
Author: Igor Seliverstov <gv...@gmail.com>
Authored: Mon Feb 20 16:19:00 2017 +0300
Committer: Igor Seliverstov <gv...@gmail.com>
Committed: Wed Mar 1 10:44:54 2017 +0300

----------------------------------------------------------------------
 .../cache/database/freelist/PagesList.java      | 44 +++++++++++++-------
 1 file changed, 28 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/b3d78b5c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/PagesList.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/PagesList.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/PagesList.java
index c03f432..1f537b6 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/PagesList.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/freelist/PagesList.java
@@ -22,6 +22,7 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteSystemProperties;
 import org.apache.ignite.internal.pagemem.Page;
@@ -76,7 +77,7 @@ public abstract class PagesList extends DataStructure {
             Math.min(8, Runtime.getRuntime().availableProcessors() * 2));
 
     /** */
-    protected final LongAdder8[] bucketsSize;
+    protected final AtomicLong[] bucketsSize;
 
     /** Page ID to store list metadata. */
     private final long metaPageId;
@@ -114,7 +115,7 @@ public abstract class PagesList extends DataStructure {
 
             return TRUE;
         }
-    };
+    }
 
     /**
      * @param cacheId Cache ID.
@@ -139,10 +140,10 @@ public abstract class PagesList extends DataStructure {
         this.buckets = buckets;
         this.metaPageId = metaPageId;
 
-        bucketsSize = new LongAdder8[buckets];
+        bucketsSize = new AtomicLong[buckets];
 
         for (int i = 0; i < buckets; i++)
-            bucketsSize[i] = new LongAdder8();
+            bucketsSize[i] = new AtomicLong();
     }
 
     /**
@@ -421,6 +422,7 @@ public abstract class PagesList extends DataStructure {
             else {
                 // It is safe to assign new tail since we do it only when write lock on tail is held.
                 tails[idx].tailId = newTailId;
+                tails[idx].empty = false;
 
                 return true;
             }
@@ -597,7 +599,7 @@ public abstract class PagesList extends DataStructure {
         if (idx == -1)
             handlePageFull(pageId, page, pageAddr, io, dataPage, dataPageAddr, bucket);
         else {
-            bucketsSize[bucket].increment();
+            bucketsSize[bucket].incrementAndGet();
 
             if (isWalDeltaRecordNeeded(wal, page))
                 wal.log(new PagesListAddPageRecord(cacheId, pageId, dataPageId));
@@ -691,7 +693,7 @@ public abstract class PagesList extends DataStructure {
 
                     assert idx != -1;
 
-                    bucketsSize[bucket].increment();
+                    bucketsSize[bucket].incrementAndGet();
 
                     dataIO.setFreeListPageId(dataPageAddr, nextId);
 
@@ -781,7 +783,7 @@ public abstract class PagesList extends DataStructure {
                     }
                 }
                 else {
-                    bucketsSize[bucket].increment();
+                    bucketsSize[bucket].incrementAndGet();
 
                     // TODO: use single WAL record for bag?
                     if (isWalDeltaRecordNeeded(wal, page))
@@ -810,7 +812,7 @@ public abstract class PagesList extends DataStructure {
     private Stripe getPageForTake(int bucket) {
         Stripe[] tails = getBucket(bucket);
 
-        if (tails == null)
+        if (tails == null || bucketsSize[bucket].get() == 0)
             return null;
 
         int len = tails.length;
@@ -893,6 +895,16 @@ public abstract class PagesList extends DataStructure {
                     continue;
                 }
 
+                if(!isReuseBucket(bucket) && stripe.empty) {
+                    // Another thread took the last page
+                    writeUnlock(tail, tailPageAddr, false);
+
+                    if(bucketsSize[bucket].get() > 0)
+                        continue;
+                    else
+                        return 0L;
+                }
+
                 assert PageIO.getPageId(tailPageAddr) == tailId : "tailId = " + tailId + ", tailPageId = " + PageIO.getPageId(tailPageAddr);
                 assert PageIO.getType(tailPageAddr) == PageIO.T_PAGE_LIST_NODE;
 
@@ -909,7 +921,7 @@ public abstract class PagesList extends DataStructure {
                     long pageId = io.takeAnyPage(tailPageAddr);
 
                     if (pageId != 0L) {
-                        bucketsSize[bucket].decrement();
+                        bucketsSize[bucket].decrementAndGet();
 
                         if (isWalDeltaRecordNeeded(wal, tail))
                             wal.log(new PagesListRemovePageRecord(cacheId, tailId, pageId));
@@ -918,9 +930,13 @@ public abstract class PagesList extends DataStructure {
 
                         ret = pageId;
 
+                        boolean empty = io.isEmpty(tailPageAddr);
+
+                        stripe.empty = empty;
+
                         // If we got an empty page in non-reuse bucket, move it back to reuse list
                         // to prevent empty page leak to data pages.
-                        if (io.isEmpty(tailPageAddr) && !isReuseBucket(bucket)) {
+                        if (empty && !isReuseBucket(bucket)) {
                             long prevId = io.getPreviousId(tailPageAddr);
 
                             if (prevId != 0L) {
@@ -969,12 +985,8 @@ public abstract class PagesList extends DataStructure {
 
                             ret = tailId;
                         }
-                        else {
+                        else
                             stripe.empty = true;
-
-                            if (bucketsSize[bucket].sum() > 0)
-                                continue;
-                        }
                     }
 
                     // If we do not have a previous page (we are at head), then we still can return
@@ -1034,7 +1046,7 @@ public abstract class PagesList extends DataStructure {
                 if (!rmvd)
                     return false;
 
-                bucketsSize[bucket].decrement();
+                bucketsSize[bucket].decrementAndGet();
 
                 if (isWalDeltaRecordNeeded(wal, page))
                     wal.log(new PagesListRemovePageRecord(cacheId, pageId, dataPageId));