001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.jmeter.control;
020:
021: import java.io.Serializable;
022:
023: import org.apache.jmeter.engine.event.LoopIterationEvent;
024: import org.apache.jmeter.engine.event.LoopIterationListener;
025: import org.apache.jmeter.samplers.Sampler;
026: import org.apache.jmeter.testelement.TestListener;
027: import org.apache.jmeter.testelement.property.BooleanProperty;
028: import org.apache.jmeter.testelement.property.FloatProperty;
029: import org.apache.jmeter.testelement.property.IntegerProperty;
030: import org.apache.jmeter.testelement.property.JMeterProperty;
031: import org.apache.jmeter.testelement.property.StringProperty;
032:
033: /**
034: * This class represents a controller that can control the number of times that
035: * it is executed, either by the total number of times the user wants the
036: * controller executed (BYNUMBER) or by the percentage of time it is called
037: * (BYPERCENT)
038: *
039: * The current implementation executes the first N samples (BYNUMBER)
040: * or the last N% of samples (BYPERCENT).
041: */
042: public class ThroughputController extends GenericController implements
043: Serializable, LoopIterationListener, TestListener {
044:
045: public static final int BYNUMBER = 0;
046:
047: public static final int BYPERCENT = 1;
048:
049: private static final String STYLE = "ThroughputController.style";// $NON-NLS-1$
050:
051: private static final String PERTHREAD = "ThroughputController.perThread";// $NON-NLS-1$
052:
053: private static final String MAXTHROUGHPUT = "ThroughputController.maxThroughput";// $NON-NLS-1$
054:
055: private static final String PERCENTTHROUGHPUT = "ThroughputController.percentThroughput";// $NON-NLS-1$
056:
057: private static int globalNumExecutions;
058:
059: private static int globalIteration;
060:
061: private static final Object counterLock = new Object(); // ensure counts are updated correctly
062:
063: /**
064: * Number of iterations on which we've chosen to deliver samplers.
065: */
066: private int numExecutions = 0;
067:
068: /**
069: * Index of the current iteration. 0-based.
070: */
071: private int iteration = -1;
072:
073: /**
074: * Whether to deliver samplers on this iteration.
075: */
076: private boolean runThisTime;
077:
078: public ThroughputController() {
079: setStyle(BYNUMBER);
080: setPerThread(true);
081: setMaxThroughput(1);
082: setPercentThroughput(100);
083: runThisTime = false;
084: }
085:
086: public void setStyle(int style) {
087: setProperty(new IntegerProperty(STYLE, style));
088: }
089:
090: public int getStyle() {
091: return getPropertyAsInt(STYLE);
092: }
093:
094: public void setPerThread(boolean perThread) {
095: setProperty(new BooleanProperty(PERTHREAD, perThread));
096: }
097:
098: public boolean isPerThread() {
099: return getPropertyAsBoolean(PERTHREAD);
100: }
101:
102: public void setMaxThroughput(int maxThroughput) {
103: setProperty(new IntegerProperty(MAXTHROUGHPUT, maxThroughput));
104: }
105:
106: public void setMaxThroughput(String maxThroughput) {
107: setProperty(new StringProperty(MAXTHROUGHPUT, maxThroughput));
108: }
109:
110: public String getMaxThroughput() {
111: return getPropertyAsString(MAXTHROUGHPUT);
112: }
113:
114: protected int getMaxThroughputAsInt() {
115: JMeterProperty prop = getProperty(MAXTHROUGHPUT);
116: int retVal = 1;
117: if (prop instanceof IntegerProperty) {
118: retVal = (((IntegerProperty) prop).getIntValue());
119: } else {
120: try {
121: retVal = Integer.parseInt(prop.getStringValue());
122: } catch (NumberFormatException e) {
123: }
124: }
125: return retVal;
126: }
127:
128: public void setPercentThroughput(float percentThroughput) {
129: setProperty(new FloatProperty(PERCENTTHROUGHPUT,
130: percentThroughput));
131: }
132:
133: public void setPercentThroughput(String percentThroughput) {
134: setProperty(new StringProperty(PERCENTTHROUGHPUT,
135: percentThroughput));
136: }
137:
138: public String getPercentThroughput() {
139: return getPropertyAsString(PERCENTTHROUGHPUT);
140: }
141:
142: protected float getPercentThroughputAsFloat() {
143: JMeterProperty prop = getProperty(PERCENTTHROUGHPUT);
144: float retVal = 100;
145: if (prop instanceof FloatProperty) {
146: retVal = (((FloatProperty) prop).getFloatValue());
147: } else {
148: try {
149: retVal = Float.parseFloat(prop.getStringValue());
150: } catch (NumberFormatException e) {
151: }
152: }
153: return retVal;
154: }
155:
156: private int getExecutions() {
157: if (!isPerThread()) {
158: return globalNumExecutions;
159: }
160: return numExecutions;
161: }
162:
163: /**
164: * @see org.apache.jmeter.control.Controller#next()
165: */
166: public Sampler next() {
167: if (runThisTime) {
168: return super .next();
169: }
170: return null;
171: }
172:
173: /**
174: * Decide whether to return any samplers on this iteration.
175: */
176: private boolean decide(int executions, int iterations) {
177: if (getStyle() == BYNUMBER) {
178: return executions < getMaxThroughputAsInt();
179: }
180: return (100.0 * executions + 50.0) / (iterations + 1) < getPercentThroughputAsFloat();
181: }
182:
183: /**
184: * @see org.apache.jmeter.control.Controller#isDone()
185: */
186: public boolean isDone() {
187: if (subControllersAndSamplers.size() == 0) {
188: return true;
189: } else if (getStyle() == BYNUMBER
190: && getExecutions() >= getMaxThroughputAsInt()
191: && current >= getSubControllers().size()) {
192: return true;
193: } else {
194: return false;
195: }
196: }
197:
198: public Object clone() {
199: ThroughputController clone = (ThroughputController) super
200: .clone();
201: clone.numExecutions = numExecutions;
202: clone.iteration = iteration;
203: clone.runThisTime = false;
204: return clone;
205: }
206:
207: public void iterationStart(LoopIterationEvent iterEvent) {
208: if (!isPerThread()) {
209: synchronized (counterLock) {
210: globalIteration++;
211: runThisTime = decide(globalNumExecutions,
212: globalIteration);
213: if (runThisTime)
214: globalNumExecutions++;
215: }
216: } else {
217: iteration++;
218: runThisTime = decide(numExecutions, iteration);
219: if (runThisTime)
220: numExecutions++;
221: }
222: }
223:
224: public void testStarted() {
225: synchronized (counterLock) {
226: globalNumExecutions = 0;
227: globalIteration = -1;
228: }
229: }
230:
231: public void testStarted(String host) {
232: testStarted();
233: }
234:
235: public void testEnded() {
236: }
237:
238: public void testEnded(String host) {
239: }
240:
241: public void testIterationStart(LoopIterationEvent event) {
242: }
243: }
|