// (C) Copyright Jack Culpepper 1997
// This code may not be distributed without permission.
package flop;

import java.net.*;
import java.io.*;
import java.util.*;
import gestalt.Connection;
import gestalt.Client;
import gestalt.TaskID;
import gestalt.msg.ServerUpdate;
import flop.FlopMetricTask;

public class FlopMetricClient extends Client {
  private static final int num_tasks = 100;
  protected Date start;
  protected Date finish;

  public FlopMetricClient( String hostname ) {
    super( hostname, "FlopMetricClient" );
  }

  public void begin( Connection c ) {
    Vector tasks = new Vector();
    start = new Date();

    report( "Entering MetricClient begin method." );

    // generate a bunch of FlopMetricTasks, and put them in the outgoing queue
    report( "Generating " + num_tasks + " tasks." );
    for ( int i = 0 ; i < num_tasks ; i++ ) {
      FlopMetricTask fmt = new FlopMetricTask( c );
      tasks.addElement( fmt.id );
      c.send( fmt );
    }

    long totalCalcTime = 0;
    long totalNetTime = 0;

    // loop, pulling objects off the incoming queue of the connection until
    // we have gotten the results of all the tasks we submitted
    while ( ! tasks.isEmpty() ) {
      if ( ! c.isAlive() ) {
        report( "My connection died!" );
        break;
      }
      while ( c.avail() ) {
        Object o = c.recv();
        if ( o instanceof FlopMetricTask ) {
          FlopMetricTask fmt = ( FlopMetricTask )o;
          boolean found = false;
          for ( int i = 0 ; i < tasks.size() ; i++ ) {
            TaskID test = ( TaskID )tasks.elementAt( i );
            if ( test.equals( fmt.id ) ) {
              found = true;
              tasks.removeElementAt( i );
//              report( "Result: " + fmt.data );
              totalCalcTime += fmt.calcTime;
              totalNetTime += ( new Date() ).getTime() - fmt.creation.getTime();
              break;
            }
          }
          if ( ! found ) report( "I did not submit this: " + fmt );
        }
        else if ( o instanceof ServerUpdate ) {
          ServerUpdate su = ( ServerUpdate )o;
          report( "Server update: tasks_pending=" + su.tasks_pending +
            ", num_slaves=" + su.num_slaves );
        }
        else report( "Found unknown object: " + o );
      }

      // sleep for a while so that this is not a tight loop
      try {
        sleep( 500 );
      }
      catch (InterruptedException e) {
        report( "What!!?!?  My sleep was interrupted: " + e );
      }
    }
    if ( tasks.isEmpty() ) {
      finish = new Date();
      report( "All results have been received." );
      report( "Total calc time: " + totalCalcTime );
      report( "Total net time: " + totalNetTime );
      long time = finish.getTime() - start.getTime();
      int ops = FlopMetricTask.ops * num_tasks;
      double mflops = ( ( double )ops ) / ( double )time;
//      report( "Milliseconds taken to do " + ops + " floating point " +
//        "operations: " + time );
      report( "Network MFlop/s: " + mflops );
    }
  }

  public static void main( String[] args ) {
    if ( args.length != 1 || args[0].equals( "" ) ) {
      System.out.println( "Usage: java FlopMetricClient <hostname>" );
    }
    else {
      FlopMetricClient c = new FlopMetricClient( args[0] );
    }
  }
}

