Commit 40ec012c authored by Sergey Vojtovich's avatar Sergey Vojtovich

Backport from 6.0-codebase.

WL#3951 - MyISAM: Additional Error Logs for Data Corruption

When table corruption is detected, in addition to current error message
provide following information:
- list of threads (and queries) accessing a table;
- thread_id of a thread that detected corruption;
- source file name and line number where this corruption was detected;
- optional extra information (string).

mysql-test/r/myisam_crash_before_flush_keys.result:
  Adjusted a test case according to WL#3951.
mysql-test/t/myisam_crash_before_flush_keys.test:
  Adjusted a test case according to WL#3951.
storage/myisam/CMakeLists.txt:
  Added mi_extrafunc.h to myisam sources list.
storage/myisam/Makefile.am:
  Added mi_extrafunc.h to myisam headers list.
storage/myisam/ha_myisam.cc:
  Added _mi_report_crashed() function (reports additional information
  whenever table corruption is detected).
storage/myisam/mi_extrafunc.h:
  All standalone programs must define their version of _mi_report_crashed()
  by including mi_extrafunc.h.
storage/myisam/mi_locking.c:
  For every call to mi_lock_database(F_[RD|WR|EXTRA_]LCK) - add
  current thread to the list of threads accessing this table.
  
  For every call to mi_lock_database(F_UNLCK) - remove current
  thread from the list of threads accessing this table.
storage/myisam/mi_test1.c:
  All standalone programs must define their version of _mi_report_crashed()
  by including mi_extrafunc.h.
storage/myisam/mi_test2.c:
  All standalone programs must define their version of _mi_report_crashed()
  by including mi_extrafunc.h.
storage/myisam/mi_test3.c:
  All standalone programs must define their version of _mi_report_crashed()
  by including mi_extrafunc.h.
storage/myisam/myisam_ftdump.c:
  All standalone programs must define their version of _mi_report_crashed()
  by including mi_extrafunc.h.
storage/myisam/myisamchk.c:
  All standalone programs must define their version of _mi_report_crashed()
  by including mi_extrafunc.h.
storage/myisam/myisamdef.h:
  Extra elements are added to MI_INFO and MYISAM_SHARE structures.
  MI_INFO is extended with LIST element, that holds a pointer to
  THD object accessing a table. MYISAM_SHARE is extended with LIST
  (list of threads accessing a table).
  
  Whenever table is marked as crashed, call mi_report_crashed() macro
  to provide useful information.
storage/myisam/myisamlog.c:
  All standalone programs must define their version of _mi_report_crashed()
  by including mi_extrafunc.h.
storage/myisam/myisampack.c:
  All standalone programs must define their version of _mi_report_crashed()
  by including mi_extrafunc.h.
storage/myisam/rt_test.c:
  All standalone programs must define their version of _mi_report_crashed()
  by including mi_extrafunc.h.
storage/myisam/sp_test.c:
  All standalone programs must define their version of _mi_report_crashed()
  by including mi_extrafunc.h.
storage/myisammrg/ha_myisammrg.cc:
  For each unedrlying table initialize `in_use' variable.
parent 23159440
......@@ -3,6 +3,8 @@
#
# Don't test this under valgrind, memory leaks will occur
# Binary must be compiled with debug for crash to occur
call mtr.add_suppression("Got an error from thread_id=.*ha_myisam.cc:");
call mtr.add_suppression("MySQL thread id .*, query id .* localhost.*root Checking table");
SET GLOBAL delay_key_write=ALL;
CREATE TABLE t1(a INT,
b INT,
......
......@@ -8,6 +8,9 @@
--echo # Binary must be compiled with debug for crash to occur
--source include/have_debug.inc
call mtr.add_suppression("Got an error from thread_id=.*ha_myisam.cc:");
call mtr.add_suppression("MySQL thread id .*, query id .* localhost.*root Checking table");
let $MYSQLD_DATADIR= `select @@datadir`;
SET GLOBAL delay_key_write=ALL;
CREATE TABLE t1(a INT,
......
......@@ -26,7 +26,8 @@ SET(MYISAM_SOURCES ft_boolean_search.c ft_nlq_search.c ft_parser.c ft_static.c
mi_rfirst.c mi_rlast.c mi_rnext.c mi_rnext_same.c mi_rprev.c mi_rrnd.c
mi_rsame.c mi_rsamepos.c mi_scan.c mi_search.c mi_static.c mi_statrec.c
mi_unique.c mi_update.c mi_write.c rt_index.c rt_key.c rt_mbr.c
rt_split.c sort.c sp_key.c ft_eval.h myisamdef.h rt_index.h mi_rkey.c)
rt_split.c sort.c sp_key.c ft_eval.h mi_extrafunc.h myisamdef.h
rt_index.h mi_rkey.c)
MYSQL_STORAGE_ENGINE(MYISAM)
......
......@@ -50,7 +50,7 @@ myisampack_LDADD= @CLIENT_EXTRA_LDFLAGS@ libmyisam.a \
noinst_PROGRAMS = mi_test1 mi_test2 mi_test3 rt_test sp_test #ft_test1 ft_eval
noinst_HEADERS = myisamdef.h rt_index.h rt_key.h rt_mbr.h sp_defs.h \
fulltext.h ftdefs.h ft_test1.h ft_eval.h \
ha_myisam.h
ha_myisam.h mi_extrafunc.h
mi_test1_DEPENDENCIES= $(LIBRARIES)
mi_test1_LDADD= @CLIENT_EXTRA_LDFLAGS@ libmyisam.a \
$(top_builddir)/mysys/libmysys.a \
......
......@@ -539,6 +539,45 @@ void mi_check_print_warning(MI_CHECK *param, const char *fmt,...)
va_end(args);
}
/**
Report list of threads (and queries) accessing a table, thread_id of a
thread that detected corruption, ource file name and line number where
this corruption was detected, optional extra information (string).
This function is intended to be used when table corruption is detected.
@param[in] file MI_INFO object.
@param[in] message Optional error message.
@param[in] sfile Name of source file.
@param[in] sline Line number in source file.
@return void
*/
void _mi_report_crashed(MI_INFO *file, const char *message,
const char *sfile, uint sline)
{
THD *cur_thd;
LIST *element;
char buf[1024];
pthread_mutex_lock(&file->s->intern_lock);
if ((cur_thd= (THD*) file->in_use.data))
sql_print_error("Got an error from thread_id=%lu, %s:%d", cur_thd->thread_id,
sfile, sline);
else
sql_print_error("Got an error from unknown thread, %s:%d", sfile, sline);
if (message)
sql_print_error("%s", message);
for (element= file->s->in_use; element; element= list_rest(element))
{
THD *thd= (THD*) element->data;
sql_print_error("%s", thd ? thd_security_context(thd, buf, sizeof(buf), 0)
: "Unknown thread accessing table");
}
pthread_mutex_unlock(&file->s->intern_lock);
}
}
......@@ -1894,6 +1933,7 @@ int ha_myisam::delete_table(const char *name)
int ha_myisam::external_lock(THD *thd, int lock_type)
{
file->in_use.data= thd;
return mi_lock_database(file, !table->s->tmp_table ?
lock_type : ((lock_type == F_UNLCK) ?
F_UNLCK : F_EXTRA_LCK));
......
/* Copyright (C) 2000-2006 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
void _mi_report_crashed(MI_INFO *file __attribute__((unused)),
const char *message __attribute__((unused)),
const char *sfile __attribute__((unused)),
uint sline __attribute__((unused)))
{
}
......@@ -45,6 +45,7 @@ int mi_lock_database(MI_INFO *info, int lock_type)
++share->w_locks;
++share->tot_locks;
info->lock_type= lock_type;
info->s->in_use= list_add(info->s->in_use, &info->in_use);
DBUG_RETURN(0);
}
......@@ -136,6 +137,7 @@ int mi_lock_database(MI_INFO *info, int lock_type)
}
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
info->lock_type= F_UNLCK;
info->s->in_use= list_delete(info->s->in_use, &info->in_use);
break;
case F_RDLCK:
if (info->lock_type == F_WRLCK)
......@@ -182,6 +184,7 @@ int mi_lock_database(MI_INFO *info, int lock_type)
share->r_locks++;
share->tot_locks++;
info->lock_type=lock_type;
info->s->in_use= list_add(info->s->in_use, &info->in_use);
break;
case F_WRLCK:
if (info->lock_type == F_RDLCK)
......@@ -231,6 +234,7 @@ int mi_lock_database(MI_INFO *info, int lock_type)
info->invalidator=info->s->invalidator;
share->w_locks++;
share->tot_locks++;
info->s->in_use= list_add(info->s->in_use, &info->in_use);
break;
default:
break; /* Impossible */
......
......@@ -679,3 +679,5 @@ static void usage()
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
#include "mi_extrafunc.h"
......@@ -1055,3 +1055,5 @@ static void copy_key(MI_INFO *info,uint inx,uchar *rec,uchar *key_buff)
}
return;
}
#include "mi_extrafunc.h"
......@@ -488,6 +488,8 @@ int test_update(MI_INFO *file,int id,int lock_type)
return 0;
}
#include "mi_extrafunc.h"
#else /* __NETWARE__ */
#include <stdio.h>
......
......@@ -274,3 +274,5 @@ static void complain(int val) /* Kinda assert :-) */
exit(1);
}
}
#include "mi_extrafunc.h"
......@@ -1815,3 +1815,5 @@ void mi_check_print_error(MI_CHECK *param, const char *fmt,...)
va_end(args);
DBUG_VOID_RETURN;
}
#include "mi_extrafunc.h"
......@@ -165,6 +165,7 @@ typedef struct st_mi_isam_share { /* Shared between opens */
MI_COLUMNDEF *rec; /* Pointer to field information */
MI_PACK pack; /* Data about packed records */
MI_BLOB *blobs; /* Pointer to blobs */
LIST *in_use; /* List of threads using this table */
char *unique_file_name; /* realpath() of index file */
char *data_file_name, /* Resolved path names from symlinks */
*index_file_name;
......@@ -242,6 +243,7 @@ struct st_myisam_info {
DYNAMIC_ARRAY *ft1_to_ft2; /* used only in ft1->ft2 conversion */
MEM_ROOT ft_memroot; /* used by the parser */
MYSQL_FTPARSER_PARAM *ftparser_param; /* share info between init/deinit */
LIST in_use; /* Thread using this table */
char *filename; /* parameter to open filename */
uchar *buff, /* Temp area for key */
*lastkey,*lastkey2; /* Last used search key */
......@@ -385,8 +387,10 @@ typedef struct st_mi_sort_param
#define mi_putint(x,y,nod) { uint16 boh=(nod ? (uint16) 32768 : 0) + (uint16) (y);\
mi_int2store(x,boh); }
#define mi_test_if_nod(x) (x[0] & 128 ? info->s->base.key_reflength : 0)
#define mi_report_crashed(A, B) _mi_report_crashed((A), (B), __FILE__, __LINE__)
#define mi_mark_crashed(x) do{(x)->s->state.changed|= STATE_CRASHED; \
DBUG_PRINT("error", ("Marked table crashed")); \
mi_report_crashed((x), 0); \
}while(0)
#define mi_mark_crashed_on_repair(x) do{(x)->s->state.changed|= \
STATE_CRASHED|STATE_CRASHED_ON_REPAIR; \
......@@ -764,6 +768,8 @@ int mi_open_keyfile(MYISAM_SHARE *share);
void mi_setup_functions(register MYISAM_SHARE *share);
my_bool mi_dynmap_file(MI_INFO *info, my_off_t size);
void mi_remap_file(MI_INFO *info, my_off_t size);
void _mi_report_crashed(MI_INFO *file, const char *message,
const char *sfile, uint sline);
/* Functions needed by mi_check */
volatile int *killed_ptr(MI_CHECK *param);
......
......@@ -845,3 +845,5 @@ static my_bool cmp_filename(struct file_info *file_info, char * name)
return 1;
return strcmp(file_info->name,name) ? 1 : 0;
}
#include "mi_extrafunc.h"
......@@ -3201,4 +3201,4 @@ static int fakecmp(my_off_t **count1, my_off_t **count2)
}
#endif
#include "mi_extrafunc.h"
......@@ -468,3 +468,5 @@ int main(int argc __attribute__((unused)),char *argv[] __attribute__((unused)))
exit(0);
}
#endif /*HAVE_RTREE_KEYS*/
#include "mi_extrafunc.h"
......@@ -562,3 +562,4 @@ int main(int argc __attribute__((unused)),char *argv[] __attribute__((unused)))
}
#endif /*HAVE_SPATIAL*/
#include "mi_extrafunc.h"
......@@ -1009,7 +1009,10 @@ int ha_myisammrg::extra_opt(enum ha_extra_function operation, ulong cache_size)
int ha_myisammrg::external_lock(THD *thd, int lock_type)
{
MYRG_TABLE *tmp;
DBUG_ASSERT(this->file->children_attached);
for (tmp= file->open_tables; tmp != file->end_table; tmp++)
tmp->table->in_use.data= thd;
return myrg_lock_database(file,lock_type);
}
......
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