<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Altentee » Performance &#38; Test Automation Experts &#187; java</title>
	<atom:link href="http://altentee.com/blogs/tag/java/feed/" rel="self" type="application/rss+xml" />
	<link>http://altentee.com</link>
	<description>Performance and Test Automation Experts</description>
	<lastBuildDate>Fri, 04 Nov 2011 03:17:30 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.3</generator>
		<item>
		<title>Sharing data safely between Java threads</title>
		<link>http://altentee.com/blogs/2007/sharing-data-safely-between-java-threads/</link>
		<comments>http://altentee.com/blogs/2007/sharing-data-safely-between-java-threads/#comments</comments>
		<pubDate>Wed, 24 Oct 2007 23:50:26 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[Altentee]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://90kts.com/blog/2007/sharing-data-safely-between-java-threads/</guid>
		<description><![CDATA[Am really starting to enjoy the power and portability of using Java in my load testing efforts, especially when the environments in which you work are often limited in terms of tool sets you&#8217;re allowed to use. For example the current Solaris environment I work in doesn&#8217;t have a C compiler native to the OS, [...]]]></description>
			<content:encoded><![CDATA[<p>Am really starting to enjoy the power and portability of using Java in my load testing efforts, especially when the environments in which you work are often limited in terms of tool sets you&#8217;re allowed to use. For example the current Solaris environment I work in doesn&#8217;t have a C compiler native to the OS, so I am automatically limited in the amount of Perl code I can write, as I am lacking more powerful modules (that need to be compiled). Enter Java; it already comes installed and for the types of mid range services I&#8217;m working on (MQ, JMS etc) has loads of great APIs you can incorporate into your own custom test harnesses.</p>
<p>All good test harnesses are going to need to be multi-threaded, but I&#8217;ve had no idea on how to safely share data between threads! This problem has been annoying me for sometime, partly due to my own ignorance and lack of understanding of Java (indeed OO principles perhaps). But in any case, I was stuck in old (bad) habits of sharing data between threads. Normally I just assign a global variable but in OO design, that&#8217;s considered poor design, so here is my attempt at getting spawned threads of a &#8216;worker&#8217; class sharing data via a common &#8216;datastore&#8217; class.<br />
<span id="more-84"></span></p>
<p>I have a standard Java application which from main, instantiates an object of my &#8216;boss&#8217; class.<br />
<code><br />
/*<br />
 * Main.java<br />
 */</p>
<p>public class Main {<br />
    public Main() {<br />
    }</p>
<p>    public static void main(String[] args) {<br />
        BossThread boss = new BossThread();<br />
        boss.start();<br />
    }<br />
}<br />
</code></p>
<p>The &#8216;boss&#8217; class normally does a number of things, such as control thread execution logic and the like. It also serves as a common point in my design from which to launch &#8216;worker&#8217; threads and also create the &#8216;datastore&#8217; object. The BossThread looks a little like this.<br />
<code><br />
/*<br />
 * BossThread.java<br />
 */<br />
import java.util.*;<br />
import java.io.*;<br />
import java.util.ArrayList;<br />
import java.util.Iterator;</p>
<p>public class BossThread extends Thread {<br />
    private final ArrayList workers     = new ArrayList();<br />
    private final DataStore dataStore   = new DataStore();<br />
    private String  threadType;               // type of thread operation<br />
    private int     numWorkersStarted = 0;    // started thread counter<br />
    private int     numThreads = 20;       // number of threads to spawn</p>
<p>    public BossThread() {<br />
    }</p>
<p>    public void run() {<br />
        try {<br />
            threadType="put";<br />
            createWorkerThreads();<br />
            startWorkerThreads();</p>
<p>            threadType="get";<br />
            createWorkerThreads();<br />
            startWorkerThreads();<br />
        } catch (Exception e) {<br />
            e.printStackTrace();<br />
        }<br />
    }</p>
<p>    private void createWorkerThreads() throws Exception {<br />
        for (int i = 1; i <= numThreads; i++) {<br />
            String threadName = threadType + "_WORKER_" + i;<br />
            workers.add(new WorkerThread(threadName, dataStore, threadType));<br />
        }<br />
    }</p>
<p>    private void startWorkerThreads() throws Exception {<br />
        int threadStartIndex=numWorkersStarted;<br />
        for (int i = threadStartIndex; i < numThreads+threadStartIndex; i++) {<br />
            WorkerThread worker = (WorkerThread) workers.get(i);<br />
            Thread.sleep(250 + (int) (Math.random() * 500));<br />
            worker.start();<br />
            numWorkersStarted++;<br />
        }<br />
    }<br />
}<br />
</code></p>
<p>So you can see that early in the piece I instantiate an instance of the DataStore class, which is then passed as a parameter along with some custom fields like threadName and threadType to my WorkerThread class. I'm also using an ArrayList to simplify the organization, creation and starting of worker threads via some private methods.</p>
<p>The WorkerThread class looks like this.<br />
<code><br />
/*<br />
 * WorkerThread.java<br />
 */</p>
<p>public class WorkerThread extends Thread {<br />
    private DataStore dataStore;<br />
    private String threadType;<br />
    private String threadName;</p>
<p>    public WorkerThread(String threadName, DataStore dataStore, String threadType) {<br />
        this.threadName = threadName;<br />
        this.dataStore  = dataStore;<br />
        this.threadType = threadType;<br />
    }</p>
<p>    public void run() {<br />
        if (threadType.equals("put")) putdataStore();<br />
        if (threadType.equals("get")) getdataStore();<br />
    }</p>
<p>    private void putdataStore() {<br />
        for (int i = 0; i < 10; i++) {<br />
            dataStore.putResponseTime("key",i);<br />
            System.out.println(threadName + " put: " + i);<br />
            try {<br />
                sleep((int)(Math.random() * 1000));<br />
            } catch (InterruptedException e) {<br />
                e.printStackTrace();<br />
            }<br />
        }<br />
    }</p>
<p>    private void getdataStore() {<br />
        int val = 0;<br />
        for (int i = 0; i < 10; i++) {<br />
            value = dataStore.getResponseTime("key");<br />
            System.out.println(threadName + " get: " + val);<br />
            try {<br />
                sleep((int)(Math.random() * 1000));<br />
            } catch (InterruptedException e) {<br />
                e.printStackTrace();<br />
            }<br />
        }<br />
    }<br />
}<br />
</code></p>
<p>You can see that its constructor gets the instance of the 'datastore' object, which can then call on public methods of the DataStore class such as putdataStore and getdataStore.</p>
<p>Finally, the DataStore class looks like this.<br />
<code><br />
/*<br />
 * DataStore.java<br />
 */</p>
<p>import java.util.*;<br />
import java.util.concurrent.*;</p>
<p>public class DataStore {<br />
    private Map<string, Integer> responseTimes    = new ConcurrentHashMap<string, Integer>();<br />
    private boolean available = false;</p>
<p>    public DataStore() {<br />
    }</p>
<p>    public synchronized void putResponseTime(String key, int val) {<br />
        responseTimes.put(key, val);<br />
        notifyAll();<br />
    }</p>
<p>    public synchronized int getResponseTime(String key) {<br />
        notifyAll();<br />
        int val=-1;<br />
        if(responseTimes.containsKey(key)){<br />
            val = responseTimes.get(key);<br />
        }<br />
        return val;<br />
    }<br />
}<br />
</code></p>
<p>In here you can get as creative as you want. I'm using the ConcurrentHashMap to store key/val pairs of data which on its own is considered thread safe. I'm not sure if it is redudant code but I chose to make the public methods synchronized aswell, in order to ensure that threads don't get into a spin when trying to access the same. To quote Sun</p>
<blockquote><p>First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.</p>
<p>Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.
</p></blockquote>
<p>Perhaps someone with a better understanding of Java and threading can explain if this is required given that I'm already using a concurrent collection? If you weren't, then you'd definitely need to consider synchronized methods ...</p>
<p>But right now, using the skeleton provided, you should be able to write thread safe programs, and easily share data between worker threads and a boss thread(s). I'm using this design at the moment to work on a MQ load harness, and hope that it will be available for public use soon. <img src='http://altentee.com/blogs/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/blogs/2007/sharing-data-safely-between-java-threads/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>A custom load harness for MQ Server</title>
		<link>http://altentee.com/blogs/2007/a-custom-load-harness-for-mq-server/</link>
		<comments>http://altentee.com/blogs/2007/a-custom-load-harness-for-mq-server/#comments</comments>
		<pubDate>Tue, 30 Jan 2007 02:44:26 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[Altentee]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[MQ]]></category>

		<guid isPermaLink="false">http://90kts.com/blog/?p=12</guid>
		<description><![CDATA[This is another blog in a similar vein to &#8220;No LoadRunner, No Problems&#8221; where I needed to write a custom test harness for MQ server. IBM kindly provide a complete Java API for getting in to the nitty gritty of MQ messages. Much can be learnt from WebSphere MQ sample code in Java and of [...]]]></description>
			<content:encoded><![CDATA[<p>This is another blog in a similar vein to &#8220;<a href="http://90kts.com/blog/?p=5">No LoadRunner, No Problems</a>&#8221; where I needed to write a custom test harness for MQ server. IBM kindly provide a complete Java API for getting in to the nitty gritty of MQ messages. Much can be learnt from <a href="http://www-304.ibm.com/jct09002c/isv/tech/sampmq.html">WebSphere MQ sample code</a> in Java and of course, if you ever get stuck in analyzing problems in your MQ setup you should always visit the <a href="http://www.mqseries.net/phpBB2/index.php?sid=72d8b22f537e53e764a27db8d7803eff">MQSeries.net :: Index</a>. Kevin Braithewaite wrote a really good harness that <a href="http://www-128.ibm.com/developerworks/websphere/library/techarticles/0407_braithwaite/0407_braithwaite.html">simplifies performance and stress testing with MQJavaRoundTrip</a>. I have since written an extended version of this test harness that takes elements from many sources (including my own) and written a comprehensive test harness for MQ which is detailed in this post.</p>
<p><span id="more-267"></span><br />
<code><br />
/**<br />
* MQ Load Generator (MQLoader)<br />
*<br />
* Compile	: javac -classpath com.ibm.mq.jar:connector.jar:jta.jar MQLoader.java<br />
* Package	: jar cfm MQLoader.jar MQLoader.MF *.class<br />
* Execute	: java -cp com.ibm.mq.jar:connector.jar:jta.jar:MQLoader.jar MQLoader [options]<br />
* Usage		: MQLoader [options]<br />
* Options	:<br />
           -logfile	path to activity logfile (errors, thread status, msg counters)<br />
		-file		path to template file or folder containing template files<br />
		-qmngr		name of MQ queue manager<br />
		-putQ		name of MQ request 'put' queue<br />
		-getQ		name of MQ reply 'get' queue<br />
		-channel	name of MQ channel<br />
		-host		IP address or DNS of MQ server<br />
		-port		port number of MQ server<br />
		-conns		number of concurrent connections to simulate<br />
		-num		number of messages to create per connection<br />
		-pacing		pacing in milliseconds between each message<br />
		-persist	optional flag for persistent messages<br />
		-verbose	optional flag for verbose output<br />
		-quiet		optional flag to suppress stdout results, recommended when using discovery mode<br />
		-putonly	optional flag for put only mode<br />
		-getonly	optional flag for get only mode<br />
		-discover	optional flag to force discovery mode<br />
		-sla		optional sla time in millisecs to target during discovery mode<br />
		-stats		optional flag to show descriptive statistics at test completion<br />
		-nomod		optional flag to stop load harness from modifying input messages IAW Strata specifications<br />
					when used the test harness will not be able to accurately calculate response time<br />
		-nolog		optional flag to stop activity logging, not recommended.<br />
*<br />
* Last edited	: 15 Feb 07 14.00<br />
* Author		: Tim Koopmans<br />
**/</p>
<p>import java.io.*;<br />
import com.ibm.mq.*;<br />
import java.util.*;<br />
import java.util.regex.*;<br />
import java.text.*;<br />
import java.text.SimpleDateFormat;<br />
import java.text.DecimalFormat;</p>
<p>public class MQLoader {<br />
	final static Properties arguments = new Properties();<br />
	public static String logfile;<br />
	public static String file;<br />
	public static String qmngr;<br />
	public static String putQ;<br />
	public static String getQ;<br />
	public static String channel;<br />
	public static String host;<br />
	public static String load;<br />
	public static String testID;<br />
	public static double thruput;<br />
	public static int port;<br />
	public static int conns;<br />
	public static int num;<br />
	public static int pacing;<br />
	public static int adjustedPacing;<br />
	public static int sla;<br />
	public static int paceMod;<br />
	public static int parseCounter		= 0;<br />
	public static int retryMax			= 1000;<br />
	public static boolean persistence 	= false;<br />
	public static boolean verbose 		= false;<br />
	public static boolean getonly 		= false;<br />
	public static boolean putonly 		= false;<br />
	public static boolean discover 		= false;<br />
	public static boolean quiet 		= false;<br />
	public static boolean stats 		= false;<br />
	public static boolean nomod 		= false;<br />
	public static boolean nolog 		= false;<br />
	public static DecimalFormat fmt 	= new DecimalFormat("###,###,##0.00");<br />
	public static int[] responseTimeArray;<br />
	public static double[] throughputArray;<br />
	int CCSID;<br />
	String content;<br />
	String[] contents;<br />
	String mqMessage;<br />
	String DTG;<br />
	String HEX;</p>
<p>	// MAIN METHOD<br />
	public static void main(String[] args) throws IOException {</p>
<p>		// CALL TO PARSE ARGS METHOD<br />
		parseArguments(args);<br />
		thruput = 1.00/pacing*1000*conns;</p>
<p>		// START TEST<br />
		String startDTG = formatDTG();<br />
		if(verbose) { System.out.println("Start DTG\t\t"+startDTG); }<br />
		if(verbose) { System.out.println("Connections\t\t"+conns); }<br />
		if(verbose) { System.out.println("Transactions\t\t"+num*conns); }<br />
		if(verbose) { System.out.println("Pacing\t\t\t"+pacing); }<br />
		if(verbose) { if(persistence) { System.out.println("Persistence\t\tON"); } else { System.out.println("Persistence\t\tOFF"); } }<br />
		if(verbose) { System.out.print("Threads Started:\t "); }</p>
<p>		// BUILD ARRAYS FOR RESPONSE TIMES &#038; THROUGHPUT<br />
		responseTimeArray 	= new int[num*conns];<br />
		throughputArray 	= new double[num*conns];</p>
<p>		try {<br />
			//MULTI THREAD PUT MODE<br />
			if((putonly) || (!getonly)) {<br />
				for (int t=1; t<=conns; t++) {<br />
					Random generator = new Random();<br />
					int randStart = generator.nextInt( pacing );<br />
					try { Thread.sleep(randStart);	} catch (InterruptedException ie) {} // Randomize start time ...</p>
<p>					try { Thread  thr = new Thread(new Runnable() {	public void run() {<br />
							MQLoader simulation = new MQLoader(file, qmngr, putQ, host, channel, port, pacing);<br />
							try { simulation.put(); } catch (IOException ioe) {}}});<br />
							thr.setName("putThread:"+t);<br />
							thr.start();<br />
					} catch (Exception ex) {<br />
						// PUT THREAD ERRORS<br />
						if(!nolog){ write(logfile, testID+"\t\tputThread:"+t+"\t\tError! Starting thread ... \n"+ex+"\n"); }<br />
					}<br />
				}<br />
				if(verbose) { System.out.print("\n"); }<br />
			}</p>
<p>			// MULTI THREAD GET MODE<br />
			if((getonly) || (!putonly)) {<br />
				if(verbose) {} else if(!quiet) { System.out.println("\n\tDate    \tTime    \tConns\tPace\tLoad\tPersist\trTime\tTestID"); }</p>
<p>				for (int t=1; t<=conns; t++) {<br />
					Random generator = new Random();<br />
					int randStart = generator.nextInt( 333 );<br />
					try { Thread.sleep(randStart);	} catch (InterruptedException ie) {} // Randomize start time ...</p>
<p>					try { Thread  thr = new Thread(new Runnable() {	public void run() {<br />
							MQLoader simulation = new MQLoader(file, qmngr, putQ, host, channel, port, pacing);<br />
							simulation.get();}});<br />
							thr.setName("getThread:"+t);<br />
							thr.start();<br />
					} catch (Exception ex) {<br />
						// GET THREAD ERRORS<br />
						if(!nolog){ write(logfile, testID+"\t\tgetThread:"+t+"\t\tError! Starting thread ... \n"+ex+"\n"); }<br />
					}<br />
					if(verbose) { System.out.print("\n"); }<br />
				}<br />
			}</p>
<p>		} catch (Exception ex) {<br />
			// GENERIC ERRORS<br />
			if(!nolog){ write(logfile, "Error! Generic error in MAIN execution ... "+ex); }<br />
		} finally {<br />
			// WAIT FOR ACTIVE THREADS<br />
			if(!putonly) {<br />
				while(Thread.currentThread().activeCount()>1) {<br />
					// Wait for all threads to finish.<br />
				}<br />
			}<br />
			// FINISH<br />
			String finishDTG = formatDTG();<br />
			if(verbose) { System.out.println("Finish DTG\t\t"+finishDTG+"\n"); }<br />
			if(putonly) { System.out.println("No messages to get as the -putonly flag was specified"); }<br />
			if(getonly) { System.out.println("No messages to put as the -getonly flag was specified"); }</p>
<p>			// OPTIONAL CALL TO STATISTICS METHOD<br />
			if(stats) { collectStats(); }<br />
		}<br />
	}</p>
<p>	// CONSTRUCTOR FOR CLASS<br />
	public MQLoader(String file, String qmngr, String putQ, String host, String channel, int port, int pacing) {<br />
		this.file 	= file;<br />
		this.qmngr	= qmngr;<br />
		this.putQ 	= putQ;<br />
		this.host 	= host;<br />
		this.channel= channel;<br />
		this.port 	= port;<br />
		this.CCSID 	= 437;<br />
		this.pacing = pacing;<br />
	}</p>
<p>	// PARSE ARGUMENTS METHOD<br />
	private static void parseArguments(String[] args) {</p>
<p>		String currentkey = null;<br />
		String currentvalue = "";</p>
<p>		arguments.setProperty("logfile","MQLoader.log");<br />
		arguments.setProperty("file", 	"InputMsg.txt");<br />
		arguments.setProperty("qmngr", 	"QMANAGER");<br />
		arguments.setProperty("putQ", 	"QUEUE.REQUEST");<br />
		arguments.setProperty("getQ", 	"QUEUE.REPLY");<br />
		arguments.setProperty("channel","CHAN_NAME");<br />
		arguments.setProperty("host", 	"10.0.1.2");<br />
		arguments.setProperty("port", 	"1415");<br />
		arguments.setProperty("conns", 	"1");<br />
		arguments.setProperty("num", 	"1");<br />
		arguments.setProperty("pacing", "5");<br />
		arguments.setProperty("load", 	"--");<br />
		arguments.setProperty("testID", "--");<br />
		arguments.setProperty("paceMod","10");<br />
		arguments.setProperty("sla", 	"1000");</p>
<p>		if (args.length == 0)<br />
			printUsage();</p>
<p>		for (int i = 0; i < args.length; i++) {<br />
			if (args[i].startsWith("-")) {<br />
				if (currentkey != null) {<br />
					arguments.setProperty(currentkey, currentvalue);<br />
				}<br />
				currentkey = args[i].substring(1);<br />
				currentvalue = "true";<br />
			} else if (currentvalue.equals("true")) {<br />
				currentvalue = args[i];<br />
			}<br />
		}<br />
		if (currentkey != null)<br />
			arguments.setProperty(currentkey, currentvalue);</p>
<p>		if (arguments.getProperty("verbose")	!=null) verbose 	= true;<br />
		if (arguments.getProperty("quiet")		!=null) quiet 		= true;<br />
		if (arguments.getProperty("stats")		!=null) stats 		= true;<br />
		if (arguments.getProperty("persist")	!=null) persistence = true;<br />
		if (arguments.getProperty("putonly")	!=null) putonly 	= true;<br />
		if (arguments.getProperty("getonly")	!=null) getonly 	= true;<br />
		if (arguments.getProperty("discover")	!=null) discover 	= true;<br />
		if (arguments.getProperty("nomod")		!=null) nomod 		= true;<br />
		if (arguments.getProperty("nolog")		!=null) nolog 		= true;</p>
<p>		logfile			= arguments.getProperty("logfile");<br />
		file 			= arguments.getProperty("file");<br />
		qmngr			= arguments.getProperty("qmngr");<br />
		putQ 			= arguments.getProperty("putQ");<br />
		getQ 			= arguments.getProperty("getQ");<br />
		channel			= arguments.getProperty("channel");<br />
		host 			= arguments.getProperty("host");<br />
		port 			= Integer.parseInt(arguments.getProperty("port"));<br />
		conns			= Integer.parseInt(arguments.getProperty("conns"));<br />
		num				= Integer.parseInt(arguments.getProperty("num"));<br />
		pacing			= Integer.parseInt(arguments.getProperty("pacing"));<br />
		load 			= arguments.getProperty("load");<br />
		testID			= arguments.getProperty("testID");<br />
		paceMod			= Integer.parseInt(arguments.getProperty("paceMod"));<br />
		sla				= Integer.parseInt(arguments.getProperty("sla"));<br />
		adjustedPacing 	= pacing;</p>
<p>	}</p>
<p>	// PRINT USAGE METHOD<br />
	private static void printUsage() {<br />
		System.out.println ("\nWarning: You are missing command line arguments!");<br />
		System.out.println ("------------------------------------------------");<br />
		System.out.println ("Usage: java MQ<br />
<options>");<br />
		System.out.println ("Options:");<br />
		System.out.println ("  -file\t\t- path to template decision request file \teg. -file TEMPLATEDIR");<br />
		System.out.println ("  -qmngr\t- name of MQ putQ manager \t\t\teg. -qmngr QMNGRNAME");<br />
		System.out.println ("  -putQ\t\t- name of MQ request queue \t\t\teg. -putQ REQUESTQUEUE");<br />
		System.out.println ("  -getQ\t\t- name of MQ reply queue \t\t\teg. -getQ REPLYQUEUE");<br />
		System.out.println ("  -channel\t- name of MQ channel \t\t\t\teg. -channel CHANNELNAME");<br />
		System.out.println ("  -host\t\t- IP address of MQ server \t\t\teg. -host 127.0.0.1");<br />
		System.out.println ("  -port\t\t- port number of MQ server \t\t\teg. -port 1415");<br />
		System.out.println ("  -conns\t- number of concurrent connections to simulate \teg. -conns 1");<br />
		System.out.println ("  -num\t\t- number of messages to create per connection \teg. -num 1000");<br />
		System.out.println ("  -pacing\t- pacing in milliseconds between each message \teg. -pacing 100");<br />
		System.out.println ("  -persist\t- optional flag for persistent messages \teg. -persist");<br />
		System.out.println ("  -verbose\t- optional flag for verbose output \t\teg. -verbose");<br />
		System.out.println ("  -quiet\t- optional flag for no output \t\t\teg. -quiet");<br />
		System.out.println ("  -stats\t- optional flag for statistics \t\t\teg. -stats");<br />
		System.out.println ("  -putonly\t- optional flag for put only mode \t\teg. -putonly");<br />
		System.out.println ("  -getonly\t- optional flag for get only mode \t\teg. -getonly");<br />
		System.out.println ("  -load\t\t- optional flag to indicate load profile \teg. -load 100");<br />
		System.out.println ("  -testID\t- optional flag to indicate testID \teg. -testID CA1.1\n");<br />
	}</p>
<p>	// PUT METHOD<br />
	public void put() throws IOException {<br />
		String threadID = Thread.currentThread().getName();<br />
		if(verbose) { System.out.print("\r"+testID+"\t\t"+threadID+"\t\tStarted: OK"); }<br />
		try { if(!nolog){ write(logfile, testID+"\t\t"+threadID+"\t\tStarted: OK"); } } catch (IOException ioe) {}<br />
		try<br />
		{<br />
			if (host != null)<br />
			{<br />
				if(verbose) { System.out.println(testID+"\t\t"+threadID+"\t\tHOST\t\t\t: " + host); }<br />
				MQEnvironment.hostname = host;<br />
				MQEnvironment.properties.put(MQC.TRANSPORT_PROPERTY,MQC.TRANSPORT_MQSERIES_CLIENT);<br />
			}<br />
			if (channel != null)<br />
			{<br />
				if(verbose) { System.out.println(testID+"\t\t"+threadID+"\t\tCHANNEL\t\t\t: " + channel); }<br />
				MQEnvironment.channel = channel;<br />
			}<br />
			if (port != 0)<br />
			{<br />
				if(verbose) { System.out.println(testID+"\t\t"+threadID+"\t\tPORT\t\t\t: " + port); }<br />
				MQEnvironment.port = port;<br />
			}<br />
			if (CCSID != 0)<br />
			{<br />
				if(verbose) { System.out.println(testID+"\t\t"+threadID+"\t\tCCSID\t\t\t: " + CCSID); }<br />
				MQEnvironment.CCSID = CCSID;<br />
			}<br />
			if(verbose) { System.out.println(testID+"\t\t"+threadID+"\t\tCONNECT Q MNGR\t\t: "+qmngr); }<br />
			MQQueueManager qMgr = new MQQueueManager(qmngr);<br />
			int openOptions = MQC.MQOO_OUTPUT<br />
					| MQC.MQOO_INQUIRE<br />
					| MQC.MQOO_FAIL_IF_QUIESCING;<br />
			if(verbose) { System.out.println(testID+"\t\t"+threadID+"\t\tOPENING QUEUE\t\t: "+putQ); }<br />
			MQQueue q = qMgr.accessQueue(putQ, openOptions, null, null, null);</p>
<p>			readFiles(file);<br />
			//readFile(file); // LEGACY</p>
<p>			MQPutMessageOptions pmo = new MQPutMessageOptions();<br />
			pmo.options = MQC.MQPMO_NONE;</p>
<p>			int retryCount=0;</p>
<p>			for (int i=1; i<=num; i++) {</p>
<p>				try {</p>
<p>					// Pick random content from the list of files provided if a directory<br />
					Random generator = new Random();<br />
					int randomContent = generator.nextInt( contents.length );<br />
					if(nomod) {<br />
						mqMessage=contents[randomContent]; // Don't modify message contents when nomod is true<br />
					}<br />
					else{<br />
						modifyContent(contents[randomContent]); // Modify message contents when nomode is false [default]<br />
																// in accordance with Strata 4.0 message specifications ...<br />
					}</p>
<p>					if(verbose) { System.out.println(testID+"\t\t"+threadID+"\t\tMSG LENGTH\t\t: "+mqMessage.length()+" bytes"); }</p>
<p>					MQMessage mqMsg = new MQMessage();<br />
					mqMsg.clearMessage();<br />
					if (persistence) {<br />
						mqMsg.persistence = MQC.MQPER_PERSISTENT;<br />
					} else {<br />
						mqMsg.persistence = MQC.MQPER_NOT_PERSISTENT;<br />
					}<br />
					mqMsg.correlationId 	= MQC.MQCI_NONE;<br />
					mqMsg.messageId 	= MQC.MQMI_NONE;<br />
					mqMsg.writeString(mqMessage);<br />
					if(verbose) { System.out.println(testID+"\t\t"+threadID+"\t\tPUT MESSAGE ON QUEUE"); }<br />
					q.put(mqMsg, pmo);<br />
				} catch (MQException ex) {<br />
					i--;<br />
					retryCount++;<br />
					//Attempt to catch the following errors:<br />
					if(ex.reasonCode==2009) {<br />
						// MQJE001: An MQException occurred: Completion Code 2, Reason 2009<br />
						// Connection to MQ has been lost, attempt to reconnect!<br />
						if(!nolog){ write(logfile, testID+"\t\t"+threadID+"\t\tError! PUT Connection to MQ has been lost, attempting to reconnect ... \n"+ex+"\n"); }<br />
						try {<br />
							qMgr = new MQQueueManager(qmngr);<br />
							q = qMgr.accessQueue(putQ, openOptions, null, null, null);<br />
						}<br />
						catch (MQException exR) {<br />
							if(!nolog){ write(logfile, testID+"\t\t"+threadID+"\t\tError! PUT Reconnect failed ... \n"+exR+"\n"); }<br />
						}<br />
					} else {<br />
						// Must have another type of MQ execption, so log it ...<br />
						if(!nolog){ write(logfile, testID+"\t\t"+threadID+"\t\tError! MQ Exception in put() method ... \n"+ex+"\n"); }<br />
						throw new IOException(<br />
						testID+"\t\t"+threadID+"\t\tConnection to MQSeries is broken on putQ(qmngr/channel)@host:port\n"<br />
						+ putQ + "(" + qmngr + "/"<br />
						+ MQEnvironment.channel + ")@"<br />
						+ MQEnvironment.hostname + ":"<br />
						+ MQEnvironment.port);<br />
					}</p>
<p>					// Enforce retry count maximums when NOT in discovery mode ...<br />
					if(!discover) {<br />
						if(retryCount>retryMax) {<br />
							// Max retries hit<br />
							i = num;<br />
							if(!nolog){ write(logfile, testID+"\t\t"+threadID+"\t\tError! Max PUT retry limit reached ... \n"+ex+"\n"); }<br />
						}<br />
					}</p>
<p>				} finally {<br />
					if(!discover) {if(!nolog){ write(logfile, testID+"\t\t"+threadID+"\t\tPut Msg: "+i+"/"+num+""); } }<br />
					//Adjust pacing based on last response time recorded so as account for elapsed test time.<br />
					if(adjustedPacing>0) { try { Thread.sleep(adjustedPacing);	} catch (InterruptedException ie) {} }<br />
				}<br />
			}</p>
<p>			if(verbose) { System.out.println(testID+"\t\t"+threadID+"\t\tCLOSING CONNECTION"); }<br />
			q.close();<br />
			qMgr.disconnect();<br />
			if(verbose) { System.out.print("\r"+testID+"\t\t"+threadID+"\t\tClosed : OK"); }<br />
			try { if(!nolog){ write(logfile, testID+"\t\t"+threadID+"\t\tClosed : OK"); } } catch (IOException ioe) {}</p>
<p>		} catch (Exception ex) {<br />
			try { if(!nolog){ write(logfile, testID+"\t\t"+threadID+"\t\tError! Generic error in PUT method ... \n"+ex+"\n"); } } catch (IOException ioe) {}<br />
		}<br />
	}</p>
<p>	// GET METHOD<br />
	private void get() {<br />
		String threadID = Thread.currentThread().getName();<br />
		if(verbose) { System.out.print("\r"+testID+"\t\t"+threadID+"\t\tStarted: OK"); }<br />
		try { if(!nolog){ write(logfile, testID+"\t\t"+threadID+"\t\tStarted: OK"); } } catch (IOException ioe) {}<br />
		try<br />
		{<br />
			if (host != null) {<br />
				if(verbose) { System.out.println(testID+"\t\t"+threadID+"\t\tHOST\t\t\t: " + host); }<br />
				MQEnvironment.hostname = host;<br />
				MQEnvironment.properties.put(MQC.TRANSPORT_PROPERTY,MQC.TRANSPORT_MQSERIES_CLIENT);<br />
				MQEnvironment.disableTracing();<br />
				MQException.log=null;<br />
			}<br />
			if (channel != null) {<br />
				if(verbose) { System.out.println(testID+"\t\t"+threadID+"\t\tCHANNEL\t\t\t: " + channel); }<br />
				MQEnvironment.channel = channel;<br />
			}<br />
			if (port != 0) {<br />
				if(verbose) { System.out.println(testID+"\t\t"+threadID+"\t\tPORT\t\t\t: " + port); }<br />
				MQEnvironment.port = port;<br />
			}<br />
			if (CCSID != 0)	{<br />
				if(verbose) { System.out.println(testID+"\t\t"+threadID+"\t\tCCSID\t\t\t: " + CCSID); }<br />
				MQEnvironment.CCSID = CCSID;<br />
			}<br />
			if(verbose) { System.out.println(testID+"\t\t"+threadID+"\t\tCONNECT Q MNGR\t\t: "+qmngr); }<br />
			MQQueueManager qMgr = new MQQueueManager(qmngr);<br />
			int openOptions = MQC.MQOO_INPUT_SHARED<br />
					| MQC.MQOO_INQUIRE<br />
					| MQC.MQOO_FAIL_IF_QUIESCING;<br />
			if(verbose) { System.out.println(testID+"\t\t"+threadID+"\t\tOPENING QUEUE\t\t: "+getQ); }<br />
			MQQueue q = qMgr.accessQueue(getQ, openOptions);</p>
<p>			int retryCount=0;</p>
<p>			for (int i=1; i<=num; i++) {<br />
				String msgText = null;</p>
<p>				try {<br />
					MQMessage mqMsg = new MQMessage();<br />
					// MQGetMessageOptions gmo = new MQGetMessageOptions();<br />
					// q.get(mqMsg, gmo);<br />
					q.get(mqMsg);</p>
<p>					if(verbose) { System.out.println(testID+"\t\t"+threadID+"\t\tMSG ID\t\t\t: "+dumpHexId(mqMsg.messageId)); }<br />
					if(verbose) { System.out.println(testID+"\t\t"+threadID+"\t\tCORREL ID\t\t: "+dumpHexId(mqMsg.correlationId)); }</p>
<p>					if(verbose) { System.out.print(testID+"\t\t"+threadID+"\t\tPUT DATE\t\t: "); }<br />
					int finYY = mqMsg.putDateTime.get(Calendar.YEAR); if(verbose) { System.out.print(finYY); }<br />
					int finMM = mqMsg.putDateTime.get(Calendar.MONTH) + 1; if(verbose) { if (finMM < 10) { System.out.print("0"); } System.out.print(finMM); }<br />
					int finDD = mqMsg.putDateTime.get(Calendar.DAY_OF_MONTH); if(verbose) { if (finDD < 10) { System.out.print("0"); } System.out.print(finDD); }<br />
					if(verbose) { System.out.println(""); }</p>
<p>					if(verbose) { System.out.print(testID+"\t\t"+threadID+"\t\tPUT TIME\t\t: "); }<br />
					int finHH = mqMsg.putDateTime.get(Calendar.HOUR_OF_DAY); if(verbose) { if (finHH < 10) { System.out.print("0"); } System.out.print(finHH); }<br />
					int finmm = mqMsg.putDateTime.get(Calendar.MINUTE); if(verbose) { if (finmm < 10) { System.out.print("0"); } System.out.print(finmm); }<br />
					int finSS = mqMsg.putDateTime.get(Calendar.SECOND); if(verbose) { if (finSS < 10) { System.out.print("0"); } System.out.print(finSS); }<br />
					int finFF = mqMsg.putDateTime.get(Calendar.MILLISECOND); finFF = finFF/10; if(verbose) { if (finFF < 10) { System.out.print("0"); } System.out.print(finFF); }<br />
					if(verbose) { System.out.println(""); }</p>
<p>					if(verbose) { System.out.println(testID+"\t\t"+threadID+"\t\tMSG LENGTH\t\t: "+mqMsg.getMessageLength()+" bytes"); }</p>
<p>					msgText = mqMsg.readLine();</p>
<p>					int finMilli = (finHH*60*60*1000)+(finmm*60*1000)+(finSS*1000)+(finFF*10);<br />
					parseContent(msgText, finMilli);</p>
<p>				} catch (MQException ex) {<br />
					i--;<br />
					retryCount++;<br />
					//Attempt to catch the following errors:<br />
					if(ex.reasonCode==2009) {<br />
						// MQJE001: An MQException occurred: Completion Code 2, Reason 2009<br />
						// Connection to MQ has been lost, attempt to reconnect!<br />
						if(!nolog){ write(logfile, testID+"\t\t"+threadID+"\t\tError! GET Connection to MQ has been lost, attempting to reconnect ... \n"+ex+"\n"); }<br />
						try {<br />
							qMgr = new MQQueueManager(qmngr);<br />
							q = qMgr.accessQueue(getQ, openOptions);<br />
						}<br />
						catch (MQException exR) {<br />
							if(!nolog){ write(logfile, testID+"\t\t"+threadID+"\t\tError! GET Reconnect failed ... \n"+exR+"\n"); }<br />
						}<br />
					} else if(ex.reasonCode==2033) {<br />
						// MQJE001: An MQException occurred: Completion Code 2, Reason 2033: (No messages available)<br />
						// This can occur when 'get' message pacing is set too quick. In order to<br />
						// prevent latency in the load balancer's decision making it is necessary<br />
						// to set a fast transaction pacing for the get method. In the case such<br />
						// as this when the pacing exceeds the amount of messages available to get<br />
						// this catch clause will sleep for the desired amount of time in millisecs.<br />
						//if(!nolog){ write(logfile, testID+"\t\t"+threadID+"\t\tError! Nil messages on queue ... \n"+ex+"\n"); }</p>
<p>						// Sleep for the full adjusted pacing rather than adjPacing/conns<br />
						try { Thread.sleep( adjustedPacing );	} catch (InterruptedException ie) {}</p>
<p>					} else {<br />
						// Must have another type of MQ execption, so log it ...<br />
						if(!nolog){ write(logfile, testID+"\t\t"+threadID+"\t\tError! MQ Exception in GET msg ... \n"+ex+"\n"); }<br />
						throw new IOException(<br />
						testID+"\t\t"+threadID+"\t\tConnection to MQSeries is broken on putQ(qmngr/channel)@host:port\n"<br />
						+ putQ + "(" + qmngr + "/"<br />
						+ MQEnvironment.channel + ")@"<br />
						+ MQEnvironment.hostname + ":"<br />
						+ MQEnvironment.port);<br />
					}</p>
<p>					// Enforce retry count maximums when NOT in discovery mode ...<br />
					if(!discover) {<br />
						if(retryCount>retryMax) {<br />
							// Max retries hit<br />
							i = num;<br />
							if(!nolog){ write(logfile, testID+"\t\t"+threadID+"\t\tError! Max GET retry limit reached ... \n"+ex+"\n"); }<br />
						}<br />
					}</p>
<p>				} finally {<br />
					if(!discover) {if(!nolog){ write(logfile, testID+"\t\t"+threadID+"\t\tGet Msg: "+i+"/"+num+""); } }</p>
<p>					if(msgText != null) {<br />
						retryCount=0;<br />
					}</p>
<p>					// Force sleep for message pacing<br />
					if(discover) {<br />
						try { Thread.sleep( 10 );	} catch (InterruptedException ie) {}<br />
					} else {<br />
						try { Thread.sleep( (int)(adjustedPacing/conns) );	} catch (InterruptedException ie) {}<br />
					}<br />
				}<br />
			}</p>
<p>			if(verbose) { System.out.println(testID+"\t\t"+threadID+"\t\tCLOSING CONNECTION"); }<br />
			q.close();<br />
			qMgr.disconnect();<br />
			if(verbose) { System.out.print("\r"+testID+"\t\t"+threadID+"\t\tClosed : OK"); }<br />
			try { if(!nolog){ write(logfile, testID+"\t\t"+threadID+"\t\tClosed : OK"); } } catch (IOException ioe) {}<br />
		}<br />
		catch (Exception ex) {<br />
			try { if(!nolog){ write(logfile, testID+"\t\t"+threadID+"\t\tError! Generic error in GET method ... \n"+ex+"\n"); } } catch (IOException ioe) {}<br />
		}<br />
	}</p>
<p>	// WRITE TO LOG FILE METHOD<br />
	public static void write(String f, String s) throws IOException {<br />
		String nowUTC = formatDTG();<br />
		try {<br />
			FileWriter aWriter = new FileWriter(f, true);<br />
			aWriter.write(nowUTC.substring(0,4)+"-"+<br />
					nowUTC.substring(4,6)+"-"+<br />
					nowUTC.substring(6,8)+"\t"+<br />
					nowUTC.substring(8,10)+":"+<br />
					nowUTC.substring(10,12)+":"+<br />
					nowUTC.substring(12,14)+"."+<br />
					nowUTC.substring(14,16)+"\t"+<br />
					s + System.getProperty("line.separator"));<br />
			aWriter.flush();<br />
			aWriter.close();<br />
		} catch (IOException ioe) {<br />
			System.out.println("Error! Unable to write to log file ...");<br />
		}<br />
	}</p>
<p>	// FORMAT DATE TIME GROUP METHOD<br />
	private static String formatDTG() {<br />
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");<br />
		TimeZone utc = TimeZone.getTimeZone("UTC");<br />
		sdf.setTimeZone(utc);<br />
		String result = sdf.format( new Date() );<br />
		String DTG = result.substring(0,16);<br />
		return DTG;<br />
	}</p>
<p>	// READ INPUT FILE METHOD (LEGACY)<br />
	public String readFile(String file) throws IOException {<br />
		FileInputStream fis = new FileInputStream(file);<br />
		int x = fis.available();<br />
		byte b[] = new byte[x];<br />
		fis.read(b);<br />
		content = new String(b);<br />
		return content;<br />
	}</p>
<p>	// READ INPUT FILES METHOD<br />
	public String[] readFiles(String file) throws IOException {</p>
<p>		String directoryName = file;<br />
		File directory;<br />
		String directoryPath = "";<br />
		String[] files;</p>
<p>		files 		= new String[1];<br />
		contents 	= new String[1];</p>
<p>		directory = new File(directoryName);<br />
		if (directory.isDirectory() == false) {<br />
			if (directory.exists() == false){<br />
				//No such directory exists<br />
				System.out.println("Error! No such directory exists ...");<br />
			} else {<br />
				//File is not a directory so treat it as a single file!<br />
				try<br />
				{<br />
					FileInputStream fis = new FileInputStream(file);<br />
					int x = fis.available();<br />
					byte b[] = new byte[x];<br />
					fis.read(b);<br />
					contents[0] = new String(b);<br />
					return contents;<br />
				} catch (Exception ex) {<br />
					System.out.println("Error! When reading contents of single file ... "+ex);<br />
				}<br />
			}<br />
		} else {</p>
<p>			files = directory.list();<br />
			contents = directory.list();</p>
<p>			directoryPath = directory.getPath();</p>
<p>		}</p>
<p>		for (int i=0; i < files.length; i++)<br />
		{<br />
			// Write contents of files to contents array<br />
			try<br />
			{<br />
				FileInputStream fis = new FileInputStream(directoryPath+"/"+files[i]);<br />
				int x = fis.available();<br />
				byte b[] = new byte[x];<br />
				fis.read(b);<br />
				contents[i] = new String(b);<br />
			} catch (Exception ex) {<br />
				System.out.println("Error! When reading contents of multiple files ... "+ex);<br />
			}</p>
<p>		}</p>
<p>		return contents;<br />
	}</p>
<p>	// MODIFY CONTENT OF INPUT FILE METHOD<br />
	public String modifyContent(String content) {<br />
		mqMessage = content;</p>
<p>		if(verbose) { System.out.println("LENGTH BYTES\t\t: "+content.length()); }<br />
		String newDTG = formatDTG();</p>
<p>		// Modify Header Detail: Message Date and Message Time<br />
		String oldDTG = content.substring(0,16);<br />
		if(verbose) { System.out.println("OLD DTG\t\t\t: "+oldDTG); }<br />
		if(verbose) { System.out.println("NEW DTG\t\t\t: "+newDTG); }<br />
		mqMessage = mqMessage.replaceAll(oldDTG, newDTG);</p>
<p>		// Modify Header Detail: CustomerID<br />
		String oldCustID = content.substring(131,158);<br />
		String newCustID = "0000000000"+newDTG;<br />
		oldCustID = oldCustID.substring(0,26); //trim to exact length<br />
		newCustID = newCustID.substring(0,26); //trim to exact length<br />
		if(verbose) { System.out.println("OLD CUST ID\t\t: "+oldCustID); }<br />
		if(verbose) { System.out.println("NEW CUST ID\t\t: "+newCustID); }<br />
		mqMessage = mqMessage.replaceAll(oldCustID, newCustID);</p>
<p>		// Modify Control Area Detail: Current Run Date<br />
		String oldRunDG = content.substring(43,52);<br />
		oldRunDG = oldRunDG.substring(0,8); //trim to exact length<br />
		if(verbose) { System.out.println("OLD RUN DG\t\t: "+oldRunDG); }<br />
		if(verbose) { System.out.println("NEW RUN DG\t\t: "+newDTG.substring(0,8)); }<br />
		mqMessage = mqMessage.replaceAll(oldRunDG, newDTG.substring(0,8));</p>
<p>		return mqMessage;<br />
	}</p>
<p>	// PARSE CONTENTS METHOD<br />
	private void parseContent(String text, int milliseconds) {</p>
<p>		String msgText 	= text;<br />
		int finMilli 	= milliseconds;<br />
		String custID 	= msgText.substring(11,37);<br />
		if(getQ==putQ){	custID = msgText.substring(131,158); }//FOR TESTING MQ PUT/GET FROM SAME QUEUE<br />
		String origDTG 	= custID.substring(10,26);<br />
		String origPutDate = origDTG.substring(0,8);<br />
		int origHH 	= Integer.parseInt(origDTG.substring(8,10));<br />
		int origmm 	= Integer.parseInt(origDTG.substring(10,12));<br />
		int origSS 	= Integer.parseInt(origDTG.substring(12,14));<br />
		int origFF 	= Integer.parseInt(origDTG.substring(14,16));</p>
<p>		if(verbose) { System.out.println("CUST ID\t\t\t: "+custID); }<br />
		if(verbose) { System.out.println("ORGIG DTG\t\t: "+origDTG); }<br />
		if(verbose) { System.out.println("ORIG HH:\t\t: " + origHH); }<br />
		if(verbose) { System.out.println("ORIG mm:\t\t: " + origmm); }<br />
		if(verbose) { System.out.println("ORIG SS:\t\t: " + origSS); }<br />
		if(verbose) { System.out.println("ORIG FF:\t\t: " + origFF); }</p>
<p>		int origMilli = (origHH*60*60*1000)+(origmm*60*1000)+(origSS*1000)+(origFF*10);<br />
		int responseTime = finMilli - origMilli;<br />
		if(responseTime<10) { responseTime=10; } //Can't measure below 10 milliseconds ...</p>
<p>		// Throughput calculation<br />
		thruput = 1.00/pacing*1000*conns;</p>
<p>		try {<br />
			// Resize responstime and throughput arrays<br />
			if (parseCounter == responseTimeArray.length) {<br />
				int newSize = parseCounter + 10;<br />
				int[] tempResponseTimeArray 	= new int[newSize];<br />
				double[] tempThroughputArray 	= new double[newSize];</p>
<p>				System.arraycopy(responseTimeArray,0,tempResponseTimeArray,0,responseTimeArray.length);<br />
				System.arraycopy(throughputArray,0,tempThroughputArray,0,throughputArray.length);</p>
<p>				responseTimeArray 	= tempResponseTimeArray;<br />
				throughputArray 	= tempThroughputArray;<br />
			}<br />
			responseTimeArray[parseCounter] = responseTime;<br />
			throughputArray[parseCounter] 	= thruput;<br />
		} catch (Exception ex) {<br />
			System.out.println("Error! When resizing response time &#038; throughput arrays ...");<br />
		}<br />
		parseCounter++;</p>
<p>		if(verbose) {<br />
			System.out.println("DIFF MILLI\t\t: " + responseTime);<br />
		} else {<br />
			// MULTI THREAD MODE<br />
			String tempLine = "\t"+origPutDate+"\t";<br />
			if (origHH < 10) { tempLine = tempLine+"0"; } tempLine = tempLine+origHH+":";<br />
			if (origmm < 10) { tempLine = tempLine+"0"; } tempLine = tempLine+origmm+":";<br />
			if (origSS < 10) { tempLine = tempLine+"0"; } tempLine = tempLine+origSS+"\t";<br />
			tempLine = tempLine+conns+"\t"+pacing+"\t"+load+"\t"+persistence+"\t"+responseTime+"\t"+testID;<br />
			if(!quiet) { System.out.println(tempLine); }</p>
<p>			// ADJUST PACING BASED ON LAST RESPONSE TIME<br />
			int lastResponseTime = responseTime;<br />
			int thisPacing = pacing - lastResponseTime;<br />
			if(thisPacing<0) { adjustedPacing=10; } else { adjustedPacing=thisPacing; }<br />
			if(verbose) { System.out.println("ADJUSTED PACING: "+thisPacing+" " +lastResponseTime+" "+adjustedPacing); }</p>
<p>			// OPTIONAL DISCOVER MODE<br />
			if(discover) {</p>
<p>				int mod = parseCounter % conns;<br />
				if(responseTime==0) {<br />
					// No message retrieved.<br />
				}<br />
				else {</p>
<p>					// LOAD BALANCER CALCULATIONS FOR DISCOVER MODE<br />
					// Pacing mods based on response time<br />
					double diff 	= (double)sla - (double)responseTime;<br />
					double fract 	= diff/1000;<br />
					double inv	= 1.00 - fract;<br />
					double fractSq	= fract * fract;<br />
					double factor 	= (sla/100) * (sla/100);</p>
<p>					if(diff<0){<br />
						pacing = (int)( (fractSq * inv * 100) + factor);<br />
					} else {<br />
						pacing = (int)( (1-(fractSq * 100))+ factor);<br />
					}</p>
<p>					// Display thinned results by modulus of number of conns<br />
					if(mod==0)<br />
					{<br />
						tempLine = tempLine+"\t"+pacing+"\t"+fmt.format(thruput);<br />
						System.out.println(tempLine);<br />
					}<br />
				}<br />
			}<br />
		}<br />
	}</p>
<p>	// FORMAT PADDING METHOD<br />
	private static String padCalc(double pad) {<br />
		String padding="";<br />
		if(pad<10) padding="     ";<br />
		else if(pad<100) padding="    ";<br />
		else if(pad<1000) padding="   ";<br />
		else if(pad<10000) padding="  ";<br />
		else if(pad<100000) padding=" ";<br />
		else padding="";<br />
		return padding;<br />
	}</p>
<p>	// STATISTICS METHOD<br />
	private static void collectStats() {</p>
<p>		System.out.println("\nDESCRIPTIVE STATISTICS "+testID);<br />
		System.out.println("--------------------------------------------------------------------------\n");<br />
		System.out.println("\t\t\t\tRESPONSE TIME\t\tTHROUGHPUT");<br />
		System.out.println("\t\t\t\t(millisecs)   \t\t(transactions/sec)");</p>
<p>		try {<br />
			Arrays.sort(responseTimeArray);<br />
			Arrays.sort(throughputArray);<br />
			String padding;<br />
			double pad;<br />
			String tempLine;</p>
<p>			// MEDIANS<br />
			double rtMedian;<br />
			int rtMiddle = responseTimeArray.length/2;<br />
			if (responseTimeArray.length%2 == 1) {<br />
				// Odd number of elements<br />
				rtMedian = responseTimeArray[rtMiddle];<br />
			} else {<br />
				// Even number of elements<br />
				rtMedian = (responseTimeArray[rtMiddle-1] + responseTimeArray[rtMiddle]) / 2.0;<br />
			}</p>
<p>			double tpMedian;<br />
			int tpMiddle = throughputArray.length/2;<br />
			if (throughputArray.length%2 == 1) {<br />
				// Odd number of elements<br />
				tpMedian = throughputArray[tpMiddle];<br />
			} else {<br />
				// Even number of elements<br />
				tpMedian = (throughputArray[tpMiddle-1] + throughputArray[tpMiddle]) / 2.0;<br />
			}</p>
<p>			padding=padCalc(rtMedian);<br />
			System.out.println("\tMEDIAN\t\t:\t"+fmt.format(rtMedian)+padding+"\t\t"+fmt.format(tpMedian));</p>
<p>			// LOWER QUARTILES<br />
			double rtLowerQuartile;<br />
			int rtLower = (int)(responseTimeArray.length/(1/0.25));<br />
			rtLowerQuartile = responseTimeArray[rtLower];</p>
<p>			double tpLowerQuartile;<br />
			int tpLower = (int)(throughputArray.length/(1/0.25));<br />
			tpLowerQuartile = throughputArray[tpLower];</p>
<p>			padding=padCalc(rtLowerQuartile);<br />
			System.out.println("\tLOWER QUARTILE\t:\t"+fmt.format(rtLowerQuartile)+padding+"\t\t"+fmt.format(tpLowerQuartile));</p>
<p>			// UPPER QUARTILES<br />
			double rtUpperQuartile;<br />
			int rtUpper = (int)(responseTimeArray.length/(1/0.75));<br />
			rtUpperQuartile = responseTimeArray[rtUpper];</p>
<p>			double tpUpperQuartile;<br />
			int tpUpper = (int)(throughputArray.length/(1/0.75));<br />
			tpUpperQuartile = throughputArray[tpUpper];</p>
<p>			padding=padCalc(rtUpperQuartile);<br />
			System.out.println("\tUPPER QUARTILE\t:\t"+fmt.format(rtUpperQuartile)+padding+"\t\t"+fmt.format(tpUpperQuartile));</p>
<p>			// 95th PERCENTILES<br />
			double rt95thPercentile;<br />
			int rtPercentile95 = (int)(responseTimeArray.length/(1/0.95));<br />
			rt95thPercentile = responseTimeArray[rtPercentile95];</p>
<p>			double tp95thPercentile;<br />
			int tpPercentile95 = (int)(throughputArray.length/(1/0.95));<br />
			tp95thPercentile = throughputArray[tpPercentile95];</p>
<p>			padding=padCalc(rt95thPercentile);<br />
			System.out.println("\t95th PERCENTILE\t:\t"+fmt.format(rt95thPercentile)+padding+"\t\t"+fmt.format(tp95thPercentile));</p>
<p>			// MININUMS<br />
			double rtMinimum = responseTimeArray[0];<br />
			double tpMinimum = throughputArray[0];</p>
<p>			padding=padCalc(rtMinimum);<br />
			System.out.println("\tMINIMUM\t\t:\t"+fmt.format(rtMinimum)+padding+"\t\t"+fmt.format(tpMinimum));</p>
<p>			// MAXIMUMS<br />
			double rtMaximum = responseTimeArray[responseTimeArray.length-1];<br />
			double tpMaximum = throughputArray[throughputArray.length-1];</p>
<p>			padding=padCalc(rtMaximum);<br />
			System.out.println("\tMAXIMUM\t\t:\t"+fmt.format(rtMaximum)+padding+"\t\t"+fmt.format(tpMaximum));</p>
<p>			// RANGES<br />
			double rtRange = rtMaximum-rtMinimum;<br />
			double tpRange = tpMaximum-tpMinimum;</p>
<p>			padding=padCalc(rtRange);<br />
			System.out.println("\tRANGE\t\t:\t"+fmt.format(rtRange)+padding+"\t\t"+fmt.format(tpRange));</p>
<p>			// INTER QUARTILE RANGES<br />
			double rtIQR = rtUpperQuartile-rtLowerQuartile;<br />
			double tpIQR = tpUpperQuartile-tpLowerQuartile;</p>
<p>			padding=padCalc(rtIQR);<br />
			System.out.println("\tIQR\t\t:\t"+fmt.format(rtIQR)+padding+"\t\t"+fmt.format(tpIQR));</p>
<p>			// N COUNTS<br />
			double rtCount = responseTimeArray.length;<br />
			double tpCount = throughputArray.length;</p>
<p>			padding=padCalc(rtCount);<br />
			System.out.println("\tCOUNT\t\t:\t"+fmt.format(rtCount)+padding+"\t\t"+fmt.format(tpCount));</p>
<p>			// MEANS<br />
			double rtMean;<br />
			double sum = 0;<br />
			double squareSum = 0;<br />
			for (int i=0; i<responseTimeArray.length; i++) {<br />
				sum += responseTimeArray[i];<br />
				squareSum += responseTimeArray[i]*responseTimeArray[i];<br />
			}<br />
			rtMean = sum / responseTimeArray.length;</p>
<p>			double tpMean;<br />
			double tpSum = 0;<br />
			double tpSuareSum = 0;<br />
			for (int i=0; i
<throughputArray.length; i++) {<br />
				tpSum += throughputArray[i];<br />
				tpSuareSum += throughputArray[i]*throughputArray[i];<br />
			}<br />
			tpMean = tpSum / throughputArray.length;</p>
<p>			padding=padCalc(rtMean);<br />
			System.out.println("\tMEAN\t\t:\t"+fmt.format(rtMean)+padding+"\t\t"+fmt.format(tpMean));</p>
<p>			// STANDARD DEVIATIONS<br />
			double rtStdDev = Math.sqrt( squareSum/rtCount - rtMean*rtMean );<br />
			double tpStdDev = Math.sqrt( tpSuareSum/tpCount - tpMean*tpMean );</p>
<p>			padding=padCalc(rtStdDev);<br />
			System.out.println("\tSTD DEV\t\t:\t"+fmt.format(rtStdDev)+padding+"\t\t"+fmt.format(tpStdDev));</p>
<p>		} catch (Exception ex) {<br />
			System.out.println("Error! Unable to calculate statistics ... ");<br />
		}<br />
		System.out.println("\n--------------------------------------------------------------------------\n");<br />
	}</p>
<p>	// DUMP HEX METHOD<br />
	public String dumpHexId(byte[] myId) {<br />
		HEX = "";<br />
		for (int i=0; i < myId.length;i++) {<br />
			char b = (char)(myId[i] &#038; 0xFF);<br />
			if (b < 0x10) {<br />
				HEX = HEX + "0";<br />
			}<br />
			HEX = HEX + (String)(Integer.toHexString(b)).toUpperCase();<br />
		}<br />
		return HEX;<br />
	}<br />
}</p>
<p></code></p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/blogs/2007/a-custom-load-harness-for-mq-server/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

