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.samplers;
020:
021: import org.apache.jmeter.util.JMeterUtils;
022: import org.apache.jorphan.logging.LoggingManager;
023: import org.apache.log.Logger;
024:
025: import java.io.Serializable;
026: import java.rmi.RemoteException;
027: import java.util.ArrayList;
028: import java.util.HashMap;
029: import java.util.List;
030: import java.util.Map;
031:
032: /**
033: * Implements batch reporting for remote testing.
034: *
035: * @author Lars Krog-Jensen
036: * Created: 2005-okt-04
037: */
038: public class StatisticalSampleSender implements SampleSender,
039: Serializable {
040: private static final Logger log = LoggingManager
041: .getLoggerForClass();
042:
043: private static final int DEFAULT_NUM_SAMPLE_THRESHOLD = 100;
044:
045: private static final long DEFAULT_TIME_THRESHOLD = 60000L;
046:
047: private RemoteSampleListener listener;
048:
049: private List sampleStore = new ArrayList();
050:
051: private Map sampleTable = new HashMap();
052:
053: private int numSamplesThreshold;
054:
055: private int sampleCount;
056:
057: private long timeThreshold;
058:
059: private long batchSendTime = -1;
060:
061: public StatisticalSampleSender() {
062: log.warn("Constructor only intended for use in testing");
063: }
064:
065: /**
066: * Constructor
067: *
068: * @param listener that the List of sample events will be sent to.
069: */
070: StatisticalSampleSender(RemoteSampleListener listener) {
071: this .listener = listener;
072: init();
073: log.info("Using batching for this run." + " Thresholds: num="
074: + numSamplesThreshold + ", time=" + timeThreshold);
075: }
076:
077: /**
078: * Checks for the Jmeter properties num_sample_threshold and time_threshold,
079: * and assigns defaults if not found.
080: */
081: private void init() {
082: this .numSamplesThreshold = JMeterUtils.getPropDefault(
083: "num_sample_threshold", DEFAULT_NUM_SAMPLE_THRESHOLD);
084: this .timeThreshold = JMeterUtils.getPropDefault(
085: "time_threshold", DEFAULT_TIME_THRESHOLD);
086: }
087:
088: /**
089: * Checks if any sample events are still present in the sampleStore and
090: * sends them to the listener. Informs the listener of the testended.
091: */
092: public void testEnded() {
093: try {
094: if (sampleStore.size() != 0) {
095: sendBatch();
096: }
097: listener.testEnded();
098: } catch (RemoteException err) {
099: log.warn("testEnded()", err);
100: }
101: }
102:
103: /**
104: * Checks if any sample events are still present in the sampleStore and
105: * sends them to the listener. Informs the listener of the testended.
106: *
107: * @param host the hostname that the test has ended on.
108: */
109: public void testEnded(String host) {
110: try {
111: if (sampleStore.size() != 0) {
112: sendBatch();
113: }
114: listener.testEnded(host);
115: } catch (RemoteException err) {
116: log.warn("testEnded(hostname)", err);
117: }
118: }
119:
120: /**
121: * Stores sample events untill either a time or sample threshold is
122: * breached. Both thresholds are reset if one fires. If only one threshold
123: * is set it becomes the only value checked against. When a threhold is
124: * breached the list of sample events is sent to a listener where the event
125: * are fired locally.
126: *
127: * @param e a Sample Event
128: */
129: public void SampleOccurred(SampleEvent e) {
130: synchronized (sampleStore) {
131: // Locate the statistical sample colector
132: String key = StatisticalSampleResult.getKey(e);
133: StatisticalSampleResult statResult = (StatisticalSampleResult) sampleTable
134: .get(key);
135: if (statResult == null) {
136: statResult = new StatisticalSampleResult(e.getResult());
137: // store the new statistical result collector
138: sampleTable.put(key, statResult);
139: // add a new wrapper samplevent
140: sampleStore.add(new SampleEvent(statResult, e
141: .getThreadGroup()));
142: }
143: statResult.add(e.getResult());
144: sampleCount++;
145: if (numSamplesThreshold != -1) {
146: if (sampleCount >= numSamplesThreshold) {
147: try {
148: if (log.isDebugEnabled()) {
149: log.debug("Firing sample");
150: }
151: sendBatch();
152: } catch (RemoteException err) {
153: log.warn("sampleOccurred", err);
154: }
155: }
156: }
157:
158: if (timeThreshold != -1) {
159: long now = System.currentTimeMillis();
160: // Checking for and creating initial timestamp to cheak against
161: if (batchSendTime == -1) {
162: this .batchSendTime = now + timeThreshold;
163: }
164:
165: if (batchSendTime < now) {
166: try {
167: if (log.isDebugEnabled()) {
168: log.debug("Firing time");
169: }
170: sendBatch();
171: this .batchSendTime = now + timeThreshold;
172: } catch (RemoteException err) {
173: log.warn("sampleOccurred", err);
174: }
175: }
176: }
177: }
178: }
179:
180: private void sendBatch() throws RemoteException {
181: if (sampleStore.size() > 0) {
182: listener.processBatch(sampleStore);
183: sampleStore.clear();
184: sampleTable.clear();
185: sampleCount = 0;
186: }
187: }
188: }
|