001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package com.tctest.transparency;
005:
006: import com.tc.object.config.ConfigVisitor;
007: import com.tc.object.config.DSOClientConfigHelper;
008: import com.tc.object.config.TransparencyClassSpec;
009: import com.tc.object.config.spec.CyclicBarrierSpec;
010: import com.tc.simulator.app.ApplicationConfig;
011: import com.tc.simulator.listener.ListenerProvider;
012: import com.tc.util.Assert;
013: import com.tc.util.concurrent.ThreadUtil;
014: import com.tctest.runner.AbstractErrorCatchingTransparentApp;
015:
016: import java.util.ArrayList;
017: import java.util.Iterator;
018: import java.util.List;
019: import java.util.Random;
020:
021: public class SubClassOfThreadGotRootTestApp extends
022: AbstractErrorCatchingTransparentApp {
023:
024: private static final int WORKER_COUNT = 5;
025: private static final int WORK_COUNT = 10;
026:
027: private static final int CREATED_WORKERS = 0;
028: private static final int CREATED_WORK = 1;
029: private static final int WORK_DONE = 2;
030: private static final int VERIFIED = 2;
031:
032: private ArrayList workers = new ArrayList();
033:
034: public SubClassOfThreadGotRootTestApp(String appId,
035: ApplicationConfig cfg, ListenerProvider listenerProvider) {
036: super (appId, cfg, listenerProvider);
037: Assert.assertTrue(getParticipantCount() == 2);
038: }
039:
040: public static void visitL1DSOConfig(ConfigVisitor visitor,
041: DSOClientConfigHelper config) {
042: String workerClass = SubClassOfThreadGotRootTestApp.Worker.class
043: .getName();
044: String workClass = SubClassOfThreadGotRootTestApp.Work.class
045: .getName();
046: TransparencyClassSpec spec = config
047: .getOrCreateSpec(workerClass);
048: String workerMethodExpression = "* " + workerClass + "*.*(..)";
049: String workMethodExpression = "* " + workClass + "*.*(..)";
050: config.addWriteAutolock(workerMethodExpression);
051: config.addWriteAutolock(workMethodExpression);
052: spec.addRoot("workQueue", "workQueue");
053:
054: CyclicBarrierSpec cbspec = new CyclicBarrierSpec();
055: cbspec.visit(visitor, config);
056:
057: // config.addExcludePattern("*..SubClassA");
058:
059: // Include everything to be instrumented.
060: config.addIncludePattern("*..*", false);
061: }
062:
063: protected void runTest() throws Throwable {
064:
065: for (int i = 0; i < WORKER_COUNT; i++) {
066: Worker worker = new Worker(getApplicationId(), i);
067: workers.add(worker);
068: worker.start();
069: }
070:
071: moveToStageAndWait(CREATED_WORKERS);
072:
073: Random r = new Random();
074:
075: for (int i = 0; i < WORKER_COUNT; i++) {
076: Worker w = (Worker) workers.get(i);
077: for (int j = 0; j < WORK_COUNT; j++) {
078: w.addWork(new Work(getApplicationId(), r
079: .nextInt(Integer.MAX_VALUE), r
080: .nextInt(Integer.MAX_VALUE)));
081: }
082: }
083:
084: moveToStageAndWait(CREATED_WORK);
085:
086: for (int i = 0; i < WORKER_COUNT; i++) {
087: Worker w = (Worker) workers.get(i);
088: w.waitToCompleteAndStop();
089: }
090:
091: moveToStageAndWait(WORK_DONE);
092:
093: for (int i = 0; i < WORKER_COUNT; i++) {
094: Worker w = (Worker) workers.get(i);
095: List workDone = w.getWorkDone();
096: System.err.println(Thread.currentThread().getName()
097: + " verifying " + workDone.size()
098: + " works done by " + w.getName());
099: for (Iterator j = workDone.iterator(); j.hasNext();) {
100: Work work = (Work) j.next();
101: work.verify();
102: }
103: }
104: moveToStage(VERIFIED);
105:
106: }
107:
108: // This class has the root
109: public class Worker extends Thread {
110:
111: List workQueue = new ArrayList();
112: List workDone = new ArrayList();
113:
114: boolean stopRequested = false;
115: private final String appId;
116:
117: public Worker(String appId, int i) {
118: super (appId + "," + i);
119: this .appId = appId;
120: }
121:
122: public void run() {
123: Random r = new Random();
124: while (!stopRequested) {
125: Work work = getWork();
126: if (work != null) {
127: work.run();
128: workDone.add(work);
129: } else if (!stopRequested) {
130: ThreadUtil.reallySleep(r.nextInt(2000) + 1);
131: }
132: }
133: }
134:
135: private int getSize() {
136: synchronized (workQueue) {
137: return workQueue.size();
138: }
139: }
140:
141: private Work getWork() {
142: synchronized (workQueue) {
143: while (workQueue.size() == 0 && !stopRequested) {
144: try {
145: workQueue.wait();
146: } catch (InterruptedException e) {
147: throw new RuntimeException(e);
148: }
149: }
150: if (stopRequested)
151: return null;
152: workQueue.notifyAll();
153: for (Iterator iter = workQueue.iterator(); iter
154: .hasNext();) {
155: Work work = (Work) iter.next();
156: if (!work.getAppId().equals(appId)) {
157: iter.remove();
158: return work;
159: }
160: }
161: System.err
162: .println("I, "
163: + getName()
164: + " couldn't get any foreign work. Trying again - Size = "
165: + getSize());
166: return null;
167: }
168: }
169:
170: public void addWork(Work work) {
171: synchronized (workQueue) {
172: workQueue.add(work);
173: workQueue.notify();
174: }
175: }
176:
177: public void waitToCompleteAndStop() {
178: synchronized (workQueue) {
179: while (workQueue.size() != 0) {
180: try {
181: workQueue.wait();
182: } catch (InterruptedException e) {
183: throw new RuntimeException(e);
184: }
185: }
186: stopRequested = true;
187: workQueue.notifyAll();
188: }
189: }
190:
191: public List getWorkDone() {
192: return workDone;
193: }
194: }
195:
196: // This is the Portable Object
197: public static class Work implements Runnable {
198:
199: int n1, n2;
200: long add, sub, multi;
201: double div;
202:
203: String workerName;
204: private final String appId;
205:
206: public Work(String appId, int n1, int n2) {
207: this .appId = appId;
208: this .n1 = n1;
209: this .n2 = n2;
210: }
211:
212: public String getAppId() {
213: return this .appId;
214: }
215:
216: public synchronized void run() {
217: workerName = Thread.currentThread().getName();
218: System.err.println("Worker " + workerName + " working on "
219: + this );
220: add = add();
221: sub = subtract();
222: multi = multiply();
223: div = divide();
224: }
225:
226: private double divide() {
227: if (n2 != 0) {
228: return n1 / n2;
229: } else {
230: return Double.NaN;
231: }
232: }
233:
234: private long multiply() {
235: return n1 * n2;
236: }
237:
238: private long subtract() {
239: return n1 - n2;
240: }
241:
242: private long add() {
243: return n1 + n2;
244: }
245:
246: public synchronized void verify() {
247: Assert.assertEquals(add, add());
248: Assert.assertEquals(sub, subtract());
249: Assert.assertEquals(multi, multiply());
250: if (Double.isNaN(div)) {
251: Assert.assertTrue(Double.isNaN(divide()));
252: } else {
253: Assert.assertEquals(div, divide());
254: }
255: }
256:
257: public String toString() {
258: return "Work(" + appId + "):{" + n1 + "," + n2 + "}";
259: }
260:
261: }
262:
263: }
|