WL 2826: Error handling of ALTER TABLE for partitioning

Loads of review comments fixed
inactivate => deactivate
table log => ddl log
Commented on Error Inject Module added
Put various #defines into enums
Fixed abort_and_upgrade_lock, removed unnecessary parameter
Fixed mysqlish method intro's
Fixed warning statements
5.1.7 was released still with partition states in clear text

Fixed io_size bug
Fixed bug in open that TRUNCATED before reading :)
file_entry => file_entry_buf
Don't open DDL log until first write call to DDL log
handler_type => handler_name
no => num
parent ac10cffe
......@@ -701,7 +701,7 @@ int ha_partition::rename_partitions(const char *path)
DBUG_PRINT("info", ("Delete subpartition %s", norm_name_buff));
if ((ret_error= file->delete_table((const char *) norm_name_buff)))
error= ret_error;
else if (inactivate_table_log_entry(sub_elem->log_entry->entry_pos))
else if (deactivate_ddl_log_entry(sub_elem->log_entry->entry_pos))
error= 1;
else
sub_elem->log_entry= NULL; /* Indicate success */
......@@ -716,13 +716,13 @@ int ha_partition::rename_partitions(const char *path)
DBUG_PRINT("info", ("Delete partition %s", norm_name_buff));
if ((ret_error= file->delete_table((const char *) norm_name_buff)))
error= ret_error;
else if (inactivate_table_log_entry(part_elem->log_entry->entry_pos))
else if (deactivate_ddl_log_entry(part_elem->log_entry->entry_pos))
error= 1;
else
part_elem->log_entry= NULL; /* Indicate success */
}
} while (++i < temp_partitions);
VOID(sync_table_log());
VOID(sync_ddl_log());
}
i= 0;
do
......@@ -771,9 +771,9 @@ int ha_partition::rename_partitions(const char *path)
DBUG_PRINT("info", ("Delete subpartition %s", norm_name_buff));
if ((ret_error= file->delete_table((const char *) norm_name_buff)))
error= ret_error;
else if (inactivate_table_log_entry(sub_elem->log_entry->entry_pos))
else if (deactivate_ddl_log_entry(sub_elem->log_entry->entry_pos))
error= 1;
VOID(sync_table_log());
VOID(sync_ddl_log());
}
file= m_new_file[part];
create_subpartition_name(part_name_buff, path,
......@@ -785,7 +785,7 @@ int ha_partition::rename_partitions(const char *path)
if ((ret_error= file->rename_table((const char *) part_name_buff,
(const char *) norm_name_buff)))
error= ret_error;
else if (inactivate_table_log_entry(sub_elem->log_entry->entry_pos))
else if (deactivate_ddl_log_entry(sub_elem->log_entry->entry_pos))
error= 1;
else
sub_elem->log_entry= NULL;
......@@ -802,9 +802,9 @@ int ha_partition::rename_partitions(const char *path)
DBUG_PRINT("info", ("Delete partition %s", norm_name_buff));
if ((ret_error= file->delete_table((const char *) norm_name_buff)))
error= ret_error;
else if (inactivate_table_log_entry(part_elem->log_entry->entry_pos))
else if (deactivate_ddl_log_entry(part_elem->log_entry->entry_pos))
error= 1;
VOID(sync_table_log());
VOID(sync_ddl_log());
}
file= m_new_file[i];
create_partition_name(part_name_buff, path,
......@@ -815,14 +815,14 @@ int ha_partition::rename_partitions(const char *path)
if ((ret_error= file->rename_table((const char *) part_name_buff,
(const char *) norm_name_buff)))
error= ret_error;
else if (inactivate_table_log_entry(part_elem->log_entry->entry_pos))
else if (deactivate_ddl_log_entry(part_elem->log_entry->entry_pos))
error= 1;
else
part_elem->log_entry= NULL;
}
}
} while (++i < no_parts);
VOID(sync_table_log());
VOID(sync_ddl_log());
DBUG_RETURN(error);
}
......
......@@ -631,9 +631,6 @@ struct Query_cache_query_flags
#else
#define SET_ERROR_INJECT_VALUE(x) \
current_thd->error_inject_value= (x)
inline bool
my_error_inject_name(const char *dbug_str)
{
......@@ -661,6 +658,43 @@ my_error_inject(int value)
return 0;
}
/*
ERROR INJECT MODULE:
--------------------
These macros are used to insert macros from the application code.
The event that activates those error injections can be activated
from SQL by using:
SET SESSION dbug=+d,code;
After the error has been injected, the macros will automatically
remove the debug code, thus similar to using:
SET SESSION dbug=-d,code
from SQL.
ERROR_INJECT_CRASH will inject a crash of the MySQL Server if code
is set when macro is called. ERROR_INJECT_CRASH can be used in
if-statements, it will always return FALSE unless of course it
crashes in which case it doesn't return at all.
ERROR_INJECT_ACTION will inject the action specified in the action
parameter of the macro, before performing the action the code will
be removed such that no more events occur. ERROR_INJECT_ACTION
can also be used in if-statements and always returns FALSE.
ERROR_INJECT can be used in a normal if-statement, where the action
part is performed in the if-block. The macro returns TRUE if the
error was activated and otherwise returns FALSE. If activated the
code is removed.
Sometimes it is necessary to perform error inject actions as a serie
of events. In this case one can use one variable on the THD object.
Thus one sets this value by using e.g. SET_ERROR_INJECT_VALUE(100).
Then one can later test for it by using ERROR_INJECT_CRASH_VALUE,
ERROR_INJECT_ACTION_VALUE and ERROR_INJECT_VALUE. This have the same
behaviour as the above described macros except that they use the
error inject value instead of a code used by DBUG macros.
*/
#define SET_ERROR_INJECT_VALUE(x) \
current_thd->error_inject_value= (x)
#define ERROR_INJECT_CRASH(code) \
DBUG_EVALUATE_IF(code, (abort(), 0), 0)
#define ERROR_INJECT_ACTION(code, action) \
......@@ -1186,57 +1220,86 @@ typedef struct st_lock_param_type
void mem_alloc_error(size_t size);
typedef struct st_table_log_entry
enum ddl_log_entry_code
{
/*
DDL_LOG_EXECUTE_CODE:
This is a code that indicates that this is a log entry to
be executed, from this entry a linked list of log entries
can be found and executed.
DDL_LOG_ENTRY_CODE:
An entry to be executed in a linked list from an execute log
entry.
DDL_IGNORE_LOG_ENTRY_CODE:
An entry that is to be ignored
*/
DDL_LOG_EXECUTE_CODE = 'e',
DDL_LOG_ENTRY_CODE = 'l',
DDL_IGNORE_LOG_ENTRY_CODE = 'i'
};
enum ddl_log_action_code
{
/*
The type of action that a DDL_LOG_ENTRY_CODE entry is to
perform.
DDL_LOG_DELETE_ACTION:
Delete an entity
DDL_LOG_RENAME_ACTION:
Rename an entity
DDL_LOG_REPLACE_ACTION:
Rename an entity after removing the previous entry with the
new name, that is replace this entry.
*/
DDL_LOG_DELETE_ACTION = 'd',
DDL_LOG_RENAME_ACTION = 'r',
DDL_LOG_REPLACE_ACTION = 's'
};
typedef struct st_ddl_log_entry
{
const char *name;
const char *from_name;
const char *handler_type;
const char *handler_name;
uint next_entry;
uint entry_pos;
char action_type;
char entry_type;
enum ddl_log_entry_code entry_type;
enum ddl_log_action_code action_type;
char phase;
char not_used;
} TABLE_LOG_ENTRY;
} DDL_LOG_ENTRY;
typedef struct st_table_log_memory_entry
typedef struct st_ddl_log_memory_entry
{
uint entry_pos;
struct st_table_log_memory_entry *next_log_entry;
struct st_table_log_memory_entry *prev_log_entry;
struct st_table_log_memory_entry *next_active_log_entry;
} TABLE_LOG_MEMORY_ENTRY;
struct st_ddl_log_memory_entry *next_log_entry;
struct st_ddl_log_memory_entry *prev_log_entry;
struct st_ddl_log_memory_entry *next_active_log_entry;
} DDL_LOG_MEMORY_ENTRY;
#define TLOG_EXECUTE_CODE 'e'
#define TLOG_LOG_ENTRY_CODE 'l'
#define TLOG_IGNORE_LOG_ENTRY_CODE 'i'
#define TLOG_DELETE_ACTION_CODE 'd'
#define TLOG_RENAME_ACTION_CODE 'r'
#define TLOG_REPLACE_ACTION_CODE 's'
#define TLOG_HANDLER_TYPE_LEN 32
#define DDL_LOG_HANDLER_TYPE_LEN 32
bool write_table_log_entry(TABLE_LOG_ENTRY *table_log_entry,
TABLE_LOG_MEMORY_ENTRY **active_entry);
bool write_execute_table_log_entry(uint first_entry,
bool write_ddl_log_entry(DDL_LOG_ENTRY *ddl_log_entry,
DDL_LOG_MEMORY_ENTRY **active_entry);
bool write_execute_ddl_log_entry(uint first_entry,
bool complete,
TABLE_LOG_MEMORY_ENTRY **active_entry);
bool inactivate_table_log_entry(uint entry_no);
void release_table_log_memory_entry(TABLE_LOG_MEMORY_ENTRY *log_entry);
bool sync_table_log();
void release_table_log();
void execute_table_log_recovery();
bool execute_table_log_entry(uint first_entry);
void lock_global_table_log();
void unlock_global_table_log();
DDL_LOG_MEMORY_ENTRY **active_entry);
bool deactivate_ddl_log_entry(uint entry_no);
void release_ddl_log_memory_entry(DDL_LOG_MEMORY_ENTRY *log_entry);
bool sync_ddl_log();
void release_ddl_log();
void execute_ddl_log_recovery();
bool execute_ddl_log_entry(uint first_entry);
void lock_global_ddl_log();
void unlock_global_ddl_log();
#define WFRM_WRITE_SHADOW 1
#define WFRM_INSTALL_SHADOW 2
#define WFRM_PACK_FRM 4
bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags);
bool abort_and_upgrade_lock(ALTER_PARTITION_PARAM_TYPE *lpt,
bool can_be_killed);
void abort_and_upgrade_lock(ALTER_PARTITION_PARAM_TYPE *lpt);
void close_open_tables_and_downgrade(ALTER_PARTITION_PARAM_TYPE *lpt);
void mysql_wait_completed_table(ALTER_PARTITION_PARAM_TYPE *lpt, TABLE *my_table);
......
......@@ -3665,7 +3665,7 @@ we force server id to 2, but this MySQL server will not act as a slave.");
unireg_abort(1);
}
}
execute_table_log_recovery();
execute_ddl_log_recovery();
create_shutdown_thread();
create_maintenance_thread();
......@@ -3696,7 +3696,7 @@ we force server id to 2, but this MySQL server will not act as a slave.");
/* (void) pthread_attr_destroy(&connection_attrib); */
DBUG_PRINT("quit",("Exiting main thread"));
release_table_log();
release_ddl_log();
#ifndef __WIN__
#ifdef EXTRA_DEBUG2
......
......@@ -36,7 +36,7 @@ enum partition_state {
PART_IS_ADDED= 8
};
struct st_table_log_memory_entry;
struct st_ddl_log_memory_entry;
class partition_element :public Sql_alloc {
public:
......@@ -46,7 +46,7 @@ public:
ulonglong part_min_rows;
char *partition_name;
char *tablespace_name;
struct st_table_log_memory_entry *log_entry;
struct st_ddl_log_memory_entry *log_entry;
longlong range_value;
char* part_comment;
char* data_file_name;
......
......@@ -28,7 +28,7 @@ typedef int (*get_part_id_func)(partition_info *part_info,
longlong *func_value);
typedef uint32 (*get_subpart_id_func)(partition_info *part_info);
struct st_table_log_memory_entry;
struct st_ddl_log_memory_entry;
class partition_info : public Sql_alloc
{
......@@ -77,9 +77,9 @@ public:
Item *item_free_list;
struct st_table_log_memory_entry *first_log_entry;
struct st_table_log_memory_entry *exec_log_entry;
struct st_table_log_memory_entry *frm_log_entry;
struct st_ddl_log_memory_entry *first_log_entry;
struct st_ddl_log_memory_entry *exec_log_entry;
struct st_ddl_log_memory_entry *frm_log_entry;
/*
A bitmap of partitions used by the current query.
......
......@@ -5826,5 +5826,5 @@ ER_NDB_CANT_SWITCH_BINLOG_FORMAT
eng "The NDB cluster engine does not support changing the binlog format on the fly yet"
ER_PARTITION_NO_TEMPORARY
eng "Cannot create temporary table with partitions"
ER_TABLE_LOG_ERROR
eng "Error in table log"
ER_DDL_LOG_ERROR
eng "Error in DDL log"
......@@ -6124,24 +6124,17 @@ bool is_equal(const LEX_STRING *a, const LEX_STRING *b)
old_lock_level Old lock level
*/
bool abort_and_upgrade_lock(ALTER_PARTITION_PARAM_TYPE *lpt,
bool can_be_killed)
void abort_and_upgrade_lock(ALTER_PARTITION_PARAM_TYPE *lpt)
{
uint flags= RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG;
int error= FALSE;
DBUG_ENTER("abort_and_upgrade_locks");
lpt->old_lock_type= lpt->table->reginfo.lock_type;
VOID(pthread_mutex_lock(&LOCK_open));
mysql_lock_abort(lpt->thd, lpt->table, TRUE);
VOID(remove_table_from_cache(lpt->thd, lpt->db, lpt->table_name, flags));
if (can_be_killed && lpt->thd->killed)
{
lpt->thd->no_warnings_for_error= 0;
error= TRUE;
}
VOID(pthread_mutex_unlock(&LOCK_open));
DBUG_RETURN(error);
DBUG_VOID_RETURN;
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -667,8 +667,9 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
#endif
next_chunk+= 5 + partition_info_len;
}
#if 0
if (share->mysql_version == 50106)
#if 1
if (share->mysql_version == 50106 ||
share->mysql_version == 50107)
{
/*
Partition state array was here in version 5.1.6, this code makes
......
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