#At file:///home2/mydev/bzrroot/mysql-6.0-bug38133-2/
2730 Ingo Struewing 2008-11-13
Bug#38133 - Myisamlog test fails on Windows
Updating of a table from the myisam.log file was not possible in most cases.
- 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 every lock.
modified:
mysql-test/r/myisamlog.result
mysql-test/t/myisamlog.test
mysys/my_file.c
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/myisamlog.c
per-file messages:
mysql-test/r/myisamlog.result
Bug#38133 - Myisamlog test fails on Windows
Changed result.
mysql-test/t/myisamlog.test
Bug#38133 - Myisamlog test fails on Windows
Added text marks to relate messages to programs.
mysys/my_file.c
Bug#38133 - Myisamlog test fails on Windows
Optimized control flow for error reporting.
Added DBUG.
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().
storage/myisam/mi_close.c
Bug#38133 - Myisamlog test fails on Windows
Added DBUG.
storage/myisam/mi_examine_log.c
Bug#38133 - Myisamlog test fails on Windows
Added member lock_type to file_info.
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 code to re-lock a file after re-open.
Pulled close_some_files() out of reopen_closed_file() to have access
to max_files.
storage/myisam/mi_locking.c
Bug#38133 - Myisamlog test fails on Windows
Disabled locking for temporary tables that do not use F_EXTRA_LCK.
Added DBUG.
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.
=== modified file 'mysql-test/r/myisamlog.result'
--- a/mysql-test/r/myisamlog.result 2008-07-09 14:27:18 +0000
+++ b/mysql-test/r/myisamlog.result 2008-11-13 08:55:37 +0000
@@ -13,6 +13,7 @@ a b
5 A knife
truncate table t1;
flush table t1;
+# Running myisamlog
Commands Used count Errors Recover errors
open 16 0 0
write 4 0 0
@@ -22,9 +23,11 @@ close 8 0
extra # 0 0
lock 48 0 0
Total # 0 0
+# Returned from myisamlog
select * from t1;
a b
flush table t1;
+# Running myisamlog
Trying to update MyISAM files according to log 'VARDIR/master-data/myisam.log'
Tables updated successfully
@@ -37,6 +40,7 @@ close 9 0
extra # 0 0
lock 50 0 0
Total # 0 0
+# Returned from myisamlog
select * from t1;
a b
1 life
=== modified file 'mysql-test/t/myisamlog.test'
--- a/mysql-test/t/myisamlog.test 2008-07-15 20:02:29 +0000
+++ b/mysql-test/t/myisamlog.test 2008-11-13 08:55:37 +0000
@@ -3,11 +3,6 @@
--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;
@@ -29,16 +24,20 @@ truncate table t1;
flush table t1;
# look at log
+--echo # Running myisamlog
--replace_regex /extra......................../extra #/ /Total................/Total #/
exec $MYISAMLOG $MYSQLTEST_VARDIR/master-data/myisam.log ;
+--echo # Returned from myisamlog
# should not have changed the table
select * from t1;
flush table t1;
# apply log to empty table
+--echo # Running myisamlog
--replace_result $MYSQLTEST_VARDIR VARDIR
--replace_regex /extra......................../extra #/ /Total................/Total #/
exec $MYISAMLOG -F $MYSQLTEST_VARDIR/master-data -u $MYSQLTEST_VARDIR/master-data/myisam.log ;
+--echo # Returned from myisamlog
# reopen the table and verify that content is back
select * from t1;
=== modified file 'mysys/my_file.c'
--- a/mysys/my_file.c 2008-06-17 23:37:23 +0000
+++ b/mysys/my_file.c 2008-11-13 08:55:37 +0000
@@ -74,8 +74,11 @@ static uint set_max_open_files(uint max_
#else
static int set_max_open_files(uint max_file_limit)
{
+ DBUG_ENTER("set_max_open_files");
+ DBUG_PRINT("enter", ("max_file_limit: %u OS_FILE_LIMIT: %u",
+ max_file_limit, OS_FILE_LIMIT));
/* We don't know the limit. Return best guess */
- return min(max_file_limit, OS_FILE_LIMIT);
+ DBUG_RETURN(min(max_file_limit, OS_FILE_LIMIT));
}
#endif
@@ -100,11 +103,14 @@ uint my_set_max_open_files(uint files)
files+= MY_FILE_MIN;
files= set_max_open_files(min(files, OS_FILE_LIMIT));
if (files <= MY_NFILE)
- DBUG_RETURN(files);
+ goto end;
if (!(tmp= (struct st_my_file_info*) my_malloc(sizeof(*tmp) * files,
MYF(MY_WME))))
- DBUG_RETURN(MY_NFILE);
+ {
+ files= MY_NFILE;
+ goto end;
+ }
/* Copy any initialized files */
memcpy((char*) tmp, (char*) my_file_info,
@@ -114,6 +120,8 @@ uint my_set_max_open_files(uint files)
my_free_open_file_info(); /* Free if already allocated */
my_file_info= tmp;
my_file_limit= files;
+
+ end:
DBUG_PRINT("exit",("files: %u", files));
DBUG_RETURN(files);
}
=== modified file 'mysys/my_lock.c'
--- a/mysys/my_lock.c 2008-09-12 12:57:19 +0000
+++ b/mysys/my_lock.c 2008-11-13 08:55:37 +0000
@@ -71,13 +71,23 @@ 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.
+ */
+ (void) UnlockFileEx(hFile, 0, liLength.LowPart, liLength.HighPart, &ov);
+
if (timeout_sec == WIN_LOCK_INFINITE)
{
if (LockFileEx(hFile, dwFlags, 0, liLength.LowPart, liLength.HighPart, &ov))
DBUG_RETURN(0);
goto error;
}
-
+
dwFlags|= LOCKFILE_FAIL_IMMEDIATELY;
timeout_millis= timeout_sec * 1000;
/* Try lock in a loop, until the lock is acquired or timeout happens */
=== modified file 'sql/handler.cc'
--- a/sql/handler.cc 2008-10-30 21:49:14 +0000
+++ b/sql/handler.cc 2008-11-13 08:55:37 +0000
@@ -1113,7 +1113,7 @@ int ha_commit_trans(THD *thd, bool all)
uint rw_ha_count;
bool rw_trans;
- DBUG_EXECUTE_IF("crash_commit_before", abort(););
+ 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-07-09 07:12:43 +0000
+++ b/storage/myisam/mi_close.c 2008-11-13 08:55:37 +0000
@@ -30,6 +30,7 @@ int mi_close(register MI_INFO *info)
DBUG_PRINT("enter",("base: %p reopen: %u locks: %u",
info, (uint) share->reopen,
(uint) share->tot_locks));
+ DBUG_PRINT("myisam", ("close '%s'", share->unresolv_file_name));
pthread_mutex_lock(&THR_LOCK_myisam);
if (info->lock_type == F_EXTRA_LCK)
=== 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 2008-11-13 08:55:37 +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;
};
@@ -96,7 +103,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 +149,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 +162,7 @@ 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", mi_exl->max_files));
compile_time_assert((sizeof(mi_log_command_name) /
sizeof(mi_log_command_name[0]) ==
@@ -186,6 +194,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 +210,18 @@ 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.
+ */
+ if (command >= MI_LOG_END_SENTINEL)
+ {
+ my_errno= HA_ERR_WRONG_COMMAND;
+ 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,23 +247,64 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM
}
else
isamlog_process= file_info.process= result= 0;
+
+ DBUG_PRINT("myisamlog", ("command: %u '%s' process: %ld filenr: %d",
+ command, mi_log_command_name[command],
+ file_info.process, file_info.filenr));
+ /*
+ 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)))
{
+ DBUG_PRINT("myisamlog", ("found info: 0x%lx file: '%s' "
+ "used: %d closed: %d",
+ (long) curr_file_info, curr_file_info->name,
+ curr_file_info->used, curr_file_info->closed));
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)
+ {
+ 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,
+ DBUG_PRINT("info",("command: %u '%s' curr_file_info: 0x%lx used: %u",
+ command, mi_log_command_name[command],
+ (ulong)curr_file_info,
curr_file_info ? curr_file_info->used : 0));
/*
We update our statistic (how many commands issued, per command type),
@@ -255,13 +324,19 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM
}
switch ((enum myisam_log_commands) command) {
case MI_LOG_OPEN:
+ DBUG_PRINT("myisamlog", ("command MI_LOG_OPEN"));
if (curr_file_info)
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 memebers 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;
@@ -330,8 +405,19 @@ 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;
}
(void) tree_insert(&tree, (uchar*) &file_info, 0, tree.custom_arg);
+
+ /*
+ tree_insert() copied file_info. Avoid that the allocated members
+ are freed while in use.
+ */
+ file_info.name= NULL;
+ file_info.show_name= NULL;
+ file_info.record= NULL;
+
if (file_info.used)
{
if (mi_exl->verbose && !mi_exl->record_pos_file)
@@ -344,6 +430,7 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM
}
break;
case MI_LOG_CLOSE:
+ DBUG_PRINT("myisamlog", ("command MI_LOG_CLOSE"));
if (mi_exl->verbose && !mi_exl->record_pos_file &&
(!mi_exl->table_selection_hook ||
(curr_file_info && curr_file_info->used)))
@@ -358,6 +445,7 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM
}
break;
case MI_LOG_EXTRA:
+ DBUG_PRINT("myisamlog", ("command MI_LOG_EXTRA"));
length= big_numbers ? mi_uint4korr(head_ptr) : mi_uint2korr(head_ptr);
DBUG_ASSERT(length == 1);
if (my_b_read(&cache, head, length))
@@ -383,6 +471,7 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM
}
break;
case MI_LOG_DELETE:
+ DBUG_PRINT("myisamlog", ("command MI_LOG_DELETE"));
length= big_numbers ? mi_uint4korr(head_ptr) : mi_uint2korr(head_ptr);
DBUG_ASSERT(length == 8);
if (my_b_read(&cache, head, length))
@@ -426,6 +515,7 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM
break;
case MI_LOG_WRITE:
case MI_LOG_UPDATE:
+ DBUG_PRINT("myisamlog", ("command MI_LOG_WRITE or MI_LOG_UPDATE"));
if (big_numbers)
{
filepos= mi_sizekorr(head_ptr);
@@ -438,7 +528,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,9 +608,11 @@ 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:
+ DBUG_PRINT("myisamlog", ("command MI_LOG_WRITE_BYTES_MYI or MI_LOG_WRITE_BYTES_MYD"));
if (big_numbers)
{
filepos= mi_sizekorr(head_ptr);
@@ -534,7 +625,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,8 +655,10 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM
goto com_err;
}
my_free(buff,MYF(0));
+ buff= NULL;
break;
case MI_LOG_CHSIZE_MYI:
+ DBUG_PRINT("myisamlog", ("command MI_LOG_CHSIZE_MYI"));
/* here 'filepos' means new length of file */
if (big_numbers)
filepos= mi_sizekorr(head_ptr);
@@ -595,6 +687,7 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM
}
break;
case MI_LOG_LOCK:
+ DBUG_PRINT("myisamlog", ("command MI_LOG_LOCK"));
length= big_numbers ? mi_uint4korr(head_ptr) : mi_uint2korr(head_ptr);
DBUG_ASSERT(length == 4);
if (my_b_read(&cache, head, length))
@@ -607,14 +700,24 @@ 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;
+ if (!curr_file_info->closed)
+ {
+ DBUG_PRINT("myisamlog",
+ ("lock info: 0x%lx process: %ld filenr: %d file: '%s'",
+ (long) curr_file_info, curr_file_info->process,
+ curr_file_info->filenr, curr_file_info->name));
+ if (mi_lock_database(curr_file_info->isam,lock_command) !=
+ (int) result)
+ goto com_err;
+ }
}
break;
case MI_LOG_DELETE_ALL:
+ DBUG_PRINT("myisamlog", ("command MI_LOG_DELETE_ALL"));
if (mi_exl->verbose && !mi_exl->record_pos_file &&
(!mi_exl->table_selection_hook ||
(curr_file_info && curr_file_info->used)))
@@ -628,6 +731,7 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM
}
break;
default:
+ DBUG_PRINT("myisamlog", ("command default/illegal"));
fflush(stdout);
fprintf(stderr, "Error: found unknown command %d in logfile, aborted\n",
command);
@@ -635,6 +739,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);
@@ -645,22 +751,29 @@ int mi_examine_log(MI_EXAMINE_LOG_PARAM
err:
fflush(stdout);
+ DBUG_PRINT("myisamlog", ("err label"));
fprintf(stderr,"Got error %d when reading from logfile\n",my_errno);
fflush(stderr);
goto end;
com_err:
fflush(stdout);
+ DBUG_PRINT("myisamlog", ("com_err label"));
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);
}
@@ -742,6 +855,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);
@@ -765,6 +880,9 @@ static int close_some_file(TREE *tree)
(void*) &access_param,left_root_right);
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 +890,35 @@ 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>" */
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 process: %ld filenr: %d file: '%s'",
+ (long) fileinfo, fileinfo->process,
+ fileinfo->filenr, fileinfo->name));
+ (void) mi_lock_database(fileinfo->isam, fileinfo->lock_type);
+ }
+ 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-09-09 19:02:38 +0000
+++ b/storage/myisam/mi_locking.c 2008-11-13 08:55:37 +0000
@@ -104,7 +104,11 @@ int mi_lock_database(MI_INFO *info, int
mi_print_error(share, HA_ERR_CRASHED);
mi_mark_crashed(info);
}
- if (info->lock_type != F_EXTRA_LCK)
+ /*
+ If we have a pseudo lock (F_EXTRA_LCK) or a temporary table,
+ skip file locking.
+ */
+ if ((info->lock_type != F_EXTRA_LCK) && !share->temporary)
{
if (share->r_locks)
{ /* Only read locks left */
@@ -568,9 +572,11 @@ int _mi_decrement_open_count(MI_INFO *in
uchar buff[2];
register MYISAM_SHARE *share=info->s;
int lock_error=0,write_error=0;
+ DBUG_ENTER("_mi_decrement_open_count");
if (share->global_changed)
{
uint old_lock=info->lock_type;
+ DBUG_PRINT("myisam", ("updating open_count: %u", share->state.open_count));
share->global_changed=0;
lock_error=mi_lock_database(info,F_WRLCK);
/* Its not fatal even if we couldn't get the lock ! */
@@ -589,7 +595,7 @@ int _mi_decrement_open_count(MI_INFO *in
if (!lock_error)
lock_error=mi_lock_database(info,old_lock);
}
- return test(lock_error || write_error);
+ DBUG_RETURN(lock_error || write_error);
}
=== modified file 'storage/myisam/myisamlog.c'
--- a/storage/myisam/myisamlog.c 2008-07-09 07:12:43 +0000
+++ b/storage/myisam/myisamlog.c 2008-11-13 08:55:37 +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");