// StatisticsFrame.java
// $Id: StatisticsFrame.java,v 1.11 2000/02/26 16:21:49 ylafon Exp $
// (c) COPYRIGHT MIT and INRIA, 1996.
// Please first read the full copyright statement in file COPYRIGHT.html

package org.w3c.jigsaw.status ;

import java.util.* ;

import org.w3c.tools.resources.*;
import org.w3c.www.http.*;
import org.w3c.jigsaw.frames.*;
import org.w3c.jigsaw.http.*;
import org.w3c.jigsaw.html.*;

/**
 * This class exports the server statistics.
 * It makes available a bunch of various parameters about the current
 * server, and uses the Refresh meta-tag (as the ThreadStat) to 
 * make them redisplay.
 * <p>This would benefit from being an applet.
 */

public class StatisticsFrame extends HTTPFrame {
    protected static Integer REFRESH_DEFAULT = new Integer(5) ;

    /**
     * Attribute index - Our refresh interval.
     */
    protected static int ATTR_REFRESH = -1 ;
    
    static {
	Attribute a   = null ;
	Class     cls = null ;
	try {
	    cls = Class.forName("org.w3c.jigsaw.status.StatisticsFrame");
	} catch (Exception ex) {
	    ex.printStackTrace() ;
	    System.exit(1) ;
	}
	// The refresh interval attribute:
	a = new IntegerAttribute("refresh"
				 , new Integer(5)
				 , Attribute.EDITABLE) ;
	ATTR_REFRESH = AttributeRegistry.registerAttribute(cls, a) ;
    }

    static String time_tbl = ("<table border=\"1\" class=\"time\">"
			      + "<caption>Request processing times"
			      + "</caption><tr>"
			      + "<th>min"
			      + "<th>avg"
			      + "<th>max"
			      + "</tr><tr>") ;
    static String thread_tbl = ("<table border class=\"thread\">"
				+ "<caption>Thread counts"
				+ "</caption><tr>"
				+ "<th>free"
				+ "<th>idle"
				+ "<th>used"
				+ "<th>total"
				+ "</tr><tr>");

    public void registerResource(FramedResource resource) {
	super.registerOtherResource(resource);
    }
				
    /**
     * Get the current set of statistics.
     * Display the collected statistics in an HTML table.
     * @param request TYhe request to process.
     */

    public Reply get (Request request) {
	HtmlGenerator g = new HtmlGenerator("Statistics") ;
	g.addMeta("Refresh", 
		  getValue(ATTR_REFRESH, REFRESH_DEFAULT).toString());
	addStyleSheet(g);
	// Dump the statistics:
	httpdStatistics stats = ((httpd)getServer()).getStatistics() ;
	// Uptime:
	g.append("<h1>Server statistics</h1>");
	long start_time = stats.getStartTime();
	long uptime     = (System.currentTimeMillis() - start_time) / 1000;
	g.append("<p>Your server was started on <span class=\"date\">");
	g.append(new Date(start_time).toString());
	long duptime = uptime / (3600L*24L);
	long htemp   = uptime % (3600L*24L);
	long huptime = htemp / 3600L;
	long mtemp   = htemp % 3600L;
	long muptime = mtemp / 60L;
	long suptime = mtemp % 60L;
	g.append("</span>\n<p>It has now been running for <span "+
		 "class=\"uptime\">"+
		 duptime + " days, "+
		 huptime + " hours, "+
		 muptime + " minutes and "+
		 suptime + " seconds.</span>\n");
	// Hits and bytes:
	g.append("<ul><li>hits:", Long.toString(stats.getHitCount()));
	long bytes = stats.getEmittedBytes();
	long kbytes = bytes / 1024;
	long mbytes = kbytes / 1024;
	long gbytes = mbytes / 1024;
	if (gbytes != 0) {
	    g.append("<li>bytes: " + gbytes + "Gb, " + mbytes % 1024 + "Mb, " +
		     kbytes % 1024 + "Kb, " + bytes % 1024);
	} else if (mbytes != 0) {
	    g.append("<li>bytes: " + mbytes + "Mb, " + kbytes % 1024 + "Kb, " 
		     + bytes % 1024);
	} else if (kbytes != 0) {
	    g.append("<li>bytes: " + kbytes + "Kb, " + bytes % 1024);
	} else {
	    g.append("<li>bytes:", Long.toString(stats.getEmittedBytes()));
	}
	// avg bytes/hit
	long avgbph = bytes / stats.getHitCount();
	kbytes = avgbph / 1024;
	mbytes = kbytes / 1024;
	gbytes = mbytes / 1024;
	if (gbytes != 0) {
	    g.append("<li>Average bytes per hit: " + gbytes + "Gb, " 
		     + mbytes % 1024 + "Mb, " +
		     kbytes % 1024 + "Kb, " + avgbph % 1024);
	} else if (mbytes != 0) {
	    g.append("<li>Average bytes per hit: " + mbytes + "Mb, " 
		     + kbytes % 1024 + "Kb, " 
		     + avgbph % 1024);
	} else if (kbytes != 0) {
	    g.append("<li>Average bytes per hit: " + kbytes + "Kb, " 
		     + avgbph % 1024);
	} else {
	    g.append("<li>Average bytes per hit:", Long.toString(avgbph));
	}
	// avg throughput
	long avgbps = bytes / uptime;
	kbytes = avgbps / 1024;
	mbytes = kbytes / 1024;
	gbytes = mbytes / 1024;
	if (gbytes != 0) {
	    g.append("<li>Average bytes per second: " + gbytes + "Gb, " 
		     + mbytes % 1024 + "Mb, " +
		     kbytes % 1024 + "Kb, " + avgbps % 1024);
	} else if (mbytes != 0) {
	    g.append("<li>Average bytes per second: " + mbytes + "Mb, " 
		     + kbytes % 1024 + "Kb, " 
		     + avgbps % 1024);
	} else if (kbytes != 0) {
	    g.append("<li>Average bytes per second: " + kbytes + "Kb, " 
		     + avgbps % 1024);
	} else {
	    g.append("<li>Average bytes per second:", Long.toString(avgbps));
	}    
	g.append("</ul>");
	// Request times:
	g.append(time_tbl) ;
	g.append("<td>"
		 , Long.toString(stats.getMinRequestTime())
		 , " <span class=\"unit\">ms</span>") ;
	g.append("<td>"
		 , Long.toString(stats.getMeanRequestTime())
		 , " <span class=\"unit\">ms</span>") ;
	g.append("<td>"
		 , Long.toString(stats.getMaxRequestTime())
		 , " <span class=\"unit\">ms</span>") ;
	g.append("</table>") ;
	// Thread report:
	g.append(thread_tbl) ;
	int free_t  = stats.getFreeThreadCount();
	int idle_t  = stats.getIdleThreadCount();
	int total_t =  stats.getTotalThreadCount();
	g.append("<td>" + free_t );
	g.append("<td>" + idle_t );
	g.append("<td>" + (total_t - free_t - idle_t ));
	g.append("<td>" + total_t);
	g.append("</table>") ;
	g.append("<p>Current load:"+stats.getServerLoad());
	Reply reply = request.makeReply(HTTP.OK) ;
	reply.setStream (g) ;
	return reply ;
    }
}

