// $Header: /home/cvs/jakarta-jmeter/src/monitor/components/org/apache/jmeter/visualizers/MonitorAccumModel.java,v 1.6 2004/03/20 20:36:37 sebb 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;
//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;
}
/**
* 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);
}
}