Repository: ignite Updated Branches: refs/heads/ignite-2.5 1cea80d29 -> 37fc72542
IGNITE-8049 Limit the number of operation cycles in B+Tree - Fixes #3769. Signed-off-by: dpavlov <[email protected]> (cherry picked from commit e491f10) Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/37fc7254 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/37fc7254 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/37fc7254 Branch: refs/heads/ignite-2.5 Commit: 37fc72542eb6baa8be8b41aecd08a194102d13c1 Parents: 1cea80d Author: ÐлекÑей СÑелÑмак <[email protected]> Authored: Fri Apr 6 18:28:22 2018 +0300 Committer: dpavlov <[email protected]> Committed: Fri Apr 6 18:39:28 2018 +0300 ---------------------------------------------------------------------- .../apache/ignite/IgniteSystemProperties.java | 5 +++ .../cache/persistence/tree/BPlusTree.java | 41 +++++++++++++++++++- .../processors/database/BPlusTreeSelfTest.java | 29 ++++++++++++++ 3 files changed, 74 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/37fc7254/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java index f7128c0..152d845 100644 --- a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java +++ b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java @@ -845,6 +845,11 @@ public final class IgniteSystemProperties { public static final String IGNITE_READ_LOAD_BALANCING = "IGNITE_READ_LOAD_BALANCING"; /** + * Number of repetitions to capture a lock in the B+Tree. + */ + public static final String IGNITE_BPLUS_TREE_LOCK_RETRIES = "IGNITE_BPLUS_TREE_LOCK_RETRIES"; + + /** * Enforces singleton. */ private IgniteSystemProperties() { http://git-wip-us.apache.org/repos/asf/ignite/blob/37fc7254/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 a520dce..4d05095 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 @@ -27,6 +27,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteException; +import org.apache.ignite.IgniteSystemProperties; import org.apache.ignite.internal.IgniteInterruptedCheckedException; import org.apache.ignite.internal.pagemem.PageIdUtils; import org.apache.ignite.internal.pagemem.PageMemory; @@ -87,6 +88,13 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements private static volatile boolean interrupted; /** */ + private static final int IGNITE_BPLUS_TREE_LOCK_RETRIES_DEFAULT = 1000; + + /** */ + private static final int LOCK_RETRIES = IgniteSystemProperties.getInteger( + IgniteSystemProperties.IGNITE_BPLUS_TREE_LOCK_RETRIES, IGNITE_BPLUS_TREE_LOCK_RETRIES_DEFAULT); + + /** */ private final AtomicBoolean destroyed = new AtomicBoolean(false); /** */ @@ -1123,6 +1131,8 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements try { for (;;) { + g.checkLockRetry(); + // Init args. g.pageId = pageId; g.fwdId = fwdId; @@ -1657,13 +1667,18 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements long page = acquirePage(pageId); try { + Result res = RETRY; + for (;;) { + if (res == RETRY) + x.checkLockRetry(); + // Init args. x.pageId(pageId); x.fwdId(fwdId); x.backId(backId); - Result res = read(pageId, page, search, x, lvl, RETRY); + res = read(pageId, page, search, x, lvl, RETRY); switch (res) { case GO_DOWN_X: @@ -1813,6 +1828,8 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements try { for (;;) { + r.checkLockRetry(); + // Init args. r.pageId = pageId; r.fwdId = fwdId; @@ -2310,6 +2327,8 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements try { for (;;) { + p.checkLockRetry(); + // Init args. p.pageId = pageId; p.fwdId = fwdId; @@ -2422,6 +2441,9 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements /** Ignore row passed, find last row */ boolean findLast; + /** Number of repetitions to capture a lock in the B+Tree (countdown). */ + int lockRetriesCnt = getLockRetries(); + /** * @param row Row. * @param findLast find last row. @@ -2534,6 +2556,16 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements boolean isFinished() { throw new IllegalStateException(); } + + /** + * @throws IgniteCheckedException If the operation can not be retried. + */ + final void checkLockRetry() throws IgniteCheckedException { + if (lockRetriesCnt == 0) + throw new IgniteCheckedException("Maximum of retries " + getLockRetries() + " reached."); + + lockRetriesCnt--; + } } /** @@ -4911,4 +4943,11 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements public boolean apply(BPlusTree<L, T> tree, BPlusIO<L> io, long pageAddr, int idx) throws IgniteCheckedException; } + + /** + * @return Return number of retries. + */ + protected int getLockRetries() { + return LOCK_RETRIES; + } } http://git-wip-us.apache.org/repos/asf/ignite/blob/37fc7254/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeSelfTest.java index 72d2e0f..83d0ddd 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/BPlusTreeSelfTest.java @@ -230,6 +230,26 @@ public class BPlusTreeSelfTest extends GridCommonAbstractTest { /** * @throws IgniteCheckedException If failed. */ + public void testRetries() throws IgniteCheckedException { + TestTree tree = createTestTree(true); + + tree.numRetries = 1; + + long size = CNT * CNT; + + try { + for (long i = 1; i <= size; i++) + tree.put(i); + + fail(); + } + catch (IgniteCheckedException ignored) { + } + } + + /** + * @throws IgniteCheckedException If failed. + */ public void _testBenchInvoke() throws IgniteCheckedException { MAX_PER_PAGE = 10; @@ -2349,6 +2369,9 @@ public class BPlusTreeSelfTest extends GridCommonAbstractTest { /** */ private static ConcurrentMap<Object, Map<Long, Long>> writeLocks = new ConcurrentHashMap<>(); + /** Number of retries. */ + private int numRetries = super.getLockRetries(); + /** * @param reuseList Reuse list. * @param canGetRow Can get row from inner page. @@ -2536,6 +2559,12 @@ public class BPlusTreeSelfTest extends GridCommonAbstractTest { return b.toString(); } + + /** {@inheritDoc} */ + @Override + protected int getLockRetries() { + return numRetries; + } } /**
