Repository: ignite Updated Branches: refs/heads/master 5d63d7f44 -> e827b600b
IGNITE-9268 Fixed unreleased page lock when exception is thrown from BPlusTree - Fixes #4543. 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/e827b600 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/e827b600 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/e827b600 Branch: refs/heads/master Commit: e827b600b5262e24280dfe3498e8e329d62b1b03 Parents: 5d63d7f Author: Anton Kalashnikov <kaa....@yandex.ru> Authored: Fri Aug 17 15:45:43 2018 +0300 Committer: Alexey Goncharuk <alexey.goncha...@gmail.com> Committed: Fri Aug 17 17:26:18 2018 +0300 ---------------------------------------------------------------------- .../cache/persistence/tree/BPlusTree.java | 35 ++++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/e827b600/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java index 762013e..141b94f 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java @@ -2577,7 +2577,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements /** * @throws IgniteCheckedException If the operation can not be retried. */ - final void checkLockRetry() throws IgniteCheckedException { + void checkLockRetry() throws IgniteCheckedException { if (lockRetriesCnt == 0) { IgniteCheckedException e = new IgniteCheckedException("Maximum number of retries " + getLockRetries() + " reached for " + getClass().getSimpleName() + " operation " + @@ -2666,6 +2666,13 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements * Put operation. */ private final class Put extends Get { + /** Mark of NULL value of page id. It means valid value can't be equal this value. */ + private static final long NULL_PAGE_ID = 0L; + /** Mark of NULL value of page. */ + private static final long NULL_PAGE = 0L; + /** Mark of NULL value of page address. */ + private static final long NULL_PAGE_ADDRESS = 0L; + /** Right child page ID for split row. */ long rightId; @@ -2673,9 +2680,8 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements T oldRow; /** - * This page is kept locked after split until insert to the upper level will not be finished. - * It is needed because split row will be "in flight" and if we'll release tail, remove on - * split row may fail. + * This page is kept locked after split until insert to the upper level will not be finished. It is needed + * because split row will be "in flight" and if we'll release tail, remove on split row may fail. */ long tailId; @@ -2736,10 +2742,10 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements * @param tailPageAddr Tail page address */ private void tail(long tailId, long tailPage, long tailPageAddr) { - assert (tailId == 0L) == (tailPage == 0L); - assert (tailPage == 0L) == (tailPageAddr == 0L); + assert (tailId == NULL_PAGE_ID) == (tailPage == NULL_PAGE); + assert (tailPage == NULL_PAGE) == (tailPageAddr == NULL_PAGE_ADDRESS); - if (this.tailPage != 0L) + if (this.tailPage != NULL_PAGE) writeUnlockAndClose(this.tailId, this.tailPage, this.tailAddr, null); this.tailId = tailId; @@ -2749,7 +2755,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements /** {@inheritDoc} */ @Override boolean canRelease(long pageId, int lvl) { - return pageId != 0L && tailId != pageId; + return pageId != NULL_PAGE_ID && tailId != pageId; } /** @@ -2759,7 +2765,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements row = null; rightId = 0; - tail(0L, 0L, 0L); + tail(NULL_PAGE_ID, NULL_PAGE, NULL_PAGE_ADDRESS); } /** {@inheritDoc} */ @@ -2830,7 +2836,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements long fwdPageAddr = writeLock(fwdId, fwdPage); // Initial write, no need to check for concurrent modification. - assert fwdPageAddr != 0L; + assert fwdPageAddr != NULL_PAGE_ADDRESS; // TODO GG-11640 log a correct forward page record. final Boolean fwdPageWalPlc = Boolean.TRUE; @@ -2878,7 +2884,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements long newRootAddr = writeLock(newRootId, newRootPage); // Initial write. - assert newRootAddr != 0L; + assert newRootAddr != NULL_PAGE_ADDRESS; // Never write full new root page, because it is known to be new. final Boolean newRootPageWalPlc = Boolean.FALSE; @@ -2995,6 +3001,13 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements return write(pageId, page, replace, this, lvl, RETRY); } + + /** {@inheritDoc} */ + @Override void checkLockRetry() throws IgniteCheckedException { + //non null tailId means that lock on tail page still hold and we can't fail with exception. + if (tailId == NULL_PAGE_ID) + super.checkLockRetry(); + } } /**