Main.java revision 0:37a05a11f281
1/*
2 * Copyright 2000-2005 Sun Microsystems, Inc.  All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
23
24/*
25 *
26 */
27
28package bench.rmi;
29
30import bench.ConfigFormatException;
31import bench.Harness;
32import bench.HtmlReporter;
33import bench.Reporter;
34import bench.TextReporter;
35import bench.XmlReporter;
36import java.io.FileInputStream;
37import java.io.FileOutputStream;
38import java.io.InputStream;
39import java.io.IOException;
40import java.io.OutputStream;
41import java.io.PrintStream;
42import java.rmi.RemoteException;
43import java.rmi.RMISecurityManager;
44import java.rmi.registry.LocateRegistry;
45import java.rmi.registry.Registry;
46import java.rmi.server.RemoteObject;
47import java.util.Timer;
48import java.util.TimerTask;
49
50/*
51 * RMI/Serialization benchmark tests.
52 */
53public class Main {
54
55    /**
56     * RMI-specific benchmark harness.
57     */
58    static class RMIHarness extends Harness {
59	/**
60	 * Construct new RMI benchmark harness.
61	 */
62	RMIHarness(InputStream in) throws IOException, ConfigFormatException {
63	    super(in);
64	}
65
66	/**
67	 * Cleanup both client and server side in between each benchmark.
68	 */
69	protected void cleanup() {
70	    System.gc();
71	    if (Main.runmode == CLIENT) {
72		try {
73		    Main.server.gc();
74		} catch (Exception e) {
75		    System.err.println("Warning: server gc failed: " + e);
76		}
77	    }
78	}
79    }
80
81    static final String CONFFILE = "/bench/rmi/config";
82    static final String VERSION = "1.3";
83    static final String REGNAME = "server";
84
85    static final int SAMEVM = 0;
86    static final int CLIENT = 1;
87    static final int SERVER = 2;
88
89    static final int TEXT = 0;
90    static final int HTML = 1;
91    static final int XML = 2;
92
93    static boolean verbose;
94    static boolean list;
95    static boolean exitOnTimer;
96    static int testDurationSeconds;
97    static volatile boolean exitRequested;
98    static Timer timer;
99    static int format = TEXT;
100    static int runmode;
101    static InputStream confstr;
102    static OutputStream repstr;
103    static String host;
104    static int port;
105    static RMIHarness harness;
106    static Reporter reporter;
107    static BenchServer server;
108    static BenchServerImpl serverImpl;
109
110    /**
111     * Returns reference to benchmark server.
112     */
113    public static BenchServer getBenchServer() {
114	return server;
115    }
116
117    /**
118     * Prints help message.
119     */
120    static void usage() {
121        PrintStream p = System.err;
122        p.println("\nUsage: java -jar rmibench.jar [-options]");
123        p.println("\nwhere options are:");
124        p.println("  -h                   print this message");
125        p.println("  -v                   verbose mode");
126        p.println("  -l                   list configuration file");
127        p.println("  -t <num hours>       repeat benchmarks for specified number of hours");
128        p.println("  -o <file>            specify output file");
129        p.println("  -c <file>            specify (non-default) " +
130		"configuration file");
131        p.println("  -html                format output as html " +
132		"(default is text)");
133        p.println("  -xml                 format output as xml");
134	p.println("  -client <host:port>  run benchmark client using server " +
135		"on specified host/port");
136	p.println("  -server <port>       run benchmark server on given port");
137    }
138
139    /**
140     * Print error message and exit.
141     */
142    static void die(String mesg) {
143	System.err.println(mesg);
144	System.exit(1);
145    }
146
147    /**
148     * Stop server and exit.
149     */
150    public static void exit() {
151	switch (runmode) {
152	    case CLIENT:
153		if (server != null) {
154		    try {
155			server.terminate(0);
156		    } catch (RemoteException re) {
157			// ignore
158		    }
159		}
160	    default:
161		System.exit(0);
162	}
163    }
164
165    /**
166     * Benchmark mainline.
167     */
168    public static void main(String[] args) {
169	setupSecurity();
170	parseArgs(args);
171	setupStreams();
172	if (list) {
173	    listConfig();
174	} else {
175	    setupServer();
176	    if (runmode != SERVER) {
177		setupHarness();
178		setupReporter();
179		if (exitOnTimer) {
180		    setupTimer(testDurationSeconds);
181		    while (true) {
182			runBenchmarks();
183			if (exitRequested) {
184			    exit();
185			}
186		    }
187		} else {
188		    runBenchmarks();
189		    exit();
190		}
191	    }
192	}
193    }
194
195    /**
196     * Parse command-line arguments.
197     */
198    static void parseArgs(String[] args) {
199	for (int i = 0; i < args.length; i++) {
200	    if (args[i].equals("-h")) {
201		usage();
202		System.exit(0);
203	    } else if (args[i].equals("-v")) {
204		verbose = true;
205	    } else if (args[i].equals("-l")) {
206		list = true;
207	    } else if (args[i].equals("-t")) {
208		if (++i >= args.length)
209		    die("Error: no timeout value specified");
210		try {
211		    exitOnTimer = true;
212		    testDurationSeconds = Integer.parseInt(args[i]) * 3600;
213		} catch (Exception e) {
214		    die("Error: unable to determine timeout value");
215		}
216	    } else if (args[i].equals("-o")) {
217		if (++i >= args.length)
218		    die("Error: no output file specified");
219		try {
220		    repstr = new FileOutputStream(args[i]);
221		} catch (IOException e) {
222		    die("Error: unable to open \"" + args[i] + "\"");
223		}
224	    } else if (args[i].equals("-c")) {
225		if (++i >= args.length)
226		    die("Error: no config file specified");
227		try {
228		    confstr = new FileInputStream(args[i]);
229		} catch (IOException e) {
230		    die("Error: unable to open \"" + args[i] + "\"");
231		}
232	    } else if (args[i].equals("-html")) {
233		if (format != TEXT)
234		    die("Error: conflicting formats");
235		format = HTML;
236	    } else if (args[i].equals("-xml")) {
237		if (format != TEXT)
238		    die("Error: conflicting formats");
239		format = XML;
240	    } else if (args[i].equals("-client")) {
241		if (runmode == CLIENT)
242		    die("Error: multiple -client options");
243		if (runmode == SERVER)
244		    die("Error: -client and -server options conflict");
245		if (++i >= args.length)
246		    die("Error: -client missing host/port");
247		try {
248		    int sepi = args[i].indexOf(':');
249		    host = args[i].substring(0, sepi);
250		    port = Integer.parseInt(args[i].substring(sepi + 1));
251		} catch (Exception e) {
252		    die("Error: illegal host/port specified for -client");
253		}
254		runmode = CLIENT;
255	    } else if (args[i].equals("-server")) {
256		if (runmode == CLIENT)
257		    die("Error: -client and -server options conflict");
258		if (runmode == SERVER)
259		    die("Error: multiple -server options");
260		if (++i >= args.length)
261		    die("Error: -server missing port");
262		try {
263		    port = Integer.parseInt(args[i]);
264		} catch (Exception e) {
265		    die("Error: illegal port specified for -server");
266		}
267		runmode = SERVER;
268	    } else {
269		System.err.println("Illegal option: \"" + args[i] + "\"");
270		usage();
271		System.exit(1);
272	    }
273	}
274    }
275
276    /**
277     * Set up security manager and policy, if not set already.
278     */
279    static void setupSecurity() {
280	if (System.getSecurityManager() != null)
281	    return;
282
283	/* As of 1.4, it is too late to set the security policy
284	 * file at this point so these line have been commented out.
285	 */
286	//System.setProperty("java.security.policy",
287	//	Main.class.getResource("/bench/rmi/policy.all").toString());
288	System.setSecurityManager(new RMISecurityManager());
289    }
290
291    /**
292     * Set up configuration file and report streams, if not set already.
293     */
294    static void setupStreams() {
295	if (repstr == null)
296	    repstr = System.out;
297	if (confstr == null)
298	    confstr = (new Main()).getClass().getResourceAsStream(CONFFILE);
299	if (confstr == null)
300	    die("Error: unable to find default config file");
301    }
302
303    /**
304     * Print contents of configuration file to selected output stream.
305     */
306    static void listConfig() {
307	try {
308	    byte[] buf = new byte[256];
309	    int len;
310	    while ((len = confstr.read(buf)) != -1)
311		repstr.write(buf, 0, len);
312	} catch (IOException e) {
313	    die("Error: failed to list config file");
314	}
315    }
316
317    /**
318     * Setup benchmark server.
319     */
320    static void setupServer() {
321	switch (runmode) {
322	    case SAMEVM:
323		try {
324		    serverImpl = new BenchServerImpl();
325		    server = (BenchServer) RemoteObject.toStub(serverImpl);
326		} catch (Exception e) {
327		    die("Error: failed to create local server: " + e);
328		}
329		if (verbose)
330		    System.out.println("Benchmark server created locally");
331		break;
332
333	    case CLIENT:
334		try {
335		    Registry reg = LocateRegistry.getRegistry(host, port);
336		    server = (BenchServer) reg.lookup(REGNAME);
337		} catch (Exception e) {
338		    die("Error: failed to connect to server: " + e);
339		}
340		if (server == null) {
341		    die("Error: server not found");
342		}
343		if (verbose) {
344		    System.out.println("Connected to benchmark server on " +
345			    host + ":" + port);
346		}
347		break;
348
349	    case SERVER:
350		try {
351		    Registry reg = LocateRegistry.createRegistry(port);
352		    serverImpl = new BenchServerImpl();
353		    reg.bind(REGNAME, serverImpl);
354		} catch (Exception e) {
355		    die("Error: failed to initialize server: " + e);
356		}
357		if (verbose) {
358		    System.out.println("Benchmark server started on port " +
359			    port);
360		}
361		break;
362
363	    default:
364		throw new InternalError("illegal runmode");
365	}
366    }
367
368    /**
369     * Set up the timer to end the test.
370     *
371     * @param delay the amount of delay, in seconds, before requesting
372     * the process exit
373     */
374    static void setupTimer(int delay) {
375	timer = new Timer(true);
376        timer.schedule(
377            new TimerTask() {
378                public void run() {
379                    exitRequested = true;
380                }
381            },
382            delay * 1000);
383    }
384
385    /**
386     * Set up benchmark harness.
387     */
388    static void setupHarness() {
389        try {
390            harness = new RMIHarness(confstr);
391        } catch (ConfigFormatException e) {
392            String errmsg = e.getMessage();
393            if (errmsg != null) {
394		die("Error parsing config file: " + errmsg);
395	    } else {
396                die("Error: illegal config file syntax");
397	    }
398        } catch (IOException e) {
399	    die("Error: failed to read config file");
400        }
401    }
402
403    /**
404     * Setup benchmark reporter.
405     */
406    static void setupReporter() {
407        String title = "RMI Benchmark, v" + VERSION;
408	switch (format) {
409	    case TEXT:
410		reporter = new TextReporter(repstr, title);
411		break;
412
413	    case HTML:
414		reporter = new HtmlReporter(repstr, title);
415		break;
416
417	    case XML:
418		reporter = new XmlReporter(repstr, title);
419		break;
420
421	    default:
422		die("Error: unrecognized format type");
423	}
424    }
425
426    /**
427     * Run benchmarks.
428     */
429    static void runBenchmarks() {
430        harness.runBenchmarks(reporter, verbose);
431    }
432}
433
434