db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kahat...@apache.org
Subject svn commit: r1234776 - in /db/derby/code/trunk/java/engine/org/apache/derby: iapi/sql/compile/CompilerContext.java impl/sql/GenericStatement.java impl/sql/compile/CompilerContextImpl.java impl/sql/compile/FromBaseTable.java
Date Mon, 23 Jan 2012 13:14:53 GMT
Author: kahatlen
Date: Mon Jan 23 13:14:52 2012
New Revision: 1234776

URL: http://svn.apache.org/viewvc?rev=1234776&view=rev
Log:
DERBY-5406: Intermittent failures in CompressTableTest and TruncateTableTest

Retry compilation if it fails because a conglomerate has disappeared.
This may happen if DDL, compress, truncate or similar operations happen
while the statement is being compiled. When trying again, the compilation
should find the new conglomerate if one exists, or fail with a proper
error message if the SQL object has been removed.

This is a workaround for a race condition in the dependency management.
When binding a statement, the compiler typically builds descriptor
objects (like a TableDescriptor) from the system tables and then registers
the statement as a dependent on that descriptor. However, another thread
may at the same time be invalidating all dependents of that descriptor.
It is possible that this happens right before the current statement has
been registered as a dependent, and it will never see the invalidation
request. Once it actually tries to access the conglomerate associated with
the descriptor, it will fail with a "conglomerate does not exist" error,
and since the statement did not see the invalidation request, the compiler
doesn't know that it should retry the compilation.

This fix also backs out the changes made in revision 1187204, as they
addressed a subset of the cases handled by this broader fix, and are not
needed any more.

Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/compile/CompilerContext.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericStatement.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CompilerContextImpl.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromBaseTable.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/compile/CompilerContext.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/compile/CompilerContext.java?rev=1234776&r1=1234775&r2=1234776&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/compile/CompilerContext.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/compile/CompilerContext.java
Mon Jan 23 13:14:52 2012
@@ -287,13 +287,6 @@ public interface CompilerContext extends
 
 	void setCurrentDependent(Dependent d);
 
-    /**
-     * Get the current dependent from this {@code CompilerContext}.
-     *
-     * @return the dependent currently being compiled
-     */
-    Dependent getCurrentDependent();
-
 	/**
 	 * Get the current auxiliary provider list from this CompilerContext.
 	 *

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericStatement.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericStatement.java?rev=1234776&r1=1234775&r2=1234776&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericStatement.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericStatement.java Mon Jan
23 13:14:52 2012
@@ -92,13 +92,40 @@ public class GenericStatement
 		*/ 
 
         final int depth = lcc.getStatementDepth();
+        String prevErrorId = null;
         while (true) {
+            boolean recompile = false;
             try {
                 return prepMinion(lcc, true, (Object[]) null,
                                   (SchemaDescriptor) null, forMetaData);
-            } finally {
-                boolean recompile = false;
+            } catch (StandardException se) {
+                // There is a chance that we didn't see the invalidation
+                // request from a DDL operation in another thread because
+                // the statement wasn't registered as a dependent until
+                // after the invalidation had been completed. Assume that's
+                // what has happened if we see a conglomerate does not exist
+                // error, and force a retry even if the statement hasn't been
+                // invalidated.
+                if (SQLState.STORE_CONGLOMERATE_DOES_NOT_EXIST.equals(
+                        se.getMessageId())) {
+                    // STORE_CONGLOMERATE_DOES_NOT_EXIST has exactly one
+                    // argument: the conglomerate id
+                    String conglomId = String.valueOf(se.getArguments()[0]);
+
+                    // Request a recompile of the statement if a conglomerate
+                    // disappears while we are compiling it. But if we have
+                    // already retried once because the same conglomerate was
+                    // missing, there's probably no hope that yet another retry
+                    // will help, so let's break out instead of potentially
+                    // looping infinitely.
+                    if (!conglomId.equals(prevErrorId)) {
+                        recompile = true;
+                    }
 
+                    prevErrorId = conglomId;
+                }
+                throw se;
+            } finally {
                 // Check if the statement was invalidated while it was
                 // compiled. If so, the newly compiled plan may not be
                 // up to date anymore, so we recompile the statement
@@ -112,7 +139,7 @@ public class GenericStatement
                 // invalidatedWhileCompiling and isValid are protected by
                 // synchronization on the prepared statement.
                 synchronized (preparedStmt) {
-                    if (preparedStmt.invalidatedWhileCompiling) {
+                    if (recompile || preparedStmt.invalidatedWhileCompiling) {
                         preparedStmt.isValid = false;
                         preparedStmt.invalidatedWhileCompiling = false;
                         recompile = true;

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CompilerContextImpl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CompilerContextImpl.java?rev=1234776&r1=1234775&r2=1234776&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CompilerContextImpl.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CompilerContextImpl.java
Mon Jan 23 13:14:52 2012
@@ -274,10 +274,6 @@ public class CompilerContextImpl extends
 		currentDependent = d;
 	}
 
-    public Dependent getCurrentDependent() {
-        return currentDependent;
-    }
-
 	/**
 	 * Get the current auxiliary provider list from this CompilerContext.
 	 *

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromBaseTable.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromBaseTable.java?rev=1234776&r1=1234775&r2=1234776&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromBaseTable.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromBaseTable.java Mon
Jan 23 13:14:52 2012
@@ -55,8 +55,6 @@ import org.apache.derby.iapi.sql.compile
 import org.apache.derby.iapi.sql.compile.RowOrdering;
 import org.apache.derby.iapi.sql.compile.Visitor;
 
-import org.apache.derby.iapi.sql.depend.DependencyManager;
-
 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
 import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor;
 import org.apache.derby.iapi.sql.dictionary.ColumnDescriptorList;
@@ -2349,20 +2347,8 @@ public class FromBaseTable extends FromT
 					);
 
             // Bail out if the descriptor couldn't be found. The conglomerate
-            // probably doesn't exist anymore because of concurrent DDL or
-            // compress operations, and the compilation will have to be tried
-            // again.
+            // probably doesn't exist anymore.
             if (baseConglomerateDescriptor == null) {
-                // The statement is typically invalidated by the operation
-                // that dropped the conglomerate. However, if the invalidation
-                // happened before we called createDependency(), we'll miss it
-                // and we won't retry the compilation with fresh dictionary
-                // information (DERBY-5406). So let's invalidate the statement
-                // ourselves here.
-                compilerContext.getCurrentDependent().makeInvalid(
-                        DependencyManager.COMPILE_FAILED,
-                        getLanguageConnectionContext());
-
                 throw StandardException.newException(
                         SQLState.STORE_CONGLOMERATE_DOES_NOT_EXIST,
                         new Long(tableDescriptor.getHeapConglomerateId()));



Mime
View raw message