List:Commits« Previous MessageNext Message »
From:Ingo Struewing Date:February 22 2009 6:02pm
Subject:bzr commit into mysql-6.0-backup branch (ingo.struewing:2773) Bug#38133
View as plain text  
#At file:///home2/mydev/bzrroot/mysql-6.0-bug38133-6/ based on revid:jorgen.loland@stripped

 2773 Ingo Struewing	2009-02-22
      Bug#38133 - Myisamlog test fails on Windows
      
      Updating of a table from the myisam.log file was not possible in most cases
      on Windows.
      - The initialization of myisamlog set the number of usable file descriptors
      to one (1!) on Windows.
      - Every log command to a different file required a close of the previous file.
      After a 'close' command the closing of the previous file failed because
      all files were closed already and myisamlog stopped.
      - File locking on Windows failed for the sequence "exclusive lock, shared lock,
      unlock, exclusive lock". It blocked on the last try to acquire an exclusive lock.
      
      Fixed by
      - requesting a reasonable number of file descriptors,
      - before re-open, close a file only if all file descriptors are in use,
      - do not re-open a file, if the command is 'close',
      - unlock a file before changing the lock type.
     @ .bzrignore
        Bug#38133 - Myisamlog test fails on Windows
        Added symbolic link libmysqld/bml.cc.
     @ mysql-test/r/myisamlog.result
        Bug#38133 - Myisamlog test fails on Windows
        fixed test result.
     @ mysql-test/r/myisamlog_coverage.result
        Bug#38133 - Myisamlog test fails on Windows
        New test result.
     @ mysql-test/t/myisamlog.test
        Bug#38133 - Myisamlog test fails on Windows
        Re-enabled the test case for Windows.
        Changed line endings to UNIX format.
        Added server restart to be independent from earlier execution.
     @ mysql-test/t/myisamlog_coverage-master.opt
        Bug#38133 - Myisamlog test fails on Windows
        New options file for new test case.
     @ mysql-test/t/myisamlog_coverage.test
        Bug#38133 - Myisamlog test fails on Windows
        New test case.
     @ mysys/my_lock.c
        Bug#38133 - Myisamlog test fails on Windows
        Added unlocking before locking to prevent multiple locks by the same process.
     @ sql/handler.cc
        Bug#38133 - Myisamlog test fails on Windows
        Changed abort() to DBUG_ABORT() to get rid of pop-up windows.
     @ storage/myisam/mi_close.c
        Bug#38133 - Myisamlog test fails on Windows
        Moved free of share to end of mi_close().
     @ storage/myisam/mi_examine_log.c
        Bug#38133 - Myisamlog test fails on Windows
        Added member lock_type to file_info.
        Added ERROR_INJECT for coverage testing, available in debug build only.
        Changed tracking of allocated memory in 'buff' and 'file_info' so that
        it can be freed in case of errors.
        Added a check for valid data in the log file.
        Disabled re-opening for a close command.
        Reduced closing of files to cases where file descriptors are used up.
        Added error handling to the call to tree_insert().
        Pulled close_some_files() out of reopen_closed_file() to have access
        to max_files.
        Added code to re-lock a file after re-open.
     @ storage/myisam/mi_locking.c
        Bug#38133 - Myisamlog test fails on Windows
        Set my_errno on error in mi_lock_database(), like in other branches.
     @ storage/myisam/mi_log.c
        Bug#38133 - Myisamlog test fails on Windows
        Disable logging for temporary tables.
        Replaced several info->s by share.
     @ storage/myisam/myisamlog.c
        Bug#38133 - Myisamlog test fails on Windows
        Allowed for more of one (1!) file descriptor on platforms that
        do not raise the maximum above the request.
        Added --debug option to support debugging with new mysql-test-run.
        Added fflush(stdout) to have repeatable order of output lines
        to support testing.

    added:
      mysql-test/r/myisamlog_coverage.result
      mysql-test/t/myisamlog_coverage-master.opt
      mysql-test/t/myisamlog_coverage.test
    modified:
      .bzrignore
      mysql-test/r/myisamlog.result
      mysql-test/t/myisamlog.test
      mysys/my_lock.c
      sql/handler.cc
      storage/myisam/mi_close.c
      storage/myisam/mi_examine_log.c
      storage/myisam/mi_locking.c
      storage/myisam/mi_log.c
      storage/myisam/myisamlog.c
=== modified file '.bzrignore'
--- a/.bzrignore	2009-02-04 22:35:10 +0000
+++ b/.bzrignore	2009-02-22 18:02:16 +0000
@@ -2010,3 +2010,4 @@ libmysql_r/probes.h
 unittest/tmp
 libmysqld/sql_join_cache.cc
 libmysqld/examples/mysqltest.cc
+libmysqld/bml.cc

=== modified file 'mysql-test/r/myisamlog.result'
--- a/mysql-test/r/myisamlog.result	2008-10-14 09:48:04 +0000
+++ b/mysql-test/r/myisamlog.result	2009-02-22 18:02:16 +0000
@@ -1,6 +1,7 @@
-create database if not exists mysqltest;
+DROP DATABASE IF EXISTS mysqltest;
+# CREATE generates no entry in the logical log.
+CREATE DATABASE mysqltest;
 use mysqltest;
-drop table if exists t1;
 create table t1 (a int, b varchar(100)) engine=myisam;
 insert into t1 values(1,'life'), (2,'file');
 insert into t1 select a*5, concat("A ",b) from t1;
@@ -14,13 +15,13 @@ a	b
 truncate table t1;
 flush table t1;
 Commands                         Used count    Errors Recover errors
-open                       26         0              0
+open                       16         0              0
 write                       4         0              0
 update                      1         0              0
 delete                      1         0              0
 close                       8         0              0
 extra                       #         0              0
-lock                       82         0              0
+lock                       48         0              0
 Total               #         0                0
 select * from t1;
 a	b
@@ -29,13 +30,13 @@ Trying to update MyISAM files according 
 Tables updated successfully
 
 Commands                         Used count    Errors Recover errors
-open                       27         0              0
+open                       17         0              0
 write                       4         0              0
 update                      1         0              0
 delete                      1         0              0
 close                       9         0              0
 extra                       #         0              0
-lock                       84         0              0
+lock                       50         0              0
 Total               #         0                0
 select * from t1;
 a	b

=== added file 'mysql-test/r/myisamlog_coverage.result'
--- a/mysql-test/r/myisamlog_coverage.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/myisamlog_coverage.result	2009-02-22 18:02:16 +0000
@@ -0,0 +1,139 @@
+DROP DATABASE IF EXISTS mysqltest;
+# CREATE generates no entry in the logical log.
+CREATE DATABASE mysqltest;
+USE mysqltest;
+CREATE TABLE t1 (c1 INT, c2 VARCHAR(100)) ENGINE=MyISAM;
+# Generate log entries.
+INSERT INTO t1 VALUES(1,'life'), (2,'file');
+INSERT INTO t1 SELECT c1*5, CONCAT("A ",c2) FROM t1;
+UPDATE t1 SET c2="A knife" WHERE c1=5;
+DELETE FROM t1 WHERE c1=10;
+SELECT * FROM t1;
+c1	c2
+1	life
+2	file
+5	A knife
+# Wipe it out (TRUNCATE generates no entry in the logical log).
+TRUNCATE TABLE t1;
+# Close the table (as we are going to change it outsid of the server).
+FLUSH TABLE t1;
+# Examine log.
+Commands                         Used count    Errors Recover errors
+open                       16         0              0
+write                       4         0              0
+update                      1         0              0
+delete                      1         0              0
+close                       8         0              0
+extra                       #         0              0
+lock                       48         0              0
+Total               #         0                0
+# Reopen the table and verify that it did not change.
+SELECT * FROM t1;
+c1	c2
+# Close the table (as we are going to change it outsid of the server).
+FLUSH TABLE t1;
+# Apply log to empty table.
+Trying to update MyISAM files according to log 'DATADIR/myisam.log'
+Tables updated successfully
+
+Commands                         Used count    Errors Recover errors
+open                       17         0              0
+write                       4         0              0
+update                      1         0              0
+delete                      1         0              0
+close                       9         0              0
+extra                       #         0              0
+lock                       50         0              0
+Total               #         0                0
+# Reopen the table and verify that content is back.
+SELECT * FROM t1;
+c1	c2
+1	life
+2	file
+5	A knife
+CHECK TABLE t1 EXTENDED;
+Table	Op	Msg_type	Msg_text
+mysqltest.t1	check	status	OK
+TRUNCATE TABLE t1;
+FLUSH TABLE t1;
+# Command line option without argument
+option "F" used without or with wrong argument
+TRUNCATE TABLE t1;
+FLUSH TABLE t1;
+# Inject error at mi_examine_log_files0
+Trying to update MyISAM files according to log 'DATADIR/myisam.log'
+ERROR_INJECT("mi_examine_log_files0")
+Got error 0, expected 0 on command open at 0
+TRUNCATE TABLE t1;
+FLUSH TABLE t1;
+# Inject error at mi_examine_log_files1
+Trying to update MyISAM files according to log 'DATADIR/myisam.log'
+ERROR_INJECT("mi_examine_log_files1")
+Tables updated successfully
+
+Commands                         Used count    Errors Recover errors
+open                       18         0              0
+write                       4         0              0
+update                      1         0              0
+delete                      1         0              0
+close                      10         0              0
+extra                       #         0              0
+lock                       54         0              0
+Total               #         0                0
+Had to do # re-open because of too few possibly open files
+TRUNCATE TABLE t1;
+FLUSH TABLE t1;
+# Inject error at mi_examine_log_command
+Trying to update MyISAM files according to log 'DATADIR/myisam.log'
+ERROR_INJECT("mi_examine_log_command")
+Unknown command 11 in logfile at position 0
+TRUNCATE TABLE t1;
+FLUSH TABLE t1;
+# Inject error at mi_examine_log_close_extra
+Trying to update MyISAM files according to log 'DATADIR/myisam.log'
+ERROR_INJECT("mi_examine_log_files1")
+ERROR_INJECT("mi_examine_log_close_extra")
+Got error -1, expected 0 on command lock at 259
+
+Commands                         Used count    Errors Recover errors
+open                        3         0              0
+extra                       #         0              0
+Total               #         0                0
+TRUNCATE TABLE t1;
+FLUSH TABLE t1;
+# Inject error at mi_examine_log_lock_result
+Trying to update MyISAM files according to log 'DATADIR/myisam.log'
+ERROR_INJECT("mi_examine_log_lock_result")
+Got error -1, expected 2147483647 on command lock at 259
+
+Commands                         Used count    Errors Recover errors
+open                        3         0              0
+extra                       #         0              0
+lock                        1         0              0
+Total               #         0                0
+TRUNCATE TABLE t1;
+FLUSH TABLE t1;
+# Inject error at close_some_file_none
+Trying to update MyISAM files according to log 'DATADIR/myisam.log'
+ERROR_INJECT("mi_examine_log_files1")
+ERROR_INJECT("close_some_file_none")
+Got error -1, expected 0 on command open at 87
+
+Commands                         Used count    Errors Recover errors
+open                        1         0              0
+extra                       #         0              0
+Total               #         0                0
+TRUNCATE TABLE t1;
+FLUSH TABLE t1;
+# Inject error at reopen_closed_file_name
+Trying to update MyISAM files according to log 'DATADIR/myisam.log'
+ERROR_INJECT("mi_examine_log_files1")
+ERROR_INJECT("reopen_closed_file_name")
+Got error 2, expected 0 on command re-open at 259
+
+Commands                         Used count    Errors Recover errors
+open                        3         0              0
+extra                       #         0              0
+Total               #         0                0
+USE test;
+DROP DATABASE mysqltest;

=== modified file 'mysql-test/t/myisamlog.test'
--- a/mysql-test/t/myisamlog.test	2008-07-22 18:08:06 +0000
+++ b/mysql-test/t/myisamlog.test	2009-02-22 18:02:16 +0000
@@ -1,48 +1,101 @@
-# Test of MyISAM logical logging and the myisamlog utility:
-# see if they can repopulate a table.
-
---source include/not_embedded.inc
-
-#
-# This test fails on win platforms currently. See BUG#38133.
-#
---source include/not_windows.inc
-
-disable_warnings;
-create database if not exists mysqltest;
-use mysqltest;
-drop table if exists t1;
-enable_warnings;
-# CREATE generates no entry in the logical log
-create table t1 (a int, b varchar(100)) engine=myisam;
-
-# we put some data into the table
-insert into t1 values(1,'life'), (2,'file');
-insert into t1 select a*5, concat("A ",b) from t1;
-update t1 set b="A knife" where a=5;
-delete from t1 where a=10;
-select * from t1;
-
-# wipe it out (TRUNCATE generates no entry in the logical log)
-truncate table t1;
-# close the table (as we are going to change it out of the server process)
-flush table t1;
-
-let $MYSQLD_DATADIR= `SELECT @@datadir`;
-
-# look at log
---replace_regex /extra......................../extra                       #/ /Total................/Total               #/
-exec $MYISAMLOG $MYSQLD_DATADIR/myisam.log ;
-# should not have changed the table
-select * from t1;
-flush table t1;
-
-# apply log to empty table
---replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
---replace_regex /extra......................../extra                       #/ /Total................/Total               #/
-exec $MYISAMLOG -F $MYSQLD_DATADIR -u $MYSQLD_DATADIR/myisam.log ;
-
-# reopen the table and verify that content is back
-select * from t1;
-check table t1 extended;
-drop database mysqltest;
+#
+# Test of MyISAM logical logging and the myisamlog utility:
+# see if they can repopulate a table.
+#
+
+#--let $MYISAMLOG = ../storage/myisam/myisamlog
+
+--source include/not_embedded.inc
+
+--disable_warnings
+--connection default
+DROP DATABASE IF EXISTS mysqltest;
+--enable_warnings
+
+#
+# get data directory.
+#
+--let $MYSQLD_DATADIR= `select @@datadir`
+
+#
+# This test needs to restart the server when run together with other
+# tests that use the --log-isam option, e.g. myisamlog_coverage.test. If
+# these would run in one server process without restart, the myisam.log
+# file would be kept open over the test cases. The later running test
+# case would append to the myisam.log file, which would give a different
+# myisam.log file than when running each standalone.
+#
+# Write mysqld.1.expect file to make mysql-test-run.pl expect shutdown
+# and wait before restarting the server.
+#
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait-myisamlog.test
+EOF
+#
+# Shutdown
+#
+--exec $MYSQLADMIN --no-defaults -S $MASTER_MYSOCK -P $MASTER_MYPORT  -u root --password= shutdown 2>&1
+#
+# Delete the old log file, if exists.
+#
+--error 0,1
+--remove_file $MYSQLD_DATADIR/myisam.log
+#
+# Write mysqld.1.expect file to make mysql-test-run.pl restart the server.
+#
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart-myisamlog.test
+EOF
+#
+# Turn on reconnect, to be sure.
+#
+--enable_reconnect
+#
+# Call script that will poll the server waiting for it to be back online again.
+#
+--source include/wait_until_connected_again.inc
+
+#
+# Start of tests.
+#
+
+--echo # CREATE generates no entry in the logical log.
+CREATE DATABASE mysqltest;
+use mysqltest;
+create table t1 (a int, b varchar(100)) engine=myisam;
+
+# we put some data into the table
+insert into t1 values(1,'life'), (2,'file');
+insert into t1 select a*5, concat("A ",b) from t1;
+update t1 set b="A knife" where a=5;
+delete from t1 where a=10;
+select * from t1;
+
+# wipe it out (TRUNCATE generates no entry in the logical log)
+truncate table t1;
+# close the table (as we are going to change it out of the server process)
+flush table t1;
+
+#
+# Make a copy of the log file for manual testing.
+--error 0,1
+--remove_file myisam-test.log
+--copy_file $MYSQLD_DATADIR/myisam.log myisam-test.log
+
+# look at log
+--replace_regex /extra......................../extra                       #/ /Total................/Total               #/
+exec $MYISAMLOG $MYSQLD_DATADIR/myisam.log ;
+# should not have changed the table
+select * from t1;
+flush table t1;
+
+# apply log to empty table
+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
+--replace_regex /extra......................../extra                       #/ /Total................/Total               #/
+exec $MYISAMLOG -F $MYSQLD_DATADIR -u $MYSQLD_DATADIR/myisam.log ;
+
+# reopen the table and verify that content is back
+select * from t1;
+check table t1 extended;
+drop database mysqltest;
+

=== added file 'mysql-test/t/myisamlog_coverage-master.opt'
--- a/mysql-test/t/myisamlog_coverage-master.opt	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/myisamlog_coverage-master.opt	2009-02-22 18:02:16 +0000
@@ -0,0 +1 @@
+--log-isam

=== added file 'mysql-test/t/myisamlog_coverage.test'
--- a/mysql-test/t/myisamlog_coverage.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/myisamlog_coverage.test	2009-02-22 18:02:16 +0000
@@ -0,0 +1,174 @@
+#
+# Coverage testing of MyISAM logical logging and the myisamlog utility
+#
+
+--source include/have_debug.inc
+--source include/not_embedded.inc
+
+--disable_warnings
+--connection default
+DROP DATABASE IF EXISTS mysqltest;
+--enable_warnings
+
+#
+# get data directory.
+#
+--let $MYSQLD_DATADIR= `select @@datadir`
+
+#
+# This test needs to restart the server when run together with other
+# tests that use the --log-isam option, e.g. myisamlog.test. If these
+# would run in one server process without restart, the myisam.log file
+# would be kept open over the test cases. The later running test case
+# would append to the myisam.log file, which would give a different
+# myisam.log file than when running each standalone.
+#
+# Write mysqld.1.expect file to make mysql-test-run.pl expect shutdown
+# and wait before restarting the server.
+#
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait-myisamlog_coverage.test
+EOF
+#
+# Shutdown
+#
+--exec $MYSQLADMIN --no-defaults -S $MASTER_MYSOCK -P $MASTER_MYPORT  -u root --password= shutdown 2>&1
+#
+# Delete the old log file, if exists.
+#
+--error 0,1
+--remove_file $MYSQLD_DATADIR/myisam.log
+#
+# Write mysqld.1.expect file to make mysql-test-run.pl restart the server.
+#
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart-myisamlog_coverage.test
+EOF
+#
+# Turn on reconnect, to be sure.
+#
+--enable_reconnect
+#
+# Call script that will poll the server waiting for it to be back online again.
+#
+--source include/wait_until_connected_again.inc
+
+#
+# Start of tests.
+#
+
+--echo # CREATE generates no entry in the logical log.
+CREATE DATABASE mysqltest;
+USE mysqltest;
+CREATE TABLE t1 (c1 INT, c2 VARCHAR(100)) ENGINE=MyISAM;
+#
+--echo # Generate log entries.
+INSERT INTO t1 VALUES(1,'life'), (2,'file');
+INSERT INTO t1 SELECT c1*5, CONCAT("A ",c2) FROM t1;
+UPDATE t1 SET c2="A knife" WHERE c1=5;
+DELETE FROM t1 WHERE c1=10;
+SELECT * FROM t1;
+#
+# Make a copy of the log file for manual testing.
+--error 0,1
+--remove_file myisam-test.log
+--copy_file $MYSQLD_DATADIR/myisam.log myisam-test.log
+#
+--echo # Wipe it out (TRUNCATE generates no entry in the logical log).
+TRUNCATE TABLE t1;
+--echo # Close the table (as we are going to change it outsid of the server).
+FLUSH TABLE t1;
+#
+--echo # Examine log.
+--replace_regex /extra......................../extra                       #/ /Total................/Total               #/
+exec $MYISAMLOG $MYSQLD_DATADIR/myisam.log 2>&1;
+#
+--echo # Reopen the table and verify that it did not change.
+SELECT * FROM t1;
+--echo # Close the table (as we are going to change it outsid of the server).
+FLUSH TABLE t1;
+#
+--echo # Apply log to empty table.
+--replace_result $MYSQLD_DATADIR DATADIR
+--replace_regex /extra......................../extra                       #/ /Total................/Total               #/
+exec $MYISAMLOG -F $MYSQLD_DATADIR -u $MYSQLD_DATADIR/myisam.log 2>&1;
+#
+--echo # Reopen the table and verify that content is back.
+SELECT * FROM t1;
+CHECK TABLE t1 EXTENDED;
+#
+#
+TRUNCATE TABLE t1;
+FLUSH TABLE t1;
+--echo # Command line option without argument
+--replace_result $MYSQLD_DATADIR DATADIR
+--error 1
+exec $MYISAMLOG -F 2>&1;
+#
+#
+TRUNCATE TABLE t1;
+FLUSH TABLE t1;
+--echo # Inject error at mi_examine_log_files0
+--replace_result $MYSQLD_DATADIR DATADIR
+--replace_regex /extra......................../extra                       #/ /Total................/Total               #/
+--error 1
+exec $MYISAMLOG -#d,mi_examine_log_files0 -F $MYSQLD_DATADIR -u $MYSQLD_DATADIR/myisam.log 2>&1;
+#
+#
+TRUNCATE TABLE t1;
+FLUSH TABLE t1;
+--echo # Inject error at mi_examine_log_files1
+--replace_result $MYSQLD_DATADIR DATADIR
+--replace_regex /extra......................../extra                       #/ /Total................/Total               #/ /[0-9]+ re-open/# re-open/
+exec $MYISAMLOG -#d,mi_examine_log_files1 -F $MYSQLD_DATADIR -u $MYSQLD_DATADIR/myisam.log 2>&1;
+#
+#
+TRUNCATE TABLE t1;
+FLUSH TABLE t1;
+--echo # Inject error at mi_examine_log_command
+--replace_result $MYSQLD_DATADIR DATADIR
+--replace_regex /extra......................../extra                       #/ /Total................/Total               #/
+--error 1
+exec $MYISAMLOG -#d,mi_examine_log_command -F $MYSQLD_DATADIR -u $MYSQLD_DATADIR/myisam.log 2>&1;
+#
+#
+TRUNCATE TABLE t1;
+FLUSH TABLE t1;
+--echo # Inject error at mi_examine_log_close_extra
+--replace_result $MYSQLD_DATADIR DATADIR
+--replace_regex /extra......................../extra                       #/ /Total................/Total               #/
+--error 1
+exec $MYISAMLOG -#d,mi_examine_log_close_extra,mi_examine_log_files1 -F $MYSQLD_DATADIR -u $MYSQLD_DATADIR/myisam.log 2>&1;
+#
+#
+TRUNCATE TABLE t1;
+FLUSH TABLE t1;
+--echo # Inject error at mi_examine_log_lock_result
+--replace_result $MYSQLD_DATADIR DATADIR
+--replace_regex /extra......................../extra                       #/ /Total................/Total               #/
+--error 1
+exec $MYISAMLOG -#d,mi_examine_log_lock_result -F $MYSQLD_DATADIR -u $MYSQLD_DATADIR/myisam.log 2>&1;
+#
+#
+TRUNCATE TABLE t1;
+FLUSH TABLE t1;
+--echo # Inject error at close_some_file_none
+--replace_result $MYSQLD_DATADIR DATADIR
+--replace_regex /extra......................../extra                       #/ /Total................/Total               #/
+--error 1
+exec $MYISAMLOG -#d,close_some_file_none,mi_examine_log_files1 -F $MYSQLD_DATADIR -u $MYSQLD_DATADIR/myisam.log 2>&1;
+#
+#
+TRUNCATE TABLE t1;
+FLUSH TABLE t1;
+--echo # Inject error at reopen_closed_file_name
+--replace_result $MYSQLD_DATADIR DATADIR
+--replace_regex /extra......................../extra                       #/ /Total................/Total               #/
+--error 1
+exec $MYISAMLOG -#d,reopen_closed_file_name,mi_examine_log_files1 -F $MYSQLD_DATADIR -u $MYSQLD_DATADIR/myisam.log 2>&1;
+#
+#
+# Cleanup.
+USE test;
+DROP DATABASE mysqltest;
+

=== modified file 'mysys/my_lock.c'
--- a/mysys/my_lock.c	2008-10-31 18:02:34 +0000
+++ b/mysys/my_lock.c	2009-02-22 18:02:16 +0000
@@ -71,6 +71,29 @@ static int win_lock(File fd, int locktyp
     /* write lock is mapped to an exclusive lock. */
     dwFlags= LOCKFILE_EXCLUSIVE_LOCK;
 
+  /*
+    Drop old lock first to avoid double locking.
+    During analyze of Bug#38133 (Myisamlog test fails on Windows)
+    I met the situation that the program myisamlog locked the file
+    exclusively, then additionally shared, then did one unlock, and
+    then blocked on an attempt to lock it exclusively again.
+    Unlocking before every lock fixed the problem.
+    Note that this introduces a race condition. When the application
+    wants to convert an exclusive lock into a shared one, it will now
+    first unlock the file and then lock it shared. A waiting exclusive
+    lock could step in here. For reasons described in Bug#38133 and
+    Bug#41124 (Server hangs on Windows with --external-locking after
+    INSERT...SELECT) and in the review thread at
+    http://lists.mysql.com/commits/60721 it seems to be the better
+    option than not to unlock here.
+    If one day someone notices a way how to do file lock type changes
+    on Windows without unlocking before taking the new lock, please
+    change this code accordingly to fix the race condition.
+  */
+  if (!UnlockFileEx(hFile, 0, liLength.LowPart, liLength.HighPart, &ov) &&
+      (GetLastError() != ERROR_NOT_LOCKED))
+    goto error;
+
   if (timeout_sec == WIN_LOCK_INFINITE)
   {
     if (LockFileEx(hFile, dwFlags, 0, liLength.LowPart, liLength.HighPart, &ov))

=== modified file 'sql/handler.cc'
--- a/sql/handler.cc	2009-02-04 10:49:16 +0000
+++ b/sql/handler.cc	2009-02-22 18:02:16 +0000
@@ -1123,7 +1123,8 @@ int ha_commit_trans(THD *thd, bool all)
     uint rw_ha_count;
     bool rw_trans;
 
-    DBUG_EXECUTE_IF("crash_commit_before", abort(););
+    /* Use DBUG_ABORT() instead of abort() to avoid a pop-up on Windows. */
+    DBUG_EXECUTE_IF("crash_commit_before", DBUG_ABORT(););
 
     /* Close all cursors that can not survive COMMIT */
     if (is_real_trans)                          /* not a statement commit */

=== modified file 'storage/myisam/mi_close.c'
--- a/storage/myisam/mi_close.c	2008-12-30 12:13:31 +0000
+++ b/storage/myisam/mi_close.c	2009-02-22 18:02:16 +0000
@@ -115,7 +115,10 @@ int mi_close(register MI_INFO *info)
       }
     }
 #endif
-    my_free((uchar*) info->s,MYF(0));
+    /*
+      Do not free the share here. myisam_log_command_logical() needs
+      to test for share->temporary.
+    */
   }
   pthread_mutex_unlock(&THR_LOCK_myisam);
   if (info->ftparser_param)
@@ -127,6 +130,9 @@ int mi_close(register MI_INFO *info)
     error = my_errno;
 
   myisam_log_command_logical(MI_LOG_CLOSE, info, NULL, 0, error);
+
+  if (flag)
+    my_free((uchar*) info->s,MYF(0));
   my_free((uchar*) info,MYF(0));
 
   if (error)

=== modified file 'storage/myisam/mi_examine_log.c'
--- a/storage/myisam/mi_examine_log.c	2008-10-20 09:16:47 +0000
+++ b/storage/myisam/mi_examine_log.c	2009-02-22 18:02:16 +0000
@@ -69,6 +69,13 @@ struct file_info {
   my_bool closed;
   /** If this table matches the inclusion rules (or has to be ignored) */
   my_bool used;
+  /**
+    Lock type, set by last MI_LOG_LOCK command. Initialized to F_UNLCK
+    at MI_LOG_OPEN. This is not changed if the file is temporarily
+    closed. So it can be re-locked on re-open.
+  */
+  int lock_type;
+  /* File was last accessed at this log entry number. */
   ulong accessed;
 };
 
@@ -85,6 +92,20 @@ struct st_access_param
 
 #define NO_FILEPOS HA_OFFSET_ERROR
 
+/*
+  Error injection. Built on DBUG.
+  This is similar to error injection in the server.
+  In case that one becomes globally available, we undefine it first.
+*/
+#ifdef ERROR_INJECT
+#undef ERROR_INJECT
+#endif
+#define ERROR_INJECT(_keyword_, _action_) \
+  DBUG_EXECUTE_IF((_keyword_), fflush(stdout); \
+                  fprintf(stderr, "ERROR_INJECT(\"%s\")\n", (_keyword_)); \
+                  fflush(stderr); DBUG_PRINT("myisamlog", \
+                  ("ERROR_INJECT(\"%s\")\n", (_keyword_))); _action_)
+
 void mi_examine_log_param_init(MI_EXAMINE_LOG_PARAM *param);
 int mi_examine_log(MI_EXAMINE_LOG_PARAM *param);
 static int read_string(IO_CACHE *file,uchar* *to,uint length);
@@ -96,7 +117,7 @@ static int test_when_accessed(struct fil
 			      struct st_access_param *access_param);
 static void file_info_free(struct file_info *info);
 static int close_some_file(TREE *tree);
-static int reopen_closed_file(TREE *tree,struct file_info *file_info);
+static int reopen_closed_file(struct file_info *file_info);
 static int find_record_with_key(struct file_info *file_info,uchar *record);
 static int mi_close_care_state(MI_INFO *info);
 static void printf_log(uint verbose, ulong isamlog_process,
@@ -142,7 +163,7 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM 
   int lock_command,mi_result;
   char isam_file_name[FN_REFLEN], llbuff[21], llbuff2[21];
   uchar head[20], *head_ptr;
-  uchar	*buff;
+  uchar	*buff= NULL;
   struct test_if_open_param open_param;
   IO_CACHE cache;
   File log_file;
@@ -155,6 +176,10 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM 
       { 11, 14 }, { 11, 14 }, {  9, 16 }, {  9, 16 }, {  7, 12 }  };
   uint has_pid_and_result[]= {1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0};
   DBUG_ENTER("mi_examine_log");
+  DBUG_PRINT("myisamlog", ("max_files: %u  update: %u",
+                           mi_exl->max_files, mi_exl->update));
+  ERROR_INJECT("mi_examine_log_files0", mi_exl->max_files= 0;);
+  ERROR_INJECT("mi_examine_log_files1", mi_exl->max_files= 1;);
 
   compile_time_assert((sizeof(mi_log_command_name) /
                        sizeof(mi_log_command_name[0]) ==
@@ -186,6 +211,14 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM 
   (void) init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,KEY_CACHE_SIZE,
                         0, 0);
 
+  /*
+    Initialize members of file_info that are used for pointing to
+    allocated memory. At the error labels we want to be able to free it.
+  */
+  file_info.name= NULL;
+  file_info.show_name= NULL;
+  file_info.record= NULL;
+
   files_open=0; access_time=0;
   while (access_time++ != mi_exl->number_of_commands &&
 	 !my_b_read(&cache, head, 1))
@@ -194,6 +227,19 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM 
     head_ptr= head;
     command=(uint) head_ptr[0];
     command-= (big_numbers= (command & MI_LOG_BIG_NUMBERS));
+    /*
+      'command' is a number that is used to index arrays. Better check
+      it for range.
+    */
+    ERROR_INJECT("mi_examine_log_command", command= MI_LOG_END_SENTINEL;);
+    if (command >= MI_LOG_END_SENTINEL)
+    {
+      fflush(stdout);
+      fprintf(stderr,"Unknown command %u in logfile at position %s\n",
+              command, llstr(isamlog_filepos, llbuff));
+      fflush(stderr);
+      goto end;
+    }
     if (big_numbers != 0)
       big_numbers= 1;
     if (my_b_read(&cache, head, head_len[command][big_numbers] - 1))
@@ -219,24 +265,68 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM 
     }
     else
       isamlog_process= file_info.process= result= 0;
+
+    /*
+      Try to find the file with file_info.process and file_info.filenr
+      in the file tree. The search function, as registered with
+      init_tree() is file_info_compare(). If the file does not exist in
+      the tree, most commands will be ignored for this file.
+    */
     if ((curr_file_info=(struct file_info*) tree_search(&tree, &file_info,
 							tree.custom_arg)))
     {
       curr_file_info->accessed=access_time;
-      if (mi_exl->update && curr_file_info->used && curr_file_info->closed)
+      /*
+        If the file has been closed due to lack of file descriptors,
+        re-open it to execute the command.
+        No need to re-open for the MI_LOG_CLOSE command.
+      */
+      if (mi_exl->update && curr_file_info->used && curr_file_info->closed &&
+          (command != MI_LOG_CLOSE))
       {
-	if (reopen_closed_file(&tree,curr_file_info))
-	{
-	  command=sizeof(mi_exl->com_count)/sizeof(mi_exl->com_count[0][0])/3;
-	  result=0;
-	  goto com_err;
-	}
+        /*
+          We found a closed file. It can only be closed due to a lack
+          of file descriptors. When a file is explicitly closed, its
+          information is removed from the tree and freed.
+          But this does not mean that there are still open files in
+          the tree. All other files could have been explicitly closed
+          meanwhile. So close a file only if there is still a lack of
+          file descriptors.
+        */
+        if (files_open >= mi_exl->max_files)
+        {
+          ERROR_INJECT("mi_examine_log_close_extra",
+                       close_some_file(&tree); my_errno= -1;);
+          if (close_some_file(&tree))
+          {
+            DBUG_PRINT("myisamlog", ("failed to close some file"));
+            goto com_err; /* No file to close */
+          }
+          files_open--;
+        }
+        if (reopen_closed_file(curr_file_info))
+        {
+          DBUG_PRINT("myisamlog", ("failed to reopen closed file"));
+          command=sizeof(mi_exl->com_count)/sizeof(mi_exl->com_count[0][0])/3;
+          result=0;
+          goto com_err;
+        }
+        files_open++;
         mi_exl->re_open_count++;
       }
     }
-    DBUG_PRINT("info",("command: %u curr_file_info: 0x%lx used: %u",
-                       command, (ulong)curr_file_info,
-                       curr_file_info ? curr_file_info->used : 0));
+    if (!curr_file_info)
+      DBUG_PRINT("myisamlog",
+                 ("command: %u '%s'  info: 0x0",
+                  command, mi_log_command_name[command]));
+    else
+      DBUG_PRINT("myisamlog",
+                 ("command: %u '%s'  info: 0x%lx  proc: %ld  "
+                  "fno: %d  file: '%s'  used: %d  closed: %d",
+                  command, mi_log_command_name[command],
+                  (ulong) curr_file_info, curr_file_info->process,
+                  curr_file_info->filenr, curr_file_info->name,
+                  curr_file_info->used, curr_file_info->closed));
     /*
       We update our statistic (how many commands issued, per command type),
       if this is a valid command about a file we want to include.
@@ -259,9 +349,14 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM 
 	printf("\nWarning: %s is opened with same process and filenumber\n"
                "Maybe you should use the -P option ?\n",
 	       curr_file_info->show_name);
-      file_info.name=0;
-      file_info.show_name=0;
-      file_info.record=0;
+      /*
+        These file_info members should be non-null only during an open
+        operation. Initially and after open they should be nulled.
+        That way we can free them in case of a jump to an error label.
+      */
+      DBUG_ASSERT(!file_info.name);
+      DBUG_ASSERT(!file_info.show_name);
+      DBUG_ASSERT(!file_info.record);
       length= big_numbers ? mi_uint4korr(head_ptr) : mi_uint2korr(head_ptr);
       if (read_string(&cache, (uchar **)&file_info.name, length))
 	goto err;
@@ -273,6 +368,7 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM 
 	for (pos=file_info.name; (pos=strchr(pos,'\\')) ; pos++)
 	  *pos= '/';
 
+        DBUG_PRINT("myisamlog", ("prefix_remove: %u", mi_exl->prefix_remove));
 	pos=file_info.name;
 	for (i=0 ; i < mi_exl->prefix_remove ; i++)
 	{
@@ -281,10 +377,18 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM 
 	    break;
 	  pos=next+1;
 	}
+        DBUG_PRINT("myisamlog", ("pos: '%s'", pos));
+        DBUG_PRINT("myisamlog", ("filepath: '%s'", mi_exl->filepath));
 	to=isam_file_name;
-	if (mi_exl->filepath)
+        /* Include filepath if pos is not an absolute path. */
+	if (mi_exl->filepath &&
+#ifdef FN_DEVCHAR
+            !strrchr(pos, FN_DEVCHAR) &&
+#endif
+            (*pos != '/'))
 	  to=convert_dirname(isam_file_name,mi_exl->filepath,NullS);
 	strmov(to,pos);
+        DBUG_PRINT("myisamlog", ("isam_file_name: '%s'", isam_file_name));
 	fn_ext(isam_file_name)[0]=0;	/* Remove extension */
       }
       open_param.name=file_info.name;
@@ -330,8 +434,15 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM 
 	  goto end;
 	files_open++;
 	file_info.closed=0;
+        /* After explicit open, file is not locked. */
+        file_info.lock_type= F_UNLCK;
+      }
+      if (!tree_insert(&tree, (uchar*) &file_info, 0, tree.custom_arg))
+      {
+        /* tree_insert() (my_malloc()) should have written an error message. */
+        goto end; /* purecov: inspected */
       }
-      (void) tree_insert(&tree, (uchar*) &file_info, 0, tree.custom_arg);
+
       if (file_info.used)
       {
 	if (mi_exl->verbose && !mi_exl->record_pos_file)
@@ -342,6 +453,21 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM 
 	if (result)
 	  mi_exl->com_count[command][1]++;
       }
+
+      DBUG_PRINT("myisamlogop",
+                 ("open  proc: %ld  fno: %d  file: '%s'  used: %d  closed: %d",
+                  file_info.process, file_info.filenr, file_info.name,
+                  file_info.used, file_info.closed));
+      /*
+        tree_insert() copied file_info (copied pointers). If not
+        NULL-ed, they would not be freed while in use: the my_free() at
+        the end of the program would rather double-free them, because
+        file_info_free() (called via delete_tree()) would already have
+        freed them.
+      */
+      file_info.name= NULL;
+      file_info.show_name= NULL;
+      file_info.record= NULL;
       break;
     case MI_LOG_CLOSE:
       if (mi_exl->verbose && !mi_exl->record_pos_file &&
@@ -352,6 +478,12 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM 
                    mi_log_command_name[command],result);
       if (curr_file_info)
       {
+        DBUG_PRINT("myisamlogop",
+                   ("close proc: %ld  fno: %d  file: '%s'  "
+                    "used: %d  closed: %d",
+                    curr_file_info->process,
+                    curr_file_info->filenr, curr_file_info->name,
+                    curr_file_info->used, curr_file_info->closed));
 	if (!curr_file_info->closed)
 	  files_open--;
 	(void) tree_delete(&tree, (uchar*) curr_file_info, 0, tree.custom_arg);
@@ -438,7 +570,6 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM 
         head_ptr+= 4;
         length= mi_uint2korr(head_ptr);
       }
-      buff=0;
       if (read_string(&cache,&buff,length))
 	goto err;
       if ((!mi_exl->record_pos_file ||
@@ -519,6 +650,7 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM 
 	}
       }
       my_free(buff,MYF(0));
+      buff= NULL;
       break;
     case MI_LOG_WRITE_BYTES_MYI:
     case MI_LOG_WRITE_BYTES_MYD:
@@ -534,7 +666,6 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM 
         head_ptr+= 4;
         length= mi_uint2korr(head_ptr);
       }
-      buff=0;
       if (read_string(&cache, &buff, length))
         goto err;
       if ((!mi_exl->record_pos_file ||
@@ -565,6 +696,7 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM 
           goto com_err;
       }
       my_free(buff,MYF(0));
+      buff= NULL;
       break;
     case MI_LOG_CHSIZE_MYI:
       /* here 'filepos' means new length of file */
@@ -607,11 +739,20 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM 
 	printf_log(mi_exl->verbose, isamlog_process, isamlog_filepos,
                    "%s: %s(%d) -> %d",FILENAME(curr_file_info),
 		   mi_log_command_name[command],lock_command,result);
-      if (mi_exl->update && curr_file_info && !curr_file_info->closed)
+      if (mi_exl->update && curr_file_info)
       {
-	if (mi_lock_database(curr_file_info->isam,lock_command) !=
-	    (int) result)
-	  goto com_err;
+        /* Remember lock type for re-open. */
+        curr_file_info->lock_type= lock_command;
+        DBUG_ASSERT(!curr_file_info->closed);
+        DBUG_PRINT("myisamlogop",
+                   ("lock  proc: %ld  fno: %d  file: '%s'  lock_type: %d",
+                    curr_file_info->process, curr_file_info->filenr,
+                    curr_file_info->name, lock_command));
+        ERROR_INJECT("mi_examine_log_lock_result",
+                     my_errno= -1; result= INT_MAX; /*Not UINT_MAX!*/);
+        if (mi_lock_database(curr_file_info->isam,lock_command) !=
+            (int) result)
+          goto com_err;
       }
       break;
     case MI_LOG_DELETE_ALL:
@@ -635,6 +776,8 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM 
       goto end;
     }
   }
+  DBUG_PRINT("myisamlog", ("end loop access_time: %lu  cmd_cnt: %lu",
+                           access_time, mi_exl->number_of_commands));
   end_key_cache(dflt_key_cache,1);
   delete_tree(&tree);
   (void) end_io_cache(&cache);
@@ -643,24 +786,33 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM 
     DBUG_RETURN(1);
   DBUG_RETURN(0);
 
+  /* purecov: begin inspected */
  err:
+  DBUG_PRINT("myisamlog", ("err label"));
   fflush(stdout);
   fprintf(stderr,"Got error %d when reading from logfile\n",my_errno);
   fflush(stderr);
   goto end;
+  /* purecov: end */
  com_err:
+  DBUG_PRINT("myisamlog", ("com_err label"));
   fflush(stdout);
   fprintf(stderr,"Got error %d, expected %d on command %s at %s\n",
           my_errno,result,mi_log_command_name[command],
           llstr(isamlog_filepos,llbuff));
   fflush(stderr);
  end:
+  DBUG_PRINT("myisamlog", ("end label"));
   end_key_cache(dflt_key_cache, 1);
   delete_tree(&tree);
   (void) end_io_cache(&cache);
   (void) my_close(log_file,MYF(0));
   if (write_file)
     (void) my_fclose(write_file,MYF(MY_WME));
+  my_free(file_info.name, MYF(MY_ALLOW_ZERO_PTR));
+  my_free(file_info.show_name, MYF(MY_ALLOW_ZERO_PTR));
+  my_free(file_info.record, MYF(MY_ALLOW_ZERO_PTR));
+  my_free(buff, MYF(MY_ALLOW_ZERO_PTR));
   DBUG_RETURN(1);
 }
 
@@ -681,6 +833,7 @@ static int read_string(IO_CACHE *file, r
     DBUG_RETURN(1);
   }
   *((char*) *to+length)= '\0';
+  DBUG_PRINT("myisamlog", ("string: '%s'", *to));
   DBUG_RETURN (0);
 }				/* read_string */
 
@@ -742,6 +895,8 @@ static int test_when_accessed (struct fi
 static void file_info_free(struct file_info *fileinfo)
 {
   DBUG_ENTER("file_info_free");
+  DBUG_PRINT("myisamlog", ("freeing info: 0x%lx  file: '%s'",
+                           (long) fileinfo, fileinfo->name));
   /* The 2 conditions below can be true only if 'update' */
   if (!fileinfo->closed)
     (void) mi_close_care_state(fileinfo->isam);
@@ -763,8 +918,12 @@ static int close_some_file(TREE *tree)
 
   (void) tree_walk(tree,(tree_walk_action) test_when_accessed,
                    (void*) &access_param,left_root_right);
+  ERROR_INJECT("close_some_file_none", access_param.found= 0; my_errno= -1;);
   if (!access_param.found)
     return 1;			/* No open file that is possibly to close */
+  DBUG_PRINT("myisamlog", ("closing info: 0x%lx  file: '%s'",
+                           (long) access_param.found,
+                           access_param.found->name));
   if (mi_close_care_state(access_param.found->isam))
     return 1;
   access_param.found->closed=1;
@@ -772,20 +931,37 @@ static int close_some_file(TREE *tree)
 }
 
 
-static int reopen_closed_file(TREE *tree, struct file_info *fileinfo)
+static int reopen_closed_file(struct file_info *fileinfo)
 {
   char name[FN_REFLEN];
-  if (close_some_file(tree))
-    return 1;				/* No file to close */
+  DBUG_ENTER("reopen_closed_file");
+
   strmov(name,fileinfo->show_name);
   if (fileinfo->id > 1)
     *strrchr(name,'<')='\0';		/* Remove "<id>" */
 
+  ERROR_INJECT("reopen_closed_file_name", strcpy(name, "/non/existent/file"););
   if (!(fileinfo->isam= mi_open(name, O_RDWR,
                                 HA_OPEN_FOR_REPAIR | HA_OPEN_WAIT_IF_LOCKED)))
-    return 1;
+    DBUG_RETURN(1);
   fileinfo->closed=0;
-  return 0;
+  /*
+    If the file was explicitly locked when we needed to close it due to
+    lack of file descriptors, we re-lock it after re-open.
+  */
+  if (fileinfo->lock_type != F_UNLCK)
+  {
+    DBUG_PRINT("myisamlog",
+               ("lock info: 0x%lx  proc: %ld  fno: %d  file: '%s'",
+                (long) fileinfo, fileinfo->process,
+                fileinfo->filenr, fileinfo->name));
+    if (mi_lock_database(fileinfo->isam, fileinfo->lock_type))
+      DBUG_RETURN(1); /* purecov: inspected */
+  }
+  DBUG_PRINT("myisamlog", ("re-opened info: 0x%lx  lock_type: %d  file: '%s'",
+                           (long) fileinfo, fileinfo->lock_type,
+                           fileinfo->name));
+  DBUG_RETURN(0);
 }
 
 	/* Try to find record with uniq key */

=== modified file 'storage/myisam/mi_locking.c'
--- a/storage/myisam/mi_locking.c	2008-10-31 18:02:34 +0000
+++ b/storage/myisam/mi_locking.c	2009-02-22 18:02:16 +0000
@@ -238,7 +238,7 @@ int mi_lock_database(MI_INFO *info, int 
      */
     if( info->owned_by_merge && (info->s)->kfile < 0 )
     {
-      error = HA_ERR_NO_SUCH_TABLE;
+      my_errno= error= HA_ERR_NO_SUCH_TABLE;
     }
   }
 #endif

=== modified file 'storage/myisam/mi_log.c'
--- a/storage/myisam/mi_log.c	2009-01-27 02:08:48 +0000
+++ b/storage/myisam/mi_log.c	2009-02-22 18:02:16 +0000
@@ -300,6 +300,10 @@ void _myisam_log_command(IO_CACHE *log, 
   my_bool logical= (log == &myisam_logical_log);
   MYISAM_SHARE *share;
   File file;
+  DBUG_ENTER("_myisam_log_command");
+  DBUG_PRINT("mi_log", ("command: %u '%s'  buffert: '%.*s'  result: %d",
+                        command, mi_log_command_name[command],
+                        length, buffert, result));
 
   /*
     Speed in online backup (physical log) matters more than in debugging
@@ -308,7 +312,7 @@ void _myisam_log_command(IO_CACHE *log, 
   if (unlikely(logical))
   {
     file= ((MI_INFO *)info_or_share)->dfile;
-    LINT_INIT(share);
+    share= ((MI_INFO *)info_or_share)->s;
   }
   else
   {
@@ -319,6 +323,13 @@ void _myisam_log_command(IO_CACHE *log, 
   DBUG_ASSERT(command == MI_LOG_OPEN  || command == MI_LOG_DELETE ||
               command == MI_LOG_CLOSE || command == MI_LOG_EXTRA ||
               command == MI_LOG_LOCK  || command == MI_LOG_DELETE_ALL);
+
+  /* Do not log operations on temporary tables. */
+  DBUG_PRINT("mi_log", ("table: '%s'  temporary: %d",
+                        share->unresolv_file_name, share->temporary));
+  if (share->temporary)
+    goto end;
+
   old_errno=my_errno;
   DBUG_ASSERT(((uint)result) <= UINT_MAX16);
   if (file >= UINT_MAX16 || length >= UINT_MAX16)
@@ -422,6 +433,8 @@ retry:
   }
   pthread_mutex_unlock(&THR_LOCK_myisam_log);
   my_errno=old_errno;
+ end:
+  DBUG_VOID_RETURN;
 }
 
 
@@ -440,17 +453,26 @@ void _myisam_log_record_logical(enum myi
                                 MI_INFO *info, const uchar *record,
                                 my_off_t filepos, int result)
 {
+  MYISAM_SHARE *share= info->s;
   uchar header[22],*pos;
   int error,old_errno;
   uint length, headerlen;
   ulong pid=(ulong) GETPID();
+  DBUG_ENTER("_myisam_log_record_logical");
 
   DBUG_ASSERT(command == MI_LOG_UPDATE || command == MI_LOG_WRITE);
+
+  /* Do not log operations on temporary tables. */
+  DBUG_PRINT("mi_log", ("table: '%s'  temporary: %d",
+                        share->unresolv_file_name, share->temporary));
+  if (share->temporary)
+    goto end;
+
   old_errno=my_errno;
-  if (!info->s->base.blobs)
-    length=info->s->base.reclength;
+  if (!share->base.blobs)
+    length=share->base.reclength;
   else
-    length=info->s->base.reclength+ _mi_calc_total_blob_length(info,record);
+    length=share->base.reclength+ _mi_calc_total_blob_length(info,record);
   DBUG_ASSERT(((uint)result) <= UINT_MAX16);
   if (info->dfile >= UINT_MAX16 || filepos >= UINT_MAX32 ||
       length >= UINT_MAX16)
@@ -479,12 +501,12 @@ void _myisam_log_record_logical(enum myi
   error= my_lock(myisam_logical_log.file, F_WRLCK, 0L, F_TO_EOF,
                  MYF(MY_SEEK_NOT_DONE));
   (void) my_b_write(&myisam_logical_log, header, headerlen);
-  (void) my_b_write(&myisam_logical_log, record, info->s->base.reclength);
-  if (info->s->base.blobs)
+  (void) my_b_write(&myisam_logical_log, record, share->base.reclength);
+  if (share->base.blobs)
   {
     MI_BLOB *blob,*end;
 
-    for (end=info->blobs+info->s->base.blobs, blob= info->blobs;
+    for (end=info->blobs+share->base.blobs, blob= info->blobs;
 	 blob != end ;
 	 blob++)
     {
@@ -499,6 +521,8 @@ void _myisam_log_record_logical(enum myi
                    MYF(MY_SEEK_NOT_DONE));
   pthread_mutex_unlock(&THR_LOCK_myisam_log);
   my_errno=old_errno;
+ end:
+  DBUG_VOID_RETURN;
 }
 
 

=== modified file 'storage/myisam/myisamlog.c'
--- a/storage/myisam/myisamlog.c	2008-07-09 07:12:43 +0000
+++ b/storage/myisam/myisamlog.c	2009-02-22 18:02:16 +0000
@@ -59,8 +59,14 @@ int main(int argc, char **argv)
     mi_exl.table_selection_hook= matches_list_of_tables;
   }
 
-  /* Number of MyISAM files we can have open at one time */
-  mi_exl.max_files= (my_set_max_open_files(max(mi_exl.max_files,8))-6)/2;
+  /*
+    Despite its name, max_files is not the number of MyISAM files we can
+    have open at one time, but the number of MyISAM tables. Some
+    operating systems do not increase the limit above the input argument
+    of my_set_max_open_files(). So don't start too low.
+  */
+  mi_exl.max_files=
+    (my_set_max_open_files(max(mi_exl.max_files * 2, MY_NFILE)) - 6) / 2;
 
   /*
     Program must work in all conditions: support symbolic links.
@@ -75,6 +81,7 @@ int main(int argc, char **argv)
 	   (mi_exl.recover ? "recover" : "update"),mi_exl.log_filename);
 
   error= mi_examine_log(&mi_exl);
+  DBUG_PRINT("myisamlog", ("error from mi_examine_log: %d", error));
 
   if (mi_exl.update && ! error)
     puts("Tables updated successfully");
@@ -256,6 +263,17 @@ static void get_options(register int *ar
 #include <help_end.h>
 	break;
       default:
+        if (*pos == '-')
+        {
+          /* Long option */
+          if (!strncmp(pos + 1, "debug=", 6))
+          {
+            pos+= 7;
+            DBUG_PUSH(pos);
+            pos= " "; /* Skip rest of arg */
+            break;
+          }
+        }
 	printf("illegal option: \"-%c\"\n",*pos);
 	break;
       }
@@ -275,8 +293,8 @@ static void get_options(register int *ar
   }
   return;
  err:
-  (void) fprintf(stderr,"option \"%c\" used without or with wrong argument\n",
-	       option);
+  fflush(stdout);
+  fprintf(stderr,"option \"%c\" used without or with wrong argument\n", option);
   exit(1);
 }
 


Attachment: [text/bzr-bundle] bzr/ingo.struewing@sun.com-20090222180216-riba1s5xckocagnp.bundle
Thread
bzr commit into mysql-6.0-backup branch (ingo.struewing:2773) Bug#38133Ingo Struewing22 Feb