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 2007/03/06 10:17:42 UTC

svn commit: r515040 - in /db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks: Control.java Deadlock.java Lock.java LockControl.java LockSet.java LockSpace.java LockTable.java SinglePool.java

Author: kahatlen
Date: Tue Mar  6 01:17:41 2007
New Revision: 515040

URL: http://svn.apache.org/viewvc?view=rev&rev=515040
Log:
DERBY-2327 (partial) Reduce monitor contention in LockSet

Encapsulated more of the lock table functionality in LockSet:
  - created a new interface (LockTable) which LockSet implements
  - replaced all references to LockSet with references to the new
    LockTable interface
  - moved code that explicitly synchronized on the LockSet object from
    LockSpace.unlockReference() and SinglePool.zeroDurationlockObject()
    to LockSet so that the granularity of the synchronization can be
    controlled by the LockSet implementation alone
  - added setter methods for deadlock timeout and wait timeout

Added:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/LockTable.java   (with props)
Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/Control.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/Deadlock.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/Lock.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/LockControl.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/LockSet.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/LockSpace.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/SinglePool.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/Control.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/Control.java?view=diff&rev=515040&r1=515039&r2=515040
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/Control.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/Control.java Tue Mar  6 01:17:41 2007
@@ -25,6 +25,7 @@
 import org.apache.derby.iapi.services.locks.Lockable;
 import org.apache.derby.iapi.services.locks.Latch;
 import java.util.List;
+import java.util.Map;
 
 public interface Control {
 
@@ -49,7 +50,7 @@
 
 	public boolean unlock(Latch lockInGroup, int unlockCount);
 
-	public void addWaiters(java.util.Dictionary waiters);
+	public void addWaiters(Map waiters);
 
 	public Lock getFirstGrant();
 

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?view=diff&rev=515040&r1=515039&r2=515040
==============================================================================
--- 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 Tue Mar  6 01:17:41 2007
@@ -50,7 +50,9 @@
 	 * <BR>
 	 * MT - must be synchronized on the <code>LockSet</code> object.
 	 */
-	static Object[] look(SinglePool factory, LockSet set, LockControl control, ActiveLock startingLock, byte deadlockWake) {
+	static Object[] look(SinglePool factory, LockTable set,
+						 LockControl control, ActiveLock startingLock,
+						 byte deadlockWake) {
 
 		// step one, get a list of all waiters
 		Dictionary waiters = Deadlock.getWaiters(set);
@@ -180,7 +182,7 @@
 		grants.remove(grants.size() - 1);
 	}
 
-	private static Hashtable getWaiters(LockSet set) {
+	private static Hashtable getWaiters(LockTable set) {
 		Hashtable waiters = new Hashtable();
 		set.addWaiters(waiters);
 		return waiters;

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/Lock.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/Lock.java?view=diff&rev=515040&r1=515039&r2=515040
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/Lock.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/Lock.java Tue Mar  6 01:17:41 2007
@@ -28,6 +28,7 @@
 import org.apache.derby.iapi.services.sanity.SanityManager;
 
 import java.util.List;
+import java.util.Map;
 
 /**
 	A Lock represents a granted or waiting lock request.
@@ -208,7 +209,7 @@
 
 		return false;
 	}
-	public void addWaiters(java.util.Dictionary waiters) {
+	public void addWaiters(Map waiters) {
 	}
 	public Lock getFirstGrant() {
 		return this;

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/LockControl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/LockControl.java?view=diff&rev=515040&r1=515039&r2=515040
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/LockControl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/LockControl.java Tue Mar  6 01:17:41 2007
@@ -27,10 +27,10 @@
 
 import org.apache.derby.iapi.services.sanity.SanityManager;
 
-import java.util.Dictionary;
 import java.util.Stack;
 import java.util.List;
 import java.util.ListIterator;
+import java.util.Map;
 
 /**
 	A LockControl contains a reference to the item being locked
@@ -268,7 +268,7 @@
 		1) The Lockable has just been unlocked, 
 	*/
 
-	public Lock addLock(LockSet ls, CompatibilitySpace compatibilitySpace,
+	public Lock addLock(LockTable ls, CompatibilitySpace compatibilitySpace,
 						Object qualifier) {
 
 		if (SanityManager.DEBUG) {
@@ -412,7 +412,7 @@
 	/**
 		Get the next waiting lock (if any).
 	*/
-	ActiveLock getNextWaiter(ActiveLock item, boolean remove, LockSet ls) {
+	ActiveLock getNextWaiter(ActiveLock item, boolean remove, LockTable ls) {
 
 		ActiveLock nextWaitingLock = null;
 
@@ -505,7 +505,7 @@
 		Give up waiting up on a lock
 	*/
 
-	protected void giveUpWait(Object item, LockSet ls) {
+	protected void giveUpWait(Object item, LockTable ls) {
 
 		int count = removeWaiter(waiting, item, ls);
 		if (item == lastPossibleSkip)
@@ -526,7 +526,7 @@
 	*/
 
 	/**
-		Add the waiters of this lock into this Dictionary object.
+		Add the waiters of this lock into this Map object.
 		<BR>
 		Each waiting thread gets two entries in the hashtable
 		<OL>
@@ -534,7 +534,7 @@
 		<LI>key=ActiveLock - value={LockControl for first waiter|ActiveLock of previosue waiter}
 		</OL>
 	*/
-	public void addWaiters(Dictionary waiters) {
+	public void addWaiters(Map waiters) {
 		
 		if ((waiting == null) || waiting.isEmpty())
 			return;
@@ -616,11 +616,11 @@
 	 *
 	 * @param waiting	The list of waiters to add to
 	 * @param lockItem	The lock request
-	 * @param ls		The LockSet
+	 * @param ls		The lock table
 	 */
 	private void addWaiter(List waiting,
 						Lock lockItem,
-						LockSet ls) {
+						LockTable ls) {
 
 		// Add lock to the waiting list
 		waiting.add(lockItem);
@@ -633,11 +633,11 @@
 	 * Remove and return the first lock request from a list of waiters.
 	 *
 	 * @param waiting	The list of waiters to pop from
-	 * @param ls		The LockSet
+	 * @param ls		The lock table
 	 *
 	 * @return	The removed lock request
 	 */
-	private Object popFrontWaiter(List waiting, LockSet ls) {
+	private Object popFrontWaiter(List waiting, LockTable ls) {
 		// Maintain count of waiters
 		ls.oneLessWaiter();
 
@@ -652,13 +652,13 @@
 	 *
 	 * @param waiting	The list of waiters to pop from
 	 * @param index		The index at which to remove the lock request
-	 * @param ls		The LockSet
+	 * @param ls		The lock table
 	 *
 	 * @return	The removed lock request
 	 */
 	private Object removeWaiter(List waiting,
 								int index,
-								LockSet ls) {
+								LockTable ls) {
 		// Maintain count of waiters
 		ls.oneLessWaiter();
 
@@ -671,13 +671,13 @@
 	 *
 	 * @param waiting	The list of waiters to pop from
 	 * @param item		The item to remove
-	 * @param ls		The LockSet
+	 * @param ls		The lock table
 	 *
 	 * @return	The number of items removed
 	 */
 	private int removeWaiter(List waiting,
 								Object item,
-								LockSet ls) {
+								LockTable ls) {
 		// Maintain count of waiters
 		ls.oneLessWaiter();
 

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/LockSet.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/LockSet.java?view=diff&rev=515040&r1=515039&r2=515040
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/LockSet.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/LockSet.java Tue Mar  6 01:17:41 2007
@@ -34,7 +34,6 @@
 import org.apache.derby.iapi.reference.Property;
 import org.apache.derby.iapi.reference.SQLState;
 
-import java.util.Dictionary;
 import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.Enumeration;
@@ -70,7 +69,7 @@
 	@see LockControl
 */
 
-final class LockSet {
+final class LockSet implements LockTable {
 	/*
 	** Fields
 	*/
@@ -85,8 +84,8 @@
 		<BR>
 		MT - immutable
 	*/
-	protected int deadlockTimeout = Property.DEADLOCK_TIMEOUT_DEFAULT * 1000;
-	protected int waitTimeout = Property.WAIT_TIMEOUT_DEFAULT * 1000;
+	private int deadlockTimeout = Property.DEADLOCK_TIMEOUT_DEFAULT * 1000;
+	private int waitTimeout = Property.WAIT_TIMEOUT_DEFAULT * 1000;
 
 //EXCLUDE-START-lockdiag- 
 
@@ -487,7 +486,7 @@
 		item.
 
 	*/
-	void unlock(Latch item, int unlockCount) {
+	public void unlock(Latch item, int unlockCount) {
 
 		if (SanityManager.DEBUG) {
 			if (SanityManager.DEBUG_ON(Constants.LOCK_TRACE)) {
@@ -567,13 +566,148 @@
 			nextGrant.wakeUp(Constants.WAITING_LOCK_GRANT);
 		}
 	}
+
+    /**
+     * Unlock an object once if it is present in the specified group. Also
+     * remove the object from the group.
+     *
+     * @param space the compatibility space
+     * @param ref a reference to the locked object
+     * @param qualifier qualifier of the lock
+     * @param group a map representing the locks in a group
+     * @return the corresponding lock in the group map, or <code>null</code> if
+     * the object was not unlocked
+     */
+    public synchronized Lock unlockReference(CompatibilitySpace space,
+                                             Lockable ref, Object qualifier,
+                                             Map group) {
+
+        Control control = getControl(ref);
+        if (control == null) {
+            return null;
+        }
+
+        Lock setLock = control.getLock(space, qualifier);
+        if (setLock == null) {
+            return null;
+        }
+
+        Lock lockInGroup = (Lock) group.remove(setLock);
+        if (lockInGroup != null) {
+            unlock(lockInGroup, 1);
+        }
+
+        return lockInGroup;
+    }
+
+    /**
+     * Lock an object and release the lock immediately. Equivalent to
+     * <pre>
+     * Lock lock = lockTable.lockObject(space, ref, qualifier, timeout);
+     * lockTable.unlock(lock, 1);
+     * </pre>
+     * except that the implementation is more efficient.
+     *
+     * @param space the compatibility space
+     * @param ref a reference to the locked object
+     * @param qualifier qualifier of the lock
+     * @param timeout maximum time to wait in milliseconds
+     * (<code>LockFactory.NO_WAIT</code> means don't wait)
+     * @return <code>true</code> if the object was locked, or
+     * <code>false</code>if the timeout was <code>NO_WAIT</code> and the lock
+     * couldn't be obtained immediately
+     * @exception StandardException if the lock could not be obtained
+     */
+    public boolean zeroDurationLockObject(
+        CompatibilitySpace space, Lockable ref, Object qualifier, int timeout)
+            throws StandardException {
+
+        if (SanityManager.DEBUG) {
+            if (SanityManager.DEBUG_ON(Constants.LOCK_TRACE)) {
+                D_LockControl.debugLock(
+                    "Zero Duration Lock Request before Grant: ",
+                    space, null, ref, qualifier, timeout);
+                if (SanityManager.DEBUG_ON(Constants.LOCK_STACK_TRACE)) {
+                    // The following will print the stack trace of the lock
+                    // request to the log.
+                    Throwable t = new Throwable();
+                    java.io.PrintWriter istream =
+                        SanityManager.GET_DEBUG_STREAM();
+                    istream.println("Stack trace of lock request:");
+                    t.printStackTrace(istream);
+                }
+            }
+        }
+
+        // Very fast zeroDurationLockObject() for unlocked objects.
+        // If no entry exists in the lock manager for this reference
+        // then it must be unlocked.
+        // If the object is locked then we perform a grantable
+        // check, skipping over any waiters.
+        // If the caller wants to wait and the lock cannot
+        // be granted then we do the slow join the queue and
+        // release the lock method.
+
+        synchronized (this) {
+            Control control = getControl(ref);
+            if (control == null) {
+                return true;
+            }
+
+            // If we are grantable, ignoring waiting locks then
+            // we can also grant this request now, as skipping
+            // over the waiters won't block them as we release
+            // the lock rightway.
+            if (control.isGrantable(true, space, qualifier)) {
+                return true;
+            }
+
+            // can't be granted and are not willing to wait.
+            if (timeout == C_LockFactory.NO_WAIT) {
+                return false;
+            }
+        }
+
+        Lock lock = lockObject(space, ref, qualifier, timeout);
+
+        if (SanityManager.DEBUG) {
+            if (SanityManager.DEBUG_ON(Constants.LOCK_TRACE)) {
+                D_LockControl.debugLock(
+                    "Zero Lock Request Granted: ",
+                    space, null, ref, qualifier, timeout);
+            }
+        }
+
+        // and simply unlock it once
+        unlock(lock, 1);
+
+        return true;
+    }
+
+    /**
+     * Set the deadlock timeout.
+     *
+     * @param timeout deadlock timeout in milliseconds
+     */
+    public void setDeadlockTimeout(int timeout) {
+        deadlockTimeout = timeout;
+    }
+
+    /**
+     * Set the wait timeout.
+     *
+     * @param timeout wait timeout in milliseconds
+     */
+    public void setWaitTimeout(int timeout) {
+        waitTimeout = timeout;
+    }
 	
 	/*
 	** Non public methods
 	*/
 //EXCLUDE-START-lockdiag- 
 
-	void setDeadlockTrace(boolean val)
+	public void setDeadlockTrace(boolean val)
 	{
 		// set this without synchronization
 		deadlockTrace = val;
@@ -611,11 +745,11 @@
     }
 
     /**
-     * Add all waiters in this lock table to a <code>Dictionary</code> object.
+     * Add all waiters in this lock table to a <code>Map</code> object.
      * <br>
      * MT - must be synchronized on this <code>LockSet</code> object.
      */
-    void addWaiters(Dictionary waiters) {
+    public void addWaiters(Map waiters) {
         for (Iterator it = locks.values().iterator(); it.hasNext(); ) {
             Control control = (Control) it.next();
             control.addWaiters(waiters);
@@ -623,11 +757,10 @@
     }
 
 //EXCLUDE-START-lockdiag- 
-	/*
+	/**
 	 * make a shallow clone of myself and my lock controls
 	 */
-	/* package */
-	synchronized Map shallowClone()
+	public synchronized Map shallowClone()
 	{
 		HashMap clone = new HashMap();
 
@@ -653,7 +786,7 @@
 	 * <BR>
 	 * MT - must be synchronized on this <code>LockSet</code> object.
 	 */
-	void oneMoreWaiter() {
+	public void oneMoreWaiter() {
 		blockCount++;
 	}
 
@@ -662,11 +795,11 @@
 	 * <BR>
 	 * MT - must be synchronized on this <code>LockSet</code> object.
 	 */
-	void oneLessWaiter() {
+	public void oneLessWaiter() {
 		blockCount--;
 	}
 
-	synchronized boolean anyoneBlocked() {
+	public synchronized boolean anyoneBlocked() {
 		if (SanityManager.DEBUG) {
 			SanityManager.ASSERT(
 				blockCount >= 0, "blockCount should not be negative");
@@ -680,7 +813,7 @@
 	 * <br>
 	 * MT - must be synchronized on this <code>LockSet</code> object.
 	 */
-	public final Control getControl(Lockable ref) {
+	private final Control getControl(Lockable ref) {
 		return (Control) locks.get(ref);
 	}
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/LockSpace.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/LockSpace.java?view=diff&rev=515040&r1=515039&r2=515040
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/LockSpace.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/LockSpace.java Tue Mar  6 01:17:41 2007
@@ -137,7 +137,7 @@
 		Unlock all the locks in a group and then remove the group.
 	*/
 
-	synchronized void unlockGroup(LockSet lset, Object group) {
+	synchronized void unlockGroup(LockTable lset, Object group) {
 		HashMap dl = (HashMap) groups.remove(group);
 		if (dl == null)
 			return;
@@ -184,7 +184,7 @@
 	/**
 		Unlock all locks in the group that match the key
 	*/
-	synchronized void unlockGroup(LockSet lset, Object group, Matchable key) {
+	synchronized void unlockGroup(LockTable lset, Object group, Matchable key) {
 		HashMap dl = (HashMap) groups.get(group);
 		if (dl == null)
 			return; //  no group at all
@@ -264,29 +264,17 @@
 
 	}
 
-	synchronized int unlockReference(LockSet lset, Lockable ref, Object qualifier, Object group) {
+	synchronized int unlockReference(LockTable lset, Lockable ref,
+									 Object qualifier, Object group) {
 
 		// look for locks matching our reference and qualifier.
 		HashMap dl = (HashMap) groups.get(group);
 		if (dl == null)
 			return 0;
 
-		Lock lockInGroup;
-		synchronized (lset) {
-			Control control = lset.getControl(ref);
-			if (control == null)
-				return 0;
-
-			Lock setLock = control.getLock(this, qualifier);
-			if (setLock == null)
-				return 0;
-
-			lockInGroup = (Lock) dl.remove(setLock);
-			if (lockInGroup == null)
-				return 0;
-			setLock = null;
-
-			lset.unlock(lockInGroup, 1);
+		Lock lockInGroup = lset.unlockReference(this, ref, qualifier, dl);
+		if (lockInGroup == null) {
+			return 0;
 		}
 
 		if (lockInGroup.getCount() == 1) {

Added: db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/LockTable.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/LockTable.java?view=auto&rev=515040
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/LockTable.java (added)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/LockTable.java Tue Mar  6 01:17:41 2007
@@ -0,0 +1,152 @@
+/*
+
+   Derby - Class org.apache.derby.impl.services.locks.LockTable
+
+   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.derby.impl.services.locks;
+
+import java.util.Map;
+import org.apache.derby.iapi.error.StandardException;
+import org.apache.derby.iapi.services.locks.CompatibilitySpace;
+import org.apache.derby.iapi.services.locks.Latch;
+import org.apache.derby.iapi.services.locks.Lockable;
+
+/**
+ * Interface which must be implemented by lock table classes.
+ */
+interface LockTable {
+
+    /**
+     * Lock an object.
+     *
+     * @param compatibilitySpace the compatibility space
+     * @param ref the object to lock
+     * @param qualifier qualifier of the lock
+     * @param timeout maximum time to wait in milliseconds
+     * (<code>LockFactory.NO_WAIT</code> means don't wait)
+     * @return a reference to the lock, or <code>null</code> if the timeout was
+     * <code>NO_WAIT</code> and the lock couldn't be obtained immediately
+     * @exception StandardException if the lock could not be obtained
+     */
+    Lock lockObject(CompatibilitySpace compatibilitySpace, Lockable ref,
+                    Object qualifier, int timeout)
+            throws StandardException;
+
+    /**
+     * Unlock an object previously locked by <code>lockObject()</code>.
+     *
+     * @param item the lock to unlock
+     * @param unlockCount the number of times to unlock the item; or zero,
+     * meaning take the unlock count from the item
+     */
+    void unlock(Latch item, int unlockCount);
+
+    /**
+     * Unlock an object once if it is present in the specified group. Also
+     * remove the object from the group.
+     *
+     * @param space the compatibility space
+     * @param ref a reference to the locked object
+     * @param qualifier qualifier of the lock
+     * @param group a map representing the locks in a group
+     * @return the corresponding lock in the group map, or <code>null</code> if
+     * the object was not unlocked
+     */
+    Lock unlockReference(CompatibilitySpace space, Lockable ref,
+                         Object qualifier, Map group);
+
+    /**
+     * Notify the lock table that it has one more waiter.
+     */
+    void oneMoreWaiter();
+
+    /**
+     * Notify the lock table that it has one less waiter.
+     *
+     */
+    void oneLessWaiter();
+
+    /**
+     * Check whether there are anyone blocked in the lock table.
+     *
+     * @return <code>true</code> if someone is blocked, <code>false</code>
+     * otherwise
+     */
+    boolean anyoneBlocked();
+
+    /**
+     * Lock an object and release the lock immediately. Equivalent to
+     * <pre>
+     * Lock lock = lockTable.lockObject(space, ref, qualifier, timeout);
+     * lockTable.unlock(lock, 1);
+     * </pre>
+     * except that the implementation might be more efficient.
+     *
+     * @param space the compatibility space
+     * @param ref a reference to the locked object
+     * @param qualifier qualifier of the lock
+     * @param timeout maximum time to wait in milliseconds
+     * (<code>LockFactory.NO_WAIT</code> means don't wait)
+     * @return <code>true</code> if the object was locked, or
+     * <code>false</code>if the timeout was <code>NO_WAIT</code> and the lock
+     * couldn't be obtained immediately
+     * @exception StandardException if the lock could not be obtained
+     */
+    boolean zeroDurationLockObject(CompatibilitySpace space, Lockable ref,
+                                   Object qualifier, int timeout)
+            throws StandardException;
+
+    /**
+     * Create a map containing a snapshot of all the (<code>Lockable</code>,
+     * <code>LockControl</code>) pairs in the lock table.
+     *
+     * @return a shallow clone of the lock table
+     */
+    Map shallowClone();
+
+    /**
+     * Set the deadlock timeout.
+     *
+     * @param timeout deadlock timeout in milliseconds
+     */
+    void setDeadlockTimeout(int timeout);
+
+    /**
+     * Set the wait timeout.
+     *
+     * @param timeout wait timeout in milliseconds
+     */
+    void setWaitTimeout(int timeout);
+
+    /**
+     * Enable or disable tracing of deadlocks.
+     *
+     * @param flag <code>true</code> enables tracing, <code>false</code>
+     * disables tracing
+     */
+    void setDeadlockTrace(boolean flag);
+
+    /**
+     * Add all waiters in the lock table to the specified map.
+     *
+     * @param waiters the map to add the waiters to
+     * @see LockControl#addWaiters
+     */
+    void addWaiters(Map waiters);
+}

Propchange: db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/LockTable.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/SinglePool.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/SinglePool.java?view=diff&rev=515040&r1=515039&r2=515040
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/SinglePool.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/SinglePool.java Tue Mar  6 01:17:41 2007
@@ -58,7 +58,7 @@
 		<BR>
 		MT - immutable - content dynamic : LockSet is ThreadSafe
 	*/
-	protected final LockSet			lockTable;
+	protected final LockTable lockTable;
 
 	/**
 		True if all deadlocks errors should be logged.
@@ -298,68 +298,8 @@
 										  Lockable ref, Object qualifier,
 										  int timeout)
 		throws StandardException {
-
-		if (SanityManager.DEBUG) {
-			if (SanityManager.DEBUG_ON(Constants.LOCK_TRACE)) {
-
-				D_LockControl.debugLock("Zero Duration Lock Request before Grant: ", 
-                    compatibilitySpace, (Object) null, ref, qualifier, timeout);
-
-                if (SanityManager.DEBUG_ON(Constants.LOCK_STACK_TRACE))
-                {
-                    // The following will print the stack trace of the lock
-                    // request to the log.  
-                    Throwable t = new Throwable();
-                   java.io.PrintWriter istream = SanityManager.GET_DEBUG_STREAM();
-
-                    istream.println("Stack trace of lock request:");
-                    t.printStackTrace(istream);
-                }
-			}
-		}
-
-		// Very fast zeroDurationlockObject() for unlocked objects.
-		// If no entry exists in the lock manager for this reference
-		// then it must be unlocked.
-		// If the object is locked then we perform a grantable
-		// check, skipping over any waiters.
-		// If the caller wants to wait and the lock cannot
-		// be granted then we do the slow join the queue and
-		// release the lock method.
-		synchronized (lockTable) {
-
-			Control control = lockTable.getControl(ref);
-			if (control == null) {
-				return true;
-			}
-
-			// If we are grantable, ignoring waiting locks then
-			// we can also grant this request now, as skipping
-			// over the waiters won't block them as we release
-			// the lock rightway.
-			if (control.isGrantable(true, compatibilitySpace, qualifier))
-				return true;
-
-			// can't be granted and are not willing to wait.
-			if (timeout == C_LockFactory.NO_WAIT)
-				return false;
-		}
-
-		Lock lock = 
-            lockTable.lockObject(compatibilitySpace, ref, qualifier, timeout);
-
-		if (SanityManager.DEBUG) {
-			if (SanityManager.DEBUG_ON(Constants.LOCK_TRACE)) {
-				D_LockControl.debugLock(
-                    "Zero Lock Request Granted: ", 
-                    compatibilitySpace, (Object) null, ref, qualifier, timeout);
-			}
-		}
-
-		// and simply unlock it once
-		lockTable.unlock(lock, 1);
-
-		return true;
+		return lockTable.zeroDurationLockObject(
+			compatibilitySpace, ref, qualifier, timeout);
 	}
 
 	public boolean isLockHeld(CompatibilitySpace compatibilitySpace,
@@ -458,9 +398,11 @@
 		String svalue = (String) value;
 
 		if (key.equals(Property.DEADLOCK_TIMEOUT))
-			lockTable.deadlockTimeout = getWaitValue(svalue,  Property.DEADLOCK_TIMEOUT_DEFAULT);
+			lockTable.setDeadlockTimeout(
+				getWaitValue(svalue,  Property.DEADLOCK_TIMEOUT_DEFAULT));
 		else if (key.equals(Property.LOCKWAIT_TIMEOUT))
-			lockTable.waitTimeout = getWaitValue(svalue,  Property.WAIT_TIMEOUT_DEFAULT);
+			lockTable.setWaitTimeout(
+				getWaitValue(svalue,  Property.WAIT_TIMEOUT_DEFAULT));
 		else if (key.equals(Property.DEADLOCK_MONITOR)) {
 			deadlockMonitor = PropertyUtil.booleanProperty(Property.DEADLOCK_MONITOR, svalue, false) ?
 				StandardException.REPORT_ALWAYS : StandardException.REPORT_DEFAULT;