001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tctest.restart.unit;
006:
007: import EDU.oswego.cs.dl.util.concurrent.CyclicBarrier;
008: import EDU.oswego.cs.dl.util.concurrent.FutureResult;
009:
010: import com.tc.exception.TCRuntimeException;
011: import com.tc.objectserver.control.ServerControl;
012: import com.tc.test.TCTestCase;
013: import com.tc.test.restart.RestartTestEnvironment;
014: import com.tc.util.PortChooser;
015: import com.tc.util.concurrent.ThreadUtil;
016: import com.tctest.restart.AppStateSnapshot;
017:
018: import java.io.File;
019: import java.util.Iterator;
020:
021: public class DSOServerRestartTester extends TCTestCase {
022:
023: private RestartTestEnvironment env;
024: private long startTimeout = 30 * 1000;
025:
026: public void setUp() throws Exception {
027: super .setUp();
028: env = new RestartTestEnvironment(this .getTempDirectory(),
029: new PortChooser(), RestartTestEnvironment.PROD_MODE);
030: env.setUp();
031: }
032:
033: public void tearDown() throws Exception {
034: assertNoTestThreadExceptions();
035: env.shutdownServer();
036: }
037:
038: public void testLockState() throws Exception {
039: RestartUnitTestApp[] apps = new RestartUnitTestApp[10];
040: for (int i = 0; i < apps.length; i++) {
041: apps[i] = new DSOServerRestartTestApp(env.getThreadGroup());
042: }
043:
044: basicTestLockState(apps);
045:
046: waitForTestThreads();
047: }
048:
049: public void testDSOLockState() throws Exception {
050: env.newExtraProcessServer();
051: env.startServer(startTimeout);
052: RestartUnitTestApp[] apps = newTestApps(10);
053:
054: basicTestLockState(apps);
055:
056: waitForTestThreads();
057: }
058:
059: private void basicTestLockState(RestartUnitTestApp[] apps)
060: throws Exception {
061: Object lck = new Object();
062: AppStateSnapshot snapshot = new AppStateSnapshot(apps);
063: CyclicBarrier startBarrier = new CyclicBarrier(apps.length + 1);
064: for (int i = 0; i < apps.length; i++) {
065: final RestartUnitTestApp app = apps[i];
066: app.setID(i);
067: app.reset();
068: app.setSharedLock(lck);
069: app.setStartBarrier(startBarrier);
070: env.startNewClientThread(new Runnable() {
071: public void run() {
072: app.attemptLock();
073: }
074: });
075: }
076:
077: // wait until all the threads have started.
078: startBarrier.barrier();
079:
080: while (true) {
081: stopServerAndReleaseLock(snapshot);
082: System.out.println(snapshot);
083: if (!snapshot.allEnded() && !env.hasThreadGroupErrors())
084: env.startServer(startTimeout);
085: else
086: break;
087: }
088: }
089:
090: private void stopServerAndReleaseLock(AppStateSnapshot snapshot)
091: throws Exception {
092: RestartUnitTestApp holder = (RestartUnitTestApp) snapshot
093: .getHolder();
094: // there was no holder. We're done.
095: if (holder == null) {
096: if (snapshot.allEnded())
097: return;
098: else
099: fail("No holder, but not all ended: " + snapshot);
100: }
101:
102: // start the shutdown sequence.
103: if (env.getServer().isRunning())
104: env.getServer().attemptShutdown();
105: // XXX: Yuck.
106: Thread.sleep(2000);
107: // release the lock, so the server can shut down.
108: holder.fallThrough();
109: // wait until the server has stopped...
110: while (env.getServer().isRunning()) {
111: Thread.sleep(100);
112: }
113: }
114:
115: public void testDSOWaitNotify() throws Exception {
116: env.newExtraProcessServer();
117: env.startServer(startTimeout);
118: RestartUnitTestApp[] apps = newTestApps(10);
119: basicTestWaitNotify(apps);
120: waitForTestThreads();
121: }
122:
123: private void basicTestWaitNotify(RestartUnitTestApp[] apps)
124: throws Exception {
125: Object lck = new Object();
126: AppStateSnapshot snapshot = new AppStateSnapshot(apps);
127: CyclicBarrier startBarrier = new CyclicBarrier(1);
128: apps[0].setDistributedSharedLock(lck);
129: ServerControl server = env.getServer();
130: for (int i = 0; i < apps.length; i++) {
131: final RestartUnitTestApp app = apps[i];
132: app.setID(i);
133: app.reset();
134: app.setStartBarrier(startBarrier);
135: env.startNewClientThread(new Runnable() {
136: public void run() {
137: app.doWait(0);
138: }
139: });
140: }
141: while (!snapshot.allWaiters()) {
142: // wait until all the threads have had a chance to wait on the distributed
143: // object...
144: snapshot.takeSnapshot();
145: }
146:
147: for (int i = 0; i < apps.length; i++) {
148: // call notify() to allow a single app to continue.
149: apps[0].doNotify();
150: server.shutdown();
151: snapshot.takeSnapshot();
152: System.out.println(snapshot);
153: assertEquals(apps.length - i - 1,
154: snapshot.getWaiters().length);
155: if (i + 1 < apps.length) {
156: server.start();
157: }
158: }
159: snapshot.takeSnapshot();
160: assertTrue(snapshot.allEnded());
161: }
162:
163: public void testDSOWaitNotifyAll() throws Exception {
164: env.newExtraProcessServer().start();
165: RestartUnitTestApp[] apps = newTestApps(10);
166: basicTestWaitNotifyAll(apps);
167: waitForTestThreads();
168: }
169:
170: public void testDSOTimedWait() throws Exception {
171: env.newExtraProcessServer().start();
172: RestartUnitTestApp[] apps = newTestApps(10);
173: basicTestTimedWait(apps);
174: waitForTestThreads();
175: }
176:
177: private void basicTestTimedWait(RestartUnitTestApp[] apps)
178: throws Exception {
179: ServerControl server = env.getServer();
180: Object lck = new Object();
181: AppStateSnapshot snapshot = new AppStateSnapshot(apps);
182: RestartUnitTestApp shutdownBlocker = newTestApps(1)[0];
183: shutdownBlocker.setStartBarrier(new CyclicBarrier(1));
184: final CyclicBarrier startBarrier = new CyclicBarrier(
185: apps.length + 1);
186: apps[0].setDistributedSharedLock(lck);
187: final int waitTime = 10 * 1000;
188: for (int i = 0; i < apps.length; i++) {
189: final RestartUnitTestApp app = apps[i];
190: app.setID(i);
191: app.reset();
192: app.setStartBarrier(startBarrier);
193: env.startNewClientThread(new Runnable() {
194: public void run() {
195: app.doWait(waitTime);
196: }
197: });
198: }
199:
200: startBarrier.barrier();
201: while (!snapshot.takeSnapshot().allWaiters()) {
202: System.out.println("Waiting for all apps to be waiters: "
203: + snapshot);
204: ThreadUtil.reallySleep(100);
205: }
206: System.out.println("obtaining a lock to block shutdown...");
207: FutureResult shutdownBlockerBarrier = new FutureResult();
208: shutdownBlocker.blockShutdown(shutdownBlockerBarrier);
209: System.out.println("starting server shutdown sequence...");
210: server.attemptShutdown();
211: System.out
212: .println("waiting for timers to go off in server before allowing shutdown to complete...");
213: ThreadUtil.reallySleep(waitTime + 1000);
214: System.out
215: .println("letting the server finish shutting down...");
216: shutdownBlockerBarrier.set(new Object());
217: System.out
218: .println("waiting until server is actually shut down...");
219: server.waitUntilShutdown();
220:
221: assertTrue(snapshot.takeSnapshot().allWaiters());
222: ThreadUtil.reallySleep(waitTime);
223: assertTrue(snapshot.takeSnapshot().allWaiters());
224: server.start();
225: while (!snapshot.takeSnapshot().allEnded()) {
226: System.out.println(snapshot);
227: ThreadUtil.reallySleep(500);
228: }
229: }
230:
231: private void basicTestWaitNotifyAll(RestartUnitTestApp[] apps)
232: throws Exception {
233: ServerControl server = env.getServer();
234: Object lck = new Object();
235: AppStateSnapshot snapshot = new AppStateSnapshot(apps);
236: CyclicBarrier startBarrier = new CyclicBarrier(1);
237: apps[0].setDistributedSharedLock(lck);
238: for (int i = 0; i < apps.length; i++) {
239: final RestartUnitTestApp app = apps[i];
240: app.setID(i);
241: app.reset();
242: app.setStartBarrier(startBarrier);
243: env.startNewClientThread(new Runnable() {
244: public void run() {
245: app.doWait(0);
246: }
247: });
248: }
249: // wait until all the threads have waited on the object.
250: while (!snapshot.allWaiters()) {
251: snapshot.takeSnapshot();
252: }
253:
254: server.shutdown();
255: final CyclicBarrier serverStartBarrier = new CyclicBarrier(2);
256: final RestartUnitTestApp app = apps[0];
257: new Thread(new Runnable() {
258: public void run() {
259: try {
260: serverStartBarrier.barrier();
261: app.doNotifyAll();
262: } catch (Exception e) {
263: throw new TCRuntimeException(e);
264: }
265: }
266: }).start();
267:
268: serverStartBarrier.barrier();
269: server.start();
270: do {
271: snapshot.takeSnapshot();
272: System.out.println(snapshot);
273: Thread.sleep(500);
274: } while (!snapshot.allEnded());
275: }
276:
277: private RestartUnitTestApp newRestartTestApp(ThreadGroup tg)
278: throws Exception {
279: // FIXME 2005-12-01 andrew
280: // IsolationClassLoader cl = new IsolationClassLoader(env.getDSOConfig(), env.getL1DSOConfig());
281: // Class clazz = cl.loadClass(DSOServerRestartTestApp.class.getName());
282: // Constructor ctor = clazz.getConstructor(new Class[] { ThreadGroup.class });
283: // return (RestartUnitTestApp) ctor.newInstance(new Object[] { tg });
284: return null;
285: }
286:
287: private RestartUnitTestApp[] newTestApps(int instanceCount)
288: throws Exception {
289: // FIXME 2005-12-01 andrew
290: // DSOServerRestartTestApp.visitL1DSOConfig(null, env.getL1DSOConfig());
291: RestartUnitTestApp[] apps = new RestartUnitTestApp[instanceCount];
292: for (int i = 0; i < apps.length; i++) {
293: apps[i] = newRestartTestApp(env.getThreadGroup());
294: }
295: return apps;
296: }
297:
298: public void testServerStartAndStop() throws Exception {
299: env.newExtraProcessServer();
300: assertTrue(isEmptyDirectory(env.getDBHome()));
301: env.startServer(startTimeout);
302: env.shutdownServer();
303: assertFalse(isEmptyDirectory(env.getDBHome()));
304: }
305:
306: private boolean isEmptyDirectory(File dir) {
307: if (dir.exists()) {
308: if (!dir.isDirectory())
309: return false;
310: if (dir.listFiles().length != 0)
311: return false;
312: }
313: return true;
314: }
315:
316: private void waitForTestThreads() {
317: while (!env.hasThreadGroupErrors() && env.hasActiveClients()) {
318: ThreadUtil.reallySleep(500);
319: }
320: }
321:
322: private void assertNoTestThreadExceptions() {
323: boolean failed = false;
324: for (Iterator i = env.getThreadGroupErrors().iterator(); i
325: .hasNext();) {
326: ((Throwable) i.next()).printStackTrace();
327: failed = true;
328: }
329: assertFalse("There were test thread exceptions", failed);
330: }
331: }
|