<?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; MQ</title>
	<atom:link href="http://altentee.com/blogs/tag/mq/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>Performance Testing MQ with LoadRunner</title>
		<link>http://altentee.com/blogs/2008/performance-testing-mq-with-loadrunner/</link>
		<comments>http://altentee.com/blogs/2008/performance-testing-mq-with-loadrunner/#comments</comments>
		<pubDate>Tue, 21 Oct 2008 06:04:50 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[Altentee]]></category>
		<category><![CDATA[loadrunner]]></category>
		<category><![CDATA[MQ]]></category>

		<guid isPermaLink="false">http://90kts.com/blog/2008/performance-testing-mq-with-loadrunner/</guid>
		<description><![CDATA[The wheel has turned full circle and I&#8217;m back in MQ land&#8230; So here is a a simple Java vuser harness which you can use in LoadRunner to put or get messages from Websphere MQ. This version doesn&#8217;t require any JNDI bindings (or access to JMS). Instead it just uses a standard server connection channel [...]]]></description>
			<content:encoded><![CDATA[<p>The wheel has turned full circle and I&#8217;m back in MQ land&#8230; So here is a a simple Java vuser harness which you can use in LoadRunner to put or get messages from Websphere MQ. This version doesn&#8217;t require any JNDI bindings (or access to JMS). Instead it just uses a standard server connection channel over TCP to get and put messages.</p>
<p>You will need to get the following jars from your Websphere MQ installation:<br />
1. com.ibm.mq.jar<br />
2. connector.jar<br />
3. jta.jar</p>
<p>Make sure you include them in your run-time settings (F4) for your script:<br />
<a href='http://90kts.com/blog/wp-content/uploads/2008/10/runtim-java-mq.png' title='Runtime settings Java vuser MQ'><img src='http://90kts.com/blog/wp-content/uploads/2008/10/runtim-java-mq.png' alt='Runtime settings Java vuser MQ' /></a><br />
<span id="more-207"></span></p>
<p><strong>PUT example</strong></p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">/*
 * LoadRunner Java script. (Build: 946)
 *
 * Script Description: simple test harness to PUT messages on a MQ queue
 * Author: Tim.Koopmans@90kts.com
 */</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">lrapi.lr</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.*</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.*</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.ibm.mq.*</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> Actions
<span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> MQQueueManager myQueueManager<span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">private</span> MQPutMessageOptions myPutMsgOptions<span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">private</span> MQQueue myQueue<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">int</span> init<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Throwable</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
	    MQEnvironment.<span style="color: #006633;">hostname</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;192.168.145.131&quot;</span><span style="color: #339933;">;</span>
	    MQEnvironment.<span style="color: #006633;">properties</span>.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span>MQC.<span style="color: #006633;">TRANSPORT_PROPERTY</span>,MQC.<span style="color: #006633;">TRANSPORT_MQSERIES_CLIENT</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    MQEnvironment.<span style="color: #006633;">channel</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;S_koops_5a7610a22&quot;</span><span style="color: #339933;">;</span>
	    MQEnvironment.<span style="color: #006633;">port</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1414</span><span style="color: #339933;">;</span>
	    MQEnvironment.<span style="color: #006633;">CCSID</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">437</span><span style="color: #339933;">;</span>
&nbsp;
	    myQueueManager <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> MQQueueManager<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;QM_koops_5a7610a22&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    <span style="color: #000066; font-weight: bold;">int</span> openOptions <span style="color: #339933;">=</span> MQC.<span style="color: #006633;">MQOO_OUTPUT</span>
			    <span style="color: #339933;">|</span> MQC.<span style="color: #006633;">MQOO_INQUIRE</span>
			    <span style="color: #339933;">|</span> MQC.<span style="color: #006633;">MQOO_FAIL_IF_QUIESCING</span><span style="color: #339933;">;</span>
&nbsp;
	    myQueue <span style="color: #339933;">=</span> myQueueManager.<span style="color: #006633;">accessQueue</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;default&quot;</span>, openOptions, <span style="color: #000066; font-weight: bold;">null</span>, <span style="color: #000066; font-weight: bold;">null</span>, <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	    myPutMsgOptions <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> MQPutMessageOptions<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    myPutMsgOptions.<span style="color: #006633;">options</span> <span style="color: #339933;">=</span> MQC.<span style="color: #006633;">MQPMO_NONE</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">Exception</span> e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    <span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000000; font-weight: bold;">return</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #666666; font-style: italic;">//end of init</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">int</span> action<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Throwable</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
	    MQMessage myPutMessage <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> MQMessage<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    myPutMessage.<span style="color: #006633;">clearMessage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    myPutMessage.<span style="color: #006633;">persistence</span> <span style="color: #339933;">=</span> MQC.<span style="color: #006633;">MQPER_PERSISTENT</span><span style="color: #339933;">;</span>
	    <span style="color: #666666; font-style: italic;">//myPutMessage.persistence = MQC.MQPER_NOT_PERSISTENT;</span>
	    myPutMessage.<span style="color: #006633;">correlationId</span> 	<span style="color: #339933;">=</span> MQC.<span style="color: #006633;">MQCI_NONE</span><span style="color: #339933;">;</span>
	    myPutMessage.<span style="color: #006633;">messageId</span> 	<span style="color: #339933;">=</span> MQC.<span style="color: #006633;">MQMI_NONE</span><span style="color: #339933;">;</span>
	    myPutMessage.<span style="color: #006633;">writeString</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;&lt;xml&gt;&lt;data&gt;foobar&lt;/data&gt;&lt;/xml&gt;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    myQueue.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span>myPutMessage, myPutMsgOptions<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span>MQException e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    <span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000000; font-weight: bold;">return</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #666666; font-style: italic;">//end of action</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">int</span> end<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Throwable</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
	     myQueue.<span style="color: #006633;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	     myQueueManager.<span style="color: #006633;">disconnect</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">Exception</span> e <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    <span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000000; font-weight: bold;">return</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #666666; font-style: italic;">//end of end</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p><strong>GET example</strong><br />
I&#8217;ve included a private method which decodes the hex string (for the msgID) into ascii. You can also get creative here. In previous test efforts I&#8217;ve embedded a date time string in the user data of the request message, then extracted and got the difference from the MQMD header on the reply queue. In other words, elapsed time between request and response. I&#8217;m keeping it simple for the example though &#8230; <img src='http://altentee.com/blogs/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">/*
 * LoadRunner Java script. (Build: 946)
 *
 * Script Description: simple test harness to GET messages on a MQ queue
 * Author: Tim.Koopmans@90kts.com
 */</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">lrapi.lr</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.*</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.*</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.ibm.mq.*</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> Actions
<span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> MQQueueManager myQueueManager<span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">private</span> MQPutMessageOptions myPutMsgOptions<span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">private</span> MQQueue myQueue<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">int</span> init<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Throwable</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
	    MQEnvironment.<span style="color: #006633;">hostname</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;192.168.145.131&quot;</span><span style="color: #339933;">;</span>
	    MQEnvironment.<span style="color: #006633;">properties</span>.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span>MQC.<span style="color: #006633;">TRANSPORT_PROPERTY</span>,MQC.<span style="color: #006633;">TRANSPORT_MQSERIES_CLIENT</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    MQEnvironment.<span style="color: #006633;">channel</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;S_koops_5a7610a22&quot;</span><span style="color: #339933;">;</span>
	    MQEnvironment.<span style="color: #006633;">port</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1414</span><span style="color: #339933;">;</span>
	    MQEnvironment.<span style="color: #006633;">CCSID</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">437</span><span style="color: #339933;">;</span>
&nbsp;
	    myQueueManager <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> MQQueueManager<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;QM_koops_5a7610a22&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    <span style="color: #000066; font-weight: bold;">int</span> openOptions <span style="color: #339933;">=</span> MQC.<span style="color: #006633;">MQOO_INPUT_SHARED</span>
                            <span style="color: #339933;">|</span> MQC.<span style="color: #006633;">MQOO_INQUIRE</span>
                            <span style="color: #339933;">|</span> MQC.<span style="color: #006633;">MQOO_FAIL_IF_QUIESCING</span><span style="color: #339933;">;</span>
&nbsp;
	    myQueue <span style="color: #339933;">=</span> myQueueManager.<span style="color: #006633;">accessQueue</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;default&quot;</span>, openOptions<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">Exception</span> e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    <span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000000; font-weight: bold;">return</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #666666; font-style: italic;">//end of init</span>
&nbsp;
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">int</span> action<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Throwable</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
	    MQMessage myGetMessage <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> MQMessage<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            myQueue.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>myGetMessage<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;MSG ID: <span style="color: #000099; font-weight: bold;">\t</span>&quot;</span><span style="color: #339933;">+</span>dumpHexId<span style="color: #009900;">&#40;</span>myGetMessage.<span style="color: #006633;">messageId</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;CORREL ID: <span style="color: #000099; font-weight: bold;">\t</span>&quot;</span><span style="color: #339933;">+</span>dumpHexId<span style="color: #009900;">&#40;</span>myGetMessage.<span style="color: #006633;">correlationId</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;MSG LENGTH:<span style="color: #000099; font-weight: bold;">\t</span>&quot;</span><span style="color: #339933;">+</span>myGetMessage.<span style="color: #006633;">getMessageLength</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #0000ff;">&quot; bytes&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;MSG CONTENT: &quot;</span><span style="color: #339933;">+</span>myGetMessage.<span style="color: #006633;">readLine</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span>MQException e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    <span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000000; font-weight: bold;">return</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #666666; font-style: italic;">//end of action</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">int</span> end<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Throwable</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
	     myQueue.<span style="color: #006633;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	     myQueueManager.<span style="color: #006633;">disconnect</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">Exception</span> e <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    <span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000000; font-weight: bold;">return</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #666666; font-style: italic;">//end of end</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #003399;">String</span> dumpHexId<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">byte</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> myId<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #003399;">String</span> hexAscii <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #339933;">;</span>
	<span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> i<span style="color: #339933;">=</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> myId.<span style="color: #006633;">length</span><span style="color: #339933;">;</span>i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    <span style="color: #000066; font-weight: bold;">char</span> b <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">char</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span>myId<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span> <span style="color: #339933;">&amp;</span> 0xFF<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>b <span style="color: #339933;">&lt;</span> 0x10<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		hexAscii <span style="color: #339933;">=</span> hexAscii <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot;0&quot;</span><span style="color: #339933;">;</span>
	    <span style="color: #009900;">&#125;</span>
	    hexAscii <span style="color: #339933;">=</span> hexAscii <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #003399;">Integer</span>.<span style="color: #006633;">toHexString</span><span style="color: #009900;">&#40;</span>b<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">toUpperCase</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000000; font-weight: bold;">return</span> hexAscii<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #666666; font-style: italic;">//end of dumpHexId</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://altentee.com/blogs/2008/performance-testing-mq-with-loadrunner/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Performance Testing MQ with JMeter</title>
		<link>http://altentee.com/blogs/2008/performance-testing-mq-with-jmeter/</link>
		<comments>http://altentee.com/blogs/2008/performance-testing-mq-with-jmeter/#comments</comments>
		<pubDate>Fri, 03 Oct 2008 05:45:58 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[Altentee]]></category>
		<category><![CDATA[jmeter]]></category>
		<category><![CDATA[MQ]]></category>

		<guid isPermaLink="false">http://90kts.com/blog/2008/performance-testing-mq-with-jmeter/</guid>
		<description><![CDATA[This is a relatively new example of how to use JMeter with WebSphere MQ. This approach is a clever way of inserting messages into MQ using a JMS sampler (point to point) with a JNDI binding within MQ. I had not heard of this approach before and am sure it will be useful in future, [...]]]></description>
			<content:encoded><![CDATA[<p>This is a relatively new example of how to use <a href="http://www.ibm.com/developerworks/websphere/library/techarticles/0808_vandekuil/0808_vandekuil.html"><strong>JMeter with WebSphere MQ</strong></a>. This approach is a clever way of inserting messages into MQ using a JMS sampler (point to point) with a JNDI binding within MQ.</p>
<p>I had not heard of this approach before and am sure it will be useful in future, provided you have sufficient access to create the bindings in the first place.</p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/blogs/2008/performance-testing-mq-with-jmeter/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Understanding the effect of MQ persistence on disk performance</title>
		<link>http://altentee.com/blogs/2007/understanding-mq-persistence-on-disk-performance/</link>
		<comments>http://altentee.com/blogs/2007/understanding-mq-persistence-on-disk-performance/#comments</comments>
		<pubDate>Fri, 28 Sep 2007 12:28:44 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[Altentee]]></category>
		<category><![CDATA[MQ]]></category>
		<category><![CDATA[theory]]></category>

		<guid isPermaLink="false">http://90kts.com/blog/2007/understanding-mq-persistence-on-disk-performance/</guid>
		<description><![CDATA[Recently I have been trying to determine what the impact of using MQ message persistence is on disk subsystem performance. There is alot of literature from IBM recommending ideal configurations to support MQ persistence, so I won&#8217;t turn this into a post that recommends ideal settings. What I did want to achieve though, was to [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I have been trying to determine what the impact of using MQ message persistence is on disk subsystem performance. There is alot of literature from IBM recommending ideal configurations to support MQ persistence, so I won&#8217;t turn this into a post that recommends ideal settings. What I did want to achieve though, was to get a better understanding of how MQ interacts with the disk subsystem when using message persistence, so that I could plan for capacity and make better recommendations for tuning on a production SAN environment.</p>
<p><span id="more-289"></span><br />
The first behaviour I wanted to describe, was whether the use of MQ persistence creates random or sequential disk activity, on the assumption that random disk access to block locations on the disk would incur a greater time penalty than sequential access.</p>
<p>In order to setup a test environment, I installed MQ version 6 on winXP platform using the default settings. This test was setup using a custom java load harness to put/get messages from a default queue which had persistence enabled with DEFPSIST(YES). File and disk statistics were collected on a Win32 platform using filemon and diskmon respectively.</p>
<p>The following graphs depict the block size written over time (x axis) relative to the sector position (y axis) of the disk drive being monitored. I was trying to achieve a similar effect to the Solaris internals <a href="http://www.solarisinternals.com/si/tools/taz/">TAZ</a> disk trace utility, albeit in a Windows environment. File stats such as number and size of write operations were collected using filemon. Transaction throughput was measured by dividing the total amount of transactions (1,000) by the total processing time. A number of different configurations were tested, but I chose to present a common setup which uses circular logging with single write, and a file page size of 16,384 x 4KB = 64MB per primary log file. The two variations I have presented are writes (MQPUT) only as well as writes (MQPUT) and reads (MQGET) concurrently. The latter being a more familiar situation for me in the workplace.<br />
<a href='http://90kts.com/blog/wp-content/uploads/2007/09/picture-2.png' title='Scenario 1 MQ Mersistence'><img src='http://90kts.com/blog/wp-content/uploads/2007/09/picture-2.png' alt='Scenario 1 MQ Mersistence' /></a><br />
<a href='http://90kts.com/blog/wp-content/uploads/2007/09/picture-3.png' title='Scenario 2 MQ Mersistence'><img src='http://90kts.com/blog/wp-content/uploads/2007/09/picture-3.png' alt='Scenario 2 MQ Mersistence' /></a></p>
<p>It can be determined from the previous test results that MQ accesses the disk in a sequential behaviour. On windows, depending on the concurrent load, it will tend to allocate 16 &#8211; 32 x 512B blocks ranging from 8 &#8211; 16KB in size, although smaller less frequent writes will favour smaller 8 x 512B blocks 4KB in size. As a result, a high number of disk write IOs are observed.</p>
<p>The environment used to test was virtual (parallels), so limited disk cacacity was available, however the change in amplitude for trans/sec is considered relative. As a result, over an 80% reduction in throughput was observed when reading (MQGET) and writing (MQPUT) to the same queue. This will have significant impact on disk subsystem performance in a production environment.</p>
<p>I was unable to perform this test on a Solaris environment due to lack of privileged access, so would be keen to see what the results are there. I believe Solaris uses the same 512B block size, so am expecting similar results. Although analysing an MQ server&#8217;s impact on disk performance using sar, produces the following information:<br />
<code>sar -d 1 10 | egrep 'md72'<br />
           md72             60     0.7    1867   16749     0.0     0.4<br />
           md72             58     0.6    1955   17272     0.0     0.3<br />
           md72             52     0.6    1768   15619     0.0     0.3<br />
           md72             52     0.6    1764   15577     0.0     0.3<br />
           md72             54     0.6    1817   16045     0.0     0.3<br />
           md72             56     0.6    1861   16447     0.0     0.3</code><br />
From that information I can then infer that the total reads + writes/sec (r+w/s) divided by the number of 512B blocks per second (blk/s) would give me an average size of around 8-9KB/sec being written to the filesystem, which correlates my assumptions on block/file sizes. Using sar and other tools like iostat though is thought to be fraught with danger, especially when monitoring a rather complex SAN subsystem; but without access to any other tools, I&#8217;m stuck with the basics. To date I&#8217;ve been relying on perceived throughput (Mr+Mw/s) reported by iostat -xM</p>
<p>Worth noting, is that when MQ performs an MQGET on a persistent queue, it also causes a write IO to update the active log file, so the number of total write IOs effectively doubles.</p>
<p>Out of all this I&#8217;m working on the following assumptions:<br />
1. MQ uses sequential disk access for persistence logging.<br />
2. The OS is typically allocating between 16 &#8211; 32 x 512B blocks ranging between 8 &#8211; 16KB in size.<br />
3. MQGETs are a contributor to overall writes (I&#8217;m assuming o remove the transactions from the log files)<br />
4. Transaction throughput is significantly reduced when an application is reading (MQGET) and writing (MQPUT) to the same queue.</p>
<p>Attached below is a copy of the qm.ini I am working with, which is based on recommended performance tuning considerations from IBM<br />
<code>#*******************************************************************#<br />
#* Module Name: qm.ini                                             *#<br />
#*******************************************************************#<br />
#ExitPath:<br />
   ExitsDefaultPath=/var/mqm/exits/<br />
   ExitsDefaultPath64=/var/mqm/exits64/<br />
#Log:<br />
   LogPrimaryFiles=15<br />
   LogSecondaryFiles=15<br />
   LogFilePages=16384<br />
   LogType=CIRCULAR<br />
   LogBufferPages=512<br />
   LogPath=/var/mqm/log/QUEUEMANGERNAME/<br />
   LogWriteIntegrity=SingleWrite<br />
#Service:<br />
   Name=AuthorizationService<br />
   EntryPoints=13<br />
#ServiceComponent:<br />
   Service=AuthorizationService<br />
   Name=MQSeries.UNIX.auth.service<br />
   Module=/opt/mqm/lib64/amqzfu<br />
   ComponentDataSize=0<br />
#Channels:<br />
   MaxChannels=400<br />
   MaxActiveChannels=400<br />
#TCP:<br />
   KeepAlive=Yes<br />
#TuningParameters:<br />
   DefaultQBufferSize=1048576<br />
   DefaultPQBufferSize=1048576</code></p>
<p>LogFilePages is set to the maximum 16384 x 4KB making each S0000[n].log file about 64MB in size. You must set this parameter as part of your Queue Manager creation i.e. crtmqm -lf 16384 Hopefully that decreases the frequency MQ needs to loop around the ring of log files. LogPrimaryFiles and LogSecondary files are set to 15, and I haven&#8217;t run out of space in my circular log files yet. It is worth reading up on the MQ system administration manual for this, in terms of planning how much space you need. As a planning figure I add the size of MQPUT messages with DEFPSIST + 750B overhead as IBM state, then multiply that amount by my expected throughput. Checkpoint behaviour as part of circular logging activity should hopefully release space as it checkpoints (once every 10,000 transactions I believe), so if you plan properly, you shouldn&#8217;t hit the tail end of your ring too soon <img src='http://altentee.com/blogs/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>The DefaultQBufferSize is 64KB which I increased to 1MB (1048576). Apparently this increases the size of the buffer before writing to the file system, but I haven&#8217;t seen the evidence of that with the tools I&#8217;m using to monitor disk writes. This area is a little cloudy for me.</p>
<p>I have also modified the LogBufferPages to 512 x 4KB giving me a 2MB buffer for similar reasons.</p>
<p>And finally, I&#8217;ve been using a combination of either MQ, a custom perl script, or <a href="ftp://ftp.emc.com/pub/elab/iorate/">EMC iorate</a> to benchmark message persistence on different mounts/filesystems etc which has been useful. Especially when you don&#8217;t have one or the other available, and you need to determine if the space you&#8217;ve been allocated is up to the task of supporting MQ persistence.</p>
<p>In order to truss the process on a Solaris 9 environment, we first had to establish which pid was writing to the log mount. Our sysadmin was able to do this for me with the following:<br />
<code><br />
# fuser -cu /var/mqm/log<br />
/var/mqm/log:    27306c(root)   27197c(root)   19735o(sr123456)<br />
</code><br />
In this case the sr user was the account under which mqm was running, so we were then able to determine the corresponding process name:<br />
<code><br />
# top -s sr123456<br />
2756  sr123456   11  59    0    0K    0K sleep 313:05 12.08% amqzlaa0_nd<br />
20162 sr123456   10  59    0    0K    0K cpu45 406:47  9.49% amqrmppa<br />
19735 sr123456    6  59    0    0K    0K sleep 718:45  3.47% amqzmuc0<br />
19742 sr123456   14  59    0    0K    0K sleep  22:22  0.00% amqzlaa0_nd<br />
19744 sr123456    1  59    0    0K    0K sleep   1:36  0.00% amqpcsea<br />
19752 sr123456    3  59    0    0K    0K sleep   0:16  0.00% runmqlsr_nd<br />
19734 sr123456    2  59    0    0K    0K sleep   0:10  0.00% amqzfuma<br />
19733 sr123456   14  59    0    0K    0K sleep   0:06  0.00% amqzxma0_nd<br />
19751 sr123456    1  59    0    0K    0K sleep   0:00  0.00% runmqtrm<br />
19749 sr123456    1  59    0    0K    0K sleep   0:00  0.00% runmqtrm<br />
19739 sr123456    4  59    0    0K    0K sleep   0:00  0.00% amqzmgr0<br />
19746 sr123456    1  59    0    0K    0K sleep   0:00  0.00% runmqtrm<br />
19747 sr123456    1  59    0    0K    0K sleep   0:00  0.00% runmqtrm<br />
19737 sr123456    2  59    0    0K    0K sleep   0:00  0.00% amqrrmfa<br />
19738 sr123456    2  59    0    0K    0K sleep   0:00  0.00% amqzdmaa<br />
</code><br />
So in this case, the process named amqzmuc0 was the process performing the logging.</p>
<p>For reference, here is a list of processes and what they typically control for MQ:<br />
<code><br />
1.  RUNMQLSR - MQ TCP listener (multi-threaded)<br />
2.  AMQCLMAA - MQ TCP listener (single-threaded)<br />
3.  AMQRMPPA - Channel process pooling job<br />
4.  RUNMQCHI - MQ channel initiator<br />
5.  AMQCRSTA - MQ receiving MCA jobs<br />
6.  RUNMQCHL - MQ sending MCA jobs<br />
7.  AMQCRS6B - LU62 receiver channel<br />
8.  AMQPCSEA - MQ command server<br />
9.  RUNMQTRM - Application trigger monitor<br />
10. RUNMQDLQ - Dead letter queue handler<br />
11. AMQFCXBA - MQ Broker Worker Job<br />
12. RUNMQBRK - MQ Broker Control Job<br />
13. AMQZMUC0 - MQ Utility Manager<br />
14. AMQZMUR0 - MQ Utility Manager<br />
15. AMQZMGR0 - MQ Process Controller<br />
16. AMQRRMFA - MQ cluster repository manager<br />
17. AMQZDMAA - MQ deferred message manager<br />
18. AMQALMPX - MQ Log Manager<br />
19. AMQZFUMA - MQ Object Authority Manager<br />
20. AMQZLAS0 - MQ Local Queue Manager agents<br />
21. AMQZLAA0 - MQ Local Queue Manager agents<br />
22. AMQZXMA0 - MQ Execution Controller<br />
</code></p>
<p>With this info at hand we could then truss the process as per the following:<br />
<code><br />
# truss -D -p 19735<br />
</code></p>
<p>Which produces the following output:<br />
<code><br />
12677624.0012   lseek(18, 2543616, SEEK_SET)                    = 2543616<br />
12677624.0017   write(18, "0FEE0315\001\0\0\0D6A4 f".., 4096)   = 4096<br />
12677624.0018   lwp_cond_broadcast(0xFFFFFFFF7B46CAC0)          = 0<br />
12677624.0018   lwp_mutex_wakeup(0xFFFFFFFF7B46CAA8)            = 0<br />
12677624.0019   lseek(18, 2547712, SEEK_SET)                    = 2547712<br />
12677624.0023   write(18, "0FEE02FD\001\0\0\0D6A4 f".., 4096)   = 4096<br />
12677624.0024   lwp_cond_broadcast(0xFFFFFFFF7B46C3D8)          = 0<br />
12677624.0024   lwp_mutex_wakeup(0xFFFFFFFF7B46C3C0)            = 0<br />
12677624.0024   lwp_cond_broadcast(0xFFFFFFFF7B46CCE0)          = 0<br />
12677624.0025   lwp_mutex_wakeup(0xFFFFFFFF7B46CCC8)            = 0<br />
12677624.0025   lwp_cond_broadcast(0xFFFFFFFF7B46BE88)          = 0<br />
12677624.0026   lwp_mutex_wakeup(0xFFFFFFFF7B46BE70)            = 0<br />
12677624.0026   lseek(18, 2551808, SEEK_SET)                    = 2551808<br />
12677624.0030   write(18, "\tD10206\001\0\0\0D6A4 f".., 4096)   = 4096<br />
</code></p>
<p>What we can see from this test case is that Solaris is writing 4KB sized blocks of data to the file system in support of MQ persistent logging. I would prefer a higher size (say 8 &#8211; 16KB) as the SAN under test would be more efficient and capable of higher throughput, but I guess that is a limitation of the size of messages I am writing (185B per message) and the way Solaris breaks up the IO.</p>
<p>There is a comment from an IBM performance tuning guide for message persistence that states:<block>It is unlikely that poor persistent message throughput will be attributed to the 2MB limit of the queue manager log.  It is possible to fill and empty the log buffer several times each second and reach a CPU limit writing data into the log buffer, before a log disk bandwidth limit is reached.</block></p>
<p>In this, they are referring to the LogBufferPages parameter which I have increased to its maximum configurable size of 512 x 4K pages = 2MB. At this point in time I am still working with the sysadmin in an effort to prove this statement provided by IBM. For the time being we are investigating the seemingly high number of syscalls and context switching which is evident from vmstat:<br />
<code><br />
# vmstat 1<br />
kthr      memory            page            disk          faults      cpu<br />
r b w   swap  free  re  mf pi po fr de sr m0 m1 m3 m4   in   sy   cs us sy id<br />
0 1 0 27901544 13821744 0 6 8  0  0  0  0  0  0  0  0 11369 173717 83335 16 24 60<br />
0 1 0 27901544 13821688 0 0 8  0  0  0  0  0  0  0  0 11201 175563 84711 14 20 66<br />
0 1 0 27901536 13821648 635 4573 0 0 0 0 0 0  0  0  0 11841 179265 84000 14 26 59<br />
0 0 0 27900496 13821472 847 6045 8 8 8 0 0 0  0  0  0 13003 178012 82634 17 25 58<br />
2 0 0 27901552 13821528 0 0 8  0  0  0  0  0  0  0  0 10994 174223 83744 15 20 64<br />
0 1 0 27901544 13821480 0 0 0  0  0  0  0  0  0  0  0 11210 175509 83986 15 18 66<br />
0 1 0 27901544 13821440 0 0 8  0  0  0  0  0  0  0  0 11178 174778 83952 17 19 63<br />
</code></p>
<p>Another aspect I am investigating is the use of threads my the amqzmuc0 process. It would seem that for a given load amqzmuc0 is spawns around XX threads for that process. Looking at the prstat for that process confirms the following:<br />
<code><br />
# prstat -mL -p 29314<br />
PID  USERNAME USR  SYS TRP TFL DFL LCK SLP LAT VCX ICX SCL SIG PROCESS/LWPID<br />
29314 sr53186  0.4 0.7  -   -   -   -  3.2  -  564 157  1K   0 amqzmuc0/3<br />
29314 sr53186  0.0 0.0  -   -   -   -  0.4  -    1   0   1   0 amqzmuc0/4<br />
29314 sr53186  0.0 0.0  -   -   -   -  0.0  -    0   0   0   0 amqzmuc0/6<br />
29314 sr53186  0.0 0.0  -   -   -   -  0.0  -    0   0   0   0 amqzmuc0/5<br />
29314 sr53186  0.0 0.0  -   -   -   -  100  -    0   0   0   0 amqzmuc0/2<br />
29314 sr53186  0.0 0.0  -   -   -   -  0.0  -    0   0   0   0 amqzmuc0/1<br />
</code></p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/blogs/2007/understanding-mq-persistence-on-disk-performance/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Problem solving in general and MQ 2195 reason codes</title>
		<link>http://altentee.com/blogs/2007/problem-solving-in-general-and-mq-2195-reason-codes/</link>
		<comments>http://altentee.com/blogs/2007/problem-solving-in-general-and-mq-2195-reason-codes/#comments</comments>
		<pubDate>Fri, 10 Aug 2007 00:05:37 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[Altentee]]></category>
		<category><![CDATA[MQ]]></category>
		<category><![CDATA[theory]]></category>

		<guid isPermaLink="false">http://90kts.com/blog/2007/problem-solving-in-general-and-mq-2195-reason-codes/</guid>
		<description><![CDATA[So I spent the best part of a day assisting our sys admin and developer resolve MQ errors that a COBOL client was throwing when opening more than one concurrent connection to a clustered queue manager. Because the architecture had recently changed to a cluster, and my load harness was no longer getting the desired [...]]]></description>
			<content:encoded><![CDATA[<p>So I spent the best part of a day assisting our sys admin and developer resolve MQ errors that a COBOL client was throwing when opening more than one concurrent connection to a clustered queue manager.</p>
<p>Because the architecture had recently changed to a cluster, and my load harness was no longer getting the desired response times, we all went down the track of investigating issues with clustering as this was the new kid on the block. Whilst the developer and sys admin revealed many other interesting tid bits of information regarding correct configuration and the like, we still could not collectively resolve the problem: the COBOL code was throwing a 2195 reason code on multiple MQCONN calls to the queue manager.</p>
<p><span id="more-286"></span><br />
Some key lessons I learned here though, was to always simplify the problem by going back to a known configuration. We ended up doing that at the end of the day (using a standard queue manager configuration) and found that the 2195 errors persisted. So this was a good indicator that we had some sort of environment/configuration error.</p>
<p>The second key lesson was to always trust the API documentation. In this case a 2195 error has the following info:</p>
<blockquote><p>
2195 MQRC_UNEXPECTED_ERROR<br />
The call was rejected because an unexpected error occurred.<br />
Corrective action: Check the applicationâ€™s parameter list to ensure, for example, that the correct number of parameters was passed, and that data pointers and storage keys are valid.</p>
<p>If the problem cannot be resolved, contact your system programmer.<br />
v On OS/390, check whether any information has been displayed on the console. If this error occurs on an MQCONN or MQCONNX call, check that the subsystem named is an active MQSeries subsystem. In particular, check that it is not a DB2 subsystem. If the problem cannot be resolved, rerun the application with a CSQSNAP DD card (if you have not already got a dump) and send the resulting dump to IBM.<br />
v On OS/2 and AS/400, consult the FFST record to obtain more detail about the problem.<br />
v On Compaq (DIGITAL) OpenVMS, Tandem NonStop Kernel, and UNIX systems, consult the FDC file to obtain more detail about the problem.
</p></blockquote>
<p>To be honest, I got put off by the &#8220;unexpected error&#8221; bit, and had the same reaction I do when I see server 500 errors for http. It&#8217;s hard not to put your head in the sand in this situation. But on closer inspection, and now with the benefit of hindsight, the corrective action does mention how to resolve this, as well as a key tip to look at the FDC file to obtain more detail about the problem. Never having seen a FDC file before I simply ignored it, but the collective nouse of the sys admin and developer later figured it all out, with the recommended solutions posted <a href="http://techdebug.com/blog/2007/08/10/tuning-solaris-9-for-mq-v60/">here</a> and <a href="http://techdebug.com/blog/2007/08/10/solaris-9-kernel-parameters/">here</a>. Well done Ted <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/problem-solving-in-general-and-mq-2195-reason-codes/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>RWI 00239 The server has reached the maximum number of simultaneous connections</title>
		<link>http://altentee.com/blogs/2007/rwi-00239-the-server-has-reached-the-maximum-number-of-simultaneous-connections/</link>
		<comments>http://altentee.com/blogs/2007/rwi-00239-the-server-has-reached-the-maximum-number-of-simultaneous-connections/#comments</comments>
		<pubDate>Fri, 25 May 2007 02:30:14 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[Altentee]]></category>
		<category><![CDATA[MQ]]></category>
		<category><![CDATA[theory]]></category>

		<guid isPermaLink="false">http://90kts.com/blog/2007/rwi-00239-the-server-has-reached-the-maximum-number-of-simultaneous-connections/</guid>
		<description><![CDATA[Once again on the topic of performance testing Business Objects, when executing a benchmark for a web intelligence report with goal being to see how many concurrent users it could support, the following error mesage was being generated in the vuser log: Connection failed. The server has reached the maximum number of simultaneous connections. (Error: [...]]]></description>
			<content:encoded><![CDATA[<p>Once again on the topic of performance testing Business Objects, when executing a benchmark for a web intelligence report with goal being to see how many concurrent users it could support, the following error mesage was being generated in the vuser log:<br />
<a href='http://90kts.com/blog/wp-content/uploads/2007/05/rwi-00239.png' title='RWI 00239 The server has reached the maximum number of simultaneous connections'><img src='http://90kts.com/blog/wp-content/uploads/2007/05/rwi-00239.png' alt='RWI 00239 The server has reached the maximum number of simultaneous connections' /></a><code><br />
Connection failed. The server has reached the maximum number of simultaneous connections. (Error: RWI 00239) (Error: INF )</code></p>
<p>What to do?</p>
<p><span id="more-279"></span></p>
<p>In order to find this error I generated a snapshot on error in the run time settings for LoadRunner, then browsed the html source for the vuser typically available at <code>C:\Documents and Settings\UserName\Local Settings\Temp\res</code></p>
<p>There were a number of incorrect conclusions that I jumped to here:</p>
<p>1. That google would save the day and spoon feed me the answer! The only information I could find was <a href="http://www.forumtopics.com/busobj/viewtopic.php?p=330313">here</a> but alas they did not have the answer. Hence my decision to post here, as no doubt some other performance tester out there is going to hit this problem. I would post on the BOB forum, but hey, you need a login to comment. Meh.</p>
<p>2. My <a href="http://en.wikipedia.org/wiki/Kludge">kludge&#8217;s</a> approach would be good enough. I thought if I want 50 concurrent users, all I need to do is make sure that I have at least 100 simultaneous connections available. Right?<br />
<a href='http://90kts.com/blog/wp-content/uploads/2007/05/boconcurrentusersettings.png' title='boconcurrentusersettings.png'><img src='http://90kts.com/blog/wp-content/uploads/2007/05/boconcurrentusersettings.thumbnail.png' alt='boconcurrentusersettings.png' /></a><br />
Wrong &#8230;</p>
<p>As it turns out, a user opens more than one session on the web intelligence server. It seems they need one to login, one as they start to navigate around the folder structure and another to open reports. I&#8217;m not too sure if this behaviour is caused by the browser (IE or Mozilla) but it seems to be consistent when using a browser. You can see this information by monitoring a user session in the central management console.<br />
<a href='http://90kts.com/blog/wp-content/uploads/2007/05/3sessionsperuser.png' title='3 Sessions Per User'><img src='http://90kts.com/blog/wp-content/uploads/2007/05/3sessionsperuser.thumbnail.png' alt='3 Sessions Per User' /></a></p>
<p>So that seems to fix the RWI 00239 errors. Now that I&#8217;m past that, on to investigating why the web intelligence servers fails under concurrent user load. RWI 00236 is my starting point, let&#8217;s revisit google to see what others have found &#8230;</p>
<p><a href='http://90kts.com/blog/wp-content/uploads/2007/05/rwi-00236.png' title='RWI 00236 The Web Intelligence server could not be reached.'><img src='http://90kts.com/blog/wp-content/uploads/2007/05/rwi-00236.png' alt='RWI 00236 The Web Intelligence server could not be reached.' /></a><br />
<code>The Web Intelligence server could not be reached. Contact your Business Objects administrator. (Error: RWI 00236)(Error: INF)</code></p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/blogs/2007/rwi-00239-the-server-has-reached-the-maximum-number-of-simultaneous-connections/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Monitoring queue statistics in MQ</title>
		<link>http://altentee.com/blogs/2007/monitoring-queue-statistics-in-mq/</link>
		<comments>http://altentee.com/blogs/2007/monitoring-queue-statistics-in-mq/#comments</comments>
		<pubDate>Mon, 30 Apr 2007 05:55:43 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[Altentee]]></category>
		<category><![CDATA[monitoring]]></category>
		<category><![CDATA[MQ]]></category>
		<category><![CDATA[perl]]></category>

		<guid isPermaLink="false">http://90kts.com/blog/2007/monitoring-queue-statistics-in-mq/</guid>
		<description><![CDATA[When load testing MQ you are no doubt going to need to be able to monitor queue statistics in terms of how many messages have been enqueued and dequeued within a given timeframe. You can use native runmqsc commands to query queues in order to find current queue depths but this is just a snapshot [...]]]></description>
			<content:encoded><![CDATA[<p>When load testing MQ you are no doubt going to need to be able to monitor queue statistics in terms of how many messages have been enqueued and dequeued within a given timeframe. You can use native <b>runmqsc</b> commands to query queues in order to find current queue depths but this is just a snapshot in time. In order to be able to monitor how many messages have been or gone, you need to sample the queue over time.  Here is a good <a href="http://www.mqseries.net/phpBB2/viewtopic.php?p=112759">synopsis</a> of options&#8230;</p>
<p>A good way to achieve this is my using the <a href="http://www-1.ibm.com/support/docview.wss?rs=203&#038;uid=swg24000668&#038;loc=en_US&#038;cs=utf-8&#038;lang=en">PCF support package</a> provided by IBM.</p>
<blockquote><p>The WebSphere MQ Programmable Command Formats (PCF) provide the capability to perform administration tasks on a queue manager by sending and receiving WebSphere MQ messages of a special format. PCF request messages are sent to the queue manager&#8217;s command queue, where they are processed by the command server and replies returned to the designated reply-to queue.</p>
<p>This SupportPac contains a set of Java classes representing PCF header structures as well as an agent that can be used to simplify the task of communicating with a target queue manager and thus enable the use of WebSphere MQ Programmable Command Formats for queue manager administration. </p></blockquote>
<p>Using a simple java object as documented in <a href="http://www-304.ibm.com/jct09002c/isv/tech/sample_code/mq/ResetQStats.java">sample</a> code, you can query queue stats of your choice. My implementation simply prints out the queue you are connected to, along with enqueue, dequeue and total queue size stats over an arbitrary time frame (eg. last 2 seconds). This can easily be called from a simple shell script.</p>
<p><span id="more-273"></span><br />
<b>ResetQStats.java</b><br />
<code><br />
/**<br />
* Reset MQ Queue Statistics (ResetQStats)<br />
*<br />
* Compile	: javac -classpath com.ibm.mq.jar:connector.jar:jta.jar:com.ibm.mq.pcf-6.0.jar ResetQStats.java</p>
<p>* Package	: jar cfm ResetQStats.jar ResetQStats.MF *.class<br />
* Execute	: java -cp com.ibm.mq.jar:connector.jar:jta.jar:com.ibm.mq.pcf-6.0.jar:ResetQStats.jar ResetQStats [options]<br />
* Usage		: ResetQStats [options]<br />
* Options	:<br />
		host		MQ hostname eg. 127.0.0.1<br />
		port		      MQ port eg. 1415<br />
		channel		MQ channel eg. CHANNEL_NAME<br />
		queue		MQ queue eg. QUEUE_NAME<br />
*<br />
* Last edited	: 6 Mar 07 14.00<br />
* Author		: Tim Koopmans<br />
**/</p>
<p>import java.io.*;<br />
import com.ibm.mq.*;<br />
import com.ibm.mq.pcf.*;</p>
<p>public class ResetQStats<br />
{<br />
	final public static String copyright =<br />
                  "Copyright (c) IBM Corp. 2005 All rights reserved.";</p>
<p>	public static void main (String [] args)<br />
	{<br />
           PCFAgent 		 agent;<br />
		PCFParameter [] parameters = { new MQCFST (CMQC.MQCA_Q_NAME,args [3]) };<br />
		MQMessage [] 	 responses;<br />
		MQCFH 			 cfh;<br />
		PCFParameter 	 p;</p>
<p>		try<br />
		{<br />
		   	// Connect a PCFAgent to the specified queue manager<br />
			if (args.length == 1)<br />
			{<br />
				agent = new PCFAgent (args [0]);<br />
			}<br />
			else<br />
			{<br />
				agent = new PCFAgent (args [0], Integer.parseInt (args [1]), args [2]);<br />
			}</p>
<p>			// Use the agent to send the request</p>
<p>			responses = agent.send (CMQCFC.MQCMD_RESET_Q_STATS, parameters);<br />
			cfh = new MQCFH (responses [0]);</p>
<p>			if (cfh.reason == 0)<br />
			{<br />
				//System.out.println ("Queue Statistics:");<br />
				for (int i = 0; i < cfh.parameterCount; i++)<br />
				{<br />
					// Walk through the returned attributes<br />
					p = PCFParameter.nextParameter (responses [0]);<br />
					int parm = p.getParameter();<br />
					switch (parm)<br />
					{<br />
						case CMQC.MQCA_Q_NAME:<br />
									        //Queue Name<br />
									        break;<br />
						case CMQC.MQIA_TIME_SINCE_RESET:<br />
									        //TimeSinceReset t(sec)<br />
									        break;<br />
						case CMQC.MQIA_MSG_ENQ_COUNT:<br />
									        //MsgEnqCount ++<br />
										  break;<br />
						case CMQC.MQIA_MSG_DEQ_COUNT:<br />
									        //MsgDeqCount --										  break;<br />
						case CMQC.MQIA_HIGH_Q_DEPTH:<br />
									        //HighQDepth  (total)<br />
										  break;<br />
					}<br />
					System.out.print(" \t" + p.getValue ());<br />
				}<br />
				System.out.print("\n");<br />
			}<br />
			else<br />
			{<br />
				System.out.println ("PCF error:\n" + cfh);<br />
				// Walk through the returned parameters describing the error<br />
				for (int i = 0; i < cfh.parameterCount; i++)<br />
				{<br />
					System.out.println (PCFParameter.nextParameter (responses [0]));<br />
				}<br />
			}</p>
<p>			// Disconnect<br />
			agent.disconnect ();<br />
		}</p>
<p>		catch (ArrayIndexOutOfBoundsException abe)<br />
		{<br />
			System.out.println ("Usage: \n" +<br />
				"\tjava ResetQStats queue-manager\n" +<br />
				"\tjava ResetQStats host port svrconn-channel");<br />
		}</p>
<p>		catch (NumberFormatException nfe)<br />
		{<br />
			System.out.println ("Invalid port: " + args [1]);<br />
			System.out.println ("Usage: \n" +<br />
				"\tjava ResetQStats queue-manager\n" +<br />
				"\tjava ResetQStats host port svrconn-channel");<br />
		}</p>
<p>		catch (MQException mqe)<br />
		{<br />
			System.err.println (mqe);<br />
		}</p>
<p>		catch (IOException ioe)<br />
		{<br />
			System.err.println (ioe);<br />
		}<br />
	}<br />
}<br />
</code></p>
<p><b>Simple Shell Script</b><br />
<code><br />
#~/bin/sh<br />
javac -classpath $HOME/harness/CDE/com.ibm.mq.jar:$HOME/harness/CDE/connector.jar:$HOME/harness/CDE/jta.jar:/home/strata/d281447/harness/CDE/com.ibm.mq.pcf-6.0.jar $HOME/harness/CDE/ResetQStats.java<br />
cd $HOME/harness/CDE<br />
jar cfm ResetQStats.jar ResetQStats.MF *.class<br />
rm $HOME/harness/CDE/*.class</p>
<p>cd $HOME/harness/CDE</p>
<p>printf "\tQueue Name\t\t\t\t\t\t++ \t-- \tdepth \tsecs\n"</p>
<p>duration=$2	#duration in seconds<br />
sampleRate=$3 	#sample every n seconds</p>
<p>i="1"<br />
while [ $i -le $duration ]<br />
do<br />
	java -cp com.ibm.mq.jar:connector.jar:jta.jar:com.ibm.mq.pcf-6.0.jar:ResetQStats.jar ResetQStats 127.0.0.1 1415 CHANNEL $1</p>
<p>	sleep $sampleRate<br />
	i=`expr $i + 1`</p>
<p>done<br />
printf "\n"<br />
</code></p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/blogs/2007/monitoring-queue-statistics-in-mq/feed/</wfw:commentRss>
		<slash:comments>2</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>

