Repository: ignite
Updated Branches:
  refs/heads/ignite-2.1 a668a224a -> e786beb64


GG-12449 - Fix eviction and checkpoint write race - Fixes #2277.

Signed-off-by: Alexey Goncharuk <alexey.goncha...@gmail.com>


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

Branch: refs/heads/ignite-2.1
Commit: 704032d942bb0412607b7cfcb2c4378429e85649
Parents: a668a22
Author: Dmitriy Govorukhin <dmitriy.govoruk...@gmail.com>
Authored: Tue Jul 11 11:56:22 2017 +0300
Committer: Alexey Goncharuk <alexey.goncha...@gmail.com>
Committed: Tue Jul 11 11:56:22 2017 +0300

----------------------------------------------------------------------
 .../persistence/pagemem/PageMemoryImpl.java     | 86 ++++++++------------
 .../cache/persistence/wal/FileInput.java        |  3 +
 2 files changed, 35 insertions(+), 54 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/704032d9/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImpl.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImpl.java
index ab6619d..e4428a2 100755
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImpl.java
@@ -646,7 +646,6 @@ public class PageMemoryImpl implements PageMemoryEx {
 
             PageHeader.tempBufferPointer(absPtr, INVALID_REL_PTR);
             PageHeader.dirty(absPtr, false);
-            PageHeader.tempDirty(absPtr, false);
 
             // We pinned the page when allocated the temp buffer, release it 
now.
             PageHeader.releasePage(absPtr);
@@ -868,13 +867,9 @@ public class PageMemoryImpl implements PageMemoryEx {
             finally {
                 seg.writeLock().unlock();
             }
-
-        }
-        else {
-            copyPageForCheckpoint(absPtr, fullId, tmpBuf, tracker);
-
-            return tag;
         }
+        else
+            return copyPageForCheckpoint(absPtr, fullId, tmpBuf, tracker) ? 
tag : null;
     }
 
     /**
@@ -882,51 +877,51 @@ public class PageMemoryImpl implements PageMemoryEx {
      * @param fullId Full id.
      * @param tmpBuf Tmp buffer.
      */
-    private void copyPageForCheckpoint(long absPtr, FullPageId fullId, 
ByteBuffer tmpBuf, CheckpointMetricsTracker tracker) {
+    private boolean copyPageForCheckpoint(long absPtr, FullPageId fullId, 
ByteBuffer tmpBuf, CheckpointMetricsTracker tracker) {
         assert absPtr != 0;
 
-        long tmpRelPtr;
-
         rwLock.writeLock(absPtr + PAGE_LOCK_OFFSET, 
OffheapReadWriteLock.TAG_LOCK_ALWAYS);
 
         try {
-            tmpRelPtr = PageHeader.tempBufferPointer(absPtr);
+            long tmpRelPtr = PageHeader.tempBufferPointer(absPtr);
 
-            clearCheckpoint(fullId);
+            if (!clearCheckpoint(fullId)){
+                assert tmpRelPtr == INVALID_REL_PTR;
 
-            if (tmpRelPtr != INVALID_REL_PTR)
+                return false;
+            }
+
+            if (tmpRelPtr != INVALID_REL_PTR){
                 PageHeader.tempBufferPointer(absPtr, INVALID_REL_PTR);
+
+                long tmpAbsPtr = checkpointPool.absolute(tmpRelPtr);
+
+                copyInBuffer(tmpAbsPtr, tmpBuf);
+
+                GridUnsafe.setMemory(tmpAbsPtr + PAGE_OVERHEAD, pageSize(), 
(byte)0);
+
+                if (tracker != null)
+                    tracker.onCowPageWritten();
+
+                checkpointPool.releaseFreePage(tmpRelPtr);
+
+                // We pinned the page when allocated the temp buffer, release 
it now.
+                PageHeader.releasePage(absPtr);
+            }
             else {
                 copyInBuffer(absPtr, tmpBuf);
 
                 PageHeader.dirty(absPtr, false);
 
+                // We pinned the page when resolve abs pointer.
                 PageHeader.releasePage(absPtr);
-
-                return;
             }
+
+            return true;
         }
         finally {
             rwLock.writeUnlock(absPtr + PAGE_LOCK_OFFSET, 
OffheapReadWriteLock.TAG_LOCK_ALWAYS);
         }
-
-        assert tmpRelPtr != 0;
-
-        long tmpAbsPtr = checkpointPool.absolute(tmpRelPtr);
-
-        copyInBuffer(tmpAbsPtr, tmpBuf);
-
-        GridUnsafe.setMemory(tmpAbsPtr + PAGE_OVERHEAD, pageSize(), (byte)0);
-
-        PageHeader.dirty(tmpAbsPtr, false);
-
-        if (tracker != null)
-            tracker.onCowPageWritten();
-
-        checkpointPool.releaseFreePage(tmpRelPtr);
-
-        // We pinned the page when allocated the temp buffer, release it now.
-        PageHeader.releasePage(absPtr);
     }
 
     /**
@@ -1146,8 +1141,6 @@ public class PageMemoryImpl implements PageMemoryEx {
 
             long tmpAbsPtr = checkpointPool.absolute(tmpRelPtr);
 
-            assert !PageHeader.tempDirty(tmpAbsPtr);
-
             GridUnsafe.copyMemory(
                 null,
                 absPtr + PAGE_OVERHEAD,
@@ -1254,15 +1247,16 @@ public class PageMemoryImpl implements PageMemoryEx {
 
     /**
      * @param fullPageId Page ID to clear.
+     * @return {@code True} if remove successfully.
      */
-    void clearCheckpoint(FullPageId fullPageId) {
+    boolean clearCheckpoint(FullPageId fullPageId) {
         Segment seg = segment(fullPageId.groupId(), fullPageId.pageId());
 
         Collection<FullPageId> pages0 = seg.segCheckpointPages;
 
         assert pages0 != null;
 
-        pages0.remove(fullPageId);
+        return pages0.remove(fullPageId);
     }
 
     /**
@@ -1655,6 +1649,7 @@ public class PageMemoryImpl implements PageMemoryEx {
 
             if (isDirty(absPtr)) {
                 // Can evict a dirty page only if should be written by a 
checkpoint.
+                // These pages does not have tmp buffer.
                 if (cpPages != null && cpPages.contains(fullPageId)) {
                     assert storeMgr != null;
 
@@ -2028,23 +2023,6 @@ public class PageMemoryImpl implements PageMemoryEx {
 
         /**
          * @param absPtr Absolute pointer.
-         * @return Dirty flag.
-         */
-        private static boolean tempDirty(long absPtr) {
-            return flag(absPtr, TMP_DIRTY_FLAG);
-        }
-
-        /**
-         * @param absPtr Absolute pointer.
-         * @param tmpDirty Temp dirty flag.
-         * @return Previous value of temp dirty flag.
-         */
-        private static boolean tempDirty(long absPtr, boolean tmpDirty) {
-            return flag(absPtr, TMP_DIRTY_FLAG, tmpDirty);
-        }
-
-        /**
-         * @param absPtr Absolute pointer.
          * @param flag Flag mask.
          * @return Flag value.
          */

http://git-wip-us.apache.org/repos/asf/ignite/blob/704032d9/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FileInput.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FileInput.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FileInput.java
index 6443a7c..74edbfa 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FileInput.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FileInput.java
@@ -102,6 +102,9 @@ public final class FileInput implements 
ByteBufferBackedDataInput {
             return;
 
         if (buf.capacity() < requested) {
+            if (expBuf == null)
+                throw new IOException("Requested size is greater than buffer: 
" + requested);
+
             buf = expBuf.expand(requested);
 
             assert available == buf.remaining();

Reply via email to