/*
 * 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        "@(#)SubTransaction1.java 1.7     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 1 (MfTransaction start/stop)
 * and sub-transactions
 *
 */

public class SubTransaction1 { 

    public static void main(String[] args) {

	SubTransaction1 mySubTransaction1 = new SubTransaction1();

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


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

	// MfTransaction example
	mySubTransaction1.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 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();
	}

	// Instanciate the Metrics MBeans
	MfTransactionMetrics transMetricsParent = new MfTransactionMetrics();
	MfTransactionMetrics transMetricsSubTrans = new MfTransactionMetrics();
	// Register it in the MBeanServer
	try {
	    ObjectName oName = MfObjectNameFactory.getTransactionMetricsName("parent_uri_name");
	    mbs.registerMBean(transMetricsParent, oName);
	    oName = MfObjectNameFactory.getTransactionMetricsName("subTrans_uri_name");
	    mbs.registerMBean(transMetricsSubTrans, oName);
	} catch (Exception e) {
	    e.printStackTrace();
	}

	// Define the MfTransaction types
	MfTransactionDefinition tranDefParent =
	    tranFactory.newTransactionDefinition("MfTransaction type parent)", "hello:/xx.xx", transMetricsParent);
	MfTransactionDefinition tranDefSubTrans =
	    tranFactory.newTransactionDefinition("MfTransaction type subTrans", "hello:/xx.xx/yyy", transMetricsSubTrans);

	// Define the MfTransaction instances (start/stop mode)
	MfTransaction tranParent = tranFactory.newTransaction(tranDefParent, null);
	MfTransaction subTrans = tranFactory.newTransaction(tranDefSubTrans, tranParent);

	for (int ii=0; ii < nbLoop; ii++, sleep(500)) {

	    // Start the parent transaction
	    int ret = tranParent.start();
	    if (ret != MfConstants.OK)
		System.out.println(tranParent.getErrorMessage(tranParent.getErrorCode()));

	    // Parent transaction processing
	    System.out.println("Parent transaction processing...");

	    math_proc(); 

	    sleep(4000);

	    // Suspend transaction time
	    ret = tranParent.block();
	    if (ret != MfConstants.OK)
		System.out.println(tranParent.getErrorMessage(tranParent.getErrorCode()));

	    // External service processing
	    sleep(1000);

	    math_proc(); 

	    // Resume transaction time
	    ret = tranParent.unblock();
	    if (ret != MfConstants.OK)
		System.out.println(tranParent.getErrorMessage(tranParent.getErrorCode()));

	    ////////////////////////////////////////////////
	    // Sub-transaction starting
	    ret = subTrans.start();
	    if (ret != MfConstants.OK)
		System.out.println(subTrans.getErrorMessage(subTrans.getErrorCode()));

	    // Sub-transaction processing
	    System.out.println("Sub-transaction processing...");

	    math_proc(); 

	    // Stop the sub-transaction
	    ret = subTrans.stop(MfConstants.STATUS_GOOD);
	    if (ret != MfConstants.OK)
		System.out.println(subTrans.getErrorMessage(subTrans.getErrorCode()));
	    ////////////////////////////////////////////////
	    

	    // Stop the parent transaction
	    ret = tranParent.stop(MfConstants.STATUS_GOOD);
	    if (ret != MfConstants.OK)
		System.out.println(tranParent.getErrorMessage(tranParent.getErrorCode()));
	}

    }

    private static void math_proc() {
	    double sum = 0;
	    for (int i = 0; i < 50000; i++) {
		double r = 0.543;
		double x = Math.pow(30, r);
		sum += x - r;
	    }	  
    } 

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

    private MBeanServer mbs = null;
    private int nbLoop = 0;

}
