Commit 2d327efd authored by unknown's avatar unknown

Fixing the little bug that if a new version reads an old control file,

it couldn't entirely write its new information (it could not write
more bytes than the old format wrote).


storage/maria/ma_control_file.c:
  Let ma_control_file_write_and_force() return error if called when
  file is not open.
  When the file was of an old version (no room for our changeable part)
  we upgrade this part. When the file was of a new version we re-use its
  format but zero the parts which we can't maintain.
storage/maria/ma_init.c:
  ma_control_file_write_and_force() now does not assert if called
  when control file is not open.
storage/maria/ma_recovery.c:
  missing ";" (thanks Peter Zaitsev for the bug report and Monty for the patch)
parent 722a8ebe
...@@ -117,7 +117,7 @@ my_bool maria_multi_threaded= FALSE; ...@@ -117,7 +117,7 @@ my_bool maria_multi_threaded= FALSE;
/** @brief if currently doing a recovery */ /** @brief if currently doing a recovery */
my_bool maria_in_recovery= FALSE; my_bool maria_in_recovery= FALSE;
/* /**
Control file is less then 512 bytes (a disk sector), Control file is less then 512 bytes (a disk sector),
to be as atomic as possible to be as atomic as possible
*/ */
...@@ -463,7 +463,14 @@ int ma_control_file_write_and_force(LSN checkpoint_lsn, uint32 logno, ...@@ -463,7 +463,14 @@ int ma_control_file_write_and_force(LSN checkpoint_lsn, uint32 logno,
uint32 sum; uint32 sum;
DBUG_ENTER("ma_control_file_write_and_force"); DBUG_ENTER("ma_control_file_write_and_force");
DBUG_ASSERT(control_file_fd >= 0); /* must be open */ if ((last_checkpoint_lsn == checkpoint_lsn) &&
(last_logno == logno) &&
(max_trid_in_control_file == trid))
DBUG_RETURN(0); /* no need to write */
if (control_file_fd < 0)
DBUG_RETURN(1);
#ifndef DBUG_OFF #ifndef DBUG_OFF
if (maria_multi_threaded) if (maria_multi_threaded)
translog_lock_handler_assert_owner(); translog_lock_handler_assert_owner();
...@@ -473,14 +480,22 @@ int ma_control_file_write_and_force(LSN checkpoint_lsn, uint32 logno, ...@@ -473,14 +480,22 @@ int ma_control_file_write_and_force(LSN checkpoint_lsn, uint32 logno,
int4store(buffer + CF_FILENO_OFFSET, logno); int4store(buffer + CF_FILENO_OFFSET, logno);
transid_store(buffer + CF_MAX_TRID_OFFSET, trid); transid_store(buffer + CF_MAX_TRID_OFFSET, trid);
if (cf_changeable_size > CF_CHANGEABLE_TOTAL_SIZE)
{
/* /*
Clear unknown part of changeable part, if bigger than ours. More room than needed for us. Must be a newer version. Clear part which
Other option would be to remember the original values in the file we cannot maintain, so that any future version notices we didn't
and copy them here, but this should be safer. maintain its extra data.
*/ */
if (cf_changeable_size > CF_CHANGEABLE_TOTAL_SIZE)
bzero(buffer + CF_CHANGEABLE_TOTAL_SIZE, bzero(buffer + CF_CHANGEABLE_TOTAL_SIZE,
cf_changeable_size - CF_CHANGEABLE_TOTAL_SIZE); cf_changeable_size - CF_CHANGEABLE_TOTAL_SIZE);
}
else
{
/* not enough room for what we need to store: enlarge */
cf_changeable_size= CF_CHANGEABLE_TOTAL_SIZE;
}
/* Note that the create-time portion is not touched */
/* Checksum is stored first */ /* Checksum is stored first */
compile_time_assert(CF_CHECKSUM_OFFSET == 0); compile_time_assert(CF_CHECKSUM_OFFSET == 0);
...@@ -488,11 +503,6 @@ int ma_control_file_write_and_force(LSN checkpoint_lsn, uint32 logno, ...@@ -488,11 +503,6 @@ int ma_control_file_write_and_force(LSN checkpoint_lsn, uint32 logno,
cf_changeable_size - CF_CHECKSUM_SIZE); cf_changeable_size - CF_CHECKSUM_SIZE);
int4store(buffer, sum); int4store(buffer, sum);
/**
@todo BUG by reusing the cf_changeable_size of the old control file (from
an old server), it does not write the new parts featured by the running
server (like max_trid), is it expected?
*/
if (my_pwrite(control_file_fd, buffer, cf_changeable_size, if (my_pwrite(control_file_fd, buffer, cf_changeable_size,
cf_create_time_size, MYF(MY_FNABP | MY_WME)) || cf_create_time_size, MYF(MY_FNABP | MY_WME)) ||
my_sync(control_file_fd, MYF(MY_WME))) my_sync(control_file_fd, MYF(MY_WME)))
......
...@@ -56,15 +56,15 @@ void maria_end(void) ...@@ -56,15 +56,15 @@ void maria_end(void)
maria_inited= maria_multi_threaded= FALSE; maria_inited= maria_multi_threaded= FALSE;
ft_free_stopwords(); ft_free_stopwords();
ma_checkpoint_end(); ma_checkpoint_end();
if (ma_control_file_inited() && if ((trid= trnman_get_max_trid()) > max_trid_in_control_file)
((trid= trnman_get_max_trid()) > max_trid_in_control_file))
{ {
/* /*
Store max transaction id into control file, in case logs are removed Store max transaction id into control file, in case logs are removed
by user, or maria_chk wants to check tables (it cannot access max trid by user, or maria_chk wants to check tables (it cannot access max trid
from the log, as it cannot process REDOs). from the log, as it cannot process REDOs).
*/ */
ma_control_file_write_and_force(last_checkpoint_lsn, last_logno, trid); (void)ma_control_file_write_and_force(last_checkpoint_lsn, last_logno,
trid);
} }
trnman_destroy(); trnman_destroy();
if (translog_status == TRANSLOG_OK) if (translog_status == TRANSLOG_OK)
......
...@@ -3089,6 +3089,7 @@ static int close_all_tables(void) ...@@ -3089,6 +3089,7 @@ static int close_all_tables(void)
print_preamble(); print_preamble();
for (count= 0, list_element= maria_open_list ; for (count= 0, list_element= maria_open_list ;
list_element ; count++, (list_element= list_element->next)) list_element ; count++, (list_element= list_element->next))
;
fprintf(stderr, "tables to flush:"); fprintf(stderr, "tables to flush:");
recovery_message_printed= REC_MSG_FLUSH; recovery_message_printed= REC_MSG_FLUSH;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment