mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged HEAD-BUG-FIX (4.3/Cloud) to HEAD (4.3/Cloud)
59123: Merged V4.2-BUG-FIX (4.2.1) to HEAD-BUG-FIX (Cloud/4.3) 59111: Merged V4.1-BUG-FIX (4.1.8) to V4.2-BUG-FIX (4.2.1) 59070: Merged DEV to V4.1-BUG-FIX (4.1.8) 58849: MNT-10096: MT: AbstractTenantRoutingContentStore can return null list of stores - Ensure that RetryingTransactionHelper starts a transaction in txn-after-completion phase (MNT-9806). git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@62103 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -366,8 +366,7 @@ public class RetryingTransactionHelper
|
|||||||
}
|
}
|
||||||
|
|
||||||
// First validate the requiresNew setting
|
// First validate the requiresNew setting
|
||||||
boolean startingNew = requiresNew;
|
if (!requiresNew)
|
||||||
if (!startingNew)
|
|
||||||
{
|
{
|
||||||
TxnReadState readState = AlfrescoTransactionSupport.getTransactionReadState();
|
TxnReadState readState = AlfrescoTransactionSupport.getTransactionReadState();
|
||||||
switch (readState)
|
switch (readState)
|
||||||
@@ -385,7 +384,7 @@ public class RetryingTransactionHelper
|
|||||||
break;
|
break;
|
||||||
case TXN_NONE:
|
case TXN_NONE:
|
||||||
// There is no current transaction so we need a new one.
|
// There is no current transaction so we need a new one.
|
||||||
startingNew = true;
|
requiresNew = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new RuntimeException("Unknown transaction state: " + readState);
|
throw new RuntimeException("Unknown transaction state: " + readState);
|
||||||
@@ -395,7 +394,7 @@ public class RetryingTransactionHelper
|
|||||||
// If we are time limiting, set ourselves a time limit and maintain the count of concurrent transactions
|
// If we are time limiting, set ourselves a time limit and maintain the count of concurrent transactions
|
||||||
long startTime = 0;
|
long startTime = 0;
|
||||||
Throwable stackTrace = null;
|
Throwable stackTrace = null;
|
||||||
if (startingNew && maxExecutionMs > 0)
|
if (requiresNew && maxExecutionMs > 0)
|
||||||
{
|
{
|
||||||
startTime = System.currentTimeMillis();
|
startTime = System.currentTimeMillis();
|
||||||
synchronized (this)
|
synchronized (this)
|
||||||
@@ -433,11 +432,10 @@ public class RetryingTransactionHelper
|
|||||||
UserTransaction txn = null;
|
UserTransaction txn = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (startingNew)
|
if (requiresNew)
|
||||||
{
|
{
|
||||||
txn = requiresNew ?
|
txn = txnService.getNonPropagatingUserTransaction(readOnly, forceWritable);
|
||||||
txnService.getNonPropagatingUserTransaction(readOnly, forceWritable) :
|
|
||||||
txnService.getUserTransaction(readOnly, forceWritable);
|
|
||||||
txn.begin();
|
txn.begin();
|
||||||
// Wrap it to protect it
|
// Wrap it to protect it
|
||||||
UserTransactionProtectionAdvise advise = new UserTransactionProtectionAdvise();
|
UserTransactionProtectionAdvise advise = new UserTransactionProtectionAdvise();
|
||||||
@@ -588,7 +586,7 @@ public class RetryingTransactionHelper
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (startingNew && maxExecutionMs > 0)
|
if (requiresNew && maxExecutionMs > 0)
|
||||||
{
|
{
|
||||||
synchronized (this)
|
synchronized (this)
|
||||||
{
|
{
|
||||||
|
@@ -246,6 +246,12 @@ public class AlfrescoTransactionSupportTest extends TestCase
|
|||||||
{
|
{
|
||||||
postCommitReadState[0] = AlfrescoTransactionSupport.getTransactionReadState();
|
postCommitReadState[0] = AlfrescoTransactionSupport.getTransactionReadState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterRollback()
|
||||||
|
{
|
||||||
|
postCommitReadState[0] = AlfrescoTransactionSupport.getTransactionReadState();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
RetryingTransactionCallback<TxnReadState> getReadStateWork = new RetryingTransactionCallback<TxnReadState>()
|
RetryingTransactionCallback<TxnReadState> getReadStateWork = new RetryingTransactionCallback<TxnReadState>()
|
||||||
@@ -271,6 +277,20 @@ public class AlfrescoTransactionSupportTest extends TestCase
|
|||||||
checkTxnReadState = transactionService.getRetryingTransactionHelper().doInTransaction(getReadStateWork, false);
|
checkTxnReadState = transactionService.getRetryingTransactionHelper().doInTransaction(getReadStateWork, false);
|
||||||
assertEquals("Expected 'read-write transaction'", TxnReadState.TXN_READ_WRITE, checkTxnReadState);
|
assertEquals("Expected 'read-write transaction'", TxnReadState.TXN_READ_WRITE, checkTxnReadState);
|
||||||
assertEquals("Expected 'no transaction'", TxnReadState.TXN_NONE, postCommitReadState[0]);
|
assertEquals("Expected 'no transaction'", TxnReadState.TXN_NONE, postCommitReadState[0]);
|
||||||
|
|
||||||
|
// Check TXN_NONE on rollback
|
||||||
|
UserTransaction txn = transactionService.getUserTransaction();
|
||||||
|
txn.begin();
|
||||||
|
AlfrescoTransactionSupport.bindListener(getReadStatePostCommit);
|
||||||
|
txn.rollback();
|
||||||
|
assertEquals("Expected 'no transaction'", TxnReadState.TXN_NONE, postCommitReadState[0]);
|
||||||
|
|
||||||
|
// Check TXN_NONE on commit
|
||||||
|
txn = transactionService.getUserTransaction();
|
||||||
|
txn.begin();
|
||||||
|
AlfrescoTransactionSupport.bindListener(getReadStatePostCommit);
|
||||||
|
txn.commit();
|
||||||
|
assertEquals("Expected 'no transaction'", TxnReadState.TXN_NONE, postCommitReadState[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testResourceHelper() throws Exception
|
public void testResourceHelper() throws Exception
|
||||||
|
@@ -334,7 +334,7 @@ public class RetryingTransactionHelperTest extends TestCase
|
|||||||
/**
|
/**
|
||||||
* Checks nesting of two transactions with <code>requiresNew == false</code>
|
* Checks nesting of two transactions with <code>requiresNew == false</code>
|
||||||
*/
|
*/
|
||||||
public void testNestedWithPropogation()
|
public void testNestedWithPropagation()
|
||||||
{
|
{
|
||||||
RetryingTransactionCallback<Long> callback = new RetryingTransactionCallback<Long>()
|
RetryingTransactionCallback<Long> callback = new RetryingTransactionCallback<Long>()
|
||||||
{
|
{
|
||||||
@@ -362,7 +362,7 @@ public class RetryingTransactionHelperTest extends TestCase
|
|||||||
/**
|
/**
|
||||||
* Checks nesting of two transactions with <code>requiresNew == true</code>
|
* Checks nesting of two transactions with <code>requiresNew == true</code>
|
||||||
*/
|
*/
|
||||||
public void testNestedWithoutPropogation()
|
public void testNestedWithoutPropagation()
|
||||||
{
|
{
|
||||||
RetryingTransactionCallback<Long> callback = new RetryingTransactionCallback<Long>()
|
RetryingTransactionCallback<Long> callback = new RetryingTransactionCallback<Long>()
|
||||||
{
|
{
|
||||||
@@ -390,17 +390,18 @@ public class RetryingTransactionHelperTest extends TestCase
|
|||||||
/**
|
/**
|
||||||
* Checks nesting of two transactions with <code>requiresNew == true</code>,
|
* Checks nesting of two transactions with <code>requiresNew == true</code>,
|
||||||
* but where the two transactions get involved in a concurrency struggle.
|
* but where the two transactions get involved in a concurrency struggle.
|
||||||
*
|
* <p/>
|
||||||
* Note: skip test for non-MySQL
|
* Note: skip test for non-MySQL
|
||||||
*/
|
*/
|
||||||
public void testNestedWithoutPropogationConcurrentUntilFailureMySQL() throws InterruptedException
|
public void testNestedWithoutPropagationConcurrentUntilFailureMySQL() throws InterruptedException
|
||||||
{
|
{
|
||||||
final RetryingTransactionHelper txnHelperForTest = transactionService.getRetryingTransactionHelper();
|
final RetryingTransactionHelper txnHelperForTest = transactionService.getRetryingTransactionHelper();
|
||||||
txnHelperForTest.setMaxRetries(1);
|
txnHelperForTest.setMaxRetries(1);
|
||||||
|
|
||||||
if (! (dialect instanceof MySQLInnoDBDialect))
|
if (! (dialect instanceof MySQLInnoDBDialect))
|
||||||
{
|
{
|
||||||
// NOOP - skip test for non-MySQL DB dialects to avoid hang if concurrently "nested" (in terms of Spring) since the initial transaction does not complete
|
// NOOP - skip test for non-MySQL DB dialects to avoid hang if concurrently "nested" (in terms of Spring)
|
||||||
|
// since the initial transaction does not complete
|
||||||
// see testConcurrencyRetryingNoFailure instead
|
// see testConcurrencyRetryingNoFailure instead
|
||||||
logger.warn("NOTE: Skipping testNestedWithoutPropogationConcurrentUntilFailureMySQLOnly for dialect: "+dialect);
|
logger.warn("NOTE: Skipping testNestedWithoutPropogationConcurrentUntilFailureMySQLOnly for dialect: "+dialect);
|
||||||
}
|
}
|
||||||
@@ -556,6 +557,7 @@ public class RetryingTransactionHelperTest extends TestCase
|
|||||||
assertEquals("Should have been called exactly once", 1, callCount.intValue());
|
assertEquals("Should have been called exactly once", 1, callCount.intValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
public void testTimeLimit()
|
public void testTimeLimit()
|
||||||
{
|
{
|
||||||
final RetryingTransactionHelper txnHelper = new RetryingTransactionHelper();
|
final RetryingTransactionHelper txnHelper = new RetryingTransactionHelper();
|
||||||
@@ -617,7 +619,39 @@ public class RetryingTransactionHelperTest extends TestCase
|
|||||||
assertEquals("Should have been called tree times", 3, callCount.intValue());
|
assertEquals("Should have been called tree times", 3, callCount.intValue());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testStartNewTransaction() throws Exception
|
||||||
|
{
|
||||||
|
// MNT-10096
|
||||||
|
class CustomListenerAdapter extends TransactionListenerAdapter
|
||||||
|
{
|
||||||
|
private String newTxnId;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterRollback()
|
||||||
|
{
|
||||||
|
newTxnId = txnHelper.doInTransaction(new RetryingTransactionCallback<String>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public String execute() throws Throwable
|
||||||
|
{
|
||||||
|
return AlfrescoTransactionSupport.getTransactionId();
|
||||||
|
}
|
||||||
|
}, true, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UserTransaction txn = transactionService.getUserTransaction();
|
||||||
|
txn.begin();
|
||||||
|
String txnId = AlfrescoTransactionSupport.getTransactionId();
|
||||||
|
CustomListenerAdapter listener = new CustomListenerAdapter();
|
||||||
|
|
||||||
|
AlfrescoTransactionSupport.bindListener(listener);
|
||||||
|
txn.rollback();
|
||||||
|
|
||||||
|
assertFalse("New transaction has not started", txnId.equals(listener.newTxnId));
|
||||||
|
}
|
||||||
|
|
||||||
private void runThreads(final RetryingTransactionHelper txnHelper, final List<Throwable> caughtExceptions,
|
private void runThreads(final RetryingTransactionHelper txnHelper, final List<Throwable> caughtExceptions,
|
||||||
Pair<Integer, Integer>... startDurationPairs)
|
Pair<Integer, Integer>... startDurationPairs)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user