/*
 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
 * This software is the proprietary information of Sun Microsystems, Inc.
 * Use is subject to license terms.
 * 
 * Copyright 2004 Sun Microsystems, Inc.  Tous droits r?serv?s.
 * Ce logiciel est propri?t? de Sun Microsystems, Inc.
 * Distribu? par des licences qui en restreignent l'utilisation.
 *
 * ident        "@(#)Transaction2.java 1.9     04/06/30 SMI"
 *
 */

package com.sun.mfwk.examples.instrum;

// java imports
//

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

// JDMK import
import com.sun.jdmk.comm.*;
import com.sun.jdmk.*;

// JMX RI imports
import javax.management.*;
import javax.management.remote.*;
import javax.management.remote.jmxmp.*;

// JESMA APIs
import com.sun.mfwk.trans.*;
import com.sun.mfwk.util.instrum.*;
import com.sun.mfwk.util.log.MfLogService;

/*
 *
 * Example of MfTransaction API usage using the Option 2 (MfTranReport report)
 *
 */

public class Transaction2 { 

    public static void main(String[] args) {

	Transaction2 myTransaction2 = new Transaction2();

	if (args.length == 1) {
	    myTransaction2.nbLoop = new Integer(args[0]).intValue();
	} else {
	    System.out.println("Usage: java Transaction2 nbLoop");
	    System.exit(1);
	}


	// Initialization: traces, connectors
	myTransaction2.init();

	// MfTransaction example
	myTransaction2.manageTransactions();
    }


    public void init() {

        // Parse system properties to check if LEVEL_TRACE and/or
	// LEVEL_DEBUG are set and enable the TRACE level accordingly
        try {
            TraceManager.parseTraceProperties();
        }
        catch (IOException e) {
            e.printStackTrace();
        }

	
	/*
        ** Create the MBean server
	*/
	mbs = MBeanServerFactory.createMBeanServer();

	/*
        ** Create JDMK HTML adaptor for debug 
	*/
	HtmlAdaptorServer htmlAdaptor = new HtmlAdaptorServer(8083);
        try {
            ObjectName oName =
                new ObjectName("jmx", "type", "htmlAdaptor");
            mbs.registerMBean(htmlAdaptor, oName);
	    htmlAdaptor.start();
        } catch(Exception e) {
            e.printStackTrace();
        }
	// waiting to leave starting state...
        while (htmlAdaptor.getState() == CommunicatorServer.STARTING) {
	    System.out.println("sleeping on htmlAdaptor");
            sleep(500);
        }
        System.out.println("\nHTML protocol adaptor started on port "+ htmlAdaptor.getPort());

	/*
        ** Create JSR 160 JMXMP connector 
	*/
	JMXConnectorServer cs = null;
	try {
	    JMXServiceURL url = new JMXServiceURL("jmxmp", null, 0);
	    cs = new JMXMPConnectorServer(url, null);
	    ObjectName csName =
		new ObjectName("jmx:type=cserver,name=jmxmpConnectorServer"); 
	    mbs.registerMBean(cs, csName);
	    cs.start();
	} catch (Exception e) {
	    e.printStackTrace();
	    System.exit(1);
	}
	System.out.println("\nJMXMP connector started.");

	// logging init
        MfLogService l = new MfLogService("sdk_transaction1");
    }


    void manageTransactions() {
	// Instanciate transaction factory
	MfTransactionFactory tranFactory = new MfTransactionFactoryImpl();

	// Instanciate the Metrics MBean
	MfTransactionMetrics transMetrics = new MfTransactionMetrics();
	// Register it in the MBeanServer
	try {
	    ObjectName oName = MfObjectNameFactory.getTransactionMetricsName("uri_name");
	    mbs.registerMBean(transMetrics, oName);
	} catch (Exception e) {
	    e.printStackTrace();
	}

	// Instanciate the MfInstrumManagement MBean
	MfInstrumManagement instrumManagement = new MfInstrumManagement();
	// Register it in the MBeanServer
	try {
	    ObjectName oName = MfObjectNameFactory.getInstrumManagementName();
	    mbs.registerMBean(instrumManagement, oName);
	} catch (Exception e) {
	    e.printStackTrace();
	}

	// Define the MfTransaction type
	MfTransactionDefinition tranDef =
	    tranFactory.newTransactionDefinition("MfTransaction type 1", "hello:/xx.xx", transMetrics);

	if (isCpuTimeSupported()) {
	    cpuTimeSupported = true;
	}

	// Define the MfTransaction instance (start/stop mode)
	MfTranReport tran = tranFactory.newTranReport(tranDef, null);

	for (int ii=0; ii < nbLoop; ii++, sleep(500)) {
	    long startTime = java.lang.System.currentTimeMillis();

	    long startCpuTime = 0;
	    if (cpuTimeSupported)
		startCpuTime = threadMBean.getCurrentThreadCpuTime();
	

	    // MfTransaction processing
	    System.out.println("Hello world1!");

	    double sum = 0;
	    for (int i = 0; i < 5000; i++) {
		double r = Math.random();
		double x = Math.pow(3, r);
		sum += x - r;
	    }	   
 
	    sleep(5000);


	    // The transaction is finished: report the info

	    long stopTime = java.lang.System.currentTimeMillis();
	    long responseTime = stopTime - startTime;

	    long stopCpuTime = threadMBean.getCurrentThreadCpuTime();
	    long cpuTime = stopCpuTime - startCpuTime;


	    tran.report(MfConstants.STATUS_GOOD, responseTime, cpuTime, stopTime);
	}

    }

    private static void sleep(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            return;
        }
    }

    private boolean isCpuTimeSupported() {
        // Check and set thread cpuTime instrumentation
        try {
            threadMBean = new MfCpuTime(null);	    

            if (threadMBean.isCurrentThreadCpuTimeSupported()) {
                 if (!threadMBean.isThreadCpuTimeEnabled()) {
                     threadMBean.setThreadCpuTimeEnabled(true);
                     System.out.println("ThreadCpuTime was not Enabled " +
                                        "we have enabled it"); 
                 } else {
                     System.out.println("ThreadCpuTime was already enabled.");
                 }
                return true;
            } else {
                System.out.println("WARNING: CurrentThreadCpuTime not supported.");
                return false;
            }
        } catch(Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    private MBeanServer mbs = null;
    private int nbLoop = 0;
    private MfCpuTime threadMBean = null;
    private boolean cpuTimeSupported = false;

}
