jmeter-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Felix Schumacher <felix.schumac...@internetallee.de>
Subject Re: svn commit: r1641081 - in /jmeter/trunk: ./ bin/ res/maven/ src/components/org/apache/jmeter/visualizers/backend/ src/core/org/apache/jmeter/resources/ src/core/org/apache/jmeter/samplers/ src/core/org/apache/jmeter/save/ xdocs/ xdocs/usermanual/
Date Sun, 30 Nov 2014 09:19:02 GMT


Am 29. November 2014 21:12:00 MEZ, schrieb Philippe Mouawad <philippe.mouawad@gmail.com>:
>Hi Felix
>
>My answer inline.
>Regards
>
>On Sat, Nov 29, 2014 at 11:51 AM, Felix Schumacher <
>felix.schumacher@internetallee.de> wrote:
>
>> Hello Philippe,
>>
>> Am Sonntag, den 23.11.2014, 12:22 +0100 schrieb Philippe Mouawad:
>> > Thanks a lot for your review which pointed to a synchronisation
>issue
>> that
>> > I fixed, good catch!
>> >
>> > I think I took all your notes into account, let me know if I forgot
>> > something.
>> in SamplerMetric you have used a sliding window for the statistics.
>> * Should we make the length of the window configurable?
>>
>
>Yes but it's a new property and we have a lot :-)
But the size of the window depends on the number of samples per time slot. Perhaps it could be dynamically sized? 

>
>
>> * Should min/max and minThreads/maxThreads be limited to the sliding
>> window, also? At least min and max would be simple to do.
>>
>
>Dev team opinion is welcome, maybe it would be better
>- min would be percentile(0)
>- max would be percentile(100)

The stats field has methods to get the minimum and the maximum values. I would take those. 

>for minThreads, maxThreads, how would you do it ?

Create another statistical field for the number of threads. Then we could provide correct answers for max/min thread numbers plus mean/average/percentile. 

Regards
Felix

>
>
>> Regards
>>  Felix
>> >
>> > Regards
>> > Philippe
>> >
>> > On Sunday, November 23, 2014, Felix Schumacher <
>> > felix.schumacher@internetallee.de> wrote:
>> >
>> > > Hi Phillipe,
>> > > Am 22.11.2014 um 19:29 schrieb Philippe Mouawad:
>> > >
>> > >> Hi Felix,
>> > >> As I said in thread, I commited code and will improve, feel free
>to
>> fix
>> > >> javadocs issues on your side.
>> > >> I will review your comment.
>> > >>
>> > >> I have spent many hours if not days on this code and I am aware
>it is
>> not
>> > >> yet fully completed (although tests are promising) but my aim
>when
>> > >> commiting it was to have feedback and help to finish it.
>> > >>
>> > > I did not mean to offend you. I can clearly see, that you put a
>lot of
>> > > effort
>> > > in this listener and I will surely try to integrate jmeter into
>our
>> > > collectd server.
>> > >
>> > > Regards
>> > >  Felix
>> > >
>> > >>
>> > >> Regards
>> > >> Philippe
>> > >>
>> > >> On Sat, Nov 22, 2014 at 7:21 PM, Felix Schumacher <
>> > >> felix.schumacher@internetallee.de> wrote:
>> > >>
>> > >>  Hello Philippe,
>> > >>>
>> > >>> I have hidden a few comments inside the cited code.
>> > >>> They are mostly around javadoc and naming things.
>> > >>>
>> > >>> Am 22.11.2014 um 16:36 schrieb pmouawad@apache.org:
>> > >>>
>> > >>>  Author: pmouawad
>> > >>>> Date: Sat Nov 22 15:36:37 2014
>> > >>>> New Revision: 1641081
>> > >>>>
>> > >>>> URL: http://svn.apache.org/r1641081
>> > >>>> Log:
>> > >>>> Bug 55932 - Create a Async BackendListener to allow easy plug
>of new
>> > >>>> listener (Graphite, JDBC, Console,...)
>> > >>>> Bugzilla Id: 55932
>> > >>>>
>> > >>>> Added:
>> > >>>>      
>jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> > >>>> backend/
>> > >>>>      
>jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> > >>>> backend/
>> > >>>> AbstractBackendListenerClient.java   (with props)
>> > >>>>      
>jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> > >>>> backend/BackendListener.java
>> > >>>>   (with props)
>> > >>>>      
>jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> > >>>> backend/BackendListenerClient.java   (with props)
>> > >>>>      
>jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> > >>>> backend/BackendListenerContext.java
>> > >>>>   (with props)
>> > >>>>      
>jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> > >>>> backend/BackendListenerGui.java   (with props)
>> > >>>>      
>jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> > >>>> backend/SamplerMetric.java
>> > >>>>   (with props)
>> > >>>> Modified:
>> > >>>>       jmeter/trunk/bin/saveservice.properties
>> > >>>>       jmeter/trunk/build.properties
>> > >>>>       jmeter/trunk/build.xml
>> > >>>>       jmeter/trunk/eclipse.classpath
>> > >>>>       jmeter/trunk/res/maven/ApacheJMeter_parent.pom
>> > >>>>       jmeter/trunk/src/core/org/apache/jmeter/resources/
>> > >>>> messages.properties
>> > >>>>       jmeter/trunk/src/core/org/apache/jmeter/resources/
>> > >>>> messages_fr.properties
>> > >>>>       jmeter/trunk/src/core/org/apache/jmeter/samplers/
>> > >>>> SampleResult.java
>> > >>>>      
>jmeter/trunk/src/core/org/apache/jmeter/save/SaveService.java
>> > >>>>       jmeter/trunk/xdocs/changes.xml
>> > >>>>       jmeter/trunk/xdocs/usermanual/component_reference.xml
>> > >>>>
>> > >>>> Modified: jmeter/trunk/bin/saveservice.properties
>> > >>>> URL:
>http://svn.apache.org/viewvc/jmeter/trunk/bin/saveservice.
>> > >>>> properties?rev=1641081&r1=1641080&r2=1641081&view=diff
>> > >>>> ============================================================
>> > >>>> ==================
>> > >>>> --- jmeter/trunk/bin/saveservice.properties (original)
>> > >>>> +++ jmeter/trunk/bin/saveservice.properties Sat Nov 22
>15:36:37 2014
>> > >>>> @@ -53,7 +53,8 @@ _file_version=$Revision$
>> > >>>>    # 2.5 = 2.10
>> > >>>>    # 2.6 = 2.11
>> > >>>>    # 2.7 = 2.12
>> > >>>> -_version=2.7
>> > >>>> +# 2.8 = 2.13
>> > >>>> +_version=2.8
>> > >>>>    #
>> > >>>>    #
>> > >>>>    # Character set encoding used to read and write JMeter XML
>files
>> and
>> > >>>> CSV results
>> > >>>> @@ -78,6 +79,8 @@ AssertionVisualizer=org.apache.jmeter.vi
>> > >>>>   
>AuthManager=org.apache.jmeter.protocol.http.control.AuthManager
>> > >>>>
>> Authorization=org.apache.jmeter.protocol.http.control.Authorization
>> > >>>>    AuthPanel=org.apache.jmeter.protocol.http.gui.AuthPanel
>> > >>>>
>>
>+BackendListener=org.apache.jmeter.visualizers.backend.BackendListener
>> > >>>> +BackendListenerGui=org.apache.jmeter.visualizers.
>> > >>>> backend.BackendListenerGui
>> > >>>>    BarChart=org.apache.jmeter.testelement.BarChart
>> > >>>>    BarChartGui=org.apache.jmeter.report.gui.BarChartGui
>> > >>>>
>> BeanShellAssertion=org.apache.jmeter.assertions.BeanShellAssertion
>> > >>>>
>> > >>>> Modified: jmeter/trunk/build.properties
>> > >>>> URL:
>http://svn.apache.org/viewvc/jmeter/trunk/build.properties?
>> > >>>> rev=1641081&r1=1641080&r2=1641081&view=diff
>> > >>>> ============================================================
>> > >>>> ==================
>> > >>>> --- jmeter/trunk/build.properties (original)
>> > >>>> +++ jmeter/trunk/build.properties Sat Nov 22 15:36:37 2014
>> > >>>> @@ -118,11 +118,21 @@ commons-logging.loc         = ${maven2.r
>> > >>>>    #commons-logging.md5         =
>E2C390FE739B2550A218262B28F290CE
>> > >>>>    commons-logging.md5         =
>040b4b4d8eac886f6b4a2a3bd2f31b00
>> > >>>>    +commons-math3.version         = 3.3
>> > >>>> +commons-math3.jar             =
>commons-math3-${commons-math3.
>> > >>>> version}.jar
>> > >>>> +commons-math3.loc             = ${maven2.repo}/org/apache/
>> > >>>> commons/commons-math3/${commons-math3.version}
>> > >>>> +commons-math3.md5             =
>87346cf2772dc2becf106c45e0f63863
>> > >>>> +
>> > >>>>    commons-net.version         = 3.3
>> > >>>>    commons-net.jar             =
>> commons-net-${commons-net.version}.jar
>> > >>>>    commons-net.loc             = ${maven2.repo}/commons-net/
>> > >>>> commons-net/${commons-net.version}
>> > >>>>    commons-net.md5             =
>c077ca61598e9c21f43f8b6488fbbee9
>> > >>>>    +commons-pool2.version         = 2.2
>> > >>>> +commons-pool2.jar             =
>commons-pool2-${commons-pool2.
>> > >>>> version}.jar
>> > >>>> +commons-pool2.loc             = ${maven2.repo}/org/apache/
>> > >>>> commons/commons-pool2/${commons-pool2.version}
>> > >>>> +commons-pool2.md5             =
>51b56c92883812c56fbeb339866ce2df
>> > >>>> +
>> > >>>>    # dnsjava for DNSCacheManager
>> > >>>>    dnsjava.version             = 2.1.6
>> > >>>>    dnsjava.jar                 =
>dnsjava-${dnsjava.version}.jar
>> > >>>>
>> > >>>> Modified: jmeter/trunk/build.xml
>> > >>>> URL: http://svn.apache.org/viewvc/jmeter/trunk/build.xml?rev=
>> > >>>> 1641081&r1=1641080&r2=1641081&view=diff
>> > >>>> ============================================================
>> > >>>> ==================
>> > >>>> --- jmeter/trunk/build.xml (original)
>> > >>>> +++ jmeter/trunk/build.xml Sat Nov 22 15:36:37 2014
>> > >>>> @@ -365,7 +365,9 @@
>> > >>>>        <include name="${lib.dir}/${commons-jexl2.jar}"/>
>> > >>>>        <include name="${lib.dir}/${commons-lang3.jar}"/>
>> > >>>>        <include name="${lib.dir}/${commons-logging.jar}"/>
>> > >>>> +    <include name="${lib.dir}/${commons-math3}"/>
>> > >>>>        <include name="${lib.dir}/${commons-net.jar}"/>
>> > >>>> +    <include name="${lib.dir}/${commons-pool2.jar}"/>
>> > >>>>        <include name="${lib.dir}/${dnsjava.jar}"/>
>> > >>>>        <include
>name="${lib.dir}/${excalibur-datasource.jar}"/>
>> > >>>>        <include
>name="${lib.dir}/${excalibur-instrument.jar}"/>
>> > >>>> @@ -438,8 +440,10 @@
>> > >>>>        <pathelement
>location="${lib.dir}/${commons-jexl2.jar}"/>
>> > >>>>        <pathelement
>location="${lib.dir}/${commons-lang3.jar}"/>
>> > >>>>        <pathelement
>location="${lib.dir}/${commons-logging.jar}"/>
>> > >>>> +    <pathelement location="${lib.dir}/${commons-math3.jar}"/>
>> > >>>>        <pathelement location="${lib.dir}/${commons-net.jar}"/>
>> > >>>> -    <pathelement location="${lib.dir}/${dnsjava.jar}"/>
>> > >>>> +       <pathelement
>location="${lib.dir}/${commons-pool2.jar}"/>
>> > >>>> +       <pathelement location="${lib.dir}/${dnsjava.jar}"/>
>> > >>>>        <pathelement
>> location="${lib.dir}/${excalibur-datasource.jar}"/>
>> > >>>>        <pathelement
>> location="${lib.dir}/${excalibur-instrument.jar}"/>
>> > >>>>        <pathelement
>location="${lib.dir}/${excalibur-logger.jar}"/>
>> > >>>> @@ -2909,7 +2913,9 @@ run JMeter unless all the JMeter jars ar
>> > >>>>            <process_jarfile jarname="commons-jexl2"/>
>> > >>>>            <process_jarfile jarname="commons-lang3"/>
>> > >>>>            <process_jarfile jarname="commons-logging"/>
>> > >>>> +        <process_jarfile jarname="commons-math3"/>
>> > >>>>            <process_jarfile jarname="commons-net"/>
>> > >>>> +       <process_jarfile jarname="commons-pool2"/>
>> > >>>>            <process_jarfile jarname="dnsjava"/>
>> > >>>>            <process_jarfile jarname="excalibur-datasource"/>
>> > >>>>            <process_jarfile jarname="excalibur-instrument"/>
>> > >>>>
>> > >>>> Modified: jmeter/trunk/eclipse.classpath
>> > >>>> URL: http://svn.apache.org/viewvc/jmeter/trunk/eclipse.
>> > >>>> classpath?rev=1641081&r1=1641080&r2=1641081&view=diff
>> > >>>> ============================================================
>> > >>>> ==================
>> > >>>> --- jmeter/trunk/eclipse.classpath (original)
>> > >>>> +++ jmeter/trunk/eclipse.classpath Sat Nov 22 15:36:37 2014
>> > >>>> @@ -55,7 +55,9 @@
>> > >>>>          <classpathentry kind="lib"
>> path="lib/commons-jexl-2.1.1.jar"/>
>> > >>>>          <classpathentry kind="lib"
>path="lib/commons-lang3-3.3.2.
>> > >>>> jar"/>
>> > >>>>          <classpathentry kind="lib"
>path="lib/commons-logging-1.2.
>> > >>>> jar"/>
>> > >>>> +    <classpathentry kind="lib"
>path="lib/commons-math3-3.3.jar"/>
>> > >>>>          <classpathentry kind="lib"
>path="lib/commons-net-3.3.jar"/>
>> > >>>> +    <classpathentry kind="lib"
>path="lib/commons-pool2-2.2.jar"/>
>> > >>>>          <classpathentry kind="lib"
>path="lib/dnsjava-2.1.6.jar"/>
>> > >>>>          <classpathentry kind="lib" path="lib/excalibur-
>> > >>>> datasource-2.1.jar"/>
>> > >>>>          <classpathentry kind="lib" path="lib/excalibur-
>> > >>>> instrument-1.0.jar"/>
>> > >>>>
>> > >>>> Modified: jmeter/trunk/res/maven/ApacheJMeter_parent.pom
>> > >>>> URL: http://svn.apache.org/viewvc/jmeter/trunk/res/maven/
>> > >>>>
>ApacheJMeter_parent.pom?rev=1641081&r1=1641080&r2=1641081&view=diff
>> > >>>> ============================================================
>> > >>>> ==================
>> > >>>> --- jmeter/trunk/res/maven/ApacheJMeter_parent.pom (original)
>> > >>>> +++ jmeter/trunk/res/maven/ApacheJMeter_parent.pom Sat Nov 22
>> 15:36:37
>> > >>>> 2014
>> > >>>> @@ -66,7 +66,9 @@ under the License.
>> > >>>>          <commons-jexl2.version>2.1.1</commons-jexl2.version>
>> > >>>>          <commons-lang3.version>3.3.2</commons-lang3.version>
>> > >>>>         
><commons-logging.version>1.2</commons-logging.version>
>> > >>>> +      <commons-math3.version>3.3</commons-math3.version>
>> > >>>>          <commons-net.version>3.3</commons-net.version>
>> > >>>> +      <commons-pool2.version>2.2</commons-pool2.version>
>> > >>>>          <dnsjava.version>2.1.6</dnsjava.version>
>> > >>>>         
><excalibur-datasource.version>2.1</excalibur-datasource.
>> > >>>> version>
>> > >>>>         
><excalibur-instrument.version>1.0</excalibur-instrument.
>> > >>>> version>
>> > >>>> @@ -181,11 +183,21 @@ under the License.
>> > >>>>            <version>${commons-logging.version}</version>
>> > >>>>          </dependency>
>> > >>>>          <dependency>
>> > >>>> +        <groupId>commons-math3</groupId>
>> > >>>> +        <artifactId>commons-math3</artifactId>
>> > >>>> +        <version>${commons-math3.version}</version>
>> > >>>> +      </dependency>
>> > >>>> +      <dependency>
>> > >>>>            <groupId>commons-net</groupId>
>> > >>>>            <artifactId>commons-net</artifactId>
>> > >>>>            <version>${commons-net.version}</version>
>> > >>>>          </dependency>
>> > >>>>          <dependency>
>> > >>>> +        <groupId>commons-pool2</groupId>
>> > >>>> +        <artifactId>commons-pool2</artifactId>
>> > >>>> +        <version>${commons-pool2.version}</version>
>> > >>>> +      </dependency>
>> > >>>> +      <dependency>
>> > >>>>              <groupId>dnsjava</groupId>
>> > >>>>              <artifactId>dnsjava</artifactId>
>> > >>>>              <version>${dnsjava.version}</version>
>> > >>>>
>> > >>>> Added:
>jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> > >>>> backend/
>> > >>>> AbstractBackendListenerClient.java
>> > >>>> URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/
>> > >>>>
>org/apache/jmeter/visualizers/backend/AbstractBackendListenerClient.
>> > >>>> java?rev=1641081&view=auto
>> > >>>> ============================================================
>> > >>>> ==================
>> > >>>> ---
>> jmeter/trunk/src/components/org/apache/jmeter/visualizers/backend/
>> > >>>> AbstractBackendListenerClient.java (added)
>> > >>>> +++
>> jmeter/trunk/src/components/org/apache/jmeter/visualizers/backend/
>> > >>>> AbstractBackendListenerClient.java Sat Nov 22 15:36:37 2014
>> > >>>> @@ -0,0 +1,121 @@
>> > >>>> +/*
>> > >>>> + * Licensed to the Apache Software Foundation (ASF) under one
>or
>> more
>> > >>>> + * contributor license agreements.  See the NOTICE file
>distributed
>> > >>>> with
>> > >>>> + * this work for additional information regarding copyright
>> ownership.
>> > >>>> + * The ASF licenses this file to You under the Apache
>License,
>> Version
>> > >>>> 2.0
>> > >>>> + * (the "License"); you may not use this file except in
>compliance
>> with
>> > >>>> + * the License.  You may obtain a copy of the License at
>> > >>>> + *
>> > >>>> + *   http://www.apache.org/licenses/LICENSE-2.0
>> > >>>> + *
>> > >>>> + * Unless required by applicable law or agreed to in writing,
>> software
>> > >>>> + * distributed under the License is distributed on an "AS IS"
>> BASIS,
>> > >>>> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
>express or
>> > >>>> implied.
>> > >>>> + * See the License for the specific language governing
>permissions
>> and
>> > >>>> + * limitations under the License.
>> > >>>> + *
>> > >>>> + */
>> > >>>> +
>> > >>>> +package org.apache.jmeter.visualizers.backend;
>> > >>>> +
>> > >>>> +import java.util.Map;
>> > >>>> +import java.util.concurrent.ConcurrentHashMap;
>> > >>>> +
>> > >>>> +import org.apache.jmeter.config.Arguments;
>> > >>>> +import org.apache.jmeter.samplers.SampleResult;
>> > >>>> +import org.apache.jorphan.logging.LoggingManager;
>> > >>>> +import org.apache.log.Logger;
>> > >>>> +
>> > >>>> +/**
>> > >>>> + * An abstract implementation of the BackendListenerClient
>> interface.
>> > >>>> This
>> > >>>> + * implementation provides default implementations of most of
>the
>> > >>>> methods in the
>> > >>>> + * interface, as well as some convenience methods, in order
>to
>> simplify
>> > >>>> + * development of BackendListenerClient implementations.
>> > >>>> + *
>> > >>>> + * While it may be necessary to make changes to the
>> > >>>> BackendListenerClient interface
>> > >>>> + * from time to time (therefore requiring changes to any
>> > >>>> implementations
>> > >>>> of this
>> > >>>> + * interface), we intend to make this abstract class provide
>> reasonable
>> > >>>> + * implementations of any new methods so that subclasses do
>not
>> > >>>> necessarily need
>> > >>>> + * to be updated for new versions. Therefore, when creating a
>new
>> > >>>> + * BackendListenerClient implementation, developers are
>encouraged
>> to
>> > >>>> subclass this
>> > >>>> + * abstract class rather than implementing the
>> BackendListenerClient
>> > >>>> interface
>> > >>>> + * directly. Implementing BackendListenerClient directly will
>> continue
>> > >>>> to be
>> > >>>> + * supported for cases where extending this class is not
>possible
>> (for
>> > >>>> example,
>> > >>>> + * when the client class is already a subclass of some other
>> class).
>> > >>>> + * <p>
>> > >>>> + * The handleSampleResult() method of BackendListenerClient
>does
>> not
>> > >>>> have a default
>> > >>>> + * implementation here, so subclasses must define at least
>this
>> method.
>> > >>>> It may
>> > >>>> + * be useful to override other methods as well.
>> > >>>> + *
>> > >>>> + * @see BackendListener#sampleOccurred(org.apache.
>> > >>>> jmeter.samplers.SampleEvent)
>> > >>>> + * @since 2.13
>> > >>>> + */
>> > >>>> +public abstract class AbstractBackendListenerClient
>implements
>> > >>>> BackendListenerClient {
>> > >>>> +
>> > >>>> +    private static final Logger log = LoggingManager.
>> > >>>> getLoggerForClass();
>> > >>>>
>> > >>>>  In classes further down the logger is stored in variables
>named
>> LOG and
>> > >>> LOGGER, should we use one name?
>> > >>> In this class we have a getter for the logger in other classes
>not.
>> Why?
>> > >>>
>> > >>>  +
>> > >>>> +    private ConcurrentHashMap<String, SamplerMetric>
>> metricsPerSampler
>> > >>>> =
>> > >>>> new ConcurrentHashMap<String, SamplerMetric>();
>> > >>>> +
>> > >>>> +    /* Implements
>> BackendListenerClient.setupTest(JavaSamplerContext)
>> > >>>> */
>> > >>>> +    @Override
>> > >>>> +    public void setupTest(BackendListenerContext context)
>throws
>> > >>>> Exception {
>> > >>>> +        log.debug(getClass().getName() + ": setupTest");
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /* Implements BackendListenerClient.teardownTest(
>> > >>>> JavaSamplerContext)
>> > >>>> */
>> > >>>> +    @Override
>> > >>>> +    public void teardownTest(BackendListenerContext context)
>throws
>> > >>>> Exception {
>> > >>>> +        log.debug(getClass().getName() + ": teardownTest");
>> > >>>> +        metricsPerSampler.clear();
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /* Implements
>BackendListenerClient.getDefaultParameters() */
>> > >>>> +    @Override
>> > >>>> +    public Arguments getDefaultParameters() {
>> > >>>> +        return null;
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Get a Logger instance which can be used by subclasses
>to log
>> > >>>> information.
>> > >>>> +     *
>> > >>>> +     * @return a Logger instance which can be used for
>logging
>> > >>>> +     */
>> > >>>> +    protected Logger getLogger() {
>> > >>>> +        return log;
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /* (non-Javadoc)
>> > >>>> +     * @see org.apache.jmeter.visualizers.
>> > >>>> backend.BackendListenerClient#
>> > >>>> createSampleResult(org.apache.jmeter.samplers.SampleResult)
>> > >>>> +     */
>> > >>>> +    @Override
>> > >>>> +    public SampleResult
>createSampleResult(BackendListenerContext
>> > >>>> context, SampleResult result) {
>> > >>>> +        SampleResult sampleResult = (SampleResult)
>result.clone();
>> > >>>> +        return sampleResult;
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     *
>> > >>>> +     * @param sampleLabel
>> > >>>> +     * @return SamplerMetric
>> > >>>>
>> > >>>>  No description of the method and the parameters?
>> > >>>
>> > >>>  +     */
>> > >>>> +    protected SamplerMetric getSamplerMetric(String
>sampleLabel) {
>> > >>>> +        SamplerMetric samplerMetric = metricsPerSampler.get(
>> > >>>> sampleLabel);
>> > >>>> +        if(samplerMetric == null) {
>> > >>>> +            samplerMetric = new SamplerMetric();
>> > >>>> +            SamplerMetric oldValue =
>metricsPerSampler.putIfAbsent(
>> > >>>> sampleLabel,
>> > >>>> samplerMetric);
>> > >>>> +            if(oldValue != null ){
>> > >>>> +                samplerMetric = oldValue;
>> > >>>> +            }
>> > >>>> +        }
>> > >>>> +        return samplerMetric;
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     *
>> > >>>> +     * @return Map<String, SamplerMetric>
>> > >>>>
>> > >>>>  No description of the method and usage of forbidden
>characters :)
>> there
>> > >>> are still more than 800 warnings in the javadoc to prune, so
>don't
>> > >>> introduce new ones, please.
>> > >>>
>> > >>>  +     */
>> > >>>> +    protected Map<String, SamplerMetric>
>getMetricsPerSampler() {
>> > >>>> +        return metricsPerSampler;
>> > >>>> +    }
>> > >>>> +
>> > >>>> +}
>> > >>>>
>> > >>>> Propchange:
>> jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> > >>>> backend/AbstractBackendListenerClient.java
>> > >>>> ------------------------------------------------------------
>> > >>>> ------------------
>> > >>>>       svn:mime-type = text/plain
>> > >>>>
>> > >>>> Added:
>jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> > >>>> backend/BackendListener.java
>> > >>>> URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/
>> > >>>> org/apache/jmeter/visualizers/backend/BackendListener.java?
>> > >>>> rev=1641081&view=auto
>> > >>>> ============================================================
>> > >>>> ==================
>> > >>>> --- jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> > >>>> backend/BackendListener.java
>> > >>>> (added)
>> > >>>> +++ jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> > >>>> backend/BackendListener.java
>> > >>>> Sat Nov 22 15:36:37 2014
>> > >>>> @@ -0,0 +1,448 @@
>> > >>>> +/*
>> > >>>> + * Licensed to the Apache Software Foundation (ASF) under one
>or
>> more
>> > >>>> + * contributor license agreements.  See the NOTICE file
>distributed
>> > >>>> with
>> > >>>> + * this work for additional information regarding copyright
>> ownership.
>> > >>>> + * The ASF licenses this file to You under the Apache
>License,
>> Version
>> > >>>> 2.0
>> > >>>> + * (the "License"); you may not use this file except in
>compliance
>> with
>> > >>>> + * the License.  You may obtain a copy of the License at
>> > >>>> + *
>> > >>>> + *   http://www.apache.org/licenses/LICENSE-2.0
>> > >>>> + *
>> > >>>> + * Unless required by applicable law or agreed to in writing,
>> software
>> > >>>> + * distributed under the License is distributed on an "AS IS"
>> BASIS,
>> > >>>> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
>express or
>> > >>>> implied.
>> > >>>> + * See the License for the specific language governing
>permissions
>> and
>> > >>>> + * limitations under the License.
>> > >>>> + *
>> > >>>> + */
>> > >>>> +
>> > >>>> +package org.apache.jmeter.visualizers.backend;
>> > >>>> +
>> > >>>> +import java.io.Serializable;
>> > >>>> +import java.lang.reflect.Method;
>> > >>>> +import java.util.ArrayList;
>> > >>>> +import java.util.HashSet;
>> > >>>> +import java.util.List;
>> > >>>> +import java.util.Set;
>> > >>>> +import java.util.concurrent.ArrayBlockingQueue;
>> > >>>> +import java.util.concurrent.BlockingQueue;
>> > >>>> +import java.util.concurrent.locks.LockSupport;
>> > >>>> +
>> > >>>> +import org.apache.jmeter.config.Arguments;
>> > >>>> +import org.apache.jmeter.engine.util.NoThreadClone;
>> > >>>> +import
>org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
>> > >>>> +import org.apache.jmeter.samplers.Remoteable;
>> > >>>> +import org.apache.jmeter.samplers.SampleEvent;
>> > >>>> +import org.apache.jmeter.samplers.SampleListener;
>> > >>>> +import org.apache.jmeter.samplers.SampleResult;
>> > >>>> +import org.apache.jmeter.testelement.AbstractTestElement;
>> > >>>> +import org.apache.jmeter.testelement.TestElement;
>> > >>>> +import org.apache.jmeter.testelement.TestStateListener;
>> > >>>> +import
>org.apache.jmeter.testelement.property.TestElementProperty;
>> > >>>> +import org.apache.jorphan.logging.LoggingManager;
>> > >>>> +import org.apache.log.Logger;
>> > >>>> +
>> > >>>> +/**
>> > >>>> + * Async Listener that delegates SampleResult handling to
>> > >>>> implementations of {@link BackendListenerClient}
>> > >>>> + * @since 2.13
>> > >>>> + */
>> > >>>> +public class BackendListener extends AbstractTestElement
>> > >>>> +    implements Serializable, SampleListener,
>TestStateListener,
>> > >>>> NoThreadClone, Remoteable  {
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     *
>> > >>>> +     */
>> > >>>> +    private static final long serialVersionUID =
>> 8184103677832024335L;
>> > >>>> +
>> > >>>> +    private static final Logger log = LoggingManager.
>> > >>>> getLoggerForClass();
>> > >>>>
>> > >>>>  See naming comment of log from above
>> > >>>
>> > >>>  +
>> > >>>> +    /**
>> > >>>> +     * Set used to register instances which implement
>teardownTest.
>> > >>>> +     * This is used so that the BackendListenerClient can be
>> notified
>> > >>>> when the test ends.
>> > >>>> +     */
>> > >>>> +    private static final Set<BackendListener> TEAR_DOWN_SET =
>new
>> > >>>> HashSet<BackendListener>();
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Property key representing the classname of the
>> > >>>> BackendListenerClient to user.
>> > >>>> +     */
>> > >>>> +    public static final String CLASSNAME = "classname";
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Queue size
>> > >>>> +     */
>> > >>>> +    public static final String QUEUE_SIZE = "QUEUE_SIZE";
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Property key representing the arguments for the
>> > >>>> BackendListenerClient.
>> > >>>> +     */
>> > >>>> +    public static final String ARGUMENTS = "arguments";
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * The BackendListenerClient class used by this sampler.
>> > >>>> +     * Created by testStarted; copied to cloned instances.
>> > >>>> +     */
>> > >>>> +    private Class<?> javaClass;
>> > >>>>
>> > >>>>  Could probably named clientClass instead of javaClass, since
>we
>> already
>> > >>> know it is a java class.
>> > >>>
>> > >>>  +
>> > >>>> +    /**
>> > >>>> +     * If true, the BackendListenerClient class implements
>> > >>>> teardownTest.
>> > >>>> +     * Created by testStarted; copied to cloned instances.
>> > >>>> +     */
>> > >>>> +    private boolean isToBeRegistered;
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * The BackendListenerClient instance
>> > >>>> +     */
>> > >>>> +    private transient BackendListenerClient
>backendListenerClient =
>> > >>>> null;
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * The JavaSamplerContext instance used by this sampler
>to hold
>> > >>>> information
>> > >>>>
>> > >>>>  BackendListenerContext?
>> > >>>
>> > >>>  +     * related to the test run, such as the parameters
>specified
>> for
>> > >>>> the
>> > >>>> sampler
>> > >>>> +     * client.
>> > >>>> +     */
>> > >>>> +    private transient BackendListenerContext context = null;
>> > >>>> +
>> > >>>> +    private static final int DEFAULT_QUEUE_SIZE = 5000;
>> > >>>> +
>> > >>>> +    private transient BlockingQueue<SampleResult> queue; //
>> created by
>> > >>>> server in readResolve method
>> > >>>> +
>> > >>>> +    private transient long queueWaits; // how many times we
>had to
>> wait
>> > >>>> to queue a sample
>> > >>>> +
>> > >>>> +    private transient long queueWaitTime; // how long we had
>to
>> wait
>> > >>>> (nanoSeconds)
>> > >>>> +
>> > >>>> +    // Create unique object as marker for end of queue
>> > >>>> +    private transient static final SampleResult FINAL_EVENT =
>new
>> > >>>> SampleResult();
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Create a BackendListener.
>> > >>>> +     */
>> > >>>> +    public BackendListener() {
>> > >>>> +        setArguments(new Arguments());
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /*
>> > >>>> +     * Ensure that the required class variables are cloned,
>> > >>>> +     * as this is not currently done by the
>super-implementation.
>> > >>>> +     */
>> > >>>> +    @Override
>> > >>>> +    public Object clone() {
>> > >>>> +        BackendListener clone = (BackendListener)
>super.clone();
>> > >>>> +        clone.javaClass = this.javaClass;
>> > >>>> +        clone.isToBeRegistered = this.isToBeRegistered;
>> > >>>> +        return clone;
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    private void initClass() {
>> > >>>> +        String name = getClassname().trim();
>> > >>>> +        try {
>> > >>>> +            javaClass = Class.forName(name, false,
>> > >>>> Thread.currentThread().getContextClassLoader());
>> > >>>> +            Method method =
>javaClass.getMethod("teardownTest", new
>> > >>>> Class[]{BackendListenerContext.class});
>> > >>>> +            isToBeRegistered =
>!method.getDeclaringClass().equals(
>> > >>>> AbstractBackendListenerClient.class);
>> > >>>> +            log.info("Created class: " + name + ". Uses
>> teardownTest:
>> > >>>> "
>> > >>>> + isToBeRegistered);
>> > >>>> +        } catch (Exception e) {
>> > >>>> +            log.error(whoAmI() + "\tException initialising: "
>+
>> name,
>> > >>>> e);
>> > >>>> +        }
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Retrieves reference to BackendListenerClient.
>> > >>>> +     *
>> > >>>> +     * Convience method used to check for null reference
>without
>> > >>>> actually
>> > >>>> +     * creating a BackendListenerClient
>> > >>>> +     *
>> > >>>> +     * @return reference to BackendListenerClient NOTUSED
>private
>> > >>>> BackendListenerClient
>> > >>>> +     *         retrieveJavaClient() { return javaClient; }
>> > >>>> +     */
>> > >>>>
>> > >>>>  Javadoc for non-existant method?
>> > >>>
>> > >>>  +
>> > >>>> +    /**
>> > >>>> +     * Generate a String identifier of this instance for
>debugging
>> > >>>> purposes.
>> > >>>> +     *
>> > >>>> +     * @return a String identifier for this sampler instance
>> > >>>> +     */
>> > >>>> +    private String whoAmI() {
>> > >>>> +        StringBuilder sb = new StringBuilder();
>> > >>>> +        sb.append(Thread.currentThread().getName());
>> > >>>> +        sb.append("@");
>> > >>>> +        sb.append(Integer.toHexString(hashCode()));
>> > >>>> +        sb.append("-");
>> > >>>> +        sb.append(getName());
>> > >>>> +        return sb.toString();
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    // TestStateListener implementation
>> > >>>> +    /* Implements TestStateListener.testStarted() */
>> > >>>> +    @Override
>> > >>>> +    public void testStarted() {
>> > >>>> +        testStarted("");
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /* Implements TestStateListener.testStarted(String) */
>> > >>>> +    @Override
>> > >>>> +    public void testStarted(String host) {
>> > >>>> +        log.debug(whoAmI() + "\ttestStarted(" + host + ")");
>> > >>>>
>> > >>>>  Maybe use isDebugEnabled to guard whoAmI() call?
>> > >>>
>> > >>>  +        queue = new
>> ArrayBlockingQueue<SampleResult>(getQueueSize());
>> > >>>> +        initClass();
>> > >>>> +        queueWaits=0L;
>> > >>>> +        queueWaitTime=0L;
>> > >>>> +        log.info(getName()+":Starting worker with
>> class:"+javaClass +"
>> > >>>> and queue capacity:"+getQueueSize());
>> > >>>> +
>> > >>>> +        backendListenerClient =
>createBackendListenerClientImp
>> > >>>> l(javaClass);
>> > >>>> +        context = new BackendListenerContext((
>> > >>>> Arguments)getArguments().
>> > >>>> clone());
>> > >>>> +        if(isToBeRegistered) {
>> > >>>>
>> > >>>>  space after if and before (?
>> > >>>
>> > >>>  +            TEAR_DOWN_SET.add(this);
>> > >>>> +        }
>> > >>>> +        try {
>> > >>>> +            backendListenerClient.setupTest(context);
>> > >>>> +        } catch (Exception e) {
>> > >>>> +            throw new java.lang.IllegalStateException("Failed
>> calling
>> > >>>> setupTest", e);
>> > >>>> +        }
>> > >>>> +
>> > >>>> +        Worker worker = new Worker(javaClass,
>> backendListenerClient,
>> > >>>> (Arguments) getArguments().clone(), queue);
>> > >>>> +        worker.setDaemon(true);
>> > >>>> +        worker.start();
>> > >>>>
>> > >>>>  Don't we want to stop worker after we're done with one test?
>> > >>>
>> > >>>  +        log.info(getName()+":Started  worker with
>> class:"+javaClass);
>> > >>>>
>> > >>>>  Spaces after :?
>> > >>>
>> > >>>  +
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /* (non-Javadoc)
>> > >>>> +     * @see
>> org.apache.jmeter.samplers.SampleListener#sampleOccurred(
>> > >>>> org.apache.jmeter.samplers.SampleEvent)
>> > >>>> +     */
>> > >>>> +    @Override
>> > >>>> +    public void sampleOccurred(SampleEvent e) {
>> > >>>>
>> > >>>>  Longer name then 'e'? I expect e to be an exception, not an
>event.
>> > >>>
>> > >>>  +        Arguments args = getArguments();
>> > >>>> +        context = new BackendListenerContext(args);
>> > >>>> +
>> > >>>> +        SampleResult sr = backendListenerClient.
>> > >>>> createSampleResult(context,
>> > >>>> e.getResult());
>> > >>>> +        try {
>> > >>>> +            if (!queue.offer(sr)){ // we failed to add the
>element
>> > >>>> first
>> > >>>> time
>> > >>>> +                queueWaits++;
>> > >>>> +                long t1 = System.nanoTime();
>> > >>>> +                queue.put(sr);
>> > >>>> +                long t2 = System.nanoTime();
>> > >>>> +                queueWaitTime += t2-t1;
>> > >>>>
>> > >>>>  Will sampleOccurred be called concurrently? If so, than
>> queueWaitTime
>> > >>> +=
>> > >>> will not be correct.
>> > >>>
>> > >>>  +            }
>> > >>>> +        } catch (Exception err) {
>> > >>>> +            log.error("sampleOccurred, failed to queue the
>sample",
>> > >>>> err);
>> > >>>> +        }
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    private static final class Worker extends Thread {
>> > >>>> +
>> > >>>> +        private final BlockingQueue<SampleResult> queue;
>> > >>>> +        private final BackendListenerContext context;
>> > >>>> +        private final BackendListenerClient
>backendListenerClient;
>> > >>>> +        private Worker(Class<?> javaClass,
>BackendListenerClient
>> > >>>> backendListenerClient, Arguments arguments,
>> BlockingQueue<SampleResult>
>> > >>>> q){
>> > >>>>
>> > >>>>  Same naming argument as above. clientclass instead of
>javaClass?
>> > >>>
>> > >>>  +            queue = q;
>> > >>>> +            // Allow BackendListenerClient implementations to
>get
>> > >>>> access
>> > >>>> to test element name
>> > >>>> +            arguments.addArgument(TestElement.NAME,
>getName());
>> > >>>> +            context = new BackendListenerContext(arguments);
>> > >>>> +            this.backendListenerClient =
>backendListenerClient;
>> > >>>> +        }
>> > >>>> +
>> > >>>> +
>> > >>>> +        @Override
>> > >>>> +        public void run() {
>> > >>>> +            boolean isDebugEnabled = log.isDebugEnabled();
>> > >>>> +            List<SampleResult> l = new
>> ArrayList<SampleResult>(queue.
>> > >>>> size());
>> > >>>>
>> > >>>>  samples instead of l?
>> > >>>
>> > >>>  +            try {
>> > >>>> +                boolean eof = false;
>> > >>>>
>> > >>>>  endOfLoop?
>> > >>>
>> > >>>  +                while (!eof) {
>> > >>>> +                    if(isDebugEnabled) {
>> > >>>> +                        log.debug("Thread:"+Thread.
>> > >>>> currentThread().getName()+"
>> > >>>> taking SampleResult from queue:"+queue.size());
>> > >>>> +                    }
>> > >>>> +                    SampleResult e = queue.take();
>> > >>>>
>> > >>>>  Could be named result, or sample instead of e
>> > >>>
>> > >>>  +                    if(isDebugEnabled) {
>> > >>>> +                        log.debug("Thread:"+Thread.
>> > >>>> currentThread().getName()+"
>> > >>>> took SampleResult:"+e+", isFinal:" + (e==FINAL_EVENT));
>> > >>>> +                    }
>> > >>>> +                    while (!(eof = (e == FINAL_EVENT)) && e
>!=
>> null ) {
>> > >>>> // try to process as many as possible
>> > >>>> +                        l.add(e);
>> > >>>> +                        if(isDebugEnabled) {
>> > >>>> +                            log.debug("Thread:"+Thread.
>> > >>>> currentThread().getName()+"
>> > >>>> polling from queue:"+queue.size());
>> > >>>> +                        }
>> > >>>> +                        e = queue.poll(); // returns null if
>> nothing on
>> > >>>> queue currently
>> > >>>> +                        if(isDebugEnabled) {
>> > >>>> +                            log.debug("Thread:"+Thread.
>> > >>>> currentThread().getName()+"
>> > >>>> took from queue:"+e+", isFinal:" + (e==FINAL_EVENT));
>> > >>>> +                        }
>> > >>>> +                    }
>> > >>>> +                    if(isDebugEnabled) {
>> > >>>> +                        log.debug("Thread:"+Thread.
>> > >>>> currentThread().getName()+
>> > >>>> +                                " exiting with FINAL
>EVENT:"+(e ==
>> > >>>> FINAL_EVENT)
>> > >>>> +                                +", null:" + (e==null));
>> > >>>> +                    }
>> > >>>> +                    int size = l.size();
>> > >>>>
>> > >>>>  No need for a temporary variable.
>> > >>>
>> > >>>  +                    if (size > 0) {
>> > >>>> +
>> backendListenerClient.handleSampleResults(l,
>> > >>>> context);
>> > >>>> +                        l.clear();
>> > >>>> +                    }
>> > >>>> +                    if(!eof) {
>> > >>>> +                        LockSupport.parkNanos(100);
>> > >>>> +                    }
>> > >>>> +                }
>> > >>>> +            } catch (InterruptedException e) {
>> > >>>> +                // NOOP
>> > >>>> +            }
>> > >>>> +            // We may have been interrupted
>> > >>>> +            int size = l.size();
>> > >>>> +            if (size > 0) {
>> > >>>> +                backendListenerClient.handleSampleResults(l,
>> context);
>> > >>>> +                l.clear();
>> > >>>> +            }
>> > >>>>
>> > >>>>  Same code as a few lines above, could be factored out into a
>method
>> > >>> handleSamples(l, context)
>> > >>>
>> > >>>  +            log.info("Worker ended");
>> > >>>> +        }
>> > >>>> +    }
>> > >>>> +
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Returns reference to
><code>BackendListenerClient</code>.
>> > >>>>
>> > >>>>  Could use a {@link...}
>> > >>>
>> > >>>  +     *
>> > >>>> +     *
>> > >>>> +     * @return BackendListenerClient reference.
>> > >>>> +     */
>> > >>>> +    static BackendListenerClient
>createBackendListenerClientImp
>> > >>>> l(Class<?>
>> > >>>> javaClass) {
>> > >>>> +        if (javaClass == null) { // failed to initialise the
>class
>> > >>>> +            return new ErrorBackendListenerClient();
>> > >>>> +        }
>> > >>>> +        BackendListenerClient client;
>> > >>>> +        try {
>> > >>>> +            client = (BackendListenerClient)
>> javaClass.newInstance();
>> > >>>> +        } catch (Exception e) {
>> > >>>> +            log.error("Exception creating: " + javaClass, e);
>> > >>>> +            client = new ErrorBackendListenerClient();
>> > >>>> +        }
>> > >>>> +        return client;
>> > >>>>
>> > >>>>  I would return newInstance() in try Block and return new
>Error.. in
>> > >>> catch
>> > >>> Block. javaClass -> clientClass
>> > >>>
>> > >>>  +    }
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Method called at the end of the test. This is called
>only
>> on one
>> > >>>> instance
>> > >>>> +     * of BackendListener. This method will loop through all
>of the
>> > >>>> other
>> > >>>> +     * BackendListenerClients which have been registered
>> (automatically
>> > >>>> in the
>> > >>>> +     * constructor) and notify them that the test has ended,
>> allowing
>> > >>>> the
>> > >>>> +     * BackendListenerClients to cleanup.
>> > >>>> +     */
>> > >>>> +    @Override
>> > >>>> +    public void testEnded() {
>> > >>>> +        try {
>> > >>>> +            queue.put(FINAL_EVENT);
>> > >>>> +        } catch (Exception ex) {
>> > >>>> +            log.warn("testEnded() with
>exception:"+ex.getMessage(),
>> > >>>> ex);
>> > >>>> +        }
>> > >>>> +        if (queueWaits > 0) {
>> > >>>> +            log.warn("QueueWaits: "+queueWaits+";
>QueueWaitTime:
>> > >>>> "+queueWaitTime+" (nanoseconds), you may need to increase
>queue
>> > >>>> capacity,
>> > >>>> see property 'backend_queue_capacity'");
>> > >>>> +        }
>> > >>>> +        synchronized (TEAR_DOWN_SET) {
>> > >>>> +            for (BackendListener backendListener :
>TEAR_DOWN_SET) {
>> > >>>> +                BackendListenerClient client =
>backendListener.
>> > >>>> backendListenerClient;
>> > >>>> +                if (client != null) {
>> > >>>> +                    try {
>> > >>>> +
>> client.teardownTest(backendListener.context);
>> > >>>> +                    } catch (Exception e) {
>> > >>>> +                        throw new java.lang.
>> > >>>> IllegalStateException("Failed
>> > >>>> calling teardownTest", e);
>> > >>>>
>> > >>>>  If we throw an exception here, we will not try every client.
>> > >>>
>> > >>>  +                    }
>> > >>>> +                }
>> > >>>> +            }
>> > >>>> +            TEAR_DOWN_SET.clear();
>> > >>>> +        }
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /* Implements TestStateListener.testEnded(String) */
>> > >>>> +    @Override
>> > >>>> +    public void testEnded(String host) {
>> > >>>> +        testEnded();
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * A {@link BackendListenerClient} implementation used
>for
>> error
>> > >>>> handling. If an
>> > >>>> +     * error occurs while creating the real
>BackendListenerClient
>> > >>>> object, it is
>> > >>>> +     * replaced with an instance of this class. Each time a
>sample
>> > >>>> occurs with
>> > >>>> +     * this class, the result is marked as a failure so the
>user
>> can
>> > >>>> see
>> > >>>> that
>> > >>>> +     * the test failed.
>> > >>>> +     */
>> > >>>> +    static class ErrorBackendListenerClient extends
>> > >>>> AbstractBackendListenerClient {
>> > >>>> +        /**
>> > >>>> +         * Return SampleResult with data on error.
>> > >>>> +         *
>> > >>>> +         * @see
>BackendListenerClient#runTest(JavaSamplerContext)
>> > >>>> +         */
>> > >>>> +        @Override
>> > >>>> +        public void handleSampleResults(List<SampleResult>
>> > >>>> sampleResults, BackendListenerContext context) {
>> > >>>> +           
>log.warn("ErrorBackendListenerClient#handleSampleResult
>> > >>>> called, noop");
>> > >>>> +            Thread.yield();
>> > >>>> +        }
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /* (non-Javadoc)
>> > >>>> +     * @see
>> org.apache.jmeter.samplers.SampleListener#sampleStarted(
>> > >>>> org.apache.jmeter.samplers.SampleEvent)
>> > >>>> +     */
>> > >>>> +    @Override
>> > >>>> +    public void sampleStarted(SampleEvent e) {
>> > >>>> +        // NOOP
>> > >>>> +
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /* (non-Javadoc)
>> > >>>> +     * @see
>> org.apache.jmeter.samplers.SampleListener#sampleStopped(
>> > >>>> org.apache.jmeter.samplers.SampleEvent)
>> > >>>> +     */
>> > >>>> +    @Override
>> > >>>> +    public void sampleStopped(SampleEvent e) {
>> > >>>> +        // NOOP
>> > >>>> +
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Set the arguments (parameters) for the
>> BackendListenerClient to
>> > >>>> be executed
>> > >>>> +     * with.
>> > >>>> +     *
>> > >>>> +     * @param args
>> > >>>> +     *            the new arguments. These replace any
>existing
>> > >>>> arguments.
>> > >>>> +     */
>> > >>>> +    public void setArguments(Arguments args) {
>> > >>>> +        setProperty(new TestElementProperty(ARGUMENTS,
>args));
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Get the arguments (parameters) for the
>> BackendListenerClient to
>> > >>>> be executed
>> > >>>> +     * with.
>> > >>>> +     *
>> > >>>> +     * @return the arguments
>> > >>>> +     */
>> > >>>> +    public Arguments getArguments() {
>> > >>>> +        return (Arguments)
>getProperty(ARGUMENTS).getObjectValue();
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Sets the Classname of the BackendListenerClient object
>> > >>>> +     *
>> > >>>> +     * @param classname
>> > >>>> +     *            the new Classname value
>> > >>>> +     */
>> > >>>> +    public void setClassname(String classname) {
>> > >>>> +        setProperty(CLASSNAME, classname);
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Gets the Classname of the BackendListenerClient object
>> > >>>> +     *
>> > >>>> +     * @return the Classname value
>> > >>>> +     */
>> > >>>> +    public String getClassname() {
>> > >>>> +        return getPropertyAsString(CLASSNAME);
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Sets the queue size
>> > >>>> +     *
>> > >>>> +     * @param queueSize
>> > >>>> +     *
>> > >>>> +     */
>> > >>>> +    public void setQueueSize(int queueSize) {
>> > >>>> +        setProperty(QUEUE_SIZE, queueSize,
>DEFAULT_QUEUE_SIZE);
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Gets the queue size
>> > >>>> +     *
>> > >>>> +     * @return int queueSize
>> > >>>> +     */
>> > >>>> +    public int getQueueSize() {
>> > >>>> +        return getPropertyAsInt(QUEUE_SIZE,
>DEFAULT_QUEUE_SIZE);
>> > >>>> +    }
>> > >>>> +}
>> > >>>>
>> > >>>> Propchange:
>> jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> > >>>> backend/BackendListener.java
>> > >>>> ------------------------------------------------------------
>> > >>>> ------------------
>> > >>>>       svn:mime-type = text/plain
>> > >>>>
>> > >>>> Added:
>jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> > >>>> backend/BackendListenerClient.java
>> > >>>> URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/
>> > >>>> org/apache/jmeter/visualizers/backend/BackendListenerClient.
>> > >>>> java?rev=1641081&view=auto
>> > >>>> ============================================================
>> > >>>> ==================
>> > >>>> --- jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> > >>>> backend/BackendListenerClient.java (added)
>> > >>>> +++ jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> > >>>> backend/BackendListenerClient.java Sat Nov 22 15:36:37 2014
>> > >>>> @@ -0,0 +1,128 @@
>> > >>>> +/*
>> > >>>> + * Licensed to the Apache Software Foundation (ASF) under one
>or
>> more
>> > >>>> + * contributor license agreements.  See the NOTICE file
>distributed
>> > >>>> with
>> > >>>> + * this work for additional information regarding copyright
>> ownership.
>> > >>>> + * The ASF licenses this file to You under the Apache
>License,
>> Version
>> > >>>> 2.0
>> > >>>> + * (the "License"); you may not use this file except in
>compliance
>> with
>> > >>>> + * the License.  You may obtain a copy of the License at
>> > >>>> + *
>> > >>>> + *   http://www.apache.org/licenses/LICENSE-2.0
>> > >>>> + *
>> > >>>> + * Unless required by applicable law or agreed to in writing,
>> software
>> > >>>> + * distributed under the License is distributed on an "AS IS"
>> BASIS,
>> > >>>> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
>express or
>> > >>>> implied.
>> > >>>> + * See the License for the specific language governing
>permissions
>> and
>> > >>>> + * limitations under the License.
>> > >>>> + *
>> > >>>> + */
>> > >>>> +
>> > >>>> +package org.apache.jmeter.visualizers.backend;
>> > >>>> +
>> > >>>> +import java.util.List;
>> > >>>> +
>> > >>>> +import org.apache.jmeter.config.Arguments;
>> > >>>> +import org.apache.jmeter.samplers.SampleResult;
>> > >>>> +
>> > >>>> +/**
>> > >>>> + * This interface defines the interactions between the
>> BackendListener
>> > >>>> and external
>> > >>>> + * Java programs which can be executed by JMeter. Any Java
>class
>> which
>> > >>>> wants to
>> > >>>> + * be executed as a JMeter test must implement this interface
>> (either
>> > >>>> directly
>> > >>>> + * or indirectly through AbstractBackendListenerClient).
>> > >>>> + * <p>
>> > >>>> + * JMeter will create one instance of a BackendListenerClient
>> > >>>> implementation for
>> > >>>> + * each user/thread in the test. Additional instances may be
>> created
>> > >>>> for
>> > >>>> + * internal use by JMeter (for example, to find out what
>> parameters are
>> > >>>> + * supported by the client).
>> > >>>> + * <p>
>> > >>>> + * When the test is started, setupTest() will be called on
>each
>> > >>>> thread's
>> > >>>> + * BackendListenerClient instance to initialize the client.
>Then
>> > >>>> handleSampleResult() will be
>> > >>>> + * called for each SampleResult notification. Finally,
>> teardownTest()
>> > >>>> will be called
>> > >>>> + * to allow the client to do any necessary clean-up.
>> > >>>> + * <p>
>> > >>>> + * The JMeter BackendListener GUI allows a list of parameters
>to be
>> > >>>> defined for the
>> > >>>> + * test. These are passed to the various test methods through
>the
>> > >>>> + * {@link BackendListenerContext}. A list of default
>parameters
>> can be
>> > >>>> defined
>> > >>>> + * through the getDefaultParameters() method. These
>parameters and
>> any
>> > >>>> default
>> > >>>> + * values associated with them will be shown in the GUI.
>Users can
>> add
>> > >>>> other
>> > >>>> + * parameters as well.
>> > >>>> + * <p>
>> > >>>> + * When possible, Listeners should extend {@link
>> > >>>> AbstractBackendListenerClient
>> > >>>> + * AbstractBackendListenerClient} rather than implementing
>> > >>>> BackendListenerClient
>> > >>>> + * directly. This should protect your tests from future
>changes to
>> the
>> > >>>> + * interface. While it may be necessary to make changes to
>the
>> > >>>> BackendListenerClient
>> > >>>> + * interface from time to time (therefore requiring changes
>to any
>> > >>>> + * implementations of this interface), we intend to make this
>> abstract
>> > >>>> class
>> > >>>> + * provide reasonable default implementations of any new
>methods so
>> > >>>> that
>> > >>>> + * subclasses do not necessarily need to be updated for new
>> versions.
>> > >>>> + * Implementing BackendListenerClient directly will continue
>to be
>> > >>>> supported for
>> > >>>> + * cases where extending this class is not possible (for
>example,
>> when
>> > >>>> the
>> > >>>> + * client class is already a subclass of some other class).
>> > >>>> + *
>> > >>>> + * @since 2.13
>> > >>>> + */
>> > >>>> +public interface BackendListenerClient {
>> > >>>> +    /**
>> > >>>> +     * Do any initialization required by this client. It is
>> generally
>> > >>>> +     * recommended to do any initialization such as getting
>> parameter
>> > >>>> values in
>> > >>>> +     * the setupTest method rather than the runTest method in
>> order to
>> > >>>> add as
>> > >>>> +     * little overhead as possible to the test.
>> > >>>> +     *
>> > >>>> +     * @param context
>> > >>>> +     *            the context to run with. This provides
>access to
>> > >>>> +     *            initialization parameters.
>> > >>>> +     */
>> > >>>> +    void setupTest(BackendListenerContext context) throws
>> Exception;
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Perform a single sample for each iteration. This
>method
>> returns
>> > >>>> a
>> > >>>> +     * <code>SampleResult</code> object.
><code>SampleResult</code>
>> has
>> > >>>> many
>> > >>>> +     * fields which can be used. At a minimum, the test
>should use
>> > >>>> +     * <code>SampleResult.sampleStart</code> and
>> > >>>> +     * <code>SampleResult.sampleEnd</code>to set the time
>that the
>> > >>>> test
>> > >>>>
>> > >>>>  use {@link..} instead of <code>..?
>> > >>>
>> > >>>  +     * required to execute. It is also a good idea to set the
>> > >>>> sampleLabel and
>> > >>>> +     * the successful flag.
>> > >>>> +     *
>> > >>>> +     * @see
>org.apache.jmeter.samplers.SampleResult#sampleStart()
>> > >>>> +     * @see
>org.apache.jmeter.samplers.SampleResult#sampleEnd()
>> > >>>> +     * @see
>org.apache.jmeter.samplers.SampleResult#setSuccessful(
>> > >>>> boolean)
>> > >>>> +     * @see
>org.apache.jmeter.samplers.SampleResult#setSampleLabel(
>> > >>>> String)
>> > >>>> +     *
>> > >>>> +     * @param context
>> > >>>> +     *            the context to run with. This provides
>access to
>> > >>>> +     *            initialization parameters.
>> > >>>> +     *
>> > >>>> +     */
>> > >>>> +    void handleSampleResults(List<SampleResult>
>sampleResults,
>> > >>>> BackendListenerContext context);
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Do any clean-up required by this test at the end of a
>test
>> run.
>> > >>>> +     *
>> > >>>> +     * @param context
>> > >>>> +     *            the context to run with. This provides
>access to
>> > >>>> +     *            initialization parameters.
>> > >>>> +     */
>> > >>>> +    void teardownTest(BackendListenerContext context) throws
>> > >>>> Exception;
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Provide a list of parameters which this test supports.
>Any
>> > >>>> parameter
>> > >>>> +     * names and associated values returned by this method
>will
>> appear
>> > >>>> in the
>> > >>>> +     * GUI by default so the user doesn't have to remember
>the
>> exact
>> > >>>> names. The
>> > >>>> +     * user can add other parameters which are not listed
>here. If
>> this
>> > >>>> method
>> > >>>> +     * returns null then no parameters will be listed. If the
>> value for
>> > >>>> some
>> > >>>> +     * parameter is null then that parameter will be listed
>in the
>> GUI
>> > >>>> with an
>> > >>>> +     * empty value.
>> > >>>> +     *
>> > >>>> +     * @return a specification of the parameters used by this
>test
>> > >>>> which
>> > >>>> should
>> > >>>> +     *         be listed in the GUI, or null if no parameters
>> should be
>> > >>>> listed.
>> > >>>> +     */
>> > >>>> +    Arguments getDefaultParameters();
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     *
>> > >>>> +     * @param context
>> > >>>> +     * @param result
>> > >>>> +     * @return
>> > >>>> +     */
>> > >>>> +    SampleResult createSampleResult(
>> > >>>> +            BackendListenerContext context, SampleResult
>result);
>> > >>>> +}
>> > >>>>
>> > >>>> Propchange:
>> jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> > >>>> backend/BackendListenerClient.java
>> > >>>> ------------------------------------------------------------
>> > >>>> ------------------
>> > >>>>       svn:mime-type = text/plain
>> > >>>>
>> > >>>> Added:
>jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> > >>>> backend/
>> > >>>> BackendListenerContext.java
>> > >>>> URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/
>> > >>>>
>org/apache/jmeter/visualizers/backend/BackendListenerContext.java?
>> > >>>> rev=1641081&view=auto
>> > >>>> ============================================================
>> > >>>> ==================
>> > >>>> ---
>> jmeter/trunk/src/components/org/apache/jmeter/visualizers/backend/
>> > >>>> BackendListenerContext.java
>> > >>>> (added)
>> > >>>> +++
>> jmeter/trunk/src/components/org/apache/jmeter/visualizers/backend/
>> > >>>> BackendListenerContext.java
>> > >>>> Sat Nov 22 15:36:37 2014
>> > >>>> @@ -0,0 +1,237 @@
>> > >>>> +/*
>> > >>>> +
>> > >>>> + * Licensed to the Apache Software Foundation (ASF) under one
>or
>> more
>> > >>>> + * contributor license agreements.  See the NOTICE file
>distributed
>> > >>>> with
>> > >>>> + * this work for additional information regarding copyright
>> ownership.
>> > >>>> + * The ASF licenses this file to You under the Apache
>License,
>> Version
>> > >>>> 2.0
>> > >>>> + * (the "License"); you may not use this file except in
>compliance
>> with
>> > >>>> + * the License.  You may obtain a copy of the License at
>> > >>>> + *
>> > >>>> + *   http://www.apache.org/licenses/LICENSE-2.0
>> > >>>> + *
>> > >>>> + * Unless required by applicable law or agreed to in writing,
>> software
>> > >>>> + * distributed under the License is distributed on an "AS IS"
>> BASIS,
>> > >>>> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
>express or
>> > >>>> implied.
>> > >>>> + * See the License for the specific language governing
>permissions
>> and
>> > >>>> + * limitations under the License.
>> > >>>> + *
>> > >>>> + */
>> > >>>> +
>> > >>>> +package org.apache.jmeter.visualizers.backend;
>> > >>>> +
>> > >>>> +import java.util.Iterator;
>> > >>>> +import java.util.Map;
>> > >>>> +
>> > >>>> +import org.apache.jmeter.config.Arguments;
>> > >>>> +import org.apache.jorphan.logging.LoggingManager;
>> > >>>> +import org.apache.log.Logger;
>> > >>>> +
>> > >>>> +/**
>> > >>>> + * BackendListenerContext is used to provide context
>information
>> to a
>> > >>>> + * BackendListenerClient implementation. This currently
>consists
>> of the
>> > >>>> + * initialization parameters which were specified in the GUI.
>> > >>>> + * @since 2.13
>> > >>>> + */
>> > >>>> +public class BackendListenerContext {
>> > >>>> +    /*
>> > >>>> +     * Implementation notes:
>> > >>>> +     *
>> > >>>> +     * All of the methods in this class are currently
>read-only. If
>> > >>>> update
>> > >>>> +     * methods are included in the future, they should be
>defined
>> so
>> > >>>> that a
>> > >>>> +     * single instance of BackendListenerContext can be
>associated
>> with
>> > >>>> each thread.
>> > >>>> +     * Therefore, no synchronization should be needed. The
>same
>> > >>>> instance
>> > >>>> should
>> > >>>> +     * be used for the call to setupTest, all calls to
>runTest,
>> and the
>> > >>>> call to
>> > >>>> +     * teardownTest.
>> > >>>> +     */
>> > >>>> +
>> > >>>> +    /** Logging */
>> > >>>> +    private static final Logger log = LoggingManager.
>> > >>>> getLoggerForClass();
>> > >>>>
>> > >>>>  See naming comments for logger above
>> > >>>
>> > >>>  +
>> > >>>> +    /**
>> > >>>> +     * Map containing the initialization parameters for the
>> > >>>> BackendListenerClient.
>> > >>>> +     */
>> > >>>> +    private final Map<String, String> params;
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     *
>> > >>>> +     * @param args
>> > >>>> +     *            the initialization parameters.
>> > >>>> +     */
>> > >>>> +    public BackendListenerContext(Arguments args) {
>> > >>>> +        this.params = args.getArgumentsAsMap();
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Determine whether or not a value has been specified
>for the
>> > >>>> parameter
>> > >>>> +     * with this name.
>> > >>>> +     *
>> > >>>> +     * @param name
>> > >>>> +     *            the name of the parameter to test
>> > >>>> +     * @return true if the parameter value has been
>specified,
>> false
>> > >>>> otherwise.
>> > >>>> +     */
>> > >>>> +    public boolean containsParameter(String name) {
>> > >>>>
>> > >>>>  hasParameter instead of containsParameter?
>> > >>>
>> > >>>  +        return params.containsKey(name);
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Get an iterator of the parameter names. Each entry in
>the
>> > >>>> Iterator is a
>> > >>>> +     * String.
>> > >>>> +     *
>> > >>>> +     * @return an Iterator of Strings listing the names of
>the
>> > >>>> parameters which
>> > >>>> +     *         have been specified for this test.
>> > >>>> +     */
>> > >>>> +    public Iterator<String> getParameterNamesIterator() {
>> > >>>> +        return params.keySet().iterator();
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Get the value of a specific parameter as a String, or
>null
>> if
>> > >>>> the
>> > >>>> value
>> > >>>> +     * was not specified.
>> > >>>> +     *
>> > >>>> +     * @param name
>> > >>>> +     *            the name of the parameter whose value
>should be
>> > >>>> retrieved
>> > >>>> +     * @return the value of the parameter, or null if the
>value
>> was not
>> > >>>> +     *         specified
>> > >>>> +     */
>> > >>>> +    public String getParameter(String name) {
>> > >>>> +        return getParameter(name, null);
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Get the value of a specified parameter as a String, or
>> return
>> > >>>> the
>> > >>>> +     * specified default value if the value was not
>specified.
>> > >>>> +     *
>> > >>>> +     * @param name
>> > >>>> +     *            the name of the parameter whose value
>should be
>> > >>>> retrieved
>> > >>>> +     * @param defaultValue
>> > >>>> +     *            the default value to return if the value of
>this
>> > >>>> parameter was
>> > >>>> +     *            not specified
>> > >>>> +     * @return the value of the parameter, or the default
>value if
>> the
>> > >>>> parameter
>> > >>>> +     *         was not specified
>> > >>>> +     */
>> > >>>> +    public String getParameter(String name, String
>defaultValue) {
>> > >>>> +        if (params == null || !params.containsKey(name)) {
>> > >>>> +            return defaultValue;
>> > >>>> +        }
>> > >>>> +        return params.get(name);
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Get the value of a specified parameter as an integer.
>An
>> > >>>> exception will
>> > >>>> +     * be thrown if the parameter is not specified or if it
>is not
>> an
>> > >>>> integer.
>> > >>>> +     * The value may be specified in decimal, hexadecimal, or
>> octal, as
>> > >>>> defined
>> > >>>> +     * by Integer.decode().
>> > >>>> +     *
>> > >>>> +     * @param name
>> > >>>> +     *            the name of the parameter whose value
>should be
>> > >>>> retrieved
>> > >>>> +     * @return the value of the parameter
>> > >>>> +     *
>> > >>>> +     * @throws NumberFormatException
>> > >>>> +     *             if the parameter is not specified or is
>not an
>> > >>>> integer
>> > >>>> +     *
>> > >>>> +     * @see java.lang.Integer#decode(java.lang.String)
>> > >>>> +     */
>> > >>>> +    public int getIntParameter(String name) throws
>> > >>>> NumberFormatException
>> > >>>> {
>> > >>>> +        if (params == null || !params.containsKey(name)) {
>> > >>>> +            throw new NumberFormatException("No value for
>parameter
>> > >>>> named '" + name + "'.");
>> > >>>>
>> > >>>>  I would expect an IllegalArgumentException, if no parameter
>of that
>> > >>> name
>> > >>> is found
>> > >>>
>> > >>>  +        }
>> > >>>> +
>> > >>>> +        return Integer.decode(params.get(name)).intValue();
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Get the value of a specified parameter as an integer,
>or
>> return
>> > >>>> the
>> > >>>> +     * specified default value if the value was not specified
>or
>> is not
>> > >>>> an
>> > >>>> +     * integer. A warning will be logged if the value is not
>an
>> > >>>> integer.
>> > >>>> The
>> > >>>> +     * value may be specified in decimal, hexadecimal, or
>octal, as
>> > >>>> defined by
>> > >>>> +     * Integer.decode().
>> > >>>> +     *
>> > >>>> +     * @param name
>> > >>>> +     *            the name of the parameter whose value
>should be
>> > >>>> retrieved
>> > >>>> +     * @param defaultValue
>> > >>>> +     *            the default value to return if the value of
>this
>> > >>>> parameter was
>> > >>>> +     *            not specified
>> > >>>> +     * @return the value of the parameter, or the default
>value if
>> the
>> > >>>> parameter
>> > >>>> +     *         was not specified
>> > >>>> +     *
>> > >>>> +     * @see java.lang.Integer#decode(java.lang.String)
>> > >>>> +     */
>> > >>>> +    public int getIntParameter(String name, int defaultValue)
>{
>> > >>>> +        if (params == null || !params.containsKey(name)) {
>> > >>>> +            return defaultValue;
>> > >>>> +        }
>> > >>>> +
>> > >>>> +        try {
>> > >>>> +            return
>Integer.decode(params.get(name)).intValue();
>> > >>>> +        } catch (NumberFormatException e) {
>> > >>>> +            log.warn("Value for parameter '" + name + "' not
>an
>> > >>>> integer:
>> > >>>> '" + params.get(name) + "'.  Using default: '"
>> > >>>> +                    + defaultValue + "'.", e);
>> > >>>> +            return defaultValue;
>> > >>>> +        }
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Get the value of a specified parameter as a long. An
>> exception
>> > >>>> will be
>> > >>>> +     * thrown if the parameter is not specified or if it is
>not a
>> long.
>> > >>>> The
>> > >>>> +     * value may be specified in decimal, hexadecimal, or
>octal, as
>> > >>>> defined by
>> > >>>> +     * Long.decode().
>> > >>>> +     *
>> > >>>> +     * @param name
>> > >>>> +     *            the name of the parameter whose value
>should be
>> > >>>> retrieved
>> > >>>> +     * @return the value of the parameter
>> > >>>> +     *
>> > >>>> +     * @throws NumberFormatException
>> > >>>> +     *             if the parameter is not specified or is
>not a
>> long
>> > >>>> +     *
>> > >>>> +     * @see Long#decode(String)
>> > >>>> +     */
>> > >>>> +    public long getLongParameter(String name) throws
>> > >>>> NumberFormatException {
>> > >>>> +        if (params == null || !params.containsKey(name)) {
>> > >>>> +            throw new NumberFormatException("No value for
>parameter
>> > >>>> named '" + name + "'.");
>> > >>>> +        }
>> > >>>> +
>> > >>>> +        return Long.decode(params.get(name)).longValue();
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Get the value of a specified parameter as along, or
>return
>> the
>> > >>>> specified
>> > >>>> +     * default value if the value was not specified or is not
>a
>> long. A
>> > >>>> warning
>> > >>>> +     * will be logged if the value is not a long. The value
>may be
>> > >>>> specified in
>> > >>>> +     * decimal, hexadecimal, or octal, as defined by
>Long.decode().
>> > >>>> +     *
>> > >>>> +     * @param name
>> > >>>> +     *            the name of the parameter whose value
>should be
>> > >>>> retrieved
>> > >>>> +     * @param defaultValue
>> > >>>> +     *            the default value to return if the value of
>this
>> > >>>> parameter was
>> > >>>> +     *            not specified
>> > >>>> +     * @return the value of the parameter, or the default
>value if
>> the
>> > >>>> parameter
>> > >>>> +     *         was not specified
>> > >>>> +     *
>> > >>>> +     * @see Long#decode(String)
>> > >>>> +     */
>> > >>>> +    public long getLongParameter(String name, long
>defaultValue) {
>> > >>>> +        if (params == null || !params.containsKey(name)) {
>> > >>>> +            return defaultValue;
>> > >>>> +        }
>> > >>>> +        try {
>> > >>>> +            return Long.decode(params.get(name)).longValue();
>> > >>>> +        } catch (NumberFormatException e) {
>> > >>>> +            log.warn("Value for parameter '" + name + "' not
>a
>> long: '"
>> > >>>> + params.get(name) + "'.  Using default: '"
>> > >>>> +                    + defaultValue + "'.", e);
>> > >>>> +            return defaultValue;
>> > >>>> +        }
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     *
>> > >>>> +     * @param name
>> > >>>> +     * @param defaultValue
>> > >>>> +     * @return
>> > >>>>
>> > >>>>  No javadoc? Again three warnings more :)
>> > >>>
>> > >>>  +     */
>> > >>>> +    public boolean getBooleanParameter(String name, boolean
>> > >>>> defaultValue) {
>> > >>>> +        if (params == null || !params.containsKey(name)) {
>> > >>>> +            return defaultValue;
>> > >>>> +        }
>> > >>>> +        return Boolean.valueOf(params.get(name));
>> > >>>> +    }
>> > >>>> +}
>> > >>>>
>> > >>>> Propchange:
>> jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> > >>>> backend/BackendListenerContext.java
>> > >>>> ------------------------------------------------------------
>> > >>>> ------------------
>> > >>>>       svn:mime-type = text/plain
>> > >>>>
>> > >>>> Added:
>jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> > >>>> backend/BackendListenerGui.java
>> > >>>> URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/
>> > >>>> org/apache/jmeter/visualizers/backend/BackendListenerGui.
>> > >>>> java?rev=1641081&view=auto
>> > >>>> ============================================================
>> > >>>> ==================
>> > >>>> --- jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> > >>>> backend/BackendListenerGui.java (added)
>> > >>>> +++ jmeter/trunk/src/components/org/apache/jmeter/visualizers/
>> > >>>> backend/BackendListenerGui.java Sat Nov 22 15:36:37 2014
>> > >>>> @@ -0,0 +1,282 @@
>> > >>>> +/*
>> > >>>> + * Licensed to the Apache Software Foundation (ASF) under one
>or
>> more
>> > >>>> + * contributor license agreements.  See the NOTICE file
>distributed
>> > >>>> with
>> > >>>> + * this work for additional information regarding copyright
>> ownership.
>> > >>>> + * The ASF licenses this file to You under the Apache
>License,
>> Version
>> > >>>> 2.0
>> > >>>> + * (the "License"); you may not use this file except in
>compliance
>> with
>> > >>>> + * the License.  You may obtain a copy of the License at
>> > >>>> + *
>> > >>>> + *   http://www.apache.org/licenses/LICENSE-2.0
>> > >>>> + *
>> > >>>> + * Unless required by applicable law or agreed to in writing,
>> software
>> > >>>> + * distributed under the License is distributed on an "AS IS"
>> BASIS,
>> > >>>> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
>express or
>> > >>>> implied.
>> > >>>> + * See the License for the specific language governing
>permissions
>> and
>> > >>>> + * limitations under the License.
>> > >>>> + *
>> > >>>> + */
>> > >>>> +
>> > >>>> +package org.apache.jmeter.visualizers.backend;
>> > >>>> +
>> > >>>> +import java.awt.BorderLayout;
>> > >>>> +import java.awt.event.ActionEvent;
>> > >>>> +import java.awt.event.ActionListener;
>> > >>>> +import java.util.ArrayList;
>> > >>>> +import java.util.HashSet;
>> > >>>> +import java.util.List;
>> > >>>> +import java.util.Map;
>> > >>>> +import java.util.Set;
>> > >>>> +
>> > >>>> +import javax.swing.ComboBoxModel;
>> > >>>> +import javax.swing.JComboBox;
>> > >>>> +import javax.swing.JLabel;
>> > >>>> +import javax.swing.JPanel;
>> > >>>> +import javax.swing.JTextField;
>> > >>>> +
>> > >>>> +import org.apache.jmeter.config.Argument;
>> > >>>> +import org.apache.jmeter.config.Arguments;
>> > >>>> +import org.apache.jmeter.config.gui.ArgumentsPanel;
>> > >>>> +import org.apache.jmeter.gui.util.HorizontalPanel;
>> > >>>> +import org.apache.jmeter.testelement.TestElement;
>> > >>>> +import
>org.apache.jmeter.testelement.property.PropertyIterator;
>> > >>>> +import org.apache.jmeter.util.JMeterUtils;
>> > >>>> +import org.apache.jmeter.visualizers.gui.AbstractListenerGui;
>> > >>>> +import org.apache.jorphan.logging.LoggingManager;
>> > >>>> +import org.apache.jorphan.reflect.ClassFinder;
>> > >>>> +import org.apache.log.Logger;
>> > >>>> +
>> > >>>> +/**
>> > >>>> + * The <code>BackendListenerGui</code> class provides the
>user
>> > >>>> interface for the
>> > >>>> + * {@link BackendListener} object.
>> > >>>> + * @since 2.13
>> > >>>> + */
>> > >>>> +public class BackendListenerGui extends AbstractListenerGui
>> implements
>> > >>>> ActionListener {
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     *
>> > >>>> +     */
>> > >>>> +    private static final long serialVersionUID =
>> 4331668988576438604L;
>> > >>>> +
>> > >>>> +    /** Logging */
>> > >>>> +    private static final Logger log = LoggingManager.
>> > >>>> getLoggerForClass();
>> > >>>> +
>> > >>>> +    /** A combo box allowing the user to choose a backend
>class. */
>> > >>>> +    private JComboBox classnameCombo;
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * A field allowing the user to specify the size of Queue
>> > >>>> +     */
>> > >>>> +    private JTextField queueSize;
>> > >>>> +
>> > >>>> +    /** A panel allowing the user to set arguments for this
>test.
>> */
>> > >>>> +    private ArgumentsPanel argsPanel;
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Create a new BackendListenerGui as a standalone
>component.
>> > >>>> +     */
>> > >>>> +    public BackendListenerGui() {
>> > >>>> +        super();
>> > >>>> +        init();
>> > >>>> +    }
>> > >>>> +
>> > >>>> +
>> > >>>> +    /** {@inheritDoc} */
>> > >>>> +    @Override
>> > >>>> +    public String getLabelResource() {
>> > >>>> +        return "backend_listener"; // $NON-NLS-1$
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Initialize the GUI components and layout.
>> > >>>> +     */
>> > >>>> +    private void init() {// called from ctor, so must not be
>> > >>>> overridable
>> > >>>> +        setLayout(new BorderLayout(0, 5));
>> > >>>> +
>> > >>>> +        setBorder(makeBorder());
>> > >>>> +        add(makeTitlePanel(), BorderLayout.NORTH);
>> > >>>> +
>> > >>>> +        JPanel classnameRequestPanel = new JPanel(new
>> BorderLayout(0,
>> > >>>> 5));
>> > >>>> +        classnameRequestPanel.add(createClassnamePanel(),
>> > >>>> BorderLayout.NORTH);
>> > >>>> +        classnameRequestPanel.add(createParameterPanel(),
>> > >>>> BorderLayout.CENTER);
>> > >>>> +
>> > >>>> +        add(classnameRequestPanel, BorderLayout.CENTER);
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Create a panel with GUI components allowing the user
>to
>> select a
>> > >>>> test
>> > >>>> +     * class.
>> > >>>> +     *
>> > >>>> +     * @return a panel containing the relevant components
>> > >>>> +     */
>> > >>>> +    private JPanel createClassnamePanel() {
>> > >>>> +        List<String> possibleClasses = new
>ArrayList<String>();
>> > >>>> +
>> > >>>> +        try {
>> > >>>> +            // Find all the classes which implement the
>> > >>>> BackendListenerClient
>> > >>>> +            // interface.
>> > >>>> +            possibleClasses =
>ClassFinder.findClassesThatExtend(
>> > >>>> JMeterUtils.getSearchPaths(),
>> > >>>> +                    new Class[] { BackendListenerClient.class
>});
>> > >>>> +
>> > >>>> +            // Remove the BackendListener class from the list
>> since it
>> > >>>> only
>> > >>>>
>> > >>>>  ErrorBackendListener
>> > >>>
>> > >>>  +            // implements the interface for error conditions.
>> > >>>> +
>> > >>>> +           
>possibleClasses.remove(BackendListener.class.getName()
>> +
>> > >>>> "$ErrorBackendListenerClient");
>> > >>>> +        } catch (Exception e) {
>> > >>>> +            log.debug("Exception getting interfaces.", e);
>> > >>>> +        }
>> > >>>> +
>> > >>>> +        JLabel label = new
>> JLabel(JMeterUtils.getResString("backend_
>> > >>>> listener_classname"));
>> > >>>> // $NON-NLS-1$
>> > >>>> +
>> > >>>> +        classnameCombo = new
>JComboBox(possibleClasses.toArray());
>> > >>>> +        classnameCombo.addActionListener(this);
>> > >>>> +        classnameCombo.setEditable(false);
>> > >>>> +        label.setLabelFor(classnameCombo);
>> > >>>> +
>> > >>>> +        HorizontalPanel classNamePanel = new
>HorizontalPanel();
>> > >>>> +        classNamePanel.add(label);
>> > >>>> +        classNamePanel.add(classnameCombo);
>> > >>>> +
>> > >>>> +        queueSize = new JTextField("", 5);
>> > >>>> +        queueSize.setName("Queue Size"); //$NON-NLS-1$
>> > >>>> +        JLabel queueSizeLabel = new JLabel(JMeterUtils.
>> > >>>> getResString("backend_listener_queue_size")); // $NON-NLS-1$
>> > >>>> +        queueSizeLabel.setLabelFor(queueSize);
>> > >>>> +        HorizontalPanel queueSizePanel = new
>HorizontalPanel();
>> > >>>> +        queueSizePanel.add(queueSizeLabel,
>BorderLayout.WEST);
>> > >>>> +        queueSizePanel.add(queueSize);
>> > >>>> +
>> > >>>> +        JPanel panel = new JPanel(new BorderLayout(0, 5));
>> > >>>> +        panel.add(classNamePanel, BorderLayout.NORTH);
>> > >>>> +        panel.add(queueSizePanel, BorderLayout.CENTER);
>> > >>>> +        return panel;
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Handle action events for this component. This method
>> currently
>> > >>>> handles
>> > >>>> +     * events for the classname combo box.
>> > >>>> +     *
>> > >>>> +     * @param evt
>> > >>>>
>> > >>>>  I would spend the few extra characters to make it event
>instead of
>> evt
>> > >>>
>> > >>>  +     *            the ActionEvent to be handled
>> > >>>> +     */
>> > >>>> +    @Override
>> > >>>> +    public void actionPerformed(ActionEvent evt) {
>> > >>>> +        if (evt.getSource() == classnameCombo) {
>> > >>>> +            String className = ((String) classnameCombo.
>> > >>>> getSelectedItem()).trim();
>> > >>>> +            try {
>> > >>>> +                BackendListenerClient client =
>> (BackendListenerClient)
>> > >>>> Class.forName(className, true,
>> > >>>> +                        Thread.currentThread().
>> > >>>> getContextClassLoader()).
>> > >>>> newInstance();
>> > >>>> +
>> > >>>> +                Arguments currArgs = new Arguments();
>> > >>>> +                argsPanel.modifyTestElement(currArgs);
>> > >>>> +                Map<String, String> currArgsMap =
>> > >>>> currArgs.getArgumentsAsMap();
>> > >>>> +
>> > >>>> +                Arguments newArgs = new Arguments();
>> > >>>> +                Arguments testParams = null;
>> > >>>> +                try {
>> > >>>> +                    testParams =
>client.getDefaultParameters();
>> > >>>> +                } catch (AbstractMethodError e) {
>> > >>>> +                    log.warn("BackendListenerClient doesn't
>> implement
>> > >>>> "
>> > >>>> +                            + "getDefaultParameters.  Default
>> > >>>> parameters
>> > >>>> won't "
>> > >>>> +                            + "be shown.  Please update your
>client
>> > >>>> class: " + className);
>> > >>>> +                }
>> > >>>> +
>> > >>>> +                if (testParams != null) {
>> > >>>> +                    PropertyIterator i =
>testParams.getArguments().
>> > >>>> iterator();
>> > >>>>
>> > >>>>  I would try a for loop instead of explicitly using an
>iterator
>> > >>>
>> > >>>  +                    while (i.hasNext()) {
>> > >>>> +                        Argument arg = (Argument)
>> > >>>> i.next().getObjectValue();
>> > >>>> +                        String name = arg.getName();
>> > >>>> +                        String value = arg.getValue();
>> > >>>> +
>> > >>>> +                        // If a user has set parameters in
>one
>> test,
>> > >>>> and
>> > >>>> then
>> > >>>> +                        // selects a different test which
>supports
>> the
>> > >>>> same
>> > >>>> +                        // parameters, those parameters
>should
>> have the
>> > >>>> same
>> > >>>> +                        // values that they did in the
>original
>> test.
>> > >>>> +                        if (currArgsMap.containsKey(name)) {
>> > >>>> +                            String newVal =
>currArgsMap.get(name);
>> > >>>> +                            if (newVal != null &&
>newVal.length()
>> > 0)
>> > >>>> {
>> > >>>> +                                value = newVal;
>> > >>>> +                            }
>> > >>>> +                        }
>> > >>>> +                        newArgs.addArgument(name, value);
>> > >>>> +                    }
>> > >>>> +                }
>> > >>>> +
>> > >>>> +                argsPanel.configure(newArgs);
>> > >>>> +            } catch (Exception e) {
>> > >>>> +                log.error("Error getting argument list for "
>+
>> > >>>> className, e);
>> > >>>> +            }
>> > >>>> +        }
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Create a panel containing components allowing the user
>to
>> > >>>> provide
>> > >>>> +     * arguments to be passed to the test class instance.
>> > >>>> +     *
>> > >>>> +     * @return a panel containing the relevant components
>> > >>>> +     */
>> > >>>> +    private JPanel createParameterPanel() {
>> > >>>> +        argsPanel = new ArgumentsPanel(JMeterUtils.
>> > >>>> getResString("backend_listener_paramtable")); // $NON-NLS-1$
>> > >>>> +        return argsPanel;
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /** {@inheritDoc} */
>> > >>>> +    @Override
>> > >>>> +    public void configure(TestElement config) {
>> > >>>> +        super.configure(config);
>> > >>>> +
>> > >>>> +        argsPanel.configure((Arguments) config.getProperty(
>> > >>>> BackendListener.ARGUMENTS).getObjectValue());
>> > >>>> +
>> > >>>> +        String className = config.getPropertyAsString(
>> > >>>> BackendListener.CLASSNAME);
>> > >>>> +        if(checkContainsClassName(classnameCombo.getModel(),
>> > >>>> className)) {
>> > >>>> +            classnameCombo.setSelectedItem(className);
>> > >>>> +        } else {
>> > >>>> +            log.error("Error setting class:'"+className+"' in
>> > >>>> BackendListener: "+getName()+
>> > >>>> +                    ", check for a missing jar in your jmeter
>> > >>>> 'search_paths' and 'plugin_dependency_paths' properties");
>> > >>>> +        }
>> > >>>> +        queueSize.setText(Integer.toString(((BackendListener)
>> > >>>> config).getQueueSize()));
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /**
>> > >>>> +     * Check combo contains className
>> > >>>> +     * @param model ComboBoxModel
>> > >>>> +     * @param className String class name
>> > >>>> +     * @return boolean
>> > >>>>
>> > >>>>  explain "boolean" or the other params a bit more?
>> > >>>
>> > >>>  +     */
>> > >>>> +    private static final boolean
>> checkContainsClassName(ComboBoxModel
>> > >>>> model, String className) {
>> > >>>> +        int size = model.getSize();
>> > >>>> +        Set<String> set = new HashSet<String>(size);
>> > >>>> +        for (int i = 0; i < size; i++) {
>> > >>>> +            set.add((String)model.getElementAt(i));
>> > >>>> +        }
>> > >>>> +        return set.contains(className);
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /** {@inheritDoc} */
>> > >>>> +    @Override
>> > >>>> +    public TestElement createTestElement() {
>> > >>>> +        BackendListener config = new BackendListener();
>> > >>>> +        modifyTestElement(config);
>> > >>>> +        return config;
>> > >>>> +    }
>> > >>>> +
>> > >>>> +    /** {@inheritDoc} */
>> > >>>> +    @Override
>> > >>>> +    public void modifyTestElement(TestElement config) {
>> > >>>> +        configureTestElement(config);
>> > >>>> +        BackendListener backendListener = (BackendListener)
>config;
>> > >>>> +        backendListener.setArguments((Arguments)
>> > >>>> argsPanel.createTestElement());
>> > >>>> +       
>backendListener.setClassname(String.valueOf(classnameCombo.
>> > >>>> getSelectedItem()));
>> > >>>> +       
>backendListener.setQueueSize(Integer.parseInt(queueSize.
>> > >>>> getText()));
>> > >>>> +
>> > >>>> +    }
>> > >>>> +
>> > >>>>
>> > >>>
>> >
>>
>>
>>


Mime
View raw message