Return-Path: Delivered-To: apmail-db-derby-commits-archive@www.apache.org Received: (qmail 43878 invoked from network); 12 Aug 2008 17:19:43 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 12 Aug 2008 17:19:43 -0000 Received: (qmail 64470 invoked by uid 500); 12 Aug 2008 17:19:42 -0000 Delivered-To: apmail-db-derby-commits-archive@db.apache.org Received: (qmail 64449 invoked by uid 500); 12 Aug 2008 17:19:42 -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 64440 invoked by uid 99); 12 Aug 2008 17:19:42 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 12 Aug 2008 10:19:42 -0700 X-ASF-Spam-Status: No, hits=-2000.0 required=10.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; Tue, 12 Aug 2008 17:18:54 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 2EB6B238899F; Tue, 12 Aug 2008 10:19:22 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r685232 - in /db/derby/code/trunk/java: engine/org/apache/derby/iapi/sql/conn/ engine/org/apache/derby/impl/sql/execute/ testing/org/apache/derbyTesting/functionTests/tests/lang/ Date: Tue, 12 Aug 2008 17:19:21 -0000 To: derby-commits@db.apache.org From: dag@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20080812171922.2EB6B238899F@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: dag Date: Tue Aug 12 10:19:20 2008 New Revision: 685232 URL: http://svn.apache.org/viewvc?rev=685232&view=rev Log: DERBY-48 A connection request that has a default schema that is being created by another transaction will fail to connect Follow-up patch to svn 685141, which accidentally committed the wrong patch revision. With this patch, the net effect is DERBY-48b-1 which should have been committed. Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/LanguageConnectionContext.java db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DDLConstantAction.java db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LazyDefaultSchemaCreationTest.java Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/LanguageConnectionContext.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/LanguageConnectionContext.java?rev=685232&r1=685231&r2=685232&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/LanguageConnectionContext.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/conn/LanguageConnectionContext.java Tue Aug 12 10:19:20 2008 @@ -502,7 +502,7 @@ /** * Return true if this schema name is the initial default schema for the * current session. - * @param schemaName + * @param schemaName * @return true */ public boolean isInitialDefaultSchema(String schemaName); Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DDLConstantAction.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DDLConstantAction.java?rev=685232&r1=685231&r2=685232&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DDLConstantAction.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DDLConstantAction.java Tue Aug 12 10:19:20 2008 @@ -101,88 +101,20 @@ SchemaDescriptor sd = dd.getSchemaDescriptor(schemaName, tc, false); if (sd == null || sd.getUUID() == null) { - CreateSchemaConstantAction csca - = new CreateSchemaConstantAction(schemaName, (String) null); + CreateSchemaConstantAction csca + = new CreateSchemaConstantAction(schemaName, (String) null); if (activation.getLanguageConnectionContext(). isInitialDefaultSchema(schemaName)) { - // DERBY-48: This operation creates the user's initial default - // schema and we don't want to hold a lock for SYSSCHEMAS for - // the duration of the user transaction, so we perform the - // creation in a nested transaction if possible. - TransactionController useTc = null; - TransactionController nestedTc = null; - - try { - nestedTc = tc.startNestedUserTransaction(false); - useTc = nestedTc; - } catch (StandardException e) { - if (SanityManager.DEBUG) { - SanityManager.THROWASSERT( - "Unexpected: not able to start nested transaction " + - "to auto-create schema", e); - } - useTc = tc; - } - - // Try max twice: if nested transaction times out, try - // again in the outer transaction because it may be a - // self-lock, that is, the outer transaction may hold some - // lock(s) that make the nested transaction attempt to set - // a write lock time out. Trying it again in the outer - // transaction will then succeed. If the reason is some - // other transaction barring us, trying again in the outer - // transaction will possibly time out again. - // - // Also, if creating a nested transaction failed, only try - // once in the outer transaction. - while (true) { - try { - csca.executeConstantAction(activation, useTc); - } catch (StandardException se) { - if (se.getMessageId().equals(SQLState.LOCK_TIMEOUT)) { - // We don't test for SQLState.DEADLOCK or - // .LOCK_TIMEOUT_LOG here because a) if it is a - // deadlock, it may be better to expose it, and b) - // LOCK_TIMEOUT_LOG happens when the app has set - // derby.locks.deadlockTrace=true, in which case we - // don't want to mask the timeout. So in both the - // latter cases we just throw. - if (useTc == nestedTc) { - - // clean up after use of nested transaction, - // then try again in outer transaction - useTc = tc; - nestedTc.destroy(); - continue; - } - } else if (se.getMessageId() - .equals(SQLState.LANG_OBJECT_ALREADY_EXISTS)) { - // Ignore "Schema already exists". Another thread has - // probably created it after we checked for it - break; - } - - // We got an non-expected exception, either in - // the nested transaction or in the outer - // transaction; we had better pass that on - if (useTc == nestedTc) { - nestedTc.destroy(); - } - - throw se; - } - break; - } - - // We either succeeded or got LANG_OBJECT_ALREADY_EXISTS. - // Clean up if we did this in a nested transaction. - if (useTc == nestedTc) { - nestedTc.commit(); - nestedTc.destroy(); - } + // DERBY-48: This operation creates the user's initial + // default schema and we don't want to hold a lock for + // SYSSCHEMAS for the duration of the user transaction + // since connection attempts may block, so we perform + // the creation in a nested transaction (if possible) + // so we can commit at once and release locks. + executeCAPreferSubTrans(csca, tc, activation); } else { - // create the schema in the user transaction always + // create the schema in the user transaction try { csca.executeConstantAction(activation); } catch (StandardException se) { @@ -204,6 +136,85 @@ } + private static void executeCAPreferSubTrans + (CreateSchemaConstantAction csca, + TransactionController tc, + Activation activation) throws StandardException { + + TransactionController useTc = null; + TransactionController nestedTc = null; + + try { + nestedTc = tc.startNestedUserTransaction(false); + useTc = nestedTc; + } catch (StandardException e) { + if (SanityManager.DEBUG) { + SanityManager.THROWASSERT( + "Unexpected: not able to start nested transaction " + + "to auto-create schema", e); + } + useTc = tc; + } + + // Try max twice: if nested transaction times out, try + // again in the outer transaction because it may be a + // self-lock, that is, the outer transaction may hold some + // lock(s) that make the nested transaction attempt to set + // a write lock time out. Trying it again in the outer + // transaction will then succeed. If the reason is some + // other transaction barring us, trying again in the outer + // transaction will possibly time out again. + // + // Also, if creating a nested transaction failed, only try + // once in the outer transaction. + while (true) { + try { + csca.executeConstantAction(activation, useTc); + } catch (StandardException se) { + if (se.getMessageId().equals(SQLState.LOCK_TIMEOUT)) { + // We don't test for SQLState.DEADLOCK or + // .LOCK_TIMEOUT_LOG here because a) if it is a + // deadlock, it may be better to expose it, and b) + // LOCK_TIMEOUT_LOG happens when the app has set + // derby.locks.deadlockTrace=true, in which case we + // don't want to mask the timeout. So in both the + // latter cases we just throw. + if (useTc == nestedTc) { + + // clean up after use of nested transaction, + // then try again in outer transaction + useTc = tc; + nestedTc.destroy(); + continue; + } + } else if (se.getMessageId() + .equals(SQLState.LANG_OBJECT_ALREADY_EXISTS)) { + // Ignore "Schema already exists". Another thread has + // probably created it after we checked for it + break; + } + + // We got an non-expected exception, either in + // the nested transaction or in the outer + // transaction; we had better pass that on + if (useTc == nestedTc) { + nestedTc.destroy(); + } + + throw se; + } + break; + } + + // We either succeeded or got LANG_OBJECT_ALREADY_EXISTS. + // Clean up if we did this in a nested transaction. + if (useTc == nestedTc) { + nestedTc.commit(); + nestedTc.destroy(); + } + } + + /** * Lock the table in exclusive or share mode to prevent deadlocks. * Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LazyDefaultSchemaCreationTest.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LazyDefaultSchemaCreationTest.java?rev=685232&r1=685231&r2=685232&view=diff ============================================================================== --- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LazyDefaultSchemaCreationTest.java (original) +++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/LazyDefaultSchemaCreationTest.java Tue Aug 12 10:19:20 2008 @@ -221,7 +221,7 @@ // Will auto-create schema OTHERSCHEMA: s1.executeUpdate("create table otherschema.t1(i int)"); s1.close(); - + JDBC.assertSingleValueResultSet( c1.createStatement().executeQuery( "select schemaname from sys.sysschemas " + @@ -234,7 +234,7 @@ c1.createStatement().executeQuery( "select schemaname from sys.sysschemas " + "where schemaname='OTHERSCHEMA'")); - + c1.rollback(); c1.close(); }