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();
+        }
     }
 
     /**

Reply via email to