mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged V3.3-BUG-FIX to HEAD
23319: Merged V3.3 to V3.3-BUG-FIX 23318: Merged PATCHES/V3.2.0 to V3.3 23317: ALF-5141: Fix unit test failure - Hopefully bullet-proof thread synchronization. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@23320 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -22,7 +22,10 @@ import java.util.Collections;
|
|||||||
import java.util.ConcurrentModificationException;
|
import java.util.ConcurrentModificationException;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import javax.transaction.Status;
|
import javax.transaction.Status;
|
||||||
@@ -557,13 +560,13 @@ public class RetryingTransactionHelperTest extends TestCase
|
|||||||
final List<Throwable> caughtExceptions = Collections.synchronizedList(new LinkedList<Throwable>());
|
final List<Throwable> caughtExceptions = Collections.synchronizedList(new LinkedList<Throwable>());
|
||||||
|
|
||||||
// Try submitting a request after a timeout
|
// Try submitting a request after a timeout
|
||||||
runThreads(txnHelper, caughtExceptions, new Pair(2, 1000), new Pair(1, 5000), new Pair(4, 1000));
|
runThreads(txnHelper, caughtExceptions, new Pair(0, 1000), new Pair(0, 5000), new Pair(4000, 1000));
|
||||||
assertEquals("Expected 1 exception", 1, caughtExceptions.size());
|
assertEquals("Expected 1 exception", 1, caughtExceptions.size());
|
||||||
assertTrue("Excpected TooBusyException", caughtExceptions.get(0) instanceof TooBusyException);
|
assertTrue("Excpected TooBusyException", caughtExceptions.get(0) instanceof TooBusyException);
|
||||||
|
|
||||||
// Stay within timeout limits
|
// Stay within timeout limits
|
||||||
caughtExceptions.clear();
|
caughtExceptions.clear();
|
||||||
runThreads(txnHelper, caughtExceptions, new Pair(2, 1000), new Pair(1, 2000), new Pair(4, 1000));
|
runThreads(txnHelper, caughtExceptions, new Pair(0, 1000), new Pair(0, 2000), new Pair(0, 1000), new Pair(1000, 1000), new Pair(1000, 2000), new Pair(2000, 1000));
|
||||||
if (caughtExceptions.size() > 0)
|
if (caughtExceptions.size() > 0)
|
||||||
{
|
{
|
||||||
throw new RuntimeException("Unexpected exception", caughtExceptions.get(0));
|
throw new RuntimeException("Unexpected exception", caughtExceptions.get(0));
|
||||||
@@ -592,70 +595,78 @@ public class RetryingTransactionHelperTest extends TestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void runThreads(final RetryingTransactionHelper txnHelper, final List<Throwable> caughtExceptions,
|
private void runThreads(final RetryingTransactionHelper txnHelper, final List<Throwable> caughtExceptions,
|
||||||
Pair<Integer, Integer>... countDurationPairs)
|
Pair<Integer, Integer>... startDurationPairs)
|
||||||
{
|
{
|
||||||
final CountDownLatch endLatch = new CountDownLatch(countDurationPairs.length);
|
ExecutorService executorService = new ThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS,
|
||||||
|
new ArrayBlockingQueue<Runnable>(10));
|
||||||
|
|
||||||
class Callback implements RetryingTransactionCallback<Void>
|
|
||||||
{
|
|
||||||
private final int duration;
|
|
||||||
|
|
||||||
public Callback(int duration)
|
|
||||||
{
|
|
||||||
this.duration = duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Void execute() throws Throwable
|
|
||||||
{
|
|
||||||
Thread.sleep(duration);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
;
|
|
||||||
class Work implements Runnable
|
class Work implements Runnable
|
||||||
{
|
{
|
||||||
private final CountDownLatch startLatch;
|
private final CountDownLatch startLatch;
|
||||||
private final Callback callback;
|
private final long endTime;
|
||||||
private final int execCount;
|
|
||||||
|
|
||||||
public Work(CountDownLatch startLatch, Callback callback, int execCount)
|
public Work(CountDownLatch startLatch, long endTime)
|
||||||
{
|
{
|
||||||
this.startLatch = startLatch;
|
this.startLatch = startLatch;
|
||||||
this.callback = callback;
|
this.endTime = endTime;
|
||||||
this.execCount = execCount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run()
|
public void run()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
txnHelper.doInTransaction(new RetryingTransactionCallback<Void>()
|
||||||
|
{
|
||||||
|
|
||||||
|
public Void execute() throws Throwable
|
||||||
{
|
{
|
||||||
// Signal that we've started
|
// Signal that we've started
|
||||||
startLatch.countDown();
|
startLatch.countDown();
|
||||||
|
|
||||||
for (int i = 0; i < execCount; i++)
|
long duration = endTime - System.currentTimeMillis();
|
||||||
|
if (duration > 0)
|
||||||
{
|
{
|
||||||
try
|
Thread.sleep(duration);
|
||||||
{
|
}
|
||||||
txnHelper.doInTransaction(callback);
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
catch (Throwable e)
|
catch (Throwable e)
|
||||||
{
|
{
|
||||||
caughtExceptions.add(e);
|
caughtExceptions.add(e);
|
||||||
|
// We never got a chance to signal we had started so do it now
|
||||||
|
if (startLatch.getCount() > 0)
|
||||||
|
{
|
||||||
|
startLatch.countDown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
endLatch.countDown();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
// Fire the threads
|
// Schedule the transactions at their required start times
|
||||||
int j = 0;
|
long startTime = System.currentTimeMillis();
|
||||||
for (Pair<Integer, Integer> pair : countDurationPairs)
|
long currentStart = 0;
|
||||||
|
for (Pair<Integer, Integer> pair : startDurationPairs)
|
||||||
{
|
{
|
||||||
|
int start = pair.getFirst();
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
long then = startTime + start;
|
||||||
|
if (then > now)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Thread.sleep(then - now);
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
currentStart = start;
|
||||||
|
}
|
||||||
CountDownLatch startLatch = new CountDownLatch(1);
|
CountDownLatch startLatch = new CountDownLatch(1);
|
||||||
Runnable work = new Work(startLatch, new Callback(pair.getSecond()), pair.getFirst());
|
Runnable work = new Work(startLatch, startTime + currentStart + pair.getSecond());
|
||||||
Thread thread = new Thread(work);
|
executorService.execute(work);
|
||||||
thread.setName(getName() + "-" + j++);
|
|
||||||
thread.setDaemon(true);
|
|
||||||
thread.start();
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Wait for the thread to get up and running. We need them starting in sequence
|
// Wait for the thread to get up and running. We need them starting in sequence
|
||||||
@@ -666,9 +677,10 @@ public class RetryingTransactionHelperTest extends TestCase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Wait for the threads to have finished
|
// Wait for the threads to have finished
|
||||||
|
executorService.shutdown();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
endLatch.await(60, TimeUnit.SECONDS);
|
executorService.awaitTermination(60, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
catch (InterruptedException e)
|
catch (InterruptedException e)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user