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.tc.simulator.crasher;
005:
006: import org.apache.commons.io.FileUtils;
007:
008: import com.tc.exception.TCRuntimeException;
009:
010: import java.io.File;
011: import java.io.IOException;
012: import java.text.DateFormat;
013: import java.text.SimpleDateFormat;
014: import java.util.ArrayList;
015: import java.util.Arrays;
016: import java.util.Iterator;
017: import java.util.LinkedList;
018: import java.util.List;
019: import java.util.Random;
020:
021: public class Crasher implements Runnable {
022:
023: private static final DateFormat dateFormat = new SimpleDateFormat(
024: "M/d/y:H:m:s,S (Z)");
025:
026: private final Arguments args;
027:
028: public Crasher(Arguments args) {
029: this .args = args;
030: }
031:
032: public void run() {
033: System.out
034: .println("instance count: " + args.getInstanceCount());
035: System.out.println("classname: " + args.getClassname());
036: System.out.println("crash freq: " + args.getCrashFrequency());
037: System.out.println("args: " + args.getMainClassArgs());
038: System.out.println("server args: " + args.getServerArgs());
039:
040: File outputDirectory = new File(args.getOutputDirectoryname());
041: if (!outputDirectory.exists()) {
042: System.out
043: .println("output directory doesn't exist. attempting to create: "
044: + outputDirectory);
045: try {
046: FileUtils.forceMkdir(outputDirectory);
047: } catch (IOException e) {
048: throw new TCRuntimeException(e);
049: }
050: } else {
051: System.out.println("output directory: " + outputDirectory);
052: }
053:
054: System.out.println("output prefix: " + args.getOutputPrefix());
055:
056: ProcessContainer[] processes = new ProcessContainer[args
057: .getInstanceCount()];
058: for (int i = 0; i < processes.length; i++) {
059: try {
060: processes[i] = new ProcessContainer(
061: new ProcessContainerConfig(i + "", dateFormat,
062: args.getServerArgs(), args
063: .getClassname(), args
064: .getMainClassArgs(),
065: outputDirectory, args.getOutputPrefix()));
066: } catch (IOException e) {
067: throw new TCRuntimeException(e);
068: }
069: }
070:
071: try {
072: doStuff(processes);
073: } catch (Exception e) {
074: throw new TCRuntimeException(e);
075: }
076: }
077:
078: private void doStuff(ProcessContainer[] processes)
079: throws IOException, InterruptedException {
080: Random random = new Random();
081: while (true) {
082: for (int i = 0; i < processes.length; i++) {
083: ProcessContainer process = processes[i];
084: if (process.isStopped()) {
085: System.out.println("Starting process " + i + "...");
086: process.start();
087: } else if (random.nextInt(100) <= (args.crashFrequency * 100)) {
088: System.out.println("Stopping process " + i + "...");
089: process.stop();
090: System.out.println("Starting process " + i + "...");
091: process.start();
092: }
093: }
094: Thread.sleep(10 * 1000);
095: }
096:
097: }
098:
099: public static class Arguments {
100: private static final String CLASSNAME_ARG = "--crasher:classname";
101: private static final String INSTANCE_COUNT_ARG = "--crasher:instance-count";
102: private static final String CRASH_FREQUENCY_ARG = "--crasher:crash-frequency";
103: private static final String SERVER_ARGS_PREFIX = "--crasher:server-arg";
104: private static final String OUTPUT_DIRECTORYNAME_ARG = "--crasher:output-directory";
105: private static final String OUTPUT_PREFIX_ARG = "--crasher:output-prefix";
106:
107: private final List args;
108: private List serverArgs;
109: private int instanceCount;
110: private String classname;
111: private double crashFrequency;
112: private String outputDirectoryname;
113: private String outputPrefix;
114:
115: public Arguments(String[] args) {
116: this .args = new LinkedList(Arrays.asList(args));
117: }
118:
119: public List getServerArgs() {
120: return new ArrayList(this .serverArgs);
121: }
122:
123: public List getMainClassArgs() {
124: return new ArrayList(args);
125: }
126:
127: public double getCrashFrequency() {
128: return this .crashFrequency;
129: }
130:
131: public int getInstanceCount() {
132: return this .instanceCount;
133: }
134:
135: public String getClassname() {
136: return this .classname;
137: }
138:
139: public String getOutputDirectoryname() {
140: return this .outputDirectoryname;
141: }
142:
143: public String getOutputPrefix() {
144: return this .outputPrefix;
145: }
146:
147: public synchronized boolean parse() {
148: try {
149: this .instanceCount = parseInstanceCount();
150: this .classname = parseClassname();
151: this .crashFrequency = parseCrashFrequency();
152: this .serverArgs = parseServerArgs();
153: this .outputDirectoryname = parseOutputDirectoryname();
154: this .outputPrefix = parseOutputPrefix();
155: addClasspath();
156:
157: } catch (Exception e) {
158: e.printStackTrace();
159: return false;
160: }
161: return true;
162: }
163:
164: private void addClasspath() {
165: this .serverArgs.add("-classpath");
166: this .serverArgs.add(System.getProperty("java.class.path"));
167: }
168:
169: private String parseOutputPrefix() {
170: String rv = getArgumentValueAndPruneArgsArray(OUTPUT_PREFIX_ARG);
171: if (rv == null) {
172: throw new RuntimeException("No such argument: "
173: + OUTPUT_PREFIX_ARG);
174: }
175: return rv;
176: }
177:
178: private String parseOutputDirectoryname() {
179: String rv = getArgumentValueAndPruneArgsArray(OUTPUT_DIRECTORYNAME_ARG);
180: if (rv == null) {
181: throw new RuntimeException("No such argument: "
182: + OUTPUT_DIRECTORYNAME_ARG);
183: }
184: return rv;
185: }
186:
187: private List parseServerArgs() {
188: return getArgumentValuesAndPruneArgsArray(new ArrayList(),
189: SERVER_ARGS_PREFIX);
190: }
191:
192: private int parseInstanceCount() throws Exception {
193: return Integer
194: .parseInt(getArgumentValueAndPruneArgsArray(INSTANCE_COUNT_ARG));
195: }
196:
197: private String parseClassname() throws Exception {
198: String rv = getArgumentValueAndPruneArgsArray(CLASSNAME_ARG);
199: if (rv == null) {
200: throw new RuntimeException("No such argument: "
201: + CLASSNAME_ARG);
202: }
203: return rv;
204: }
205:
206: private double parseCrashFrequency() throws Exception {
207: return Double
208: .parseDouble(getArgumentValueAndPruneArgsArray(CRASH_FREQUENCY_ARG));
209: }
210:
211: private String getArgumentValueAndPruneArgsArray(
212: String argumentPattern) {
213: List values = getArgumentValuesAndPruneArgsArray(
214: new ArrayList(), argumentPattern);
215: return (String) ((values.size() > 0) ? values.get(0) : null);
216: }
217:
218: private List getArgumentValuesAndPruneArgsArray(List list,
219: String argumentPattern) {
220: List tmp = getArgumentsAndPruneArgsArray(new ArrayList(),
221: argumentPattern);
222: for (Iterator i = tmp.iterator(); i.hasNext();) {
223: String arg = (String) i.next();
224: list.add(arg.substring(arg.indexOf('=') + 1, arg
225: .length()));
226: }
227: return list;
228: }
229:
230: private List getArgumentsAndPruneArgsArray(List list,
231: String argumentPattern) {
232: for (Iterator i = args.iterator(); i.hasNext();) {
233: String arg = (String) i.next();
234: if (arg.startsWith(argumentPattern)) {
235: i.remove();
236: list.add(arg);
237: }
238: }
239: return list;
240: }
241:
242: public StringBuffer usage(StringBuffer buf) {
243: buf
244: .append("Crasher -- starts, crashes, and restarts Container instances.\n");
245: buf.append("Usage:\n");
246: buf.append("\tjava " + Crasher.class.getName() + " "
247: + INSTANCE_COUNT_ARG + "=<instance count> "
248: + CRASH_FREQUENCY_ARG + "=<crash frequency [0-1]> "
249: + "[[" + SERVER_ARGS_PREFIX
250: + "=<server arg>],...] " + OUTPUT_DIRECTORYNAME_ARG
251: + "=<output directory> " + OUTPUT_PREFIX_ARG
252: + "=<output prefix> " + CLASSNAME_ARG
253: + "=<main class> <main class args>\n\n");
254: return buf;
255: }
256:
257: }
258:
259: public static void main(String[] args) throws Exception {
260: Arguments arguments = new Arguments(args);
261: if (!arguments.parse()) {
262: System.out.println(arguments.usage(new StringBuffer()));
263: return;
264: }
265: new Crasher(arguments).run();
266: }
267:
268: }
|