package examples.mega.client;

import java.rmi.RemoteException;

import java.io.IOException;

import javax.xml.rpc.ServiceException;

import weblogic.utils.Debug;
import weblogic.utils.AssertionError;

/**
 * @author Copyright (c) 2002 by BEA Systems. All Rights Reserved.
 */

public final class MultiThreadedPerfClient {

  private final static boolean debug   = true;
  private final static boolean verbose = true;

  private int nThreads = 15;
  private int iter = 50;

  public void invoke( String url ){

    ClientThread[] threads = new ClientThread[nThreads];
    long[] time = new long[nThreads];

    Barrier barrier = new Barrier(nThreads);

    // create all threads
    for (int i=0; i<threads.length; i++) {
      threads[i] = new ClientThread(barrier, url, time, i, iter);
    }

    // start'em up
    for (int i=0; i<threads.length; i++) {
      threads[i].start();
    }

    // wait for completion
    for (int i=0; i<threads.length; i++) {
      try {
        threads[i].join();
      } catch (InterruptedException ie) {
        ie.printStackTrace();
        throw new AssertionError(ie);
      }
    }

    System.out.println("\n\nRESULTS for "+nThreads+
      " threads doing "+iter+" invokes\n\n");

    // print out all the times
    for (int i=0; i<threads.length; i++) {
      
      double mps = (((double)iter) / (double) time[i]) * 1000.0d;

      System.out.println("Thread["+i+"] took "+time[i]+
        "ms with "+mps+" invokes/s");
    }
  }

  private static class Barrier {

    private int n;
    private int waiters;

    Barrier(int n) { this.n = n; }

    synchronized void enter() {
      waiters++;

      if (waiters < n) {
        try {
          wait();
        } catch (InterruptedException ie) {}
      } else {
        System.out.println("** BARRIER COMPLETE");
        notifyAll();
        return;
      }
    }
  }



  private static class ClientThread
    extends Thread
  {
    private long time[];
    private int threadIndex;

    private int iter;
    private MegaPort port;

    private Barrier barrier;

    ClientThread(Barrier barrier, String url, long[] time, 
      int threadIndex, int iter) 
    {
      this.barrier     = barrier;
      this.time        = time;
      this.threadIndex = threadIndex;
      this.iter        = iter;

      try{
        MegaWebService service = new MegaWebService_Impl( url );
        port = service.getMegaPort();
      }catch( IOException e ){
        throw new AssertionError( "Failed to get service:" + e, e );
      }catch( ServiceException e ){
        throw new AssertionError( "Failed to get service:" + e, e );
      }
    }

    public void run() {

      // warm-up and hit the barrier to smooth out the thread
      // start-up/connection noise

      for (int i=0; i<100; i++) {
        try {
          port.v();
        } catch (Exception e) {
          e.printStackTrace();
          return;
        }
      }

      barrier.enter();


      long start = System.currentTimeMillis();

      for (int i=0; i<iter; i++) {
        try {
          port.v();
        } catch (Exception e) {
          e.printStackTrace();
          return;
        }
      }

      long stop = System.currentTimeMillis();

      time[threadIndex] = stop - start;
    }
  }

}

