View Javadoc

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