Return-Path: X-Original-To: apmail-db-derby-commits-archive@www.apache.org Delivered-To: apmail-db-derby-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 95F2A48A9 for ; Thu, 23 Jun 2011 19:12:21 +0000 (UTC) Received: (qmail 1602 invoked by uid 500); 23 Jun 2011 19:12:21 -0000 Delivered-To: apmail-db-derby-commits-archive@db.apache.org Received: (qmail 1552 invoked by uid 500); 23 Jun 2011 19:12:21 -0000 Mailing-List: contact derby-commits-help@db.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: "Derby Development" List-Id: Delivered-To: mailing list derby-commits@db.apache.org Received: (qmail 1545 invoked by uid 99); 23 Jun 2011 19:12:21 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 23 Jun 2011 19:12:21 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 23 Jun 2011 19:12:19 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 008AD2388897; Thu, 23 Jun 2011 19:11:59 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1139039 - in /db/derby/code/branches/10.5/java/engine/org/apache/derby/impl/store/access: btree/BTreeController.java heap/HeapCompressScan.java heap/HeapPostCommit.java Date: Thu, 23 Jun 2011 19:11:58 -0000 To: derby-commits@db.apache.org From: mikem@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20110623191159.008AD2388897@eris.apache.org> Author: mikem Date: Thu Jun 23 19:11:58 2011 New Revision: 1139039 URL: http://svn.apache.org/viewvc?rev=1139039&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 from trunk to 10.5 branch. Clean merge. 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.5/java/engine/org/apache/derby/impl/store/access/btree/BTreeController.java db/derby/code/branches/10.5/java/engine/org/apache/derby/impl/store/access/heap/HeapCompressScan.java db/derby/code/branches/10.5/java/engine/org/apache/derby/impl/store/access/heap/HeapPostCommit.java Modified: db/derby/code/branches/10.5/java/engine/org/apache/derby/impl/store/access/btree/BTreeController.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.5/java/engine/org/apache/derby/impl/store/access/btree/BTreeController.java?rev=1139039&r1=1139038&r2=1139039&view=diff ============================================================================== --- db/derby/code/branches/10.5/java/engine/org/apache/derby/impl/store/access/btree/BTreeController.java (original) +++ db/derby/code/branches/10.5/java/engine/org/apache/derby/impl/store/access/btree/BTreeController.java Thu Jun 23 19:11:58 2011 @@ -109,7 +109,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. @@ -187,14 +191,23 @@ public class BTreeController extends Ope } finally { - if (controlRow != null) { - if (purged_at_least_one_row) { + if (controlRow != null) + { + if (purged_at_least_one_row) + { // Set a hint in the page that scans positioned on it // need to reposition because rows have disappeared from - // the page. + // the page. If at least one row has been purged, then + // do not release the latch. Purge requires latch to + // be held until commit, where it will be released after + // the commit log record has been logged. controlRow.page.setRepositionNeeded(); } - controlRow.release(); + else + { + // Ok to release latch if no purging has happened. + controlRow.release(); + } } } @@ -308,6 +321,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(); } } @@ -315,6 +334,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.5/java/engine/org/apache/derby/impl/store/access/heap/HeapCompressScan.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.5/java/engine/org/apache/derby/impl/store/access/heap/HeapCompressScan.java?rev=1139039&r1=1139038&r2=1139039&view=diff ============================================================================== --- db/derby/code/branches/10.5/java/engine/org/apache/derby/impl/store/access/heap/HeapCompressScan.java (original) +++ db/derby/code/branches/10.5/java/engine/org/apache/derby/impl/store/access/heap/HeapCompressScan.java Thu Jun 23 19:11:58 2011 @@ -208,7 +208,11 @@ class HeapCompressScan // At this point assume table level lock, and that this // transcation did not delete the row, so any // deleted row must be a committed deleted row which can - // be purged. + // be purged. Usually latches on purged pages must + // be held until end transaction to prevent other + // transactions from using space necessary for a possible + // undo of the purge, but in this case a table level + // lock is held and will insure correct undo behavior. scan_position.current_page.purgeAtSlot( scan_position.current_slot, 1, false); Modified: db/derby/code/branches/10.5/java/engine/org/apache/derby/impl/store/access/heap/HeapPostCommit.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.5/java/engine/org/apache/derby/impl/store/access/heap/HeapPostCommit.java?rev=1139039&r1=1139038&r2=1139039&view=diff ============================================================================== --- db/derby/code/branches/10.5/java/engine/org/apache/derby/impl/store/access/heap/HeapPostCommit.java (original) +++ db/derby/code/branches/10.5/java/engine/org/apache/derby/impl/store/access/heap/HeapPostCommit.java Thu Jun 23 19:11:58 2011 @@ -222,7 +222,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();