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 ka...@apache.org on 2008/08/23 09:46:46 UTC

svn commit: r688275 - in /db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql: GenericStatement.java conn/GenericLanguageConnectionContext.java

Author: kahatlen
Date: Sat Aug 23 00:46:45 2008
New Revision: 688275

URL: http://svn.apache.org/viewvc?rev=688275&view=rev
Log:
DERBY-3786: Assert failure in CacheEntry.unkeepForRemove when running stress.multi

Merged fix from trunk (revision 688027).

Modified:
    db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/GenericStatement.java
    db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java

Modified: db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/GenericStatement.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/GenericStatement.java?rev=688275&r1=688274&r2=688275&view=diff
==============================================================================
--- db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/GenericStatement.java (original)
+++ db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/GenericStatement.java Sat Aug 23 00:46:45 2008
@@ -593,6 +593,16 @@
 		}
 	}
 
+    /**
+     * Return the {@link PreparedStatement} currently associated with this
+     * statement.
+     *
+     * @return the prepared statement that is associated with this statement
+     */
+    public PreparedStatement getPreparedStatement() {
+        return preparedStmt;
+    }
+
 	/*
 	** Identity
 	*/

Modified: db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java?rev=688275&r1=688274&r2=688275&view=diff
==============================================================================
--- db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java (original)
+++ db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/conn/GenericLanguageConnectionContext.java Sat Aug 23 00:46:45 2008
@@ -29,7 +29,6 @@
 import org.apache.derby.impl.sql.execute.AutoincrementCounter;
 import org.apache.derby.impl.sql.GenericPreparedStatement;
 import org.apache.derby.impl.sql.GenericStatement;
-import org.apache.derby.iapi.sql.Statement;
 
 import org.apache.derby.iapi.services.property.PropertyUtil;
 import org.apache.derby.iapi.services.context.ContextManager;
@@ -879,13 +878,16 @@
 
 	/**
 	*  This method will remove a statement from the  statement cache.
-	*  It will be called,  for example, if there is an exception preparing
-	*  the statement.
+    *  It should only be called if there is an exception preparing
+    *  the statement. The caller must have set the flag
+    *  {@code preparedStmt.compilingStatement} in the {@code GenericStatement}
+    *  before calling this method in order to prevent race conditions when
+    *  calling {@link CacheManager#remove(Cacheable)}.
 	*
 	*  @param statement Statement to remove
 	*  @exception StandardException thrown if lookup goes wrong.
 	*/	
-	public void removeStatement(Statement statement)
+	public void removeStatement(GenericStatement statement)
 		throws StandardException {
         
         CacheManager statementCache =
@@ -894,9 +896,29 @@
 		if (statementCache == null)
 			return;
  
-			Cacheable cachedItem = statementCache.findCached(statement);
-			if (cachedItem != null)
-				statementCache.remove(cachedItem);
+        Cacheable cachedItem = statementCache.findCached(statement);
+        // No need to do anything if the statement is already removed
+        if (cachedItem != null) {
+            CachedStatement cs = (CachedStatement) cachedItem;
+            if (statement.getPreparedStatement() != cs.getPreparedStatement()) {
+                // DERBY-3786: Someone else has removed the statement from
+                // the cache, probably because of the same error that brought
+                // us here. In addition, someone else has recreated the
+                // statement. Since the recreated statement is not the same
+                // object as the one we are working on, we don't have the
+                // proper guarding (through the synchronized flag
+                // GenericStatement.preparedStmt.compilingStatement) to ensure
+                // that we're the only ones calling CacheManager.remove() on
+                // this statement. Therefore, just release the statement here
+                // so that we don't get in the way for the other thread that
+                // is trying to compile the same query.
+                statementCache.release(cachedItem);
+            } else {
+                // The statement object that we were trying to compile is still
+                // in the cache. Since the compilation failed, remove it.
+                statementCache.remove(cachedItem);
+            }
+        }
 	}
 
 	/**