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