package edu.vt.marian.common;

import java.io.*;
import java.net.*;
import java.util.*;


/** Class name: PerformanceMeasurement
	<P>Class description: this class is used to do system performance measurement,
		it will record time for each measurement automatically, caculate the 
		average, and dump all the results to a file in human readable format
	@author: Jianxin Zhao
	<P>Finished time: ????, 1999
	<P>Known bugs: none
	<P>Platform: jdk1.1.7 under WINDOW 95
*/

public class PerformanceMeasurement
{
	/** possible return values of methods
	*/
	public final static int OK = 0;
	public final static int INVALID_ID = 1;
	public final static int FILE_WRITE_ERROR = 2;

	/** this is the seperator for different measurement
	*/
	private final static String measurement_separator = "**************************************";

	/** this is the seperator used at the beginning of dump file
	*/
	private final static String dump_separator = "==========================================";

	/** this vector contains all the data of all the performance measure 
	*/
	private Vector measurements = new Vector();


	/** this constructor will create a PerformanceMeasurement object, there is no
		Measurement at this time
	*/
	public PerformanceMeasurement()
	{
	}


	/** this will add a new measurement into this object, the return value is the id of
		this Measurement and can be used to do measure later
	*/
	public int add_measurement(String description)
	{
		Measurement m = new Measurement(description);
		measurements.addElement(m);
		return measurements.size() - 1;
	}


	/** this method will record a start time for the Measurement specified by the 
		parameter measurement_id
	*/
	public int start_measure(int measurement_id)
	{
		if ((measurement_id < 0) || (measurement_id >= measurements.size()))
		{
			System.err.println("PerformanceMeasurement.start_measure(): parameter measurement_id is invalid");
			return INVALID_ID;
		}
		
		// id is valid here
		Measurement m = (Measurement) measurements.elementAt(measurement_id);
		m.start((new Date()).getTime());
		return OK;
	}
	

	/** this method will record a end time for the specified measurement_id
		
	*/
	public int end_measure(int measurement_id)
	{
		Date d = new Date();

		if ((measurement_id < 0) || (measurement_id >= measurements.size()))
		{
			System.err.println("PerformanceMeasurement.end_measure(): parameter measurement_id is invalid");
			return INVALID_ID;
		}
		
		// id is valid here
		Measurement m = (Measurement) measurements.elementAt(measurement_id);
		m.end(d.getTime());
		return OK;
	}


	/** this method will dump all the result of this object so far into
		the file in human readable format, it will rewrite the file or append
		to the end of it depending on the parameter append
	*/
	public int dump_to_file(String file_name, boolean append)
	{
		// first create stream for the file
		PrintWriter pw = null;
        try
        {
            pw = new PrintWriter(new FileOutputStream(file_name, append));             
        }
        catch (Exception e)
        {
			System.err.println("PerformanceMeasurement.dump_to_file(): file stream creating error");
			return FILE_WRITE_ERROR;
        }

		// the stream is created successfully, write results to it
		pw.println(dump_separator);
		pw.println("Time: " + (new Date()).toString());

		// write our each measurement
		Measurement m = null;
		for (int i = 0; i < measurements.size(); i++)
		{
			pw.println(measurement_separator);
			m = (Measurement) measurements.elementAt(i);
			m.to_stream(pw);
		}

		pw.flush();
		pw.close();
		return OK;
	}
	
	
	/** this method will dump all the result of the specified measurement so far into
		the file in human readable format, it will rewrite the file or append
		to the end of it depending on the parameter append
	*/
	public int dump_to_file(String file_name, int measurement_id, boolean append)
	{
		if ((measurement_id < 0) || (measurement_id >= measurements.size()))
		{
			System.err.println("PerformanceMeasurement.dump_to_file(): parameter measurement_id is invalid");
			return INVALID_ID;
		}
		
		// first create stream for the file
		PrintWriter pw = null;
        try
        {
			pw = new PrintWriter(new FileOutputStream(file_name, append));             
        }
        catch (Exception e)
        {
			System.err.println("PerformanceMeasurement.dump_to_file(): file stream creating error");
			return FILE_WRITE_ERROR;
        }

		// the stream is created successfully, write results to it
		pw.println(dump_separator);
		pw.println("Time: " + (new Date()).toString());

		// write our the measurement
		Measurement m = (Measurement) measurements.elementAt(measurement_id);
		m.to_stream(pw);
		pw.flush();
		pw.close();

		return OK;
	}
}