Repository: ignite Updated Branches: refs/heads/master 28870dc71 -> 85f5309db
IGNITE-4989 Assertion error in BPlusTree#finishTail - Fixes #1894. Signed-off-by: Sergi Vladykin <sergi.vlady...@gmail.com> Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/85f5309d Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/85f5309d Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/85f5309d Branch: refs/heads/master Commit: 85f5309db0b12f3dc1c843463537518e05c0fd80 Parents: 28870dc Author: EdShangGG <eshangar...@gridgain.com> Authored: Wed May 3 15:07:54 2017 +0300 Committer: Sergi Vladykin <sergi.vlady...@gmail.com> Committed: Wed May 3 15:07:54 2017 +0300 ---------------------------------------------------------------------- .../cache/database/tree/BPlusTree.java | 6 +- .../processors/database/BPlusTreeSelfTest.java | 75 ++++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/85f5309d/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/BPlusTree.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/BPlusTree.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/BPlusTree.java index 648f35a..a4c09d5 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/BPlusTree.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/database/tree/BPlusTree.java @@ -443,6 +443,10 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements throws IgniteCheckedException { assert lvl == 0 : lvl; // Leaf. + // Check the triangle invariant. + if (io.getForward(leafAddr) != r.fwdId) + return RETRY; + final int cnt = io.getCount(leafAddr); assert cnt <= Short.MAX_VALUE: cnt; @@ -3384,7 +3388,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements if (tail.lvl == 0) { // At the bottom level we can't have a tail without a sibling, it means we have higher levels. - assert tail.sibling != null; + assert tail.sibling != null : tail; return NOT_FOUND; // Lock upper level, we are at the bottom now. } http://git-wip-us.apache.org/repos/asf/ignite/blob/85f5309d/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 0254c4c..a46242c 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 @@ -27,8 +27,10 @@ import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLongArray; +import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.Lock; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.configuration.MemoryPolicyConfiguration; @@ -1225,6 +1227,79 @@ public class BPlusTreeSelfTest extends GridCommonAbstractTest { } /** + * + */ + public void testConcurrentGrowDegenerateTreeAndConcurrentRemove() throws Exception { + //calculate tree size when split happens + final TestTree t = createTestTree(true); + long i = 0; + + for (; ; i++) { + t.put(i); + + if (t.rootLevel() > 0) //split happened + break; + } + + final long treeStartSize = i; + + final AtomicReference<Throwable> failed = new AtomicReference<>(); + + for (int k = 0; k < 100; k++) { + final TestTree tree = createTestTree(true); + + final AtomicBoolean start = new AtomicBoolean(); + + final AtomicInteger ready = new AtomicInteger(); + + Thread first = new Thread(new Runnable() { + @Override public void run() { + ready.incrementAndGet(); + + while (!start.get()); //waiting without blocking + + try { + tree.remove(treeStartSize / 2L); + } + catch (Throwable th) { + failed.set(th); + } + } + }); + + Thread second = new Thread(new Runnable() { + @Override public void run() { + ready.incrementAndGet(); + + while (!start.get()); //waiting without blocking + + try { + tree.put(treeStartSize + 1); + } + catch (Throwable th) { + failed.set(th); + } + } + }); + + for (int j = 0; j < treeStartSize; j++) + tree.put((long)j); + + first.start(); + second.start(); + + while (ready.get() != 2); + + start.set(true); + + first.join(); + second.join(); + + assertNull(failed.get()); + } + } + + /** * @param canGetRow Can get row from inner page. * @throws Exception If failed. */