db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kmars...@apache.org
Subject svn commit: r726121 - in /db/derby/code/trunk/java: engine/org/apache/derby/impl/services/locks/Deadlock.java testing/org/apache/derbyTesting/functionTests/tests/store/Derby3980DeadlockTest.java
Date Fri, 12 Dec 2008 21:24:38 GMT
Author: kmarsden
Date: Fri Dec 12 13:24:38 2008
New Revision: 726121

URL: http://svn.apache.org/viewvc?rev=726121&view=rev
Log:
DERBY-3980 Conflicting select then update with REPEATABLE_READ gives lock timeout instead
of deadlock

Just javadoc changes and adding a new test for the issue that can't be enabled until we have
a fix.  This check-in does not fix the issue in any way.


Added:
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/Derby3980DeadlockTest.java
  (with props)
Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/Deadlock.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/Deadlock.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/Deadlock.java?rev=726121&r1=726120&r2=726121&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/Deadlock.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/Deadlock.java Fri
Dec 12 13:24:38 2008
@@ -48,6 +48,15 @@
 	/**
 	 * Look for a deadlock.
 	 * <BR>
+	 * Walk through the graph of all locks and search for cycles among
+	 * the waiting lock requests which would indicate a deadlock. A simple
+	 * deadlock cycle is where the granted locks of waiting compatibility
+	 * space A is blocking compatibility space B and space B holds locks causing
+	 * space A to wait.
+	 * <p>
+	 * Would be nice to get a better high level description of deadlock
+	 * search.
+	 * <p> 
 	 * MT - if the <code>LockTable</code> is a <code>LockSet</code>
object, the
 	 * callers must be synchronized on the <code>LockSet</code> object in order
 	 * to satisfy the syncronization requirements of
@@ -56,6 +65,26 @@
 	 * the <code>ReentrantLock</code>s guarding the entries in the lock table,
 	 * and the callers must make sure that only a single thread calls
 	 * <code>look()</code> at a time.
+	 *
+	 *
+	 * @param factory The locking system factory
+	 * @param set The complete lock table. A lock table is a hash
+	 * table keyed by a Lockable and with a LockControl as
+	 * the data element.
+	 * @param control A LockControl contains a reference to the item being
+	 * locked and doubly linked lists for the granted locks
+	 * and the waiting locks. The passed in value is the
+	 * lock that the caller was waiting on when woken up
+	 * to do the deadlock check.
+	 * @param startingLock represents the specific waiting lock request that
+	 * the caller has been waiting on, before just being
+	 * woken up to do this search.
+	 * @param deadlockWake Either Constants.WAITING_LOCK_IN_WAIT, or
+	 * Constants.WAITING_LOCK_DEADLOCK. 
+	 *
+	 * @return The identifier to be used to open the conglomerate later.
+	 *
+	 * @exception StandardException Standard exception policy.
 	 */
 	static Object[] look(AbstractPool factory, LockTable set,
 						 LockControl control, ActiveLock startingLock,

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/Derby3980DeadlockTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/Derby3980DeadlockTest.java?rev=726121&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/Derby3980DeadlockTest.java
(added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/Derby3980DeadlockTest.java
Fri Dec 12 13:24:38 2008
@@ -0,0 +1,159 @@
+/*
+ *
+ * Derby - Class org.apache.derbyTesting.functionTests.tests.store.Derby3980DeadlockTest
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
+ */
+package org.apache.derbyTesting.functionTests.tests.store;
+
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Iterator;
+import java.util.LinkedList;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.derbyTesting.junit.BaseJDBCTestCase;
+import org.apache.derbyTesting.junit.CleanDatabaseTestSetup;
+import org.apache.derbyTesting.junit.DatabasePropertyTestSetup;
+import org.apache.derbyTesting.junit.TestConfiguration;
+
+/**
+ * Test to test two threads doing select then delete of a row
+ * using REPEATABLE_READ isolation level.  We should get a 
+ * deadlock (SQLState 40001);
+ *
+ */
+public class Derby3980DeadlockTest extends BaseJDBCTestCase {
+    private final int THREAD_COUNT = 2;
+    private LinkedList  listExceptions = new LinkedList();
+    private Object syncObject = new Object();
+    private int startedCount = 0;
+    
+    public Derby3980DeadlockTest(String name) {
+        super(name);
+    }
+
+    
+    public void test3980Deadlock() {
+        Thread [] t = new Thread[THREAD_COUNT];
+        createThreads(t);
+        waitForThreads(t);
+        checkExceptions();        
+    }
+    
+    
+    /**
+     * Check we have one deadlock exception.
+     */
+    private void checkExceptions() {        
+        for( Iterator i = listExceptions.iterator(); i.hasNext(); ) {
+            SQLException e = (SQLException) i.next();
+            assertSQLState("40001",e);
+        }
+        assertEquals("Expected 1 exception, got" + listExceptions.size(),
+                1,listExceptions.size());
+    }
+
+    private void waitForThreads(Thread[] t) {
+        for (int i = 0; i < THREAD_COUNT; i++)
+        {   
+            try {
+                t[i].join();
+            } catch (InterruptedException e){
+               fail(
+                        "FAIL - InterruptedException  thrown waiting for the threads");
+            }
+        }
+        
+    }
+
+    private void createThreads(Thread[] t) {
+        for (int i = 0; i < THREAD_COUNT; i++)
+        {   
+            t[i] = new Thread(new Runnable() {
+                public void run() {threadWorker(); }
+
+                private void threadWorker() {
+                    Connection threadConnection = null;
+                    
+                    try {
+                        synchronized (syncObject) {
+                            
+                            /* If a connection hasn't been opened for this thread, open one
*/
+                            if (threadConnection == null){
+                                threadConnection = openDefaultConnection();
+                            }
+                            
+                            /* A new thread started, so we increment the counter */
+                            startedCount++;
+                            
+                            /* Wake all the threads to run the check below */
+                            syncObject.notifyAll();
+                            
+                            while (startedCount < THREAD_COUNT) {
+                                syncObject.wait();
+                            }
+                        }          
+                        Statement stmt = threadConnection.createStatement();
+                    
+                    threadConnection.setAutoCommit(false);
+                    /* set isolation level to repeatable read */
+                    threadConnection.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
+                    
+                    ResultSet rs = stmt.executeQuery("select * from t where i = 456");
+                    while (rs.next());
+                    
+                    //stmt.executeUpdate("update t set i = 456 where i = 456");
+                    stmt.executeUpdate("delete from t  where i = 456");
+                    threadConnection.commit();
+                    } catch (Exception e) {
+                        synchronized(syncObject){
+                            listExceptions.add(e);
+                        }
+                    }
+
+                    
+                }},"Thread"+i);
+            t[i].start();
+        }
+        
+    }
+
+    public static Test suite() {
+
+	Test suite = TestConfiguration.embeddedSuite(Derby3980DeadlockTest.class);
+    return new  CleanDatabaseTestSetup(
+                DatabasePropertyTestSetup.setLockTimeouts(suite, 5, 10)) {
+         /**
+          * Creates the table used in the test cases.
+          * 
+          */
+         protected void decorateSQL(Statement s) throws SQLException {
+            s.executeUpdate("CREATE TABLE T (I INT)");
+            s.executeUpdate("INSERT INTO T VALUES(456)");
+         }
+      
+     };
+	
+    }
+
+}
+

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/Derby3980DeadlockTest.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message