1 /******************************************************************************* 2 * Copyright (c) 2000, 2016 IBM Corporation and others. 3 * 4 * This program and the accompanying materials are made 5 * available under the terms of the Eclipse Public License 2.0 which accompanies this distribution, and is available at 6 * https://www.eclipse.org/legal/epl-2.0/ 7 * 8 * SPDX-License-Identifier: EPL-2.0 9 * 10 * Contributors: IBM Corporation - initial API and implementation 11 *******************************************************************************/ 12 13 package org.eclipse.test.internal.performance.db; 14 15 import java.io.File; 16 import java.io.PrintWriter; 17 import java.sql.Connection; 18 import java.sql.DriverManager; 19 import java.sql.ResultSet; 20 import java.sql.SQLException; 21 import java.sql.Timestamp; 22 import java.util.ArrayList; 23 import java.util.Arrays; 24 import java.util.HashMap; 25 import java.util.List; 26 import java.util.Map; 27 import java.util.Set; 28 import java.util.regex.Matcher; 29 import java.util.regex.Pattern; 30 31 import org.eclipse.test.internal.performance.InternalPerformanceMeter; 32 import org.eclipse.test.internal.performance.PerformanceTestPlugin; 33 import org.eclipse.test.internal.performance.data.DataPoint; 34 import org.eclipse.test.internal.performance.data.Dim; 35 import org.eclipse.test.internal.performance.data.Sample; 36 import org.eclipse.test.internal.performance.data.Scalar; 37 import org.eclipse.test.internal.performance.eval.StatisticsSession; 38 import org.eclipse.test.performance.Dimension; 39 import org.eclipse.test.performance.Performance; 40 import org.junit.Assert; 41 42 public class DB { 43 44 private static final boolean DEBUG = false; 45 private static final boolean INFO = true; 46 private static final boolean AGGREGATE = true; 47 48 // the two supported DB types 49 private static final String DERBY = "derby"; //$NON-NLS-1$ 50 private static final String CLOUDSCAPE = "cloudscape"; //$NON-NLS-1$ 51 52 private static DB fgDefault; 53 findClosest(final String[] names, final String name)54 private static String findClosest(final String[] names, final String name) { 55 for (String name2 : names) { 56 if (name2.equals(name)) { 57 return name; 58 } 59 } 60 // dw 7/16/2016: assuming this pattern is supposed to be JUST the date part of build id 61 // yyyymmdd 62 // There are probably much better patterns than even my "quick and dirty" method? 63 final Pattern pattern = Pattern.compile("20[0-9][0-9][01][0-9][0-3][0-9]"); //$NON-NLS-1$ 64 // This poorly hardcoded pattern could have one of the big limitations in finding the "right" version to use in plots? 65 // final Pattern pattern = Pattern.compile("200[3-9][01][0-9][0-3][0-9]"); //$NON-NLS-1$ 66 67 final Matcher matcher = pattern.matcher(name); 68 69 if (!matcher.find()) { 70 return name; 71 } 72 73 final int x = Integer.parseInt(name.substring(matcher.start(), matcher.end())); 74 int ix = -1; 75 int mind = 0; 76 77 for (int i = 0; i < names.length; i++) { 78 matcher.reset(names[i]); 79 if (matcher.find()) { 80 final int y = Integer.parseInt(names[i].substring(matcher.start(), matcher.end())); 81 final int d = Math.abs(y - x); 82 if ((ix < 0) || (d < mind)) { 83 mind = d; 84 ix = i; 85 } 86 } 87 } 88 89 if (ix >= 0) { 90 return names[ix]; 91 } 92 return name; 93 } 94 getConnection()95 public static Connection getConnection() { 96 return getDefault().fConnection; 97 } 98 getDefault()99 synchronized static DB getDefault() { 100 if (fgDefault == null) { 101 fgDefault = new DB(); 102 fgDefault.connect(); 103 if (PerformanceTestPlugin.getDefault() == null) { 104 // not started as plugin 105 Runtime.getRuntime().addShutdownHook(new Thread() { 106 107 @Override 108 public void run() { 109 shutdown(); 110 } 111 }); 112 } 113 } 114 return fgDefault; 115 } 116 getScenarioSeries(final String scenarioName, Variations v, final String seriesKey, final String startBuild, final String endBuild, final Dim[] dims)117 public static Scenario getScenarioSeries(final String scenarioName, Variations v, final String seriesKey, 118 final String startBuild, final String endBuild, final Dim[] dims) { 119 v = (Variations) v.clone(); 120 v.put(seriesKey, new String[] { startBuild, endBuild }); 121 final Scenario.SharedState ss = new Scenario.SharedState(v, scenarioName, seriesKey, dims); 122 Scenario scenario = new Scenario(scenarioName, ss); 123 final TimeSeries ts = scenario.getTimeSeries(dims[0]); 124 if (ts.getLength() < 2) { 125 v.put(seriesKey, "%"); //$NON-NLS-1$ 126 final String[] names = DB.querySeriesValues(scenarioName, v, seriesKey); 127 if (names.length >= 2) { 128 final String start = findClosest(names, startBuild); 129 final String end = findClosest(names, endBuild); 130 v.put(seriesKey, new String[] { start, end }); 131 scenario = new Scenario(scenarioName, ss); 132 } 133 } 134 return scenario; 135 } 136 isActive()137 public static boolean isActive() { 138 return (fgDefault != null) && (fgDefault.getSQL() != null); 139 } 140 141 /** 142 * @param variations 143 * used to tag the data in the database 144 * @param sample 145 * the sample maked as failed 146 * @param failMesg 147 * the reason of the failure 148 */ markAsFailed(final Variations variations, final Sample sample, final String failMesg)149 public static void markAsFailed(final Variations variations, final Sample sample, final String failMesg) { 150 getDefault().internalMarkAsFailed(variations, sample, failMesg); 151 } 152 153 /** 154 * @param names 155 * @param variationPatterns 156 * @param scenarioPattern 157 * @deprecated Use queryDistinctValues instead 158 */ 159 @Deprecated queryBuildNames(final List<String> names, final Variations variationPatterns, final String scenarioPattern)160 public static void queryBuildNames(final List<String> names, final Variations variationPatterns, final String scenarioPattern) { 161 getDefault().internalQueryDistinctValues(names, PerformanceTestPlugin.BUILD, variationPatterns, scenarioPattern); 162 } 163 164 // Datapaoints queryDataPoints(final Variations variations, final String scenarioName, final Set<Dim> dims)165 public static DataPoint[] queryDataPoints(final Variations variations, final String scenarioName, final Set<Dim> dims) { 166 return getDefault().internalQueryDataPoints(variations, scenarioName, dims); 167 } 168 queryDistinctValues(final List<String> values, final String key, final Variations variationPatterns, final String scenarioPattern)169 public static void queryDistinctValues(final List<String> values, final String key, final Variations variationPatterns, 170 final String scenarioPattern) { 171 getDefault().internalQueryDistinctValues(values, key, variationPatterns, scenarioPattern); 172 } 173 queryFailure(final String scenarioPattern, final Variations variations)174 public static Map<String, String> queryFailure(final String scenarioPattern, final Variations variations) { 175 return getDefault().internalQueryFailure(scenarioPattern, variations); 176 } 177 178 /** 179 * @param configName 180 * @param buildPatterns 181 * @param scenarioName 182 * @return Scenario 183 * @deprecated Use queryScenarios(Variations variations, ...) instead 184 */ 185 @Deprecated queryScenario(final String configName, final String[] buildPatterns, final String scenarioName)186 public static Scenario queryScenario(final String configName, final String[] buildPatterns, final String scenarioName) { 187 final Variations variations = new Variations(); 188 variations.put(PerformanceTestPlugin.CONFIG, configName); 189 variations.put(PerformanceTestPlugin.BUILD, buildPatterns); 190 return new Scenario(scenarioName, variations, PerformanceTestPlugin.BUILD, null); 191 } 192 193 // Scenarios 194 /** 195 * Return all Scenarios that match the given config, build, and scenario name. 196 * 197 * @param configName 198 * @param buildPattern 199 * @param scenarioPattern 200 * @return array of scenarios 201 * @deprecated Use queryScenarios(Variations variations, ...) instead 202 */ 203 @Deprecated queryScenarios(final String configName, final String buildPattern, final String scenarioPattern)204 public static Scenario[] queryScenarios(final String configName, final String buildPattern, final String scenarioPattern) { 205 final Variations variations = new Variations(); 206 variations.put(PerformanceTestPlugin.CONFIG, configName); 207 variations.put(PerformanceTestPlugin.BUILD, buildPattern); 208 return queryScenarios(variations, scenarioPattern, PerformanceTestPlugin.BUILD, null); 209 } 210 211 /** 212 * @param configName 213 * @param buildPatterns 214 * @param scenarioPattern 215 * @param dimensions 216 * @return array of scenarios 217 * @deprecated Use queryScenarios(Variations variations, ...) instead 218 */ 219 @Deprecated queryScenarios(final String configName, final String[] buildPatterns, final String scenarioPattern, final Dim[] dimensions)220 public static Scenario[] queryScenarios(final String configName, final String[] buildPatterns, final String scenarioPattern, 221 final Dim[] dimensions) { 222 final Variations variations = new Variations(); 223 variations.put(PerformanceTestPlugin.CONFIG, configName); 224 variations.put(PerformanceTestPlugin.BUILD, buildPatterns); 225 return queryScenarios(variations, scenarioPattern, PerformanceTestPlugin.BUILD, dimensions); 226 } 227 228 /** 229 * Returns all Scenarios that match the given variation and scenario pattern. Every Scenario returned contains a series of 230 * datapoints specified by the seriesKey. 231 * 232 * For example to get the datapoints for For every Scenario only the specified Diemnsions are retrieved from the database. 233 * 234 * @param variations 235 * @param scenarioPattern 236 * @param seriesKey 237 * @param dimensions 238 * @return array of scenarios or <code>null</code> if an error occured. 239 */ queryScenarios(final Variations variations, final String scenarioPattern, final String seriesKey, final Dim[] dimensions)240 public static Scenario[] queryScenarios(final Variations variations, final String scenarioPattern, final String seriesKey, 241 final Dim[] dimensions) { 242 // get all Scenario names 243 final String[] scenarioNames = getDefault().internalQueryScenarioNames(variations, scenarioPattern); 244 if (scenarioNames == null) { 245 return new Scenario[0]; 246 } 247 final Scenario.SharedState ss = new Scenario.SharedState(variations, scenarioPattern, seriesKey, dimensions); 248 final Scenario[] tables = new Scenario[scenarioNames.length]; 249 for (int i = 0; i < scenarioNames.length; i++) { 250 tables[i] = new Scenario(scenarioNames[i], ss); 251 } 252 return tables; 253 } 254 querySeriesValues(final String scenarioName, final Variations v, final String seriesKey)255 public static String[] querySeriesValues(final String scenarioName, final Variations v, final String seriesKey) { 256 return getDefault().internalQuerySeriesValues(v, scenarioName, seriesKey); 257 } 258 259 /** 260 * Returns all summaries that match the given variation and scenario patterns. If scenarioPattern is null, all summary scenarios 261 * are returned that are marked as "global". If scenarioPattern is not null, it is used to filter the scenarios and only 262 * scenarios marked as "local" are returned. 263 * 264 * @param variationPatterns 265 * @param scenarioPattern 266 * @return array of summaries or <code>null</code> if an error occured. 267 */ querySummaries(final Variations variationPatterns, final String scenarioPattern)268 public static SummaryEntry[] querySummaries(final Variations variationPatterns, final String scenarioPattern) { 269 return getDefault().internalQuerySummaries(variationPatterns, scenarioPattern); 270 } 271 shutdown()272 public static void shutdown() { 273 if (DEBUG) { 274 System.out.println("DB.shutdown"); //$NON-NLS-1$ 275 } 276 if (fgDefault != null) { 277 fgDefault.disconnect(); 278 fgDefault = null; 279 } 280 } 281 282 /** 283 * Store the data contained in the given sample in the database. The data is tagged with key/value pairs from variations. 284 * 285 * @param variations 286 * used to tag the data in the database 287 * @param sample 288 * the sample to store 289 * @return returns true if data could be stored successfully 290 */ store(final Variations variations, final Sample sample)291 public static boolean store(final Variations variations, final Sample sample) { 292 return getDefault().internalStore(variations, sample); 293 } 294 295 private Connection fConnection; 296 297 private SQL fSQL; 298 299 private int fStoredSamples; 300 301 private boolean fStoreCalled; 302 303 // ---- private implementation 304 305 private boolean fIsEmbedded; 306 307 /* fDBType is either "derby" or "cloudscape" */ 308 private String fDBType; 309 310 /** 311 * Private constructor to block instance creation. 312 */ DB()313 private DB() { 314 // empty implementation 315 } 316 317 /** 318 * dbloc= embed in home directory dbloc=/tmp/performance embed given location dbloc=net://localhost connect to local server 319 * dbloc=net://www.eclipse.org connect to remove server 320 */ connect()321 private void connect() { 322 323 if (fConnection != null) { 324 return; 325 } 326 327 if (DEBUG) { 328 DriverManager.setLogWriter(new PrintWriter(System.out)); 329 } 330 final String dbloc = PerformanceTestPlugin.getDBLocation(); 331 if (dbloc == null) { 332 return; 333 } 334 335 final String dbname = PerformanceTestPlugin.getDBName(); 336 String url = null; 337 final java.util.Properties info = new java.util.Properties(); 338 339 fDBType = DERBY; // assume we are using Derby 340 try { 341 if (dbloc.startsWith("net://")) { //$NON-NLS-1$ 342 // remote 343 fIsEmbedded = false; 344 // connect over network 345 // connect over network 346 final String driverName = "org.apache.derby.jdbc.ClientDriver"; //$NON-NLS-1$ 347 if (INFO) { 348 System.out.println("Trying to connect over network, with net:// protocol; " + driverName + " ..."); //$NON-NLS-1$ //$NON-NLS-2$ 349 } 350 Class.forName(driverName); 351 //Class.forName("com.ibm.db2.jcc.DB2Driver"); //$NON-NLS-1$ 352 info.put("user", PerformanceTestPlugin.getDBUser()); //$NON-NLS-1$ 353 info.put("password", PerformanceTestPlugin.getDBPassword()); //$NON-NLS-1$ 354 info.put("retrieveMessagesFromServerOnGetMessage", "true"); //$NON-NLS-1$ //$NON-NLS-2$ 355 url = dbloc + "/" + dbname + ";create=true"; //$NON-NLS-1$//$NON-NLS-2$ 356 } else if (dbloc.startsWith("//")) { //$NON-NLS-1$ 357 // remote 358 fIsEmbedded = false; 359 // connect over network 360 final String driverName = "org.apache.derby.jdbc.ClientDriver"; //$NON-NLS-1$ 361 if (INFO) { 362 System.out 363 .println("Trying to connect over network with // jdbc protocol; " + driverName + " to " + dbloc + '/' + dbname + " ..."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 364 } 365 Class.forName(driverName); 366 info.put("user", PerformanceTestPlugin.getDBUser()); //$NON-NLS-1$ 367 info.put("password", PerformanceTestPlugin.getDBPassword()); //$NON-NLS-1$ 368 info.put("create", "true"); //$NON-NLS-1$ //$NON-NLS-2$ 369 url = dbloc + '/' + dbname; 370 } else { 371 372 // workaround for Derby issue: 373 // http://nagoya.apache.org/jira/browse/DERBY-1 374 if ("Mac OS X".equals(System.getProperty("os.name"))) { //$NON-NLS-1$ //$NON-NLS-2$ 375 System.setProperty("derby.storage.fileSyncTransactionLog", "true"); //$NON-NLS-1$ //$NON-NLS-2$ 376 } 377 378 // embedded 379 fIsEmbedded = true; 380 try { 381 Class.forName("org.apache.derby.jdbc.EmbeddedDriver"); //$NON-NLS-1$ 382 } 383 catch (final ClassNotFoundException e) { 384 Class.forName("com.ihost.cs.jdbc.CloudscapeDriver"); //$NON-NLS-1$ 385 fDBType = CLOUDSCAPE; 386 } 387 if (DEBUG) { 388 System.out.println("Loaded embedded " + fDBType); //$NON-NLS-1$ 389 } 390 File f; 391 if (dbloc.length() == 0) { 392 final String user_home = System.getProperty("user.home"); //$NON-NLS-1$ 393 if (user_home == null) { 394 return; 395 } 396 f = new File(user_home, fDBType); 397 } else { 398 f = new File(dbloc); 399 } 400 url = new File(f, dbname).getAbsolutePath(); 401 info.put("user", PerformanceTestPlugin.getDBUser()); //$NON-NLS-1$ 402 info.put("password", PerformanceTestPlugin.getDBPassword()); //$NON-NLS-1$ 403 info.put("create", "true"); //$NON-NLS-1$ //$NON-NLS-2$ 404 } 405 try { 406 fConnection = DriverManager.getConnection("jdbc:" + fDBType + ":" + url, info); //$NON-NLS-1$ //$NON-NLS-2$ 407 } 408 catch (final SQLException e) { 409 System.out.println("SQLException: " + e); //$NON-NLS-1$ 410 if ("08001".equals(e.getSQLState()) && DERBY.equals(fDBType)) { //$NON-NLS-1$ 411 if (DEBUG) { 412 System.out.println("DriverManager.getConnection failed; retrying for cloudscape"); //$NON-NLS-1$ 413 } 414 // try Cloudscape 415 fDBType = CLOUDSCAPE; 416 fConnection = DriverManager.getConnection("jdbc:" + fDBType + ":" + url, info); //$NON-NLS-1$ //$NON-NLS-2$ 417 } else { 418 throw e; 419 } 420 } 421 if (INFO) { 422 System.out.println("connect succeeded!"); //$NON-NLS-1$ 423 } 424 425 fConnection.setAutoCommit(false); 426 fSQL = new SQL(fConnection); 427 fConnection.commit(); 428 429 } 430 catch (final SQLException ex) { 431 PerformanceTestPlugin.logError(ex.getMessage()); 432 433 } 434 catch (final ClassNotFoundException e) { 435 PerformanceTestPlugin.log(e); 436 } 437 } 438 disconnect()439 private void disconnect() { 440 if (INFO) { 441 if (fStoreCalled) { 442 System.out.println("stored " + fStoredSamples + " new datapoints in DB"); //$NON-NLS-1$ //$NON-NLS-2$ 443 } else { 444 System.out.println("no new datapoints in DB"); //$NON-NLS-1$ 445 } 446 System.out.println("disconnecting from DB"); //$NON-NLS-1$ 447 } 448 if (fSQL != null) { 449 try { 450 fSQL.dispose(); 451 } 452 catch (final SQLException e1) { 453 PerformanceTestPlugin.log(e1); 454 } 455 fSQL = null; 456 } 457 if (fConnection != null) { 458 try { 459 fConnection.commit(); 460 } 461 catch (final SQLException e) { 462 PerformanceTestPlugin.log(e); 463 } 464 try { 465 fConnection.close(); 466 } 467 catch (final SQLException e) { 468 PerformanceTestPlugin.log(e); 469 } 470 fConnection = null; 471 } 472 473 if (fIsEmbedded) { 474 try { 475 DriverManager.getConnection("jdbc:" + fDBType + ":;shutdown=true"); //$NON-NLS-1$ //$NON-NLS-2$ 476 } 477 catch (final SQLException e) { 478 final String message = e.getMessage(); 479 if (message.indexOf("system shutdown.") < 0) { //$NON-NLS-1$ 480 e.printStackTrace(); 481 } 482 } 483 } 484 } 485 getSQL()486 SQL getSQL() { 487 return fSQL; 488 } 489 internalMarkAsFailed(final Variations variations, final Sample sample, final String failMesg)490 private void internalMarkAsFailed(final Variations variations, final Sample sample, final String failMesg) { 491 492 if (fSQL == null) { 493 return; 494 } 495 496 try { 497 final int variation_id = fSQL.getVariations(variations); 498 final int scenario_id = fSQL.getScenario(sample.getScenarioID()); 499 500 fSQL.insertFailure(variation_id, scenario_id, failMesg); 501 502 fConnection.commit(); 503 504 } 505 catch (final SQLException e) { 506 PerformanceTestPlugin.log(e); 507 try { 508 fConnection.rollback(); 509 } 510 catch (final SQLException e1) { 511 PerformanceTestPlugin.log(e1); 512 } 513 } 514 } 515 internalQueryDataPoints(final Variations variations, final String scenarioName, final Set<Dim> dimSet)516 private DataPoint[] internalQueryDataPoints(final Variations variations, final String scenarioName, final Set<Dim> dimSet) { 517 if (fSQL == null) { 518 return null; 519 } 520 521 long start = System.currentTimeMillis(); 522 if (DEBUG) { 523 System.out.print(" - query data points from DB for scenario " + scenarioName + "..."); //$NON-NLS-1$ //$NON-NLS-2$ 524 } 525 526 final ArrayList<DataPoint> dataPoints = new ArrayList<>(); 527 try (ResultSet rs = fSQL.queryDataPoints(variations, scenarioName)){ 528 if (DEBUG) { 529 final long time = System.currentTimeMillis(); 530 System.out.println("done in " + (time - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ 531 start = time; 532 } 533 while (rs.next()) { 534 final int datapoint_id = rs.getInt(1); 535 final int step = rs.getInt(2); 536 537 final HashMap<Dim, Scalar> map = new HashMap<>(); 538 try (final ResultSet rs2 = fSQL.queryScalars(datapoint_id)) { 539 while (rs2.next()) { 540 final int dim_id = rs2.getInt(1); 541 final long value = rs2.getBigDecimal(2).longValue(); 542 final Dim dim = Dim.getDimension(dim_id); 543 if (dim != null) { 544 if ((dimSet == null) || dimSet.contains(dim)) { 545 map.put(dim, new Scalar(dim, value)); 546 } 547 } 548 } 549 if (map.size() > 0) { 550 dataPoints.add(new DataPoint(step, map)); 551 } 552 553 } 554 } 555 final int n = dataPoints.size(); 556 if (DEBUG) { 557 final long time = System.currentTimeMillis(); 558 System.out.println(" + " + n + " datapoints created in " + (time - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 559 } 560 return dataPoints.toArray(new DataPoint[n]); 561 562 } 563 catch (final SQLException e) { 564 PerformanceTestPlugin.log(e); 565 } 566 return null; 567 } 568 569 /* 570 * 571 */ internalQueryDistinctValues(final List<String> values, final String seriesKey, final Variations variations, final String scenarioPattern)572 private void internalQueryDistinctValues(final List<String> values, final String seriesKey, final Variations variations, 573 final String scenarioPattern) { 574 if (fSQL == null) { 575 return; 576 } 577 final long start = System.currentTimeMillis(); 578 if (DEBUG) { 579 System.out.print(" - query distinct values from DB for scenario pattern '" + scenarioPattern + "'..."); //$NON-NLS-1$ //$NON-NLS-2$ 580 } 581 try (ResultSet result = fSQL.queryVariations(variations.toExactMatchString(), scenarioPattern)){ 582 while (result.next()) { 583 final Variations v = new Variations(); 584 v.parseDB(result.getString(1)); 585 final String build = v.getProperty(seriesKey); 586 if ((build != null) && !values.contains(build)) { 587 values.add(build); 588 } 589 } 590 } catch (final SQLException e) { 591 PerformanceTestPlugin.log(e); 592 593 } finally { 594 if (DEBUG) { 595 final long time = System.currentTimeMillis(); 596 System.out.println("done in " + (time - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ 597 } 598 } 599 } 600 internalQueryFailure(final String scenarioPattern, final Variations variations)601 private Map<String, String> internalQueryFailure(final String scenarioPattern, final Variations variations) { 602 if (fSQL == null) { 603 return null; 604 } 605 final long start = System.currentTimeMillis(); 606 if (DEBUG) { 607 System.out.print(" - query failure from DB for scenario pattern '" + scenarioPattern + "'..."); //$NON-NLS-1$ //$NON-NLS-2$ 608 } 609 try (ResultSet result = fSQL.queryFailure(variations, scenarioPattern)) { 610 final Map<String, String> map = new HashMap<>(); 611 while (result.next()) { 612 final String scenario = result.getString(1); 613 final String message = result.getString(2); 614 map.put(scenario, message); 615 } 616 return map; 617 } catch (final SQLException e) { 618 PerformanceTestPlugin.log(e); 619 620 } finally { 621 if (DEBUG) { 622 final long time = System.currentTimeMillis(); 623 System.out.println("done in " + (time - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ 624 } 625 } 626 return null; 627 } 628 629 /* 630 * Returns array of scenario names matching the given pattern. 631 */ internalQueryScenarioNames(final Variations variations, final String scenarioPattern)632 private String[] internalQueryScenarioNames(final Variations variations, final String scenarioPattern) { 633 if (fSQL == null) { 634 return null; 635 } 636 final long start = System.currentTimeMillis(); 637 if (DEBUG) { 638 System.out.print(" - query scenario names from DB for scenario pattern '" + scenarioPattern + "'..."); //$NON-NLS-1$ //$NON-NLS-2$ 639 } 640 try (ResultSet result = fSQL.queryScenarios(variations, scenarioPattern)) { 641 final ArrayList<String> scenarios = new ArrayList<>(); 642 while (result.next()) { 643 scenarios.add(result.getString(1)); 644 } 645 return scenarios.toArray(new String[scenarios.size()]); 646 } catch (final SQLException e) { 647 PerformanceTestPlugin.log(e); 648 } finally { 649 if (DEBUG) { 650 final long time = System.currentTimeMillis(); 651 System.out.println("done in " + (time - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ 652 } 653 } 654 return null; 655 } 656 internalQuerySeriesValues(Variations v, final String scenarioName, final String seriesKey)657 private String[] internalQuerySeriesValues(Variations v, final String scenarioName, final String seriesKey) { 658 659 boolean isCloned = false; 660 661 String[] seriesPatterns = null; 662 final Object object = v.get(seriesKey); 663 if (object instanceof String[]) { 664 seriesPatterns = (String[]) object; 665 } else if (object instanceof String) { 666 seriesPatterns = new String[] { (String) object }; 667 } else { 668 Assert.assertTrue(false); 669 } 670 671 final ArrayList<String> values = new ArrayList<>(); 672 for (String seriesPattern : seriesPatterns) { 673 if (seriesPattern.indexOf('%') >= 0) { 674 if (!isCloned) { 675 v = (Variations) v.clone(); 676 isCloned = true; 677 } 678 v.put(seriesKey, seriesPattern); 679 internalQueryDistinctValues(values, seriesKey, v, scenarioName); 680 } else { 681 values.add(seriesPattern); 682 } 683 } 684 685 final String[] names = values.toArray(new String[values.size()]); 686 687 boolean sort = true; 688 final Pattern pattern = Pattern.compile("20[0-9][3-9][01][0-9][0-3][0-9]"); //$NON-NLS-1$ 689 final Matcher matcher = pattern.matcher(""); //$NON-NLS-1$ 690 for (String name : names) { 691 matcher.reset(name); 692 if (!matcher.find()) { 693 sort = false; 694 break; 695 } 696 } 697 if (sort) { 698 Arrays.sort(names, (o1, o2) -> { 699 String s1 = o1; 700 String s2 = o2; 701 702 matcher.reset(s1); 703 if (matcher.find()) { 704 s1 = s1.substring(matcher.start()); 705 } 706 707 matcher.reset(s2); 708 if (matcher.find()) { 709 s2 = s2.substring(matcher.start()); 710 } 711 712 return s1.compareTo(s2); 713 }); 714 } 715 return names; 716 } 717 internalQuerySummaries(final Variations variationPatterns, final String scenarioPattern)718 private SummaryEntry[] internalQuerySummaries(final Variations variationPatterns, final String scenarioPattern) { 719 if (fSQL == null) { 720 return null; 721 } 722 final long start = System.currentTimeMillis(); 723 if (DEBUG) { 724 System.out.print(" - query summaries from DB for scenario pattern '" + scenarioPattern + "'..."); //$NON-NLS-1$ //$NON-NLS-2$ 725 } 726 ResultSet result = null; 727 try { 728 final List<SummaryEntry> fingerprints = new ArrayList<>(); 729 if (scenarioPattern != null) { 730 result = fSQL.querySummaryEntries(variationPatterns, scenarioPattern); 731 } else { 732 result = fSQL.queryGlobalSummaryEntries(variationPatterns); 733 } 734 while (result.next()) { 735 final String scenarioName = result.getString(1); 736 final String shortName = result.getString(2); 737 final int dim_id = result.getInt(3); 738 final boolean isGlobal = result.getShort(4) == 1; 739 final int comment_id = result.getInt(5); 740 int commentKind = 0; 741 String comment = null; 742 if (comment_id != 0) { 743 try (final ResultSet rs2 = fSQL.getComment(comment_id)) { 744 if (rs2.next()) { 745 commentKind = rs2.getInt(1); 746 comment = rs2.getString(2); 747 } 748 } 749 } 750 if (dim_id != 0) { 751 fingerprints.add(new SummaryEntry(scenarioName, shortName, Dim.getDimension(dim_id), isGlobal, commentKind, 752 comment)); 753 } 754 } 755 return fingerprints.toArray(new SummaryEntry[fingerprints.size()]); 756 } 757 catch (final SQLException e) { 758 PerformanceTestPlugin.log(e); 759 } 760 finally { 761 if (result != null) { 762 try { 763 result.close(); 764 } 765 catch (final SQLException e1) { 766 // ignored 767 } 768 } 769 if (DEBUG) { 770 final long time = System.currentTimeMillis(); 771 System.out.println("done in " + (time - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ 772 } 773 } 774 return null; 775 } 776 internalStore(final Variations variations, final Sample sample)777 private boolean internalStore(final Variations variations, final Sample sample) { 778 779 if ((fSQL == null) || (sample == null)) { 780 return false; 781 } 782 783 final DataPoint[] dataPoints = sample.getDataPoints(); 784 final int n = dataPoints.length; 785 if (n <= 0) { 786 return false; 787 } 788 789 //System.out.println("store started..."); //$NON-NLS-1$ 790 try { 791 // long l= System.currentTimeMillis(); 792 final int variation_id = fSQL.getVariations(variations); 793 final int scenario_id = fSQL.getScenario(sample.getScenarioID()); 794 final String comment = sample.getComment(); 795 if (sample.isSummary()) { 796 final boolean isGlobal = sample.isGlobal(); 797 798 int commentId = 0; 799 final int commentKind = sample.getCommentType(); 800 if ((commentKind == Performance.EXPLAINS_DEGRADATION_COMMENT) && (comment != null)) { 801 commentId = fSQL.getCommentId(commentKind, comment); 802 } 803 804 final Dimension[] summaryDimensions = sample.getSummaryDimensions(); 805 for (final Dimension dimension : summaryDimensions) { 806 if (dimension instanceof Dim) { 807 fSQL.createSummaryEntry(variation_id, scenario_id, ((Dim) dimension).getId(), isGlobal, commentId); 808 } 809 } 810 final String shortName = sample.getShortname(); 811 if (shortName != null) { 812 fSQL.setScenarioShortName(scenario_id, shortName); 813 } 814 } else if (comment != null) { 815 int commentId = 0; 816 final int commentKind = sample.getCommentType(); 817 if (commentKind == Performance.EXPLAINS_DEGRADATION_COMMENT) { 818 commentId = fSQL.getCommentId(commentKind, comment); 819 } 820 fSQL.createSummaryEntry(variation_id, scenario_id, 0, false, commentId); // use 821 // special 822 // dim 823 // id 824 // '0' 825 // to 826 // identify 827 // summary 828 // entry 829 // created 830 // to 831 // only 832 // handle 833 // a 834 // comment 835 } 836 final int sample_id = fSQL.createSample(variation_id, scenario_id, new Timestamp(sample.getStartTime())); 837 838 if (AGGREGATE) { 839 final StatisticsSession stats = new StatisticsSession(dataPoints); 840 final Dim[] dims = dataPoints[0].getDimensions(); 841 842 int datapoint_id = fSQL.createDataPoint(sample_id, 0, InternalPerformanceMeter.AVERAGE); 843 for (final Dim dim : dims) { 844 fSQL.insertScalar(datapoint_id, dim.getId(), (long) stats.getAverage(dim)); 845 } 846 847 datapoint_id = fSQL.createDataPoint(sample_id, 0, InternalPerformanceMeter.STDEV); 848 for (final Dim dim : dims) { 849 // see StatisticsSession 850 final long value = Double.doubleToLongBits(stats.getStddev(dim)); 851 fSQL.insertScalar(datapoint_id, dim.getId(), value); 852 } 853 854 datapoint_id = fSQL.createDataPoint(sample_id, 0, InternalPerformanceMeter.SIZE); 855 for (final Dim dim : dims) { 856 fSQL.insertScalar(datapoint_id, dim.getId(), stats.getCount(dim)); 857 } 858 } else { 859 for (int i = 0; i < dataPoints.length; i++) { 860 final DataPoint dp = dataPoints[i]; 861 final int datapoint_id = fSQL.createDataPoint(sample_id, i, dp.getStep()); 862 final Scalar[] scalars = dp.getScalars(); 863 for (final Scalar scalar : scalars) { 864 final int dim_id = scalar.getDimension().getId(); 865 final long value = scalar.getMagnitude(); 866 fSQL.insertScalar(datapoint_id, dim_id, value); 867 } 868 } 869 } 870 871 fConnection.commit(); 872 fStoredSamples++; 873 fStoreCalled = true; 874 875 // System.err.println(System.currentTimeMillis()-l); 876 877 } 878 catch (final SQLException e) { 879 PerformanceTestPlugin.log(e); 880 try { 881 fConnection.rollback(); 882 } 883 catch (final SQLException e1) { 884 PerformanceTestPlugin.log(e1); 885 } 886 } 887 return true; 888 } 889 } 890