1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl.loadtest.data;
14
15 import java.util.ArrayList;
16 import java.util.EnumMap;
17 import java.util.HashMap;
18 import java.util.List;
19 import java.util.Map;
20
21 import javax.swing.event.TableModelEvent;
22 import javax.swing.event.TableModelListener;
23 import javax.swing.table.AbstractTableModel;
24
25 import com.eviware.soapui.impl.wsdl.loadtest.data.LoadTestStatistics.Statistic;
26 import com.eviware.soapui.model.support.LoadTestRunListenerAdapter;
27 import com.eviware.soapui.model.testsuite.LoadTestRunContext;
28 import com.eviware.soapui.model.testsuite.LoadTestRunner;
29
30 /***
31 * Collector of statistics to be exposed as TableModels
32 *
33 * @author Ole.Matzura
34 */
35
36 public class StatisticsHistory
37 {
38 private final LoadTestStatistics statistics;
39 private List<long[][]> data = new ArrayList<long[][]>();
40 private List<Long> threadCounts = new ArrayList<Long>();
41 private Map<Integer,TestStepStatisticsHistory> testStepStatisticHistories =
42 new HashMap<Integer,TestStepStatisticsHistory>();
43 private EnumMap<Statistic,StatisticsValueHistory> statisticsValueHistories =
44 new EnumMap<Statistic,StatisticsValueHistory>( Statistic.class );
45
46
47 private long resolution = 0;
48 private InternalTableModelListener internalTableModelListener = new InternalTableModelListener();
49 private Updater updater = new Updater();
50
51 public StatisticsHistory( LoadTestStatistics statistics )
52 {
53 this.statistics = statistics;
54
55 statistics.addTableModelListener( internalTableModelListener );
56 statistics.getLoadTest().addLoadTestRunListener( new LoadTestRunListenerAdapter() {
57
58 public void beforeLoadTest( LoadTestRunner loadTestRunner, LoadTestRunContext context )
59 {
60 if( resolution > 0 )
61 new Thread( updater ).start();
62 }
63 } );
64 }
65
66 public long getResolution()
67 {
68 return resolution;
69 }
70
71 public void setResolution( long resolution )
72 {
73 long old = this.resolution;
74 this.resolution = resolution;
75
76 if( resolution > 0 && old == 0 )
77 {
78 new Thread( updater ).start();
79 }
80 }
81
82 public int getRowCount()
83 {
84 return data.size();
85 }
86
87 public long[][] getHistoryAt( int index )
88 {
89 return data.get( index );
90 }
91
92 public long getThreadCountAt( int index )
93 {
94 return threadCounts.get( index );
95 }
96
97 public StatisticsHistoryModel getTestStepHistory( int testStepIndex )
98 {
99 if( !testStepStatisticHistories.containsKey( testStepIndex ))
100 {
101 testStepStatisticHistories.put( testStepIndex, new TestStepStatisticsHistory( testStepIndex ));
102 }
103
104 return testStepStatisticHistories.get( testStepIndex );
105 }
106
107 public StatisticsHistoryModel getStatisticsValueHistory( Statistic statistic )
108 {
109 if( !statisticsValueHistories.containsKey( statistic ))
110 {
111 statisticsValueHistories.put( statistic, new StatisticsValueHistory( statistic ) );
112 }
113
114 return statisticsValueHistories.get( statistic );
115 }
116
117 public void reset()
118 {
119 data.clear();
120 threadCounts.clear();
121
122 for( StatisticsValueHistory history : statisticsValueHistories.values() )
123 {
124 history.fireTableDataChanged();
125 history.fireTableStructureChanged();
126 }
127
128 for( TestStepStatisticsHistory history : testStepStatisticHistories.values() )
129 {
130 history.fireTableDataChanged();
131 history.fireTableStructureChanged();
132 }
133 }
134
135 private synchronized void updateHistory()
136 {
137 if( statistics.getStatistic( LoadTestStatistics.TOTAL, Statistic.COUNT ) == 0 )
138 {
139 reset();
140 }
141 else
142 {
143 int columnCount = statistics.getColumnCount();
144 int rowCount = statistics.getRowCount();
145
146 long[][] values = new long[rowCount][columnCount-2];
147
148 for( int c = 0; c < rowCount; c++ )
149 {
150 for( int i = 2; i< columnCount; i++ )
151 {
152 try
153 {
154 values[c][i - 2] = Long.parseLong(statistics.getValueAt(c, i).toString());
155 }
156 catch (NumberFormatException ex)
157 {
158 values[c][i - 2] = (long) Float.parseFloat(statistics.getValueAt(c, i).toString());
159 }
160 }
161 }
162
163 data.add( values );
164 threadCounts.add( statistics.getLoadTest().getThreadCount() );
165
166
167 int sz = data.size()-1;
168 for( StatisticsValueHistory history : statisticsValueHistories.values() )
169 {
170 history.fireTableRowsInserted( sz, sz );
171 }
172
173 for( TestStepStatisticsHistory history : testStepStatisticHistories.values() )
174 {
175 history.fireTableRowsInserted( sz, sz );
176 }
177 }
178 }
179
180 public abstract class StatisticsHistoryModel extends AbstractTableModel
181 {
182 public abstract void release();
183 }
184
185 private class TestStepStatisticsHistory extends StatisticsHistoryModel
186 {
187 private final int testStepIndex;
188
189 public TestStepStatisticsHistory(int testStepIndex)
190 {
191 this.testStepIndex = testStepIndex == -1 ? statistics.getRowCount()-1 : testStepIndex;
192 }
193
194 public int getTestStepIndex()
195 {
196 return testStepIndex;
197 }
198
199 public int getRowCount()
200 {
201 return data.size();
202 }
203
204 public int getColumnCount()
205 {
206 return statistics.getColumnCount()-1;
207 }
208
209 public Object getValueAt(int rowIndex, int columnIndex)
210 {
211 if( columnIndex == 0 ) return threadCounts.get( rowIndex );
212
213
214 if( rowIndex < data.size() )
215 return data.get( rowIndex )[testStepIndex][columnIndex-1];
216 else return
217 new Long( 0 );
218 }
219
220 public Class<?> getColumnClass(int columnIndex)
221 {
222 return Long.class;
223 }
224
225 public String getColumnName(int column)
226 {
227 return column == 0 ? "ThreadCount" :
228 Statistic.forIndex( column-1 ).getName();
229 }
230
231 public void release()
232 {
233 testStepStatisticHistories.remove( testStepIndex );
234 }
235 }
236
237 private class StatisticsValueHistory extends StatisticsHistoryModel
238 {
239 private final Statistic statistic;
240
241 public StatisticsValueHistory(Statistic statistic)
242 {
243 this.statistic = statistic;
244 }
245
246 public Statistic getStatistic()
247 {
248 return statistic;
249 }
250
251 public int getRowCount()
252 {
253 return data.size();
254 }
255
256 public int getColumnCount()
257 {
258 return statistics.getRowCount()+1;
259 }
260
261 public Object getValueAt(int rowIndex, int columnIndex)
262 {
263 if( columnIndex == 0 )
264 return threadCounts.get( rowIndex );
265
266 return data.get( rowIndex )[columnIndex-1][statistic.getIndex()];
267 }
268
269 public Class<?> getColumnClass(int columnIndex)
270 {
271 return Long.class;
272 }
273
274 public String getColumnName(int column)
275 {
276 if( column == 0 )
277 return "ThreadCount";
278
279 if( column == statistics.getRowCount() )
280 return "Total";
281
282 return statistics.getLoadTest().getTestCase().getTestStepAt( column-1 ).getName();
283 }
284
285 public void release()
286 {
287 statisticsValueHistories.remove( statistic );
288 }
289 }
290
291 private class InternalTableModelListener implements TableModelListener
292 {
293 public synchronized void tableChanged(TableModelEvent e)
294 {
295 if( (resolution > 0 && statistics.getLoadTest().isRunning()) ||
296 e.getType() != TableModelEvent.UPDATE ) return;
297 updateHistory();
298 }
299 }
300
301 private final class Updater implements Runnable
302 {
303 public void run()
304 {
305 while( resolution > 0 && statistics.getLoadTest().isRunning() )
306 {
307 try
308 {
309 updateHistory();
310 Thread.sleep( resolution );
311 }
312 catch( InterruptedException e )
313 {
314 e.printStackTrace();
315 break;
316 }
317 }
318 }
319 }
320 }