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:35:48 UTC
svn commit: r688274 - in /db/derby/code/trunk/java:
engine/org/apache/derby/iapi/services/locks/
engine/org/apache/derby/iapi/sql/dictionary/
engine/org/apache/derby/iapi/store/access/
engine/org/apache/derby/iapi/store/raw/ engine/org/apache/derby/imp...
Author: kahatlen
Date: Sat Aug 23 00:35:47 2008
New Revision: 688274
URL: http://svn.apache.org/viewvc?rev=688274&view=rev
Log:
DERBY-3693: Deadlocks accessing DB metadata
Make sure that the nested transaction used to recompile meta-data
queries does not wait for locks to prevent hangs when there's a lock
conflict between the nested transaction and the user transaction.
Added:
db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/locks/LockOwner.java (with props)
Modified:
db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/locks/CompatibilitySpace.java
db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/locks/LockFactory.java
db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/SPSDescriptor.java
db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/access/TransactionController.java
db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/Transaction.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/AbstractPool.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/ConcurrentLockSet.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/LockTable.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/services/reflect/UpdateLoader.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/RAMTransaction.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/Xact.java
db/derby/code/trunk/java/storeless/org/apache/derby/impl/storeless/NoOpTransaction.java
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DatabaseMetaDataTest.java
Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/locks/CompatibilitySpace.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/locks/CompatibilitySpace.java?rev=688274&r1=688273&r2=688274&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/locks/CompatibilitySpace.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/locks/CompatibilitySpace.java Sat Aug 23 00:35:47 2008
@@ -41,5 +41,5 @@
* @return object representing the owner of the compatibility space, or
* <code>null</code> if no owner has been specified.
*/
- Object getOwner();
+ LockOwner getOwner();
}
Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/locks/LockFactory.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/locks/LockFactory.java?rev=688274&r1=688273&r2=688274&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/locks/LockFactory.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/locks/LockFactory.java Sat Aug 23 00:35:47 2008
@@ -46,7 +46,7 @@
* transaction object). Might be <code>null</code>.
* @return an object which represents a compatibility space
*/
- public CompatibilitySpace createCompatibilitySpace(Object owner);
+ public CompatibilitySpace createCompatibilitySpace(LockOwner owner);
/**
Lock an object within a compatibility space
Added: db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/locks/LockOwner.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/locks/LockOwner.java?rev=688274&view=auto
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/locks/LockOwner.java (added)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/locks/LockOwner.java Sat Aug 23 00:35:47 2008
@@ -0,0 +1,36 @@
+/*
+ * Derby - Class org.apache.derby.iapi.services.locks.LockOwner
+ *
+ * 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.iapi.services.locks;
+
+/**
+ * Interface for classes that represent an owner of the locks within a
+ * compatibility space.
+ */
+public interface LockOwner {
+ /**
+ * Tells whether lock requests should time out immediately if the lock
+ * cannot be granted at once, even if {@code C_LockFactory.TIMED_WAIT}
+ * was specified in the lock request.
+ *
+ * @return {@code true} if timed waits should time out immediately,
+ * {@code false} otherwise
+ */
+ boolean noWait();
+}
Propchange: db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/locks/LockOwner.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/SPSDescriptor.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/SPSDescriptor.java?rev=688274&r1=688273&r2=688274&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/SPSDescriptor.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/SPSDescriptor.java Sat Aug 23 00:35:47 2008
@@ -692,6 +692,10 @@
try
{
nestedTC = lcc.getTransactionCompile().startNestedUserTransaction(false);
+ // DERBY-3693: The nested transaction may run into a lock
+ // conflict with its parent transaction, in which case we
+ // don't want to wait for a timeout.
+ nestedTC.setNoLockWait(true);
}
catch (StandardException se)
{
Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/access/TransactionController.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/access/TransactionController.java?rev=688274&r1=688273&r2=688274&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/access/TransactionController.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/access/TransactionController.java Sat Aug 23 00:35:47 2008
@@ -1482,6 +1482,15 @@
public CompatibilitySpace getLockSpace();
/**
+ * Tell this transaction whether it should time out immediately if a lock
+ * cannot be granted without waiting.
+ *
+ * @param noWait if {@code true} never wait for a lock in this transaction,
+ * but time out immediately
+ */
+ public void setNoLockWait(boolean noWait);
+
+ /**
* Return static information about the conglomerate to be included in a
* a compiled plan.
* <p>
Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/Transaction.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/Transaction.java?rev=688274&r1=688273&r2=688274&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/Transaction.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/Transaction.java Sat Aug 23 00:35:47 2008
@@ -59,6 +59,14 @@
**/
CompatibilitySpace getCompatibilitySpace();
+ /**
+ * Tell this transaction whether it should time out immediately if a lock
+ * cannot be granted without waiting.
+ *
+ * @param noWait if {@code true} never wait for a lock in this transaction,
+ * but time out immediately
+ */
+ void setNoLockWait(boolean noWait);
/**
Called after the transaction has been attached to an Access Manger
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/AbstractPool.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/AbstractPool.java?rev=688274&r1=688273&r2=688274&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/AbstractPool.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/AbstractPool.java Sat Aug 23 00:35:47 2008
@@ -39,6 +39,8 @@
import java.io.Serializable;
import java.util.Dictionary;
import java.util.Enumeration;
+import org.apache.derby.iapi.reference.SQLState;
+import org.apache.derby.iapi.services.locks.LockOwner;
/**
* An abstract implementation of LockFactory that allows different
@@ -120,8 +122,16 @@
// See if NO_WAIT was passed in and the lock could not be granted.
if (lock == null) {
if (SanityManager.DEBUG) {
- SanityManager.ASSERT(timeout == C_LockFactory.NO_WAIT, "timeout not NO_WAIT");
+ SanityManager.ASSERT(noLockWait(timeout, compatibilitySpace),
+ "timeout not NO_WAIT");
}
+
+ // If this is a timed wait, we should behave as if we timed out
+ // and throw a LOCK_TIMEOUT.
+ if (timeout == C_LockFactory.TIMED_WAIT) {
+ throw StandardException.newException(SQLState.LOCK_TIMEOUT);
+ }
+
return false;
}
@@ -145,7 +155,7 @@
* @param owner the owner of the compatibility space
* @return an object which represents a compatibility space
*/
- public CompatibilitySpace createCompatibilitySpace(Object owner) {
+ public CompatibilitySpace createCompatibilitySpace(LockOwner owner) {
return new LockSpace(owner);
}
@@ -284,8 +294,27 @@
Lockable ref, Object qualifier,
int timeout)
throws StandardException {
- return lockTable.zeroDurationLockObject(
+ boolean success = lockTable.zeroDurationLockObject(
compatibilitySpace, ref, qualifier, timeout);
+
+ if (!success) {
+
+ // zeroDurationLockObject should only return false if we have
+ // requested that we shouldn't wait for locks. Otherwise, an
+ // exception should have been thrown.
+ if (SanityManager.DEBUG) {
+ SanityManager.ASSERT(noLockWait(timeout, compatibilitySpace),
+ "Should have timed out");
+ }
+
+ // If this is a timed wait, we should behave as if we timed out and
+ // throw LOCK_TIMEOUT.
+ if (timeout == C_LockFactory.TIMED_WAIT) {
+ throw StandardException.newException(SQLState.LOCK_TIMEOUT);
+ }
+ }
+
+ return success;
}
public boolean isLockHeld(CompatibilitySpace compatibilitySpace,
@@ -307,6 +336,26 @@
((LockSpace) compatibilitySpace).clearLimit(group);
}
+ /**
+ * Check if we should not wait for locks, given the specified timeout and
+ * compatibility space. If the timeout is {@code C_LockFactory.NO_WAIT} or
+ * the {@code LockOwner} has the {@code noWait} flag set, we shouldn't
+ * wait for locks.
+ *
+ * @param timeout the specified timeout
+ * @param compat the compatibility space
+ * @return {@code true} if we shouldn't wait for locks, {@code false}
+ * otherwise
+ */
+ static boolean noLockWait(int timeout, CompatibilitySpace compat) {
+ if (timeout == C_LockFactory.NO_WAIT) {
+ return true;
+ } else {
+ LockOwner owner = compat.getOwner();
+ return owner != null && owner.noWait();
+ }
+ }
+
//EXCLUDE-START-lockdiag-
/**
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/ConcurrentLockSet.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/ConcurrentLockSet.java?rev=688274&r1=688273&r2=688274&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/ConcurrentLockSet.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/ConcurrentLockSet.java Sat Aug 23 00:35:47 2008
@@ -355,7 +355,7 @@
return lockItem;
}
- if (timeout == C_LockFactory.NO_WAIT) {
+ if (AbstractPool.noLockWait(timeout, compatibilitySpace)) {
// remove all trace of lock
control.giveUpWait(lockItem, this);
@@ -792,22 +792,7 @@
}
/**
- * 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
+ * {@inheritDoc}
*/
public boolean zeroDurationLockObject(
CompatibilitySpace space, Lockable ref, Object qualifier, int timeout)
@@ -860,7 +845,7 @@
}
// can't be granted and are not willing to wait.
- if (timeout == C_LockFactory.NO_WAIT) {
+ if (AbstractPool.noLockWait(timeout, space)) {
return false;
}
} finally {
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?rev=688274&r1=688273&r2=688274&view=diff
==============================================================================
--- 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 Sat Aug 23 00:35:47 2008
@@ -183,7 +183,7 @@
return lockItem;
}
- if (timeout == C_LockFactory.NO_WAIT) {
+ if (AbstractPool.noLockWait(timeout, compatibilitySpace)) {
// remove all trace of lock
control.giveUpWait(lockItem, this);
@@ -579,22 +579,7 @@
}
/**
- * 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
+ * {@inheritDoc}
*/
public boolean zeroDurationLockObject(
CompatibilitySpace space, Lockable ref, Object qualifier, int timeout)
@@ -641,7 +626,7 @@
}
// can't be granted and are not willing to wait.
- if (timeout == C_LockFactory.NO_WAIT) {
+ if (AbstractPool.noLockWait(timeout, space)) {
return false;
}
}
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?rev=688274&r1=688273&r2=688274&view=diff
==============================================================================
--- 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 Sat Aug 23 00:35:47 2008
@@ -32,6 +32,7 @@
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
+import org.apache.derby.iapi.services.locks.LockOwner;
/**
@@ -53,7 +54,7 @@
/** Map from group references to groups of locks. */
private final HashMap groups;
/** Reference to the owner of this compatibility space. */
- private final Object owner;
+ private final LockOwner owner;
private HashMap spareGroups[] = new HashMap[3];
@@ -68,7 +69,7 @@
*
* @param owner an object representing the owner of the compatibility space
*/
- LockSpace(Object owner) {
+ LockSpace(LockOwner owner) {
groups = new HashMap();
this.owner = owner;
}
@@ -78,7 +79,7 @@
*
* @return the owner of the compatibility space
*/
- public Object getOwner() {
+ public LockOwner getOwner() {
return owner;
}
Modified: 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?rev=688274&r1=688273&r2=688274&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/LockTable.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/services/locks/LockTable.java Sat Aug 23 00:35:47 2008
@@ -39,9 +39,10 @@
* @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
+ * ({@code C_LockFactory.NO_WAIT} means don't wait)
+ * @return a reference to the lock, or <code>null</code> if the lock
+ * couldn't be obtained immediately and the timeout was {@code NO_WAIT}
+ * or {@code LockOwner} had the {@code noWait} flag set
* @exception StandardException if the lock could not be obtained
*/
Lock lockObject(CompatibilitySpace compatibilitySpace, Lockable ref,
@@ -102,10 +103,10 @@
* @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)
+ * ({@code C_LockFactory.NO_WAIT} 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
+ * {@code false} if the object couldn't be locked immediately and timeout
+ * was {@code NO_WAIT} or {@code LockOwner} had the {@code noWait} flag set
* @exception StandardException if the lock could not be obtained
*/
boolean zeroDurationLockObject(CompatibilitySpace space, Lockable ref,
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/services/reflect/UpdateLoader.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/services/reflect/UpdateLoader.java?rev=688274&r1=688273&r2=688274&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/services/reflect/UpdateLoader.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/services/reflect/UpdateLoader.java Sat Aug 23 00:35:47 2008
@@ -23,7 +23,6 @@
import org.apache.derby.iapi.services.context.ContextService;
import org.apache.derby.iapi.services.monitor.Monitor;
-import org.apache.derby.iapi.services.monitor.Monitor;
import org.apache.derby.iapi.services.stream.HeaderPrintWriter;
import org.apache.derby.iapi.util.IdUtil;
import org.apache.derby.iapi.error.StandardException;
@@ -46,6 +45,7 @@
import org.apache.derby.iapi.reference.Module;
import org.apache.derby.iapi.services.i18n.MessageService;
import org.apache.derby.iapi.services.locks.CompatibilitySpace;
+import org.apache.derby.iapi.services.locks.LockOwner;
/**
* UpdateLoader implements then functionality of
@@ -62,7 +62,7 @@
* UpdateLoader will then try to load the class from each of the jars
* in order of derby.database.classpath using the jar's installed JarLoader.
*/
-final class UpdateLoader {
+final class UpdateLoader implements LockOwner {
/**
* List of packages that Derby will not support being loaded
@@ -404,6 +404,16 @@
}
return jarReader;
}
+
+ /**
+ * Tell the lock manager that we don't want timed waits to time out
+ * immediately.
+ *
+ * @return {@code false}
+ */
+ public boolean noWait() {
+ return false;
+ }
}
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/RAMTransaction.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/RAMTransaction.java?rev=688274&r1=688273&r2=688274&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/RAMTransaction.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/RAMTransaction.java Sat Aug 23 00:35:47 2008
@@ -2436,6 +2436,23 @@
}
/**
+ * Tell this transaction whether it should skip waiting for locks and
+ * instead time out immediately.
+ *
+ * <p>
+ *
+ * For now, this only works if the transaction has its own compatibility
+ * space. If it has inherited the compatibility space from its parent,
+ * the request will be ignored (or cause a failure in debug builds).
+ *
+ * @param noWait if {@code true} never wait for a lock, but time out
+ * immediately
+ */
+ public void setNoLockWait(boolean noWait) {
+ rawtran.setNoLockWait(noWait);
+ }
+
+ /**
* Get string id of the transaction.
* <p>
* This transaction "name" will be the same id which is returned in
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/Xact.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/Xact.java?rev=688274&r1=688273&r2=688274&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/Xact.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/Xact.java Sat Aug 23 00:35:47 2008
@@ -58,8 +58,6 @@
import org.apache.derby.iapi.services.property.PersistentSet;
-import org.apache.derby.catalog.UUID;
-
import java.util.Stack;
import java.util.Enumeration;
import java.util.Properties;
@@ -76,11 +74,9 @@
import org.apache.derby.iapi.services.property.PropertyUtil;
import org.apache.derby.iapi.reference.Property;
-import org.apache.derby.impl.store.raw.log.LogToFile;
-
import org.apache.derby.iapi.services.io.LimitObjectInput;
-import org.apache.derby.iapi.services.context.ContextService;
+import org.apache.derby.iapi.services.locks.LockOwner;
/**
@@ -98,7 +94,7 @@
@see Transaction
*/
-public class Xact extends RawTransaction implements Limit {
+public class Xact extends RawTransaction implements Limit, LockOwner {
/*
** Static Fields
@@ -252,6 +248,11 @@
// backup copy.
private boolean backupBlocked;
+ /**
+ * Tells if lock requests should time out immediately if they cannot be
+ * granted without waiting.
+ */
+ private boolean dontWaitForLocks;
/*
** Constructor
@@ -571,6 +572,39 @@
return(this.compatibilitySpace);
}
+ /**
+ * Tells whether lock requests should time out immediately if they can't
+ * be granted without waiting. Only works if this object is the owner of
+ * the compatibility space used in the request.
+ *
+ * @return whether waiting for locks should time out immediately
+ */
+ public boolean noWait() {
+ return dontWaitForLocks;
+ }
+
+ /**
+ * Set whether lock requests should time out immediately if they can't be
+ * granted without waiting.
+ *
+ * <p>
+ *
+ * This only works if this transaction is the owner of the compatibility
+ * space used in the request. If this transaction has inherited the
+ * compatibility space from its parent, the call to this method has no
+ * effect (except in debug builds, where an error will be raised).
+ *
+ * @param noWait whether lock requests should time out immediately if
+ * they can't be granted without waiting
+ */
+ public void setNoLockWait(boolean noWait) {
+ if (SanityManager.DEBUG) {
+ SanityManager.ASSERT(compatibilitySpace.getOwner() == this,
+ "Trying to set no-wait mode on transaction that " +
+ "shares compatibility space with its parent");
+ }
+ dontWaitForLocks = noWait;
+ }
/**
get the short (internal to raw store) transaction id that is unique
Modified: db/derby/code/trunk/java/storeless/org/apache/derby/impl/storeless/NoOpTransaction.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/storeless/org/apache/derby/impl/storeless/NoOpTransaction.java?rev=688274&r1=688273&r2=688274&view=diff
==============================================================================
--- db/derby/code/trunk/java/storeless/org/apache/derby/impl/storeless/NoOpTransaction.java (original)
+++ db/derby/code/trunk/java/storeless/org/apache/derby/impl/storeless/NoOpTransaction.java Sat Aug 23 00:35:47 2008
@@ -422,4 +422,8 @@
return(null);
}
+ public void setNoLockWait(boolean noWait) {
+ // TODO Auto-generated method stub
+ }
+
}
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DatabaseMetaDataTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DatabaseMetaDataTest.java?rev=688274&r1=688273&r2=688274&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DatabaseMetaDataTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DatabaseMetaDataTest.java Sat Aug 23 00:35:47 2008
@@ -44,6 +44,7 @@
import java.util.List;
import java.util.Locale;
//import java.util.Map;
+import java.util.Properties;
import java.util.Random;
import java.util.StringTokenizer;
@@ -210,6 +211,23 @@
// test from waiting one minute
DatabasePropertyTestSetup.setLockTimeouts(
new DatabaseMetaDataTest("initialCompilationTest"), 2, 4)));
+
+ // Test for DERBY-3693 needs a fresh database to ensure that the size
+ // of SYSTABLES is so small that creating a relatively small number of
+ // tables will cause the query plan for getTables() to be invalidated.
+ // Also, set a high lock timeout explicitly so that we can check that
+ // an internal timeout followed by a retry didn't happen, and set
+ // derby.language.stalePlanCheckInterval to a low value so that the
+ // invalidation happens earlier.
+ Properties props = new Properties();
+ props.setProperty("derby.locks.waitTimeout", "90");
+ props.setProperty("derby.language.stalePlanCheckInterval", "5");
+ suite.addTest(
+ TestConfiguration.singleUseDatabaseDecorator(
+ new DatabasePropertyTestSetup(
+ new DatabaseMetaDataTest("recompileTimeoutTest"),
+ props, true)));
+
return suite;
}
@@ -290,6 +308,44 @@
}
/**
+ * Tests that we don't get an internal timeout when a meta-data statement
+ * is recompiled because the size of the tables it queries has changed
+ * (DERBY-3693). The test must be run on a fresh database, to ensure that
+ * SYSTABLES initially has a relatively small number of records. The lock
+ * timeout must be high (more than 60 seconds) to enable us to see the
+ * difference between an internal lock timeout and slow execution.
+ * derby.language.stalePlanCheckInterval should be set to 5 (the lowest
+ * possible value) so that we don't have to wait long for the query plan
+ * to be invalidated.
+ */
+ public void recompileTimeoutTest() throws SQLException {
+ DatabaseMetaData dmd = getDMD();
+
+ // Make sure getTables() is initially compiled while SYSTABLES is small
+ JDBC.assertDrainResults(dmd.getTables(null, "%", "%", null));
+
+ // Grow SYSTABLES
+ Statement s = createStatement();
+ for (int i = 0; i < 20; i++) {
+ s.executeUpdate("create table t" + i + "(x int)");
+ }
+
+ // Execute getTables() derby.language.stalePlanCheckInterval times so
+ // that its plan is invalidated. Before DERBY-3693 was fixed, the
+ // recompilation after the invalidation would get an internal timeout
+ // and take very long time to complete.
+ for (int i = 0; i < 5; i++) {
+ long time = System.currentTimeMillis();
+ JDBC.assertDrainResults(dmd.getTables(null, "%", "T0", null));
+ time = System.currentTimeMillis() - time;
+ if (time > 60000) {
+ fail("getTables() took a very long time, possibly because " +
+ "of an internal timeout. i=" + i + ", time=" + time);
+ }
+ }
+ }
+
+ /**
* Test the methods that indicate if a feature
* is supported or not. Methods start with
* 'support'. See secton 7.3 in JDBC 3.0 specification.