GG-11044 - Implement page evictions from PageMemory for the case when data size is bigger than allocated memory.
Fix. Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/99915a6d Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/99915a6d Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/99915a6d Branch: refs/heads/ignite-db-x-10884 Commit: 99915a6d8e22e01eff4244bc56b2be5be033bb7e Parents: d2fedf6 Author: dkarachentsev <[email protected]> Authored: Fri Apr 22 16:51:10 2016 +0300 Committer: dkarachentsev <[email protected]> Committed: Fri Apr 22 16:51:10 2016 +0300 ---------------------------------------------------------------------- .../internal/pagemem/impl/PageMemoryImpl.java | 58 ++++++++++++++++++-- 1 file changed, 52 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/99915a6d/modules/core/src/main/java/org/apache/ignite/internal/pagemem/impl/PageMemoryImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/impl/PageMemoryImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/impl/PageMemoryImpl.java index 62a4e72..5ee8bf3 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/impl/PageMemoryImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/impl/PageMemoryImpl.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; +import java.util.BitSet; import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -944,11 +945,13 @@ public class PageMemoryImpl implements PageMemory { final int cap = seg.loadedPages.capacity(); - assert seg.loadedPages.size() >= RANDOM_PAGES_EVICT_NUM; - if (seg.acquiredPages.size() >= seg.loadedPages.size()) throw new OutOfMemoryException("No not acquired pages left for segment. Unable to evict."); + // With big number of random picked pages we may fall into infinite loop, because + // every time the same page may be found. + SimpleLongSet ignored = null; + while (true) { for (int i = 0; i < RANDOM_PAGES_EVICT_NUM; i++) { // We need to lookup for pages only in current segment for thread safety, @@ -958,7 +961,10 @@ public class PageMemoryImpl implements PageMemory { assert addr != INVALID_REL_PTR; - pageRelAddrs[i] = addr; + if (ignored != null && ignored.contains(addr)) + i--; + else + pageRelAddrs[i] = addr; } final long relEvictAddr = findSuitablePageRelAddr(pageRelAddrs); @@ -967,16 +973,31 @@ public class PageMemoryImpl implements PageMemory { final long absEvictAddr = absolute(relEvictAddr); - assert absEvictAddr != dbMetaPageIdPtr; - final FullPageId fullPageId = readFullPageId(absEvictAddr); + final long metaPageId = mem.readLong(dbMetaPageIdPtr); + + if (fullPageId.pageId() == metaPageId && fullPageId.cacheId() == 0) { + if (ignored == null) + ignored = new SimpleLongSet(); + + ignored.add(relEvictAddr); + + continue; + } + assert seg.writeLock().isHeldByCurrentThread(); if (!seg.acquiredPages.containsKey(fullPageId)) seg.loadedPages.remove(fullPageId); - else + else { + if (ignored == null) + ignored = new SimpleLongSet(); + + ignored.add(relEvictAddr); + continue; + } // Force flush data and free page. if (isDirty(absEvictAddr)) { @@ -1039,6 +1060,31 @@ public class PageMemoryImpl implements PageMemory { } /** + * Long set based on BitSet. + */ + private static class SimpleLongSet { + /** */ + final BitSet bitSet = new BitSet(); + + /** + * Add value to set. + * + * @param val Value. + */ + void add(final long val) { + bitSet.set((int)(val % Integer.MAX_VALUE)); + } + + /** + * @param val Value to check. + * @return {@code True} if set contains value. + */ + boolean contains(final long val) { + return bitSet.get((int)(val % Integer.MAX_VALUE)); + } + } + + /** * */ private class Segment extends ReentrantReadWriteLock {
