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 SQLModRateJobClass 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_UPDATES_COMPLETED = 54 "Updates Completed"; 55 56 57 58 62 public static final String STAT_TRACKER_UPDATE_DURATION = 63 "Update Duration (ms)"; 64 65 66 67 70 public static final char[] ALPHABET = 71 "abcdefghijklmnopqrstuvwxyz".toCharArray(); 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 update.", 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 updates to perform before ending " + 93 "the job.", false, -1, true, -1, false, 0); 94 95 IntegerParameter timeBetweenUpdatesParameter = 97 new IntegerParameter("time_between_updates", "Time Between Updates (ms)", 98 "Specifies the length of time in milliseconds " + 99 "that should be allowed between updates. Note " + 100 "that this time is measured between the " + 101 "beginning of one update and the beginning of " + 102 "the next rather than the end of one and the " + 103 "beginning of the next.", true, 0, true, 0, false, 104 0); 105 106 IntegerParameter valueLengthParameter = 108 new IntegerParameter("value_length", "Generated Value Length", 109 "Specifies the number of characters to include " + 110 "in the randomly-generated value to use in the " + 111 "update.", true, 20, true, 1, false, 0); 112 113 IntegerParameter warmUpParameter = 115 new IntegerParameter("warm_up", "Warm Up Time (s)", 116 "Specifies the length of time in seconds after " + 117 "the job starts that it should begin collecting " + 118 "statistics.", true, 0, true, 0, false, 0); 119 120 PasswordParameter passwordParameter = 122 new PasswordParameter("password", "User Password", 123 "The password for the user account to use to " + 124 "connect to the database.", false, ""); 125 126 PlaceholderParameter placeholder = new PlaceholderParameter(); 128 129 StringParameter driverClassParameter = 131 new StringParameter("driver_class", "JDBC Driver Class", 132 "The fully-qualified Java class that provides " + 133 "the JDBC interface to the SQL database.", true, ""); 134 135 StringParameter jdbcURLParameter = 137 new StringParameter("jdbc_url", "JDBC URL", 138 "The URL that specifies the information to use to " + 139 "connect to the SQL database.", true, ""); 140 141 StringParameter matchColumnParameter = 143 new StringParameter("match_column", "Column to Match", 144 "The name of the database column to query in " + 145 "order to find the records to update.", true, ""); 146 147 StringParameter matchValueParameter = 149 new StringParameter("match_value", "Match Value", 150 "The value or value pattern to use to find the " + 151 "records to update. It may optionally include a " + 152 "bracketed pair of integers separated by a dash " + 153 "(for random access) or a colon (for sequential " + 154 "access) to alter the query each time it is " + 155 "issued.", true, ""); 156 157 StringParameter tableNameParameter = 159 new StringParameter("table_name", "Table Name", 160 "The of the table in the database in which the " + 161 "updates should be performed.", true, ""); 162 163 StringParameter updateColumnParameter = 165 new StringParameter("update_column", "Column to Update", 166 "The name of the database column to replace with " + 167 "a randomly generated string in matching records.", 168 true, ""); 169 170 StringParameter userNameParameter = 172 new StringParameter("username", "User Name", 173 "The username for the account to use to connect " + 174 "to the database.", false, ""); 175 176 177 178 static boolean alwaysDisconnect; 180 static boolean useRange; 181 static boolean useSequential; 182 static int coolDownTime; 183 static int iterations; 184 static int rangeMin; 185 static int rangeMax; 186 static int rangeSpan; 187 static int sequentialCounter; 188 static int timeBetweenUpdates; 189 static int valueLength; 190 static int warmUpTime; 191 static String driverClass; 192 static String jdbcURL; 193 static String matchColumn; 194 static String tableName; 195 static String updateColumn; 196 static String userName; 197 static String userPassword; 198 static String valueInitial; 199 static String valueFinal; 200 201 202 static Random parentRandom; 204 Random random; 205 206 207 Connection connection; 209 210 211 IncrementalTracker exceptionsCaught; 213 IncrementalTracker updatesCompleted; 214 TimeTracker updateTimer; 215 216 217 218 221 public SQLModRateJobClass() 222 { 223 super(); 224 } 225 226 227 228 233 public String getJobName() 234 { 235 return "SQL ModRate"; 236 } 237 238 239 240 245 public String getJobDescription() 246 { 247 return "This job can be used to repeatedly perform updates in an SQL " + 248 "database to generate load and measure performance."; 249 } 250 251 252 253 261 public String getJobCategoryName() 262 { 263 return "SQL"; 264 } 265 266 267 268 275 public ParameterList getParameterStubs() 276 { 277 Parameter[] parameters = new Parameter[] 278 { 279 placeholder, 280 driverClassParameter, 281 jdbcURLParameter, 282 userNameParameter, 283 passwordParameter, 284 placeholder, 285 tableNameParameter, 286 updateColumnParameter, 287 valueLengthParameter, 288 matchColumnParameter, 289 matchValueParameter, 290 placeholder, 291 warmUpParameter, 292 coolDownParameter, 293 timeBetweenUpdatesParameter, 294 iterationsParameter, 295 disconnectParameter 296 }; 297 298 return new ParameterList(parameters); 299 } 300 301 302 303 317 public StatTracker[] getStatTrackerStubs(String clientID, String threadID, 318 int collectionInterval) 319 { 320 return new StatTracker[] 321 { 322 new IncrementalTracker(clientID, threadID, STAT_TRACKER_UPDATES_COMPLETED, 323 collectionInterval), 324 new TimeTracker(clientID, threadID, STAT_TRACKER_UPDATE_DURATION, 325 collectionInterval), 326 new IncrementalTracker(clientID, threadID, STAT_TRACKER_EXCEPTIONS_CAUGHT, 327 collectionInterval) 328 }; 329 } 330 331 332 333 338 public StatTracker[] getStatTrackers() 339 { 340 return new StatTracker[] 341 { 342 updatesCompleted, 343 updateTimer, 344 exceptionsCaught 345 }; 346 } 347 348 349 350 358 public boolean providesParameterTest() 359 { 360 return true; 361 } 362 363 364 365 392 public boolean testJobParameters(ParameterList parameters, 393 ArrayList outputMessages) 394 { 395 StringParameter driverParam = 397 parameters.getStringParameter(driverClassParameter.getName()); 398 if ((driverParam == null) || (! driverParam.hasValue())) 399 { 400 outputMessages.add("ERROR: No JDBC driver class provided."); 401 return false; 402 } 403 String driverClass = driverParam.getStringValue(); 404 405 406 StringParameter urlParam = 407 parameters.getStringParameter(jdbcURLParameter.getName()); 408 if ((urlParam == null) || (! urlParam.hasValue())) 409 { 410 outputMessages.add("ERROR: No JDBC URL provided."); 411 return false; 412 } 413 String jdbcURL = urlParam.getStringValue(); 414 415 416 String userName = ""; 417 StringParameter usernameParam = 418 parameters.getStringParameter(userNameParameter.getName()); 419 if ((usernameParam != null) && usernameParam.hasValue()) 420 { 421 userName = usernameParam.getStringValue(); 422 } 423 424 425 String userPW = ""; 426 PasswordParameter pwParam = 427 parameters.getPasswordParameter(passwordParameter.getName()); 428 if ((pwParam != null) && pwParam.hasValue()) 429 { 430 userPW = pwParam.getStringValue(); 431 } 432 433 434 try 436 { 437 outputMessages.add("Trying to load JDBC driver class '" + driverClass + 438 "'...."); 439 Class.forName(driverClass); 440 outputMessages.add("Driver class loaded successfully."); 441 outputMessages.add(""); 442 } 443 catch (Exception e) 444 { 445 outputMessages.add("ERROR: Unable to load driver class: " + 446 stackTraceToString(e)); 447 return false; 448 } 449 450 451 try 454 { 455 outputMessages.add("Trying to connect to database using JDBC URL '" + 456 jdbcURL + "' as user '" + userName + "'...."); 457 458 Connection connection = DriverManager.getConnection(jdbcURL, userName, 459 userPW); 460 461 outputMessages.add("Connected successfully."); 462 outputMessages.add(""); 463 464 try 465 { 466 connection.close(); 467 } catch (Exception e) {} 468 469 outputMessages.add("Connection closed."); 470 outputMessages.add(""); 471 } 472 catch (Exception e) 473 { 474 outputMessages.add("ERROR: Unable to connect: " + 475 stackTraceToString(e)); 476 return false; 477 } 478 479 outputMessages.add("All tests completed."); 480 return true; 481 } 482 483 484 485 493 public void initializeClient(String clientID, ParameterList parameters) 494 { 495 driverClass = null; 497 driverClassParameter = 498 parameters.getStringParameter(driverClassParameter.getName()); 499 if (driverClassParameter != null) 500 { 501 driverClass = driverClassParameter.getStringValue(); 502 } 503 504 jdbcURL = null; 506 jdbcURLParameter = 507 parameters.getStringParameter(jdbcURLParameter.getName()); 508 if (jdbcURLParameter != null) 509 { 510 jdbcURL = jdbcURLParameter.getStringValue(); 511 } 512 513 userName = ""; 515 userNameParameter = 516 parameters.getStringParameter(userNameParameter.getName()); 517 if ((userNameParameter != null) && userNameParameter.hasValue()) 518 { 519 userName = userNameParameter.getStringValue(); 520 } 521 522 userPassword = ""; 524 passwordParameter = 525 parameters.getPasswordParameter(passwordParameter.getName()); 526 if ((passwordParameter != null) && passwordParameter.hasValue()) 527 { 528 userPassword = passwordParameter.getStringValue(); 529 } 530 531 tableName = null; 533 tableNameParameter = 534 parameters.getStringParameter(tableNameParameter.getName()); 535 if (tableNameParameter != null) 536 { 537 tableName = tableNameParameter.getStringValue(); 538 } 539 540 updateColumn = null; 542 updateColumnParameter = 543 parameters.getStringParameter(updateColumnParameter.getName()); 544 if (updateColumnParameter != null) 545 { 546 updateColumn = updateColumnParameter.getStringValue(); 547 } 548 549 valueLength = 20; 551 valueLengthParameter = 552 parameters.getIntegerParameter(valueLengthParameter.getName()); 553 if (valueLengthParameter != null) 554 { 555 valueLength = valueLengthParameter.getIntValue(); 556 } 557 558 matchColumn = null; 560 matchColumnParameter = 561 parameters.getStringParameter(matchColumnParameter.getName()); 562 if (matchColumnParameter != null) 563 { 564 matchColumn = matchColumnParameter.getStringValue(); 565 } 566 567 matchValueParameter = 569 parameters.getStringParameter(matchValueParameter.getName()); 570 if (matchValueParameter != null) 571 { 572 String valueStr = matchValueParameter.getStringValue(); 573 useRange = false; 574 useSequential = false; 575 576 int openBracketPos = valueStr.indexOf('['); 577 int dashPos = valueStr.indexOf('-', openBracketPos); 578 if (dashPos < 0) 579 { 580 dashPos = valueStr.indexOf(':', openBracketPos); 581 useSequential = true; 582 } 583 584 int closeBracketPos; 585 if ((openBracketPos >= 0) && (dashPos > 0) && 586 ((closeBracketPos = valueStr.indexOf(']', dashPos)) > 0)) 587 { 588 try 589 { 590 rangeMin = Integer.parseInt(valueStr.substring(openBracketPos+1, 591 dashPos)); 592 rangeMax = Integer.parseInt(valueStr.substring(dashPos+1, 593 closeBracketPos)); 594 rangeSpan = rangeMax - rangeMin + 1; 595 596 valueInitial = valueStr.substring(0, openBracketPos); 597 valueFinal = valueStr.substring(closeBracketPos+1); 598 useRange = true; 599 sequentialCounter = rangeMin; 600 } 601 catch (Exception e) 602 { 603 useRange = false; 604 } 605 } 606 else 607 { 608 useRange = false; 609 } 610 } 611 612 warmUpTime = 0; 614 warmUpParameter = parameters.getIntegerParameter(warmUpParameter.getName()); 615 if (warmUpParameter != null) 616 { 617 warmUpTime = warmUpParameter.getIntValue(); 618 } 619 620 coolDownTime = 0; 622 coolDownParameter = 623 parameters.getIntegerParameter(coolDownParameter.getName()); 624 if (coolDownParameter != null) 625 { 626 coolDownTime = coolDownParameter.getIntValue(); 627 } 628 629 timeBetweenUpdates = 0; 631 timeBetweenUpdatesParameter = 632 parameters.getIntegerParameter(timeBetweenUpdatesParameter.getName()); 633 if (timeBetweenUpdatesParameter != null) 634 { 635 timeBetweenUpdates = timeBetweenUpdatesParameter.getIntValue(); 636 } 637 638 iterations = -1; 640 iterationsParameter = 641 parameters.getIntegerParameter(iterationsParameter.getName()); 642 if ((iterationsParameter != null) && iterationsParameter.hasValue()) 643 { 644 iterations = iterationsParameter.getIntValue(); 645 } 646 647 alwaysDisconnect = false; 649 disconnectParameter = 650 parameters.getBooleanParameter(disconnectParameter.getName()); 651 if (disconnectParameter != null) 652 { 653 alwaysDisconnect = disconnectParameter.getBooleanValue(); 654 } 655 656 657 parentRandom = new Random(); 659 } 660 661 662 663 674 public void initializeThread(String clientID, String threadID, 675 int collectionInterval, ParameterList parameters) 676 { 677 updatesCompleted = new IncrementalTracker(clientID, threadID, 679 STAT_TRACKER_UPDATES_COMPLETED, 680 collectionInterval); 681 updateTimer = new TimeTracker(clientID, threadID, 682 STAT_TRACKER_UPDATE_DURATION, 683 collectionInterval); 684 exceptionsCaught = new IncrementalTracker(clientID, threadID, 685 STAT_TRACKER_EXCEPTIONS_CAUGHT, 686 collectionInterval); 687 688 689 RealTimeStatReporter statReporter = getStatReporter(); 691 if (statReporter != null) 692 { 693 String jobID = getJobID(); 694 updatesCompleted.enableRealTimeStats(statReporter, jobID); 695 updateTimer.enableRealTimeStats(statReporter, jobID); 696 exceptionsCaught.enableRealTimeStats(statReporter, jobID); 697 } 698 699 700 random = new Random(parentRandom.nextLong()); 702 } 703 704 705 706 709 public void runJob() 710 { 711 try 714 { 715 Class.forName(driverClass); 716 } 717 catch (Exception e) 718 { 719 logMessage("Unable to load the driver class \"" + driverClass + "\" -- " + 720 e); 721 indicateStoppedDueToError(); 722 return; 723 } 724 725 726 long currentTime = System.currentTimeMillis(); 728 boolean collectingStats = false; 729 long startCollectingTime = currentTime + (1000 * warmUpTime); 730 long stopCollectingTime = Long.MAX_VALUE; 731 if ((coolDownTime > 0) && (getShouldStopTime() > 0)) 732 { 733 stopCollectingTime = getShouldStopTime() - (1000 * coolDownTime); 734 } 735 736 737 boolean connected = false; 739 boolean infinite = (iterations <= 0); 740 long updateStartTime = 0; 741 PreparedStatement statement = null; 742 connection = null; 743 744 745 for (int i=0; ((! shouldStop()) && ((infinite || (i < iterations)))); i++) 747 { 748 currentTime = System.currentTimeMillis(); 749 if ((! collectingStats) && (currentTime >= startCollectingTime) && 750 (currentTime < stopCollectingTime)) 751 { 752 updatesCompleted.startTracker(); 754 updateTimer.startTracker(); 755 exceptionsCaught.startTracker(); 756 collectingStats = true; 757 } 758 else if (collectingStats && (currentTime >= stopCollectingTime)) 759 { 760 updatesCompleted.stopTracker(); 762 updateTimer.stopTracker(); 763 exceptionsCaught.stopTracker(); 764 collectingStats = false; 765 } 766 767 768 if (! connected) 770 { 771 try 772 { 773 connection = DriverManager.getConnection(jdbcURL, userName, 774 userPassword); 775 connected = true; 776 } 777 catch (SQLException se) 778 { 779 logMessage("Unable to connect to the database: " + se); 780 indicateStoppedDueToError(); 781 break; 782 } 783 784 String sql = "UPDATE " + tableName + " SET " + updateColumn + 785 " = ? WHERE " + matchColumn + " = ?;"; 786 try 787 { 788 statement = connection.prepareStatement(sql); 789 } 790 catch (SQLException se) 791 { 792 logMessage("Unable to parse SQL statement \"" + sql + "\"."); 793 indicateStoppedDueToError(); 794 break; 795 } 796 } 797 798 799 if (timeBetweenUpdates > 0) 801 { 802 updateStartTime = System.currentTimeMillis(); 803 } 804 if (collectingStats) 805 { 806 updateTimer.startTimer(); 807 } 808 try 809 { 810 if (useRange) 811 { 812 statement.setString(1, getRandomValue(valueLength)); 813 statement.setString(2, getMatchValue()); 814 } 815 statement.execute(); 816 if (collectingStats) 817 { 818 updateTimer.stopTimer(); 819 updatesCompleted.increment(); 820 } 821 } 822 catch (SQLException se) 823 { 824 writeVerbose("Caught SQL Exception: " + se); 825 if (collectingStats) 826 { 827 exceptionsCaught.increment(); 828 } 829 } 830 831 832 if (alwaysDisconnect) 834 { 835 try 836 { 837 statement.close(); 838 } catch (Exception e) {} 839 840 try 841 { 842 connection.close(); 843 } catch (Exception e) {} 844 connected = false; 845 } 846 847 848 if (timeBetweenUpdates > 0) 850 { 851 if (! shouldStop()) 852 { 853 long now = System.currentTimeMillis(); 854 long sleepTime = timeBetweenUpdates - (now - updateStartTime); 855 if (sleepTime > 0) 856 { 857 try 858 { 859 Thread.sleep(sleepTime); 860 } catch (InterruptedException ie) {} 861 } 862 } 863 } 864 } 865 866 867 if (connected) 869 { 870 try 871 { 872 statement.close(); 873 } catch (Exception e) {} 874 875 try 876 { 877 connection.close(); 878 } catch (Exception e) {} 879 } 880 881 if (collectingStats) 882 { 883 updatesCompleted.stopTracker(); 884 updateTimer.stopTracker(); 885 exceptionsCaught.stopTracker(); 886 } 887 } 888 889 890 891 895 public void destroy() 896 { 897 if (connection != null) 898 { 899 try 900 { 901 connection.close(); 902 } catch (Exception e) {} 903 904 connection = null; 905 } 906 } 907 908 909 910 917 public String getRandomValue(int valueLength) 918 { 919 char[] returnChars = new char[valueLength]; 920 921 for (int i=0; i < valueLength; i++) 922 { 923 returnChars[i] = ALPHABET[Math.abs((random.nextInt()) & 0x7FFFFFFF) % 924 ALPHABET.length]; 925 } 926 927 return new String (returnChars); 928 } 929 930 931 932 937 public String getMatchValue() 938 { 939 if (useRange) 940 { 941 int value; 942 if (useSequential) 943 { 944 value = sequentialCounter++; 945 if (sequentialCounter > rangeMax) 946 { 947 sequentialCounter = rangeMin; 948 } 949 } 950 else 951 { 952 value = ((random.nextInt() & 0x7FFFFFFF) % rangeSpan) + rangeMin; 953 } 954 955 return valueInitial + value + valueFinal; 956 } 957 else 958 { 959 return valueInitial; 960 } 961 } 962 } 963 964 | Popular Tags |