Home | History | Annotate | Download | only in db
      1 /*******************************************************************************
      2  * Copyright (c) 2000, 2009 IBM Corporation and others.
      3  * All rights reserved. This program and the accompanying materials
      4  * are made available under the terms of the Eclipse Public License v1.0
      5  * which accompanies this distribution, and is available at
      6  * http://www.eclipse.org/legal/epl-v10.html
      7  *
      8  * Contributors:
      9  *     IBM Corporation - initial API and implementation
     10  *******************************************************************************/
     11 package org.eclipse.test.internal.performance.results.db;
     12 
     13 import java.io.DataInputStream;
     14 import java.io.DataOutputStream;
     15 import java.io.IOException;
     16 import java.util.Arrays;
     17 import java.util.Comparator;
     18 import java.util.HashSet;
     19 import java.util.List;
     20 import java.util.Set;
     21 import java.util.StringTokenizer;
     22 
     23 import org.eclipse.test.internal.performance.results.utils.Util;
     24 
     25 
     26 /**
     27  * Class to handle performance results of a component's scenario
     28  * (for example 'org.eclipse.jdt.core.FullSourceWorkspaceSearchTest#searchAllTypeNames()').
     29  *
     30  * It gives access to results for each configuration run on this scenario.
     31  *
     32  * @see ConfigResults
     33  */
     34 public class ScenarioResults extends AbstractResults {
     35 	String fileName;
     36 	String label;
     37 	String shortName;
     38 
     39 public ScenarioResults(int id, String name, String shortName) {
     40 	super(null, id);
     41 	this.name = name;
     42 	this.label = shortName;
     43 }
     44 
     45 /*
     46  * Complete results with additional database information.
     47  */
     48 void completeResults(String lastBuildName) {
     49 	String[] builds = DB_Results.getBuilds();
     50 	class BuildDateComparator implements Comparator {
     51 		public int compare(Object o1, Object o2) {
     52 	        String s1 = (String) o1;
     53 	        String s2 = (String) o2;
     54 	        return Util.getBuildDate(s1).compareTo(Util.getBuildDate(s2));
     55 	    }
     56 	}
     57 	BuildDateComparator comparator = new BuildDateComparator();
     58 	Arrays.sort(builds, comparator);
     59 	int idx = Arrays.binarySearch(builds, lastBuildName, comparator);
     60 	if (idx < 0) {
     61 		builds = null;
     62 	} else {
     63 		int size = builds.length - ++idx;
     64 		System.arraycopy(builds, idx, builds = new String[size], 0, size);
     65 	}
     66 //	String[] builds = null;
     67 	int size = size();
     68 	for (int i=0; i<size; i++) {
     69 		ConfigResults configResults = (ConfigResults) this.children.get(i);
     70 		configResults.completeResults(builds);
     71 	}
     72 }
     73 
     74 /**
     75  * Returns the first configuration baseline build name.
     76  *
     77  * @return The name of the baseline build
     78  * @see ConfigResults#getBaselineBuildName()
     79  */
     80 public String getBaselineBuildName() {
     81 	int size = size();
     82 	StringBuffer buffer = new StringBuffer();
     83 	for (int i=0; i<size; i++) {
     84 		ConfigResults configResults = (ConfigResults) this.children.get(i);
     85 		if (configResults.isValid()) {
     86 			return configResults.getBaselineBuildName();
     87 			/* TODO (frederic) decide what return when baseline is not the same on all configs...
     88 			 * Currently returns the first found, but may be a comma-separated list?
     89 			String baselineName = configResults.getBaselineBuildName();
     90 			if (buffer.indexOf(baselineName) < 0) {
     91 				if (buffer.length() > 0) buffer.append('|');
     92 				buffer.append(baselineName);
     93 			}
     94 			*/
     95 		}
     96 	}
     97 	return buffer.toString();
     98 }
     99 
    100 Set getAllBuildNames() {
    101 	Set buildNames = new HashSet();
    102 	int size = size();
    103 	for (int i=0; i<size; i++) {
    104 		ConfigResults configResults = (ConfigResults) this.children.get(i);
    105 		List builds = configResults.getBuilds(null);
    106 		int length = builds.size();
    107 		for (int j=0; j<length; j++) {
    108 			buildNames.add(((BuildResults)builds.get(j)).getName());
    109 		}
    110 	}
    111 	return buildNames;
    112 }
    113 
    114 /**
    115  * Return the results of the given configuration.
    116  *
    117  * @param config The configuration name
    118  * @return The {@link ConfigResults results} for the given configuration
    119  * 	or <code>null</code> if none was found.
    120  */
    121 public ConfigResults getConfigResults(String config) {
    122 	return (ConfigResults) getResults(config);
    123 }
    124 
    125 /**
    126  * Return a name which can be used as a file name to store information
    127  * related to this scenario. This name does not contain the extension.
    128  *
    129  * @return The file name
    130  */
    131 public String getFileName() {
    132 	if (this.fileName == null) {
    133 		this.fileName = "Scenario" + this.id; //$NON-NLS-1$
    134 	}
    135 	return this.fileName;
    136 }
    137 
    138 /**
    139  * Returns the scenario label. If no label exist as there's no associated summary,
    140  * then the short name is returned
    141  *
    142  * @return The label of the scenario or it's short name if no summary exists
    143  */
    144 public String getLabel() {
    145 	return this.label == null ? getShortName() : this.label;
    146 }
    147 
    148 /**
    149  * Returns the short name of the scenario. Short name is the name scenario
    150  * from which package declaration has been removed.
    151  *
    152  * @return The scenario short name
    153  */
    154 public String getShortName() {
    155 	if (this.shortName == null) {
    156 		// Remove class name qualification
    157 		int testSeparator = this.name.indexOf('#');
    158 		boolean hasClassName = testSeparator >= 0;
    159 		if (!hasClassName) {
    160 			testSeparator = this.name.lastIndexOf('.');
    161 			if (testSeparator <= 0) {
    162 				return this.shortName = this.name;
    163 			}
    164 		}
    165 		int classSeparator = this.name.substring(0, testSeparator).lastIndexOf('.');
    166 		if (classSeparator < 0) {
    167 			return this.shortName = this.name;
    168 		}
    169 		int length = this.name.length();
    170 		String testName = this.name.substring(classSeparator+1, length);
    171 		if (!hasClassName && testName.startsWith("test.")) { // specific case for swt... //$NON-NLS-1$
    172 			testName = testName.substring(5);
    173 		}
    174 
    175 		// Remove qualification from test name
    176 		StringTokenizer tokenizer = new StringTokenizer(testName, " :,", true); //$NON-NLS-1$
    177 		StringBuffer buffer = new StringBuffer(tokenizer.nextToken());
    178 		while (tokenizer.hasMoreTokens()) {
    179 			String token = tokenizer.nextToken();
    180 			char fc = token.charAt(0);
    181 			while (fc == ' ' || fc == ',' || fc == ':') {
    182 				buffer.append(token); // add the separator
    183 				token = tokenizer.nextToken();
    184 				fc = token.charAt(0);
    185 			}
    186 			int last = token.lastIndexOf('.');
    187 			if (last >= 3) {
    188 				int first = token .indexOf('.');
    189 				if (first == last) {
    190 					buffer.append(token);
    191 				} else {
    192 					buffer.append(token.substring(last+1));
    193 				}
    194 			} else {
    195 				buffer.append(token);
    196 			}
    197 		}
    198 		this.shortName = buffer.toString();
    199 	}
    200 	return this.shortName;
    201 }
    202 
    203 /**
    204  * Returns whether one of the scenario's config has a summary or not.
    205  *
    206  * @return <code>true</code> if one of the scenario's config has a summary
    207  * 	<code>false</code> otherwise.
    208  */
    209 public boolean hasSummary() {
    210 	int size = size();
    211 	for (int i=0; i<size; i++) {
    212 		ConfigResults configResults = (ConfigResults) this.children.get(i);
    213 		BuildResults currentBuildResults = configResults.getCurrentBuildResults();
    214 		if (currentBuildResults != null && currentBuildResults.hasSummary()) return true;
    215 	}
    216 	return false;
    217 }
    218 
    219 /* (non-Javadoc)
    220  * @see org.eclipse.test.internal.performance.results.AbstractResults#hashCode()
    221  */
    222 public int hashCode() {
    223 	return this.id;
    224 }
    225 
    226 /**
    227  * Returns whether the current scenario is valid or not.
    228  *
    229  * @return <code>true</code> if all the builds contained in the database are
    230  * 	known by the scenario (ie. at least one its configuration knows each of the
    231  * 	db builds), <code>false</code> otherwise.
    232  */
    233 public boolean isValid() {
    234 	int size = this.children.size();
    235 	for (int i=0; i<size; i++) {
    236 		ConfigResults configResults = (ConfigResults) this.children.get(i);
    237 		if (configResults.isValid()) {
    238 			return true;
    239 		}
    240 	}
    241 	return false;
    242 }
    243 
    244 /**
    245  * Returns whether the current build of the given config has valid results or not.
    246  *
    247  * @param config The name of the configuration
    248  * @return <code>true</code> if the build has valid results
    249  * 	<code>false</code> otherwise.
    250  */
    251 public boolean isValid(String config) {
    252 	return getResults(config) != null;
    253 }
    254 
    255 /**
    256  * Returns whether the current scenario knows a build or not.
    257  *
    258  * @param buildName The name of the build
    259  * @return <code>true</code> if the at least one of scenario configuration
    260  * 	knows the given build, <code>false</code> otherwise.
    261  */
    262 public boolean knowsBuild(String buildName) {
    263 	String[] buildNames = buildName == null
    264 		? DB_Results.getBuilds()
    265 		: new String[] { buildName };
    266 	Set scenarioBuilds = getAllBuildNames();
    267 	int length = buildNames.length;
    268 	for (int i=0; i<length; i++) {
    269 		if (!scenarioBuilds.contains(buildNames[i])) {
    270 			return false;
    271 		}
    272 	}
    273 	return true;
    274 }
    275 
    276 /*
    277  * Read scenario results information from database.
    278  *
    279 void read(String buildName, long lastBuildTime) {
    280 
    281 	// Get values
    282 	print("	+ scenario '"+getShortName()+"': values..."); //$NON-NLS-1$ //$NON-NLS-2$
    283 	long start = System.currentTimeMillis();
    284 	String configPattern = getPerformance().getConfigurationsPattern();
    285 	DB_Results.queryScenarioValues(this, configPattern, buildName, lastBuildTime);
    286 	print(timeString(System.currentTimeMillis()-start));
    287 
    288 	// Set baseline and current builds
    289 	print(", infos..."); //$NON-NLS-1$
    290 	start = System.currentTimeMillis();
    291 	int size = size();
    292 	String[] builds = buildName == null ? null : new String[] { buildName };
    293 	for (int i=0; i<size; i++) {
    294 		ConfigResults configResults = (ConfigResults) this.children.get(i);
    295 		configResults.completeResults(builds);
    296 	}
    297 	println(timeString(System.currentTimeMillis()-start));
    298 }
    299 */
    300 
    301 /*
    302  * Read data from a local file
    303  */
    304 void readData(DataInputStream stream) throws IOException {
    305 
    306 	// Read data stored locally
    307 	int size = stream.readInt();
    308 	for (int i=0; i<size; i++) {
    309 		int config_id = stream.readInt();
    310 		ConfigResults configResults = (ConfigResults) getResults(config_id);
    311 		if (configResults == null) {
    312 			configResults = new ConfigResults(this, config_id);
    313 			addChild(configResults, true);
    314 		}
    315 		configResults.readData(stream);
    316 	}
    317 }
    318 
    319 /*
    320  * Read new data from the database.
    321  * This is typically needed when the build results are not in the local file...
    322  *
    323 boolean readNewData(String lastBuildName, boolean force) {
    324 	if (lastBuildName == null) {
    325 		read(null, -1);
    326 		return true;
    327 	}
    328 	PerformanceResults performanceResults = getPerformance();
    329 	String lastBuildDate = getBuildDate(lastBuildName, getBaselinePrefix());
    330 	if (force || performanceResults.getBuildDate().compareTo(lastBuildDate) > 0) {
    331 		long lastBuildTime = 0;
    332 	    try {
    333 		    lastBuildTime = DATE_FORMAT.parse(lastBuildDate).getTime();
    334 	    } catch (ParseException e) {
    335 		    // should not happen
    336 	    }
    337 	    read(lastBuildName, lastBuildTime);
    338 		return true;
    339 	}
    340 	return false;
    341 }
    342 */
    343 
    344 /*
    345  * Set value from database information.
    346  */
    347 void setInfos(int config_id, int build_id, int summaryKind, String comment) {
    348 	ConfigResults configResults = (ConfigResults) getResults(config_id);
    349 	if (configResults == null) {
    350 		configResults = new ConfigResults(this, config_id);
    351 		addChild(configResults, true);
    352 	}
    353 	configResults.setInfos(build_id, summaryKind, comment);
    354 }
    355 
    356 /*
    357  * Set value from database information.
    358  */
    359 void setValue(int build_id, int dim_id, int config_id, int step, long value) {
    360 	ConfigResults configResults = (ConfigResults) getResults(config_id);
    361 	if (configResults == null) {
    362 		configResults = new ConfigResults(this, config_id);
    363 		addChild(configResults, true);
    364 	}
    365 	configResults.setValue(build_id, dim_id, step, value);
    366 }
    367 
    368 /*
    369  * Read scenario results information from database.
    370  */
    371 boolean updateBuild(String buildName, boolean force) {
    372 
    373 	if (!force && knowsBuild(buildName)) {
    374 		return false;
    375 	}
    376 
    377 	// Get values
    378 	print("	+ scenario '"+getShortName()+"': values..."); //$NON-NLS-1$ //$NON-NLS-2$
    379 	long start = System.currentTimeMillis();
    380 	String configPattern = getPerformance().getConfigurationsPattern();
    381 	DB_Results.queryScenarioValues(this, configPattern, buildName);
    382 	print(Util.timeString(System.currentTimeMillis()-start));
    383 
    384 	// Set baseline and current builds
    385 	print(", infos..."); //$NON-NLS-1$
    386 	start = System.currentTimeMillis();
    387 	int size = size();
    388 	String[] builds = buildName == null ? null : new String[] { buildName };
    389 	for (int i=0; i<size; i++) {
    390 		ConfigResults configResults = (ConfigResults) this.children.get(i);
    391 		configResults.completeResults(builds);
    392 	}
    393 	println(Util.timeString(System.currentTimeMillis()-start));
    394 	return true;
    395 }
    396 
    397 void write(DataOutputStream stream) throws IOException {
    398 	int size = size();
    399 	stream.writeInt(this.id);
    400 	stream.writeInt(size);
    401 	for (int i=0; i<size; i++) {
    402 		ConfigResults configResults = (ConfigResults) this.children.get(i);
    403 		configResults.write(stream);
    404 	}
    405 }
    406 
    407 }
    408