1 16 package com.sun.slamd.example; 17 18 19 20 import java.sql.*; 21 import java.util.*; 22 import com.sun.slamd.job.*; 23 import com.sun.slamd.parameter.*; 24 import com.sun.slamd.stat.*; 25 26 27 28 29 37 public class SQLSearchRateJobClass 38 extends JobClass 39 { 40 44 public static final String STAT_TRACKER_EXCEPTIONS_CAUGHT = 45 "Exceptions Caught"; 46 47 48 49 53 public static final String STAT_TRACKER_QUERIES_COMPLETED = 54 "Queries Completed"; 55 56 57 58 62 public static final String STAT_TRACKER_QUERY_DURATION = 63 "Query Duration (ms)"; 64 65 66 67 71 public static final String STAT_TRACKER_ROWS_RETURNED = "Rows Returned"; 72 73 74 75 BooleanParameter disconnectParameter = 77 new BooleanParameter("disconnect", "Always Disconnect", 78 "Indicates whether the connection to the " + 79 "database should be dropped after each query.", 80 false); 81 82 IntegerParameter coolDownParameter = 84 new IntegerParameter("cool_down", "Cool Down Time (s)", 85 "Specifies the length of time in seconds before " + 86 "the job ends that it should stop collecting " + 87 "statistics.", true, 0, true, 0, false, 0); 88 89 IntegerParameter iterationsParameter = 91 new IntegerParameter("iterations", "Number of Iterations", 92 "The number of queries to issue before ending " + 93 "the job.", false, -1, true, -1, false, 0); 94 95 IntegerParameter timeBetweenQueriesParameter = 97 new IntegerParameter("time_between_queries", "Time Between Queries (ms)", 98 "Specifies the length of time in milliseconds " + 99 "that should be allowed between queries. Note " + 100 "that this time is measured between the " + 101 "beginning of one query and the beginning of the " + 102 "next rather than the end of one and the " + 103 "beginning of the next.", true, 0, true, 0, false, 104 0); 105 106 IntegerParameter warmUpParameter = 108 new IntegerParameter("warm_up", "Warm Up Time (s)", 109 "Specifies the length of time in seconds after " + 110 "the job starts that it should begin collecting " + 111 "statistics.", true, 0, true, 0, false, 0); 112 113 PasswordParameter passwordParameter = 115 new PasswordParameter("password", "User Password", 116 "The password for the user account to use to " + 117 "connect to the database.", false, ""); 118 119 PlaceholderParameter placeholder = new PlaceholderParameter(); 121 122 StringParameter driverClassParameter = 124 new StringParameter("driver_class", "JDBC Driver Class", 125 "The fully-qualified Java class that provides " + 126 "the JDBC interface to the SQL database.", true, ""); 127 128 StringParameter jdbcURLParameter = 130 new StringParameter("jdbc_url", "JDBC URL", 131 "The URL that specifies the information to use to " + 132 "connect to the SQL database.", true, ""); 133 134 StringParameter sqlQueryParameter = 136 new StringParameter("sql_query", "SQL Query", 137 "The SQL statement to use to query the database. " + 138 "It may optionally include a bracketed pair of " + 139 "integers separated by a dash (for random access) " + 140 "or a colon (for sequential access) to alter the " + 141 "query each time it is issued.", true, ""); 142 143 StringParameter userNameParameter = 145 new StringParameter("username", "User Name", 146 "The username for the account to use to connect " + 147 "to the database.", false, ""); 148 149 150 151 static boolean alwaysDisconnect; 153 static boolean useRange; 154 static boolean useSequential; 155 static int coolDownTime; 156 static int iterations; 157 static int rangeMin; 158 static int rangeMax; 159 static int rangeSpan; 160 static int sequentialCounter; 161 static int timeBetweenQueries; 162 static int warmUpTime; 163 static String driverClass; 164 static String jdbcURL; 165 static String sqlQuery; 166 static String userName; 167 static String userPassword; 168 static String variableInitial; 169 static String variableFinal; 170 171 172 static Random parentRandom; 174 Random random; 175 176 177 Connection connection; 179 180 181 IncrementalTracker exceptionsCaught; 183 IncrementalTracker queriesCompleted; 184 IntegerValueTracker rowsReturned; 185 TimeTracker queryTimer; 186 187 188 189 192 public SQLSearchRateJobClass() 193 { 194 super(); 195 } 196 197 198 199 204 public String getJobName() 205 { 206 return "SQL SearchRate"; 207 } 208 209 210 211 216 public String getJobDescription() 217 { 218 return "This job can be used to repeatedly query an SQL database to " + 219 "generate load and measure performance."; 220 } 221 222 223 224 232 public String getJobCategoryName() 233 { 234 return "SQL"; 235 } 236 237 238 239 246 public ParameterList getParameterStubs() 247 { 248 Parameter[] parameters = new Parameter[] 249 { 250 placeholder, 251 driverClassParameter, 252 jdbcURLParameter, 253 userNameParameter, 254 passwordParameter, 255 sqlQueryParameter, 256 placeholder, 257 warmUpParameter, 258 coolDownParameter, 259 timeBetweenQueriesParameter, 260 iterationsParameter, 261 disconnectParameter 262 }; 263 264 return new ParameterList(parameters); 265 } 266 267 268 269 283 public StatTracker[] getStatTrackerStubs(String clientID, String threadID, 284 int collectionInterval) 285 { 286 return new StatTracker[] 287 { 288 new IncrementalTracker(clientID, threadID, STAT_TRACKER_QUERIES_COMPLETED, 289 collectionInterval), 290 new IntegerValueTracker(clientID, threadID, STAT_TRACKER_ROWS_RETURNED, 291 collectionInterval), 292 new TimeTracker(clientID, threadID, STAT_TRACKER_QUERY_DURATION, 293 collectionInterval), 294 new IncrementalTracker(clientID, threadID, STAT_TRACKER_EXCEPTIONS_CAUGHT, 295 collectionInterval) 296 }; 297 } 298 299 300 301 306 public StatTracker[] getStatTrackers() 307 { 308 return new StatTracker[] 309 { 310 queriesCompleted, 311 queryTimer, 312 rowsReturned, 313 exceptionsCaught 314 }; 315 } 316 317 318 319 327 public boolean providesParameterTest() 328 { 329 return true; 330 } 331 332 333 334 361 public boolean testJobParameters(ParameterList parameters, 362 ArrayList outputMessages) 363 { 364 StringParameter driverParam = 366 parameters.getStringParameter(driverClassParameter.getName()); 367 if ((driverParam == null) || (! driverParam.hasValue())) 368 { 369 outputMessages.add("ERROR: No JDBC driver class provided."); 370 return false; 371 } 372 String driverClass = driverParam.getStringValue(); 373 374 375 StringParameter urlParam = 376 parameters.getStringParameter(jdbcURLParameter.getName()); 377 if ((urlParam == null) || (! urlParam.hasValue())) 378 { 379 outputMessages.add("ERROR: No JDBC URL provided."); 380 return false; 381 } 382 String jdbcURL = urlParam.getStringValue(); 383 384 385 String userName = ""; 386 StringParameter usernameParam = 387 parameters.getStringParameter(userNameParameter.getName()); 388 if ((usernameParam != null) && usernameParam.hasValue()) 389 { 390 userName = usernameParam.getStringValue(); 391 } 392 393 394 String userPW = ""; 395 PasswordParameter pwParam = 396 parameters.getPasswordParameter(passwordParameter.getName()); 397 if ((pwParam != null) && pwParam.hasValue()) 398 { 399 userPW = pwParam.getStringValue(); 400 } 401 402 403 try 405 { 406 outputMessages.add("Trying to load JDBC driver class '" + driverClass + 407 "'...."); 408 Class.forName(driverClass); 409 outputMessages.add("Driver class loaded successfully."); 410 outputMessages.add(""); 411 } 412 catch (Exception e) 413 { 414 outputMessages.add("ERROR: Unable to load driver class: " + 415 stackTraceToString(e)); 416 return false; 417 } 418 419 420 try 423 { 424 outputMessages.add("Trying to connect to database using JDBC URL '" + 425 jdbcURL + "' as user '" + userName + "'...."); 426 427 Connection connection = DriverManager.getConnection(jdbcURL, userName, 428 userPW); 429 430 outputMessages.add("Connected successfully."); 431 outputMessages.add(""); 432 433 try 434 { 435 connection.close(); 436 } catch (Exception e) {} 437 438 outputMessages.add("Connection closed."); 439 outputMessages.add(""); 440 } 441 catch (Exception e) 442 { 443 outputMessages.add("ERROR: Unable to connect: " + 444 stackTraceToString(e)); 445 return false; 446 } 447 448 outputMessages.add("All tests completed."); 449 return true; 450 } 451 452 453 454 462 public void initializeClient(String clientID, ParameterList parameters) 463 { 464 driverClass = null; 466 driverClassParameter = 467 parameters.getStringParameter(driverClassParameter.getName()); 468 if (driverClassParameter != null) 469 { 470 driverClass = driverClassParameter.getStringValue(); 471 } 472 473 jdbcURL = null; 475 jdbcURLParameter = 476 parameters.getStringParameter(jdbcURLParameter.getName()); 477 if (jdbcURLParameter != null) 478 { 479 jdbcURL = jdbcURLParameter.getStringValue(); 480 } 481 482 userName = ""; 484 userNameParameter = 485 parameters.getStringParameter(userNameParameter.getName()); 486 if ((userNameParameter != null) && userNameParameter.hasValue()) 487 { 488 userName = userNameParameter.getStringValue(); 489 } 490 491 userPassword = ""; 493 passwordParameter = 494 parameters.getPasswordParameter(passwordParameter.getName()); 495 if ((passwordParameter != null) && passwordParameter.hasValue()) 496 { 497 userPassword = passwordParameter.getStringValue(); 498 } 499 500 sqlQueryParameter = 502 parameters.getStringParameter(sqlQueryParameter.getName()); 503 if (sqlQueryParameter != null) 504 { 505 sqlQuery = sqlQueryParameter.getStringValue(); 506 useRange = false; 507 useSequential = false; 508 509 int openBracketPos = sqlQuery.indexOf('['); 510 int dashPos = sqlQuery.indexOf('-', openBracketPos); 511 if (dashPos < 0) 512 { 513 dashPos = sqlQuery.indexOf(':', openBracketPos); 514 useSequential = true; 515 } 516 517 int closeBracketPos; 518 if ((openBracketPos >= 0) && (dashPos > 0) && 519 ((closeBracketPos = sqlQuery.indexOf(']', dashPos)) > 0)) 520 { 521 try 522 { 523 rangeMin = Integer.parseInt(sqlQuery.substring(openBracketPos+1, 524 dashPos)); 525 rangeMax = Integer.parseInt(sqlQuery.substring(dashPos+1, 526 closeBracketPos)); 527 rangeSpan = rangeMax - rangeMin + 1; 528 529 variableInitial = ""; 530 int openSpacePos = sqlQuery.lastIndexOf(' ', openBracketPos); 531 if (openSpacePos > 0) 532 { 533 variableInitial = sqlQuery.substring(openSpacePos+1, 534 openBracketPos); 535 if (variableInitial.startsWith("\"") || 536 variableInitial.startsWith("'")) 537 { 538 variableInitial = variableInitial.substring(1); 539 } 540 } 541 else 542 { 543 openSpacePos = openBracketPos-1; 544 } 545 546 variableFinal = ""; 547 int closeSpacePos = sqlQuery.indexOf(' ', closeBracketPos); 548 int closeParenPos = sqlQuery.indexOf(')', closeBracketPos); 549 if ((closeSpacePos < 0) || 550 ((closeParenPos > 0) && (closeParenPos < closeSpacePos))) 551 { 552 closeSpacePos = closeParenPos; 553 } 554 if (closeSpacePos > 0) 555 { 556 variableFinal = sqlQuery.substring(closeBracketPos+1, 557 closeSpacePos); 558 } 559 else 560 { 561 closeSpacePos = sqlQuery.indexOf(';', closeBracketPos); 562 if (closeSpacePos > 0) 563 { 564 variableFinal = sqlQuery.substring(closeBracketPos+1, 565 closeSpacePos); 566 } 567 else 568 { 569 closeSpacePos = closeBracketPos + 1; 570 } 571 } 572 if (variableFinal.endsWith("\"") || variableFinal.endsWith("'")) 573 { 574 variableFinal = variableFinal.substring(0, 575 variableFinal.length()-1); 576 } 577 578 sqlQuery = sqlQuery.substring(0, openSpacePos+1) + "?" + 579 sqlQuery.substring(closeSpacePos); 580 useRange = true; 581 sequentialCounter = rangeMin; 582 } 583 catch (Exception e) 584 { 585 useRange = false; 586 } 587 } 588 else 589 { 590 useRange = false; 591 } 592 } 593 594 warmUpTime = 0; 596 warmUpParameter = parameters.getIntegerParameter(warmUpParameter.getName()); 597 if (warmUpParameter != null) 598 { 599 warmUpTime = warmUpParameter.getIntValue(); 600 } 601 602 coolDownTime = 0; 604 coolDownParameter = 605 parameters.getIntegerParameter(coolDownParameter.getName()); 606 if (coolDownParameter != null) 607 { 608 coolDownTime = coolDownParameter.getIntValue(); 609 } 610 611 timeBetweenQueries = 0; 613 timeBetweenQueriesParameter = 614 parameters.getIntegerParameter(timeBetweenQueriesParameter.getName()); 615 if (timeBetweenQueriesParameter != null) 616 { 617 timeBetweenQueries = timeBetweenQueriesParameter.getIntValue(); 618 } 619 620 iterations = -1; 622 iterationsParameter = 623 parameters.getIntegerParameter(iterationsParameter.getName()); 624 if ((iterationsParameter != null) && iterationsParameter.hasValue()) 625 { 626 iterations = iterationsParameter.getIntValue(); 627 } 628 629 alwaysDisconnect = false; 631 disconnectParameter = 632 parameters.getBooleanParameter(disconnectParameter.getName()); 633 if (disconnectParameter != null) 634 { 635 alwaysDisconnect = disconnectParameter.getBooleanValue(); 636 } 637 638 639 parentRandom = new Random(); 641 } 642 643 644 645 656 public void initializeThread(String clientID, String threadID, 657 int collectionInterval, ParameterList parameters) 658 { 659 queriesCompleted = new IncrementalTracker(clientID, threadID, 661 STAT_TRACKER_QUERIES_COMPLETED, 662 collectionInterval); 663 queryTimer = new TimeTracker(clientID, threadID, 664 STAT_TRACKER_QUERY_DURATION, 665 collectionInterval); 666 rowsReturned = new IntegerValueTracker(clientID, threadID, 667 STAT_TRACKER_ROWS_RETURNED, 668 collectionInterval); 669 exceptionsCaught = new IncrementalTracker(clientID, threadID, 670 STAT_TRACKER_EXCEPTIONS_CAUGHT, 671 collectionInterval); 672 673 674 RealTimeStatReporter statReporter = getStatReporter(); 676 if (statReporter != null) 677 { 678 String jobID = getJobID(); 679 queriesCompleted.enableRealTimeStats(statReporter, jobID); 680 queryTimer.enableRealTimeStats(statReporter, jobID); 681 rowsReturned.enableRealTimeStats(statReporter, jobID); 682 exceptionsCaught.enableRealTimeStats(statReporter, jobID); 683 } 684 685 686 random = new Random(parentRandom.nextLong()); 688 } 689 690 691 692 695 public void runJob() 696 { 697 try 700 { 701 Class.forName(driverClass); 702 } 703 catch (Exception e) 704 { 705 logMessage("Unable to load the driver class \"" + driverClass + "\" -- " + 706 e); 707 indicateStoppedDueToError(); 708 return; 709 } 710 711 712 long currentTime = System.currentTimeMillis(); 714 boolean collectingStats = false; 715 long startCollectingTime = currentTime + (1000 * warmUpTime); 716 long stopCollectingTime = Long.MAX_VALUE; 717 if ((coolDownTime > 0) && (getShouldStopTime() > 0)) 718 { 719 stopCollectingTime = getShouldStopTime() - (1000 * coolDownTime); 720 } 721 722 723 boolean connected = false; 725 boolean infinite = (iterations <= 0); 726 long queryStartTime = 0; 727 PreparedStatement statement = null; 728 connection = null; 729 730 731 for (int i=0; ((! shouldStop()) && ((infinite || (i < iterations)))); i++) 733 { 734 currentTime = System.currentTimeMillis(); 735 if ((! collectingStats) && (currentTime >= startCollectingTime) && 736 (currentTime < stopCollectingTime)) 737 { 738 queriesCompleted.startTracker(); 740 queryTimer.startTracker(); 741 rowsReturned.startTracker(); 742 exceptionsCaught.startTracker(); 743 collectingStats = true; 744 } 745 else if (collectingStats && (currentTime >= stopCollectingTime)) 746 { 747 queriesCompleted.stopTracker(); 749 queryTimer.stopTracker(); 750 rowsReturned.stopTracker(); 751 exceptionsCaught.stopTracker(); 752 collectingStats = false; 753 } 754 755 756 if (! connected) 758 { 759 try 760 { 761 connection = DriverManager.getConnection(jdbcURL, userName, 762 userPassword); 763 connected = true; 764 } 765 catch (SQLException se) 766 { 767 logMessage("Unable to connect to the database: " + se); 768 indicateStoppedDueToError(); 769 break; 770 } 771 772 try 773 { 774 statement = connection.prepareStatement(sqlQuery); 775 } 776 catch (SQLException se) 777 { 778 logMessage("Unable to parse SQL query \"" + sqlQuery + "\"."); 779 indicateStoppedDueToError(); 780 break; 781 } 782 } 783 784 785 int matchingRows = 0; 788 789 790 if (timeBetweenQueries > 0) 792 { 793 queryStartTime = System.currentTimeMillis(); 794 } 795 if (collectingStats) 796 { 797 queryTimer.startTimer(); 798 } 799 try 800 { 801 if (useRange) 802 { 803 statement.setString(1, getQueryVariableComponent()); 804 } 805 ResultSet resultSet = statement.executeQuery(); 806 while (resultSet.next()) 807 { 808 matchingRows++; 809 } 810 811 if (collectingStats) 812 { 813 queryTimer.stopTimer(); 814 queriesCompleted.increment(); 815 rowsReturned.addValue(matchingRows); 816 } 817 } 818 catch (SQLException se) 819 { 820 writeVerbose("Caught SQL Exception: " + se); 821 if (collectingStats) 822 { 823 exceptionsCaught.increment(); 824 } 825 } 826 827 828 if (alwaysDisconnect) 830 { 831 try 832 { 833 statement.close(); 834 } catch (Exception e) {} 835 836 try 837 { 838 connection.close(); 839 } catch (Exception e) {} 840 connected = false; 841 } 842 843 844 if (timeBetweenQueries > 0) 846 { 847 if (! shouldStop()) 848 { 849 long now = System.currentTimeMillis(); 850 long sleepTime = timeBetweenQueries - (now - queryStartTime); 851 if (sleepTime > 0) 852 { 853 try 854 { 855 Thread.sleep(sleepTime); 856 } catch (InterruptedException ie) {} 857 } 858 } 859 } 860 } 861 862 863 if (connected) 865 { 866 try 867 { 868 statement.close(); 869 } catch (Exception e) {} 870 871 try 872 { 873 connection.close(); 874 } catch (Exception e) {} 875 } 876 877 if (collectingStats) 878 { 879 queriesCompleted.stopTracker(); 880 queryTimer.stopTracker(); 881 rowsReturned.stopTracker(); 882 exceptionsCaught.stopTracker(); 883 } 884 } 885 886 887 888 892 public void destroy() 893 { 894 if (connection != null) 895 { 896 try 897 { 898 connection.close(); 899 } catch (Exception e) {} 900 901 connection = null; 902 } 903 } 904 905 906 907 914 public String getQueryVariableComponent() 915 { 916 int value; 917 if (useSequential) 918 { 919 value = sequentialCounter++; 920 if (sequentialCounter > rangeMax) 921 { 922 sequentialCounter = rangeMin; 923 } 924 } 925 else 926 { 927 value = ((random.nextInt() & 0x7FFFFFFF) % rangeSpan) + rangeMin; 928 } 929 930 return variableInitial + value + variableFinal; 931 } 932 } 933 934 | Popular Tags |