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: package org.apache.jmeter.visualizers;
018:
019: import java.io.Serializable;
020: import java.net.URL;
021: import java.util.ArrayList;
022: import java.util.Collections;
023: import java.util.HashMap;
024: import java.util.Iterator;
025: import java.util.LinkedList;
026: import java.util.List;
027:
028: import org.apache.jmeter.monitor.model.ObjectFactory;
029: import org.apache.jmeter.monitor.model.Status;
030: import org.apache.jmeter.monitor.util.Stats;
031: import org.apache.jmeter.protocol.http.sampler.HTTPSampleResult;
032: import org.apache.jmeter.samplers.Clearable;
033: import org.apache.jmeter.samplers.SampleResult;
034:
035: public class MonitorAccumModel implements Clearable, Serializable {
036:
037: private HashMap MAP;
038:
039: /**
040: * we use this to set the current monitorModel so that we can save the stats
041: * to the resultcolllector.
042: */
043: private MonitorModel CURRENT;
044:
045: private List listeners;
046:
047: /**
048: * By default, we set the default to 800
049: */
050: private int DEFAULT_BUFFER = 800;
051:
052: /**
053: *
054: */
055: public MonitorAccumModel() {
056: MAP = new HashMap();
057: listeners = new LinkedList();
058: }
059:
060: public int getBufferSize() {
061: return DEFAULT_BUFFER;
062: }
063:
064: public void setBufferSize(int buffer) {
065: DEFAULT_BUFFER = buffer;
066: }
067:
068: /**
069: * Added this method we that we can save the calculated stats.
070: *
071: * @return current sample
072: */
073: public MonitorModel getLastSample() {
074: return this .CURRENT;
075: }
076:
077: /**
078: * Method will look up the server in the map. The MonitorModel will be added
079: * to an existing list, or a new one will be created.
080: *
081: * @param model
082: */
083: public void addSample(MonitorModel model) {
084: this .CURRENT = model;
085: if (MAP.containsKey(model.getURL())) {
086: List newlist = updateArray(model, (List) MAP.get(model
087: .getURL()));
088: MAP.put(model.getURL(), newlist);
089: } else {
090: List samples = Collections
091: .synchronizedList(new LinkedList());
092: samples.add(model);
093: MAP.put(model.getURL(), samples);
094: }
095: }
096:
097: /**
098: * We want to keep only 240 entries for each server, so we handle the object
099: * array ourselves.
100: *
101: * @param model
102: */
103: private List updateArray(MonitorModel model, List list) {
104: if (list.size() < DEFAULT_BUFFER) {
105: list.add(model);
106: } else {
107: list.add(model);
108: list.remove(0);
109: }
110: return list;
111: }
112:
113: /**
114: * Get all MonitorModels matching the URL.
115: *
116: * @param url
117: * @return list
118: */
119: public List getAllSamples(String url) {
120: if (!MAP.containsKey(url)) {
121: return Collections.synchronizedList(new LinkedList());
122: } else {
123: return (List) MAP.get(url);
124: }
125: }
126:
127: /**
128: * Get the MonitorModel matching the url.
129: *
130: * @param url
131: * @return list
132: */
133: public MonitorModel getSample(String url) {
134: if (MAP.containsKey(url)) {
135: ArrayList list = (ArrayList) MAP.get(url);
136: return (MonitorModel) list.get(0);
137: } else {
138: return null;
139: }
140: }
141:
142: /**
143: * Method will try to parse the response data. If the request was a monitor
144: * request, but the response was incomplete, bad or the server refused the
145: * connection, we will set the server's health to "dead". If the request was
146: * not a monitor sample, the method will ignore it.
147: *
148: * @param sample
149: */
150: public void addSample(SampleResult sample) {
151: URL surl = null;
152: if (sample instanceof HTTPSampleResult) {
153: surl = ((HTTPSampleResult) sample).getURL();
154: // String rescontent = new String(sample.getResponseData());
155: if (sample.isResponseCodeOK()
156: && ((HTTPSampleResult) sample).isMonitor()) {
157: ObjectFactory of = ObjectFactory.getInstance();
158: Status st = of.parseBytes(sample.getResponseData());
159: if (st != null) {
160: MonitorStats stat = new MonitorStats(Stats
161: .calculateStatus(st), Stats
162: .calculateLoad(st), 0, Stats
163: .calculateMemoryLoad(st), Stats
164: .calculateThreadLoad(st), surl.getHost(),
165: String.valueOf(surl.getPort()), surl
166: .getProtocol(), System
167: .currentTimeMillis());
168: MonitorModel mo = new MonitorModel(stat);
169: this .addSample(mo);
170: notifyListeners(mo);
171: } else {
172: noResponse(surl);
173: }
174: } else if (((HTTPSampleResult) sample).isMonitor()) {
175: noResponse(surl);
176: }
177: }
178: }
179:
180: /**
181: * If there is no response from the server, we create a new MonitorStats
182: * object with the current timestamp and health "dead".
183: *
184: * @param url
185: */
186: public void noResponse(URL url) {
187: notifyListeners(createNewMonitorModel(url));
188: }
189:
190: /**
191: * Method will return a new MonitorModel object with the given URL. This is
192: * used when the server fails to respond fully, or is dead.
193: *
194: * @param url
195: * @return new MonitorModel
196: */
197: public MonitorModel createNewMonitorModel(URL url) {
198: MonitorStats stat = new MonitorStats(Stats.DEAD, 0, 0, 0, 0,
199: url.getHost(), String.valueOf(url.getPort()), url
200: .getProtocol(), System.currentTimeMillis());
201: MonitorModel mo = new MonitorModel(stat);
202: return mo;
203: }
204:
205: /**
206: * Clears everything except the listener. Do not clear the listeners. If we
207: * clear listeners, subsequent "run" will not notify the gui of data
208: * changes.
209: */
210: public void clearData() {
211: Iterator itr = this .MAP.keySet().iterator();
212: while (itr.hasNext()) {
213: List lt = (List) this .MAP.get(itr.next());
214: lt.clear();
215: }
216: this .MAP.clear();
217: }
218:
219: /**
220: * notify the listeners with the MonitorModel object.
221: *
222: * @param model
223: */
224: public void notifyListeners(MonitorModel model) {
225: for (int idx = 0; idx < listeners.size(); idx++) {
226: MonitorListener ml = (MonitorListener) listeners.get(idx);
227: ml.addSample(model);
228: }
229: }
230:
231: /**
232: * Add a listener. When samples are added, the class will notify the
233: * listener of the change.
234: *
235: * @param listener
236: */
237: public void addListener(MonitorListener listener) {
238: listeners.add(listener);
239: }
240: }
|