// $Header: /home/cvs/jakarta-jmeter/src/monitor/components/org/apache/jmeter/visualizers/MonitorAccumModel.java,v 1.8 2005/07/12 20:50:27 mstover1 Exp $
/*
* Copyright 2004 The Apache Software Foundation.
*
* Licensed 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;
import java.io.Serializable;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.LinkedList;
import org.apache.jmeter.samplers.Clearable;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.monitor.model.ObjectFactory;
import org.apache.jmeter.monitor.model.Status;
import org.apache.jmeter.monitor.util.Stats;
import org.apache.jmeter.protocol.http.sampler.HTTPSampleResult;
public class MonitorAccumModel implements Clearable, Serializable {
private HashMap MAP;
/**
* we use this to set the current monitorModel so that we can save the stats
* to the resultcolllector.
*/
private MonitorModel CURRENT;
private List listeners;
/**
* By default, we set the default to 800
*/
private int DEFAULT_BUFFER = 800;
/**
*
*/
public MonitorAccumModel() {
MAP = new HashMap();
listeners = new LinkedList();
}
public int getBufferSize() {
return DEFAULT_BUFFER;
}
public void setBufferSize(int buffer) {
DEFAULT_BUFFER = buffer;
}
/**
* Added this method we that we can save the calculated stats.
*
* @return
*/
public MonitorModel getLastSample() {
return this.CURRENT;
}
/**
* Method will look up the server in the map. The MonitorModel will be added
* to an existing list, or a new one will be created.
*
* @param model
*/
public void addSample(MonitorModel model) {
this.CURRENT = model;
if (MAP.containsKey(model.getURL())) {
List newlist = updateArray(model, (List) MAP.get(model.getURL()));
MAP.put(model.getURL(), newlist);
} else {
List samples = Collections.synchronizedList(new LinkedList());
samples.add(model);
MAP.put(model.getURL(), samples);
}
}
/**
* We want to keep only 240 entries for each server, so we handle the object
* array ourselves.
*
* @param model
*/
private List updateArray(MonitorModel model, List list) {
if (list.size() < DEFAULT_BUFFER) {
list.add(model);
} else {
list.add(model);
list.remove(0);
}
return list;
}
/**
* Get all MonitorModels matching the URL.
*
* @param url
* @return list
*/
public List getAllSamples(String url) {
if (!MAP.containsKey(url)) {
return Collections.synchronizedList(new LinkedList());
} else {
return (List) MAP.get(url);
}
}
/**
* Get the MonitorModel matching the url.
*
* @param url
* @return list
*/
public MonitorModel getSample(String url) {
if (MAP.containsKey(url)) {
ArrayList list = (ArrayList) MAP.get(url);
return (MonitorModel) list.get(0);
} else {
return null;
}
}
/**
* Method will try to parse the response data. If the request was a monitor
* request, but the response was incomplete, bad or the server refused the
* connection, we will set the server's health to "dead". If the request was
* not a monitor sample, the method will ignore it.
*
* @param sample
*/
public void addSample(SampleResult sample) {
URL surl = null;
if (sample instanceof HTTPSampleResult) {
surl = ((HTTPSampleResult) sample).getURL();
}
// String rescontent = new String(sample.getResponseData());
if (sample.getResponseCode().equals("200") && ((HTTPSampleResult) sample).isMonitor()) {
ObjectFactory of = ObjectFactory.getInstance();
Status st = of.parseBytes(sample.getResponseData());
if (st != null) {
MonitorStats stat = new MonitorStats(Stats.calculateStatus(st), Stats.calculateLoad(st), 0, Stats
.calculateMemoryLoad(st), Stats.calculateThreadLoad(st), surl.getHost(), String.valueOf(surl
.getPort()), surl.getProtocol(), System.currentTimeMillis());
MonitorModel mo = new MonitorModel(stat);
this.addSample(mo);
notifyListeners(mo);
} else {
noResponse(surl);
}
} else if (((HTTPSampleResult) sample).isMonitor()) {
noResponse(surl);
}
}
/**
* If there is no response from the server, we create a new MonitorStats
* object with the current timestamp and health "dead".
*
* @param url
*/
public void noResponse(URL url) {
notifyListeners(createNewMonitorModel(url));
}
/**
* Method will return a new MonitorModel object with the given URL. This is
* used when the server fails to respond fully, or is dead.
*
* @param url
* @return new MonitorModel
*/
public MonitorModel createNewMonitorModel(URL url) {
MonitorStats stat = new MonitorStats(Stats.DEAD, 0, 0, 0, 0, url.getHost(), String.valueOf(url.getPort()), url
.getProtocol(), System.currentTimeMillis());
MonitorModel mo = new MonitorModel(stat);
return mo;
}
/**
* Clears everything except the listener. Do not clear the listeners. If we
* clear listeners, subsequent "run" will not notify the gui of data
* changes.
*/
public void clear() {
Iterator itr = this.MAP.keySet().iterator();
while (itr.hasNext()) {
List lt = (List) this.MAP.get(itr.next());
lt.clear();
}
this.MAP.clear();
}
/**
* notify the listeners with the MonitorModel object.
*
* @param model
*/
public void notifyListeners(MonitorModel model) {
for (int idx = 0; idx < listeners.size(); idx++) {
MonitorListener ml = (MonitorListener) listeners.get(idx);
ml.addSample(model);
}
}
/**
* Add a listener. When samples are added, the class will notify the
* listener of the change.
*
* @param listener
*/
public void addListener(MonitorListener listener) {
listeners.add(listener);
}
}