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.system;
006:
007: import org.apache.commons.io.FileUtils;
008:
009: import com.tc.object.config.ConfigVisitor;
010: import com.tc.object.config.DSOClientConfigHelper;
011: import com.tc.object.config.TransparencyClassSpec;
012: import com.tc.objectserver.control.ExtraL1ProcessControl;
013: import com.tc.simulator.app.ApplicationConfig;
014: import com.tc.simulator.listener.ListenerProvider;
015: import com.tctest.ServerCrashingAppBase;
016:
017: import java.io.File;
018: import java.util.ArrayList;
019: import java.util.List;
020: import java.util.Random;
021:
022: public class ClientTerminatingTestApp extends ServerCrashingAppBase {
023: private static boolean DEBUG = false;
024: private static boolean isSynchronousWrite;
025:
026: public static final String FORCE_KILL = "force-kill";
027:
028: private static final int LOOP_COUNT = 2;
029: private static final List queue = new ArrayList();
030:
031: private int id = -1;
032: private long count = 0;
033: private ExtraL1ProcessControl client;
034: private final boolean forceKill;
035: private String appId;
036:
037: public ClientTerminatingTestApp(String appId,
038: ApplicationConfig cfg, ListenerProvider listenerProvider) {
039: super (appId, cfg, listenerProvider);
040:
041: String forceKillVal = cfg.getAttribute(FORCE_KILL);
042: if (forceKillVal != null && !forceKillVal.equals("")) {
043: forceKill = true;
044: } else {
045: forceKill = false;
046: }
047:
048: this .appId = appId;
049: }
050:
051: public static void debugPrintln(String s) {
052: if (DEBUG) {
053: System.err.println(s);
054: }
055: }
056:
057: public void runTest() throws Throwable {
058: List myList = new ArrayList();
059: synchronized (queue) {
060: if (id != -1) {
061: throw new AssertionError(
062: "Only one controller per Instance allowed. Check the Execution count");
063: }
064: id = queue.size();
065:
066: debugPrintln("******* appId=[" + appId + "] id=[" + id
067: + "]");
068: queue.add(myList);
069: debugPrintln("******* adding to queue: mylistInQueue=["
070: + queue.contains(myList) + "] isNull=["
071: + (myList == null) + "]");
072: }
073:
074: Random random = new Random();
075: int times = LOOP_COUNT;
076: try {
077: while (times-- > 0) {
078: long toAdd = random.nextInt(10) * 50L + 1;
079: File workingDir = new File(
080: getConfigFileDirectoryPath(), "client-" + id
081: + "-" + times);
082: FileUtils.forceMkdir(workingDir);
083: System.err.println(this + "Creating Client with args "
084: + id + " , " + toAdd);
085: List jvmArgs = new ArrayList();
086: addTestTcPropertiesFile(jvmArgs);
087: client = new ExtraL1ProcessControl(getHostName(),
088: getPort(), Client.class, getConfigFilePath(),
089: new String[] { "" + id, "" + toAdd,
090: "" + forceKill }, workingDir, jvmArgs);
091: client.start();
092: int exitCode = client.waitFor();
093: if (exitCode == 0) {
094: System.err.println(this + "Client exited normally");
095: verify(myList, toAdd);
096: } else {
097: String errorMsg = this
098: + "Client exited abnormally. Exit code = "
099: + exitCode;
100: System.err.println("error message: " + errorMsg);
101: throw new AssertionError(errorMsg);
102: }
103: }
104: } catch (Exception e) {
105: System.err.println(this + " Got - " + e);
106: throw new AssertionError(e);
107: }
108:
109: }
110:
111: private void verify(List myList, long toAdd) {
112: synchronized (myList) {
113: if (toAdd != myList.size()) {
114: String errorMsg = this + " Expected " + toAdd
115: + " elements in the list. But Found "
116: + myList.size();
117: System.err.println(errorMsg);
118: throw new AssertionError(errorMsg);
119: }
120: }
121: for (int i = 0; i < myList.size(); i++) {
122: synchronized (myList) {
123: if ((++count != ((Long) myList.get(i)).longValue())) {
124: String errorMsg = this + " Expected " + count
125: + " value in the list. But Found "
126: + myList.get(i);
127: System.err.println(errorMsg);
128: throw new AssertionError(errorMsg);
129: }
130: }
131: }
132: }
133:
134: public String toString() {
135: return "Controller(" + id + ") :";
136: }
137:
138: public static class Client {
139: private int id;
140: private long addCount;
141: private boolean shouldForceKill;
142: private List clientQueue = new ArrayList();
143:
144: public Client(int i, long addCount, boolean shouldForceKill) {
145: this .id = i;
146: this .addCount = addCount;
147: this .shouldForceKill = shouldForceKill;
148:
149: debugPrintln("******* id=[" + id + "] addCount=["
150: + this .addCount + "] shoudlForceKill=["
151: + this .shouldForceKill + "]");
152: }
153:
154: public static void main(String args[]) {
155: if (args.length < 2 || args.length > 3) {
156: throw new AssertionError(
157: "Usage : Client <id> <num of increments> [shouldForceKill]");
158: }
159:
160: boolean shouldForceKill;
161: if (args.length == 3 && args[2] != null
162: && !args[2].equals("")) {
163: shouldForceKill = Boolean.valueOf(args[2])
164: .booleanValue();
165: } else {
166: shouldForceKill = false;
167: }
168:
169: Client client = new Client(Integer.parseInt(args[0]), Long
170: .parseLong(args[1]), shouldForceKill);
171: client.execute();
172: }
173:
174: // Written so that many transactions are created ...
175: public void execute() {
176: List myList = null;
177: long count = 0;
178: System.err.println(this + " execute : addCount = "
179: + addCount);
180: synchronized (clientQueue) {
181: myList = (List) clientQueue.get(id);
182: }
183: synchronized (myList) {
184: if (myList.size() > 0) {
185: count = ((Long) myList.get(myList.size() - 1))
186: .longValue();
187: myList.clear();
188: }
189: }
190: while (addCount-- > 0) {
191: synchronized (myList) {
192: myList.add(new Long(++count));
193: }
194: }
195:
196: if (shouldForceKill) {
197: System.err
198: .println(this + " killed forceably :" + count);
199: Runtime.getRuntime().halt(0);
200: } else {
201: System.err.println(this + " put till :" + count);
202: System.exit(0);
203: }
204: }
205:
206: public String toString() {
207: return "Client(" + id + ") :";
208: }
209:
210: }
211:
212: public static void visitL1DSOConfig(ConfigVisitor visitor,
213: DSOClientConfigHelper config) {
214: String testClassName = ClientTerminatingTestApp.class.getName();
215: String clientClassName = Client.class.getName();
216: TransparencyClassSpec spec = config
217: .getOrCreateSpec(testClassName);
218: TransparencyClassSpec spec2 = config
219: .getOrCreateSpec(clientClassName);
220:
221: String methodExpression = "* " + testClassName + "*.*(..)";
222: setLockLevel(config, methodExpression);
223: spec.addRoot("queue", "queue");
224:
225: methodExpression = "* " + clientClassName + "*.*(..)";
226: config.addWriteAutolock(methodExpression);
227: spec2.addRoot("clientQueue", "queue");
228: }
229:
230: private static void setLockLevel(DSOClientConfigHelper config,
231: String methodExpression) {
232: if (isSynchronousWrite) {
233: config.addSynchronousWriteAutolock(methodExpression);
234: debugPrintln("****** doing synch write");
235: } else {
236: config.addWriteAutolock(methodExpression);
237: debugPrintln("***** doing regular write");
238: }
239: }
240:
241: public static void setSynchronousWrite(boolean isSynchWrite) {
242: isSynchronousWrite = isSynchWrite;
243: }
244:
245: }
|