You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by mi...@apache.org on 2011/06/24 18:32:30 UTC

svn commit: r1139376 - in /db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/store/access: btree/BTreeController.java heap/HeapPostCommit.java

Author: mikem
Date: Fri Jun 24 16:32:30 2011
New Revision: 1139376

URL: http://svn.apache.org/viewvc?rev=1139376&view=rev
Log:
DERBY-5284 A derby crash at exactly right time during a btree split can cause a
corrupt db which can not be booted.

backport fix #1139085 from 10.4 branch to 10.1 branch. clean merge by doing
merge of the 10.4 conflict resolved change.

Fixed a problem during BTREE split.  The first phase of btree split sees
if it can reclaim space from committed deleted rows.  If it finds any
it purges these rows in a nested internal transaction.  It needs to hold
the latch on the page until end of transaction, but did not.  This allowed
a very small window of a few instructions where another insert could use
the space on the page and then a system crash could cause the purges to undo
but fail due to the insert.

The fix was to hold the latch and let commit release it.


Modified:
    db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/store/access/btree/BTreeController.java
    db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/store/access/heap/HeapPostCommit.java

Modified: db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/store/access/btree/BTreeController.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/store/access/btree/BTreeController.java?rev=1139376&r1=1139375&r2=1139376&view=diff
==============================================================================
--- db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/store/access/btree/BTreeController.java (original)
+++ db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/store/access/btree/BTreeController.java Fri Jun 24 16:32:30 2011
@@ -110,7 +110,11 @@ public class BTreeController extends Ope
      * it would be a waste to merge the page only to split it again to allow
      * the insert of the row causing the split.
      *
-	 * @return true if at least one row was purged.
+	 * @return true if at least one row was purged.  If true, then the routine
+     *              will leave the page latched, and the caller will release
+     *              the latch by committing or aborting the transaction.  The
+     *              latch must be held to end transaction to insure space on
+     *              the page remains available for a undo of the purge.
      *
      * @param open_btree The already open btree to use to get latch on page.
      * @param pageno     The page number of the leaf to attempt the reclaim on.
@@ -193,8 +197,14 @@ public class BTreeController extends Ope
         }
         finally
         {
-            if (controlRow != null)
-                controlRow.release();
+            if (controlRow != null) 
+            {
+                if (!purged_at_least_one_row) 
+                {
+                    // Ok to release latch if no purging has happened.
+                    controlRow.release();
+                }
+            }
 
             return(purged_at_least_one_row);
         }
@@ -307,6 +317,12 @@ public class BTreeController extends Ope
                 // don't split if we reclaim any rows.
                 do_split = !reclaim_deleted_rows(split_open_btree, leaf_pageno);
 
+                // on return if !do_split then the latch on leaf_pageno is held
+                // and will be released by the committing or aborting the 
+                // transaction.  If a purge has been done, no other action on
+                // the page should be attempted (ie. a split) before committing
+                // the purges.
+
                 split_open_btree.close();
             }
         }
@@ -314,6 +330,9 @@ public class BTreeController extends Ope
         long new_leaf_pageno = leaf_pageno; 
         if (do_split)
         {
+            // no space was reclaimed from deleted rows, so do split to allow
+            // space for a subsequent insert.
+
             split_open_btree = new OpenBTree();
             split_open_btree.init(
                 this.init_open_user_scans, 

Modified: db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/store/access/heap/HeapPostCommit.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/store/access/heap/HeapPostCommit.java?rev=1139376&r1=1139375&r2=1139376&view=diff
==============================================================================
--- db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/store/access/heap/HeapPostCommit.java (original)
+++ db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/store/access/heap/HeapPostCommit.java Fri Jun 24 16:32:30 2011
@@ -225,7 +225,10 @@ class HeapPostCommit implements Servicea
             {
                 // If no purge happened on the page and the page is not
                 // removed, feel free to unlatch it.  Otherwise, let
-                // transaction commit take care of it.
+                // transaction commit take care of it.  The latch must be
+                // held until end transaction in order to insure no other
+                // transaction uses the space freed by the purge, which
+                // would cause a subquent undo of the purge to fail.
 				if (!purgingDone)
                 {
                     page.unlatch();