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 rh...@apache.org on 2014/05/10 15:55:50 UTC

svn commit: r1593702 - in /db/derby/code/trunk/java: engine/org/apache/derby/iapi/error/ engine/org/apache/derby/iapi/services/locks/ engine/org/apache/derby/iapi/sql/dictionary/ engine/org/apache/derby/iapi/store/raw/ engine/org/apache/derby/iapi/stor...

Author: rhillegas
Date: Sat May 10 13:55:50 2014
New Revision: 1593702

URL: http://svn.apache.org/r1593702
Log:
DERBY-6554: Raise SelfDeadlock when a nested subtransaction can't immediately get a lock because it is blocked by its parent transaction; commit derby-6554-02-ae-selfDeadlock_sps_compress.diff.

Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/error/StandardException.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/locks/LockOwner.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/raw/RawStoreFactory.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/xact/TransactionFactory.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/LockControl.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/sql/catalog/SequenceUpdater.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/InsertResultSet.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/access/heap/HeapController.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/RawStore.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/InternalXact.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/Xact.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/XactFactory.java
    db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml
    db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SequenceTest.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/error/StandardException.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/error/StandardException.java?rev=1593702&r1=1593701&r2=1593702&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/error/StandardException.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/error/StandardException.java Sat May 10 13:55:50 2014
@@ -658,6 +658,19 @@ public class StandardException extends E
     }
 
     /**
+     * Is this a self-deadlock exception caused by a nested transaction
+     * being blocked by its parent's locks.
+     * <p>
+     *
+     * @return true if this exception is a self-deadlock.
+     *
+     **/
+    public final boolean isSelfDeadlock() {
+
+        return(SQLState.SELF_DEADLOCK.equals(getSQLState()));
+    }
+
+    /**
      * Is this a lock timeout or lock deadlock exception.
      * <p>
      *

Modified: 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=1593702&r1=1593701&r2=1593702&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/locks/LockOwner.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/locks/LockOwner.java Sat May 10 13:55:50 2014
@@ -51,4 +51,20 @@ public interface LockOwner {
      * {@code false} otherwise
      */
     boolean noWait();
+
+
+    /**
+     * <p>
+     * Return true if this is a nested owner, e.g., a nested user transaction.
+     * </p>
+     */
+    public boolean isNestedOwner();
+
+    /**
+     * <p>
+     * Return true if this owner nests under another owner.
+     * </p>
+     */
+    public boolean nestsUnder( LockOwner other );
+
 }

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=1593702&r1=1593701&r2=1593702&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 May 10 13:55:50 2014
@@ -750,7 +750,10 @@ public class SPSDescriptor extends Uniqu
                         nestedTC.rollbackToSavePoint(savepoint, false, null);
                     }
 
-                    if (nestedTC != null && se.isLockTimeout())
+                    if (
+                        (nestedTC != null) &&
+                        ( se.isLockTimeout() || se.isSelfDeadlock() )
+                        )
 					{
                         // Locks were set nowait, so a lock timeout here
                         // means that some lock request in the nested 

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/RawStoreFactory.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/RawStoreFactory.java?rev=1593702&r1=1593701&r2=1593702&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/RawStoreFactory.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/RawStoreFactory.java Sat May 10 13:55:50 2014
@@ -660,6 +660,7 @@ public interface RawStoreFactory extends
         context is popped off the stack.
         </UL>
 
+        @param parentTransaction parent transaction
         @param compatibilitySpace compatibility space to use for locks.
         @param contextMgr is the context manager to use.  An exception will be
         thrown if context is not the current context.
@@ -674,6 +675,7 @@ public interface RawStoreFactory extends
     */
 
     public Transaction startNestedReadOnlyUserTransaction(
+    Transaction parentTransaction,
     CompatibilitySpace compatibilitySpace,
     ContextManager contextMgr,
     String         transName)
@@ -720,6 +722,7 @@ public interface RawStoreFactory extends
         context is popped off the stack.
         </UL>
 
+        @param parentTransaction parent transaction
         @param contextMgr is the context manager to use.  An exception will be
         thrown if context is not the current context.
         @param transName is the name of the transaction. This name will be 
@@ -737,6 +740,7 @@ public interface RawStoreFactory extends
     */
 
     public Transaction startNestedUpdateUserTransaction(
+    Transaction parentTransaction,
     ContextManager contextMgr,
     String         transName,
     boolean        flush_log_on_xact_end)

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/xact/TransactionFactory.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/xact/TransactionFactory.java?rev=1593702&r1=1593701&r2=1593702&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/xact/TransactionFactory.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/raw/xact/TransactionFactory.java Sat May 10 13:55:50 2014
@@ -95,6 +95,8 @@ public interface TransactionFactory exte
         method will push a transaction context as described in
         RawStoreFactory.startNestedTransaction
 
+		@param rsf                      the RawStoreFactory
+		@param parentTransaction   the parent transaction
 		@param compatibilitySpace   compatibility space to use for locks.
         @param contextMgr           is the context manager to use.  It must be 
                                     the current context manager.
@@ -107,6 +109,7 @@ public interface TransactionFactory exte
 	*/
 	public RawTransaction startNestedReadOnlyUserTransaction(
     RawStoreFactory rsf,
+    RawTransaction parentTransaction,
     CompatibilitySpace compatibilitySpace,
     ContextManager  contextMgr,
     String          transName)
@@ -117,6 +120,8 @@ public interface TransactionFactory exte
         will push a transaction context as described in
         RawStoreFactory.startNestedTransaction
 
+		@param rsf                      the RawStoreFactory
+		@param parentTransaction   the parent transaction
         @param contextMgr               is the context manager to use.  It must
                                         be the current context manager.
         @param transName                is the transaction name. It will be 
@@ -134,6 +139,7 @@ public interface TransactionFactory exte
 	*/
 	public RawTransaction startNestedUpdateUserTransaction(
     RawStoreFactory rsf,
+    RawTransaction parentTransaction,
     ContextManager  contextMgr,
     String          transName,
     boolean         flush_log_on_xact_end)

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=1593702&r1=1593701&r2=1593702&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 May 10 13:55:50 2014
@@ -319,6 +319,7 @@ final class ConcurrentLockSet implements
 		LockControl control;
 		Lock lockItem;
         String  lockDebug = null;
+        boolean blockedByParent = false;
 
         Entry entry = getEntry(ref);
         try {
@@ -355,12 +356,23 @@ final class ConcurrentLockSet implements
 				return lockItem;
 			}
 
-			if (AbstractPool.noLockWait(timeout, compatibilitySpace)) {
-
+            //
+            // This logic supports the use-case of DERBY-6554.
+            //
+            blockedByParent =
+                (timeout == 0) &&
+                compatibilitySpace.getOwner().isNestedOwner() &&
+                control.blockedByParent( lockItem );
+
+			if (
+                AbstractPool.noLockWait(timeout, compatibilitySpace) ||
+                blockedByParent
+                )
+            {
     			// remove all trace of lock
     			control.giveUpWait(lockItem, this);
 
-                if (SanityManager.DEBUG) 
+               if (SanityManager.DEBUG) 
                 {
                     if (SanityManager.DEBUG_ON("DeadlockTrace"))
                     {
@@ -391,11 +403,17 @@ final class ConcurrentLockSet implements
                     }
                 }
 
-				return null;
+               return null;
 			}
 
         } finally {
             entry.unlock();
+            
+            if ( blockedByParent )
+            {
+                throw StandardException.newException
+                    ( SQLState.SELF_DEADLOCK );
+            }
         }
 
 		boolean deadlockWait = false;

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?rev=1593702&r1=1593701&r2=1593702&view=diff
==============================================================================
--- 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 Sat May 10 13:55:50 2014
@@ -24,6 +24,7 @@ package org.apache.derby.impl.services.l
 import org.apache.derby.iapi.services.locks.CompatibilitySpace;
 import org.apache.derby.iapi.services.locks.Lockable;
 import org.apache.derby.iapi.services.locks.Latch;
+import org.apache.derby.iapi.services.locks.LockOwner;
 
 import org.apache.derby.shared.common.sanity.SanityManager;
 
@@ -599,6 +600,42 @@ final class LockControl implements Contr
 		return null;
 	}
 
+    /**
+     * <p>
+     * Returns true if the childLock is blocked because its parent owns
+     * a conficting lock.
+     * This code was written to support the fix to DERBY-6554. The only known
+     * way that this condition arises is when a write attempt by a nested user
+     * transaction is blocked by a read lock held by the main transaction.
+     * This only happens while trying to write to SYS.SYSSEQUENCES while
+     * managing sequence generators.
+     * </p>
+     */
+    public boolean blockedByParent( Lock childLock )
+    {
+        if ( granted == null ) { return false; }
+        
+        LockOwner   childOwner = childLock.getCompatabilitySpace().getOwner();
+        Object          requestedQualifier = childLock.getQualifier();
+
+        for ( Lock grantedLock : granted )
+        {
+            LockOwner   ownerOfGrant = grantedLock.getCompatabilitySpace().getOwner();
+
+            if ( childOwner.nestsUnder( ownerOfGrant ) )
+            {
+                Object  grantedQualifier = grantedLock.getQualifier();
+
+                if ( !grantedLock.getLockable().requestCompatible( requestedQualifier, grantedQualifier ) )
+                {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
 //EXCLUDE-START-lockdiag- 
 	/**
 	 * make a shallow clone of myself

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=1593702&r1=1593701&r2=1593702&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 May 10 13:55:50 2014
@@ -414,6 +414,17 @@ final class UpdateLoader implements Lock
     public boolean noWait() {
         return false;
     }
+    
+    public boolean isNestedOwner()
+    {
+        return false;
+    }
+
+    public boolean nestsUnder( LockOwner other )
+    {
+        return false;
+    }
+    
 }
 
 

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/SequenceUpdater.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/SequenceUpdater.java?rev=1593702&r1=1593701&r2=1593702&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/SequenceUpdater.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/SequenceUpdater.java Sat May 10 13:55:50 2014
@@ -449,6 +449,7 @@ public abstract class SequenceUpdater im
         if ( nestedTransaction != null )
         {
             boolean retval = false;
+            boolean escalateToParentTransaction = false;
             
             try
             {
@@ -456,7 +457,20 @@ public abstract class SequenceUpdater im
             }
             catch (StandardException se)
             {
-                if ( !se.isLockTimeout() ) { throw se; }
+                if ( !se.isLockTimeout() )
+                {
+                    if ( se.isSelfDeadlock() )
+                    {
+                        // We're blocked by a lock held by our parent transaction.
+                        // Escalate into the parent transaction now. See DERBY-6554.
+                        escalateToParentTransaction = true;
+                    }
+                    else
+                    {
+                        Monitor.logThrowable( se );
+                        throw se;
+                    }
+                }
             }
             finally
             {
@@ -467,6 +481,11 @@ public abstract class SequenceUpdater im
                 nestedTransaction.commit();
                 nestedTransaction.destroy();
 
+                if ( escalateToParentTransaction )
+                {
+                    retval = updateCurrentValueOnDisk( executionTransaction, oldValue, newValue, false );
+                }
+
                 return retval;
             }
         }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/InsertResultSet.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/InsertResultSet.java?rev=1593702&r1=1593701&r2=1593702&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/InsertResultSet.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/InsertResultSet.java Sat May 10 13:55:50 2014
@@ -820,7 +820,10 @@ class InsertResultSet extends DMLWriteRe
 					throw se;
 				}
 
-				if (se.getMessageId().equals(SQLState.LOCK_TIMEOUT))
+				if (
+                    se.getMessageId().equals(SQLState.LOCK_TIMEOUT) ||
+                    se.getMessageId().equals(SQLState.SELF_DEADLOCK)
+                    )
 				{
 					// if we couldn't do this with a nested xaction, retry with
 					// parent-- we need to wait this time!

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=1593702&r1=1593701&r2=1593702&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 May 10 13:55:50 2014
@@ -1431,9 +1431,8 @@ public class RAMTransaction 
     long    conglomId)
         throws StandardException
     {
-        findExistingConglomerate(conglomId).purgeConglomerate(
-            this, 
-            rawtran);
+        findExistingConglomerate(conglomId).purgeConglomerate
+            ( this, rawtran );
 
 		return;
     }
@@ -2320,10 +2319,12 @@ public class RAMTransaction 
         Transaction child_rawtran = 
             ((readOnly) ?
                 accessmanager.getRawStore().startNestedReadOnlyUserTransaction(
+                    rawtran, 
                     getLockSpace(), 
                     cm,
                     AccessFactoryGlobals.NESTED_READONLY_USER_TRANS) :
                 accessmanager.getRawStore().startNestedUpdateUserTransaction(
+                    rawtran, 
                     cm, 
                     AccessFactoryGlobals.NESTED_UPDATE_USER_TRANS,
                     flush_log_on_xact_end));

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/heap/HeapController.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/heap/HeapController.java?rev=1593702&r1=1593701&r2=1593702&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/heap/HeapController.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/heap/HeapController.java Sat May 10 13:55:50 2014
@@ -549,10 +549,17 @@ public class HeapController 
     protected boolean lockRowAtSlotNoWaitExclusive(RecordHandle rh)
         throws StandardException
     {
-        return(
-            open_conglom.getContainer().getLockingPolicy().
-                lockRecordForWrite(
-                    open_conglom.getRawTran(), rh, false, false));
+        try {
+            return(
+                   open_conglom.getContainer().getLockingPolicy().
+                   lockRecordForWrite
+                   ( open_conglom.getRawTran(), rh, false, false) );
+        }
+        catch (StandardException se)
+        {
+            if ( se.isSelfDeadlock() ) { return false; }
+            else { throw se; }
+        }
     }
     protected void removePage(Page page)
         throws StandardException

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/RawStore.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/RawStore.java?rev=1593702&r1=1593701&r2=1593702&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/RawStore.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/RawStore.java Sat May 10 13:55:50 2014
@@ -435,25 +435,31 @@ public final class RawStore implements R
 	}
 
 	public Transaction startNestedReadOnlyUserTransaction(
+    Transaction parentTransaction,
     CompatibilitySpace compatibilitySpace,
     ContextManager  contextMgr,
     String          transName)
         throws StandardException
     {
 		return(
-            xactFactory.startNestedReadOnlyUserTransaction(
-                this, compatibilitySpace, contextMgr, transName));
+            xactFactory.startNestedReadOnlyUserTransaction
+            (
+             this, (RawTransaction) parentTransaction, compatibilitySpace, contextMgr, transName)
+            );
 	}
 
 	public Transaction startNestedUpdateUserTransaction(
+    Transaction parentTransaction,
     ContextManager  contextMgr,
     String          transName,
     boolean         flush_log_on_xact_end)
         throws StandardException
     {
 		return(
-            xactFactory.startNestedUpdateUserTransaction(
-                this, contextMgr, transName, flush_log_on_xact_end));
+            xactFactory.startNestedUpdateUserTransaction
+            (
+             this, (RawTransaction) parentTransaction, contextMgr, transName, flush_log_on_xact_end)
+            );
 	}
 
 	public Transaction findUserTransaction(

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/InternalXact.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/InternalXact.java?rev=1593702&r1=1593701&r2=1593702&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/InternalXact.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/InternalXact.java Sat May 10 13:55:50 2014
@@ -56,7 +56,7 @@ public class InternalXact extends Xact  
     DataValueFactory    dataValueFactory) 
     {
 		super(
-            xactFactory, logFactory, dataFactory, dataValueFactory, 
+            xactFactory, null, logFactory, dataFactory, dataValueFactory, 
             false, null, false);
 
 		// always want to hold latches & containers open past the commit/abort

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=1593702&r1=1593701&r2=1593702&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 May 10 13:55:50 2014
@@ -179,6 +179,9 @@ public class Xact extends RawTransaction
 	// id that is valid locally in this raw store.
 	private volatile TransactionId	myId;
 
+    // id of parent transaction if this is a nested user transaction
+    private volatile TransactionId parentTransactionId;
+
 	protected Logger		logger;		// the object we use to access the log.
 
 
@@ -272,8 +275,9 @@ public class Xact extends RawTransaction
 	** Constructor
 	*/
 
-	protected Xact(
+    protected Xact(
     XactFactory         xactFactory, 
+    Xact          parentTransaction, 
     LogFactory          logFactory, 
     DataFactory         dataFactory,
     DataValueFactory    dataValueFactory,
@@ -285,6 +289,10 @@ public class Xact extends RawTransaction
 		super();
 
 		this.xactFactory            = xactFactory;
+        if ( parentTransaction != null )
+        {
+            parentTransactionId = parentTransaction.getId();
+        }
 		this.logFactory             = logFactory;
 		this.dataFactory            = dataFactory;
 		this.dataValueFactory       = dataValueFactory;
@@ -2834,6 +2842,19 @@ public class Xact extends RawTransaction
 		logFactory.checkpointInRFR(cinstant, redoLWM, undoLWM, dataFactory);
 	}
 
+    public boolean isNestedOwner()
+    {
+        return (parentTransactionId != null );
+    }
+
+    public boolean nestsUnder( LockOwner other )
+    {
+        if ( parentTransactionId == null ) { return false; }
+        else if ( !(other instanceof Xact) ) { return false; }
+        {
+            return parentTransactionId.equals( ((Xact) other).getId() );
+        }
+    }
 }
 
 class LockCount {

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/XactFactory.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/XactFactory.java?rev=1593702&r1=1593701&r2=1593702&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/XactFactory.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/XactFactory.java Sat May 10 13:55:50 2014
@@ -253,6 +253,7 @@ public class XactFactory implements Tran
      * Common work done to create local or global transactions.
      *
      * @param rsf    the raw store factory creating this xact.
+     * @param parentTransaction parent transaction (if this is a nested user transaction)
      * @param cm     the current context manager to associate the xact with.
      * @param compatibilitySpace 
      *               if null, use the transaction being created, else if 
@@ -262,6 +263,7 @@ public class XactFactory implements Tran
      **/
     private Xact startCommonTransaction(
     RawStoreFactory     rsf, 
+    Xact                    parentTransaction, 
     ContextManager      cm,
     boolean             readOnly,
     CompatibilitySpace  compatibilitySpace,
@@ -284,7 +286,7 @@ public class XactFactory implements Tran
 
 		Xact xact = 
             new Xact(
-                this, logFactory, dataFactory, dataValueFactory, 
+                this, parentTransaction, logFactory, dataFactory, dataValueFactory, 
                 readOnly, compatibilitySpace, flush_log_on_xact_end);
 
         xact.setTransName(transName);
@@ -304,6 +306,7 @@ public class XactFactory implements Tran
         return(
             startCommonTransaction(
                 rsf, 
+                null, 
                 cm, 
                 false,              // user xact always read/write 
                 null, 
@@ -315,6 +318,7 @@ public class XactFactory implements Tran
 
 	public RawTransaction startNestedReadOnlyUserTransaction(
     RawStoreFactory rsf,
+    RawTransaction parentTransaction,
     CompatibilitySpace compatibilitySpace,
     ContextManager  cm,
     String          transName)
@@ -323,6 +327,7 @@ public class XactFactory implements Tran
         return(
             startCommonTransaction(
                 rsf, 
+                (Xact) parentTransaction, 
                 cm, 
                 true, 
                 compatibilitySpace, 
@@ -335,6 +340,7 @@ public class XactFactory implements Tran
 
 	public RawTransaction startNestedUpdateUserTransaction(
     RawStoreFactory rsf,
+    RawTransaction parentTransaction,
     ContextManager  cm,
     String          transName,
     boolean         flush_log_on_xact_end)
@@ -343,6 +349,7 @@ public class XactFactory implements Tran
         return(
             startCommonTransaction(
                 rsf, 
+                (Xact) parentTransaction, 
                 cm, 
                 false, 
                 null, 
@@ -373,6 +380,7 @@ public class XactFactory implements Tran
         Xact xact =
             startCommonTransaction(
                 rsf, 
+                null, 
                 cm, 
                 false, 
                 null, 
@@ -426,7 +434,7 @@ public class XactFactory implements Tran
 
 		Xact xact = 
             new Xact(
-                this, logFactory, dataFactory, dataValueFactory, 
+                this, null, logFactory, dataFactory, dataValueFactory, 
                 false, null, false);
 
 		// hold latches etc. past commit in NTT

Modified: db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml?rev=1593702&r1=1593701&r2=1593702&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml Sat May 10 13:55:50 2014
@@ -1127,6 +1127,11 @@ Guide.
             </msg>
 
             <msg>
+                <name>40XL2</name>
+                <text>Self-deadlock.</text>
+            </msg>
+
+            <msg>
                 <name>40XT0</name>
                 <text>An internal error was identified by RawStore module.</text>
             </msg>

Modified: db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java?rev=1593702&r1=1593701&r2=1593702&view=diff
==============================================================================
--- db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java (original)
+++ db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java Sat May 10 13:55:50 2014
@@ -271,6 +271,7 @@ public interface SQLState {
 	String DEADLOCK = "40001";
 	String LOCK_TIMEOUT = "40XL1";
     String LOCK_TIMEOUT_LOG = "40XL1.T.1";
+    String SELF_DEADLOCK = "40XL2";
 
 	/*
 	** Store - access.protocol.Interface statement exceptions

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SequenceTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SequenceTest.java?rev=1593702&r1=1593701&r2=1593702&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SequenceTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SequenceTest.java Sat May 10 13:55:50 2014
@@ -644,6 +644,67 @@ public class SequenceTest extends Genera
     }
     
     /**
+     * Verify that a sequence can be used in the same transaction
+     * which created it.
+     */
+    public void test_17_6554() throws Exception
+    {
+        Connection alphaConn = openUserConnection( ALPHA );
+        Connection betaConn = openUserConnection( BETA );
+
+        alphaConn.setAutoCommit( false );
+        betaConn.setAutoCommit( false );
+
+        String  createSequence = "create sequence seq6554";
+        String  nextValueFor = "values next value for seq6554";
+        String[][]  nextValueForResults =
+            new String[][]
+            {
+                { "-2147483648" },
+            }; 
+
+        goodStatement( alphaConn, createSequence );
+        assertResults( alphaConn, nextValueFor, nextValueForResults, true );
+        alphaConn.rollback();
+
+        goodStatement( betaConn, createSequence );
+        assertResults( betaConn, nextValueFor, nextValueForResults, true );
+        betaConn.rollback();
+
+        // now try creating and using the sequence inside the nested
+        // transaction context of a database procedure
+
+        goodStatement
+            (
+             alphaConn,
+             "create procedure createSequence( sequenceName varchar( 128 ) )\n" +
+             "language java parameter style java modifies sql data\n" +
+             "external name 'org.apache.derbyTesting.functionTests.tests.lang.SequenceTest.createSequence'\n"
+             );
+        goodStatement( alphaConn, "grant execute on procedure createSequence to public" );
+        alphaConn.commit();
+
+        String  runProcedure = "call alpha.createSequence( 'seq6554_2' )";
+        String  postProcedureQuery= "values next value for seq6554_2";
+        String[][]  postProcedureResults =
+            new String[][]
+            {
+                { "-2147483647" },
+            };
+
+        goodStatement( alphaConn, runProcedure );
+        assertResults( alphaConn, postProcedureQuery, postProcedureResults, true );
+        alphaConn.rollback();
+        
+        goodStatement( betaConn, runProcedure );
+        assertResults( betaConn, postProcedureQuery, postProcedureResults, true );
+        betaConn.rollback();
+
+        alphaConn.setAutoCommit( true );
+        betaConn.setAutoCommit( true );
+    }
+    
+    /**
      * Verify that sequence numbers pick up where they left off after eviction from
      * the sequence cache.
      */