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;
005:
006: import com.tc.object.bytecode.Manageable;
007: import com.tc.object.bytecode.ManagerUtil;
008: import com.tc.object.config.ConfigVisitor;
009: import com.tc.object.config.DSOClientConfigHelper;
010: import com.tc.object.config.TransparencyClassSpec;
011: import com.tc.simulator.app.ApplicationConfig;
012: import com.tc.simulator.listener.ListenerProvider;
013: import com.tc.util.Assert;
014: import com.tc.util.DebugUtil;
015: import com.tctest.runner.AbstractTransparentApp;
016:
017: import java.util.Iterator;
018: import java.util.Random;
019: import java.util.concurrent.CyclicBarrier;
020: import java.util.concurrent.LinkedBlockingQueue;
021:
022: public class LinkedBlockingQueueCrashTestApp extends
023: AbstractTransparentApp {
024: int upbound = 2000;
025: long MaxRuntimeMillis = 5 * 60 * 1000 + 30000;
026:
027: private final CyclicBarrier barrier = new CyclicBarrier(
028: getParticipantCount());
029: private final LinkedBlockingQueue<EventNode> lbqueue1 = new LinkedBlockingQueue<EventNode>();
030: private final LinkedBlockingQueue<EventNode> lbqueue2 = new LinkedBlockingQueue<EventNode>();
031: private final EventNode eventIndex = new EventNode(0, "test");
032: private final GetController controller = new GetController(
033: getParticipantCount());
034:
035: public LinkedBlockingQueueCrashTestApp(String appId,
036: ApplicationConfig cfg, ListenerProvider listenerProvider) {
037: super (appId, cfg, listenerProvider);
038: }
039:
040: public void run() {
041: try {
042: DebugUtil.DEBUG = false;
043: int index = barrier.await();
044:
045: testBlockingQueue(index);
046:
047: DebugUtil.DEBUG = false;
048: } catch (Throwable t) {
049: notifyError(t);
050: }
051: }
052:
053: public static void visitL1DSOConfig(ConfigVisitor visitor,
054: DSOClientConfigHelper config) {
055:
056: String testClass = LinkedBlockingQueueCrashTestApp.class
057: .getName();
058: TransparencyClassSpec spec = config.getOrCreateSpec(testClass);
059: config.addIncludePattern(testClass + "$*", false, false, true);
060:
061: String methodExpression = "* " + testClass + "*.*(..)";
062: config.addWriteAutolock(methodExpression);
063: methodExpression = "* " + EventNode.class.getName() + "*.*(..)";
064: config.addWriteAutolock(methodExpression);
065: methodExpression = "* " + GetController.class.getName()
066: + "*.*(..)";
067: config.addWriteAutolock(methodExpression);
068:
069: spec.addRoot("barrier", "barrier");
070: spec.addRoot("lbqueue1", "lbqueue1");
071: spec.addRoot("lbqueue2", "lbqueue2");
072: spec.addRoot("eventIndex", "eventIndex");
073: spec.addRoot("controller", "controller");
074: }
075:
076: private void testBlockingQueue(int index) throws Exception {
077: EventNode node = null;
078: Random r = new Random();
079: long endTime = System.currentTimeMillis() + MaxRuntimeMillis;
080:
081: while (true) {
082:
083: // avoid all are getter
084: boolean doPut;
085: if (r.nextBoolean()) {
086: doPut = true;
087: } else {
088: synchronized (controller) {
089: doPut = controller.canDoGet() ? false : true;
090: if (!doPut)
091: controller.incGetter();
092: }
093: }
094:
095: if (doPut) {
096: node = doPut();
097: System.err.println("*** Doing put id=" + node.getId()
098: + " by thread= " + index + ", client: "
099: + ManagerUtil.getClientID());
100: } else {
101: node = doPass();
102: System.err.println("*** Doing pass id=" + node.getId()
103: + " by thread= " + index + ", client: "
104: + ManagerUtil.getClientID());
105: controller.decGetter();
106: }
107: // ended when total nodes exceed
108: if (node.getId() >= upbound)
109: controller.ending();
110: // limited by time too
111: if (System.currentTimeMillis() >= endTime)
112: controller.ending();
113:
114: if (controller.canQuit())
115: break;
116:
117: Thread.sleep(r.nextInt(20));
118: }
119: index = barrier.await();
120:
121: // verify
122: if (index == 0) {
123: System.err.println("*** Start verification");
124: // verify size
125: Assert.assertTrue("Wrong event count",
126: eventIndex.getId() == lbqueue1.size()
127: + lbqueue2.size());
128:
129: // verify no event lost
130: int lastItem;
131: synchronized (eventIndex) {
132: lastItem = eventIndex.getId();
133: eventIndex.setId(0);
134: }
135: int id = 0;
136: while (id < lastItem) {
137: EventNode event;
138: event = lbqueue2.peek();
139: if ((event != null) && (id == event.getId())) {
140: lbqueue2.take();
141: } else {
142: boolean found = false;
143: // searching for the event
144: Iterator it = lbqueue2.iterator();
145: while (it.hasNext()) {
146: event = (EventNode) it.next();
147: if (id == event.getId()) {
148: found = true;
149: lbqueue2.remove(event);
150: break;
151: }
152: }
153: if (!found) {
154: it = lbqueue1.iterator();
155: while (it.hasNext()) {
156: event = (EventNode) it.next();
157: if (id == event.getId()) {
158: found = true;
159: lbqueue1.remove(event);
160: break;
161: }
162: }
163: }
164:
165: Assert.assertTrue("Event " + id + " not found",
166: found);
167: }
168: ++id;
169: if (id % 10 == 0)
170: System.err.println("*** Verify id=" + id);
171: } // while
172:
173: Assert.assertTrue("Duplicate events found", 0 == (lbqueue1
174: .size() + lbqueue2.size()));
175:
176: System.err.println("*** Verification Successful");
177: }
178:
179: index = barrier.await();
180: }
181:
182: private EventNode doPut() throws Exception {
183: EventNode node;
184: synchronized (eventIndex) {
185: node = eventIndex.produce();
186: }
187: lbqueue1.put(node);
188: return (node);
189: }
190:
191: private EventNode doGet() throws Exception {
192: EventNode node = lbqueue2.take();
193: return (node);
194: }
195:
196: private EventNode doPass() throws Exception {
197: EventNode node;
198: if (DebugUtil.DEBUG) {
199: System.err.println("Client " + ManagerUtil.getClientID()
200: + " doPass -- queue size: " + lbqueue1.size());
201: }
202: node = lbqueue1.take();
203: if (DebugUtil.DEBUG) {
204: if (node instanceof Manageable) {
205: System.err.println("Client "
206: + ManagerUtil.getClientID()
207: + " passing id: "
208: + node.getId()
209: + " objectID: "
210: + ((Manageable) node).__tc_managed()
211: .getObjectID());
212: }
213: System.err.println("Client "
214: + ManagerUtil.getClientID()
215: + " passing from queue: "
216: + ((Manageable) lbqueue1).__tc_managed()
217: .getObjectID()
218: + " to queue: "
219: + ((Manageable) lbqueue2).__tc_managed()
220: .getObjectID());
221: }
222: lbqueue2.put(node);
223: return (node);
224: }
225:
226: private static class EventNode {
227: EventNode next;
228: String name;
229: int id;
230:
231: public EventNode produce() {
232: EventNode node;
233: node = new EventNode(getId(), "Event" + getId());
234: setId(getId() + 1);
235: // System.out.println("*** Produce id=" + node.getId());
236: return (node);
237: }
238:
239: public EventNode(int id, String name) {
240: this .id = id;
241: this .name = name;
242: }
243:
244: public EventNode getNextNode() {
245: return (next);
246: }
247:
248: public void setNextNode(EventNode next) {
249: this .next = next;
250: }
251:
252: public int getId() {
253: return (id);
254: }
255:
256: public void setId(int id) {
257: this .id = id;
258: }
259:
260: public String toString() {
261: return name;
262: }
263: }
264:
265: public static class GetController {
266: private int participants, getters;
267: private boolean ending = false;
268:
269: public GetController(int participant) {
270: this .participants = participant;
271: getters = 0;
272: }
273:
274: public synchronized void incGetter() throws Exception {
275: ++getters;
276: System.out.println("*** incGetter " + getters);
277: Assert.assertTrue("Stuck in every node is a getter",
278: getters < participants);
279: }
280:
281: public synchronized void decGetter() throws Exception {
282: --getters;
283: System.out.println("*** decGetter " + getters);
284: Assert
285: .assertTrue("Negative number of getter",
286: getters >= 0);
287: }
288:
289: public synchronized int nGetters() {
290: return (getters);
291: }
292:
293: public synchronized boolean canDoGet() {
294: // no more getter if ending the test
295: if (ending)
296: return (false);
297: else
298: return (getters < (participants - 1));
299: }
300:
301: public synchronized void clean() {
302: getters = 0;
303: }
304:
305: public synchronized void ending() {
306: ending = true;
307: }
308:
309: public synchronized boolean canQuit() {
310: if (ending && (getters == 0))
311: return true;
312: else
313: return false;
314: }
315: }
316:
317: }
|