diff options
Diffstat (limited to 'sql/ddl_log.cc')
-rw-r--r-- | sql/ddl_log.cc | 83 |
1 files changed, 67 insertions, 16 deletions
diff --git a/sql/ddl_log.cc b/sql/ddl_log.cc index 951a7abd95f..418b5f3b5b0 100644 --- a/sql/ddl_log.cc +++ b/sql/ddl_log.cc @@ -77,6 +77,8 @@ #define DDL_LOG_MAGIC_LENGTH 4 /* How many times to try to execute a ddl log entry that causes crashes */ #define DDL_LOG_MAX_RETRY 3 +#define DDL_LOG_RETRY_MASK 0xFF +#define DDL_LOG_RETRY_BITS 8 uchar ddl_log_file_magic[]= { (uchar) 254, (uchar) 254, (uchar) 11, (uchar) 2 }; @@ -155,7 +157,7 @@ mysql_mutex_t LOCK_gdl; #define DDL_LOG_XID_POS 10 /* Used to store unique uuid from the .frm file */ #define DDL_LOG_UUID_POS 18 -/* ID_POS can be used to store something unique, like file size (4 bytes) */ +/* ID_POS can be used to store something unique, like file size (8 bytes) */ #define DDL_LOG_ID_POS DDL_LOG_UUID_POS + MY_UUID_SIZE #define DDL_LOG_END_POS DDL_LOG_ID_POS + 8 @@ -335,7 +337,7 @@ static bool write_ddl_log_file_entry(uint entry_pos) static bool update_phase(uint entry_pos, uchar phase) { DBUG_ENTER("update_phase"); - DBUG_PRINT("enter", ("phase: %d", (int) phase)); + DBUG_PRINT("ddl_log", ("pos: %u phase: %u", entry_pos, (uint) phase)); DBUG_RETURN(mysql_file_pwrite(global_ddl_log.file_id, &phase, 1, global_ddl_log.io_size * entry_pos + @@ -369,6 +371,8 @@ static bool update_next_entry_pos(uint entry_pos, uint next_entry) uchar buff[4]; DBUG_ENTER("update_next_entry_pos"); + DBUG_PRINT("ddl_log", ("pos: %u->%u", entry_pos, next_entry)); + int4store(buff, next_entry); DBUG_RETURN(mysql_file_pwrite(global_ddl_log.file_id, buff, sizeof(buff), global_ddl_log.io_size * entry_pos + @@ -420,6 +424,7 @@ static bool disable_execute_entry(uint entry_pos) { uchar buff[1]; DBUG_ENTER("disable_execute_entry"); + DBUG_PRINT("ddl_log", ("pos: {%u}", entry_pos)); buff[0]= DDL_LOG_IGNORE_ENTRY_CODE; DBUG_RETURN(mysql_file_pwrite(global_ddl_log.file_id, buff, sizeof(buff), @@ -1296,13 +1301,15 @@ static int ddl_log_execute_action(THD *thd, MEM_ROOT *mem_root, mysql_mutex_assert_owner(&LOCK_gdl); DBUG_PRINT("ddl_log", - ("entry type: %u action type: %u (%s) phase: %u next: %u " + ("pos: %u=>%u->%u type: %u action: %u (%s) phase: %u " "handler: '%s' name: '%s' from_name: '%s' tmp_name: '%s'", + recovery_state.execute_entry_pos, + ddl_log_entry->entry_pos, + ddl_log_entry->next_entry, (uint) ddl_log_entry->entry_type, (uint) ddl_log_entry->action_type, ddl_log_action_name[ddl_log_entry->action_type], (uint) ddl_log_entry->phase, - ddl_log_entry->next_entry, ddl_log_entry->handler_name.str, ddl_log_entry->name.str, ddl_log_entry->from_name.str, @@ -2470,13 +2477,13 @@ bool ddl_log_write_entry(DDL_LOG_ENTRY *ddl_log_entry, error= FALSE; DBUG_PRINT("ddl_log", - ("entry type: %u action type: %u (%s) phase: %u next: %u " + ("pos: %u->%u action: %u (%s) phase: %u " "handler: '%s' name: '%s' from_name: '%s' tmp_name: '%s'", - (uint) ddl_log_entry->entry_type, + (*active_entry)->entry_pos, + (uint) ddl_log_entry->next_entry, (uint) ddl_log_entry->action_type, ddl_log_action_name[ddl_log_entry->action_type], (uint) ddl_log_entry->phase, - ddl_log_entry->next_entry, ddl_log_entry->handler_name.str, ddl_log_entry->name.str, ddl_log_entry->from_name.str, @@ -2510,6 +2517,7 @@ bool ddl_log_write_entry(DDL_LOG_ENTRY *ddl_log_entry, @param first_entry First entry in linked list of entries to execute. + @param cond_entry Check and don't execute if cond_entry is active @param[in,out] active_entry Entry to execute, 0 = NULL if the entry is written first time and needs to be returned. In this case the entry written @@ -2520,6 +2528,7 @@ bool ddl_log_write_entry(DDL_LOG_ENTRY *ddl_log_entry, */ bool ddl_log_write_execute_entry(uint first_entry, + uint cond_entry, DDL_LOG_MEMORY_ENTRY **active_entry) { uchar *file_entry_buf= global_ddl_log.file_entry_buf; @@ -2536,13 +2545,17 @@ bool ddl_log_write_execute_entry(uint first_entry, file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= (uchar)DDL_LOG_EXECUTE_CODE; int4store(file_entry_buf + DDL_LOG_NEXT_ENTRY_POS, first_entry); + int8store(file_entry_buf + DDL_LOG_ID_POS, ((ulonglong)cond_entry << DDL_LOG_RETRY_BITS)); if (!(*active_entry)) { if (ddl_log_get_free_entry(active_entry)) DBUG_RETURN(TRUE); got_free_entry= TRUE; - } + } + DBUG_PRINT("ddl_log", + ("pos: %u=>%u", + (*active_entry)->entry_pos, first_entry)); if (write_ddl_log_file_entry((*active_entry)->entry_pos)) { if (got_free_entry) @@ -2575,6 +2588,7 @@ bool ddl_log_increment_phase(uint entry_pos) { bool error; DBUG_ENTER("ddl_log_increment_phase"); + DBUG_PRINT("ddl_log", ("pos: %u", entry_pos)); mysql_mutex_lock(&LOCK_gdl); error= ddl_log_increment_phase_no_lock(entry_pos); @@ -2754,13 +2768,13 @@ int ddl_log_execute_recovery() recovery_state.xid= ddl_log_entry.xid; /* purecov: begin tested */ - if (ddl_log_entry.unique_id > DDL_LOG_MAX_RETRY) + if ((ddl_log_entry.unique_id & DDL_LOG_RETRY_MASK) > DDL_LOG_MAX_RETRY) { error= -1; continue; } update_unique_id(i, ++ddl_log_entry.unique_id); - if (ddl_log_entry.unique_id > DDL_LOG_MAX_RETRY) + if ((ddl_log_entry.unique_id & DDL_LOG_RETRY_MASK) > DDL_LOG_MAX_RETRY) { sql_print_error("DDL_LOG: Aborting executing entry %u after %llu " "retries", i, ddl_log_entry.unique_id); @@ -2769,6 +2783,15 @@ int ddl_log_execute_recovery() } /* purecov: end tested */ + uint cond_entry= (uint)(ddl_log_entry.unique_id >> DDL_LOG_RETRY_BITS); + + if (cond_entry && is_execute_entry_active(cond_entry)) + { + if (disable_execute_entry(i)) + error= -1; + continue; + } + if (ddl_log_execute_entry_no_lock(thd, ddl_log_entry.next_entry)) { /* Real unpleasant scenario but we have to continue anyway */ @@ -2848,8 +2871,7 @@ void ddl_log_release() Methods for DDL_LOG_STATE */ -static void add_log_entry(DDL_LOG_STATE *state, - DDL_LOG_MEMORY_ENTRY *log_entry) +void ddl_log_add_entry(DDL_LOG_STATE *state, DDL_LOG_MEMORY_ENTRY *log_entry) { log_entry->next_active_log_entry= state->list; state->main_entry= state->list= log_entry; @@ -3028,7 +3050,7 @@ static bool ddl_log_write(DDL_LOG_STATE *ddl_state, ddl_log_release_memory_entry(log_entry); DBUG_RETURN(1); } - add_log_entry(ddl_state, log_entry); + ddl_log_add_entry(ddl_state, log_entry); ddl_state->flags|= ddl_log_entry->flags; // Update cache DBUG_RETURN(0); } @@ -3178,7 +3200,7 @@ static bool ddl_log_drop(THD *thd, DDL_LOG_STATE *ddl_state, } mysql_mutex_unlock(&LOCK_gdl); - add_log_entry(ddl_state, log_entry); + ddl_log_add_entry(ddl_state, log_entry); DBUG_RETURN(0); error: @@ -3478,7 +3500,7 @@ bool ddl_log_store_query(THD *thd, DDL_LOG_STATE *ddl_state, goto err; parent_entry_pos= ddl_state->list->entry_pos; entry_pos= first_entry->entry_pos; - add_log_entry(ddl_state, first_entry); + ddl_log_add_entry(ddl_state, first_entry); while (length) { @@ -3494,7 +3516,7 @@ bool ddl_log_store_query(THD *thd, DDL_LOG_STATE *ddl_state, if (ddl_log_get_free_entry(&next_entry)) goto err; ddl_log_entry.next_entry= next_entry_pos= next_entry->entry_pos; - add_log_entry(ddl_state, next_entry); + ddl_log_add_entry(ddl_state, next_entry); } else { @@ -3526,3 +3548,32 @@ err: mysql_mutex_unlock(&LOCK_gdl); DBUG_RETURN(1); } + + +/* + Log an delete frm file +*/ + +/* + TODO: Partitioning atomic DDL refactoring: this should be replaced with + ddl_log_create_table(). +*/ +bool ddl_log_delete_frm(DDL_LOG_STATE *ddl_state, const char *to_path) +{ + DDL_LOG_ENTRY ddl_log_entry; + DDL_LOG_MEMORY_ENTRY *log_entry; + DBUG_ENTER("ddl_log_delete_frm"); + bzero(&ddl_log_entry, sizeof(ddl_log_entry)); + ddl_log_entry.action_type= DDL_LOG_DELETE_ACTION; + ddl_log_entry.next_entry= ddl_state->list ? ddl_state->list->entry_pos : 0; + + lex_string_set(&ddl_log_entry.handler_name, reg_ext); + lex_string_set(&ddl_log_entry.name, to_path); + + mysql_mutex_assert_owner(&LOCK_gdl); + if (ddl_log_write_entry(&ddl_log_entry, &log_entry)) + DBUG_RETURN(1); + + ddl_log_add_entry(ddl_state, log_entry); + DBUG_RETURN(0); +} |