1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
|
#!/usr/bin/perl
################################################################################
#
# This script runs the transactional stress test "stress_tx_rr" against the
# transactional storage engine and looks for errors in two log files:
# var/stress/<timestamp>/mysql-stress-test.log
# var/log/master.err
#
# The script assumes current working dir is mysql-test/.
#
# Regarding the server error log, currently only error lines containing the
# string "Error:" will be reported as a critical error, in addition to signs
# of crashes.
#
# In the stress test log, all lines matching the regex "S\d:" (denoting an
# error with a specified severity) will be reported as errors.
#
# Error information including the full server log in the case of server crash
# is output to standard out.
#
# This script is and should be silent if no errors are detected.
#
################################################################################
use File::Find;
use File::Spec;
use Cwd;
use Cwd 'abs_path';
use Getopt::Long;
# Checking script is run from the correct location
if (! -f "mysql-test-run.pl") {
print("\nERROR: This script should be run from the \'\<INSTALL_DIR\>/mysql-test\' directory.\n");
error(1);
}
$runlog="rr_trx.log";
my $errorFound;
my $installdir=abs_path(File::Spec->updir());
my $f=abs_path($0);
my ($v,$d,$f)=File::Spec->splitpath($f);
my $testsuitedir=$v.$d;
################################################################################
# Run stress test, redirect output to tmp file.
# Duration is specified in seconds. Some nice values:
# 5 minutes = 300
# 30 minutes = 1800
# 1 hour = 3600
# 2 hours = 7200
# 5 hours = 18000
# 12 hours = 43200
#
################################################################################
$opt_duration=600;
# Special handling for the InnoDB plugin
$plugin_params="\"--plugin-load=innodb=ha_innodb_plugin.so;innodb_trx=ha_innodb_plugin.so;innodb_locks=ha_innodb_plugin.so;innodb_cmp=ha_innodb_plugin.so;innodb_cmp_reset=ha_innodb_plugin.so;innodb_cmpmem=ha_innodb_plugin.so;innodb_cmpmem_reset=ha_innodb_plugin.so\"";
$plugin_params=~s/so/dll/g if (windows());
$opt_help="";
$opt_try="";
$opt_engine="";
$opt_threads=10;
# Collection command line options
GetOptions("engine:s" => \$opt_engine,
"duration=i" => \$opt_duration,
"threads=i" => \$opt_treads,
"try", "help") || usage();
if ($opt_help) { usage(); }
if (!$opt_engine) {
print("\nERROR: --engine=\<engine\> argument is required!!!\n");
usage();
}
# setting specific engine parameters
$engine_options="";
# for innodb engine
if ($opt_engine eq "InnoDB") {
$engine_options=
"--mysqld=--innodb " .
"--mysqld=--innodb-lock-wait-timeout=2 " .
" ";
}
elsif ($opt_engine eq "InnoDB_plugin") {
$engine_options=
"--mysqld=--innodb " .
"--mysqld=--ignore-builtin-innodb " .
#"--mysqld=--plugin_dir=".$installdir."/lib " .
"--mysqld=--plugin_dir=".$installdir."/storage/innodb_plugin/.libs " .
"--mysqld=--innodb-lock-wait-timeout=2 " .
"--mysqld=".$plugin_params." " .
" ";
}
# add parameters for a new engine by modifying the 'elsif' section below
elsif ($opt_engine eq "zz") {
$engine_options=
" ";
}
else {
print("\nERROR: '".$opt_engine."' - unknown engine\n");
add_engine_help();
}
# From this point forward there is no difference between the build in InnoDB and the plugin
$opt_engine='InnoDB' if ($opt_engine eq 'InnoDB_plugin');
# checking that custom files for that engine exist
$engine_lower= lc($opt_engine);
$missing=0;
if (!-f $testsuitedir.'init_'.$engine_lower.'.txt') {
print("\nERROR: config file 'init_".$engine_lower.".txt' missing.");
$missing=1;
}
if (!-f $testsuitedir.'t/init_'.$engine_lower.'.test') {
print("\nERROR: config file 'init_".$engine_lower.".test' missing.");
$missing=1;
}
if (!-f $testsuitedir.'r/init_'.$engine_lower.'.result') {
print("\nERROR: config file 'init_".$engine_lower.".result' missing.");
$missing=1;
}
add_engine_help() if ($missing);
# bilding test command line
$cmd="MTR_VERSION=1 " .
"perl ./mysql-test-run.pl " .
"--comment=stress_tx_rr_".$opt_engine." " .
"--stress " .
"--stress-init-file=init_".$engine_lower.".txt " .
"--stress-test-file=run.txt " .
"--stress-suite=engines/rr_trx " .
"--stress-test-duration=".$opt_duration." " .
"--stress-threads=".$opt_threads." " .
"--mysqld=--log-output=file " .
"--mysqld=--sql-mode=no_engine_substitution " .
"--skip-im " .
$engine_options .
" > ".$runlog." 2>&1";
# running the test
print("\n Running \'rr_trx\' test with ".$opt_threads." clients\n");
print(" for ".$opt_duration." seconds using the ".$opt_engine." storag engine.\n");
print("\n Log file: ".$runlog."\n");
if ($opt_try) {
print("\nThe following command will execute:\n");
print("$cmd\n\n");
exit(0);
}
system $cmd;
################################################################################
# Check for crash and other severe errors in the server log.
#
################################################################################
# Open log file. If MTR_VERSION=1 this is in var/log/master.err.
# Otherwise, it is in ?... [stress_tx_rr not yet runnable with MTR_VERSION=2]
# Assuming current directory mysql-test/
my $serverlog=getcwd() . "/var/log/master.err";
open(SERVERLOG, $serverlog)
or die "Unable to open $serverlog. Test not run?";
my @servererrors = (); # Lines with "Severe" errors in server error log
my @crash = (); # Empty if no stack trace detected, non-empty otherwise.
# Grep for errors and crashes. Going line-by-line since the file can be large.
while (<SERVERLOG>) {
$line = $_;
push @crash, $line if /This could be because you hit a bug/;
push @servererrors, $line if /Error:/;
}
close(SERVERLOG);
if (@crash) {
# Crash (stack trace) detected in server log.
print "Transactional stress test stress_tx_rr:\n\n";
print "SERVER CRASH DETECTED!\n";
print "Server log: $serverlog printed at the bottom of this log.\n\n";
print "########################################################\n\n";
}
if (@servererrors) {
# "Severe" errors detected. Print error lines to std out
print "CRITICAL ERRORS:\n\n";
foreach $error (@servererrors) {
print $error;
}
print "\n########################################################\n\n";
}
################################################################################
# Check for errors reported by mysql-stress-test.pl. Transactional consistency
# issues are shown as result diffs.
################################################################################
my $dir;
find(\&finddir, cwd); # sets variable $dir
# Open log file
my $logfile="$dir/mysql-stress-test.log";
open(LOGFILE, $logfile)
or die "Unable to open $logfile. Test not run?";
my @errors = ();
my @heading = ();
# Grep for errors. Going line-by-line since the file can be large.
while (<LOGFILE>) {
#push @errors, $_ if ! /No Errors/;
push @errors, $_ if /S\d:/;
push @heading, $_ if /TestID|=====/;
}
close(LOGFILE);
# Print all errors, i.e. all lines that do not contain the string "No Errors"
if (@errors) {
$errorFound = 1;
print "Stress test main log file: $logfile\n";
print "Errors follow:\n\n";
# First print the heading
foreach $header_line (@heading) {
print $header_line;
}
foreach $error (@errors) {
print $error;
}
}
# If errors in server log, output the log and exit 1?
if (@servererrors or @crash) {
$errorFound = 1;
print "\n########################################################\n\n";
print "Server error log (master.err):\n\n";
open(SERVERLOG, $serverlog)
or die "Unable to open $serverlog!";
while (<SERVERLOG>) {
print $_;
}
close(SERVERLOG);
}
if ($errorFound) {
# Exit with error code != 0 if we found an error.
print("\nTest Completed with errors. \n");
print(" - See ".$runlog." for summary.\n");
print(" - See files under var/stress for details.\n");
exit 1;
}
print("\nTest Completed - See ".$runlog." for details\n");
################################################################################
# Helper routines etc.
#
################################################################################
sub finddir {
my $file = $File::Find::name; # complete path to the file
return unless -d $file; # process directories (-d), not files (-f)
return unless $_ =~ m/^\d{14}$/; # check if file matches timstamp regex,
# must be 14 digits
$dir=$file;
#$dir= $_; # $_ = just the file name, no path
return $_;
}
sub usage
{
print <<EOF;
SYNTAX $0 --engine=<engine> [--duration=<nn>] [--thread=<nn>] [--try]
--engine=<engine>
The engine used to run the test. \<engine\> needs to be provided exactly as
it is reprted in the SHOW ENGINES comand.
EXCEPTION: In order to use the InnoDB plugin, specify 'InnoDB_plugin'
Required option.
--duration=nn
The time the test should run for in seconds. Defaut value is 600 seconds (10 minutes).
Optional parameter
--threads=nn
The number of clients used by the test driver. Defaut value is 10.
Optional parameter
--try
Do not run the actual test but show what will be run
Optional parameter
EOF
exit(0);
}
sub add_engine_help
{
print <<EOF;
\nThis test is can be run against any transactional engine. However scripts need to be modifed in order
to support such engines (support to InnoDB is provided as an example).
In order to add support for a new engine, you will need to modify scripts as follows:
1) cd to INSTALL_DIR/mysql-test/suite/engines/rr_trx
2) Modify the 'run_stress_rr.pl' file by adding an 'elsif' section for your engine and have it
include specifc values required to be passed as startup parameters to the MySQL server by
specifying them using "--mysqld" options (see InnoDB example).
3) Copy the 'init_innodb.txt' file to 'init_<engine>.txt file and change its content to be "init_<engine>".
4) In the 't' directory copy the "init_innodb.test" file to "init_\<engine\>.test" and change the value of
the '\$engine' variable to \<engine\>.
5) In the 'r' directory copy "the init_innodb.result" file to "init_\<engine\>.result" and change refrences
to 'InnoDB' to \<engine\>.
EOF
exit(0);
}
sub windows {
if (
($^O eq 'MSWin32') ||
($^O eq 'MSWin64')
) {
return 1;
} else {
return 0;
}
}
|