mirror of
				https://github.com/MariaDB/server.git
				synced 2025-11-04 04:46:15 +01:00 
			
		
		
		
	I spent 4 hours on work and 12 hours of testing to try to find the reason for aria crashing in recovery when starting a new test, in which case the 'data directory' should be a copy of "install.db", but aria_log.00000001 content was not correct. The following changes are mostly done to make it a bit easier to find out more in case of future similar crashes: - Mark last_checkpoint_lsn volatile (safety). - Write checkpoint message to aria_recovery.trace - When compling with DBUG and with HAVE_DBUG_TRANSLOG_SRC, use checksum's for Aria log pages. We cannot have it on by default for DBUG servers yet as there is bugs when changing CRC between restarts. - Added a message to mtr --verbose when copying the data directory. - Removed extra linefeed in Aria recovery message (cleanup)
		
			
				
	
	
		
			149 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			149 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* Copyright (C) 2006,2007,2008 MySQL AB
 | 
						|
 | 
						|
   This program is free software; you can redistribute it and/or modify
 | 
						|
   it under the terms of the GNU General Public License as published by
 | 
						|
   the Free Software Foundation; version 2 of the License.
 | 
						|
 | 
						|
   This program is distributed in the hope that it will be useful,
 | 
						|
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
   GNU General Public License for more details.
 | 
						|
 | 
						|
   You should have received a copy of the GNU General Public License
 | 
						|
   along with this program; if not, write to the Free Software
 | 
						|
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
 | 
						|
 | 
						|
/*
 | 
						|
  Q: Why isn't ma_recovery_util.c simply moved to ma_recovery.c ?
 | 
						|
 | 
						|
  A: ma_recovery.c, because it invokes objects from ma_check.c (like
 | 
						|
  maria_chk_init()) causes the following problem:
 | 
						|
  if a source file a.c of a program invokes a function defined in
 | 
						|
  ma_recovery.c, then a.o depends on ma_recovery.o which depends on
 | 
						|
  ma_check.o: linker thus brings in ma_check.o. That brings in the
 | 
						|
  dependencies of ma_check.o which are definitions of _ma_check_print_info()
 | 
						|
  etc; if a.o does not define them then the ones of ha_maria.o are used
 | 
						|
  i.e. ha_maria.o is linked into the program, and this brings in dependencies
 | 
						|
  of ha_maria.o on mysqld.o into the program's linking which thus fails, as
 | 
						|
  the program is not linked with mysqld.o.
 | 
						|
  Thus, while several functions defined in ma_recovery.c could be useful to
 | 
						|
  other files, they cannot be used by them.
 | 
						|
  So we are going to gradually move a great share of ma_recovery.c's exported
 | 
						|
  functions into the present file, to isolate the problematic components and
 | 
						|
  avoid the problem.
 | 
						|
*/
 | 
						|
 | 
						|
#include "maria_def.h"
 | 
						|
 | 
						|
HASH all_dirty_pages;
 | 
						|
struct st_dirty_page /* used only in the REDO phase */
 | 
						|
{
 | 
						|
  uint64 file_and_page_id;
 | 
						|
  LSN rec_lsn;
 | 
						|
};
 | 
						|
/*
 | 
						|
  LSN after which dirty pages list does not apply. Can be slightly before
 | 
						|
  when ma_checkpoint_execute() started.
 | 
						|
*/
 | 
						|
LSN checkpoint_start= LSN_IMPOSSIBLE;
 | 
						|
 | 
						|
/** @todo looks like duplicate of recovery_message_printed */
 | 
						|
my_bool procent_printed;
 | 
						|
FILE *tracef; /**< trace file for debugging */
 | 
						|
 | 
						|
ulong recovery_found_crashed_tables;
 | 
						|
uint skipped_lsn_err_count;
 | 
						|
 | 
						|
/** @brief Prints to a trace file if it is not NULL */
 | 
						|
void tprint(FILE *trace_file __attribute__ ((unused)),
 | 
						|
            const char *format __attribute__ ((unused)), ...)
 | 
						|
{
 | 
						|
  va_list args;
 | 
						|
#ifndef DBUG_OFF
 | 
						|
  {
 | 
						|
    char buff[1024];
 | 
						|
    size_t length;
 | 
						|
    va_start(args, format);
 | 
						|
    length= my_vsnprintf(buff, sizeof(buff)-1, format, args);
 | 
						|
    if (length && buff[length-1] == '\n')
 | 
						|
      buff[length-1]= 0;                      /* Don't print end \n */
 | 
						|
    DBUG_PRINT("info", ("%s", buff));
 | 
						|
    va_end(args);
 | 
						|
  }
 | 
						|
#endif
 | 
						|
  va_start(args, format);
 | 
						|
  if (trace_file != NULL)
 | 
						|
    vfprintf(trace_file, format, args);
 | 
						|
  va_end(args);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void eprint(FILE *trace_file __attribute__ ((unused)),
 | 
						|
            const char *format __attribute__ ((unused)), ...)
 | 
						|
{
 | 
						|
  va_list args;
 | 
						|
  va_start(args, format);
 | 
						|
  DBUG_PRINT("error", ("%s", format));
 | 
						|
  if (!trace_file)
 | 
						|
    trace_file= stderr;
 | 
						|
 | 
						|
  if (procent_printed && trace_file == stderr)
 | 
						|
  {
 | 
						|
    procent_printed= 0;
 | 
						|
    /* In silent mode, print on another line than the 0% 10% 20% line */
 | 
						|
    fputc('\n', stderr);
 | 
						|
    fflush(stderr);
 | 
						|
  }
 | 
						|
  vfprintf(trace_file , format, args);
 | 
						|
  fputc('\n', trace_file);
 | 
						|
  if (trace_file != stderr)
 | 
						|
  {
 | 
						|
    va_start(args, format);
 | 
						|
    my_printv_error(HA_ERR_INITIALIZATION, format, MYF(0), args);
 | 
						|
  }
 | 
						|
  va_end(args);
 | 
						|
  fflush(trace_file);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
   Tells if the dirty pages list found in checkpoint record allows to ignore a
 | 
						|
   REDO for a certain page.
 | 
						|
 | 
						|
   @param  shortid         short id of the table
 | 
						|
   @param  lsn             REDO record's LSN
 | 
						|
   @param  page            page number
 | 
						|
   @param  index           TRUE if index page, FALSE if data page
 | 
						|
*/
 | 
						|
 | 
						|
my_bool _ma_redo_not_needed_for_page(uint16 shortid, LSN lsn,
 | 
						|
                                     pgcache_page_no_t page,
 | 
						|
                                     my_bool index)
 | 
						|
{
 | 
						|
  if (cmp_translog_addr(lsn, checkpoint_start) < 0)
 | 
						|
  {
 | 
						|
    /*
 | 
						|
      64-bit key is formed like this:
 | 
						|
      Most significant byte: 0 if data page, 1 if index page
 | 
						|
      Next 2 bytes: table's short id
 | 
						|
      Next 5 bytes: page number
 | 
						|
    */
 | 
						|
    char llbuf[22];
 | 
						|
    uint64 file_and_page_id=
 | 
						|
      (((uint64)((index << 16) | shortid)) << 40) | page;
 | 
						|
    struct st_dirty_page *dirty_page= (struct st_dirty_page *)
 | 
						|
      my_hash_search(&all_dirty_pages,
 | 
						|
                  (uchar *)&file_and_page_id, sizeof(file_and_page_id));
 | 
						|
    DBUG_PRINT("info", ("page %lld in dirty pages list: %d",
 | 
						|
                        (ulonglong) page,
 | 
						|
                        dirty_page != NULL));
 | 
						|
    if ((dirty_page == NULL) ||
 | 
						|
        cmp_translog_addr(lsn, dirty_page->rec_lsn) < 0)
 | 
						|
    {
 | 
						|
      tprint(tracef, ", ignoring page %s because of dirty_pages list\n",
 | 
						|
             llstr((ulonglong) page, llbuf));
 | 
						|
      return TRUE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return FALSE;
 | 
						|
}
 |