1 /*
   2  * Copyright (c) 2000, 2008, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  *
  26  */
  27 
  28 package bench.rmi;
  29 
  30 import bench.ConfigFormatException;
  31 import bench.Harness;
  32 import bench.HtmlReporter;
  33 import bench.Reporter;
  34 import bench.TextReporter;
  35 import bench.XmlReporter;
  36 import java.io.FileInputStream;
  37 import java.io.FileOutputStream;
  38 import java.io.InputStream;
  39 import java.io.IOException;
  40 import java.io.OutputStream;
  41 import java.io.PrintStream;
  42 import java.rmi.RemoteException;
  43 import java.rmi.RMISecurityManager;
  44 import java.rmi.registry.LocateRegistry;
  45 import java.rmi.registry.Registry;
  46 import java.rmi.server.RemoteObject;
  47 import java.util.Timer;
  48 import java.util.TimerTask;
  49 
  50 /*
  51  * RMI/Serialization benchmark tests.
  52  */
  53 public 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 }