You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jdo-commits@db.apache.org by mz...@apache.org on 2006/03/09 21:03:12 UTC
svn commit: r384593 -
/db/jdo/trunk/tck20/src/java/org/apache/jdo/tck/api/persistencemanager/ThreadSafe.java
Author: mzaun
Date: Thu Mar 9 12:03:10 2006
New Revision: 384593
URL: http://svn.apache.org/viewcvs?rev=384593&view=rev
Log:
JDO-238 - fixed TCK test case ThreadSafe
Modified:
db/jdo/trunk/tck20/src/java/org/apache/jdo/tck/api/persistencemanager/ThreadSafe.java
Modified: db/jdo/trunk/tck20/src/java/org/apache/jdo/tck/api/persistencemanager/ThreadSafe.java
URL: http://svn.apache.org/viewcvs/db/jdo/trunk/tck20/src/java/org/apache/jdo/tck/api/persistencemanager/ThreadSafe.java?rev=384593&r1=384592&r2=384593&view=diff
==============================================================================
--- db/jdo/trunk/tck20/src/java/org/apache/jdo/tck/api/persistencemanager/ThreadSafe.java (original)
+++ db/jdo/trunk/tck20/src/java/org/apache/jdo/tck/api/persistencemanager/ThreadSafe.java Thu Mar 9 12:03:10 2006
@@ -28,6 +28,7 @@
import org.apache.jdo.tck.pc.mylib.PCPoint;
import org.apache.jdo.tck.util.BatchTestRunner;
import org.apache.jdo.tck.util.ThreadExceptionHandler;
+import org.apache.jdo.tck.util.RogueBarrier;
/**
*<B>Title:</B> Thread Safe
@@ -40,8 +41,6 @@
It is a requirement for all JDO implementations to be thread-safe. That is, the behavior of the implementation must be predictable in the presence of multiple application threads. This assertion will generate multiple test cases to be evaluated.
*/
-
-
public class ThreadSafe extends PersistenceManagerTest {
/** */
@@ -57,118 +56,143 @@
BatchTestRunner.run(ThreadSafe.class);
}
- private PersistenceManagerFactory pmf;
- PCPoint p1 = null;
- private int totalThreadCount = 10;
- private int completedThreadCount = 0;
- private int succeeds = 0;
- private int catchNumber = 0;
+ private final int threadCount = 10;
+ private final ThreadExceptionHandler group = new ThreadExceptionHandler();
+ private final RogueBarrier barrier = new RogueBarrier(threadCount);
+ private int successCount = 0;
+ private int exceptionCount = 0;
/** */
public void testThreadSafe() throws Exception {
- if(debug) logger.debug("\nSTART testThreadSafe");
- pmf = getPMF();
+ if (debug) logger.debug("\nSTART testThreadSafe");
+
+ // test thread-safety of PMF.getPersistenceManager():
+ // pmf.getPM(), pm.close()
+ final PCPoint[] nullPC = new PCPoint[threadCount];
+ runThreads(nullPC, "Concurrent PMF.getPersistenceManager()",
+ threadCount);
+
+ // test thread-safety of PMF.getPersistenceManager():
+ // pmf.getPM(), pm.makePersistent(private transient PC), pm.close()
+ final PCPoint[] localPC = new PCPoint[threadCount];
+ for (int i = 0; i < threadCount; i++) {
+ localPC[i] = new PCPoint(1,i);
+ }
+ runThreads(localPC, "Concurrent PMF.getPersistenceManager()"
+ + ".makePersistent()", threadCount);
- p1 = new PCPoint(3,3);
+ // test thread-safety of PM.makePersistent():
+ // pmf.getPM(), pm.makePersistent(shared transient PC), pm.close()
+ final PCPoint[] sharedPC = new PCPoint[threadCount];
+ final PCPoint p1 = new PCPoint(3,3);
+ for (int i = 0; i < threadCount; i++) {
+ sharedPC[i] = p1;
+ }
+ runThreads(sharedPC, "Concurrent PM.makePersistent("
+ + "shared transient PC)", 1);
+ }
- ThreadExceptionHandler group = new ThreadExceptionHandler();
- Thread[] threads = new Thread[totalThreadCount];
- for (int i=0; i < totalThreadCount; i++) {
- Thread t = new Thread(group, new PMThread(pmf, p1));
+ /** */
+ public void runThreads(Object[] pc, String header, int toSucceed) {
+ // start threads with their pc instance
+ final Thread[] threads = new Thread[threadCount];
+ for (int i = 0; i < threadCount; i++) {
+ Thread t = new Thread(group, new PMThread(pc[i]));
t.setName("ThreadSafeID-" + i);
threads[i] = t;
t.start();
}
- for (int i = 0; i < totalThreadCount; i++) {
- try {
- threads[i].join();
- }
- catch (InterruptedException e) {
- // ignored
+ // wait for all threads to finish
+ for (int i = 0; i < threadCount; i++) {
+ while (true) {
+ try {
+ threads[i].join();
+ break;
+ } catch (InterruptedException e) { // swallow
+ }
}
- }
-
- checkResults(group);
- }
+ }
- /** */
- protected synchronized void complete() {
- completedThreadCount++;
- }
-
- /** */
- protected synchronized void winning(PCPoint pc) {
- if (debug)
- logger.debug("[" + Thread.currentThread().getName() + "]: succeeds");
- succeeds++;
+ checkResults(header, toSucceed);
}
/** */
- public void checkResults(ThreadExceptionHandler group) {
+ protected synchronized void checkResults(String header, int toSucceed) {
// check unhandled exceptions
- Set uncaught = group.getAllUncaughtExceptions();
+ final Set uncaught = group.getAllUncaughtExceptions();
if ((uncaught != null) && !uncaught.isEmpty()) {
StringBuffer report = new StringBuffer("Uncaught exceptions:\n");
for (Iterator i = uncaught.iterator(); i.hasNext();) {
Map.Entry next = (Map.Entry)i.next();
Thread thread = (Thread)next.getKey();
Throwable problem = (Throwable)next.getValue();
- report.append(
- "Uncaught exception " + problem + " in thread " + thread + "\n");
+ report.append(header + ": Uncaught exception " + problem
+ + " in thread " + thread + "\n");
}
fail(ASSERTION_FAILED, report.toString());
+ group.clear();
}
-
- if (succeeds != 1) {
- fail(ASSERTION_FAILED,
- "Only one thread should succeed, number of succeeded threads is " + succeeds);
+
+ // check success count
+ if (successCount != toSucceed) {
+ fail(ASSERTION_FAILED, header + ": Incorrect number of "
+ + "\"succeeding\" threads; expected=" + toSucceed
+ + " found=" + successCount);
}
+ successCount = 0;
- if (catchNumber != totalThreadCount - 1) {
- fail(ASSERTION_FAILED,
- "All but one threads should throw exceptions, expected " +
- (totalThreadCount - 1) + ", got " + catchNumber);
+ // check exception count
+ final int toExcept = threadCount - toSucceed;
+ if (exceptionCount != toExcept) {
+ fail(ASSERTION_FAILED, header + ": Incorrect number of "
+ + "\"failing\" threads; expected=" + toExcept
+ + " found=" + exceptionCount);
}
+ exceptionCount = 0;
+ }
+
+ /** */
+ protected synchronized void markSuccess() {
+ logger.debug("[" + Thread.currentThread().getName() + "]: success");
+ successCount++;
+ }
+
+ /** */
+ protected synchronized void markExpectedException() {
+ logger.debug("[" + Thread.currentThread().getName() + "]: expected exception");
+ exceptionCount++;
}
-/** */
+ /** */
class PMThread implements Runnable {
- private final PersistenceManager pm;
private final Object pc;
/** */
- PMThread(PersistenceManagerFactory pmf, PCPoint pc) {
- this.pm = pmf.getPersistenceManager();
+ PMThread(Object pc) {
this.pc = pc;
}
/** */
public void run() {
- String threadName = Thread.currentThread().getName();
- Transaction tx = pm.currentTransaction();
+ ThreadSafe.this.logger.debug("[" + Thread.currentThread().getName()
+ + "]: running");
+ final PersistenceManager pm = pmf.getPersistenceManager();
try {
- ThreadSafe.this.logger.debug("[" + threadName + "]: running");
+ Transaction tx = pm.currentTransaction();
tx.begin();
- pm.makePersistent(pc);
- tx.commit();
- tx = null;
- winning((PCPoint) pc);
- complete();
- }
- catch (JDOUserException ex) {
- ThreadSafe.this.logger.debug("[" + threadName +
- "]: throws expected " + ex);
- catchNumber++;
- complete();
- }
- finally {
- if ((tx != null) && tx.isActive()) {
- tx.rollback();
+ if (pc != null) {
+ pm.makePersistent(pc);
}
- pm.close();
+ tx.commit();
+ markSuccess();
+ } catch (JDOUserException ex) {
+ markExpectedException();
+ } finally {
+ barrier.await();
+ cleanupPM(pm);
}
- } // run
- } // class PMThread
+ }
+ }
}