Commit 3fca2390 authored by Michael Widenius's avatar Michael Widenius

Log queries to maria_log if compiled with EXTRA_DEBUG

Added DBUG_ASSERT() to unlikely error senario
Don't use errno == 0 in maria_create() / myisam_create()

sql/sql_insert.cc:
  Added DBUG_ASSERT() for case that should never happen in real life
  Added my_error() to avoid assert if mysql_lock() or postlock() doesn't call my_error()
storage/maria/ha_maria.cc:
  Log queries to maria_log if compiled with EXTRA_DEBUG
storage/maria/ma_create.c:
  Don't use errno == 0
storage/maria/ma_loghandler.c:
  Added logging of debug info to maria_log
storage/maria/ma_loghandler.h:
  Added logging of debug info to maria_log
storage/maria/ma_recovery.c:
  Added printing of debug info from maria_log
storage/maria/trnman.c:
  Added functions to read/store state in TRN
storage/maria/trnman.h:
  Added functions to read/store state in TRN
storage/maria/trnman_public.h:
  Added state in TRN to remmeber if we have already logged the query
storage/myisam/mi_create.c:
  Don't use errno == 0
parent a955efc4
...@@ -3493,6 +3493,9 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, ...@@ -3493,6 +3493,9 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
MYSQL_LOCK_IGNORE_FLUSH, &not_used)) || MYSQL_LOCK_IGNORE_FLUSH, &not_used)) ||
hooks->postlock(&table, 1)) hooks->postlock(&table, 1))
{ {
DBUG_ASSERT(0); // This should never happen
/* purecov: begin tested */
my_error(ER_CANT_LOCK, MYF(0), my_errno);
if (*lock) if (*lock)
{ {
mysql_unlock_tables(thd, *lock); mysql_unlock_tables(thd, *lock);
...@@ -3502,6 +3505,7 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, ...@@ -3502,6 +3505,7 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
if (!create_info->table_existed) if (!create_info->table_existed)
drop_open_table(thd, table, create_table->db, create_table->table_name); drop_open_table(thd, table, create_table->db, create_table->table_name);
DBUG_RETURN(0); DBUG_RETURN(0);
/* purecov: end */
} }
DBUG_RETURN(table); DBUG_RETURN(table);
} }
......
...@@ -2261,6 +2261,9 @@ int ha_maria::extra_opt(enum ha_extra_function operation, ulong cache_size) ...@@ -2261,6 +2261,9 @@ int ha_maria::extra_opt(enum ha_extra_function operation, ulong cache_size)
int ha_maria::delete_all_rows() int ha_maria::delete_all_rows()
{ {
THD *thd= current_thd;
(void) translog_log_debug_info(file->trn, LOGREC_DEBUG_INFO_QUERY,
(uchar*) thd->query, thd->query_length);
if (file->s->now_transactional && if (file->s->now_transactional &&
((table->in_use->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) || ((table->in_use->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) ||
table->in_use->locked_tables)) table->in_use->locked_tables))
...@@ -2277,6 +2280,9 @@ int ha_maria::delete_all_rows() ...@@ -2277,6 +2280,9 @@ int ha_maria::delete_all_rows()
int ha_maria::delete_table(const char *name) int ha_maria::delete_table(const char *name)
{ {
THD *thd= current_thd;
(void) translog_log_debug_info(0, LOGREC_DEBUG_INFO_QUERY,
(uchar*) thd->query, thd->query_length);
return maria_delete_table(name); return maria_delete_table(name);
} }
...@@ -2350,6 +2356,16 @@ int ha_maria::external_lock(THD *thd, int lock_type) ...@@ -2350,6 +2356,16 @@ int ha_maria::external_lock(THD *thd, int lock_type)
DBUG_PRINT("info", ("Disabling logging for table")); DBUG_PRINT("info", ("Disabling logging for table"));
_ma_tmp_disable_logging_for_table(file, TRUE); _ma_tmp_disable_logging_for_table(file, TRUE);
} }
#ifdef EXTRA_DEBUG
if (lock_type == F_WRLCK &&
! (trnman_get_state(trn) & TRN_STATE_INFO_LOGGED))
{
trnman_set_state(trn, trnman_get_state(trn) | TRN_STATE_INFO_LOGGED |
TRN_STATE_TABLES_CAN_CHANGE);
(void) translog_log_debug_info(trn, LOGREC_DEBUG_INFO_QUERY,
(uchar*) thd->query, thd->query_length);
}
#endif
} }
else else
{ {
...@@ -2374,9 +2390,10 @@ int ha_maria::external_lock(THD *thd, int lock_type) ...@@ -2374,9 +2390,10 @@ int ha_maria::external_lock(THD *thd, int lock_type)
external lock of the table external lock of the table
*/ */
file->state= &file->s->state.state; file->state= &file->s->state.state;
if (trn && trnman_has_locked_tables(trn)) if (trn)
{ {
if (!trnman_decrement_locked_tables(trn)) if (trnman_has_locked_tables(trn) &&
!trnman_decrement_locked_tables(trn))
{ {
/* /*
OK should not have been sent to client yet (ACID). OK should not have been sent to client yet (ACID).
...@@ -2399,6 +2416,7 @@ int ha_maria::external_lock(THD *thd, int lock_type) ...@@ -2399,6 +2416,7 @@ int ha_maria::external_lock(THD *thd, int lock_type)
} }
#endif #endif
} }
trnman_set_state(trn, trnman_get_state(trn) & ~ TRN_STATE_INFO_LOGGED);
} }
} }
} /* if transactional table */ } /* if transactional table */
...@@ -2433,6 +2451,16 @@ int ha_maria::start_stmt(THD *thd, thr_lock_type lock_type) ...@@ -2433,6 +2451,16 @@ int ha_maria::start_stmt(THD *thd, thr_lock_type lock_type)
call to start_stmt(). call to start_stmt().
*/ */
trnman_new_statement(trn); trnman_new_statement(trn);
#ifdef EXTRA_DEBUG
if (!(trnman_get_state(trn) & TRN_STATE_INFO_LOGGED) &&
trnman_get_state(trn) & TRN_STATE_TABLES_CAN_CHANGE)
{
trnman_set_state(trn, trnman_get_state(trn) | TRN_STATE_INFO_LOGGED);
(void) translog_log_debug_info(trn, LOGREC_DEBUG_INFO_QUERY,
(uchar*) thd->query, thd->query_length);
}
#endif
} }
return 0; return 0;
} }
...@@ -2645,6 +2673,7 @@ int ha_maria::create(const char *name, register TABLE *table_arg, ...@@ -2645,6 +2673,7 @@ int ha_maria::create(const char *name, register TABLE *table_arg,
TABLE_SHARE *share= table_arg->s; TABLE_SHARE *share= table_arg->s;
uint options= share->db_options_in_use; uint options= share->db_options_in_use;
enum data_file_type row_type; enum data_file_type row_type;
THD *thd= current_thd;
DBUG_ENTER("ha_maria::create"); DBUG_ENTER("ha_maria::create");
for (i= 0; i < share->keys; i++) for (i= 0; i < share->keys; i++)
...@@ -2709,6 +2738,9 @@ int ha_maria::create(const char *name, register TABLE *table_arg, ...@@ -2709,6 +2738,9 @@ int ha_maria::create(const char *name, register TABLE *table_arg,
ha_create_info->page_checksum == HA_CHOICE_YES) ha_create_info->page_checksum == HA_CHOICE_YES)
create_flags|= HA_CREATE_PAGE_CHECKSUM; create_flags|= HA_CREATE_PAGE_CHECKSUM;
(void) translog_log_debug_info(0, LOGREC_DEBUG_INFO_QUERY,
(uchar*) thd->query, thd->query_length);
/* TODO: Check that the following fn_format is really needed */ /* TODO: Check that the following fn_format is really needed */
error= error=
maria_create(fn_format(buff, name, "", "", maria_create(fn_format(buff, name, "", "",
...@@ -2725,6 +2757,9 @@ int ha_maria::create(const char *name, register TABLE *table_arg, ...@@ -2725,6 +2757,9 @@ int ha_maria::create(const char *name, register TABLE *table_arg,
int ha_maria::rename_table(const char *from, const char *to) int ha_maria::rename_table(const char *from, const char *to)
{ {
THD *thd= current_thd;
(void) translog_log_debug_info(0, LOGREC_DEBUG_INFO_QUERY,
(uchar*) thd->query, thd->query_length);
return maria_rename(from, to); return maria_rename(from, to);
} }
...@@ -2869,6 +2904,8 @@ static int maria_commit(handlerton *hton __attribute__ ((unused)), ...@@ -2869,6 +2904,8 @@ static int maria_commit(handlerton *hton __attribute__ ((unused)),
TRN *trn= THD_TRN; TRN *trn= THD_TRN;
DBUG_ENTER("maria_commit"); DBUG_ENTER("maria_commit");
trnman_reset_locked_tables(trn, 0); trnman_reset_locked_tables(trn, 0);
trnman_set_state(trn, trnman_get_state(trn) & ~TRN_STATE_INFO_LOGGED);
/* statement or transaction ? */ /* statement or transaction ? */
if ((thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && !all) if ((thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && !all)
DBUG_RETURN(0); // end of statement DBUG_RETURN(0); // end of statement
......
...@@ -652,7 +652,8 @@ int maria_create(const char *name, enum data_file_type datafile_type, ...@@ -652,7 +652,8 @@ int maria_create(const char *name, enum data_file_type datafile_type,
/* There are only 16 bits for the total header length. */ /* There are only 16 bits for the total header length. */
if (info_length > 65535) if (info_length > 65535)
{ {
my_printf_error(0, "Maria table '%s' has too many columns and/or " my_printf_error(HA_WRONG_CREATE_OPTION,
"Maria table '%s' has too many columns and/or "
"indexes and/or unique constraints.", "indexes and/or unique constraints.",
MYF(0), name + dirname_length(name)); MYF(0), name + dirname_length(name));
my_errno= HA_WRONG_CREATE_OPTION; my_errno= HA_WRONG_CREATE_OPTION;
......
...@@ -685,6 +685,10 @@ static LOG_DESC INIT_LOGREC_IMPORTED_TABLE= ...@@ -685,6 +685,10 @@ static LOG_DESC INIT_LOGREC_IMPORTED_TABLE=
{LOGRECTYPE_VARIABLE_LENGTH, 0, 0, NULL, NULL, NULL, 0, {LOGRECTYPE_VARIABLE_LENGTH, 0, 0, NULL, NULL, NULL, 0,
"imported_table", LOGREC_IS_GROUP_ITSELF, NULL, NULL}; "imported_table", LOGREC_IS_GROUP_ITSELF, NULL, NULL};
static LOG_DESC INIT_LOGREC_DEBUG_INFO=
{LOGRECTYPE_VARIABLE_LENGTH, 0, 0, NULL, NULL, NULL, 0,
"info", LOGREC_IS_GROUP_ITSELF, NULL, NULL};
const myf log_write_flags= MY_WME | MY_NABP | MY_WAIT_IF_FULL; const myf log_write_flags= MY_WME | MY_NABP | MY_WAIT_IF_FULL;
void translog_table_init() void translog_table_init()
...@@ -774,6 +778,9 @@ void translog_table_init() ...@@ -774,6 +778,9 @@ void translog_table_init()
INIT_LOGREC_REDO_BITMAP_NEW_PAGE; INIT_LOGREC_REDO_BITMAP_NEW_PAGE;
log_record_type_descriptor[LOGREC_IMPORTED_TABLE]= log_record_type_descriptor[LOGREC_IMPORTED_TABLE]=
INIT_LOGREC_IMPORTED_TABLE; INIT_LOGREC_IMPORTED_TABLE;
log_record_type_descriptor[LOGREC_DEBUG_INFO]=
INIT_LOGREC_DEBUG_INFO;
for (i= LOGREC_FIRST_FREE; i < LOGREC_NUMBER_OF_TYPES; i++) for (i= LOGREC_FIRST_FREE; i < LOGREC_NUMBER_OF_TYPES; i++)
log_record_type_descriptor[i].rclass= LOGRECTYPE_NOT_ALLOWED; log_record_type_descriptor[i].rclass= LOGRECTYPE_NOT_ALLOWED;
#ifndef DBUG_OFF #ifndef DBUG_OFF
...@@ -8299,6 +8306,43 @@ void translog_set_file_size(uint32 size) ...@@ -8299,6 +8306,43 @@ void translog_set_file_size(uint32 size)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
/**
Write debug information to log if we EXTRA_DEBUG is enabled
*/
my_bool translog_log_debug_info(TRN *trn, enum translog_debug_info_type type,
uchar *info, size_t length)
{
#ifdef EXTRA_DEBUG
LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 2];
uchar debug_type;
LSN lsn;
if (!trn)
{
/*
We can't log the current transaction because we don't have
an active transaction. Use a temporary transaction object instead
*/
trn= &dummy_transaction_object;
}
debug_type= (uchar) type;
log_array[TRANSLOG_INTERNAL_PARTS + 0].str= &debug_type;
log_array[TRANSLOG_INTERNAL_PARTS + 0].length= 1;
log_array[TRANSLOG_INTERNAL_PARTS + 1].str= info;
log_array[TRANSLOG_INTERNAL_PARTS + 1].length= length;
return translog_write_record(&lsn, LOGREC_DEBUG_INFO,
trn, NULL,
(translog_size_t) (1+ length),
sizeof(log_array)/sizeof(log_array[0]),
log_array, NULL, NULL);
#else
return 0;
#endif
}
#ifdef MARIA_DUMP_LOG #ifdef MARIA_DUMP_LOG
#include <my_getopt.h> #include <my_getopt.h>
extern void translog_example_table_init(); extern void translog_example_table_init();
......
...@@ -144,6 +144,7 @@ enum translog_record_type ...@@ -144,6 +144,7 @@ enum translog_record_type
LOGREC_UNDO_BULK_INSERT, LOGREC_UNDO_BULK_INSERT,
LOGREC_REDO_BITMAP_NEW_PAGE, LOGREC_REDO_BITMAP_NEW_PAGE,
LOGREC_IMPORTED_TABLE, LOGREC_IMPORTED_TABLE,
LOGREC_DEBUG_INFO,
LOGREC_FIRST_FREE, LOGREC_FIRST_FREE,
LOGREC_RESERVED_FUTURE_EXTENSION= 63 LOGREC_RESERVED_FUTURE_EXTENSION= 63
}; };
...@@ -167,6 +168,12 @@ enum en_key_op ...@@ -167,6 +168,12 @@ enum en_key_op
KEY_OP_COMPACT_PAGE /* Compact key page */ KEY_OP_COMPACT_PAGE /* Compact key page */
}; };
enum translog_debug_info_type
{
LOGREC_DEBUG_INFO_QUERY
};
/* Size of log file; One log file is restricted to 4G */ /* Size of log file; One log file is restricted to 4G */
typedef uint32 translog_size_t; typedef uint32 translog_size_t;
...@@ -323,6 +330,9 @@ translog_assign_id_to_share_from_recovery(struct st_maria_share *share, ...@@ -323,6 +330,9 @@ translog_assign_id_to_share_from_recovery(struct st_maria_share *share,
extern my_bool translog_walk_filenames(const char *directory, extern my_bool translog_walk_filenames(const char *directory,
my_bool (*callback)(const char *, my_bool (*callback)(const char *,
const char *)); const char *));
extern my_bool translog_log_debug_info(TRN *trn,
enum translog_debug_info_type type,
uchar *info, size_t length);
enum enum_translog_status enum enum_translog_status
{ {
......
...@@ -98,6 +98,7 @@ prototype_redo_exec_hook(UNDO_KEY_DELETE); ...@@ -98,6 +98,7 @@ prototype_redo_exec_hook(UNDO_KEY_DELETE);
prototype_redo_exec_hook(UNDO_KEY_DELETE_WITH_ROOT); prototype_redo_exec_hook(UNDO_KEY_DELETE_WITH_ROOT);
prototype_redo_exec_hook(COMMIT); prototype_redo_exec_hook(COMMIT);
prototype_redo_exec_hook(CLR_END); prototype_redo_exec_hook(CLR_END);
prototype_redo_exec_hook(DEBUG_INFO);
prototype_undo_exec_hook(UNDO_ROW_INSERT); prototype_undo_exec_hook(UNDO_ROW_INSERT);
prototype_undo_exec_hook(UNDO_ROW_DELETE); prototype_undo_exec_hook(UNDO_ROW_DELETE);
prototype_undo_exec_hook(UNDO_ROW_UPDATE); prototype_undo_exec_hook(UNDO_ROW_UPDATE);
...@@ -488,6 +489,11 @@ static void display_record_position(const LOG_DESC *log_desc, ...@@ -488,6 +489,11 @@ static void display_record_position(const LOG_DESC *log_desc,
number ? "" : " ", number, LSN_IN_PARTS(rec->lsn), number ? "" : " ", number, LSN_IN_PARTS(rec->lsn),
rec->short_trid, log_desc->name, rec->type, rec->short_trid, log_desc->name, rec->type,
(ulong)rec->record_length); (ulong)rec->record_length);
if (rec->type == LOGREC_DEBUG_INFO)
{
/* Print some extra information */
(*log_desc->record_execute_in_redo_phase)(rec);
}
} }
...@@ -2003,6 +2009,37 @@ prototype_redo_exec_hook(CLR_END) ...@@ -2003,6 +2009,37 @@ prototype_redo_exec_hook(CLR_END)
} }
/**
Hock to print debug information (like MySQL query)
*/
prototype_redo_exec_hook(DEBUG_INFO)
{
uchar *data;
enum translog_debug_info_type debug_info;
enlarge_buffer(rec);
if (log_record_buffer.str == NULL ||
translog_read_record(rec->lsn, 0, rec->record_length,
log_record_buffer.str, NULL) !=
rec->record_length)
{
eprint(tracef, "Failed to read record debug record");
return 1;
}
debug_info= (enum translog_debug_info_type) log_record_buffer.str[0];
data= log_record_buffer.str + 1;
switch (debug_info) {
case LOGREC_DEBUG_INFO_QUERY:
tprint(tracef, "Query: %s\n", (char*) data);
break;
default:
DBUG_ASSERT(0);
}
return 0;
}
/** /**
In some cases we have to skip execution of an UNDO record during the UNDO In some cases we have to skip execution of an UNDO record during the UNDO
phase. phase.
...@@ -2361,6 +2398,7 @@ static int run_redo_phase(LSN lsn, enum maria_apply_log_way apply) ...@@ -2361,6 +2398,7 @@ static int run_redo_phase(LSN lsn, enum maria_apply_log_way apply)
install_redo_exec_hook(UNDO_BULK_INSERT); install_redo_exec_hook(UNDO_BULK_INSERT);
install_undo_exec_hook(UNDO_BULK_INSERT); install_undo_exec_hook(UNDO_BULK_INSERT);
install_redo_exec_hook(IMPORTED_TABLE); install_redo_exec_hook(IMPORTED_TABLE);
install_redo_exec_hook(DEBUG_INFO);
current_group_end_lsn= LSN_IMPOSSIBLE; current_group_end_lsn= LSN_IMPOSSIBLE;
#ifndef DBUG_OFF #ifndef DBUG_OFF
...@@ -3403,6 +3441,7 @@ static void print_redo_phase_progress(TRANSLOG_ADDRESS addr) ...@@ -3403,6 +3441,7 @@ static void print_redo_phase_progress(TRANSLOG_ADDRESS addr)
} }
} }
#ifdef MARIA_EXTERNAL_LOCKING #ifdef MARIA_EXTERNAL_LOCKING
#error Marias Checkpoint and Recovery are really not ready for it #error Marias Checkpoint and Recovery are really not ready for it
#endif #endif
......
...@@ -88,6 +88,19 @@ void trnman_reset_locked_tables(TRN *trn, uint locked_tables) ...@@ -88,6 +88,19 @@ void trnman_reset_locked_tables(TRN *trn, uint locked_tables)
trn->locked_tables= locked_tables; trn->locked_tables= locked_tables;
} }
#ifdef EXTRA_DEBUG
uint16 trnman_get_state(TRN *trn)
{
return trn->state;
}
void trnman_set_state(TRN *trn, uint16 state)
{
trn->state= state;
}
#endif
static void wt_thd_release_self(TRN *trn) static void wt_thd_release_self(TRN *trn)
{ {
if (trn->wt) if (trn->wt)
......
...@@ -53,6 +53,7 @@ struct st_ma_transaction ...@@ -53,6 +53,7 @@ struct st_ma_transaction
LSN_WITH_FLAGS first_undo_lsn; LSN_WITH_FLAGS first_undo_lsn;
uint locked_tables; uint locked_tables;
uint16 short_id; uint16 short_id;
uint16 state; /* Internal flags */
}; };
#define TRANSACTION_LOGGED_LONG_ID ULL(0x8000000000000000) #define TRANSACTION_LOGGED_LONG_ID ULL(0x8000000000000000)
......
...@@ -70,5 +70,17 @@ my_bool trnman_exists_active_transactions(TrID min_id, TrID max_id, ...@@ -70,5 +70,17 @@ my_bool trnman_exists_active_transactions(TrID min_id, TrID max_id,
void trnman_lock(); void trnman_lock();
void trnman_unlock(); void trnman_unlock();
my_bool trman_is_inited(); my_bool trman_is_inited();
#ifdef EXTRA_DEBUG
uint16 trnman_get_state(TRN *);
void trnman_set_state(TRN *, uint16 state_bit);
#else
#define trnman_get_state(A) 0
uint16 trnman_set_state(A, B) do { } while (0)
#endif
/* Bits for 'state' */
#define TRN_STATE_INFO_LOGGED 1 /* Query is logged */
#define TRN_STATE_TABLES_CAN_CHANGE 2 /* Things can change during trans. */
C_MODE_END C_MODE_END
#endif #endif
...@@ -496,7 +496,8 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, ...@@ -496,7 +496,8 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
/* There are only 16 bits for the total header length. */ /* There are only 16 bits for the total header length. */
if (info_length > 65535) if (info_length > 65535)
{ {
my_printf_error(0, "MyISAM table '%s' has too many columns and/or " my_printf_error(HA_WRONG_CREATE_OPTION,
"MyISAM table '%s' has too many columns and/or "
"indexes and/or unique constraints.", "indexes and/or unique constraints.",
MYF(0), name + dirname_length(name)); MYF(0), name + dirname_length(name));
my_errno= HA_WRONG_CREATE_OPTION; my_errno= HA_WRONG_CREATE_OPTION;
......
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