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.object.config.ConfigLockLevel;
012: import com.tc.object.config.ConfigVisitor;
013: import com.tc.object.config.DSOClientConfigHelper;
014: import com.tc.object.config.LockDefinition;
015: import com.tc.object.config.LockDefinitionImpl;
016: import com.tc.object.config.Root;
017: import com.tctest.restart.AbstractRestartTestApp;
018:
019: import java.lang.reflect.InvocationTargetException;
020:
021: public class DSOServerRestartTestApp extends AbstractRestartTestApp
022: implements RestartUnitTestApp {
023:
024: private final FutureResult fallThroughControl = new FutureResult();
025: private final Object[] sharedLockHolder = new Object[1];
026: private final Object[] distributedSharedLockHolder = new Object[1];
027: private CyclicBarrier startBarrier;
028:
029: public DSOServerRestartTestApp(ThreadGroup threadGroup) {
030: super (threadGroup);
031: changeState(INIT);
032: }
033:
034: public String toString() {
035: return getClass().getName() + "[" + getID() + ", "
036: + state.peek() + "]";
037: }
038:
039: public void setStartBarrier(CyclicBarrier startBarrier) {
040: this .startBarrier = startBarrier;
041: }
042:
043: public void setSharedLock(Object lck) {
044: synchronized (this .sharedLockHolder) {
045: this .sharedLockHolder[0] = lck;
046: }
047: }
048:
049: public void setDistributedSharedLock(Object lck) {
050: synchronized (this .distributedSharedLockHolder) {
051: this .distributedSharedLockHolder[0] = lck;
052: }
053: }
054:
055: public Object getSharedLock() {
056: Object rv = null;
057: synchronized (this .sharedLockHolder) {
058: if (this .sharedLockHolder[0] != null)
059: rv = this .sharedLockHolder[0];
060: }
061: if (rv == null) {
062: synchronized (this .distributedSharedLockHolder) {
063: rv = this .distributedSharedLockHolder[0];
064: }
065: }
066: System.out.println("returning shared lock...");
067: return rv;
068: }
069:
070: public synchronized void reset() {
071: if (!(isEnd() || isInit()))
072: throw new IllegalStateException(
073: "call to reset() when not in STOP state or INIT");
074: changeState(INIT);
075: }
076:
077: public void doWait(long millis) {
078: if (!isInit())
079: throw new IllegalStateException(
080: "call to doWait() when not in INIT state.");
081: try {
082: changeState(START);
083: this .startBarrier.barrier();
084: System.out.println("About to call basicDoWait()...");
085: basicDoWait(millis);
086: changeState(END);
087: } catch (Exception e) {
088: throw new TCRuntimeException(e);
089: }
090: }
091:
092: private void basicDoWait(long millis) throws InterruptedException {
093: Object sharedLock = getSharedLock();
094: synchronized (sharedLock) {
095: changeState(WAITER);
096: sharedLock.wait(millis);
097: changeState(HOLDER);
098: // clear the state so no one can check it until it is set again.
099: this .state.clear();
100: }
101: }
102:
103: public void doNotify() {
104: Object sharedLock = getSharedLock();
105: synchronized (sharedLock) {
106: System.out.println("About to call notify()");
107: sharedLock.notify();
108: }
109: }
110:
111: public void doNotifyAll() {
112: Object sharedLock = getSharedLock();
113: synchronized (sharedLock) {
114: System.out.println("About to call notifyAll()");
115: sharedLock.notifyAll();
116: }
117: }
118:
119: public void attemptLock() {
120: if (!isInit())
121: throw new IllegalStateException(
122: "call to attemptLock() when not in INIT state.");
123: try {
124: changeState(START);
125: this .startBarrier.barrier();
126: System.out.println("About to call basicAttemptLock()...");
127: basicAttemptLock();
128: changeState(END);
129: } catch (Exception e) {
130: throw new TCRuntimeException(e);
131: }
132: }
133:
134: private void basicAttemptLock() throws InterruptedException,
135: InvocationTargetException {
136: synchronized (getSharedLock()) {
137: // synchronizing on the shared lock simulates the named lock on this
138: // method.
139: changeState(HOLDER);
140: fallThroughControl.get();
141: // clear the state so no one can check the state until it is set again.
142: this .state.clear();
143: }
144: }
145:
146: public void blockShutdown(final FutureResult blocker)
147: throws Exception {
148: final FutureResult callback = new FutureResult();
149: new Thread(this .threadGroup, new Runnable() {
150: public void run() {
151: try {
152: syncBlockShutdown(blocker, callback);
153: } catch (Exception e) {
154: throw new TCRuntimeException(e);
155: }
156: }
157: }).start();
158: callback.get();
159: }
160:
161: private void syncBlockShutdown(FutureResult blocker,
162: FutureResult callback) throws InterruptedException,
163: InvocationTargetException {
164: System.out.println("Blocking shutdown...");
165: callback.set(new Object());
166: blocker.get();
167: }
168:
169: public void fallThrough() {
170: if (!isHolder())
171: throw new IllegalStateException(
172: "Attempt to release a lock without owning it.");
173: try {
174: fallThroughControl.set(new Object());
175: synchronized (this ) {
176: while (!isEnd())
177: wait();
178: }
179: } catch (InterruptedException e) {
180: throw new TCRuntimeException(e);
181: }
182: }
183:
184: public static void visitL1DSOConfig(ConfigVisitor visitor,
185: DSOClientConfigHelper cfg) {
186: String appClassName = DSOServerRestartTestApp.class.getName();
187: cfg.addIncludePattern(appClassName);
188: cfg.addRoot(new Root(appClassName,
189: "distributedSharedLockHolder", appClassName
190: + ".distributedSharedLockHolder"), true);
191: cfg.addWriteAutolock("void " + appClassName
192: + ".setDistributedSharedLock(java.lang.Object)");
193: cfg.addReadAutolock("java.lang.Object " + appClassName
194: + ".getSharedLock()");
195:
196: cfg.addWriteAutolock("void " + appClassName
197: + ".basicDoWait(..)");
198: cfg.addWriteAutolock("void " + appClassName + ".doNotify()");
199: cfg.addWriteAutolock("void " + appClassName + ".doNotifyAll()");
200: LockDefinition lockDefinition = new LockDefinitionImpl(
201: "basicAttemptLock", ConfigLockLevel.WRITE);
202: lockDefinition.commit();
203: cfg.addLock("void " + appClassName + ".basicAttemptLock()",
204: lockDefinition);
205:
206: lockDefinition = new LockDefinitionImpl("blockShutdown",
207: ConfigLockLevel.WRITE);
208: lockDefinition.commit();
209: cfg.addLock("void " + appClassName + ".syncBlockShutdown(..)",
210: lockDefinition);
211: }
212:
213: }
|