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();