/*
 * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/* @test
 *
 * @summary The juicer is the classic RMI stress test.  The juicer makes
 * a large number of concurrent, long running, remote method invocations
 * between many threads which have exported remote objects.  These
 * threads use remote objects that carry on deep "two party"
 * recursion.  The juicer relies on Distributed Garbage Collection to
 * unexport these remote objects when no more references are held to them.
 * The two parties in the recursion are OrangeImpl and
 * OrangeEchoImpl.  OrangeImpl checks the base case of the recursion
 * so that the program will exit.
 *
 * When the AppleUserImpl.main() method is invoked, the class binds an
 * instance of itself in a registry.  A second server process,
 * an ApplicationServer, is started which looks up the recently
 * bound AppleUser object.  This server is either started up in
 * the same VM or can optionally be started in a separate VM on the
 * same host or on a different host. When this test is run on the
 * RMI profile, ApplicationServer must be started by AppleUserImpl
 * and the complete juicer runs in a single process.
 *
 * The second server process instructs the AppleUserImpl to "use" some apples.
 * AppleUserImpl creates a new thread for each apple.  These threads
 * initiate the two party recursion.
 *
 * Each recursive call nests to a depth determined by this
 * expression: (2 + Math.abs(random.nextInt() % (maxLevel + 1)),
 * where maxLevel is a command line parameter.  Thus each recursive
 * call nests a random number of levels between 2 and maxLevel.
 *
 * The test ends when an exception is encountered or the stop time
 * has been reached.
 *
 * @library ../../testlibrary
 *
 * @build Apple AppleEvent AppleImpl AppleUserImpl
 * @build Orange OrangeEcho OrangeEchoImpl OrangeImpl
 * @build ApplicationServer
 *
 * @run main/othervm/policy=security.policy AppleUserImpl -seconds 30
 *
 * @author Peter Jones, Nigel Daley
 */

import java.rmi.RemoteException;
import java.rmi.NoSuchObjectException;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.registry.LocateRegistry;
import java.util.Random;
import java.util.logging.Logger;
import java.util.logging.Level;

/**
 * The AppleUserImpl class implements the behavior of the remote
 * "apple user" objects exported by the server.  The application server
 * passes each of its remote "apple" objects to an apple user, and an
 * AppleUserThread is created for each apple.
 */
public class AppleUserImpl extends UnicastRemoteObject implements AppleUser {

    private static final Logger logger =
        Logger.getLogger("reliability.appleuser");
    private static int threadNum = 0;
    private static long testDuration = 0;
    private static int maxLevel = 7;
    private static Exception status = null;
    private static boolean finished = false;
    private static boolean startTestNotified = false;
    private static final Random random = new Random();
    private static final Object lock = new Object();

    public AppleUserImpl() throws RemoteException {
    }

    /**
     * Allows the other server process to indicate that it is ready
     * to start "juicing".
     */
    public synchronized void startTest() throws RemoteException {
        startTestNotified = true;
        this.notifyAll();
    }

    /**
     * Allows the other server process to report an exception to this
     * process and thereby terminate the test.
     */
    public void reportException(Exception status) throws RemoteException {
        synchronized (lock) {
            this.status = status;
            lock.notifyAll();
        }
    }

    /**
     * "Use" supplied apple object.  Create an AppleUserThread to
     * stress it out.
     */
    public synchronized void useApple(Apple apple) throws RemoteException {
        String threadName = Thread.currentThread().getName();
        logger.log(Level.FINEST,
            threadName + ": AppleUserImpl.useApple(): BEGIN");

        AppleUserThread t =
            new AppleUserThread("AppleUserThread-" + (++threadNum), apple);
        t.start();

        logger.log(Level.FINEST,
            threadName + ": AppleUserImpl.useApple(): END");
    }

    /**
     * The AppleUserThread class repeatedly invokes calls on its associated
     * Apple object to stress the RMI system.
     */
    class AppleUserThread extends Thread {

        final Apple apple;

        public AppleUserThread(String name, Apple apple) {
            super(name);
            this.apple = apple;
        }

        public void run() {
            int orangeNum = 0;
            long stopTime = System.currentTimeMillis() + testDuration;
            Logger logger = Logger.getLogger("reliability.appleuserthread");

            try {
                do { // loop until stopTime is reached

                    /*
                     * Notify apple with some apple events.  This tests
                     * serialization of arrays.
                     */
                    int numEvents = Math.abs(random.nextInt() % 5);
                    AppleEvent[] events = new AppleEvent[numEvents];
                    for (int i = 0; i < events.length; i++) {
                        events[i] = new AppleEvent(orangeNum % 3);
                    }
                    apple.notify(events);

                    /*
                     * Request a new orange object be created in
                     * the application server.
                     */
                    Orange orange = apple.newOrange(
                        "Orange(" + getName() + ")-" + (++orangeNum));

                    /*
                     * Create a large message of random ints to pass to orange.
                     */
                    int msgLength = 1000 + Math.abs(random.nextInt() % 3000);
                    int[] message = new int[msgLength];
                    for (int i = 0; i < message.length; i++) {
                        message[i] = random.nextInt();
                    }

                    /*
                     * Invoke recursive call on the orange.  Base case
                     * of recursion inverts messgage.
                     */
                    OrangeEchoImpl echo = new OrangeEchoImpl(
                        "OrangeEcho(" + getName() + ")-" + orangeNum);
                    int[] response = orange.recurse(echo, message,
                        2 + Math.abs(random.nextInt() % (maxLevel + 1)));

                    /*
                     * Verify message was properly inverted and not corrupted
                     * through all the recursive method invocations.
                     */
                    if (response.length != message.length) {
                        throw new RuntimeException(
                            "ERROR: CORRUPTED RESPONSE: " +
                            "wrong length of returned array " + "(should be " +
                            message.length + ", is " + response.length + ")");
                    }
                    for (int i = 0; i < message.length; i++) {
                        if (~message[i] != response[i]) {
                            throw new RuntimeException(
                                "ERROR: CORRUPTED RESPONSE: " +
                                "at element " + i + "/" + message.length +
                                " of returned array (should be " +
                                Integer.toHexString(~message[i]) + ", is " +
                                Integer.toHexString(response[i]) + ")");
                        }
                    }

                    try {
                        Thread.sleep(Math.abs(random.nextInt() % 10) * 1000);
                    } catch (InterruptedException e) {
                    }

                } while (System.currentTimeMillis() < stopTime);

            } catch (Exception e) {
                status = e;
            }
            finished = true;
            synchronized (lock) {
                lock.notifyAll();
            }
        }
    }

    private static void usage() {
        System.err.println("Usage: AppleUserImpl [-hours <hours> | " +
                                                 "-seconds <seconds>]");
        System.err.println("                     [-maxLevel <maxLevel>]");
        System.err.println("                     [-othervm]");
        System.err.println("                     [-exit]");
        System.err.println("  hours    The number of hours to run the juicer.");
        System.err.println("           The default is 0 hours.");
        System.err.println("  seconds  The number of seconds to run the juicer.");
        System.err.println("           The default is 0 seconds.");
        System.err.println("  maxLevel The maximum number of levels to ");
        System.err.println("           recurse on each call.");
        System.err.println("           The default is 7 levels.");
        System.err.println("  othervm  If present, the VM will wait for the");
        System.err.println("           ApplicationServer to start in");
        System.err.println("           another process.");
        System.err.println("           The default is to run everything in");
        System.err.println("           a single VM.");
        System.err.println("  exit     If present, the VM will call");
        System.err.println("           System.exit() when main() finishes.");
        System.err.println("           The default is to not call");
        System.err.println("           System.exit().");
        System.err.println();
    }

    /**
     * Entry point for the "juicer" server process.  Create and export
     * an apple user implementation in an rmiregistry running on localhost.
     */
    public static void main(String[] args) {
        String durationString = null;
        boolean othervm = false;
        boolean exit = false;
        try {
            // parse command line args
            for (int i = 0; i < args.length ; i++ ) {
                String arg = args[i];
                if (arg.equals("-hours")) {
                    if (durationString != null) {
                        usage();
                    }
                    i++;
                    int hours = Integer.parseInt(args[i]);
                    durationString = hours + " hours";
                    testDuration = hours * 60 * 60 * 1000;
                } else if (arg.equals("-seconds")) {
                    if (durationString != null) {
                        usage();
                    }
                    i++;
                    long seconds = Long.parseLong(args[i]);
                    durationString = seconds + " seconds";
                    testDuration = seconds * 1000;
                } else if (arg.equals("-maxLevel")) {
                    i++;
                    maxLevel = Integer.parseInt(args[i]);
                } else if (arg.equals("-othervm")) {
                    othervm = true;
                } else if (arg.equals("-exit")) {
                    exit = true;
                } else {
                    usage();
                }
            }
            if (durationString == null) {
                durationString = testDuration + " milliseconds";
            }
        } catch (Throwable t) {
            usage();
            throw new RuntimeException("TEST FAILED: Bad argument");
        }

        AppleUserImpl user = null;
        long startTime = 0;
        Thread server = null;
        int exitValue = 0;
        try {
            user = new AppleUserImpl();

            synchronized (user) {
                // create new registry and bind new AppleUserImpl in registry
                LocateRegistry.createRegistry(2006);
                LocateRegistry.getRegistry(2006).rebind("AppleUser",user);

                // start the other server if applicable
                if (othervm) {
                    // the other server must be running in a separate process
                    logger.log(Level.INFO, "Application server must be " +
                        "started in separate process");
                } else {
                    Class app = Class.forName("ApplicationServer");
                    server = new Thread((Runnable) app.newInstance());
                    logger.log(Level.INFO, "Starting application server " +
                        "in same process");
                    server.start();
                }

                // wait for other server to call startTest method
                logger.log(Level.INFO, "Waiting for application server " +
                    "process to start");
                while (!startTestNotified) {
                   user.wait();
                }
            }

            startTime = System.currentTimeMillis();
            logger.log(Level.INFO, "Test starting");

            // wait for exception to be reported or first thread to complete
            logger.log(Level.INFO, "Waiting " + durationString + " for " +
                "test to complete or exception to be thrown");

            synchronized (lock) {
                while (status == null && !finished) {
                    lock.wait();
                }
            }

            if (status != null) {
                throw new RuntimeException("TEST FAILED: "
                    + "juicer server reported an exception", status);
            } else {
                logger.log(Level.INFO, "TEST PASSED");
            }
        } catch (Exception e) {
            logger.log(Level.INFO, "TEST FAILED");
            exitValue = 1;
            if (exit) {
                e.printStackTrace();
            }
            throw new RuntimeException("TEST FAILED: "
                    + "unexpected exception", e);
        } finally {
            long actualDuration = System.currentTimeMillis() - startTime;
            logger.log(Level.INFO, "Test finished");
            try {
                UnicastRemoteObject.unexportObject(user, true);
            } catch (NoSuchObjectException ignore) {
            }
            logger.log(Level.INFO, "Test duration was " +
                (actualDuration/1000) + " seconds " +
                "(" + (actualDuration/3600000) + " hours)");
            System.gc(); System.gc();
            if (exit) {
                System.exit(exitValue);
            }
        }
    }
}
