diff options
Diffstat (limited to 'storage/maria/ma_recovery_util.c')
-rw-r--r-- | storage/maria/ma_recovery_util.c | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/storage/maria/ma_recovery_util.c b/storage/maria/ma_recovery_util.c new file mode 100644 index 00000000..fe43d812 --- /dev/null +++ b/storage/maria/ma_recovery_util.c @@ -0,0 +1,149 @@ +/* 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) + { + 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; +} |